summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/apic.c77
-rw-r--r--arch/i386/kernel/i8259.c4
-rw-r--r--arch/i386/kernel/io_apic.c6
-rw-r--r--arch/i386/kernel/smpboot.c68
-rw-r--r--arch/i386/kernel/time.c12
-rw-r--r--include/asm-i386/apic.h3
-rw-r--r--include/asm-i386/hw_irq.h1
-rw-r--r--include/asm-i386/mach-default/smpboot_hooks.h15
-rw-r--r--include/asm-i386/mach-visws/smpboot_hooks.h7
-rw-r--r--init/main.c11
10 files changed, 104 insertions, 100 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 9204be6eedb3..7c724ffa08bb 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -803,7 +803,6 @@ no_apic:
void __init init_apic_mappings(void)
{
- unsigned int orig_apicid;
unsigned long apic_phys;
/*
@@ -825,11 +824,8 @@ void __init init_apic_mappings(void)
* Fetch the APIC ID of the BSP in case we have a
* default configuration (or the MP table is broken).
*/
- orig_apicid = boot_cpu_physical_apicid;
- boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
- if ((orig_apicid != -1U) && (orig_apicid != boot_cpu_physical_apicid))
- printk(KERN_WARNING "Boot APIC ID in local APIC unexpected (%d vs %d)",
- orig_apicid, boot_cpu_physical_apicid);
+ if (boot_cpu_physical_apicid == -1U)
+ boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
#ifdef CONFIG_X86_IO_APIC
{
@@ -1259,81 +1255,40 @@ fastcall void smp_error_interrupt(struct pt_regs *regs)
}
/*
- * This initializes the IO-APIC and APIC hardware.
+ * This initializes the IO-APIC and APIC hardware if this is
+ * a UP kernel.
*/
-int __init APIC_init(void)
+int __init APIC_init_uniprocessor (void)
{
- if (enable_local_apic < 0) {
- printk(KERN_INFO "APIC disabled\n");
- return -1;
- }
+ if (enable_local_apic < 0)
+ clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
- /* See if we have a SMP configuration or have forced enabled
- * the local apic.
- */
- if (!smp_found_config && !acpi_lapic && !cpu_has_apic) {
- enable_local_apic = -1;
+ if (!smp_found_config && !cpu_has_apic)
return -1;
- }
/*
- * Complain if the BIOS pretends there is an apic.
- * Then get out because we don't have an a local apic.
+ * Complain if the BIOS pretends there is one.
*/
if (!cpu_has_apic && APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
boot_cpu_physical_apicid);
- printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
- enable_local_apic = -1;
return -1;
}
verify_local_APIC();
- /*
- * Should not be necessary because the MP table should list the boot
- * CPU too, but we do it for the sake of robustness anyway.
- * Makes no sense to do this check in clustered apic mode, so skip it
- */
- if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
- printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
- boot_cpu_physical_apicid);
- physid_set(boot_cpu_physical_apicid, phys_cpu_present_map);
- }
-
- /*
- * Switch from PIC to APIC mode.
- */
connect_bsp_APIC();
- setup_local_APIC();
-#ifdef CONFIG_X86_IO_APIC
- /*
- * Now start the IO-APICs
- */
- if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
- setup_IO_APIC();
-#endif
- return 0;
-}
+ phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
-void __init APIC_late_time_init(void)
-{
- /* Improve our loops per jiffy estimate */
- loops_per_jiffy = ((1000 + HZ - 1)/HZ)*cpu_khz;
- boot_cpu_data.loops_per_jiffy = loops_per_jiffy;
- cpu_data[0].loops_per_jiffy = loops_per_jiffy;
-
- /* setup_apic_nmi_watchdog doesn't work properly before cpu_khz is
- * initialized. So redo it here to ensure the boot cpu is setup
- * properly.
- */
- if (nmi_watchdog == NMI_LOCAL_APIC)
- setup_apic_nmi_watchdog();
+ setup_local_APIC();
#ifdef CONFIG_X86_IO_APIC
- if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
- IO_APIC_late_time_init();
+ if (smp_found_config)
+ if (!skip_ioapic_setup && nr_ioapics)
+ setup_IO_APIC();
#endif
setup_boot_APIC_clock();
+
+ return 0;
}
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index d86f24909284..323ef8ab3244 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -435,8 +435,4 @@ void __init init_IRQ(void)
setup_irq(FPU_IRQ, &fpu_irq);
irq_ctx_init(smp_processor_id());
-
-#ifdef CONFIG_X86_LOCAL_APIC
- APIC_init();
-#endif
}
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 5a77c52b20a9..cc5d7ac5b2e7 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -2387,15 +2387,11 @@ void __init setup_IO_APIC(void)
sync_Arb_IDs();
setup_IO_APIC_irqs();
init_IO_APIC_traps();
+ check_timer();
if (!acpi_ioapic)
print_IO_APIC();
}
-void __init IO_APIC_late_time_init(void)
-{
- check_timer();
-}
-
/*
* Called after all the initialization is done. If we didnt find any
* APIC bugs then we can allow the modify fast path
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 5a2bbe0c4fff..01b618e73ecd 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -1078,16 +1078,6 @@ void *xquad_portio;
EXPORT_SYMBOL(xquad_portio);
#endif
-/*
- * Fall back to non SMP mode after errors.
- *
- */
-static __init void disable_smp(void)
-{
- cpu_set(0, cpu_sibling_map[0]);
- cpu_set(0, cpu_core_map[0]);
-}
-
static void __init smp_boot_cpus(unsigned int max_cpus)
{
int apicid, cpu, bit, kicked;
@@ -1100,6 +1090,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
printk("CPU%d: ", 0);
print_cpu_info(&cpu_data[0]);
+ boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
boot_cpu_logical_apicid = logical_smp_processor_id();
x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
@@ -1111,27 +1102,68 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
cpus_clear(cpu_core_map[0]);
cpu_set(0, cpu_core_map[0]);
- map_cpu_to_logical_apicid();
-
/*
* If we couldn't find an SMP configuration at boot time,
* get out of here now!
*/
if (!smp_found_config && !acpi_lapic) {
printk(KERN_NOTICE "SMP motherboard not detected.\n");
- disable_smp();
+ smpboot_clear_io_apic_irqs();
+ phys_cpu_present_map = physid_mask_of_physid(0);
+ if (APIC_init_uniprocessor())
+ printk(KERN_NOTICE "Local APIC not detected."
+ " Using dummy APIC emulation.\n");
+ map_cpu_to_logical_apicid();
+ cpu_set(0, cpu_sibling_map[0]);
+ cpu_set(0, cpu_core_map[0]);
+ return;
+ }
+
+ /*
+ * Should not be necessary because the MP table should list the boot
+ * CPU too, but we do it for the sake of robustness anyway.
+ * Makes no sense to do this check in clustered apic mode, so skip it
+ */
+ if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
+ printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
+ boot_cpu_physical_apicid);
+ physid_set(hard_smp_processor_id(), phys_cpu_present_map);
+ }
+
+ /*
+ * If we couldn't find a local APIC, then get out of here now!
+ */
+ if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) {
+ printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
+ boot_cpu_physical_apicid);
+ printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
+ smpboot_clear_io_apic_irqs();
+ phys_cpu_present_map = physid_mask_of_physid(0);
+ cpu_set(0, cpu_sibling_map[0]);
+ cpu_set(0, cpu_core_map[0]);
return;
}
+ verify_local_APIC();
+
/*
* If SMP should be disabled, then really disable it!
*/
- if (!max_cpus || (enable_local_apic < 0)) {
- printk(KERN_INFO "SMP mode deactivated.\n");
- disable_smp();
+ if (!max_cpus) {
+ smp_found_config = 0;
+ printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
+ smpboot_clear_io_apic_irqs();
+ phys_cpu_present_map = physid_mask_of_physid(0);
+ cpu_set(0, cpu_sibling_map[0]);
+ cpu_set(0, cpu_core_map[0]);
return;
}
+ connect_bsp_APIC();
+ setup_local_APIC();
+ map_cpu_to_logical_apicid();
+
+
setup_portio_remap();
/*
@@ -1212,6 +1244,10 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
cpu_set(0, cpu_sibling_map[0]);
cpu_set(0, cpu_core_map[0]);
+ smpboot_setup_io_apic();
+
+ setup_boot_APIC_clock();
+
/*
* Synchronize the TSC with the AP
*/
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 07471bba2dc6..41c5b2dc6200 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -440,8 +440,8 @@ static int time_init_device(void)
device_initcall(time_init_device);
-extern void (*late_time_init)(void);
#ifdef CONFIG_HPET_TIMER
+extern void (*late_time_init)(void);
/* Duplicate of time_init() below, with hpet_enable part added */
static void __init hpet_time_init(void)
{
@@ -458,11 +458,6 @@ static void __init hpet_time_init(void)
printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
time_init_hook();
-
-#ifdef CONFIG_X86_LOCAL_APIC
- if (enable_local_apic >= 0)
- APIC_late_time_init();
-#endif
}
#endif
@@ -487,9 +482,4 @@ void __init time_init(void)
printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
time_init_hook();
-
-#ifdef CONFIG_X86_LOCAL_APIC
- if (enable_local_apic >= 0)
- late_time_init = APIC_late_time_init;
-#endif
}
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index a515e2aed829..8c454aa58ac6 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -118,8 +118,7 @@ extern void release_lapic_nmi(void);
extern void disable_timer_nmi_watchdog(void);
extern void enable_timer_nmi_watchdog(void);
extern void nmi_watchdog_tick (struct pt_regs * regs);
-extern int APIC_init(void);
-extern void APIC_late_time_init(void);
+extern int APIC_init_uniprocessor (void);
extern void disable_APIC_timer(void);
extern void enable_APIC_timer(void);
diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
index 9139b89497a1..622815bf3243 100644
--- a/include/asm-i386/hw_irq.h
+++ b/include/asm-i386/hw_irq.h
@@ -55,7 +55,6 @@ void init_8259A(int aeoi);
void FASTCALL(send_IPI_self(int vector));
void init_VISWS_APIC_irqs(void);
void setup_IO_APIC(void);
-void IO_APIC_late_time_init(void);
void disable_IO_APIC(void);
void print_IO_APIC(void);
int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
diff --git a/include/asm-i386/mach-default/smpboot_hooks.h b/include/asm-i386/mach-default/smpboot_hooks.h
index d7c70c144f9f..7f45f6311059 100644
--- a/include/asm-i386/mach-default/smpboot_hooks.h
+++ b/include/asm-i386/mach-default/smpboot_hooks.h
@@ -1,6 +1,11 @@
/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
* which needs to alter them. */
+static inline void smpboot_clear_io_apic_irqs(void)
+{
+ io_apic_irqs = 0;
+}
+
static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
{
CMOS_WRITE(0xa, 0xf);
@@ -27,3 +32,13 @@ static inline void smpboot_restore_warm_reset_vector(void)
*((volatile long *) phys_to_virt(0x467)) = 0;
}
+
+static inline void smpboot_setup_io_apic(void)
+{
+ /*
+ * Here we can be sure that there is an IO-APIC in the system. Let's
+ * go and set it up:
+ */
+ if (!skip_ioapic_setup && nr_ioapics)
+ setup_IO_APIC();
+}
diff --git a/include/asm-i386/mach-visws/smpboot_hooks.h b/include/asm-i386/mach-visws/smpboot_hooks.h
index 14d8e0375f7a..d926471fa359 100644
--- a/include/asm-i386/mach-visws/smpboot_hooks.h
+++ b/include/asm-i386/mach-visws/smpboot_hooks.h
@@ -11,7 +11,14 @@ static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
/* for visws do nothing for any of these */
+static inline void smpboot_clear_io_apic_irqs(void)
+{
+}
+
static inline void smpboot_restore_warm_reset_vector(void)
{
}
+static inline void smpboot_setup_io_apic(void)
+{
+}
diff --git a/init/main.c b/init/main.c
index 4075d97e94b1..f142d4035341 100644
--- a/init/main.c
+++ b/init/main.c
@@ -64,6 +64,10 @@
#endif
#endif
+#ifdef CONFIG_X86_LOCAL_APIC
+#include <asm/smp.h>
+#endif
+
/*
* Versions of gcc older than that listed below may actually compile
* and link okay, but the end product can have subtle run time bugs.
@@ -310,7 +314,14 @@ extern void setup_arch(char **);
#ifndef CONFIG_SMP
+#ifdef CONFIG_X86_LOCAL_APIC
+static void __init smp_init(void)
+{
+ APIC_init_uniprocessor();
+}
+#else
#define smp_init() do { } while (0)
+#endif
static inline void setup_per_cpu_areas(void) { }
static inline void smp_prepare_cpus(unsigned int maxcpus) { }
OpenPOWER on IntegriCloud