Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150436519
D1943.id3912.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
D1943.id3912.diff
View Options
Index: sys/x86/include/apicvar.h
===================================================================
--- sys/x86/include/apicvar.h
+++ sys/x86/include/apicvar.h
@@ -426,6 +426,7 @@
void xen_intr_handle_upcall(struct trapframe *frame);
extern int x2apic_mode;
+extern int lapic_eoi_suppression;
#ifdef _SYS_SYSCTL_H_
SYSCTL_DECL(_hw_apic);
Index: sys/x86/x86/io_apic.c
===================================================================
--- sys/x86/x86/io_apic.c
+++ sys/x86/x86/io_apic.c
@@ -97,6 +97,7 @@
u_int io_apic_id:4;
u_int io_intbase:8; /* System Interrupt base */
u_int io_numintr:8;
+ u_int io_haseoi:1;
volatile ioapic_t *io_addr; /* XXX: should use bus_space */
vm_paddr_t io_paddr;
STAILQ_ENTRY(ioapic) io_next;
@@ -134,10 +135,53 @@
SYSCTL_INT(_hw_apic, OID_AUTO, enable_extint, CTLFLAG_RDTUN, &enable_extint, 0,
"Enable the ExtINT pin in the first I/O APIC");
-static __inline void
-_ioapic_eoi_source(struct intsrc *isrc)
+static void
+_ioapic_eoi_source(struct intsrc *isrc, int locked)
{
+ struct ioapic_intsrc *src;
+ struct ioapic *io;
+ volatile uint32_t *apic_eoi;
+ uint32_t low1;
+
lapic_eoi();
+ if (!lapic_eoi_suppression)
+ return;
+ src = (struct ioapic_intsrc *)isrc;
+ if (src->io_edgetrigger)
+ return;
+ io = (struct ioapic *)isrc->is_pic;
+
+ /*
+ * Handle targeted EOI for level-triggered pins, if broadcast
+ * EOI suppression is supported by LAPICs.
+ */
+ if (io->io_haseoi) {
+ /*
+ * If IOAPIC has EOI Register, simply write vector
+ * number into the reg.
+ */
+ apic_eoi = (volatile uint32_t *)((volatile char *)
+ io->io_addr + IOAPIC_EOIR);
+ *apic_eoi = src->io_vector;
+ } else {
+ /*
+ * Otherwise, if IO-APIC is too old to provide EOIR,
+ * do what Intel did for the Linux kernel. Temporary
+ * switch the pin to edge-trigger and back, masking
+ * the pin during the trick.
+ */
+ if (!locked)
+ mtx_lock_spin(&icu_lock);
+ low1 = src->io_lowreg;
+ low1 &= ~IOART_TRGRLVL;
+ low1 |= IOART_TRGREDG | IOART_INTMSET;
+ ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(src->io_intpin),
+ low1);
+ ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(src->io_intpin),
+ src->io_lowreg);
+ if (!locked)
+ mtx_unlock_spin(&icu_lock);
+ }
}
static u_int
@@ -230,7 +274,7 @@
}
if (eoi == PIC_EOI)
- _ioapic_eoi_source(isrc);
+ _ioapic_eoi_source(isrc, 1);
mtx_unlock_spin(&icu_lock);
}
@@ -239,7 +283,7 @@
ioapic_eoi_source(struct intsrc *isrc)
{
- _ioapic_eoi_source(isrc);
+ _ioapic_eoi_source(isrc, 0);
}
/*
@@ -545,6 +589,23 @@
io->io_addr = apic;
io->io_paddr = addr;
+ if (bootverbose) {
+ printf("ioapic%u: ver 0x%02x maxredir 0x%02x\n", io->io_id,
+ (value & IOART_VER_VERSION), (value & IOART_VER_MAXREDIR)
+ >> MAXREDIRSHIFT);
+ }
+ /*
+ * The summary information about IO-APIC versions is taken from
+ * the Linux kernel source:
+ * 0Xh 82489DX
+ * 1Xh I/OAPIC or I/O(x)APIC which are not PCI 2.2 Compliant
+ * 2Xh I/O(x)APIC which is PCI 2.2 Compliant
+ * 30h-FFh Reserved
+ * IO-APICs with version >= 0x20 have working EOIR register.
+ */
+ if ((value & IOART_VER_VERSION) >= 0x20)
+ io->io_haseoi = 1;
+
/*
* Initialize pins. Start off with interrupts disabled. Default
* to active-hi and edge-triggered for ISA interrupts and active-lo
Index: sys/x86/x86/local_apic.c
===================================================================
--- sys/x86/x86/local_apic.c
+++ sys/x86/x86/local_apic.c
@@ -159,11 +159,14 @@
volatile char *lapic_map;
vm_paddr_t lapic_paddr;
int x2apic_mode;
+int lapic_eoi_suppression;
static u_long lapic_timer_divisor;
static struct eventtimer lapic_et;
SYSCTL_NODE(_hw, OID_AUTO, apic, CTLFLAG_RD, 0, "APIC options");
SYSCTL_INT(_hw_apic, OID_AUTO, x2apic_mode, CTLFLAG_RD, &x2apic_mode, 0, "");
+SYSCTL_INT(_hw_apic, OID_AUTO, eoi_suppression, CTLFLAG_RD,
+ &lapic_eoi_suppression, 0, "");
static uint32_t
lapic_read32(enum LAPIC_REGISTERS reg)
@@ -380,6 +383,7 @@
static void
native_lapic_init(vm_paddr_t addr)
{
+ uint32_t ver;
u_int regs[4];
int i, arat;
@@ -443,6 +447,20 @@
lapic_et.et_priv = NULL;
et_register(&lapic_et);
}
+
+ /*
+ * Set lapic_eoi_suppression after lapic_enable(), to not
+ * enable suppression in the hardware prematurely. Note that
+ * we by default enable suppression even when system only has
+ * one IO-APIC, since EOI is broadcasted to all APIC agents,
+ * including CPUs, otherwise.
+ */
+ ver = lapic_read32(LAPIC_VERSION);
+ if ((ver & APIC_VER_EOI_SUPPRESSION) != 0) {
+ lapic_eoi_suppression = 1;
+ TUNABLE_INT_FETCH("hw.lapic_eoi_suppression",
+ &lapic_eoi_suppression);
+ }
}
/*
@@ -755,6 +773,8 @@
value = lapic_read32(LAPIC_SVR);
value &= ~(APIC_SVR_VECTOR | APIC_SVR_FOCUS);
value |= APIC_SVR_FEN | APIC_SVR_SWEN | APIC_SPURIOUS_INT;
+ if (lapic_eoi_suppression)
+ value |= APIC_SVR_EOI_SUPPRESSION;
lapic_write32(LAPIC_SVR, value);
}
@@ -1562,8 +1582,10 @@
return;
#endif
/*
- * Finish setting up the local APIC on the BSP once we know how to
- * properly program the LINT pins.
+ * Finish setting up the local APIC on the BSP once we know
+ * how to properly program the LINT pins. In particular, this
+ * enables the EOI suppression mode, if LAPIC support it and
+ * user did not disabled the mode.
*/
lapic_setup(1);
if (bootverbose)
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Apr 2, 5:24 AM (6 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30707365
Default Alt Text
D1943.id3912.diff (5 KB)
Attached To
Mode
D1943: Implement EOI suppression mode.
Attached
Detach File
Event Timeline
Log In to Comment