aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-05-31 22:51:14 +0000
committerMark Johnston <markj@FreeBSD.org>2021-06-07 01:00:32 +0000
commitcbced258dee43b4f65e62572aa2fcd67225eca20 (patch)
tree01e0dffc5af33611df273305f2a5e681b426704b
parent4616a539172f03a325dc5fdbc6e4d7610297ae9e (diff)
x86: Fix lapic_ipi_alloc() on i386
The loop which checks to see if "dynamic" IDT entries are allocated needs to compare with the trampoline address of the reserved ISR. Otherwise it will never succeed. Reported by: Harry Schmalzbauer <freebsd@omnilan.de> Tested by: Harry Schmalzbauer <freebsd@omnilan.de> Reviewed by: kib Sponsored by: The FreeBSD Foundation (cherry picked from commit 18f55c67f746f0ad12fe972328234d340a621df9)
-rw-r--r--sys/x86/x86/local_apic.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index 2a1c3ad56148..a34cfbb8b1c9 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -2113,6 +2113,10 @@ native_lapic_ipi_vectored(u_int vector, int dest)
#endif /* SMP */
+#ifdef __i386__
+extern uintptr_t setidt_disp;
+#endif
+
/*
* Since the IDT is shared by all CPUs the IPI slot update needs to be globally
* visible.
@@ -2141,6 +2145,9 @@ native_lapic_ipi_alloc(inthand_t *ipifunc)
for (idx = IPI_DYN_FIRST; idx <= IPI_DYN_LAST; idx++) {
ip = &idt[idx];
func = (ip->gd_hioffset << 16) | ip->gd_looffset;
+#ifdef __i386__
+ func -= setidt_disp;
+#endif
if ((!pti && func == (uintptr_t)&IDTVEC(rsvd)) ||
(pti && func == (uintptr_t)&IDTVEC(rsvd_pti))) {
vector = idx;
@@ -2164,6 +2171,9 @@ native_lapic_ipi_free(int vector)
mtx_lock_spin(&icu_lock);
ip = &idt[vector];
func = (ip->gd_hioffset << 16) | ip->gd_looffset;
+#ifdef __i386__
+ func -= setidt_disp;
+#endif
KASSERT(func != (uintptr_t)&IDTVEC(rsvd) &&
func != (uintptr_t)&IDTVEC(rsvd_pti),
("invalid idtfunc %#lx", func));