aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Horne <mhorne@FreeBSD.org>2023-02-06 18:08:35 +0000
committerMitchell Horne <mhorne@FreeBSD.org>2023-02-06 19:26:53 +0000
commit06faad1de2c9aadcfd606d5f7121b201dbfbaa9d (patch)
tree072e5b065632cf2bf7aae55f26f13c3d926efe0f
parent0e563bde48b1af6bd472e940f04a8d76315749ab (diff)
downloadsrc-06faad1de2c9aadcfd606d5f7121b201dbfbaa9d.tar.gz
src-06faad1de2c9aadcfd606d5f7121b201dbfbaa9d.zip
dtrace: handle page faults in riscv dtrace_trap()
We must detect the correct amount to increment sepc, as it may have been a compressed instruction that triggered the fault. Reviewed by: markj MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D38299
-rw-r--r--sys/cddl/dev/dtrace/riscv/dtrace_subr.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/sys/cddl/dev/dtrace/riscv/dtrace_subr.c b/sys/cddl/dev/dtrace/riscv/dtrace_subr.c
index 1e24a88f6c75..f32bb3a2343e 100644
--- a/sys/cddl/dev/dtrace/riscv/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/riscv/dtrace_subr.c
@@ -63,6 +63,8 @@ typedef struct dtrace_invop_hdlr {
dtrace_invop_hdlr_t *dtrace_invop_hdlr;
+static int match_opcode(uint32_t insn, int match, int mask);
+
int
dtrace_invop(uintptr_t addr, struct trapframe *frame)
{
@@ -188,6 +190,8 @@ dtrace_gethrestime(void)
int
dtrace_trap(struct trapframe *frame, u_int type)
{
+ uint16_t insn;
+
/*
* A trap can occur while DTrace executes a probe. Before
* executing the probe, DTrace blocks re-scheduling and sets
@@ -196,9 +200,7 @@ dtrace_trap(struct trapframe *frame, u_int type)
* 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.
@@ -208,15 +210,24 @@ dtrace_trap(struct trapframe *frame, u_int type)
case SCAUSE_LOAD_ACCESS_FAULT:
case SCAUSE_STORE_ACCESS_FAULT:
case SCAUSE_INST_ACCESS_FAULT:
+ case SCAUSE_INST_PAGE_FAULT:
+ case SCAUSE_LOAD_PAGE_FAULT:
+ case SCAUSE_STORE_PAGE_FAULT:
/* Flag a bad address. */
cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR;
- cpu_core[curcpu].cpuc_dtrace_illval = 0;
+ cpu_core[curcpu].cpuc_dtrace_illval = frame->tf_stval;
/*
* Offset the instruction pointer to the instruction
- * following the one causing the fault.
+ * following the one causing the fault. Check if the
+ * instruction is compressed or not. Standard
+ * instructions always have bits [1:0] == 11.
*/
- frame->tf_sepc += 4;
+ insn = *(uint16_t *)frame->tf_sepc;
+ if (match_opcode(insn, 0x3, 0x3))
+ frame->tf_sepc += INSN_SIZE;
+ else
+ frame->tf_sepc += INSN_C_SIZE;
return (1);
default: