From 86d692fe83b6d699dbf900e72cdf9f77dcaccd74 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Tue, 28 Aug 2012 12:23:26 +0800 Subject: [PATCH] MachIntr: Add two methods to find IRQ - Find IRQ conforming to the specified trigger and polarity, if it was configured. - Find IRQ by GSI, the located IRQ must conform to the specified trigger and polarity if it was configured. --- sys/platform/pc32/apic/ioapic_abi.c | 46 ++++++++++++++++++++------ sys/platform/pc32/apic/ioapic_abi.h | 3 -- sys/platform/pc32/i386/mptable.c | 4 +-- sys/platform/pc32/icu/icu_abi.c | 50 +++++++++++++++++++++++++++++ sys/platform/pc32/isa/clock.c | 4 +-- sys/platform/pc64/apic/ioapic_abi.c | 46 ++++++++++++++++++++------ sys/platform/pc64/apic/ioapic_abi.h | 3 -- sys/platform/pc64/icu/icu_abi.c | 50 +++++++++++++++++++++++++++++ sys/platform/pc64/isa/clock.c | 4 +-- sys/platform/pc64/x86_64/mptable.c | 4 +-- sys/sys/machintr.h | 9 ++++++ 11 files changed, 189 insertions(+), 34 deletions(-) diff --git a/sys/platform/pc32/apic/ioapic_abi.c b/sys/platform/pc32/apic/ioapic_abi.c index 0bdf382468..ced1388e9b 100644 --- a/sys/platform/pc32/apic/ioapic_abi.c +++ b/sys/platform/pc32/apic/ioapic_abi.c @@ -496,6 +496,10 @@ static void ioapic_abi_intr_teardown(int); static void ioapic_abi_legacy_intr_config(int, enum intr_trigger, enum intr_polarity); static int ioapic_abi_legacy_intr_cpuid(int); +static int ioapic_abi_legacy_intr_find(int, + enum intr_trigger, enum intr_polarity); +static int ioapic_abi_legacy_intr_find_bygsi(int, + enum intr_trigger, enum intr_polarity); static int ioapic_abi_msi_alloc(int [], int, int); static void ioapic_abi_msi_release(const int [], int, int); @@ -527,6 +531,8 @@ struct machintr_abi MachIntrABI_IOAPIC = { .legacy_intr_config = ioapic_abi_legacy_intr_config, .legacy_intr_cpuid = ioapic_abi_legacy_intr_cpuid, + .legacy_intr_find = ioapic_abi_legacy_intr_find, + .legacy_intr_find_bygsi = ioapic_abi_legacy_intr_find_bygsi, .msi_alloc = ioapic_abi_msi_alloc, .msi_release = ioapic_abi_msi_release, @@ -842,14 +848,22 @@ ioapic_fixup_legacy_irqmaps(void) } } -int -ioapic_find_legacy_by_gsi(int gsi, enum intr_trigger trig, +static int +ioapic_abi_legacy_intr_find_bygsi(int gsi, enum intr_trigger trig, enum intr_polarity pola) { int cpu; - KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); - KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); +#ifdef INVARIANTS + if (trig == INTR_TRIGGER_CONFORM) { + KKASSERT(pola == INTR_POLARITY_CONFORM); + } else { + KKASSERT(trig == INTR_TRIGGER_EDGE || + trig == INTR_TRIGGER_LEVEL); + KKASSERT(pola == INTR_POLARITY_HIGH || + pola == INTR_POLARITY_LOW); + } +#endif for (cpu = 0; cpu < ncpus; ++cpu) { int irq; @@ -861,7 +875,9 @@ ioapic_find_legacy_by_gsi(int gsi, enum intr_trigger trig, if (map->im_gsi == gsi) { KKASSERT(map->im_type == IOAPIC_IMT_LEGACY); - if (map->im_flags & IOAPIC_IMF_CONF) { + if ((map->im_flags & IOAPIC_IMF_CONF) && + trig != INTR_TRIGGER_CONFORM && + pola != INTR_POLARITY_CONFORM) { if (map->im_trig != trig || map->im_pola != pola) return -1; @@ -873,14 +889,22 @@ ioapic_find_legacy_by_gsi(int gsi, enum intr_trigger trig, return -1; } -int -ioapic_find_legacy_by_irq(int irq, enum intr_trigger trig, +static int +ioapic_abi_legacy_intr_find(int irq, enum intr_trigger trig, enum intr_polarity pola) { int cpu; - KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); - KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); +#ifdef INVARIANTS + if (trig == INTR_TRIGGER_CONFORM) { + KKASSERT(pola == INTR_POLARITY_CONFORM); + } else { + KKASSERT(trig == INTR_TRIGGER_EDGE || + trig == INTR_TRIGGER_LEVEL); + KKASSERT(pola == INTR_POLARITY_HIGH || + pola == INTR_POLARITY_LOW); + } +#endif if (irq < 0 || irq >= ioapic_abi_legacy_irq_max) return -1; @@ -889,7 +913,9 @@ ioapic_find_legacy_by_irq(int irq, enum intr_trigger trig, const struct ioapic_irqmap *map = &ioapic_irqmaps[cpu][irq]; if (map->im_type == IOAPIC_IMT_LEGACY) { - if (map->im_flags & IOAPIC_IMF_CONF) { + if ((map->im_flags & IOAPIC_IMF_CONF) && + trig != INTR_TRIGGER_CONFORM && + pola != INTR_POLARITY_CONFORM) { if (map->im_trig != trig || map->im_pola != pola) return -1; diff --git a/sys/platform/pc32/apic/ioapic_abi.h b/sys/platform/pc32/apic/ioapic_abi.h index 3fd3d4eac2..7c548ec8b7 100644 --- a/sys/platform/pc32/apic/ioapic_abi.h +++ b/sys/platform/pc32/apic/ioapic_abi.h @@ -70,7 +70,4 @@ void ioapic_set_legacy_irqmap(int, int, enum intr_trigger, enum intr_polarity); void ioapic_fixup_legacy_irqmaps(void); -int ioapic_find_legacy_by_gsi(int, enum intr_trigger, enum intr_polarity); -int ioapic_find_legacy_by_irq(int, enum intr_trigger, enum intr_polarity); - #endif /* !_ARCH_APIC_IOAPIC_ABI_H_ */ diff --git a/sys/platform/pc32/i386/mptable.c b/sys/platform/pc32/i386/mptable.c index 745adee444..444ed5c01f 100644 --- a/sys/platform/pc32/i386/mptable.c +++ b/sys/platform/pc32/i386/mptable.c @@ -1441,7 +1441,7 @@ mptable_pci_int_route(int bus, int dev, int pin, int intline) gsi = ioapic_gsi(pci_int->mpci_ioapic_idx, pci_int->mpci_ioapic_pin); if (gsi >= 0) { - irq = ioapic_find_legacy_by_gsi(gsi, + irq = machintr_legacy_intr_find_bygsi(gsi, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); } } @@ -1452,7 +1452,7 @@ mptable_pci_int_route(int bus, int dev, int pin, int intline) "for %d:%d INT%c\n", bus, dev, pin + 'A'); } - irq = ioapic_find_legacy_by_irq(intline, + irq = machintr_legacy_intr_find(intline, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); } diff --git a/sys/platform/pc32/icu/icu_abi.c b/sys/platform/pc32/icu/icu_abi.c index 2bfc13cc88..1ea3b1d62b 100644 --- a/sys/platform/pc32/icu/icu_abi.c +++ b/sys/platform/pc32/icu/icu_abi.c @@ -85,6 +85,7 @@ static struct icu_irqmap { int im_type; /* ICU_IMT_ */ enum intr_trigger im_trig; int im_msi_base; + uint32_t im_flags; } icu_irqmaps[MAXCPU][IDT_HWI_VECTORS]; static struct lwkt_token icu_irqmap_tok = @@ -102,6 +103,8 @@ static struct lwkt_token icu_irqmap_tok = (map)->im_type != ICU_IMT_SYSCALL && \ (map)->im_type != ICU_IMT_SHADOW) +#define ICU_IMF_CONF 0x1 + extern void ICU_INTREN(int); extern void ICU_INTRDIS(int); @@ -115,6 +118,10 @@ static void icu_abi_intr_teardown(int); static void icu_abi_legacy_intr_config(int, enum intr_trigger, enum intr_polarity); static int icu_abi_legacy_intr_cpuid(int); +static int icu_abi_legacy_intr_find(int, enum intr_trigger, + enum intr_polarity); +static int icu_abi_legacy_intr_find_bygsi(int, enum intr_trigger, + enum intr_polarity); static int icu_abi_msi_alloc(int [], int, int); static void icu_abi_msi_release(const int [], int, int); @@ -143,6 +150,8 @@ struct machintr_abi MachIntrABI_ICU = { .legacy_intr_config = icu_abi_legacy_intr_config, .legacy_intr_cpuid = icu_abi_legacy_intr_cpuid, + .legacy_intr_find = icu_abi_legacy_intr_find, + .legacy_intr_find_bygsi = icu_abi_legacy_intr_find_bygsi, .msi_alloc = icu_abi_msi_alloc, .msi_release = icu_abi_msi_release, @@ -370,6 +379,7 @@ icu_abi_legacy_intr_config(int irq, enum intr_trigger trig, KKASSERT(map->im_type == ICU_IMT_LEGACY); /* TODO: Check whether it is configured or not */ + map->im_flags |= ICU_IMF_CONF; if (trig == map->im_trig) return; @@ -671,3 +681,43 @@ icu_abi_msi_map(int intr, uint64_t *addr, uint32_t *data, int cpuid) lwkt_reltoken(&icu_irqmap_tok); } + +static int +icu_abi_legacy_intr_find(int irq, enum intr_trigger trig, + enum intr_polarity pola __unused) +{ + const struct icu_irqmap *map; + +#ifdef INVARIANTS + if (trig == INTR_TRIGGER_CONFORM) { + KKASSERT(pola == INTR_POLARITY_CONFORM); + } else { + KKASSERT(trig == INTR_TRIGGER_EDGE || + trig == INTR_TRIGGER_LEVEL); + KKASSERT(pola == INTR_POLARITY_HIGH || + pola == INTR_POLARITY_LOW); + } +#endif + + if (irq < 0 || irq >= ICU_HWI_VECTORS) + return -1; + + map = &icu_irqmaps[0][irq]; + if (map->im_type == ICU_IMT_LEGACY) { + if ((map->im_flags & ICU_IMF_CONF) && + trig != INTR_TRIGGER_CONFORM) { + if (map->im_trig != trig) + return -1; + } + return irq; + } + return -1; +} + +static int +icu_abi_legacy_intr_find_bygsi(int gsi, enum intr_trigger trig, + enum intr_polarity pola) +{ + /* GSI and IRQ has 1:1 mapping */ + return icu_abi_legacy_intr_find(gsi, trig, pola); +} diff --git a/sys/platform/pc32/isa/clock.c b/sys/platform/pc32/isa/clock.c index 4af55a2188..838bf56207 100644 --- a/sys/platform/pc32/isa/clock.c +++ b/sys/platform/pc32/isa/clock.c @@ -1057,13 +1057,13 @@ i8254_intr_initclock(struct cputimer_intr *cti, boolean_t selected) /* Finish initializing 8253 timer 0. */ if (ioapic_enable) { - irq = ioapic_find_legacy_by_irq(0, INTR_TRIGGER_EDGE, + irq = machintr_legacy_intr_find(0, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); if (irq < 0) { mixed_mode_setup: error = ioapic_conf_legacy_extint(0); if (!error) { - irq = ioapic_find_legacy_by_irq(0, + irq = machintr_legacy_intr_find(0, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); if (irq < 0) error = ENOENT; diff --git a/sys/platform/pc64/apic/ioapic_abi.c b/sys/platform/pc64/apic/ioapic_abi.c index 92b7e57243..367e70f28b 100644 --- a/sys/platform/pc64/apic/ioapic_abi.c +++ b/sys/platform/pc64/apic/ioapic_abi.c @@ -494,6 +494,10 @@ static void ioapic_abi_intr_teardown(int); static void ioapic_abi_legacy_intr_config(int, enum intr_trigger, enum intr_polarity); static int ioapic_abi_legacy_intr_cpuid(int); +static int ioapic_abi_legacy_intr_find(int, + enum intr_trigger, enum intr_polarity); +static int ioapic_abi_legacy_intr_find_bygsi(int, + enum intr_trigger, enum intr_polarity); static int ioapic_abi_msi_alloc(int [], int, int); static void ioapic_abi_msi_release(const int [], int, int); @@ -524,6 +528,8 @@ struct machintr_abi MachIntrABI_IOAPIC = { .legacy_intr_config = ioapic_abi_legacy_intr_config, .legacy_intr_cpuid = ioapic_abi_legacy_intr_cpuid, + .legacy_intr_find = ioapic_abi_legacy_intr_find, + .legacy_intr_find_bygsi = ioapic_abi_legacy_intr_find_bygsi, .msi_alloc = ioapic_abi_msi_alloc, .msi_release = ioapic_abi_msi_release, @@ -839,14 +845,22 @@ ioapic_fixup_legacy_irqmaps(void) } } -int -ioapic_find_legacy_by_gsi(int gsi, enum intr_trigger trig, +static int +ioapic_abi_legacy_intr_find_bygsi(int gsi, enum intr_trigger trig, enum intr_polarity pola) { int cpu; - KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); - KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); +#ifdef INVARIANTS + if (trig == INTR_TRIGGER_CONFORM) { + KKASSERT(pola == INTR_POLARITY_CONFORM); + } else { + KKASSERT(trig == INTR_TRIGGER_EDGE || + trig == INTR_TRIGGER_LEVEL); + KKASSERT(pola == INTR_POLARITY_HIGH || + pola == INTR_POLARITY_LOW); + } +#endif for (cpu = 0; cpu < ncpus; ++cpu) { int irq; @@ -858,7 +872,9 @@ ioapic_find_legacy_by_gsi(int gsi, enum intr_trigger trig, if (map->im_gsi == gsi) { KKASSERT(map->im_type == IOAPIC_IMT_LEGACY); - if (map->im_flags & IOAPIC_IMF_CONF) { + if ((map->im_flags & IOAPIC_IMF_CONF) && + trig != INTR_TRIGGER_CONFORM && + pola != INTR_POLARITY_CONFORM) { if (map->im_trig != trig || map->im_pola != pola) return -1; @@ -870,14 +886,22 @@ ioapic_find_legacy_by_gsi(int gsi, enum intr_trigger trig, return -1; } -int -ioapic_find_legacy_by_irq(int irq, enum intr_trigger trig, +static int +ioapic_abi_legacy_intr_find(int irq, enum intr_trigger trig, enum intr_polarity pola) { int cpu; - KKASSERT(trig == INTR_TRIGGER_EDGE || trig == INTR_TRIGGER_LEVEL); - KKASSERT(pola == INTR_POLARITY_HIGH || pola == INTR_POLARITY_LOW); +#ifdef INVARIANTS + if (trig == INTR_TRIGGER_CONFORM) { + KKASSERT(pola == INTR_POLARITY_CONFORM); + } else { + KKASSERT(trig == INTR_TRIGGER_EDGE || + trig == INTR_TRIGGER_LEVEL); + KKASSERT(pola == INTR_POLARITY_HIGH || + pola == INTR_POLARITY_LOW); + } +#endif if (irq < 0 || irq >= ioapic_abi_legacy_irq_max) return -1; @@ -886,7 +910,9 @@ ioapic_find_legacy_by_irq(int irq, enum intr_trigger trig, const struct ioapic_irqmap *map = &ioapic_irqmaps[cpu][irq]; if (map->im_type == IOAPIC_IMT_LEGACY) { - if (map->im_flags & IOAPIC_IMF_CONF) { + if ((map->im_flags & IOAPIC_IMF_CONF) && + trig != INTR_TRIGGER_CONFORM && + pola != INTR_POLARITY_CONFORM) { if (map->im_trig != trig || map->im_pola != pola) return -1; diff --git a/sys/platform/pc64/apic/ioapic_abi.h b/sys/platform/pc64/apic/ioapic_abi.h index ff0be4df96..8cdf762fb0 100644 --- a/sys/platform/pc64/apic/ioapic_abi.h +++ b/sys/platform/pc64/apic/ioapic_abi.h @@ -69,7 +69,4 @@ void ioapic_set_legacy_irqmap(int, int, enum intr_trigger, enum intr_polarity); void ioapic_fixup_legacy_irqmaps(void); -int ioapic_find_legacy_by_gsi(int, enum intr_trigger, enum intr_polarity); -int ioapic_find_legacy_by_irq(int, enum intr_trigger, enum intr_polarity); - #endif /* !_ARCH_APIC_IOAPIC_ABI_H_ */ diff --git a/sys/platform/pc64/icu/icu_abi.c b/sys/platform/pc64/icu/icu_abi.c index 426b034639..8b0c2cd8eb 100644 --- a/sys/platform/pc64/icu/icu_abi.c +++ b/sys/platform/pc64/icu/icu_abi.c @@ -85,6 +85,7 @@ static struct icu_irqmap { int im_type; /* ICU_IMT_ */ enum intr_trigger im_trig; int im_msi_base; + uint32_t im_flags; /* ICU_IMF_ */ } icu_irqmaps[MAXCPU][IDT_HWI_VECTORS]; static struct lwkt_token icu_irqmap_tok = @@ -100,6 +101,8 @@ static struct lwkt_token icu_irqmap_tok = #define ICU_IMT_ISHWI(map) ((map)->im_type != ICU_IMT_RESERVED && \ (map)->im_type != ICU_IMT_SYSCALL) +#define ICU_IMF_CONF 0x1 + extern void ICU_INTREN(int); extern void ICU_INTRDIS(int); @@ -113,6 +116,10 @@ static void icu_abi_intr_teardown(int); static void icu_abi_legacy_intr_config(int, enum intr_trigger, enum intr_polarity); static int icu_abi_legacy_intr_cpuid(int); +static int icu_abi_legacy_intr_find(int, enum intr_trigger, + enum intr_polarity); +static int icu_abi_legacy_intr_find_bygsi(int, enum intr_trigger, + enum intr_polarity); static int icu_abi_msi_alloc(int [], int, int); static void icu_abi_msi_release(const int [], int, int); @@ -141,6 +148,8 @@ struct machintr_abi MachIntrABI_ICU = { .legacy_intr_config = icu_abi_legacy_intr_config, .legacy_intr_cpuid = icu_abi_legacy_intr_cpuid, + .legacy_intr_find = icu_abi_legacy_intr_find, + .legacy_intr_find_bygsi = icu_abi_legacy_intr_find_bygsi, .msi_alloc = icu_abi_msi_alloc, .msi_release = icu_abi_msi_release, @@ -368,6 +377,7 @@ icu_abi_legacy_intr_config(int irq, enum intr_trigger trig, KKASSERT(map->im_type == ICU_IMT_LEGACY); /* TODO: Check whether it is configured or not */ + map->im_flags |= ICU_IMF_CONF; if (trig == map->im_trig) return; @@ -635,3 +645,43 @@ icu_abi_msi_map(int intr, uint64_t *addr, uint32_t *data, int cpuid) lwkt_reltoken(&icu_irqmap_tok); } + +static int +icu_abi_legacy_intr_find(int irq, enum intr_trigger trig, + enum intr_polarity pola __unused) +{ + const struct icu_irqmap *map; + +#ifdef INVARIANTS + if (trig == INTR_TRIGGER_CONFORM) { + KKASSERT(pola == INTR_POLARITY_CONFORM); + } else { + KKASSERT(trig == INTR_TRIGGER_EDGE || + trig == INTR_TRIGGER_LEVEL); + KKASSERT(pola == INTR_POLARITY_HIGH || + pola == INTR_POLARITY_LOW); + } +#endif + + if (irq < 0 || irq >= ICU_HWI_VECTORS) + return -1; + + map = &icu_irqmaps[0][irq]; + if (map->im_type == ICU_IMT_LEGACY) { + if ((map->im_flags & ICU_IMF_CONF) && + trig != INTR_TRIGGER_CONFORM) { + if (map->im_trig != trig) + return -1; + } + return irq; + } + return -1; +} + +static int +icu_abi_legacy_intr_find_bygsi(int gsi, enum intr_trigger trig, + enum intr_polarity pola) +{ + /* GSI and IRQ has 1:1 mapping */ + return icu_abi_legacy_intr_find(gsi, trig, pola); +} diff --git a/sys/platform/pc64/isa/clock.c b/sys/platform/pc64/isa/clock.c index 13c5589780..ed55c44755 100644 --- a/sys/platform/pc64/isa/clock.c +++ b/sys/platform/pc64/isa/clock.c @@ -1064,13 +1064,13 @@ i8254_intr_initclock(struct cputimer_intr *cti, boolean_t selected) /* Finish initializing 8254 timer 0. */ if (ioapic_enable) { - irq = ioapic_find_legacy_by_irq(0, INTR_TRIGGER_EDGE, + irq = machintr_legacy_intr_find(0, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); if (irq < 0) { mixed_mode_setup: error = ioapic_conf_legacy_extint(0); if (!error) { - irq = ioapic_find_legacy_by_irq(0, + irq = machintr_legacy_intr_find(0, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); if (irq < 0) error = ENOENT; diff --git a/sys/platform/pc64/x86_64/mptable.c b/sys/platform/pc64/x86_64/mptable.c index 088bee6596..30faeb8d3b 100644 --- a/sys/platform/pc64/x86_64/mptable.c +++ b/sys/platform/pc64/x86_64/mptable.c @@ -1441,7 +1441,7 @@ mptable_pci_int_route(int bus, int dev, int pin, int intline) gsi = ioapic_gsi(pci_int->mpci_ioapic_idx, pci_int->mpci_ioapic_pin); if (gsi >= 0) { - irq = ioapic_find_legacy_by_gsi(gsi, + irq = machintr_legacy_intr_find_bygsi(gsi, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); } } @@ -1452,7 +1452,7 @@ mptable_pci_int_route(int bus, int dev, int pin, int intline) "for %d:%d INT%c\n", bus, dev, pin + 'A'); } - irq = ioapic_find_legacy_by_irq(intline, + irq = machintr_legacy_intr_find(intline, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); } diff --git a/sys/sys/machintr.h b/sys/sys/machintr.h index f4807fc78e..17b09fc606 100644 --- a/sys/sys/machintr.h +++ b/sys/sys/machintr.h @@ -69,6 +69,10 @@ struct machintr_abi { void (*legacy_intr_config) /* config legacy intr */ (int intr, enum intr_trigger trig, enum intr_polarity pola); int (*legacy_intr_cpuid)(int intr); /* legacy intr target cpu */ + int (*legacy_intr_find) /* find legacy intr */ + (int intr, enum intr_trigger trig, enum intr_polarity pola); + int (*legacy_intr_find_bygsi) /* find legacy intr by GSI */ + (int gsi, enum intr_trigger trig, enum intr_polarity pola); int (*msi_alloc) /* alloc count MSIs on cpu */ (int intrs[], int count, int cpuid); @@ -101,6 +105,11 @@ struct machintr_abi { #define machintr_legacy_intr_cpuid(intr) \ MachIntrABI.legacy_intr_cpuid((intr)) +#define machintr_legacy_intr_find(intr, trig, pola) \ + MachIntrABI.legacy_intr_find((intr), (trig), (pola)) +#define machintr_legacy_intr_find_bygsi(gsi, trig, pola) \ + MachIntrABI.legacy_intr_find_bygsi((gsi), (trig), (pola)) + extern struct machintr_abi MachIntrABI; #endif /* _KERNEL */ -- 2.41.0