kinst: Add per-CPU interrupt trampolines
authorMark Johnston <markj@FreeBSD.org>
Thu, 8 Dec 2022 20:03:51 +0000 (15:03 -0500)
committerMark Johnston <markj@FreeBSD.org>
Thu, 8 Dec 2022 20:03:51 +0000 (15:03 -0500)
commit84d7fe4a6f647faa2c91cb254b155e88e68c798c
tree0a95b350ad7e6b7280a769f0665e94fe77183f87
parent778b74378f42e08ea2a021c87292e2df1f1c7b1e
kinst: Add per-CPU interrupt trampolines

In the common case, kinst emulates a traced instruction by copying it to
a trampoline, where it is followed by a jump back to the original code,
and pointing the interrupted thread's %rip at the trampoline.  In
particular, the trampoline is executed with the same CPU context as the
original instruction, so if interrupts are enabled at the point where
the probe fires, they will be enabled when the trampoline is
subsequently executed.

It can happen that an interrupt is raised while a thread is executing a
kinst trampoline.  In that case, it is possible that the interrupt
handler will trigger a kinst probe, so we must ensure that the thread
does not recurse and overwrite its trampoline before it is finished
executing the original contents, otherwise an attempt to trace code
called from interrupt handlers can crash the kernel.

To that end, add a per-CPU trampoline, used when the probe fired with
interrupts disabled.  Note that this is not quite complete since it does
not handle the possibility of kinst probes firing while executing an NMI
handler.

Also ensure that we do not trace instructions which set IF, since in
that case it is not clear which trampoline (the per-thread trampoline or
the per-CPU trampoline) we should use, and since such instructions are
rare.

Reported and tested by: Domagoj Stolfa
Reviewed by: christos
Fixes: f0bc4ed144fc ("kinst: Initial revision")
Differential Revision: https://reviews.freebsd.org/D37619
sys/cddl/dev/kinst/amd64/kinst_isa.c
sys/cddl/dev/kinst/kinst.c
sys/cddl/dev/kinst/kinst.h