Add support for 'C'-compressed ISA extension to DTrace FBT provider.

Approved by:	re (kib)
Sponsored by:	DARPA, AFRL
This commit is contained in:
br 2018-09-03 14:34:09 +00:00
parent 545428e18d
commit 639c5f49ef
6 changed files with 171 additions and 148 deletions

View File

@ -2496,12 +2496,11 @@ extern void dtrace_helpers_destroy(proc_t *);
#elif defined(__riscv)
#define SD_RA_SP_MASK 0x01fff07f
#define SD_RA_SP 0x00113023
#define DTRACE_INVOP_SD 1
#define DTRACE_INVOP_RET 2
#define DTRACE_INVOP_NOP 3
#define DTRACE_INVOP_C_SDSP 2
#define DTRACE_INVOP_RET 3
#define DTRACE_INVOP_C_RET 4
#define DTRACE_INVOP_NOP 5
#endif

View File

@ -19,7 +19,7 @@
*
* CDDL HEADER END
*
* Portions Copyright 2016 Ruslan Bukin <br@bsdpad.com>
* Portions Copyright 2016-2018 Ruslan Bukin <br@bsdpad.com>
*
* $FreeBSD$
*
@ -42,8 +42,8 @@ __FBSDID("$FreeBSD$");
#include <sys/dtrace_impl.h>
#include <sys/dtrace_bsd.h>
#include <machine/vmparam.h>
#include <machine/encoding.h>
#include <machine/riscvreg.h>
#include <machine/riscv_opcode.h>
#include <machine/clock.h>
#include <machine/frame.h>
#include <machine/trap.h>
@ -77,7 +77,6 @@ dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax)
return (0);
}
void
dtrace_invop_add(int (*func)(uintptr_t, struct trapframe *, uintptr_t))
{
@ -237,30 +236,59 @@ dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which,
(uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs);
}
static int
match_opcode(uint32_t insn, int match, int mask)
{
if (((insn ^ match) & mask) == 0)
return (1);
return (0);
}
static int
dtrace_invop_start(struct trapframe *frame)
{
int data, invop, reg, update_sp;
register_t arg1, arg2;
register_t *sp;
uint32_t uimm;
uint32_t imm;
InstFmt i;
int offs;
int tmp;
int invop;
invop = dtrace_invop(frame->tf_sepc, frame, frame->tf_sepc);
if (invop == RISCV_INSN_RET) {
if (match_opcode(invop, (MATCH_SD | RS2_RA | RS1_SP),
(MASK_SD | RS2_MASK | RS1_MASK))) {
/* Non-compressed store of ra to sp */
imm = (invop >> 7) & 0x1f;
imm |= ((invop >> 25) & 0x7f) << 5;
sp = (register_t *)((uint8_t *)frame->tf_sp + imm);
*sp = frame->tf_ra;
frame->tf_sepc += INSN_SIZE;
return (0);
}
if (match_opcode(invop, (MATCH_JALR | (X_RA << RS1_SHIFT)),
(MASK_JALR | RD_MASK | RS1_MASK | IMM_MASK))) {
/* Non-compressed ret */
frame->tf_sepc = frame->tf_ra;
return (0);
}
if ((invop & SD_RA_SP_MASK) == SD_RA_SP) {
i.word = invop;
imm = i.SType.imm0_4 | (i.SType.imm5_11 << 5);
sp = (register_t *)((uint8_t *)frame->tf_sp + imm);
if (match_opcode(invop, (MATCH_C_SDSP | RS2_C_RA),
(MASK_C_SDSP | RS2_C_MASK))) {
/* 'C'-compressed store of ra to sp */
uimm = ((invop >> 10) & 0x7) << 3;
uimm |= ((invop >> 7) & 0x7) << 6;
sp = (register_t *)((uint8_t *)frame->tf_sp + uimm);
*sp = frame->tf_ra;
frame->tf_sepc += INSN_SIZE;
frame->tf_sepc += INSN_C_SIZE;
return (0);
}
if (match_opcode(invop, (MATCH_C_JR | (X_RA << RD_SHIFT)),
(MASK_C_JR | RD_MASK))) {
/* 'C'-compressed ret */
frame->tf_sepc = frame->tf_ra;
return (0);
}

View File

@ -21,7 +21,7 @@
* Portions Copyright 2006-2008 John Birrell jb@freebsd.org
* Portions Copyright 2013 Justin Hibbits jhibbits@freebsd.org
* Portions Copyright 2013 Howard Su howardsu@freebsd.org
* Portions Copyright 2016 Ruslan Bukin <br@bsdpad.com>
* Portions Copyright 2016-2018 Ruslan Bukin <br@bsdpad.com>
*
* $FreeBSD$
*/
@ -37,10 +37,12 @@
#include <sys/dtrace.h>
#include <machine/riscvreg.h>
#include <machine/encoding.h>
#include "fbt.h"
#define FBT_PATCHVAL (RISCV_INSN_BREAK)
#define FBT_C_PATCHVAL MATCH_C_EBREAK
#define FBT_PATCHVAL MATCH_EBREAK
#define FBT_ENTRY "entry"
#define FBT_RETURN "return"
@ -73,8 +75,62 @@ void
fbt_patch_tracepoint(fbt_probe_t *fbt, fbt_patchval_t val)
{
*fbt->fbtp_patchpoint = val;
cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
switch(fbt->fbtp_patchval) {
case FBT_C_PATCHVAL:
*(uint16_t *)fbt->fbtp_patchpoint = (uint16_t)val;
cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 2);
break;
case FBT_PATCHVAL:
*fbt->fbtp_patchpoint = val;
cpu_icache_sync_range((vm_offset_t)fbt->fbtp_patchpoint, 4);
break;
};
}
static int
match_opcode(uint32_t insn, int match, int mask)
{
if (((insn ^ match) & mask) == 0)
return (1);
return (0);
}
static int
check_c_ret(uint32_t **instr)
{
uint16_t *instr1;
int i;
for (i = 0; i < 2; i++) {
instr1 = (uint16_t *)(*instr) + i;
if (match_opcode(*instr1, (MATCH_C_JR | (X_RA << RD_SHIFT)),
(MASK_C_JR | RD_MASK))) {
*instr = (uint32_t *)instr1;
return (1);
}
}
return (0);
}
static int
check_c_sdsp(uint32_t **instr)
{
uint16_t *instr1;
int i;
for (i = 0; i < 2; i++) {
instr1 = (uint16_t *)(*instr) + i;
if (match_opcode(*instr1, (MATCH_C_SDSP | RS2_C_RA),
(MASK_C_SDSP | RS2_C_MASK))) {
*instr = (uint32_t *)instr1;
return (1);
}
}
return (0);
}
int
@ -85,6 +141,8 @@ fbt_provide_module_function(linker_file_t lf, int symindx,
uint32_t *instr, *limit;
const char *name;
char *modname;
int patchval;
int rval;
modname = opaque;
name = symval->name;
@ -98,8 +156,20 @@ fbt_provide_module_function(linker_file_t lf, int symindx,
/* Look for sd operation */
for (; instr < limit; instr++) {
if ((*instr & SD_RA_SP_MASK) == SD_RA_SP)
/* Look for a non-compressed store of ra to sp */
if (match_opcode(*instr, (MATCH_SD | RS2_RA | RS1_SP),
(MASK_SD | RS2_MASK | RS1_MASK))) {
rval = DTRACE_INVOP_SD;
patchval = FBT_PATCHVAL;
break;
}
/* Look for a 'C'-compressed store of ra to sp. */
if (check_c_sdsp(&instr)) {
rval = DTRACE_INVOP_C_SDSP;
patchval = FBT_C_PATCHVAL;
break;
}
}
if (instr >= limit)
@ -113,8 +183,8 @@ fbt_provide_module_function(linker_file_t lf, int symindx,
fbt->fbtp_ctl = lf;
fbt->fbtp_loadcnt = lf->loadcnt;
fbt->fbtp_savedval = *instr;
fbt->fbtp_patchval = FBT_PATCHVAL;
fbt->fbtp_rval = DTRACE_INVOP_SD;
fbt->fbtp_patchval = patchval;
fbt->fbtp_rval = rval;
fbt->fbtp_symindx = symindx;
fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
@ -125,8 +195,20 @@ fbt_provide_module_function(linker_file_t lf, int symindx,
retfbt = NULL;
again:
for (; instr < limit; instr++) {
if (*instr == RISCV_INSN_RET)
/* Look for non-compressed return */
if (match_opcode(*instr, (MATCH_JALR | (X_RA << RS1_SHIFT)),
(MASK_JALR | RD_MASK | RS1_MASK | IMM_MASK))) {
rval = DTRACE_INVOP_RET;
patchval = FBT_PATCHVAL;
break;
}
/* Look for 'C'-compressed return */
if (check_c_ret(&instr)) {
rval = DTRACE_INVOP_C_RET;
patchval = FBT_C_PATCHVAL;
break;
}
}
if (instr >= limit)
@ -150,9 +232,9 @@ again:
fbt->fbtp_ctl = lf;
fbt->fbtp_loadcnt = lf->loadcnt;
fbt->fbtp_symindx = symindx;
fbt->fbtp_rval = DTRACE_INVOP_RET;
fbt->fbtp_rval = rval;
fbt->fbtp_savedval = *instr;
fbt->fbtp_patchval = FBT_PATCHVAL;
fbt->fbtp_patchval = patchval;
fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;

View File

@ -88,6 +88,15 @@ device vtnet # VirtIO Ethernet device
device virtio_blk # VirtIO Block device
device virtio_mmio # VirtIO MMIO bus
# DTrace support
# device dtrace
# device dtrace_profile
# device dtrace_sdt
# device dtrace_fbt
# device dtrace_systrace
# device dtrace_prototype
# device dtraceall
# Serial (COM) ports
device uart # Generic UART driver
device uart_ns8250 # ns8250-type UART driver

View File

@ -1,116 +0,0 @@
/*-
* Copyright (c) 2016 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* Portions of this software were developed by SRI International and the
* University of Cambridge Computer Laboratory under DARPA/AFRL contract
* FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by the University of Cambridge
* Computer Laboratory as part of the CTSRD Project, with support from the
* UK Higher Education Innovation Fund (HEIF).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MACHINE_RISCV_OPCODE_H_
#define _MACHINE_RISCV_OPCODE_H_
/*
* Define the instruction formats and opcode values for the
* RISC-V instruction set.
*/
#include <machine/endian.h>
/*
* Define the instruction formats.
*/
typedef union {
unsigned word;
struct {
unsigned opcode: 7;
unsigned rd: 5;
unsigned funct3: 3;
unsigned rs1: 5;
unsigned rs2: 5;
unsigned funct7: 7;
} RType;
struct {
unsigned opcode: 7;
unsigned rd: 5;
unsigned funct3: 3;
unsigned rs1: 5;
unsigned rs2: 6;
unsigned funct7: 6;
} R2Type;
struct {
unsigned opcode: 7;
unsigned rd: 5;
unsigned funct3: 3;
unsigned rs1: 5;
unsigned imm: 12;
} IType;
struct {
unsigned opcode: 7;
unsigned imm0_4: 5;
unsigned funct3: 3;
unsigned rs1: 5;
unsigned rs2: 5;
unsigned imm5_11: 7;
} SType;
struct {
unsigned opcode: 7;
unsigned imm11: 1;
unsigned imm1_4: 4;
unsigned funct3: 3;
unsigned rs1: 5;
unsigned rs2: 5;
unsigned imm5_10: 6;
unsigned imm12: 1;
} SBType;
struct {
unsigned opcode: 7;
unsigned rd: 5;
unsigned imm12_31: 20;
} UType;
struct {
unsigned opcode: 7;
unsigned rd: 5;
unsigned imm12_19: 8;
unsigned imm11: 1;
unsigned imm1_10: 10;
unsigned imm20: 1;
} UJType;
} InstFmt;
#define RISCV_OPCODE(r) (r & 0x7f)
#endif /* !_MACHINE_RISCV_OPCODE_H_ */

View File

@ -157,10 +157,31 @@
#define XLEN 8
#define INSN_SIZE 4
#define INSN_C_SIZE 2
#define RISCV_INSN_NOP 0x00000013
#define RISCV_INSN_BREAK 0x00100073
#define RISCV_INSN_RET 0x00008067
#define X_RA 1
#define X_SP 2
#define X_GP 3
#define X_TP 4
#define X_T0 5
#define X_T1 6
#define X_T2 7
#define X_T3 28
#define RD_SHIFT 7
#define RD_MASK (0x1f << RD_SHIFT)
#define RS1_SHIFT 15
#define RS1_MASK (0x1f << RS1_SHIFT)
#define RS1_SP (X_SP << RS1_SHIFT)
#define RS2_SHIFT 20
#define RS2_MASK (0x1f << RS2_SHIFT)
#define RS2_RA (X_RA << RS2_SHIFT)
#define IMM_SHIFT 20
#define IMM_MASK (0xfff << IMM_SHIFT)
#define RS2_C_SHIFT 2
#define RS2_C_MASK (0x1f << RS2_C_SHIFT)
#define RS2_C_RA (X_RA << RS2_C_SHIFT)
#define CSR_ZIMM(val) \
(__builtin_constant_p(val) && ((u_long)(val) < 32))