diff --git a/cddl/lib/libdtrace/Makefile b/cddl/lib/libdtrace/Makefile index 84258169e44a..468603633658 100644 --- a/cddl/lib/libdtrace/Makefile +++ b/cddl/lib/libdtrace/Makefile @@ -1,145 +1,146 @@ # $FreeBSD$ .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/common .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libgen/common PACKAGE= dtrace LIB= dtrace SRCS= dt_aggregate.c \ dt_as.c \ dt_buf.c \ dt_cc.c \ dt_cg.c \ dt_consume.c \ dt_decl.c \ dt_dis.c \ dt_dof.c \ dt_error.c \ dt_errtags.c \ dt_grammar.y \ dt_handle.c \ dt_ident.c \ dt_isadep.c \ dt_inttab.c \ dt_lex.l \ dt_link.c \ dt_list.c \ dt_map.c \ dt_module.c \ dt_names.c \ dt_open.c \ dt_options.c \ dt_parser.c \ dt_pcb.c \ dt_pid.c \ dt_pq.c \ dt_pragma.c \ dt_print.c \ dt_printf.c \ dt_proc.c \ dt_program.c \ dt_provider.c \ dt_regset.c \ dt_string.c \ dt_strtab.c \ dt_subr.c \ dt_sugar.c \ dt_work.c \ dt_xlator.c \ gmatch.c DSRCS= errno.d \ io.d \ ip.d \ psinfo.d \ sctp.d \ siftr.d \ signal.d \ tcp.d \ socket.d \ udp.d \ udplite.d \ unistd.d FILES= ${DSRCS} FILESDIR= /usr/lib/dtrace FILESMODE= ${NOBINMODE} INCSGROUPS= INCS SYSINCS SYSINCSDIR= ${INCLUDEDIR}/sys INCS+= ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/common/dtrace.h SYSINCS+= ${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h SYSINCS+= ${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common/sys/ctf_api.h WARNS?= 1 CFLAGS+= -DIN_BASE CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/include CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/lib/libspl/include/ CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/lib/libspl/include/os/freebsd CFLAGS+= -I${SRCTOP}/sys CFLAGS+= -include ${SRCTOP}/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h CFLAGS+= -DHAVE_ISSETUGID CFLAGS+= -I${.OBJDIR} -I${.CURDIR} \ -I${SRCTOP}/sys/cddl/dev/dtrace/${MACHINE_ARCH} \ -I${SRCTOP}/sys/cddl/dev/kinst \ -I${SRCTOP}/sys/cddl/compat/opensolaris \ -I${SRCTOP}/cddl/compat/opensolaris/include \ -I${OPENSOLARIS_USR_DISTDIR}/head \ -I${OPENSOLARIS_USR_DISTDIR}/lib/libctf/common \ -I${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common \ -I${OPENSOLARIS_SYS_DISTDIR}/uts/common #CFLAGS+= -DYYDEBUG .if ${MACHINE_CPUARCH} == "aarch64" CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/aarch64 .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/aarch64 .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/aarch64 .elif ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" CFLAGS+= -I${SRCTOP}/sys/cddl/dev/dtrace/x86 CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/intel -DDIS_MEM .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/i386 .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/${MACHINE_ARCH} .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/x86 .elif ${MACHINE_CPUARCH} == "arm" CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/arm .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/arm .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/arm .elif ${MACHINE_CPUARCH} == "powerpc" CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/powerpc .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/powerpc .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/powerpc .elif ${MACHINE_CPUARCH} == "riscv" CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/riscv .PATH: ${SRCTOP}/cddl/contrib/opensolaris/lib/libdtrace/riscv .PATH: ${SRCTOP}/sys/cddl/dev/dtrace/riscv .else # temporary hack CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/intel .endif .if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64" SRCS+= dis_tables.c instr_size.c DSRCS+= regs_x86.d .endif .if ${MACHINE_CPUARCH} == "riscv" SRCS+= instr_size.c +DSRCS+= regs_riscv.d .endif YFLAGS+=-d LIBADD= ctf elf proc pthread rtld_db CLEANFILES= dt_errtags.c dt_names.c .include dt_errtags.c: ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/dt_errtags.h sh ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/mkerrtags.sh < ${.ALLSRC} > ${.TARGET} dt_names.c: ${OPENSOLARIS_SYS_DISTDIR}/uts/common/sys/dtrace.h sh ${OPENSOLARIS_USR_DISTDIR}/lib/libdtrace/common/mknames.sh < ${.ALLSRC} > ${.TARGET} diff --git a/cddl/lib/libdtrace/regs_riscv.d b/cddl/lib/libdtrace/regs_riscv.d new file mode 100644 index 000000000000..e8a9667d2efd --- /dev/null +++ b/cddl/lib/libdtrace/regs_riscv.d @@ -0,0 +1,74 @@ +/* + * SPDX-License-Identifier: CDDL 1.0 + * + * Copyright 2023 Christos Margiolis + */ + +inline int R_ZERO = 0; +#pragma D binding "1.13" R_ZERO +inline int R_RA = 1; +#pragma D binding "1.13" R_RA +inline int R_SP = 2; +#pragma D binding "1.13" R_SP +inline int R_GP = 3; +#pragma D binding "1.13" R_GP +inline int R_TP = 4; +#pragma D binding "1.13" R_TP +inline int R_T0 = 5; +#pragma D binding "1.13" R_T0 +inline int R_T1 = 6; +#pragma D binding "1.13" R_T1 +inline int R_T2 = 7; +#pragma D binding "1.13" R_T2 +inline int R_S0 = 8; +#pragma D binding "1.13" R_S0 +inline int R_FP = 8; +#pragma D binding "1.13" R_FP +inline int R_S1 = 9; +#pragma D binding "1.13" R_S1 +inline int R_A0 = 10; +#pragma D binding "1.13" R_A0 +inline int R_A1 = 11; +#pragma D binding "1.13" R_A1 +inline int R_A2 = 12; +#pragma D binding "1.13" R_A2 +inline int R_A3 = 13; +#pragma D binding "1.13" R_A3 +inline int R_A4 = 14; +#pragma D binding "1.13" R_A4 +inline int R_A5 = 15; +#pragma D binding "1.13" R_A5 +inline int R_A6 = 16; +#pragma D binding "1.13" R_A6 +inline int R_A7 = 17; +#pragma D binding "1.13" R_A7 +inline int R_S2 = 18; +#pragma D binding "1.13" R_S2 +inline int R_S3 = 19; +#pragma D binding "1.13" R_S3 +inline int R_S4 = 20; +#pragma D binding "1.13" R_S4 +inline int R_S5 = 21; +#pragma D binding "1.13" R_S5 +inline int R_S6 = 22; +#pragma D binding "1.13" R_S6 +inline int R_S7 = 23; +#pragma D binding "1.13" R_S7 +inline int R_S8 = 24; +#pragma D binding "1.13" R_S8 +inline int R_S9 = 25; +#pragma D binding "1.13" R_S9 +inline int R_S10 = 26; +#pragma D binding "1.13" R_S10 +inline int R_S11 = 27; +#pragma D binding "1.13" R_S11 +inline int R_T3 = 28; +#pragma D binding "1.13" R_T3 +inline int R_T4 = 29; +#pragma D binding "1.13" R_T4 +inline int R_T5 = 30; +#pragma D binding "1.13" R_T5 +inline int R_T6 = 31; +#pragma D binding "1.13" R_T6 +inline int R_PC = 32; +#pragma D binding "1.13" R_PC diff --git a/sys/cddl/dev/dtrace/riscv/dtrace_isa.c b/sys/cddl/dev/dtrace/riscv/dtrace_isa.c index 6e6459a8ce74..61743c42d9b7 100644 --- a/sys/cddl/dev/dtrace/riscv/dtrace_isa.c +++ b/sys/cddl/dev/dtrace/riscv/dtrace_isa.c @@ -1,419 +1,443 @@ /* * 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 "regset.h" #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; uintptr_t caller; register_t sp; int scp_offset; int depth; depth = 0; caller = solaris_cpu[curcpu].cpu_dtrace_caller; if (intrpc != 0) { pcstack[depth++] = (pc_t)intrpc; } /* * Construct the unwind state, starting from this function. This frame, * and 'aframes' others will be skipped. */ __asm __volatile("mv %0, sp" : "=&r" (sp)); state.fp = (uintptr_t)__builtin_frame_address(0); state.sp = (uintptr_t)sp; state.pc = (uintptr_t)dtrace_getpcstack; while (depth < pcstack_limit) { if (!unwind_frame(curthread, &state)) break; if (!INKERNEL(state.pc) || !kstack_contains(curthread, (vm_offset_t)state.fp, sizeof(uintptr_t))) break; if (aframes > 0) { aframes--; /* * fbt_invop() records the return address at the time * the FBT probe fires. We need to insert this into the * backtrace manually, since the stack frame state at * the time of the probe does not capture it. */ if (aframes == 0 && caller != 0) pcstack[depth++] = caller; } 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; oldfp = fp; 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 - 1 * sizeof(uint64_t))); fp = dtrace_fuword64((void *)(fp - 2 * sizeof(uint64_t))); if (fp == oldfp) { *flags |= CPU_DTRACE_BADSTACK; cpu_core[curcpu].cpuc_dtrace_illval = fp; break; } oldfp = fp; } return (ret); } void dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit) { volatile uint16_t *flags; struct trapframe *tf; uintptr_t pc, 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; 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) { struct trapframe *tf; uintptr_t pc, fp; int n = 0; if (curproc == NULL || (tf = curthread->td_frame) == NULL) return (0); if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) return (-1); pc = tf->tf_sepc; 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. */ pc = tf->tf_ra; n++; } n += dtrace_getustack_common(NULL, 0, pc, fp); 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; bool done; depth = 1; done = false; __asm __volatile("mv %0, sp" : "=&r" (sp)); state.fp = (uintptr_t)__builtin_frame_address(0); state.sp = sp; state.pc = (uintptr_t)dtrace_getstackdepth; do { done = !unwind_frame(curthread, &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); + switch (reg) { + case REG_ZERO: + return (0); + case REG_RA: + return (rp->tf_ra); + case REG_SP: + return (rp->tf_sp); + case REG_GP: + return (rp->tf_gp); + case REG_TP: + return (rp->tf_tp); + case REG_T0 ... REG_T2: + return (rp->tf_t[reg - REG_T0]); + case REG_S0 ... REG_S1: + return (rp->tf_s[reg - REG_S0]); + case REG_A0 ... REG_A7: + return (rp->tf_a[reg - REG_A0]); + case REG_S2 ... REG_S11: + return (rp->tf_s[reg - REG_S2 + 2]); + case REG_T3 ... REG_T6: + return (rp->tf_t[reg - REG_T3 + 3]); + case REG_PC: + return (rp->tf_sepc); + default: + DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); + return (0); + } + /* NOTREACHED */ } 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/regset.h b/sys/cddl/dev/dtrace/riscv/regset.h index f99b48f8354f..034781f11238 100644 --- a/sys/cddl/dev/dtrace/riscv/regset.h +++ b/sys/cddl/dev/dtrace/riscv/regset.h @@ -1,51 +1,84 @@ /* * 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 */ +#define REG_ZERO 0 +#define REG_RA 1 +#define REG_SP 2 +#define REG_GP 3 +#define REG_TP 4 +#define REG_T0 5 +#define REG_T1 6 +#define REG_T2 7 +#define REG_S0 8 +#define REG_FP 8 +#define REG_S1 9 +#define REG_A0 10 +#define REG_A1 11 +#define REG_A2 12 +#define REG_A3 13 +#define REG_A4 14 +#define REG_A5 15 +#define REG_A6 16 +#define REG_A7 17 +#define REG_S2 18 +#define REG_S3 19 +#define REG_S4 20 +#define REG_S5 21 +#define REG_S6 22 +#define REG_S7 23 +#define REG_S8 24 +#define REG_S9 25 +#define REG_S10 26 +#define REG_S11 27 +#define REG_T3 28 +#define REG_T4 29 +#define REG_T5 30 +#define REG_T6 31 +#define REG_PC 32 #ifdef __cplusplus } #endif #endif /* _REGSET_H */