Add initial DTrace support for RISC-V.
Sponsored by: DARPA, AFRL Sponsored by: HEIF5
This commit is contained in:
parent
fa851a8bfb
commit
fed1ca4b71
@ -250,6 +250,9 @@ printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
|||||||
dofr[j].dofr_offset + 4;
|
dofr[j].dofr_offset + 4;
|
||||||
rel->r_info = ELF32_R_INFO(count + dep->de_global,
|
rel->r_info = ELF32_R_INFO(count + dep->de_global,
|
||||||
R_PPC_REL32);
|
R_PPC_REL32);
|
||||||
|
#elif defined(__riscv__)
|
||||||
|
/* XXX */
|
||||||
|
printf("%s:%s(%d): DOODAD\n",__FUNCTION__,__FILE__,__LINE__);
|
||||||
#elif defined(__sparc)
|
#elif defined(__sparc)
|
||||||
/*
|
/*
|
||||||
* Add 4 bytes to hit the low half of this 64-bit
|
* 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;
|
dofr[j].dofr_offset;
|
||||||
rel->r_info = ELF64_R_INFO(count + dep->de_global,
|
rel->r_info = ELF64_R_INFO(count + dep->de_global,
|
||||||
R_PPC64_REL64);
|
R_PPC64_REL64);
|
||||||
|
#elif defined(__riscv__)
|
||||||
|
/* XXX */
|
||||||
#elif defined(__i386) || defined(__amd64)
|
#elif defined(__i386) || defined(__amd64)
|
||||||
rel->r_offset = s->dofs_offset +
|
rel->r_offset = s->dofs_offset +
|
||||||
dofr[j].dofr_offset;
|
dofr[j].dofr_offset;
|
||||||
@ -935,7 +940,15 @@ dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
|
|||||||
|
|
||||||
return (0);
|
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)
|
#elif defined(__sparc)
|
||||||
|
|
||||||
#define DT_OP_RET 0x81c7e008
|
#define DT_OP_RET 0x81c7e008
|
||||||
|
@ -310,7 +310,8 @@ pfprint_fp(dtrace_hdl_t *dtp, FILE *fp, const char *format,
|
|||||||
case sizeof (double):
|
case sizeof (double):
|
||||||
return (dt_printf(dtp, fp, format,
|
return (dt_printf(dtp, fp, format,
|
||||||
*((double *)addr) / n));
|
*((double *)addr) / n));
|
||||||
#if !defined(__arm__) && !defined(__powerpc__) && !defined(__mips__)
|
#if !defined(__arm__) && !defined(__powerpc__) && \
|
||||||
|
!defined(__mips__) && !defined(__riscv__)
|
||||||
case sizeof (long double):
|
case sizeof (long double):
|
||||||
return (dt_printf(dtp, fp, format,
|
return (dt_printf(dtp, fp, format,
|
||||||
*((long double *)addr) / ldn));
|
*((long double *)addr) / ldn));
|
||||||
|
139
cddl/contrib/opensolaris/lib/libdtrace/riscv/dt_isadep.c
Normal file
139
cddl/contrib/opensolaris/lib/libdtrace/riscv/dt_isadep.c
Normal file
@ -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 <br@bsdpad.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
|
||||||
|
#include <dt_impl.h>
|
||||||
|
#include <dt_pid.h>
|
||||||
|
|
||||||
|
#if !defined(sun)
|
||||||
|
#include <libproc_compat.h>
|
||||||
|
#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);
|
||||||
|
}
|
@ -26,7 +26,7 @@ _libzpool= libzpool
|
|||||||
.endif
|
.endif
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
.if ${MACHINE_CPUARCH} != "sparc64" && ${MACHINE_CPUARCH} != "riscv"
|
.if ${MACHINE_CPUARCH} != "sparc64"
|
||||||
_drti= drti
|
_drti= drti
|
||||||
_libdtrace= libdtrace
|
_libdtrace= libdtrace
|
||||||
.endif
|
.endif
|
||||||
|
@ -95,6 +95,10 @@ CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/mips
|
|||||||
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/powerpc
|
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/powerpc
|
||||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/powerpc
|
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/powerpc
|
||||||
.PATH: ${.CURDIR}/../../../sys/cddl/dev/dtrace/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"
|
.elif ${MACHINE_CPUARCH} == "sparc64"
|
||||||
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/sparc
|
CFLAGS+= -I${OPENSOLARIS_SYS_DISTDIR}/uts/sparc
|
||||||
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/sparc
|
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/sparc
|
||||||
|
@ -26,7 +26,8 @@ _lockstat= lockstat
|
|||||||
_plockstat= plockstat
|
_plockstat= plockstat
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
|
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm" || \
|
||||||
|
${MACHINE_CPUARCH} == "riscv"
|
||||||
_dtrace= dtrace
|
_dtrace= dtrace
|
||||||
_lockstat= lockstat
|
_lockstat= lockstat
|
||||||
.endif
|
.endif
|
||||||
|
@ -12026,7 +12026,7 @@ err:
|
|||||||
|
|
||||||
*factor = 1;
|
*factor = 1;
|
||||||
#if defined(__aarch64__) || defined(__amd64__) || defined(__arm__) || \
|
#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
|
* FreeBSD isn't good at limiting the amount of memory we
|
||||||
* ask to malloc, so let's place a limit here before trying
|
* ask to malloc, so let's place a limit here before trying
|
||||||
|
@ -2495,6 +2495,16 @@ extern void dtrace_helpers_destroy(proc_t *);
|
|||||||
|
|
||||||
#define DTRACE_INVOP_SD 1
|
#define DTRACE_INVOP_SD 1
|
||||||
#define DTRACE_INVOP_LD 2
|
#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
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
29
sys/cddl/contrib/opensolaris/uts/riscv/dtrace/fasttrap_isa.c
Normal file
29
sys/cddl/contrib/opensolaris/uts/riscv/dtrace/fasttrap_isa.c
Normal file
@ -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
|
||||||
|
*/
|
46
sys/cddl/contrib/opensolaris/uts/riscv/sys/fasttrap_isa.h
Normal file
46
sys/cddl/contrib/opensolaris/uts/riscv/sys/fasttrap_isa.h
Normal file
@ -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 <sys/types.h>
|
||||||
|
|
||||||
|
#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 */
|
176
sys/cddl/dev/dtrace/riscv/dtrace_asm.S
Normal file
176
sys/cddl/dev/dtrace/riscv/dtrace_asm.S
Normal file
@ -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 <br@bsdpad.com>
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _ASM
|
||||||
|
#define _LOCORE
|
||||||
|
|
||||||
|
#include <sys/cpuvar_defs.h>
|
||||||
|
#include <sys/dtrace.h>
|
||||||
|
|
||||||
|
#include <machine/riscvreg.h>
|
||||||
|
#include <machine/asm.h>
|
||||||
|
|
||||||
|
#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)
|
394
sys/cddl/dev/dtrace/riscv/dtrace_isa.c
Normal file
394
sys/cddl/dev/dtrace/riscv/dtrace_isa.c
Normal file
@ -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 <br@bsdpad.com>
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/stack.h>
|
||||||
|
#include <sys/pcpu.h>
|
||||||
|
|
||||||
|
#include <machine/frame.h>
|
||||||
|
#include <machine/md_var.h>
|
||||||
|
#include <machine/reg.h>
|
||||||
|
|
||||||
|
#include <vm/vm.h>
|
||||||
|
#include <vm/vm_param.h>
|
||||||
|
#include <vm/pmap.h>
|
||||||
|
|
||||||
|
#include <machine/atomic.h>
|
||||||
|
#include <machine/db_machdep.h>
|
||||||
|
#include <machine/md_var.h>
|
||||||
|
#include <machine/stack.h>
|
||||||
|
#include <ddb/db_sym.h>
|
||||||
|
#include <ddb/ddb.h>
|
||||||
|
#include <sys/kdb.h>
|
||||||
|
|
||||||
|
#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));
|
||||||
|
}
|
282
sys/cddl/dev/dtrace/riscv/dtrace_subr.c
Normal file
282
sys/cddl/dev/dtrace/riscv/dtrace_subr.c
Normal file
@ -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 <br@bsdpad.com>
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/systm.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/kernel.h>
|
||||||
|
#include <sys/malloc.h>
|
||||||
|
#include <sys/kmem.h>
|
||||||
|
#include <sys/smp.h>
|
||||||
|
#include <sys/dtrace_impl.h>
|
||||||
|
#include <sys/dtrace_bsd.h>
|
||||||
|
#include <machine/vmparam.h>
|
||||||
|
#include <machine/riscvreg.h>
|
||||||
|
#include <machine/riscv_opcode.h>
|
||||||
|
#include <machine/clock.h>
|
||||||
|
#include <machine/frame.h>
|
||||||
|
#include <machine/trap.h>
|
||||||
|
#include <vm/pmap.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
51
sys/cddl/dev/dtrace/riscv/regset.h
Normal file
51
sys/cddl/dev/dtrace/riscv/regset.h
Normal file
@ -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 */
|
165
sys/cddl/dev/fbt/riscv/fbt_isa.c
Normal file
165
sys/cddl/dev/fbt/riscv/fbt_isa.c
Normal file
@ -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 <br@bsdpad.com>
|
||||||
|
*
|
||||||
|
* $FreeBSD$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include <sys/dtrace.h>
|
||||||
|
|
||||||
|
#include <machine/riscvreg.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
30
sys/cddl/dev/fbt/riscv/fbt_isa.h
Normal file
30
sys/cddl/dev/fbt/riscv/fbt_isa.h
Normal file
@ -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
|
@ -143,6 +143,11 @@ struct profile_probe_percpu;
|
|||||||
#define PROF_ARTIFICIAL_FRAMES 10
|
#define PROF_ARTIFICIAL_FRAMES 10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __riscv__
|
||||||
|
/* TODO: verify */
|
||||||
|
#define PROF_ARTIFICIAL_FRAMES 10
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct profile_probe {
|
typedef struct profile_probe {
|
||||||
char prof_name[PROF_NAMELEN];
|
char prof_name[PROF_NAMELEN];
|
||||||
dtrace_id_t prof_id;
|
dtrace_id_t prof_id;
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
# $FreeBSD$
|
# $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/blowfish/bf_enc.c optional crypto | ipsec
|
||||||
crypto/des/des_enc.c optional crypto | ipsec | netsmb
|
crypto/des/des_enc.c optional crypto | ipsec | netsmb
|
||||||
dev/ofw/ofw_cpu.c optional fdt
|
dev/ofw/ofw_cpu.c optional fdt
|
||||||
|
@ -59,6 +59,11 @@ struct trapframe {
|
|||||||
uint64_t tf_scause;
|
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.
|
* Signal frame. Pushed onto user stack before calling sigcode.
|
||||||
*/
|
*/
|
||||||
|
@ -124,6 +124,11 @@
|
|||||||
#define XLEN 8
|
#define XLEN 8
|
||||||
#define INSN_SIZE 4
|
#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) \
|
#define CSR_ZIMM(val) \
|
||||||
(__builtin_constant_p(val) && ((u_long)(val) < 32))
|
(__builtin_constant_p(val) && ((u_long)(val) < 32))
|
||||||
|
|
||||||
|
@ -64,6 +64,12 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <machine/resource.h>
|
#include <machine/resource.h>
|
||||||
#include <machine/intr.h>
|
#include <machine/intr.h>
|
||||||
|
|
||||||
|
#ifdef KDTRACE_HOOKS
|
||||||
|
#include <sys/dtrace_bsd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int (*dtrace_invop_jump_addr)(struct trapframe *);
|
||||||
|
|
||||||
extern register_t fsu_intr_fault;
|
extern register_t fsu_intr_fault;
|
||||||
|
|
||||||
/* Called from exception.S */
|
/* Called from exception.S */
|
||||||
@ -271,6 +277,11 @@ do_trap_supervisor(struct trapframe *frame)
|
|||||||
return;
|
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",
|
CTR3(KTR_TRAP, "do_trap_supervisor: curthread: %p, sepc: %lx, frame: %p",
|
||||||
curthread, frame->tf_sepc, frame);
|
curthread, frame->tf_sepc, frame);
|
||||||
|
|
||||||
@ -281,6 +292,12 @@ do_trap_supervisor(struct trapframe *frame)
|
|||||||
data_abort(frame, 0);
|
data_abort(frame, 0);
|
||||||
break;
|
break;
|
||||||
case EXCP_INSTR_BREAKPOINT:
|
case EXCP_INSTR_BREAKPOINT:
|
||||||
|
#ifdef KDTRACE_HOOKS
|
||||||
|
if (dtrace_invop_jump_addr != 0) {
|
||||||
|
dtrace_invop_jump_addr(frame);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef KDB
|
#ifdef KDB
|
||||||
kdb_trap(exception, 0, frame);
|
kdb_trap(exception, 0, frame);
|
||||||
#else
|
#else
|
||||||
@ -290,7 +307,7 @@ do_trap_supervisor(struct trapframe *frame)
|
|||||||
break;
|
break;
|
||||||
case EXCP_INSTR_ILLEGAL:
|
case EXCP_INSTR_ILLEGAL:
|
||||||
dump_regs(frame);
|
dump_regs(frame);
|
||||||
panic("Illegal instruction at %x\n", frame->tf_sepc);
|
panic("Illegal instruction at 0x%016lx\n", frame->tf_sepc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dump_regs(frame);
|
dump_regs(frame);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user