aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt2
-rw-r--r--arch/x86/kernel/acpi/boot.c2
-rw-r--r--arch/x86/kernel/apic_64.c154
-rw-r--r--arch/x86/kernel/cpu/common_64.c2
-rw-r--r--arch/x86/kernel/genapic_64.c1
-rw-r--r--arch/x86/kernel/mpparse.c2
-rw-r--r--arch/x86/kernel/setup.c2
-rw-r--r--arch/x86/kernel/smpboot.c5
-rw-r--r--include/asm-x86/apic.h5
9 files changed, 171 insertions, 4 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 795c487af8e4..56689ef1a159 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1377,6 +1377,8 @@ and is between 256 and 4096 characters. It is defined in the file
1377 1377
1378 nolapic_timer [X86-32,APIC] Do not use the local APIC timer. 1378 nolapic_timer [X86-32,APIC] Do not use the local APIC timer.
1379 1379
1380 nox2apic [X86-64,APIC] Do not enable x2APIC mode.
1381
1380 noltlbs [PPC] Do not use large page/tlb entries for kernel 1382 noltlbs [PPC] Do not use large page/tlb entries for kernel
1381 lowmem mapping on PPC40x. 1383 lowmem mapping on PPC40x.
1382 1384
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 785700a08e9d..8705262ddcda 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -1337,7 +1337,9 @@ static void __init acpi_process_madt(void)
1337 acpi_ioapic = 1; 1337 acpi_ioapic = 1;
1338 1338
1339 smp_found_config = 1; 1339 smp_found_config = 1;
1340#ifdef CONFIG_X86_32
1340 setup_apic_routing(); 1341 setup_apic_routing();
1342#endif
1341 } 1343 }
1342 } 1344 }
1343 if (error == -EINVAL) { 1345 if (error == -EINVAL) {
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c
index d5c06917b5b1..dd0501039f09 100644
--- a/arch/x86/kernel/apic_64.c
+++ b/arch/x86/kernel/apic_64.c
@@ -27,6 +27,7 @@
27#include <linux/clockchips.h> 27#include <linux/clockchips.h>
28#include <linux/acpi_pmtmr.h> 28#include <linux/acpi_pmtmr.h>
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/dmar.h>
30 31
31#include <asm/atomic.h> 32#include <asm/atomic.h>
32#include <asm/smp.h> 33#include <asm/smp.h>
@@ -39,6 +40,7 @@
39#include <asm/proto.h> 40#include <asm/proto.h>
40#include <asm/timex.h> 41#include <asm/timex.h>
41#include <asm/apic.h> 42#include <asm/apic.h>
43#include <asm/i8259.h>
42 44
43#include <mach_ipi.h> 45#include <mach_ipi.h>
44#include <mach_apic.h> 46#include <mach_apic.h>
@@ -46,8 +48,12 @@
46static int disable_apic_timer __cpuinitdata; 48static int disable_apic_timer __cpuinitdata;
47static int apic_calibrate_pmtmr __initdata; 49static int apic_calibrate_pmtmr __initdata;
48int disable_apic; 50int disable_apic;
51int disable_x2apic;
49int x2apic; 52int x2apic;
50 53
54/* x2apic enabled before OS handover */
55int x2apic_preenabled;
56
51/* Local APIC timer works in C2 */ 57/* Local APIC timer works in C2 */
52int local_apic_timer_c2_ok; 58int local_apic_timer_c2_ok;
53EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); 59EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
@@ -896,6 +902,125 @@ void __cpuinit end_local_APIC_setup(void)
896 apic_pm_activate(); 902 apic_pm_activate();
897} 903}
898 904
905void check_x2apic(void)
906{
907 int msr, msr2;
908
909 rdmsr(MSR_IA32_APICBASE, msr, msr2);
910
911 if (msr & X2APIC_ENABLE) {
912 printk("x2apic enabled by BIOS, switching to x2apic ops\n");
913 x2apic_preenabled = x2apic = 1;
914 apic_ops = &x2apic_ops;
915 }
916}
917
918void enable_x2apic(void)
919{
920 int msr, msr2;
921
922 rdmsr(MSR_IA32_APICBASE, msr, msr2);
923 if (!(msr & X2APIC_ENABLE)) {
924 printk("Enabling x2apic\n");
925 wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
926 }
927}
928
929void enable_IR_x2apic(void)
930{
931#ifdef CONFIG_INTR_REMAP
932 int ret;
933 unsigned long flags;
934
935 if (!cpu_has_x2apic)
936 return;
937
938 if (!x2apic_preenabled && disable_x2apic) {
939 printk(KERN_INFO
940 "Skipped enabling x2apic and Interrupt-remapping "
941 "because of nox2apic\n");
942 return;
943 }
944
945 if (x2apic_preenabled && disable_x2apic)
946 panic("Bios already enabled x2apic, can't enforce nox2apic");
947
948 if (!x2apic_preenabled && skip_ioapic_setup) {
949 printk(KERN_INFO
950 "Skipped enabling x2apic and Interrupt-remapping "
951 "because of skipping io-apic setup\n");
952 return;
953 }
954
955 ret = dmar_table_init();
956 if (ret) {
957 printk(KERN_INFO
958 "dmar_table_init() failed with %d:\n", ret);
959
960 if (x2apic_preenabled)
961 panic("x2apic enabled by bios. But IR enabling failed");
962 else
963 printk(KERN_INFO
964 "Not enabling x2apic,Intr-remapping\n");
965 return;
966 }
967
968 local_irq_save(flags);
969 mask_8259A();
970 save_mask_IO_APIC_setup();
971
972 ret = enable_intr_remapping(1);
973
974 if (ret && x2apic_preenabled) {
975 local_irq_restore(flags);
976 panic("x2apic enabled by bios. But IR enabling failed");
977 }
978
979 if (ret)
980 goto end;
981
982 if (!x2apic) {
983 x2apic = 1;
984 apic_ops = &x2apic_ops;
985 enable_x2apic();
986 }
987end:
988 if (ret)
989 /*
990 * IR enabling failed
991 */
992 restore_IO_APIC_setup();
993 else
994 reinit_intr_remapped_IO_APIC(x2apic_preenabled);
995
996 unmask_8259A();
997 local_irq_restore(flags);
998
999 if (!ret) {
1000 if (!x2apic_preenabled)
1001 printk(KERN_INFO
1002 "Enabled x2apic and interrupt-remapping\n");
1003 else
1004 printk(KERN_INFO
1005 "Enabled Interrupt-remapping\n");
1006 } else
1007 printk(KERN_ERR
1008 "Failed to enable Interrupt-remapping and x2apic\n");
1009#else
1010 if (!cpu_has_x2apic)
1011 return;
1012
1013 if (x2apic_preenabled)
1014 panic("x2apic enabled prior OS handover,"
1015 " enable CONFIG_INTR_REMAP");
1016
1017 printk(KERN_INFO "Enable CONFIG_INTR_REMAP for enabling intr-remapping "
1018 " and x2apic\n");
1019#endif
1020
1021 return;
1022}
1023
899/* 1024/*
900 * Detect and enable local APICs on non-SMP boards. 1025 * Detect and enable local APICs on non-SMP boards.
901 * Original code written by Keir Fraser. 1026 * Original code written by Keir Fraser.
@@ -943,6 +1068,11 @@ void __init early_init_lapic_mapping(void)
943 */ 1068 */
944void __init init_apic_mappings(void) 1069void __init init_apic_mappings(void)
945{ 1070{
1071 if (x2apic) {
1072 boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id());
1073 return;
1074 }
1075
946 /* 1076 /*
947 * If no local APIC can be found then set up a fake all 1077 * If no local APIC can be found then set up a fake all
948 * zeroes page to simulate the local APIC and another 1078 * zeroes page to simulate the local APIC and another
@@ -981,6 +1111,9 @@ int __init APIC_init_uniprocessor(void)
981 return -1; 1111 return -1;
982 } 1112 }
983 1113
1114 enable_IR_x2apic();
1115 setup_apic_routing();
1116
984 verify_local_APIC(); 1117 verify_local_APIC();
985 1118
986 connect_bsp_APIC(); 1119 connect_bsp_APIC();
@@ -1238,10 +1371,14 @@ static int lapic_resume(struct sys_device *dev)
1238 maxlvt = lapic_get_maxlvt(); 1371 maxlvt = lapic_get_maxlvt();
1239 1372
1240 local_irq_save(flags); 1373 local_irq_save(flags);
1241 rdmsr(MSR_IA32_APICBASE, l, h); 1374 if (!x2apic) {
1242 l &= ~MSR_IA32_APICBASE_BASE; 1375 rdmsr(MSR_IA32_APICBASE, l, h);
1243 l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; 1376 l &= ~MSR_IA32_APICBASE_BASE;
1244 wrmsr(MSR_IA32_APICBASE, l, h); 1377 l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
1378 wrmsr(MSR_IA32_APICBASE, l, h);
1379 } else
1380 enable_x2apic();
1381
1245 apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED); 1382 apic_write(APIC_LVTERR, ERROR_APIC_VECTOR | APIC_LVT_MASKED);
1246 apic_write(APIC_ID, apic_pm_state.apic_id); 1383 apic_write(APIC_ID, apic_pm_state.apic_id);
1247 apic_write(APIC_DFR, apic_pm_state.apic_dfr); 1384 apic_write(APIC_DFR, apic_pm_state.apic_dfr);
@@ -1381,6 +1518,15 @@ __cpuinit int apic_is_clustered_box(void)
1381 return (clusters > 2); 1518 return (clusters > 2);
1382} 1519}
1383 1520
1521static __init int setup_nox2apic(char *str)
1522{
1523 disable_x2apic = 1;
1524 clear_cpu_cap(&boot_cpu_data, X86_FEATURE_X2APIC);
1525 return 0;
1526}
1527early_param("nox2apic", setup_nox2apic);
1528
1529
1384/* 1530/*
1385 * APIC command line parameters 1531 * APIC command line parameters
1386 */ 1532 */
diff --git a/arch/x86/kernel/cpu/common_64.c b/arch/x86/kernel/cpu/common_64.c
index 36537ab9e56a..e7bf3c2dc5fe 100644
--- a/arch/x86/kernel/cpu/common_64.c
+++ b/arch/x86/kernel/cpu/common_64.c
@@ -606,6 +606,8 @@ void __cpuinit cpu_init(void)
606 barrier(); 606 barrier();
607 607
608 check_efer(); 608 check_efer();
609 if (cpu != 0 && x2apic)
610 enable_x2apic();
609 611
610 /* 612 /*
611 * set up and load the per-CPU TSS 613 * set up and load the per-CPU TSS
diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/genapic_64.c
index 1029e178cdf7..792e21ba1a81 100644
--- a/arch/x86/kernel/genapic_64.c
+++ b/arch/x86/kernel/genapic_64.c
@@ -16,6 +16,7 @@
16#include <linux/ctype.h> 16#include <linux/ctype.h>
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/hardirq.h> 18#include <linux/hardirq.h>
19#include <linux/dmar.h>
19 20
20#include <asm/smp.h> 21#include <asm/smp.h>
21#include <asm/ipi.h> 22#include <asm/ipi.h>
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 3b25e49380c6..70e1f3e287fb 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -545,7 +545,9 @@ static int __init smp_read_mpc(struct mp_config_table *mpc, unsigned early)
545 generic_bigsmp_probe(); 545 generic_bigsmp_probe();
546#endif 546#endif
547 547
548#ifdef CONFIG_X86_32
548 setup_apic_routing(); 549 setup_apic_routing();
550#endif
549 if (!num_processors) 551 if (!num_processors)
550 printk(KERN_ERR "MPTABLE: no processors registered!\n"); 552 printk(KERN_ERR "MPTABLE: no processors registered!\n");
551 return num_processors; 553 return num_processors;
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 987b6fde3a99..2e78a143dec3 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -730,6 +730,8 @@ void __init setup_arch(char **cmdline_p)
730 num_physpages = max_pfn; 730 num_physpages = max_pfn;
731 731
732 check_efer(); 732 check_efer();
733 if (cpu_has_x2apic)
734 check_x2apic();
733 735
734 /* How many end-of-memory variables you have, grandma! */ 736 /* How many end-of-memory variables you have, grandma! */
735 /* need this before calling reserve_initrd */ 737 /* need this before calling reserve_initrd */
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index c55263b3df02..0c43e1f2e7d3 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1145,6 +1145,11 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
1145 current_thread_info()->cpu = 0; /* needed? */ 1145 current_thread_info()->cpu = 0; /* needed? */
1146 set_cpu_sibling_map(0); 1146 set_cpu_sibling_map(0);
1147 1147
1148#ifdef CONFIG_X86_64
1149 enable_IR_x2apic();
1150 setup_apic_routing();
1151#endif
1152
1148 if (smp_sanity_check(max_cpus) < 0) { 1153 if (smp_sanity_check(max_cpus) < 0) {
1149 printk(KERN_INFO "SMP disabled\n"); 1154 printk(KERN_INFO "SMP disabled\n");
1150 disable_smp(); 1155 disable_smp();
diff --git a/include/asm-x86/apic.h b/include/asm-x86/apic.h
index aa746704a5c9..129752dd2525 100644
--- a/include/asm-x86/apic.h
+++ b/include/asm-x86/apic.h
@@ -100,6 +100,11 @@ extern void apic_wait_icr_idle(void);
100extern u32 safe_apic_wait_icr_idle(void); 100extern u32 safe_apic_wait_icr_idle(void);
101extern void apic_icr_write(u32 low, u32 id); 101extern void apic_icr_write(u32 low, u32 id);
102#else 102#else
103extern int x2apic, x2apic_preenabled;
104extern void check_x2apic(void);
105extern void enable_x2apic(void);
106extern void enable_IR_x2apic(void);
107extern void x2apic_icr_write(u32 low, u32 id);
103 108
104struct apic_ops { 109struct apic_ops {
105 u32 (*read)(u32 reg); 110 u32 (*read)(u32 reg);