Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151522949
D2042.id.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
D2042.id.diff
View Options
Index: head/sys/x86/include/apicvar.h
===================================================================
--- head/sys/x86/include/apicvar.h
+++ head/sys/x86/include/apicvar.h
@@ -111,11 +111,8 @@
#define IPI_INVLPG (APIC_IPI_INTS + 2)
#define IPI_INVLRNG (APIC_IPI_INTS + 3)
#define IPI_INVLCACHE (APIC_IPI_INTS + 4)
-#ifdef __i386__
-#define IPI_LAZYPMAP (APIC_IPI_INTS + 5) /* Lazy pmap release. */
-#endif
/* Vector to handle bitmap based IPIs */
-#define IPI_BITMAP_VECTOR (APIC_IPI_INTS + 6)
+#define IPI_BITMAP_VECTOR (APIC_IPI_INTS + 5)
/* IPIs handled by IPI_BITMAP_VECTOR */
#define IPI_AST 0 /* Generate software trap. */
@@ -124,8 +121,15 @@
#define IPI_BITMAP_LAST IPI_HARDCLOCK
#define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
-#define IPI_STOP (APIC_IPI_INTS + 7) /* Stop CPU until restarted. */
-#define IPI_SUSPEND (APIC_IPI_INTS + 8) /* Suspend CPU until restarted. */
+#define IPI_STOP (APIC_IPI_INTS + 6) /* Stop CPU until restarted. */
+#define IPI_SUSPEND (APIC_IPI_INTS + 7) /* Suspend CPU until restarted. */
+#ifdef __i386__
+#define IPI_LAZYPMAP (APIC_IPI_INTS + 8) /* Lazy pmap release. */
+#define IPI_DYN_FIRST (APIC_IPI_INTS + 9)
+#else
+#define IPI_DYN_FIRST (APIC_IPI_INTS + 8)
+#endif
+#define IPI_DYN_LAST (254) /* IPIs allocated at runtime */
/*
* IPI_STOP_HARD does not need to occupy a slot in the IPI vector space since
@@ -224,6 +228,8 @@
void (*ipi_raw)(register_t, u_int);
void (*ipi_vectored)(u_int, int);
int (*ipi_wait)(int);
+ int (*ipi_alloc)(inthand_t *ipifunc);
+ void (*ipi_free)(int vector);
/* LVT */
int (*set_lvt_mask)(u_int, u_int, u_char);
@@ -397,6 +403,20 @@
}
static inline int
+lapic_ipi_alloc(inthand_t *ipifunc)
+{
+
+ return (apic_ops.ipi_alloc(ipifunc));
+}
+
+static inline void
+lapic_ipi_free(int vector)
+{
+
+ return (apic_ops.ipi_free(vector));
+}
+
+static inline int
lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked)
{
Index: head/sys/x86/x86/local_apic.c
===================================================================
--- head/sys/x86/x86/local_apic.c
+++ head/sys/x86/x86/local_apic.c
@@ -303,6 +303,8 @@
enum intr_polarity pol);
static int native_lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
enum intr_trigger trigger);
+static int native_lapic_ipi_alloc(inthand_t *ipifunc);
+static void native_lapic_ipi_free(int vector);
struct apic_ops apic_ops = {
.create = native_lapic_create,
@@ -329,6 +331,8 @@
.ipi_raw = native_lapic_ipi_raw,
.ipi_vectored = native_lapic_ipi_vectored,
.ipi_wait = native_lapic_ipi_wait,
+ .ipi_alloc = native_lapic_ipi_alloc,
+ .ipi_free = native_lapic_ipi_free,
#endif
.set_lvt_mask = native_lapic_set_lvt_mask,
.set_lvt_mode = native_lapic_set_lvt_mode,
@@ -1761,4 +1765,60 @@
}
#endif /* DETECT_DEADLOCK */
}
+
+/*
+ * Since the IDT is shared by all CPUs the IPI slot update needs to be globally
+ * visible.
+ *
+ * Consider the case where an IPI is generated immediately after allocation:
+ * vector = lapic_ipi_alloc(ipifunc);
+ * ipi_selected(other_cpus, vector);
+ *
+ * In xAPIC mode a write to ICR_LO has serializing semantics because the
+ * APIC page is mapped as an uncached region. In x2APIC mode there is an
+ * explicit 'mfence' before the ICR MSR is written. Therefore in both cases
+ * the IDT slot update is globally visible before the IPI is delivered.
+ */
+static int
+native_lapic_ipi_alloc(inthand_t *ipifunc)
+{
+ struct gate_descriptor *ip;
+ long func;
+ int idx, vector;
+
+ KASSERT(ipifunc != &IDTVEC(rsvd), ("invalid ipifunc %p", ipifunc));
+
+ vector = -1;
+ mtx_lock_spin(&icu_lock);
+ for (idx = IPI_DYN_FIRST; idx <= IPI_DYN_LAST; idx++) {
+ ip = &idt[idx];
+ func = (ip->gd_hioffset << 16) | ip->gd_looffset;
+ if (func == (uintptr_t)&IDTVEC(rsvd)) {
+ vector = idx;
+ setidt(vector, ipifunc, SDT_APIC, SEL_KPL, GSEL_APIC);
+ break;
+ }
+ }
+ mtx_unlock_spin(&icu_lock);
+ return (vector);
+}
+
+static void
+native_lapic_ipi_free(int vector)
+{
+ struct gate_descriptor *ip;
+ long func;
+
+ KASSERT(vector >= IPI_DYN_FIRST && vector <= IPI_DYN_LAST,
+ ("%s: invalid vector %d", __func__, vector));
+
+ mtx_lock_spin(&icu_lock);
+ ip = &idt[vector];
+ func = (ip->gd_hioffset << 16) | ip->gd_looffset;
+ KASSERT(func != (uintptr_t)&IDTVEC(rsvd),
+ ("invalid idtfunc %#lx", func));
+ setidt(vector, &IDTVEC(rsvd), SDT_APICT, SEL_KPL, GSEL_APIC);
+ mtx_unlock_spin(&icu_lock);
+}
+
#endif /* SMP */
Index: head/sys/x86/xen/xen_apic.c
===================================================================
--- head/sys/x86/xen/xen_apic.c
+++ head/sys/x86/xen/xen_apic.c
@@ -311,7 +311,22 @@
XEN_APIC_UNSUPPORTED;
return (0);
}
-#endif
+
+static int
+xen_pv_lapic_ipi_alloc(inthand_t *ipifunc)
+{
+
+ XEN_APIC_UNSUPPORTED;
+ return (-1);
+}
+
+static void
+xen_pv_lapic_ipi_free(int vector)
+{
+
+ XEN_APIC_UNSUPPORTED;
+}
+#endif /* SMP */
static int
xen_pv_lapic_set_lvt_mask(u_int apic_id, u_int lvt, u_char masked)
@@ -372,6 +387,8 @@
.ipi_raw = xen_pv_lapic_ipi_raw,
.ipi_vectored = xen_pv_lapic_ipi_vectored,
.ipi_wait = xen_pv_lapic_ipi_wait,
+ .ipi_alloc = xen_pv_lapic_ipi_alloc,
+ .ipi_free = xen_pv_lapic_ipi_free,
#endif
.set_lvt_mask = xen_pv_lapic_set_lvt_mask,
.set_lvt_mode = xen_pv_lapic_set_lvt_mode,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 10, 12:20 AM (18 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31181418
Default Alt Text
D2042.id.diff (5 KB)
Attached To
Mode
D2042: APIs to dynamically allocate and free IPI slots.
Attached
Detach File
Event Timeline
Log In to Comment