From 9a4bd8f3e26e2f6db1aec89d14732669a387cc3a Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Fri, 3 Jun 2011 17:10:10 +0800 Subject: [PATCH] x86_64: Allow UP kernel to use LAPIC timer and I/O APIC --- sys/bus/pci/pci_pci.c | 6 ++- sys/platform/pc64/acpica5/acpi_machdep.c | 43 ++++------------------ sys/platform/pc64/apic/apic_vector.s | 3 ++ sys/platform/pc64/apic/ioapic_abi.c | 1 + sys/platform/pc64/apic/lapic.c | 22 +++++++++-- sys/platform/pc64/apic/lapic.h | 19 ++++++---- sys/platform/pc64/conf/files | 16 ++++---- sys/platform/pc64/icu/icu.c | 6 --- sys/platform/pc64/icu/icu_abi.c | 3 -- sys/platform/pc64/icu/icu_var.h | 2 - sys/platform/pc64/include/acpica_machdep.h | 2 - sys/platform/pc64/include/intr_machdep.h | 14 +++---- sys/platform/pc64/isa/clock.c | 24 +++--------- sys/platform/pc64/x86_64/ipl.s | 9 ++--- sys/platform/pc64/x86_64/machdep.c | 3 +- sys/platform/pc64/x86_64/nexus.c | 31 +++++++--------- 16 files changed, 84 insertions(+), 120 deletions(-) diff --git a/sys/bus/pci/pci_pci.c b/sys/bus/pci/pci_pci.c index cd273c43a6..81659cc6fb 100644 --- a/sys/bus/pci/pci_pci.c +++ b/sys/bus/pci/pci_pci.c @@ -126,12 +126,16 @@ pcib_probe(device_t dev) if ((pci_get_class(dev) == PCIC_BRIDGE) && (pci_get_subclass(dev) == PCIS_BRIDGE_PCI)) { device_set_desc(dev, "PCI-PCI bridge"); -#if defined(__i386__) || defined(__x86_64__) +#if defined(__i386__) #ifdef SMP /* PCIBIOS PCI-PCI bridge is -2000 */ if (ioapic_enable) return (-1000); #endif +#elif defined(__x86_64__) + /* PCIBIOS PCI-PCI bridge is -2000 */ + if (ioapic_enable) + return (-1000); #endif return (-10000); } diff --git a/sys/platform/pc64/acpica5/acpi_machdep.c b/sys/platform/pc64/acpica5/acpi_machdep.c index 3d3943ffb6..701b93c4b1 100644 --- a/sys/platform/pc64/acpica5/acpi_machdep.c +++ b/sys/platform/pc64/acpica5/acpi_machdep.c @@ -56,15 +56,6 @@ static device_t acpi_dev; uint32_t acpi_reset_video = 1; TUNABLE_INT("hw.acpi.reset_video", &acpi_reset_video); -/* - * -1 == unset. Use acpi_GetDefaultIntrModel() - */ -#ifdef SMP /* APIC-IO */ -static int intr_model = -1; -#else -static int intr_model = ACPI_INTR_PIC; -#endif - static struct apm_softc apm_softc; static d_open_t apmopen; @@ -331,29 +322,11 @@ acpi_capm_init(struct acpi_softc *sc) kprintf("Warning: ACPI is disabling APM's device. You can't run both\n"); } -/* - * Lazy initialize intr_model - */ -static int -acpi_GetDefaultIntrModel(void) -{ - if (intr_model == -1) { -#ifdef SMP - if (ioapic_enable) - intr_model = ACPI_INTR_APIC; - else - intr_model = ACPI_INTR_PIC; -#else - intr_model = ACPI_INTR_PIC; -#endif - } - return intr_model; -} - int acpi_machdep_init(device_t dev) { struct acpi_softc *sc; + int intr_model; acpi_dev = dev; sc = device_get_softc(acpi_dev); @@ -370,7 +343,12 @@ acpi_machdep_init(device_t dev) acpi_install_wakeup_handler(sc); - if (acpi_GetDefaultIntrModel() != ACPI_INTR_PIC) + if (ioapic_enable) + intr_model = ACPI_INTR_APIC; + else + intr_model = ACPI_INTR_PIC; + + if (intr_model != ACPI_INTR_PIC) acpi_SetIntrModel(intr_model); SYSCTL_ADD_UINT(&sc->acpi_sysctl_ctx, @@ -380,10 +358,3 @@ acpi_machdep_init(device_t dev) return (0); } - -void -acpi_SetDefaultIntrModel(int model) -{ - - intr_model = model; -} diff --git a/sys/platform/pc64/apic/apic_vector.s b/sys/platform/pc64/apic/apic_vector.s index c12a03ad60..5e662b9b1e 100644 --- a/sys/platform/pc64/apic/apic_vector.s +++ b/sys/platform/pc64/apic/apic_vector.s @@ -175,6 +175,7 @@ Xspuriousint: jmp doreti_iret +#ifdef SMP /* * Handle TLB shootdowns. @@ -297,6 +298,8 @@ Xipiq: APIC_POP_FRAME jmp doreti_iret +#endif /* SMP */ + .text SUPERALIGN_TEXT .globl Xtimer diff --git a/sys/platform/pc64/apic/ioapic_abi.c b/sys/platform/pc64/apic/ioapic_abi.c index 05153ef0ee..da0059c9e3 100644 --- a/sys/platform/pc64/apic/ioapic_abi.c +++ b/sys/platform/pc64/apic/ioapic_abi.c @@ -60,6 +60,7 @@ #include #include #include +#include extern inthand_t IDTVEC(ioapic_intr0), diff --git a/sys/platform/pc64/apic/lapic.c b/sys/platform/pc64/apic/lapic.c index 8089d6af70..d5d10f6c1c 100644 --- a/sys/platform/pc64/apic/lapic.c +++ b/sys/platform/pc64/apic/lapic.c @@ -123,6 +123,11 @@ lapic_init(boolean_t bsp) setidt(XSPURIOUSINT_OFFSET, Xspuriousint, SDT_SYSIGT, SEL_KPL, 0); + /* Install a timer vector */ + setidt(XTIMER_OFFSET, Xtimer, + SDT_SYSIGT, SEL_KPL, 0); + +#ifdef SMP /* Install an inter-CPU IPI for TLB invalidation */ setidt(XINVLTLB_OFFSET, Xinvltlb, SDT_SYSIGT, SEL_KPL, 0); @@ -131,13 +136,10 @@ lapic_init(boolean_t bsp) setidt(XIPIQ_OFFSET, Xipiq, SDT_SYSIGT, SEL_KPL, 0); - /* Install a timer vector */ - setidt(XTIMER_OFFSET, Xtimer, - SDT_SYSIGT, SEL_KPL, 0); - /* Install an inter-CPU IPI for CPU stop/restart */ setidt(XCPUSTOP_OFFSET, Xcpustop, SDT_SYSIGT, SEL_KPL, 0); +#endif } /* @@ -477,14 +479,22 @@ lapic_timer_restart_handler(void *dummy __unused) static void lapic_timer_intr_pmfixup(struct cputimer_intr *cti __unused) { +#ifdef SMP lwkt_send_ipiq_mask(smp_active_mask, lapic_timer_fixup_handler, NULL); +#else + lapic_timer_fixup_handler(NULL); +#endif } static void lapic_timer_intr_restart(struct cputimer_intr *cti __unused) { +#ifdef SMP lwkt_send_ipiq_mask(smp_active_mask, lapic_timer_restart_handler, NULL); +#else + lapic_timer_restart_handler(NULL); +#endif } @@ -499,6 +509,8 @@ apic_dump(char* str) lapic->lvt_lint0, lapic->lvt_lint1, lapic->tpr, lapic->svr); } +#ifdef SMP + /* * Inter Processor Interrupt functions. */ @@ -625,6 +637,8 @@ selected_apic_ipi(cpumask_t target, int vector, int delivery_mode) crit_exit(); } +#endif /* SMP */ + /* * Timer code, in development... * - suggested by rgrimes@gndrsh.aac.dev.com diff --git a/sys/platform/pc64/apic/lapic.h b/sys/platform/pc64/apic/lapic.h index d198617f8a..74d1433963 100644 --- a/sys/platform/pc64/apic/lapic.h +++ b/sys/platform/pc64/apic/lapic.h @@ -59,10 +59,6 @@ extern int lapic_enable; void apic_dump(char*); void lapic_init(boolean_t); -int apic_ipi(int, int, int); -void selected_apic_ipi(cpumask_t, int, int); -void single_apic_ipi(int, int, int); -int single_apic_ipi_passive(int, int, int); void lapic_set_cpuid(int, int); int lapic_config(void); void lapic_enumerator_register(struct lapic_enumerator *); @@ -71,6 +67,17 @@ int get_apic_timer_frequency(void); int read_apic_timer(void); void u_sleep(int); +void lapic_map(vm_offset_t /* XXX should be vm_paddr_t */); +int lapic_unused_apic_id(int); +void lapic_fixup_noioapic(void); + +#ifdef SMP + +int apic_ipi(int, int, int); +void selected_apic_ipi(cpumask_t, int, int); +void single_apic_ipi(int, int, int); +int single_apic_ipi_passive(int, int, int); + /* * Send an IPI INTerrupt containing 'vector' to all CPUs EXCEPT myself */ @@ -82,8 +89,6 @@ all_but_self_ipi(int vector) return apic_ipi(APIC_DEST_ALLESELF, vector, APIC_DELMODE_FIXED); } -void lapic_map(vm_offset_t /* XXX should be vm_paddr_t */); -int lapic_unused_apic_id(int); -void lapic_fixup_noioapic(void); +#endif /* SMP */ #endif /* _ARCH_APIC_LAPIC_H_ */ diff --git a/sys/platform/pc64/conf/files b/sys/platform/pc64/conf/files index 18ac7d0099..54d935fbf0 100644 --- a/sys/platform/pc64/conf/files +++ b/sys/platform/pc64/conf/files @@ -167,11 +167,11 @@ platform/pc64/x86_64/identcpu.c standard platform/pc64/x86_64/amd64_mem.c standard platform/pc64/x86_64/cpufreq_machdep.c standard -platform/pc64/apic/lapic.c optional smp -platform/pc64/apic/ioapic.c optional smp -platform/pc64/apic/ioapic_abi.c optional smp -platform/pc64/apic/ioapic_ipl.s optional smp -platform/pc64/apic/apic_vector.s optional smp +platform/pc64/apic/lapic.c standard +platform/pc64/apic/ioapic.c standard +platform/pc64/apic/ioapic_abi.c standard +platform/pc64/apic/ioapic_ipl.s standard +platform/pc64/apic/apic_vector.s standard bus/isa/x86_64/isa.c optional isa bus/isa/x86_64/isa_dma.c optional isa @@ -187,7 +187,7 @@ platform/pc64/icu/elcr.c standard bus/pci/x86_64/legacy.c optional pci bus/pci/x86_64/pci_bus.c optional pci bus/pci/x86_64/pci_cfgreg.c optional pci -bus/pci/x86_64/mptable_pci.c optional pci smp +bus/pci/x86_64/mptable_pci.c optional pci # notyet (BIOS struct and functions) #bus/pci/x86_64/pci_pir.c optional pci @@ -201,10 +201,10 @@ platform/pc64/x86_64/console.c standard platform/pc64/x86_64/ipl_funcs.c standard kern/syscalls.c standard platform/pc64/x86_64/mp_machdep.c optional smp -platform/pc64/x86_64/mptable.c optional smp +platform/pc64/x86_64/mptable.c standard platform/pc64/acpica5/acpi_sdt.c standard platform/pc64/acpica5/acpi_fadt.c standard -platform/pc64/acpica5/acpi_madt.c optional smp +platform/pc64/acpica5/acpi_madt.c standard dev/misc/atkbd/atkbd_isa.c optional atkbd dev/misc/atkbdc_layer/atkbdc_isa.c optional atkbdc dev/misc/ppc/ppc.c optional ppc diff --git a/sys/platform/pc64/icu/icu.c b/sys/platform/pc64/icu/icu.c index 3792fe68d1..5c99ea0ed1 100644 --- a/sys/platform/pc64/icu/icu.c +++ b/sys/platform/pc64/icu/icu.c @@ -70,10 +70,8 @@ icu_init(void) int auto_eoi = 0; /* 8086 mode */ #endif -#ifdef SMP if (ioapic_enable) auto_eoi = 2; /* auto EOI, 8086 mode */ -#endif /* * Program master @@ -183,8 +181,6 @@ icu_ioapic_extint(int irq, int vec) return 0; } -#ifdef SMP - void icu_reinit_noioapic(void) { @@ -209,5 +205,3 @@ icu_reinit_noioapic(void) MachIntrABI.cleanup(); crit_exit(); } - -#endif diff --git a/sys/platform/pc64/icu/icu_abi.c b/sys/platform/pc64/icu/icu_abi.c index 239989e4d3..837b788076 100644 --- a/sys/platform/pc64/icu/icu_abi.c +++ b/sys/platform/pc64/icu/icu_abi.c @@ -167,8 +167,6 @@ static void icu_finalize(void) { KKASSERT(MachIntrABI.type == MACHINTR_ICU); - -#ifdef SMP KKASSERT(!ioapic_enable); /* @@ -184,7 +182,6 @@ icu_finalize(void) outb(0x22, 0x70); outb(0x23, 0x01); } -#endif /* SMP */ } static int diff --git a/sys/platform/pc64/icu/icu_var.h b/sys/platform/pc64/icu/icu_var.h index 47e046c729..7d04411bbb 100644 --- a/sys/platform/pc64/icu/icu_var.h +++ b/sys/platform/pc64/icu/icu_var.h @@ -40,9 +40,7 @@ void icu_definit(void); void icu_reinit(void); -#ifdef SMP void icu_reinit_noioapic(void); -#endif intrmask_t icu_irq_pending(void); diff --git a/sys/platform/pc64/include/acpica_machdep.h b/sys/platform/pc64/include/acpica_machdep.h index 11ba221676..3ade026867 100644 --- a/sys/platform/pc64/include/acpica_machdep.h +++ b/sys/platform/pc64/include/acpica_machdep.h @@ -74,6 +74,4 @@ extern int acpi_release_global_lock(uint32_t *lock); #define COMPILER_DEPENDENT_INT64 long #define COMPILER_DEPENDENT_UINT64 unsigned long -void acpi_SetDefaultIntrModel(int model); - #endif /* _MACHINE_ACPICA_MACHDEP_H__ */ diff --git a/sys/platform/pc64/include/intr_machdep.h b/sys/platform/pc64/include/intr_machdep.h index 262cb988cc..113845a376 100644 --- a/sys/platform/pc64/include/intr_machdep.h +++ b/sys/platform/pc64/include/intr_machdep.h @@ -54,8 +54,6 @@ #define IDT_OFFSET_SYSCALL 0x80 #define IDT_OFFSET_IPI 0xe0 -#if defined(SMP) - /* * Local APIC TPR priority vector levels: * @@ -132,8 +130,6 @@ /* NOTE: this vector MUST be xxxx1111 */ #define XSPURIOUSINT_OFFSET (IDT_OFFSET_IPIG2 + 15) -#endif /* SMP */ - #ifndef LOCORE /* @@ -146,14 +142,16 @@ typedef void inthand_t(u_int cs, u_int ef, u_int esp, u_int ss); #define IDTVEC(name) __CONCAT(X,name) -#if defined(SMP) +inthand_t + Xspuriousint, /* handle APIC "spurious INTs" */ + Xtimer; /* handle LAPIC timer INT */ + +#ifdef SMP inthand_t Xinvltlb, /* TLB shootdowns */ Xcpustop, /* CPU stops & waits for another CPU to restart it */ - Xspuriousint, /* handle APIC "spurious INTs" */ - Xtimer, /* handle LAPIC timer INT */ Xipiq; /* handle lwkt_send_ipiq() requests */ -#endif /* SMP */ +#endif #endif /* LOCORE */ diff --git a/sys/platform/pc64/isa/clock.c b/sys/platform/pc64/isa/clock.c index 5059466e47..4403aa9e22 100644 --- a/sys/platform/pc64/isa/clock.c +++ b/sys/platform/pc64/isa/clock.c @@ -86,10 +86,8 @@ #include #include -#ifdef SMP #include #include -#endif #include #include #include @@ -1008,8 +1006,6 @@ resettodr(void) crit_exit(); } -#ifdef SMP - static int i8254_ioapic_trial(int irq, struct cputimer_intr *cti) { @@ -1041,8 +1037,6 @@ i8254_ioapic_trial(int irq, struct cputimer_intr *cti) return 0; } -#endif /* SMP */ - /* * Start both clocks running. DragonFly note: the stat clock is no longer * used. Instead, 8254 based systimers are used for all major clock @@ -1051,10 +1045,8 @@ i8254_ioapic_trial(int irq, struct cputimer_intr *cti) static void i8254_intr_initclock(struct cputimer_intr *cti, boolean_t selected) { -#ifdef SMP /* APIC-IO */ void *clkdesc = NULL; int irq = 0, mixed_mode = 0, error; -#endif callout_init(&sysbeepstop_ch); @@ -1070,7 +1062,6 @@ i8254_intr_initclock(struct cputimer_intr *cti, boolean_t selected) rtc_statusb = RTCSB_24HR; /* Finish initializing 8254 timer 0. */ -#ifdef SMP if (ioapic_enable) { irq = ioapic_abi_find_irq(0, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); @@ -1103,21 +1094,17 @@ mixed_mode_setup: INTR_NOENTROPY); machintr_intren(irq); } else { -#endif - register_int(0, clkintr, NULL, "clk", NULL, - INTR_EXCL | INTR_CLOCK | - INTR_NOPOLL | INTR_MPSAFE | - INTR_NOENTROPY); - machintr_intren(0); -#ifdef SMP /* APIC-IO */ + register_int(0, clkintr, NULL, "clk", NULL, + INTR_EXCL | INTR_CLOCK | + INTR_NOPOLL | INTR_MPSAFE | + INTR_NOENTROPY); + machintr_intren(0); } -#endif /* Initialize RTC. */ writertc(RTC_STATUSA, rtc_statusa); writertc(RTC_STATUSB, RTCSB_24HR); -#ifdef SMP if (ioapic_enable) { error = i8254_ioapic_trial(irq, cti); if (error) { @@ -1140,7 +1127,6 @@ mixed_mode_setup: } } } -#endif return; nointr: diff --git a/sys/platform/pc64/x86_64/ipl.s b/sys/platform/pc64/x86_64/ipl.s index a96f63e1eb..ff8f4282df 100644 --- a/sys/platform/pc64/x86_64/ipl.s +++ b/sys/platform/pc64/x86_64/ipl.s @@ -153,9 +153,9 @@ doreti_next: #ifdef SMP testl $RQF_IPIQ,PCPU(reqflags) jnz doreti_ipiq +#endif testl $RQF_TIMER,PCPU(reqflags) jnz doreti_timer -#endif /* * check for an unmasked int (3 groups) */ @@ -323,6 +323,7 @@ doreti_ipiq: decl PCPU(intr_nesting_level) movl %r12d,%eax /* restore cpl for loop */ jmp doreti_next +#endif doreti_timer: movl %eax,%r12d /* save cpl (can't use stack) */ @@ -337,8 +338,6 @@ doreti_timer: movl %r12d,%eax /* restore cpl for loop */ jmp doreti_next -#endif - /* * SPLZ() a C callable procedure to dispatch any unmasked pending * interrupts regardless of critical section nesting. ASTs @@ -363,9 +362,9 @@ splz_next: #ifdef SMP testl $RQF_IPIQ,PCPU(reqflags) jnz splz_ipiq +#endif testl $RQF_TIMER,PCPU(reqflags) jnz splz_timer -#endif /* * check for an unmasked int (3 groups) */ @@ -453,6 +452,7 @@ splz_ipiq: call lwkt_process_ipiq popq %rax jmp splz_next +#endif splz_timer: andl $~RQF_TIMER,PCPU(reqflags) @@ -461,7 +461,6 @@ splz_timer: call lapic_timer_process popq %rax jmp splz_next -#endif /* * dofastunpend(%rcx:intr) diff --git a/sys/platform/pc64/x86_64/machdep.c b/sys/platform/pc64/x86_64/machdep.c index ebed1a6308..3d19c73fe7 100644 --- a/sys/platform/pc64/x86_64/machdep.c +++ b/sys/platform/pc64/x86_64/machdep.c @@ -1772,11 +1772,10 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) * Default MachIntrABI to ICU */ MachIntrABI = MachIntrABI_ICU; -#ifdef SMP + TUNABLE_INT_FETCH("hw.apic_io_enable", &ioapic_enable); /* for compat */ TUNABLE_INT_FETCH("hw.ioapic_enable", &ioapic_enable); TUNABLE_INT_FETCH("hw.lapic_enable", &lapic_enable); -#endif /* * start with one cpu. Note: with one cpu, ncpus2_shift, ncpus2_mask, diff --git a/sys/platform/pc64/x86_64/nexus.c b/sys/platform/pc64/x86_64/nexus.c index 305d58bffe..e5e0dfa364 100644 --- a/sys/platform/pc64/x86_64/nexus.c +++ b/sys/platform/pc64/x86_64/nexus.c @@ -159,23 +159,20 @@ nexus_probe(device_t dev) irq_rman.rm_start = 0; irq_rman.rm_type = RMAN_ARRAY; irq_rman.rm_descr = "Interrupt request lines"; -#ifdef SMP -if (ioapic_enable) { - irq_rman.rm_end = APIC_INTMAPSIZE - 1; - if (rman_init(&irq_rman) - || rman_manage_region(&irq_rman, - irq_rman.rm_start, irq_rman.rm_end)) - panic("nexus_probe irq_rman"); -} else { -#endif - irq_rman.rm_end = 15; - if (rman_init(&irq_rman) - || rman_manage_region(&irq_rman, irq_rman.rm_start, 1) - || rman_manage_region(&irq_rman, 3, irq_rman.rm_end)) - panic("nexus_probe irq_rman"); -#ifdef SMP -} -#endif + + if (ioapic_enable) { + irq_rman.rm_end = APIC_INTMAPSIZE - 1; + if (rman_init(&irq_rman) + || rman_manage_region(&irq_rman, + irq_rman.rm_start, irq_rman.rm_end)) + panic("nexus_probe irq_rman"); + } else { + irq_rman.rm_end = 15; + if (rman_init(&irq_rman) + || rman_manage_region(&irq_rman, irq_rman.rm_start, 1) + || rman_manage_region(&irq_rman, 3, irq_rman.rm_end)) + panic("nexus_probe irq_rman"); + } /* * ISA DMA on PCI systems is implemented in the ISA part of each -- 2.41.0