patch-2.4.23 linux-2.4.23/arch/i386/kernel/apic.c
Next file: linux-2.4.23/arch/i386/kernel/dmi_scan.c
Previous file: linux-2.4.23/arch/i386/kernel/acpitable.h
Back to the patch index
Back to the overall index
- Lines: 153
- Date:
2003-11-28 10:26:19.000000000 -0800
- Orig file:
linux-2.4.22/arch/i386/kernel/apic.c
- Orig date:
2003-06-13 07:51:29.000000000 -0700
diff -urN linux-2.4.22/arch/i386/kernel/apic.c linux-2.4.23/arch/i386/kernel/apic.c
@@ -38,6 +38,8 @@
int prof_old_multiplier[NR_CPUS] = { 1, };
int prof_counter[NR_CPUS] = { 1, };
+static int enabled_via_apicbase;
+
int get_maxlvt(void)
{
unsigned int v, ver, maxlvt;
@@ -142,6 +144,13 @@
value = apic_read(APIC_SPIV);
value &= ~APIC_SPIV_APIC_ENABLED;
apic_write_around(APIC_SPIV, value);
+
+ if (enabled_via_apicbase) {
+ unsigned int l, h;
+ rdmsr(MSR_IA32_APICBASE, l, h);
+ l &= ~MSR_IA32_APICBASE_ENABLE;
+ wrmsr(MSR_IA32_APICBASE, l, h);
+ }
}
/*
@@ -464,7 +473,6 @@
static void apic_pm_suspend(void *data)
{
- unsigned int l, h;
unsigned long flags;
if (apic_pm_state.perfctr_pmdev)
@@ -484,9 +492,6 @@
__save_flags(flags);
__cli();
disable_local_APIC();
- rdmsr(MSR_IA32_APICBASE, l, h);
- l &= ~MSR_IA32_APICBASE_ENABLE;
- wrmsr(MSR_IA32_APICBASE, l, h);
__restore_flags(flags);
}
@@ -497,10 +502,18 @@
__save_flags(flags);
__cli();
+
+ /*
+ * Make sure the APICBASE points to the right address
+ *
+ * FIXME! This will be wrong if we ever support suspend on
+ * SMP! We'll need to do this as part of the CPU restore!
+ */
rdmsr(MSR_IA32_APICBASE, l, h);
l &= ~MSR_IA32_APICBASE_BASE;
- l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+ l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
wrmsr(MSR_IA32_APICBASE, l, h);
+
apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
apic_write(APIC_ID, apic_pm_state.apic_id);
apic_write(APIC_DFR, apic_pm_state.apic_dfr);
@@ -593,7 +606,26 @@
* Detect and enable local APICs on non-SMP boards.
* Original code written by Keir Fraser.
*/
-int dont_enable_local_apic __initdata = 0;
+
+/*
+ * Knob to control our willingness to enable the local APIC.
+ */
+int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
+
+static int __init lapic_disable(char *str)
+{
+ enable_local_apic = -1;
+ clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+ return 0;
+}
+__setup("nolapic", lapic_disable);
+
+static int __init lapic_enable(char *str)
+{
+ enable_local_apic = 1;
+ return 0;
+}
+__setup("lapic", lapic_enable);
static int __init detect_init_APIC (void)
{
@@ -601,7 +633,7 @@
extern void get_cpu_vendor(struct cpuinfo_x86*);
/* Disabled by DMI scan or kernel option? */
- if (dont_enable_local_apic)
+ if (enable_local_apic < 0)
return -1;
/* Workaround for us being called before identify_cpu(). */
@@ -616,7 +648,7 @@
goto no_apic;
case X86_VENDOR_INTEL:
if (boot_cpu_data.x86 == 6 ||
- (boot_cpu_data.x86 == 15 && cpu_has_apic) ||
+ (boot_cpu_data.x86 == 15 && (cpu_has_apic || enable_local_apic > 0)) ||
(boot_cpu_data.x86 == 5 && cpu_has_apic))
break;
goto no_apic;
@@ -636,6 +668,7 @@
l &= ~MSR_IA32_APICBASE_BASE;
l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
wrmsr(MSR_IA32_APICBASE, l, h);
+ enabled_via_apicbase = 1;
}
}
/*
@@ -649,6 +682,12 @@
}
set_bit(X86_FEATURE_APIC, &boot_cpu_data.x86_capability);
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+
+ /* The BIOS may have set up the APIC at some other address */
+ rdmsr(MSR_IA32_APICBASE, l, h);
+ if (l & MSR_IA32_APICBASE_ENABLE)
+ mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
+
if (nmi_watchdog != NMI_NONE)
nmi_watchdog = NMI_LOCAL_APIC;
@@ -928,14 +967,8 @@
static unsigned int calibration_result;
-int dont_use_local_apic_timer __initdata = 0;
-
void __init setup_APIC_clocks (void)
{
- /* Disabled by DMI scan or kernel option? */
- if (dont_use_local_apic_timer)
- return;
-
printk("Using local APIC timer interrupts.\n");
using_apic_timer = 1;
@@ -1152,6 +1185,9 @@
*/
int __init APIC_init_uniprocessor (void)
{
+ if (enable_local_apic < 0)
+ clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+
if (!smp_found_config && !cpu_has_apic)
return -1;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)