From 501a9d9525962ad8c39b12d142394c7aa1df0f76 Mon Sep 17 00:00:00 2001 From: br Date: Tue, 24 May 2016 16:41:37 +0000 Subject: [PATCH] Add initial DTrace support for RISC-V. Sponsored by: DARPA, AFRL Sponsored by: HEIF5 --- .../lib/libdtrace/common/dt_link.c | 15 +- .../lib/libdtrace/common/dt_printf.c | 3 +- .../lib/libdtrace/riscv/dt_isadep.c | 139 ++++++ cddl/lib/Makefile | 2 +- cddl/lib/libdtrace/Makefile | 4 + cddl/usr.sbin/Makefile | 3 +- .../opensolaris/uts/common/dtrace/dtrace.c | 2 +- .../opensolaris/uts/common/sys/dtrace.h | 10 + .../uts/riscv/dtrace/fasttrap_isa.c | 29 ++ .../opensolaris/uts/riscv/sys/fasttrap_isa.h | 46 ++ sys/cddl/dev/dtrace/riscv/dtrace_asm.S | 176 ++++++++ sys/cddl/dev/dtrace/riscv/dtrace_isa.c | 394 ++++++++++++++++++ sys/cddl/dev/dtrace/riscv/dtrace_subr.c | 282 +++++++++++++ sys/cddl/dev/dtrace/riscv/regset.h | 51 +++ sys/cddl/dev/fbt/riscv/fbt_isa.c | 165 ++++++++ sys/cddl/dev/fbt/riscv/fbt_isa.h | 30 ++ sys/cddl/dev/profile/profile.c | 5 + sys/conf/files.riscv | 4 + sys/riscv/include/frame.h | 5 + sys/riscv/include/riscvreg.h | 5 + sys/riscv/riscv/trap.c | 19 +- 21 files changed, 1383 insertions(+), 6 deletions(-) create mode 100644 cddl/contrib/opensolaris/lib/libdtrace/riscv/dt_isadep.c create mode 100644 sys/cddl/contrib/opensolaris/uts/riscv/dtrace/fasttrap_isa.c create mode 100644 sys/cddl/contrib/opensolaris/uts/riscv/sys/fasttrap_isa.h create mode 100644 sys/cddl/dev/dtrace/riscv/dtrace_asm.S create mode 100644 sys/cddl/dev/dtrace/riscv/dtrace_isa.c create mode 100644 sys/cddl/dev/dtrace/riscv/dtrace_subr.c create mode 100644 sys/cddl/dev/dtrace/riscv/regset.h create mode 100644 sys/cddl/dev/fbt/riscv/fbt_isa.c create mode 100644 sys/cddl/dev/fbt/riscv/fbt_isa.h diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c index f574cf763804..ba5919d9d6b7 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c @@ -250,6 +250,9 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__); dofr[j].dofr_offset + 4; rel->r_info = ELF32_R_INFO(count + dep->de_global, R_PPC_REL32); +#elif defined(__riscv__) +/* XXX */ +printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__); #elif defined(__sparc) /* * Add 4 bytes to hit the low half of this 64-bit @@ -440,6 +443,8 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, dof_elf64_t *dep) dofr[j].dofr_offset; rel->r_info = ELF64_R_INFO(count + dep->de_global, R_PPC64_REL64); +#elif defined(__riscv__) +/* XXX */ #elif defined(__i386) || defined(__amd64) rel->r_offset = s->dofs_offset + dofr[j].dofr_offset; @@ -935,7 +940,15 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, return (0); } - +#elif defined(__riscv__) +/* XXX */ +static int +dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela, + uint32_t *off) +{ +printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__); + return (0); +} #elif defined(__sparc) #define DT_OP_RET 0x81c7e008 diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c index d408aed45199..01659b517a91 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c @@ -310,7 +310,8 @@ pfprint_fp(dtrace_hdl_t *dtp, FILE *fp, const char *format, case sizeof (double): return (dt_printf(dtp, fp, format, *((double *)addr) / n)); -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__mips__) +#if !defined(__arm__) && !defined(__powerpc__) && \ + !defined(__mips__) && !defined(__riscv__) case sizeof (long double): return (dt_printf(dtp, fp, format, *((long double *)addr) / ldn)); diff --git a/cddl/contrib/opensolaris/lib/libdtrace/riscv/dt_isadep.c b/cddl/contrib/opensolaris/lib/libdtrace/riscv/dt_isadep.c new file mode 100644 index 000000000000..9f5af8570490 --- /dev/null +++ b/cddl/contrib/opensolaris/lib/libdtrace/riscv/dt_isadep.c @@ -0,0 +1,139 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * Copyright 2014 Howard Su + * Copyright 2015 George V. Neville-Neil + * Copyright 2015 Ruslan Bukin + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include +#include +#include +#include +#include + +#include +#include + +#if !defined(sun) +#include +#endif + +/*ARGSUSED*/ +int +dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp, + fasttrap_probe_spec_t *ftp, const GElf_Sym *symp) +{ + + ftp->ftps_type = DTFTP_ENTRY; + ftp->ftps_pc = (uintptr_t)symp->st_value; + ftp->ftps_size = (size_t)symp->st_size; + ftp->ftps_noffs = 1; + ftp->ftps_offs[0] = 0; + + if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { + dt_dprintf("fasttrap probe creation ioctl failed: %s\n", + strerror(errno)); + return (dt_set_errno(dtp, errno)); + } + + return (1); +} + +int +dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp, + fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret) +{ + + dt_dprintf("%s: unimplemented\n", __func__); + + return (DT_PROC_ERR); +} + +/*ARGSUSED*/ +int +dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp, + fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off) +{ + + if (!ALIGNED_POINTER(off, 4)) + return (DT_PROC_ALIGN); + + ftp->ftps_type = DTFTP_OFFSETS; + ftp->ftps_pc = (uintptr_t)symp->st_value; + ftp->ftps_size = (size_t)symp->st_size; + ftp->ftps_noffs = 1; + ftp->ftps_offs[0] = off; + + if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { + dt_dprintf("fasttrap probe creation ioctl failed: %s\n", + strerror(errno)); + return (dt_set_errno(dtp, errno)); + } + + return (1); +} + +/*ARGSUSED*/ +int +dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp, + fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern) +{ + ulong_t i; + + ftp->ftps_type = DTFTP_OFFSETS; + ftp->ftps_pc = (uintptr_t)symp->st_value; + ftp->ftps_size = (size_t)symp->st_size; + ftp->ftps_noffs = 0; + + /* + * If we're matching against everything, just iterate through each + * instruction in the function, otherwise look for matching offset + * names by constructing the string and comparing it against the + * pattern. + */ + if (strcmp("*", pattern) == 0) { + for (i = 0; i < symp->st_size; i += 4) { + ftp->ftps_offs[ftp->ftps_noffs++] = i; + } + } else { + char name[sizeof (i) * 2 + 1]; + + for (i = 0; i < symp->st_size; i += 4) { + (void) sprintf(name, "%lx", i); + if (gmatch(name, pattern)) + ftp->ftps_offs[ftp->ftps_noffs++] = i; + } + } + + if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) { + dt_dprintf("fasttrap probe creation ioctl failed: %s\n", + strerror(errno)); + return (dt_set_errno(dtp, errno)); + } + + return (ftp->ftps_noffs); +} diff --git a/cddl/lib/Makefile b/cddl/lib/Makefile index 2bfc6c1e1574..9371865ca428 100644 --- a/cddl/lib/Makefile +++ b/cddl/lib/Makefile @@ -26,7 +26,7 @@ _libzpool= libzpool .endif .endif -.if ${MACHINE_CPUARCH} != "sparc64" && ${MACHINE_CPUARCH} != "riscv" +.if ${MACHINE_CPUARCH} != "sparc64" _drti= drti _libdtrace= libdtrace .endif diff --git a/cddl/lib/libdtrace/Makefile b/cddl/lib/libdtrace/Makefile index 642357fca309..080865c44bab 100644 --- a/cddl/lib/libdtrace/Makefile +++ b/cddl/lib/libdtrace/Makefile @@ -95,6 +95,10 @@ CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/mips CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/powerpc .PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/powerpc .PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/powerpc +.elif ${MACHINE_CPUARCH} == "riscv" +CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/riscv +.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/riscv +.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/riscv .elif ${MACHINE_CPUARCH} == "sparc64" CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/sparc .PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/sparc diff --git a/cddl/usr.sbin/Makefile b/cddl/usr.sbin/Makefile index 07dc671639f2..ff96d859f399 100644 --- a/cddl/usr.sbin/Makefile +++ b/cddl/usr.sbin/Makefile @@ -26,7 +26,8 @@ _lockstat= lockstat _plockstat= plockstat .endif -.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm" +.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm" || \ + ${MACHINE_CPUARCH} == "riscv" _dtrace= dtrace _lockstat= lockstat .endif diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index 086d7786b93c..c2cfd820a610 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -12026,7 +12026,7 @@ dtrace_buffer_alloc(dtrace_buffer_t *bufs, size_t size, int flags, *factor = 1; #if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) || \ - defined(__mips__) || defined(__powerpc__) + defined(__mips__) || defined(__powerpc__) || defined(__riscv__) /* * FreeBSD isn't good at limiting the amount of memory we * ask to malloc, so let's place a limit here before trying diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h index 730b42374a86..cd5f4d0d5eed 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h @@ -2495,6 +2495,16 @@ extern void dtrace_helpers_destroy(proc_t *); #define DTRACE_INVOP_SD 1 #define DTRACE_INVOP_LD 2 + +#elif defined(__riscv__) + +#define SD_RA_SP_MASK 0x1fff07f +#define SD_RA_SP 0x0113023 + +#define DTRACE_INVOP_SD 1 +#define DTRACE_INVOP_RET 2 +#define DTRACE_INVOP_NOP 3 + #endif #ifdef __cplusplus diff --git a/sys/cddl/contrib/opensolaris/uts/riscv/dtrace/fasttrap_isa.c b/sys/cddl/contrib/opensolaris/uts/riscv/dtrace/fasttrap_isa.c new file mode 100644 index 000000000000..17ef0f3a94a7 --- /dev/null +++ b/sys/cddl/contrib/opensolaris/uts/riscv/dtrace/fasttrap_isa.c @@ -0,0 +1,29 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * XXX: Placeholder for RISC-V fasttrap code + */ diff --git a/sys/cddl/contrib/opensolaris/uts/riscv/sys/fasttrap_isa.h b/sys/cddl/contrib/opensolaris/uts/riscv/sys/fasttrap_isa.h new file mode 100644 index 000000000000..9d164e4c5bd8 --- /dev/null +++ b/sys/cddl/contrib/opensolaris/uts/riscv/sys/fasttrap_isa.h @@ -0,0 +1,46 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _FASTTRAP_ISA_H +#define _FASTTRAP_ISA_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32_t fasttrap_instr_t; + +/* XXX: Place for RISC-V fasttrap headers */ + +#ifdef __cplusplus +} +#endif + +#endif /* _FASTTRAP_ISA_H */ diff --git a/sys/cddl/dev/dtrace/riscv/dtrace_asm.S b/sys/cddl/dev/dtrace/riscv/dtrace_asm.S new file mode 100644 index 000000000000..da2045813e89 --- /dev/null +++ b/sys/cddl/dev/dtrace/riscv/dtrace_asm.S @@ -0,0 +1,176 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Portions Copyright 2016 Ruslan Bukin + * + * $FreeBSD$ + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#define _ASM +#define _LOCORE + +#include +#include + +#include +#include + +#include "assym.s" + +/* +void dtrace_membar_producer(void) +*/ +ENTRY(dtrace_membar_producer) + RET +END(dtrace_membar_producer) + +/* +void dtrace_membar_consumer(void) +*/ +ENTRY(dtrace_membar_consumer) + RET +END(dtrace_membar_consumer) + +/* +dtrace_icookie_t dtrace_interrupt_disable(void) +*/ +ENTRY(dtrace_interrupt_disable) + csrci sstatus, 1 + RET +END(dtrace_interrupt_disable) + +/* +void dtrace_interrupt_enable(dtrace_icookie_t cookie) +*/ +ENTRY(dtrace_interrupt_enable) + csrsi sstatus, 1 + RET +END(dtrace_interrupt_enable) +/* +uint8_t +dtrace_fuword8_nocheck(void *addr) +*/ +ENTRY(dtrace_fuword8_nocheck) + lb a0, 0(a0) + RET +END(dtrace_fuword8_nocheck) + +/* +uint16_t +dtrace_fuword16_nocheck(void *addr) +*/ +ENTRY(dtrace_fuword16_nocheck) + lh a0, 0(a0) + RET +END(dtrace_fuword16_nocheck) + +/* +uint32_t +dtrace_fuword32_nocheck(void *addr) +*/ +ENTRY(dtrace_fuword32_nocheck) + lw a0, 0(a0) + RET +END(dtrace_fuword32_nocheck) + +/* +uint64_t +dtrace_fuword64_nocheck(void *addr) +*/ +ENTRY(dtrace_fuword64_nocheck) + ld a0, 0(a0) + RET +END(dtrace_fuword64_nocheck) + +/* +void +dtrace_copy(uintptr_t uaddr, uintptr_t kaddr, size_t size) +*/ +ENTRY(dtrace_copy) + beqz a2, 2f /* If len == 0 then skip loop */ +1: + lb a4, 0(a0) /* Load from uaddr */ + addi a0, a0, 1 + sb a4, 0(a1) /* Store in kaddr */ + addi a1, a1, 1 + addi a2, a2, -1 /* len-- */ + bnez a2, 1b +2: + RET +END(dtrace_copy) + +/* +void +dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size, + volatile uint16_t *flags) +XXX: Check for flags? +*/ +ENTRY(dtrace_copystr) + beqz a2, 2f /* If len == 0 then skip loop */ + lb a4, 0(a0) /* Load from uaddr */ + addi a0, a0, 1 + sb a4, 0(a1) /* Store in kaddr */ + addi a1, a1, 1 + beqz a4, 2f /* If == 0 then break */ + addi a2, a2, -1 /* len-- */ + bnez a2, 1b +2: + RET +END(dtrace_copystr) + +/* +uintptr_t +dtrace_caller(int aframes) +*/ +ENTRY(dtrace_caller) + li a0, -1 + RET +END(dtrace_caller) + +/* +uint32_t +dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new) +*/ +ENTRY(dtrace_cas32) +1: lr.w a3, 0(a0) /* Load target */ + bne a3, a1, 2f /* *target != cmp ? return */ + sc.w a4, a2, 0(a0) /* Store new to target */ + bnez a4, 1b /* Try again if store not succeed */ +2: mv a0, a3 /* Return the value loaded from target */ + RET +END(dtrace_cas32) + +/* +void * +dtrace_casptr(volatile void *target, volatile void *cmp, volatile void *new) +*/ +ENTRY(dtrace_casptr) +1: lr.d a3, 0(a0) /* Load target */ + bne a3, a1, 2f /* *target != cmp ? return */ + sc.d a4, a2, 0(a0) /* Store new to target */ + bnez a4, 1b /* Try again if store not succeed */ +2: mv a0, a3 /* Return the value loaded from target */ + RET +END(dtrace_casptr) diff --git a/sys/cddl/dev/dtrace/riscv/dtrace_isa.c b/sys/cddl/dev/dtrace/riscv/dtrace_isa.c new file mode 100644 index 000000000000..955d2cb10f65 --- /dev/null +++ b/sys/cddl/dev/dtrace/riscv/dtrace_isa.c @@ -0,0 +1,394 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Portions Copyright 2016 Ruslan Bukin + * + * $FreeBSD$ + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "regset.h" + +/* + * Wee need some reasonable default to prevent backtrace code + * from wandering too far + */ +#define MAX_FUNCTION_SIZE 0x10000 +#define MAX_PROLOGUE_SIZE 0x100 +#define MAX_USTACK_DEPTH 2048 + +uint8_t dtrace_fuword8_nocheck(void *); +uint16_t dtrace_fuword16_nocheck(void *); +uint32_t dtrace_fuword32_nocheck(void *); +uint64_t dtrace_fuword64_nocheck(void *); + +void +dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, + uint32_t *intrpc) +{ + struct unwind_state state; + int scp_offset; + register_t sp; + int depth; + + depth = 0; + + if (intrpc != 0) { + pcstack[depth++] = (pc_t) intrpc; + } + + aframes++; + + __asm __volatile("mv %0, sp" : "=&r" (sp)); + + state.fp = (uint64_t)__builtin_frame_address(0); + state.sp = sp; + state.pc = (uint64_t)dtrace_getpcstack; + + while (depth < pcstack_limit) { + if (unwind_frame(&state)) + break; + + if (!INKERNEL(state.pc) || !INKERNEL(state.fp)) + break; + + /* + * NB: Unlike some other architectures, we don't need to + * explicitly insert cpu_dtrace_caller as it appears in the + * normal kernel stack trace rather than a special trap frame. + */ + if (aframes > 0) { + aframes--; + } else { + pcstack[depth++] = state.pc; + } + + } + + for (; depth < pcstack_limit; depth++) { + pcstack[depth] = 0; + } +} + +static int +dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc, + uintptr_t fp) +{ + volatile uint16_t *flags; + uintptr_t oldfp; + int ret; + + ret = 0; + flags = (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; + + ASSERT(pcstack == NULL || pcstack_limit > 0); + + while (pc != 0) { + /* + * We limit the number of times we can go around this + * loop to account for a circular stack. + */ + if (ret++ >= MAX_USTACK_DEPTH) { + *flags |= CPU_DTRACE_BADSTACK; + cpu_core[curcpu].cpuc_dtrace_illval = fp; + break; + } + + if (pcstack != NULL) { + *pcstack++ = (uint64_t)pc; + pcstack_limit--; + if (pcstack_limit <= 0) + break; + } + + if (fp == 0) + break; + + pc = dtrace_fuword64((void *)(fp + + offsetof(struct riscv_frame, f_retaddr))); + fp = dtrace_fuword64((void *)fp); + + if (fp == oldfp) { + *flags |= CPU_DTRACE_BADSTACK; + cpu_core[curcpu].cpuc_dtrace_illval = fp; + break; + } + } + + return (ret); +} + +void +dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) +{ + volatile uint16_t *flags; + struct trapframe *tf; + uintptr_t pc, sp, fp; + proc_t *p; + int n; + + p = curproc; + flags = (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; + + if (*flags & CPU_DTRACE_FAULT) + return; + + if (pcstack_limit <= 0) + return; + + /* + * If there's no user context we still need to zero the stack. + */ + if (p == NULL || (tf = curthread->td_frame) == NULL) + goto zero; + + *pcstack++ = (uint64_t)p->p_pid; + pcstack_limit--; + + if (pcstack_limit <= 0) + return; + + pc = tf->tf_sepc; + sp = tf->tf_sp; + fp = tf->tf_s[0]; + + if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { + /* + * In an entry probe. The frame pointer has not yet been + * pushed (that happens in the function prologue). The + * best approach is to add the current pc as a missing top + * of stack and back the pc up to the caller, which is stored + * at the current stack pointer address since the call + * instruction puts it there right before the branch. + */ + + *pcstack++ = (uint64_t)pc; + pcstack_limit--; + if (pcstack_limit <= 0) + return; + + pc = tf->tf_ra; + } + + n = dtrace_getustack_common(pcstack, pcstack_limit, pc, fp); + ASSERT(n >= 0); + ASSERT(n <= pcstack_limit); + + pcstack += n; + pcstack_limit -= n; + +zero: + while (pcstack_limit-- > 0) + *pcstack++ = 0; +} + +int +dtrace_getustackdepth(void) +{ + + printf("IMPLEMENT ME: %s\n", __func__); + + return (0); +} + +void +dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit) +{ + + printf("IMPLEMENT ME: %s\n", __func__); +} + +/*ARGSUSED*/ +uint64_t +dtrace_getarg(int arg, int aframes) +{ + + printf("IMPLEMENT ME: %s\n", __func__); + + return (0); +} + +int +dtrace_getstackdepth(int aframes) +{ + struct unwind_state state; + int scp_offset; + register_t sp; + int depth; + int done; + + depth = 1; + done = 0; + + __asm __volatile("mv %0, sp" : "=&r" (sp)); + + state.fp = (uint64_t)__builtin_frame_address(0); + state.sp = sp; + state.pc = (uint64_t)dtrace_getstackdepth; + + do { + done = unwind_frame(&state); + if (!INKERNEL(state.pc) || !INKERNEL(state.fp)) + break; + depth++; + } while (!done); + + if (depth < aframes) + return (0); + else + return (depth - aframes); +} + +ulong_t +dtrace_getreg(struct trapframe *rp, uint_t reg) +{ + + printf("IMPLEMENT ME: %s\n", __func__); + + return (0); +} + +static int +dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size) +{ + + if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[curcpu].cpuc_dtrace_illval = uaddr; + return (0); + } + + return (1); +} + +void +dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size, + volatile uint16_t *flags) +{ + + if (dtrace_copycheck(uaddr, kaddr, size)) + dtrace_copy(uaddr, kaddr, size); +} + +void +dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size, + volatile uint16_t *flags) +{ + + if (dtrace_copycheck(uaddr, kaddr, size)) + dtrace_copy(kaddr, uaddr, size); +} + +void +dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size, + volatile uint16_t *flags) +{ + + if (dtrace_copycheck(uaddr, kaddr, size)) + dtrace_copystr(uaddr, kaddr, size, flags); +} + +void +dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size, + volatile uint16_t *flags) +{ + + if (dtrace_copycheck(uaddr, kaddr, size)) + dtrace_copystr(kaddr, uaddr, size, flags); +} + +uint8_t +dtrace_fuword8(void *uaddr) +{ + + if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; + return (0); + } + + return (dtrace_fuword8_nocheck(uaddr)); +} + +uint16_t +dtrace_fuword16(void *uaddr) +{ + + if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; + return (0); + } + + return (dtrace_fuword16_nocheck(uaddr)); +} + +uint32_t +dtrace_fuword32(void *uaddr) +{ + + if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; + return (0); + } + + return (dtrace_fuword32_nocheck(uaddr)); +} + +uint64_t +dtrace_fuword64(void *uaddr) +{ + + if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR); + cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr; + return (0); + } + + return (dtrace_fuword64_nocheck(uaddr)); +} diff --git a/sys/cddl/dev/dtrace/riscv/dtrace_subr.c b/sys/cddl/dev/dtrace/riscv/dtrace_subr.c new file mode 100644 index 000000000000..90d15fc1e0d5 --- /dev/null +++ b/sys/cddl/dev/dtrace/riscv/dtrace_subr.c @@ -0,0 +1,282 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * Portions Copyright 2016 Ruslan Bukin + * + * $FreeBSD$ + * + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern dtrace_id_t dtrace_probeid_error; +extern int (*dtrace_invop_jump_addr)(struct trapframe *); +extern void dtrace_getnanotime(struct timespec *tsp); + +int dtrace_invop(uintptr_t, struct trapframe *, uintptr_t); +void dtrace_invop_init(void); +void dtrace_invop_uninit(void); + +typedef struct dtrace_invop_hdlr { + int (*dtih_func)(uintptr_t, struct trapframe *, uintptr_t); + struct dtrace_invop_hdlr *dtih_next; +} dtrace_invop_hdlr_t; + +dtrace_invop_hdlr_t *dtrace_invop_hdlr; + +int +dtrace_invop(uintptr_t addr, struct trapframe *frame, uintptr_t eax) +{ + dtrace_invop_hdlr_t *hdlr; + int rval; + + for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next) + if ((rval = hdlr->dtih_func(addr, frame, eax)) != 0) + return (rval); + + return (0); +} + + +void +dtrace_invop_add(int (*func)(uintptr_t, struct trapframe *, uintptr_t)) +{ + dtrace_invop_hdlr_t *hdlr; + + hdlr = kmem_alloc(sizeof (dtrace_invop_hdlr_t), KM_SLEEP); + hdlr->dtih_func = func; + hdlr->dtih_next = dtrace_invop_hdlr; + dtrace_invop_hdlr = hdlr; +} + +void +dtrace_invop_remove(int (*func)(uintptr_t, struct trapframe *, uintptr_t)) +{ + dtrace_invop_hdlr_t *hdlr, *prev; + + hdlr = dtrace_invop_hdlr; + prev = NULL; + + for (;;) { + if (hdlr == NULL) + panic("attempt to remove non-existent invop handler"); + + if (hdlr->dtih_func == func) + break; + + prev = hdlr; + hdlr = hdlr->dtih_next; + } + + if (prev == NULL) { + ASSERT(dtrace_invop_hdlr == hdlr); + dtrace_invop_hdlr = hdlr->dtih_next; + } else { + ASSERT(dtrace_invop_hdlr != hdlr); + prev->dtih_next = hdlr->dtih_next; + } + + kmem_free(hdlr, 0); +} + +/*ARGSUSED*/ +void +dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit)) +{ + + (*func)(0, (uintptr_t)VM_MIN_KERNEL_ADDRESS); +} + +void +dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg) +{ + cpuset_t cpus; + + if (cpu == DTRACE_CPUALL) + cpus = all_cpus; + else + CPU_SETOF(cpu, &cpus); + + smp_rendezvous_cpus(cpus, smp_no_rendevous_barrier, func, + smp_no_rendevous_barrier, arg); +} + +static void +dtrace_sync_func(void) +{ + +} + +void +dtrace_sync(void) +{ + + dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL); +} + +/* + * DTrace needs a high resolution time function which can + * be called from a probe context and guaranteed not to have + * instrumented with probes itself. + * + * Returns nanoseconds since boot. + */ +uint64_t +dtrace_gethrtime() +{ + struct timespec curtime; + + nanouptime(&curtime); + + return (curtime.tv_sec * 1000000000UL + curtime.tv_nsec); + +} + +uint64_t +dtrace_gethrestime(void) +{ + struct timespec current_time; + + dtrace_getnanotime(¤t_time); + + return (current_time.tv_sec * 1000000000UL + current_time.tv_nsec); +} + +/* Function to handle DTrace traps during probes. See riscv/riscv/trap.c */ +int +dtrace_trap(struct trapframe *frame, u_int type) +{ + /* + * A trap can occur while DTrace executes a probe. Before + * executing the probe, DTrace blocks re-scheduling and sets + * a flag in it's per-cpu flags to indicate that it doesn't + * want to fault. On returning from the probe, the no-fault + * flag is cleared and finally re-scheduling is enabled. + * + * Check if DTrace has enabled 'no-fault' mode: + * + */ + + if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) { + /* + * There are only a couple of trap types that are expected. + * All the rest will be handled in the usual way. + */ + switch (type) { + case EXCP_LOAD_ACCESS_FAULT: + case EXCP_STORE_ACCESS_FAULT: + case EXCP_INSTR_ACCESS_FAULT: + /* Flag a bad address. */ + cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR; + cpu_core[curcpu].cpuc_dtrace_illval = 0; + + /* + * Offset the instruction pointer to the instruction + * following the one causing the fault. + */ + frame->tf_sepc += 4; + + return (1); + default: + /* Handle all other traps in the usual way. */ + break; + } + } + + /* Handle the trap in the usual way. */ + return (0); +} + +void +dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, + int fault, int fltoffs, uintptr_t illval) +{ + + dtrace_probe(dtrace_probeid_error, (uint64_t)(uintptr_t)state, + (uintptr_t)epid, + (uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs); +} + +static int +dtrace_invop_start(struct trapframe *frame) +{ + int data, invop, reg, update_sp; + register_t arg1, arg2; + register_t *sp; + uint32_t imm; + InstFmt i; + int offs; + int tmp; + + invop = dtrace_invop(frame->tf_sepc, frame, frame->tf_sepc); + + if (invop == RISCV_INSN_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); + *sp = frame->tf_ra; + frame->tf_sepc += INSN_SIZE; + return (0); + } + + return (-1); +} + +void +dtrace_invop_init(void) +{ + + dtrace_invop_jump_addr = dtrace_invop_start; +} + +void +dtrace_invop_uninit(void) +{ + + dtrace_invop_jump_addr = 0; +} diff --git a/sys/cddl/dev/dtrace/riscv/regset.h b/sys/cddl/dev/dtrace/riscv/regset.h new file mode 100644 index 000000000000..f99b48f8354f --- /dev/null +++ b/sys/cddl/dev/dtrace/riscv/regset.h @@ -0,0 +1,51 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * $FreeBSD$ + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */ + +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + +#ifndef _REGSET_H +#define _REGSET_H + +/* + * #pragma ident "@(#)regset.h 1.11 05/06/08 SMI" + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Place here */ + +#ifdef __cplusplus +} +#endif + +#endif /* _REGSET_H */ diff --git a/sys/cddl/dev/fbt/riscv/fbt_isa.c b/sys/cddl/dev/fbt/riscv/fbt_isa.c new file mode 100644 index 000000000000..a8ff9ad92432 --- /dev/null +++ b/sys/cddl/dev/fbt/riscv/fbt_isa.c @@ -0,0 +1,165 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * 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 + * + * $FreeBSD$ + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include + +#include + +#include + +#include "fbt.h" + +#define FBT_PATCHVAL (RISCV_INSN_BREAK) +#define FBT_ENTRY "entry" +#define FBT_RETURN "return" + +int +fbt_invop(uintptr_t addr, struct trapframe *frame, uintptr_t rval) +{ + solaris_cpu_t *cpu; + fbt_probe_t *fbt; + + cpu = &solaris_cpu[curcpu]; + fbt = fbt_probetab[FBT_ADDR2NDX(addr)]; + + for (; fbt != NULL; fbt = fbt->fbtp_hashnext) { + if ((uintptr_t)fbt->fbtp_patchpoint == addr) { + cpu->cpu_dtrace_caller = addr; + + dtrace_probe(fbt->fbtp_id, frame->tf_a[0], + frame->tf_a[1], frame->tf_a[2], + frame->tf_a[3], frame->tf_a[4]); + + cpu->cpu_dtrace_caller = 0; + return (fbt->fbtp_savedval); + } + } + + return (0); +} + +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); +} + +int +fbt_provide_module_function(linker_file_t lf, int symindx, + linker_symval_t *symval, void *opaque) +{ + fbt_probe_t *fbt, *retfbt; + uint32_t *target, *start; + uint32_t *instr, *limit; + const char *name; + char *modname; + int offs; + + modname = opaque; + name = symval->name; + + /* Check if function is excluded from instrumentation */ + if (fbt_excluded(name)) + return (0); + + instr = (uint32_t *)(symval->value); + limit = (uint32_t *)(symval->value + symval->size); + + /* Look for sd operation */ + for (; instr < limit; instr++) { + if ((*instr & SD_RA_SP_MASK) == SD_RA_SP) + break; + } + + if (instr >= limit) + return (0); + + fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO); + fbt->fbtp_name = name; + fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, + name, FBT_ENTRY, 3, fbt); + fbt->fbtp_patchpoint = instr; + 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_symindx = symindx; + + fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; + fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; + + lf->fbt_nentries++; + + retfbt = NULL; +again: + for (; instr < limit; instr++) { + if (*instr == RISCV_INSN_RET) + break; + } + + if (instr >= limit) + return (0); + + /* + * We have a winner! + */ + fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO); + fbt->fbtp_name = name; + if (retfbt == NULL) { + fbt->fbtp_id = dtrace_probe_create(fbt_id, modname, + name, FBT_RETURN, 3, fbt); + } else { + retfbt->fbtp_next = fbt; + fbt->fbtp_id = retfbt->fbtp_id; + } + retfbt = fbt; + + fbt->fbtp_patchpoint = instr; + fbt->fbtp_ctl = lf; + fbt->fbtp_loadcnt = lf->loadcnt; + fbt->fbtp_symindx = symindx; + fbt->fbtp_rval = DTRACE_INVOP_RET; + fbt->fbtp_savedval = *instr; + fbt->fbtp_patchval = FBT_PATCHVAL; + fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)]; + fbt_probetab[FBT_ADDR2NDX(instr)] = fbt; + + lf->fbt_nentries++; + + instr++; + goto again; +} diff --git a/sys/cddl/dev/fbt/riscv/fbt_isa.h b/sys/cddl/dev/fbt/riscv/fbt_isa.h new file mode 100644 index 000000000000..5552f31a64a6 --- /dev/null +++ b/sys/cddl/dev/fbt/riscv/fbt_isa.h @@ -0,0 +1,30 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + * + * $FreeBSD$ + * + */ + +#ifndef _FBT_ISA_H_ +#define _FBT_ISA_H_ + +typedef uint32_t fbt_patchval_t; + +#endif diff --git a/sys/cddl/dev/profile/profile.c b/sys/cddl/dev/profile/profile.c index 4deac8710dc7..3b584246d14e 100644 --- a/sys/cddl/dev/profile/profile.c +++ b/sys/cddl/dev/profile/profile.c @@ -143,6 +143,11 @@ struct profile_probe_percpu; #define PROF_ARTIFICIAL_FRAMES 10 #endif +#ifdef __riscv__ +/* TODO: verify */ +#define PROF_ARTIFICIAL_FRAMES 10 +#endif + typedef struct profile_probe { char prof_name[PROF_NAMELEN]; dtrace_id_t prof_id; diff --git a/sys/conf/files.riscv b/sys/conf/files.riscv index 184018522a86..fe30078f183f 100644 --- a/sys/conf/files.riscv +++ b/sys/conf/files.riscv @@ -1,4 +1,8 @@ # $FreeBSD$ +cddl/compat/opensolaris/kern/opensolaris_atomic.c optional zfs | dtrace compile-with "${CDDL_C}" +cddl/dev/dtrace/riscv/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}" +cddl/dev/dtrace/riscv/dtrace_subr.c optional dtrace compile-with "${DTRACE_C}" +cddl/dev/fbt/riscv/fbt_isa.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" crypto/blowfish/bf_enc.c optional crypto | ipsec crypto/des/des_enc.c optional crypto | ipsec | netsmb dev/ofw/ofw_cpu.c optional fdt diff --git a/sys/riscv/include/frame.h b/sys/riscv/include/frame.h index e74d9262b355..d0756f757877 100644 --- a/sys/riscv/include/frame.h +++ b/sys/riscv/include/frame.h @@ -59,6 +59,11 @@ struct trapframe { uint64_t tf_scause; }; +struct riscv_frame { + struct riscv_frame *f_frame; + u_long f_retaddr; +}; + /* * Signal frame. Pushed onto user stack before calling sigcode. */ diff --git a/sys/riscv/include/riscvreg.h b/sys/riscv/include/riscvreg.h index a71ee47e83fd..6984ab118ab5 100644 --- a/sys/riscv/include/riscvreg.h +++ b/sys/riscv/include/riscvreg.h @@ -124,6 +124,11 @@ #define XLEN 8 #define INSN_SIZE 4 +#define INSN_SIZE 4 +#define RISCV_INSN_NOP 0x00000013 +#define RISCV_INSN_BREAK 0x00100073 +#define RISCV_INSN_RET 0x00008067 + #define CSR_ZIMM(val) \ (__builtin_constant_p(val) && ((u_long)(val) < 32)) diff --git a/sys/riscv/riscv/trap.c b/sys/riscv/riscv/trap.c index 6327204563f1..22d27f41e592 100644 --- a/sys/riscv/riscv/trap.c +++ b/sys/riscv/riscv/trap.c @@ -64,6 +64,12 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef KDTRACE_HOOKS +#include +#endif + +int (*dtrace_invop_jump_addr)(struct trapframe *); + extern register_t fsu_intr_fault; /* Called from exception.S */ @@ -271,6 +277,11 @@ do_trap_supervisor(struct trapframe *frame) return; } +#ifdef KDTRACE_HOOKS + if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, exception)) + return; +#endif + CTR3(KTR_TRAP, "do_trap_supervisor: curthread: %p, sepc: %lx, frame: %p", curthread, frame->tf_sepc, frame); @@ -281,6 +292,12 @@ do_trap_supervisor(struct trapframe *frame) data_abort(frame, 0); break; case EXCP_INSTR_BREAKPOINT: +#ifdef KDTRACE_HOOKS + if (dtrace_invop_jump_addr != 0) { + dtrace_invop_jump_addr(frame); + break; + } +#endif #ifdef KDB kdb_trap(exception, 0, frame); #else @@ -290,7 +307,7 @@ do_trap_supervisor(struct trapframe *frame) break; case EXCP_INSTR_ILLEGAL: dump_regs(frame); - panic("Illegal instruction at %x\n", frame->tf_sepc); + panic("Illegal instruction at 0x%016lx\n", frame->tf_sepc); break; default: dump_regs(frame);