From 95874ffdec65823430464b7869d8f0acf75cc226 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Sat, 29 Oct 2011 21:13:43 +0800 Subject: [PATCH] x86_64/ioapic: Allow GSI's target CPU to be configured - Tuneable hw.ioapic.gsi.X.cpu is added, which could be used to specify the GSI X's target CPU id - If hw.ioapic.gsi.X is not set, then GSI X will be target to CPU Y, Y = X % ncpus --- sys/dev/acpica5/acpi_sci_var.h | 1 + sys/platform/pc64/acpica5/acpi_fadt.c | 6 ++ sys/platform/pc64/apic/ioapic.c | 17 +++--- sys/platform/pc64/apic/ioapic.h | 2 +- sys/platform/pc64/apic/ioapic_abi.c | 79 ++++++++++++++++++++++++--- 5 files changed, 87 insertions(+), 18 deletions(-) diff --git a/sys/dev/acpica5/acpi_sci_var.h b/sys/dev/acpica5/acpi_sci_var.h index 71982a8a84..7d413144c1 100644 --- a/sys/dev/acpica5/acpi_sci_var.h +++ b/sys/dev/acpica5/acpi_sci_var.h @@ -4,5 +4,6 @@ void acpi_sci_config(void); int acpi_sci_enabled(void); int acpi_sci_pci_shariable(void); +int acpi_sci_irqno(void); #endif /* !_ACPI_SCI_VAR_H_ */ diff --git a/sys/platform/pc64/acpica5/acpi_fadt.c b/sys/platform/pc64/acpica5/acpi_fadt.c index d49013e333..6822bea149 100644 --- a/sys/platform/pc64/acpica5/acpi_fadt.c +++ b/sys/platform/pc64/acpica5/acpi_fadt.c @@ -252,3 +252,9 @@ acpi_sci_pci_shariable(void) else return 0; } + +int +acpi_sci_irqno(void) +{ + return acpi_sci_irq; +} diff --git a/sys/platform/pc64/apic/ioapic.c b/sys/platform/pc64/apic/ioapic.c index e198b0a207..c3325d7e85 100644 --- a/sys/platform/pc64/apic/ioapic.c +++ b/sys/platform/pc64/apic/ioapic.c @@ -73,7 +73,7 @@ static void ioapic_gsi_setup(int); static const struct ioapic_info * ioapic_gsi_search(int); static void ioapic_pin_prog(void *, int, int, - enum intr_trigger, enum intr_polarity, uint32_t); + enum intr_trigger, enum intr_polarity, uint32_t, int); static struct ioapic_conf ioapic_conf; @@ -376,7 +376,7 @@ ioapic_gsi_setup(int gsi) */ ioapic_pin_setup(ioapic_gsi_ioaddr(gsi), ioapic_gsi_pin(gsi), 0, - INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); + INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH, 0); return; } trig = INTR_TRIGGER_EDGE; @@ -441,7 +441,7 @@ void ioapic_extpin_setup(void *addr, int pin, int vec) { ioapic_pin_prog(addr, pin, vec, - INTR_TRIGGER_CONFORM, INTR_POLARITY_CONFORM, IOART_DELEXINT); + INTR_TRIGGER_CONFORM, INTR_POLARITY_CONFORM, IOART_DELEXINT, 0); } int @@ -452,7 +452,7 @@ ioapic_extpin_gsi(void) void ioapic_pin_setup(void *addr, int pin, int vec, - enum intr_trigger trig, enum intr_polarity pola) + enum intr_trigger trig, enum intr_polarity pola, int cpuid) { /* * Always clear an I/O APIC pin before [re]programming it. This is @@ -467,13 +467,14 @@ ioapic_pin_setup(void *addr, int pin, int vec, * interrupt. */ ioapic_pin_prog(addr, pin, vec, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH, - IOART_DELFIXED); - ioapic_pin_prog(addr, pin, vec, trig, pola, IOART_DELFIXED); + IOART_DELFIXED, cpuid); + ioapic_pin_prog(addr, pin, vec, trig, pola, IOART_DELFIXED, cpuid); } static void ioapic_pin_prog(void *addr, int pin, int vec, - enum intr_trigger trig, enum intr_polarity pola, uint32_t del_mode) + enum intr_trigger trig, enum intr_polarity pola, + uint32_t del_mode, int cpuid) { uint32_t flags, target; int select; @@ -529,7 +530,7 @@ ioapic_pin_prog(void *addr, int pin, int vec, } target = ioapic_read(addr, select + 1) & IOART_HI_DEST_RESV; - target |= (CPUID_TO_APICID(0) << IOART_HI_DEST_SHIFT) & + target |= (CPUID_TO_APICID(cpuid) << IOART_HI_DEST_SHIFT) & IOART_HI_DEST_MASK; ioapic_write(addr, select, flags | vec); diff --git a/sys/platform/pc64/apic/ioapic.h b/sys/platform/pc64/apic/ioapic.h index 25a1d1cc6c..b439c263e2 100644 --- a/sys/platform/pc64/apic/ioapic.h +++ b/sys/platform/pc64/apic/ioapic.h @@ -57,7 +57,7 @@ void ioapic_intsrc(int, int, enum intr_trigger, enum intr_polarity); void *ioapic_gsi_ioaddr(int); int ioapic_gsi_pin(int); void ioapic_pin_setup(void *, int, int, - enum intr_trigger, enum intr_polarity); + enum intr_trigger, enum intr_polarity, int); void ioapic_extpin_setup(void *, int, int); int ioapic_extpin_gsi(void); int ioapic_gsi(int, int); diff --git a/sys/platform/pc64/apic/ioapic_abi.c b/sys/platform/pc64/apic/ioapic_abi.c index 2798911f29..282fa7e5e2 100644 --- a/sys/platform/pc64/apic/ioapic_abi.c +++ b/sys/platform/pc64/apic/ioapic_abi.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -53,8 +54,6 @@ #include #include -#include - #include #include #include @@ -63,6 +62,8 @@ #include #include +#include + #define IOAPIC_HWI_VECTORS IDT_HWI_VECTORS extern inthand_t @@ -490,6 +491,8 @@ static void ioapic_abi_setdefault(void); static void ioapic_abi_stabilize(void); static void ioapic_abi_initmap(void); +static int ioapic_abi_gsi_cpuid(int, int); + struct machintr_abi MachIntrABI_IOAPIC = { MACHINTR_IOAPIC, .intr_disable = ioapic_abi_intr_disable, @@ -680,7 +683,7 @@ ioapic_abi_set_irqmap(int irq, int gsi, enum intr_trigger trig, struct ioapic_irqinfo *info; struct ioapic_irqmap *map; void *ioaddr; - int pin; + int pin, cpuid; KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); @@ -705,6 +708,8 @@ ioapic_abi_set_irqmap(int irq, int gsi, enum intr_trigger trig, pin = ioapic_gsi_pin(map->im_gsi); ioaddr = ioapic_gsi_ioaddr(map->im_gsi); + cpuid = ioapic_abi_gsi_cpuid(irq, map->im_gsi); + info = &ioapic_irqs[irq]; imen_lock(); @@ -716,7 +721,7 @@ ioapic_abi_set_irqmap(int irq, int gsi, enum intr_trigger trig, info->io_flags |= IOAPIC_IRQI_FLAG_LEVEL; ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq, - map->im_trig, map->im_pola); + map->im_trig, map->im_pola, cpuid); imen_unlock(); } @@ -790,7 +795,7 @@ ioapic_abi_intr_config(int irq, enum intr_trigger trig, enum intr_polarity pola) struct ioapic_irqinfo *info; struct ioapic_irqmap *map; void *ioaddr; - int pin; + int pin, cpuid; KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); @@ -834,6 +839,8 @@ ioapic_abi_intr_config(int irq, enum intr_trigger trig, enum intr_polarity pola) pin = ioapic_gsi_pin(map->im_gsi); ioaddr = ioapic_gsi_ioaddr(map->im_gsi); + cpuid = ioapic_abi_gsi_cpuid(irq, map->im_gsi); + info = &ioapic_irqs[irq]; imen_lock(); @@ -843,7 +850,7 @@ ioapic_abi_intr_config(int irq, enum intr_trigger trig, enum intr_polarity pola) info->io_flags |= IOAPIC_IRQI_FLAG_LEVEL; ioapic_pin_setup(ioaddr, pin, IDT_OFFSET + irq, - map->im_trig, map->im_pola); + map->im_trig, map->im_pola, cpuid); imen_unlock(); } @@ -856,6 +863,9 @@ ioapic_abi_extint_irqmap(int irq) void *ioaddr; int pin, error, vec; + /* XXX only irq0 is allowed */ + KKASSERT(irq == 0); + vec = IDT_OFFSET + irq; if (ioapic_abi_extint_irq == irq) @@ -911,8 +921,59 @@ ioapic_abi_extint_irqmap(int irq) } static int -ioapic_abi_intr_cpuid(int irq __unused) +ioapic_abi_intr_cpuid(int irq) { - /* TODO */ - return 0; + const struct ioapic_irqmap *map; + + KKASSERT(irq >= 0 && irq < IOAPIC_HWI_VECTORS); + map = &ioapic_irqmaps[irq]; + + if (map->im_type == IOAPIC_IMT_RESERVED) { + /* XXX some drivers tries to peek at IRQ 2 */ + return 0; + } + + KASSERT(map->im_type == IOAPIC_IMT_LINE, + ("invalid irq %d, type %d\n", irq, map->im_type)); + KKASSERT(map->im_gsi >= 0); + + return ioapic_abi_gsi_cpuid(irq, map->im_gsi); +} + +static int +ioapic_abi_gsi_cpuid(int irq, int gsi) +{ + char envpath[32]; + int cpuid = -1; + + KKASSERT(gsi >= 0); + + if (irq == 0 || gsi == 0) { + if (bootverbose) + kprintf("GSI %d -> CPU 0 (0)\n", gsi); + return 0; + } + + if (irq == acpi_sci_irqno()) { + if (bootverbose) + kprintf("GSI %d -> CPU 0 (sci)\n", gsi); + return 0; + } + + ksnprintf(envpath, sizeof(envpath), "hw.ioapic.gsi.%d.cpu", gsi); + kgetenv_int(envpath, &cpuid); + + if (cpuid < 0) { + cpuid = gsi % ncpus; + if (bootverbose) + kprintf("GSI %d -> CPU %d (auto)\n", gsi, cpuid); + } else if (cpuid >= ncpus) { + cpuid = ncpus - 1; + if (bootverbose) + kprintf("GSI %d -> CPU %d (fixup)\n", gsi, cpuid); + } else { + if (bootverbose) + kprintf("GSI %d -> CPU %d (user)\n", gsi, cpuid); + } + return cpuid; } -- 2.41.0