Commit 453c1404 authored by Ingo Molnar's avatar Ingo Molnar

Merge branch 'x86/apic' into x86/x2apic

Conflicts:

	arch/x86/kernel/paravirt.c
	arch/x86/kernel/smpboot.c
	arch/x86/kernel/vmi_32.c
	arch/x86/lguest/boot.c
	arch/x86/xen/enlighten.c
	include/asm-x86/apic.h
	include/asm-x86/paravirt.h
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parents a208f37a 35b68055
...@@ -362,10 +362,6 @@ config X86_ALIGNMENT_16 ...@@ -362,10 +362,6 @@ config X86_ALIGNMENT_16
def_bool y def_bool y
depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
config X86_GOOD_APIC
def_bool y
depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 || MVIAC7 || X86_64
config X86_INTEL_USERCOPY config X86_INTEL_USERCOPY
def_bool y def_bool y
depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2 depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2
......
This diff is collapsed.
...@@ -61,7 +61,7 @@ EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); ...@@ -61,7 +61,7 @@ EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
/* /*
* Debug level, exported for io_apic.c * Debug level, exported for io_apic.c
*/ */
int apic_verbosity; unsigned int apic_verbosity;
/* Have we found an MP table */ /* Have we found an MP table */
int smp_found_config; int smp_found_config;
...@@ -386,7 +386,7 @@ static void setup_APIC_timer(void) ...@@ -386,7 +386,7 @@ static void setup_APIC_timer(void)
#define TICK_COUNT 100000000 #define TICK_COUNT 100000000
static void __init calibrate_APIC_clock(void) static int __init calibrate_APIC_clock(void)
{ {
unsigned apic, apic_start; unsigned apic, apic_start;
unsigned long tsc, tsc_start; unsigned long tsc, tsc_start;
...@@ -440,6 +440,17 @@ static void __init calibrate_APIC_clock(void) ...@@ -440,6 +440,17 @@ static void __init calibrate_APIC_clock(void)
clockevent_delta2ns(0xF, &lapic_clockevent); clockevent_delta2ns(0xF, &lapic_clockevent);
calibration_result = result / HZ; calibration_result = result / HZ;
/*
* Do a sanity check on the APIC calibration result
*/
if (calibration_result < (1000000 / HZ)) {
printk(KERN_WARNING
"APIC frequency too slow, disabling apic timer\n");
return -1;
}
return 0;
} }
/* /*
...@@ -466,14 +477,7 @@ void __init setup_boot_APIC_clock(void) ...@@ -466,14 +477,7 @@ void __init setup_boot_APIC_clock(void)
} }
printk(KERN_INFO "Using local APIC timer interrupts.\n"); printk(KERN_INFO "Using local APIC timer interrupts.\n");
calibrate_APIC_clock(); if (calibrate_APIC_clock()) {
/*
* Do a sanity check on the APIC calibration result
*/
if (calibration_result < (1000000 / HZ)) {
printk(KERN_WARNING
"APIC frequency too slow, disabling apic timer\n");
/* No broadcast on UP ! */ /* No broadcast on UP ! */
if (num_possible_cpus() > 1) if (num_possible_cpus() > 1)
setup_APIC_timer(); setup_APIC_timer();
......
...@@ -131,13 +131,7 @@ static void __init check_popad(void) ...@@ -131,13 +131,7 @@ static void __init check_popad(void)
* (for due to lack of "invlpg" and working WP on a i386) * (for due to lack of "invlpg" and working WP on a i386)
* - In order to run on anything without a TSC, we need to be * - In order to run on anything without a TSC, we need to be
* compiled for a i486. * compiled for a i486.
* - In order to support the local APIC on a buggy Pentium machine, */
* we need to be compiled with CONFIG_X86_GOOD_APIC disabled,
* which happens implicitly if compiled for a Pentium or lower
* (unless an advanced selection of CPU features is used) as an
* otherwise config implies a properly working local APIC without
* the need to do extra reads from the APIC.
*/
static void __init check_config(void) static void __init check_config(void)
{ {
...@@ -151,21 +145,6 @@ static void __init check_config(void) ...@@ -151,21 +145,6 @@ static void __init check_config(void)
if (boot_cpu_data.x86 == 3) if (boot_cpu_data.x86 == 3)
panic("Kernel requires i486+ for 'invlpg' and other features"); panic("Kernel requires i486+ for 'invlpg' and other features");
#endif #endif
/*
* If we were told we had a good local APIC, check for buggy Pentia,
* i.e. all B steppings and the C2 stepping of P54C when using their
* integrated APIC (see 11AP erratum in "Pentium Processor
* Specification Update").
*/
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_GOOD_APIC)
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
&& cpu_has_apic
&& boot_cpu_data.x86 == 5
&& boot_cpu_data.x86_model == 2
&& (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11))
panic("Kernel compiled for PMMX+, assumes a local APIC without the read-before-write bug!");
#endif
} }
......
...@@ -227,6 +227,16 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) ...@@ -227,6 +227,16 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
if (cpu_has_bts) if (cpu_has_bts)
ds_init_intel(c); ds_init_intel(c);
/*
* See if we have a good local APIC by checking for buggy Pentia,
* i.e. all B steppings and the C2 stepping of P54C when using their
* integrated APIC (see 11AP erratum in "Pentium Processor
* Specification Update").
*/
if (cpu_has_apic && (c->x86<<8 | c->x86_model<<4) == 0x520 &&
(c->x86_mask < 0x6 || c->x86_mask == 0xb))
set_cpu_cap(c, X86_FEATURE_11AP);
#ifdef CONFIG_X86_NUMAQ #ifdef CONFIG_X86_NUMAQ
numaq_tsc_disable(); numaq_tsc_disable();
#endif #endif
......
...@@ -102,7 +102,7 @@ static void intel_init_thermal(struct cpuinfo_x86 *c) ...@@ -102,7 +102,7 @@ static void intel_init_thermal(struct cpuinfo_x86 *c)
/* The temperature transition interrupt handler setup */ /* The temperature transition interrupt handler setup */
h = THERMAL_APIC_VECTOR; /* our delivery vector */ h = THERMAL_APIC_VECTOR; /* our delivery vector */
h |= (APIC_DM_FIXED | APIC_LVT_MASKED); /* we'll mask till we're ready */ h |= (APIC_DM_FIXED | APIC_LVT_MASKED); /* we'll mask till we're ready */
apic_write_around(APIC_LVTTHMR, h); apic_write(APIC_LVTTHMR, h);
rdmsr(MSR_IA32_THERM_INTERRUPT, l, h); rdmsr(MSR_IA32_THERM_INTERRUPT, l, h);
wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03 , h); wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03 , h);
...@@ -114,7 +114,7 @@ static void intel_init_thermal(struct cpuinfo_x86 *c) ...@@ -114,7 +114,7 @@ static void intel_init_thermal(struct cpuinfo_x86 *c)
wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h); wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h);
l = apic_read(APIC_LVTTHMR); l = apic_read(APIC_LVTTHMR);
apic_write_around(APIC_LVTTHMR, l & ~APIC_LVT_MASKED); apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
printk(KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu); printk(KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu);
/* enable thermal throttle processing */ /* enable thermal throttle processing */
......
...@@ -756,7 +756,7 @@ void send_IPI_self(int vector) ...@@ -756,7 +756,7 @@ void send_IPI_self(int vector)
/* /*
* Send the IPI. The write to APIC_ICR fires this off. * Send the IPI. The write to APIC_ICR fires this off.
*/ */
apic_write_around(APIC_ICR, cfg); apic_write(APIC_ICR, cfg);
} }
#endif /* !CONFIG_SMP */ #endif /* !CONFIG_SMP */
...@@ -2029,7 +2029,7 @@ static void mask_lapic_irq(unsigned int irq) ...@@ -2029,7 +2029,7 @@ static void mask_lapic_irq(unsigned int irq)
unsigned long v; unsigned long v;
v = apic_read(APIC_LVT0); v = apic_read(APIC_LVT0);
apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED); apic_write(APIC_LVT0, v | APIC_LVT_MASKED);
} }
static void unmask_lapic_irq(unsigned int irq) static void unmask_lapic_irq(unsigned int irq)
...@@ -2037,7 +2037,7 @@ static void unmask_lapic_irq(unsigned int irq) ...@@ -2037,7 +2037,7 @@ static void unmask_lapic_irq(unsigned int irq)
unsigned long v; unsigned long v;
v = apic_read(APIC_LVT0); v = apic_read(APIC_LVT0);
apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED); apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
} }
static struct irq_chip lapic_chip __read_mostly = { static struct irq_chip lapic_chip __read_mostly = {
...@@ -2167,7 +2167,7 @@ static inline void __init check_timer(void) ...@@ -2167,7 +2167,7 @@ static inline void __init check_timer(void)
* The AEOI mode will finish them in the 8259A * The AEOI mode will finish them in the 8259A
* automatically. * automatically.
*/ */
apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
init_8259A(1); init_8259A(1);
timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver)); timer_ack = (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver));
...@@ -2176,8 +2176,9 @@ static inline void __init check_timer(void) ...@@ -2176,8 +2176,9 @@ static inline void __init check_timer(void)
pin2 = ioapic_i8259.pin; pin2 = ioapic_i8259.pin;
apic2 = ioapic_i8259.apic; apic2 = ioapic_i8259.apic;
printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
vector, apic1, pin1, apic2, pin2); "apic1=%d pin1=%d apic2=%d pin2=%d\n",
vector, apic1, pin1, apic2, pin2);
/* /*
* Some BIOS writers are clueless and report the ExtINTA * Some BIOS writers are clueless and report the ExtINTA
...@@ -2215,12 +2216,13 @@ static inline void __init check_timer(void) ...@@ -2215,12 +2216,13 @@ static inline void __init check_timer(void)
} }
clear_IO_APIC_pin(apic1, pin1); clear_IO_APIC_pin(apic1, pin1);
if (!no_pin1) if (!no_pin1)
printk(KERN_ERR "..MP-BIOS bug: " apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
"8254 timer not connected to IO-APIC\n"); "8254 timer not connected to IO-APIC\n");
printk(KERN_INFO "...trying to set up timer (IRQ0) " apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
"through the 8259A ... "); "(IRQ0) through the 8259A ...\n");
printk("\n..... (found pin %d) ...", pin2); apic_printk(APIC_QUIET, KERN_INFO
"..... (found apic %d pin %d) ...\n", apic2, pin2);
/* /*
* legacy devices should be connected to IO APIC #0 * legacy devices should be connected to IO APIC #0
*/ */
...@@ -2229,7 +2231,7 @@ static inline void __init check_timer(void) ...@@ -2229,7 +2231,7 @@ static inline void __init check_timer(void)
unmask_IO_APIC_irq(0); unmask_IO_APIC_irq(0);
enable_8259A_irq(0); enable_8259A_irq(0);
if (timer_irq_works()) { if (timer_irq_works()) {
printk("works.\n"); apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
timer_through_8259 = 1; timer_through_8259 = 1;
if (nmi_watchdog == NMI_IO_APIC) { if (nmi_watchdog == NMI_IO_APIC) {
disable_8259A_irq(0); disable_8259A_irq(0);
...@@ -2243,44 +2245,47 @@ static inline void __init check_timer(void) ...@@ -2243,44 +2245,47 @@ static inline void __init check_timer(void)
*/ */
disable_8259A_irq(0); disable_8259A_irq(0);
clear_IO_APIC_pin(apic2, pin2); clear_IO_APIC_pin(apic2, pin2);
printk(" failed.\n"); apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
} }
if (nmi_watchdog == NMI_IO_APIC) { if (nmi_watchdog == NMI_IO_APIC) {
printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
"through the IO-APIC - disabling NMI Watchdog!\n");
nmi_watchdog = NMI_NONE; nmi_watchdog = NMI_NONE;
} }
timer_ack = 0; timer_ack = 0;
printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); apic_printk(APIC_QUIET, KERN_INFO
"...trying to set up timer as Virtual Wire IRQ...\n");
lapic_register_intr(0, vector); lapic_register_intr(0, vector);
apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */ apic_write(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */
enable_8259A_irq(0); enable_8259A_irq(0);
if (timer_irq_works()) { if (timer_irq_works()) {
printk(" works.\n"); apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
goto out; goto out;
} }
disable_8259A_irq(0); disable_8259A_irq(0);
apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector); apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
printk(" failed.\n"); apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
printk(KERN_INFO "...trying to set up timer as ExtINT IRQ..."); apic_printk(APIC_QUIET, KERN_INFO
"...trying to set up timer as ExtINT IRQ...\n");
init_8259A(0); init_8259A(0);
make_8259A_irq(0); make_8259A_irq(0);
apic_write_around(APIC_LVT0, APIC_DM_EXTINT); apic_write(APIC_LVT0, APIC_DM_EXTINT);
unlock_ExtINT_logic(); unlock_ExtINT_logic();
if (timer_irq_works()) { if (timer_irq_works()) {
printk(" works.\n"); apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
goto out; goto out;
} }
printk(" failed :(.\n"); apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a " panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a "
"report. Then try booting with the 'noapic' option"); "report. Then try booting with the 'noapic' option.\n");
out: out:
local_irq_restore(flags); local_irq_restore(flags);
} }
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include <asm/proto.h> #include <asm/proto.h>
#include <asm/acpi.h> #include <asm/acpi.h>
#include <asm/dma.h> #include <asm/dma.h>
#include <asm/i8259.h>
#include <asm/nmi.h> #include <asm/nmi.h>
#include <asm/msidef.h> #include <asm/msidef.h>
#include <asm/hypertransport.h> #include <asm/hypertransport.h>
...@@ -2010,8 +2011,9 @@ static inline void __init check_timer(void) ...@@ -2010,8 +2011,9 @@ static inline void __init check_timer(void)
pin2 = ioapic_i8259.pin; pin2 = ioapic_i8259.pin;
apic2 = ioapic_i8259.apic; apic2 = ioapic_i8259.apic;
apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", apic_printk(APIC_QUIET, KERN_INFO "..TIMER: vector=0x%02X "
cfg->vector, apic1, pin1, apic2, pin2); "apic1=%d pin1=%d apic2=%d pin2=%d\n",
cfg->vector, apic1, pin1, apic2, pin2);
/* /*
* Some BIOS writers are clueless and report the ExtINTA * Some BIOS writers are clueless and report the ExtINTA
...@@ -2053,14 +2055,13 @@ static inline void __init check_timer(void) ...@@ -2053,14 +2055,13 @@ static inline void __init check_timer(void)
panic("timer doesn't work through Interrupt-remapped IO-APIC"); panic("timer doesn't work through Interrupt-remapped IO-APIC");
clear_IO_APIC_pin(apic1, pin1); clear_IO_APIC_pin(apic1, pin1);
if (!no_pin1) if (!no_pin1)
apic_printk(APIC_QUIET,KERN_ERR "..MP-BIOS bug: " apic_printk(APIC_QUIET, KERN_ERR "..MP-BIOS bug: "
"8254 timer not connected to IO-APIC\n"); "8254 timer not connected to IO-APIC\n");
apic_printk(APIC_VERBOSE,KERN_INFO apic_printk(APIC_QUIET, KERN_INFO "...trying to set up timer "
"...trying to set up timer (IRQ0) " "(IRQ0) through the 8259A ...\n");
"through the 8259A ... "); apic_printk(APIC_QUIET, KERN_INFO
apic_printk(APIC_VERBOSE,"\n..... (found apic %d pin %d) ...", "..... (found apic %d pin %d) ...\n", apic2, pin2);
apic2, pin2);
/* /*
* legacy devices should be connected to IO APIC #0 * legacy devices should be connected to IO APIC #0
*/ */
...@@ -2069,7 +2070,7 @@ static inline void __init check_timer(void) ...@@ -2069,7 +2070,7 @@ static inline void __init check_timer(void)
unmask_IO_APIC_irq(0); unmask_IO_APIC_irq(0);
enable_8259A_irq(0); enable_8259A_irq(0);
if (timer_irq_works()) { if (timer_irq_works()) {
apic_printk(APIC_VERBOSE," works.\n"); apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
timer_through_8259 = 1; timer_through_8259 = 1;
if (nmi_watchdog == NMI_IO_APIC) { if (nmi_watchdog == NMI_IO_APIC) {
disable_8259A_irq(0); disable_8259A_irq(0);
...@@ -2083,29 +2084,32 @@ static inline void __init check_timer(void) ...@@ -2083,29 +2084,32 @@ static inline void __init check_timer(void)
*/ */
disable_8259A_irq(0); disable_8259A_irq(0);
clear_IO_APIC_pin(apic2, pin2); clear_IO_APIC_pin(apic2, pin2);
apic_printk(APIC_VERBOSE," failed.\n"); apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
} }
if (nmi_watchdog == NMI_IO_APIC) { if (nmi_watchdog == NMI_IO_APIC) {
printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); apic_printk(APIC_QUIET, KERN_WARNING "timer doesn't work "
"through the IO-APIC - disabling NMI Watchdog!\n");
nmi_watchdog = NMI_NONE; nmi_watchdog = NMI_NONE;
} }
apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); apic_printk(APIC_QUIET, KERN_INFO
"...trying to set up timer as Virtual Wire IRQ...\n");
lapic_register_intr(0); lapic_register_intr(0);
apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */ apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */
enable_8259A_irq(0); enable_8259A_irq(0);
if (timer_irq_works()) { if (timer_irq_works()) {
apic_printk(APIC_VERBOSE," works.\n"); apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
goto out; goto out;
} }
disable_8259A_irq(0); disable_8259A_irq(0);
apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector); apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
apic_printk(APIC_VERBOSE," failed.\n"); apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ..."); apic_printk(APIC_QUIET, KERN_INFO
"...trying to set up timer as ExtINT IRQ...\n");
init_8259A(0); init_8259A(0);
make_8259A_irq(0); make_8259A_irq(0);
...@@ -2114,11 +2118,12 @@ static inline void __init check_timer(void) ...@@ -2114,11 +2118,12 @@ static inline void __init check_timer(void)
unlock_ExtINT_logic(); unlock_ExtINT_logic();
if (timer_irq_works()) { if (timer_irq_works()) {
apic_printk(APIC_VERBOSE," works.\n"); apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
goto out; goto out;
} }
apic_printk(APIC_VERBOSE," failed :(.\n"); apic_printk(APIC_QUIET, KERN_INFO "..... failed :(.\n");
panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n"); panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a "
"report. Then try booting with the 'noapic' option.\n");
out: out:
local_irq_restore(flags); local_irq_restore(flags);
} }
......
...@@ -70,7 +70,7 @@ void __send_IPI_shortcut(unsigned int shortcut, int vector) ...@@ -70,7 +70,7 @@ void __send_IPI_shortcut(unsigned int shortcut, int vector)
/* /*
* Send the IPI. The write to APIC_ICR fires this off. * Send the IPI. The write to APIC_ICR fires this off.
*/ */
apic_write_around(APIC_ICR, cfg); apic_write(APIC_ICR, cfg);
} }
void send_IPI_self(int vector) void send_IPI_self(int vector)
...@@ -98,7 +98,7 @@ static inline void __send_IPI_dest_field(unsigned long mask, int vector) ...@@ -98,7 +98,7 @@ static inline void __send_IPI_dest_field(unsigned long mask, int vector)
* prepare target chip field * prepare target chip field
*/ */
cfg = __prepare_ICR2(mask); cfg = __prepare_ICR2(mask);
apic_write_around(APIC_ICR2, cfg); apic_write(APIC_ICR2, cfg);
/* /*
* program the ICR * program the ICR
...@@ -108,7 +108,7 @@ static inline void __send_IPI_dest_field(unsigned long mask, int vector) ...@@ -108,7 +108,7 @@ static inline void __send_IPI_dest_field(unsigned long mask, int vector)
/* /*
* Send the IPI. The write to APIC_ICR fires this off. * Send the IPI. The write to APIC_ICR fires this off.
*/ */
apic_write_around(APIC_ICR, cfg); apic_write(APIC_ICR, cfg);
} }
/* /*
......
...@@ -263,7 +263,7 @@ late_initcall(init_lapic_nmi_sysfs); ...@@ -263,7 +263,7 @@ late_initcall(init_lapic_nmi_sysfs);
static void __acpi_nmi_enable(void *__unused) static void __acpi_nmi_enable(void *__unused)
{ {
apic_write_around(APIC_LVT0, APIC_DM_NMI); apic_write(APIC_LVT0, APIC_DM_NMI);
} }
/* /*
...@@ -277,7 +277,7 @@ void acpi_nmi_enable(void) ...@@ -277,7 +277,7 @@ void acpi_nmi_enable(void)
static void __acpi_nmi_disable(void *__unused) static void __acpi_nmi_disable(void *__unused)
{ {
apic_write_around(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED); apic_write(APIC_LVT0, APIC_DM_NMI | APIC_LVT_MASKED);
} }
/* /*
......
...@@ -590,14 +590,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) ...@@ -590,14 +590,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
* Give the other CPU some time to accept the IPI. * Give the other CPU some time to accept the IPI.
*/ */
udelay(200); udelay(200);
/*
* Due to the Pentium erratum 3AP.
*/
maxlvt = lapic_get_maxlvt(); maxlvt = lapic_get_maxlvt();
if (maxlvt > 3) { if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
apic_read_around(APIC_SPIV);
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
}
accept_status = (apic_read(APIC_ESR) & 0xEF); accept_status = (apic_read(APIC_ESR) & 0xEF);
Dprintk("NMI sent.\n"); Dprintk("NMI sent.\n");
...@@ -623,12 +618,14 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) ...@@ -623,12 +618,14 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
return send_status; return send_status;
} }
maxlvt = lapic_get_maxlvt();
/* /*
* Be paranoid about clearing APIC errors. * Be paranoid about clearing APIC errors.
*/ */
if (APIC_INTEGRATED(apic_version[phys_apicid])) { if (APIC_INTEGRATED(apic_version[phys_apicid])) {
apic_read_around(APIC_SPIV); if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
apic_read(APIC_ESR); apic_read(APIC_ESR);
} }
...@@ -683,12 +680,10 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) ...@@ -683,12 +680,10 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
*/ */
Dprintk("#startup loops: %d.\n", num_starts); Dprintk("#startup loops: %d.\n", num_starts);
maxlvt = lapic_get_maxlvt();
for (j = 1; j <= num_starts; j++) { for (j = 1; j <= num_starts; j++) {
Dprintk("Sending STARTUP #%d.\n", j); Dprintk("Sending STARTUP #%d.\n", j);
apic_read_around(APIC_SPIV); if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
apic_read(APIC_ESR); apic_read(APIC_ESR);
Dprintk("After apic_write.\n"); Dprintk("After apic_write.\n");
...@@ -716,13 +711,8 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) ...@@ -716,13 +711,8 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
* Give the other CPU some time to accept the IPI. * Give the other CPU some time to accept the IPI.
*/ */
udelay(200); udelay(200);
/* if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
* Due to the Pentium erratum 3AP.
*/
if (maxlvt > 3) {
apic_read_around(APIC_SPIV);
apic_write(APIC_ESR, 0); apic_write(APIC_ESR, 0);
}
accept_status = (apic_read(APIC_ESR) & 0xEF); accept_status = (apic_read(APIC_ESR) & 0xEF);
if (send_status || accept_status) if (send_status || accept_status)
break; break;
......
...@@ -906,7 +906,6 @@ static inline int __init activate_vmi(void) ...@@ -906,7 +906,6 @@ static inline int __init activate_vmi(void)
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
para_fill(apic_ops->read, APICRead); para_fill(apic_ops->read, APICRead);
para_fill(apic_ops->write, APICWrite); para_fill(apic_ops->write, APICWrite);
para_fill(apic_ops->write_atomic, APICWrite);
#endif #endif
/* /*
......
...@@ -816,7 +816,6 @@ static u32 lguest_apic_safe_wait_icr_idle(void) ...@@ -816,7 +816,6 @@ static u32 lguest_apic_safe_wait_icr_idle(void)
static struct apic_ops lguest_basic_apic_ops = { static struct apic_ops lguest_basic_apic_ops = {
.read = lguest_apic_read, .read = lguest_apic_read,
.write = lguest_apic_write, .write = lguest_apic_write,
.write_atomic = lguest_apic_write,
.icr_read = lguest_apic_icr_read, .icr_read = lguest_apic_icr_read,
.icr_write = lguest_apic_icr_write, .icr_write = lguest_apic_icr_write,
.wait_icr_idle = lguest_apic_wait_icr_idle, .wait_icr_idle = lguest_apic_wait_icr_idle,
......
...@@ -583,7 +583,6 @@ static u32 xen_safe_apic_wait_icr_idle(void) ...@@ -583,7 +583,6 @@ static u32 xen_safe_apic_wait_icr_idle(void)
static struct apic_ops xen_basic_apic_ops = { static struct apic_ops xen_basic_apic_ops = {
.read = xen_apic_read, .read = xen_apic_read,
.write = xen_apic_write, .write = xen_apic_write,
.write_atomic = xen_apic_write,
.icr_read = xen_apic_icr_read, .icr_read = xen_apic_icr_read,
.icr_write = xen_apic_icr_write, .icr_write = xen_apic_icr_write,
.wait_icr_idle = xen_apic_wait_icr_idle, .wait_icr_idle = xen_apic_wait_icr_idle,
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/alternative.h>
#include <asm/fixmap.h> #include <asm/fixmap.h>
#include <asm/apicdef.h> #include <asm/apicdef.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -12,7 +14,7 @@ ...@@ -12,7 +14,7 @@
#define ARCH_APICTIMER_STOPS_ON_C3 1 #define ARCH_APICTIMER_STOPS_ON_C3 1
#define Dprintk(x...) #define Dprintk printk
/* /*
* Debugging macros * Debugging macros
...@@ -37,7 +39,7 @@ extern void generic_apic_probe(void); ...@@ -37,7 +39,7 @@ extern void generic_apic_probe(void);
#ifdef CONFIG_X86_LOCAL_APIC #ifdef CONFIG_X86_LOCAL_APIC
extern int apic_verbosity; extern unsigned int apic_verbosity;
extern int local_apic_timer_c2_ok; extern int local_apic_timer_c2_ok;
extern int ioapic_force; extern int ioapic_force;
...@@ -57,12 +59,11 @@ extern int is_vsmp_box(void); ...@@ -57,12 +59,11 @@ extern int is_vsmp_box(void);
static inline void native_apic_mem_write(u32 reg, u32 v) static inline void native_apic_mem_write(u32 reg, u32 v)
{ {
*((volatile u32 *)(APIC_BASE + reg)) = v; volatile u32 *addr = (volatile u32 *)(APIC_BASE + reg);
}
static inline void native_apic_mem_write_atomic(u32 reg, u32 v) alternative_io("movl %0, %1", "xchgl %0, %1", X86_FEATURE_11AP,
{ ASM_OUTPUT2("=r" (v), "=m" (*addr)),
(void)xchg((u32 *)(APIC_BASE + reg), v); ASM_OUTPUT2("0" (v), "m" (*addr)));
} }
static inline u32 native_apic_mem_read(u32 reg) static inline u32 native_apic_mem_read(u32 reg)
...@@ -101,7 +102,6 @@ extern void x2apic_icr_write(u32 low, u32 id); ...@@ -101,7 +102,6 @@ extern void x2apic_icr_write(u32 low, u32 id);
struct apic_ops { struct apic_ops {
u32 (*read)(u32 reg); u32 (*read)(u32 reg);
void (*write)(u32 reg, u32 v); void (*write)(u32 reg, u32 v);
void (*write_atomic)(u32 reg, u32 v);
u64 (*icr_read)(void); u64 (*icr_read)(void);
void (*icr_write)(u32 low, u32 high); void (*icr_write)(u32 low, u32 high);
void (*wait_icr_idle)(void); void (*wait_icr_idle)(void);
...@@ -112,7 +112,6 @@ extern struct apic_ops *apic_ops; ...@@ -112,7 +112,6 @@ extern struct apic_ops *apic_ops;
#define apic_read (apic_ops->read) #define apic_read (apic_ops->read)
#define apic_write (apic_ops->write) #define apic_write (apic_ops->write)
#define apic_write_atomic (apic_ops->write_atomic)
#define apic_icr_read (apic_ops->icr_read) #define apic_icr_read (apic_ops->icr_read)
#define apic_icr_write (apic_ops->icr_write) #define apic_icr_write (apic_ops->icr_write)
#define apic_wait_icr_idle (apic_ops->wait_icr_idle) #define apic_wait_icr_idle (apic_ops->wait_icr_idle)
...@@ -120,16 +119,6 @@ extern struct apic_ops *apic_ops; ...@@ -120,16 +119,6 @@ extern struct apic_ops *apic_ops;
extern int get_physical_broadcast(void); extern int get_physical_broadcast(void);
#ifdef CONFIG_X86_GOOD_APIC
# define FORCE_READ_AROUND_WRITE 0
# define apic_read_around(x)
# define apic_write_around(x, y) apic_write((x), (y))
#else
# define FORCE_READ_AROUND_WRITE 1
# define apic_read_around(x) apic_read(x)
# define apic_write_around(x, y) apic_write_atomic((x), (y))
#endif
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
static inline void ack_x2APIC_irq(void) static inline void ack_x2APIC_irq(void)
{ {
...@@ -150,7 +139,7 @@ static inline void ack_APIC_irq(void) ...@@ -150,7 +139,7 @@ static inline void ack_APIC_irq(void)
/* Docs say use 0 for future compatibility */ /* Docs say use 0 for future compatibility */
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
apic_write_around(APIC_EOI, 0); apic_write(APIC_EOI, 0);
#else #else
native_apic_mem_write(APIC_EOI, 0); native_apic_mem_write(APIC_EOI, 0);
#endif #endif
......
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */ #define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */
#define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* Mfence synchronizes RDTSC */ #define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* Mfence synchronizes RDTSC */
#define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */ #define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */
#define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ #define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */
......
...@@ -63,9 +63,9 @@ static inline void init_apic_ldr(void) ...@@ -63,9 +63,9 @@ static inline void init_apic_ldr(void)
unsigned long val; unsigned long val;
int cpu = smp_processor_id(); int cpu = smp_processor_id();
apic_write_around(APIC_DFR, APIC_DFR_VALUE); apic_write(APIC_DFR, APIC_DFR_VALUE);
val = calculate_ldr(cpu); val = calculate_ldr(cpu);
apic_write_around(APIC_LDR, val); apic_write(APIC_LDR, val);
} }
static inline void setup_apic_routing(void) static inline void setup_apic_routing(void)
......
...@@ -48,10 +48,10 @@ static inline void init_apic_ldr(void) ...@@ -48,10 +48,10 @@ static inline void init_apic_ldr(void)
{ {
unsigned long val; unsigned long val;
apic_write_around(APIC_DFR, APIC_DFR_VALUE); apic_write(APIC_DFR, APIC_DFR_VALUE);
val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id()); val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
apic_write_around(APIC_LDR, val); apic_write(APIC_LDR, val);
} }
static inline int apic_id_registered(void) static inline int apic_id_registered(void)
......
...@@ -66,9 +66,9 @@ static inline void init_apic_ldr(void) ...@@ -66,9 +66,9 @@ static inline void init_apic_ldr(void)
unsigned long val; unsigned long val;
int cpu = smp_processor_id(); int cpu = smp_processor_id();
apic_write_around(APIC_DFR, APIC_DFR_VALUE); apic_write(APIC_DFR, APIC_DFR_VALUE);
val = calculate_ldr(cpu); val = calculate_ldr(cpu);
apic_write_around(APIC_LDR, val); apic_write(APIC_LDR, val);
} }
#ifndef CONFIG_X86_GENERICARCH #ifndef CONFIG_X86_GENERICARCH
......
...@@ -63,10 +63,10 @@ static inline void init_apic_ldr(void) ...@@ -63,10 +63,10 @@ static inline void init_apic_ldr(void)
* BIOS puts 5 CPUs in one APIC cluster, we're hosed. */ * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */
BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT); BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT);
id = my_cluster | (1UL << count); id = my_cluster | (1UL << count);
apic_write_around(APIC_DFR, APIC_DFR_VALUE); apic_write(APIC_DFR, APIC_DFR_VALUE);
val = apic_read(APIC_LDR) & ~APIC_LDR_MASK; val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
val |= SET_APIC_LOGICAL_ID(id); val |= SET_APIC_LOGICAL_ID(id);
apic_write_around(APIC_LDR, val); apic_write(APIC_LDR, val);
} }
static inline int multi_timer_check(int apic, int irq) static inline int multi_timer_check(int apic, int irq)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment