Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144413118
D40963.id124639.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D40963.id124639.diff
View Options
diff --git a/sys/cddl/dev/kinst/riscv/kinst_isa.c b/sys/cddl/dev/kinst/riscv/kinst_isa.c
--- a/sys/cddl/dev/kinst/riscv/kinst_isa.c
+++ b/sys/cddl/dev/kinst/riscv/kinst_isa.c
@@ -14,20 +14,7 @@
#include "kinst.h"
-/*
- * Per-CPU trampolines used when the interrupted thread is executing with
- * interrupts disabled. If an interrupt is raised while executing a trampoline,
- * the interrupt thread cannot safely overwrite its trampoline if it hits a
- * kinst probe while executing the interrupt handler.
- */
-DPCPU_DEFINE_STATIC(uint8_t *, intr_tramp);
-
-/*
- * The double-breakpoint mechanism needs to save the current probe for the next
- * call to kinst_invop(). As with per-CPU trampolines, this also has to be done
- * per-CPU when interrupts are disabled.
- */
-DPCPU_DEFINE_STATIC(struct kinst_probe *, intr_probe);
+DPCPU_DEFINE_STATIC(struct kinst_cpu_state *, kinst_state);
#define _MATCH_REG(reg) \
(offsetof(struct trapframe, tf_ ## reg) / sizeof(register_t))
@@ -253,14 +240,14 @@
}
static void
-kinst_trampoline_populate(struct kinst_probe *kp, uint8_t *tramp)
+kinst_trampoline_populate(struct kinst_probe *kp)
{
static uint16_t nop = MATCH_C_NOP;
static uint32_t ebreak = MATCH_EBREAK;
int ilen;
ilen = kp->kp_md.instlen;
- kinst_memcpy(tramp, &kp->kp_savedval, ilen);
+ kinst_memcpy(kp->kp_tramp, &kp->kp_savedval, ilen);
/*
* Since we cannot encode large displacements in a single instruction
@@ -273,9 +260,9 @@
* Add a NOP after a compressed instruction for padding.
*/
if (ilen == INSN_C_SIZE)
- kinst_memcpy(&tramp[ilen], &nop, INSN_C_SIZE);
+ kinst_memcpy(&kp->kp_tramp[ilen], &nop, INSN_C_SIZE);
- kinst_memcpy(&tramp[INSN_SIZE], &ebreak, INSN_SIZE);
+ kinst_memcpy(&kp->kp_tramp[INSN_SIZE], &ebreak, INSN_SIZE);
fence_i();
}
@@ -306,27 +293,26 @@
kinst_invop(uintptr_t addr, struct trapframe *frame, uintptr_t scratch)
{
solaris_cpu_t *cpu;
+ struct kinst_cpu_state *ks;
struct kinst_probe *kp;
- uint8_t *tramp;
- /*
- * Use per-CPU trampolines and probes if the thread executing the
- * instruction was executing with interrupts disabled.
- */
- if ((frame->tf_sstatus & SSTATUS_SPIE) == 0) {
- tramp = DPCPU_GET(intr_tramp);
- kp = DPCPU_GET(intr_probe);
- } else {
- tramp = curthread->t_kinst_tramp;
- kp = curthread->t_kinst_curprobe;
- }
+ ks = DPCPU_GET(kinst_state);
/*
* Detect if the breakpoint was triggered by the trampoline, and
* manually set the PC to the next instruction.
*/
- if (addr == (uintptr_t)(tramp + INSN_SIZE))
- return (kinst_jump_next_instr(frame, kp));
+ if (ks->state == KINST_PROBE_FIRED &&
+ addr == (uintptr_t)(ks->kp->kp_tramp + INSN_SIZE)) {
+ /*
+ * Restore interrupts if they were enabled prior to the first
+ * breakpoint.
+ */
+ if ((ks->status & SSTATUS_SPIE) != 0)
+ frame->tf_sstatus |= SSTATUS_SPIE;
+ ks->state = KINST_PROBE_ARMED;
+ return (kinst_jump_next_instr(frame, ks->kp));
+ }
LIST_FOREACH(kp, KINST_GETPROBE(addr), kp_hashnext) {
if ((uintptr_t)kp->kp_patchpoint == addr)
@@ -340,10 +326,14 @@
dtrace_probe(kp->kp_id, 0, 0, 0, 0, 0);
cpu->cpu_dtrace_caller = 0;
- if (kp->kp_md.emulate)
+ ks->state = KINST_PROBE_FIRED;
+
+ if (kp->kp_md.emulate) {
+ ks->state = KINST_PROBE_ARMED;
return (kinst_emulate(frame, kp));
+ }
- if (tramp == NULL) {
+ if (kp->kp_tramp == NULL) {
/*
* A trampoline allocation failed, so this probe is
* effectively disabled. Restore the original
@@ -356,12 +346,16 @@
kinst_patch_tracepoint(kp, kp->kp_savedval);
frame->tf_sepc = (register_t)kp->kp_patchpoint;
} else {
- kinst_trampoline_populate(kp, tramp);
- frame->tf_sepc = (register_t)tramp;
- if ((frame->tf_sstatus & SSTATUS_SPIE) == 0)
- DPCPU_SET(intr_probe, kp);
- else
- curthread->t_kinst_curprobe = kp;
+ kinst_trampoline_populate(kp);
+ frame->tf_sepc = (register_t)kp->kp_tramp;
+
+ /*
+ * Cache the current SSTATUS and clear interrupts for the
+ * duration of the double breakpoint.
+ */
+ ks->status = frame->tf_sstatus;
+ ks->kp = kp;
+ frame->tf_sstatus &= ~SSTATUS_SPIE;
}
return (MATCH_C_NOP);
@@ -556,6 +550,7 @@
kp->kp_patchval = KINST_PATCHVAL;
else
kp->kp_patchval = KINST_C_PATCHVAL;
+ kp->kp_tramp = kinst_trampoline_alloc(M_WAITOK);
kinst_instr_dissect(kp, instrsize);
kinst_probe_create(kp, lf);
@@ -571,14 +566,15 @@
int
kinst_md_init(void)
{
- uint8_t *tramp;
+ struct kinst_cpu_state *ks;
int cpu;
CPU_FOREACH(cpu) {
- tramp = kinst_trampoline_alloc(M_WAITOK);
- if (tramp == NULL)
+ ks = malloc(sizeof(*ks), M_KINST, M_WAITOK | M_ZERO);
+ if (ks == NULL)
return (ENOMEM);
- DPCPU_ID_SET(cpu, intr_tramp, tramp);
+ ks->state = KINST_PROBE_ARMED;
+ DPCPU_ID_SET(cpu, kinst_state, ks);
}
return (0);
@@ -587,14 +583,14 @@
void
kinst_md_deinit(void)
{
- uint8_t *tramp;
+ struct kinst_cpu_state *ks;
int cpu;
CPU_FOREACH(cpu) {
- tramp = DPCPU_ID_GET(cpu, intr_tramp);
- if (tramp != NULL) {
- kinst_trampoline_dealloc(tramp);
- DPCPU_ID_SET(cpu, intr_tramp, NULL);
+ ks = DPCPU_ID_GET(cpu, kinst_state);
+ if (ks != NULL) {
+ free(ks, M_KINST);
+ DPCPU_ID_SET(cpu, kinst_state, NULL);
}
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 7:41 AM (9 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28554696
Default Alt Text
D40963.id124639.diff (5 KB)
Attached To
Mode
D40963: kinst: use per-probe trampolines in riscv
Attached
Detach File
Event Timeline
Log In to Comment