diff options
Diffstat (limited to 'arch')
76 files changed, 2200 insertions, 610 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 8bf0fa652eb6..f78c2be4242b 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -175,4 +175,7 @@ config HAVE_PERF_EVENTS_NMI | |||
175 | config HAVE_ARCH_JUMP_LABEL | 175 | config HAVE_ARCH_JUMP_LABEL |
176 | bool | 176 | bool |
177 | 177 | ||
178 | config HAVE_ARCH_MUTEX_CPU_RELAX | ||
179 | bool | ||
180 | |||
178 | source "kernel/gcov/Kconfig" | 181 | source "kernel/gcov/Kconfig" |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index e0b98e71ff47..6c6d7b339aae 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -99,6 +99,7 @@ config S390 | |||
99 | select HAVE_KERNEL_LZMA | 99 | select HAVE_KERNEL_LZMA |
100 | select HAVE_KERNEL_LZO | 100 | select HAVE_KERNEL_LZO |
101 | select HAVE_GET_USER_PAGES_FAST | 101 | select HAVE_GET_USER_PAGES_FAST |
102 | select HAVE_ARCH_MUTEX_CPU_RELAX | ||
102 | select ARCH_INLINE_SPIN_TRYLOCK | 103 | select ARCH_INLINE_SPIN_TRYLOCK |
103 | select ARCH_INLINE_SPIN_TRYLOCK_BH | 104 | select ARCH_INLINE_SPIN_TRYLOCK_BH |
104 | select ARCH_INLINE_SPIN_LOCK | 105 | select ARCH_INLINE_SPIN_LOCK |
diff --git a/arch/s390/include/asm/mutex.h b/arch/s390/include/asm/mutex.h index 458c1f7fbc18..688271f5f2e4 100644 --- a/arch/s390/include/asm/mutex.h +++ b/arch/s390/include/asm/mutex.h | |||
@@ -7,3 +7,5 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <asm-generic/mutex-dec.h> | 9 | #include <asm-generic/mutex-dec.h> |
10 | |||
11 | #define arch_mutex_cpu_relax() barrier() | ||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e330da21b84f..b6fccb07123e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -377,6 +377,18 @@ config X86_ELAN | |||
377 | 377 | ||
378 | If unsure, choose "PC-compatible" instead. | 378 | If unsure, choose "PC-compatible" instead. |
379 | 379 | ||
380 | config X86_INTEL_CE | ||
381 | bool "CE4100 TV platform" | ||
382 | depends on PCI | ||
383 | depends on PCI_GODIRECT | ||
384 | depends on X86_32 | ||
385 | depends on X86_EXTENDED_PLATFORM | ||
386 | select X86_REBOOTFIXUPS | ||
387 | ---help--- | ||
388 | Select for the Intel CE media processor (CE4100) SOC. | ||
389 | This option compiles in support for the CE4100 SOC for settop | ||
390 | boxes and media devices. | ||
391 | |||
380 | config X86_MRST | 392 | config X86_MRST |
381 | bool "Moorestown MID platform" | 393 | bool "Moorestown MID platform" |
382 | depends on PCI | 394 | depends on PCI |
@@ -385,6 +397,10 @@ config X86_MRST | |||
385 | depends on X86_EXTENDED_PLATFORM | 397 | depends on X86_EXTENDED_PLATFORM |
386 | depends on X86_IO_APIC | 398 | depends on X86_IO_APIC |
387 | select APB_TIMER | 399 | select APB_TIMER |
400 | select I2C | ||
401 | select SPI | ||
402 | select INTEL_SCU_IPC | ||
403 | select X86_PLATFORM_DEVICES | ||
388 | ---help--- | 404 | ---help--- |
389 | Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin | 405 | Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin |
390 | Internet Device(MID) platform. Moorestown consists of two chips: | 406 | Internet Device(MID) platform. Moorestown consists of two chips: |
@@ -466,6 +482,19 @@ config X86_ES7000 | |||
466 | Support for Unisys ES7000 systems. Say 'Y' here if this kernel is | 482 | Support for Unisys ES7000 systems. Say 'Y' here if this kernel is |
467 | supposed to run on an IA32-based Unisys ES7000 system. | 483 | supposed to run on an IA32-based Unisys ES7000 system. |
468 | 484 | ||
485 | config X86_32_IRIS | ||
486 | tristate "Eurobraille/Iris poweroff module" | ||
487 | depends on X86_32 | ||
488 | ---help--- | ||
489 | The Iris machines from EuroBraille do not have APM or ACPI support | ||
490 | to shut themselves down properly. A special I/O sequence is | ||
491 | needed to do so, which is what this module does at | ||
492 | kernel shutdown. | ||
493 | |||
494 | This is only for Iris machines from EuroBraille. | ||
495 | |||
496 | If unused, say N. | ||
497 | |||
469 | config SCHED_OMIT_FRAME_POINTER | 498 | config SCHED_OMIT_FRAME_POINTER |
470 | def_bool y | 499 | def_bool y |
471 | prompt "Single-depth WCHAN output" | 500 | prompt "Single-depth WCHAN output" |
@@ -1141,16 +1170,16 @@ config NUMA | |||
1141 | comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI" | 1170 | comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI" |
1142 | depends on X86_32 && X86_SUMMIT && (!HIGHMEM64G || !ACPI) | 1171 | depends on X86_32 && X86_SUMMIT && (!HIGHMEM64G || !ACPI) |
1143 | 1172 | ||
1144 | config K8_NUMA | 1173 | config AMD_NUMA |
1145 | def_bool y | 1174 | def_bool y |
1146 | prompt "Old style AMD Opteron NUMA detection" | 1175 | prompt "Old style AMD Opteron NUMA detection" |
1147 | depends on X86_64 && NUMA && PCI | 1176 | depends on X86_64 && NUMA && PCI |
1148 | ---help--- | 1177 | ---help--- |
1149 | Enable K8 NUMA node topology detection. You should say Y here if | 1178 | Enable AMD NUMA node topology detection. You should say Y here if |
1150 | you have a multi processor AMD K8 system. This uses an old | 1179 | you have a multi processor AMD system. This uses an old method to |
1151 | method to read the NUMA configuration directly from the builtin | 1180 | read the NUMA configuration directly from the builtin Northbridge |
1152 | Northbridge of Opteron. It is recommended to use X86_64_ACPI_NUMA | 1181 | of Opteron. It is recommended to use X86_64_ACPI_NUMA instead, |
1153 | instead, which also takes priority if both are compiled in. | 1182 | which also takes priority if both are compiled in. |
1154 | 1183 | ||
1155 | config X86_64_ACPI_NUMA | 1184 | config X86_64_ACPI_NUMA |
1156 | def_bool y | 1185 | def_bool y |
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index b59ee765414e..45143bbcfe5e 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug | |||
@@ -117,6 +117,17 @@ config DEBUG_RODATA_TEST | |||
117 | feature as well as for the change_page_attr() infrastructure. | 117 | feature as well as for the change_page_attr() infrastructure. |
118 | If in doubt, say "N" | 118 | If in doubt, say "N" |
119 | 119 | ||
120 | config DEBUG_SET_MODULE_RONX | ||
121 | bool "Set loadable kernel module data as NX and text as RO" | ||
122 | depends on MODULES | ||
123 | ---help--- | ||
124 | This option helps catch unintended modifications to loadable | ||
125 | kernel module's text and read-only data. It also prevents execution | ||
126 | of module data. Such protection may interfere with run-time code | ||
127 | patching and dynamic kernel tracing - and they might also protect | ||
128 | against certain classes of kernel exploits. | ||
129 | If in doubt, say "N". | ||
130 | |||
120 | config DEBUG_NX_TEST | 131 | config DEBUG_NX_TEST |
121 | tristate "Testcase for the NX non-executable stack feature" | 132 | tristate "Testcase for the NX non-executable stack feature" |
122 | depends on DEBUG_KERNEL && m | 133 | depends on DEBUG_KERNEL && m |
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 52f85a196fa0..35af09d13dc1 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S | |||
@@ -182,7 +182,7 @@ no_longmode: | |||
182 | hlt | 182 | hlt |
183 | jmp 1b | 183 | jmp 1b |
184 | 184 | ||
185 | #include "../../kernel/verify_cpu_64.S" | 185 | #include "../../kernel/verify_cpu.S" |
186 | 186 | ||
187 | /* | 187 | /* |
188 | * Be careful here startup_64 needs to be at a predictable | 188 | * Be careful here startup_64 needs to be at a predictable |
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 4a2adaa9aefc..13009d1af99a 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h | |||
@@ -66,6 +66,7 @@ extern void alternatives_smp_module_add(struct module *mod, char *name, | |||
66 | extern void alternatives_smp_module_del(struct module *mod); | 66 | extern void alternatives_smp_module_del(struct module *mod); |
67 | extern void alternatives_smp_switch(int smp); | 67 | extern void alternatives_smp_switch(int smp); |
68 | extern int alternatives_text_reserved(void *start, void *end); | 68 | extern int alternatives_text_reserved(void *start, void *end); |
69 | extern bool skip_smp_alternatives; | ||
69 | #else | 70 | #else |
70 | static inline void alternatives_smp_module_add(struct module *mod, char *name, | 71 | static inline void alternatives_smp_module_add(struct module *mod, char *name, |
71 | void *locks, void *locks_end, | 72 | void *locks, void *locks_end, |
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h index c8517f81b21e..6aee50d655d1 100644 --- a/arch/x86/include/asm/amd_nb.h +++ b/arch/x86/include/asm/amd_nb.h | |||
@@ -3,36 +3,53 @@ | |||
3 | 3 | ||
4 | #include <linux/pci.h> | 4 | #include <linux/pci.h> |
5 | 5 | ||
6 | extern struct pci_device_id k8_nb_ids[]; | 6 | extern struct pci_device_id amd_nb_misc_ids[]; |
7 | struct bootnode; | 7 | struct bootnode; |
8 | 8 | ||
9 | extern int early_is_k8_nb(u32 value); | 9 | extern int early_is_amd_nb(u32 value); |
10 | extern int cache_k8_northbridges(void); | 10 | extern int amd_cache_northbridges(void); |
11 | extern void k8_flush_garts(void); | 11 | extern void amd_flush_garts(void); |
12 | extern int k8_get_nodes(struct bootnode *nodes); | 12 | extern int amd_get_nodes(struct bootnode *nodes); |
13 | extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn); | 13 | extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn); |
14 | extern int k8_scan_nodes(void); | 14 | extern int amd_scan_nodes(void); |
15 | 15 | ||
16 | struct k8_northbridge_info { | 16 | struct amd_northbridge { |
17 | struct pci_dev *misc; | ||
18 | }; | ||
19 | |||
20 | struct amd_northbridge_info { | ||
17 | u16 num; | 21 | u16 num; |
18 | u8 gart_supported; | 22 | u64 flags; |
19 | struct pci_dev **nb_misc; | 23 | struct amd_northbridge *nb; |
20 | }; | 24 | }; |
21 | extern struct k8_northbridge_info k8_northbridges; | 25 | extern struct amd_northbridge_info amd_northbridges; |
26 | |||
27 | #define AMD_NB_GART 0x1 | ||
28 | #define AMD_NB_L3_INDEX_DISABLE 0x2 | ||
22 | 29 | ||
23 | #ifdef CONFIG_AMD_NB | 30 | #ifdef CONFIG_AMD_NB |
24 | 31 | ||
25 | static inline struct pci_dev *node_to_k8_nb_misc(int node) | 32 | static inline int amd_nb_num(void) |
26 | { | 33 | { |
27 | return (node < k8_northbridges.num) ? k8_northbridges.nb_misc[node] : NULL; | 34 | return amd_northbridges.num; |
28 | } | 35 | } |
29 | 36 | ||
30 | #else | 37 | static inline int amd_nb_has_feature(int feature) |
38 | { | ||
39 | return ((amd_northbridges.flags & feature) == feature); | ||
40 | } | ||
31 | 41 | ||
32 | static inline struct pci_dev *node_to_k8_nb_misc(int node) | 42 | static inline struct amd_northbridge *node_to_amd_nb(int node) |
33 | { | 43 | { |
34 | return NULL; | 44 | return (node < amd_northbridges.num) ? &amd_northbridges.nb[node] : NULL; |
35 | } | 45 | } |
46 | |||
47 | #else | ||
48 | |||
49 | #define amd_nb_num(x) 0 | ||
50 | #define amd_nb_has_feature(x) false | ||
51 | #define node_to_amd_nb(x) NULL | ||
52 | |||
36 | #endif | 53 | #endif |
37 | 54 | ||
38 | 55 | ||
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index f6ce0bda3b98..cf12007796db 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h | |||
@@ -238,6 +238,7 @@ extern void setup_boot_APIC_clock(void); | |||
238 | extern void setup_secondary_APIC_clock(void); | 238 | extern void setup_secondary_APIC_clock(void); |
239 | extern int APIC_init_uniprocessor(void); | 239 | extern int APIC_init_uniprocessor(void); |
240 | extern void enable_NMI_through_LVT0(void); | 240 | extern void enable_NMI_through_LVT0(void); |
241 | extern int apic_force_enable(void); | ||
241 | 242 | ||
242 | /* | 243 | /* |
243 | * On 32bit this is mach-xxx local | 244 | * On 32bit this is mach-xxx local |
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h index a859ca461fb0..47a30ff8e517 100644 --- a/arch/x86/include/asm/apicdef.h +++ b/arch/x86/include/asm/apicdef.h | |||
@@ -145,6 +145,7 @@ | |||
145 | 145 | ||
146 | #ifdef CONFIG_X86_32 | 146 | #ifdef CONFIG_X86_32 |
147 | # define MAX_IO_APICS 64 | 147 | # define MAX_IO_APICS 64 |
148 | # define MAX_LOCAL_APIC 256 | ||
148 | #else | 149 | #else |
149 | # define MAX_IO_APICS 128 | 150 | # define MAX_IO_APICS 128 |
150 | # define MAX_LOCAL_APIC 32768 | 151 | # define MAX_LOCAL_APIC 32768 |
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h index 8e6218550e77..c8bfe63a06de 100644 --- a/arch/x86/include/asm/bootparam.h +++ b/arch/x86/include/asm/bootparam.h | |||
@@ -124,6 +124,7 @@ enum { | |||
124 | X86_SUBARCH_LGUEST, | 124 | X86_SUBARCH_LGUEST, |
125 | X86_SUBARCH_XEN, | 125 | X86_SUBARCH_XEN, |
126 | X86_SUBARCH_MRST, | 126 | X86_SUBARCH_MRST, |
127 | X86_SUBARCH_CE4100, | ||
127 | X86_NR_SUBARCHS, | 128 | X86_NR_SUBARCHS, |
128 | }; | 129 | }; |
129 | 130 | ||
diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index 9479a037419f..0141b234406f 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h | |||
@@ -117,6 +117,10 @@ enum fixed_addresses { | |||
117 | FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */ | 117 | FIX_TEXT_POKE1, /* reserve 2 pages for text_poke() */ |
118 | FIX_TEXT_POKE0, /* first page is last, because allocation is backward */ | 118 | FIX_TEXT_POKE0, /* first page is last, because allocation is backward */ |
119 | __end_of_permanent_fixed_addresses, | 119 | __end_of_permanent_fixed_addresses, |
120 | |||
121 | #ifdef CONFIG_X86_MRST | ||
122 | FIX_LNW_VRTC, | ||
123 | #endif | ||
120 | /* | 124 | /* |
121 | * 256 temporary boot-time mappings, used by early_ioremap(), | 125 | * 256 temporary boot-time mappings, used by early_ioremap(), |
122 | * before ioremap() is functional. | 126 | * before ioremap() is functional. |
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 4aa2bb3b242a..ef328901c802 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h | |||
@@ -93,6 +93,17 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx) | |||
93 | int err; | 93 | int err; |
94 | 94 | ||
95 | /* See comment in fxsave() below. */ | 95 | /* See comment in fxsave() below. */ |
96 | #ifdef CONFIG_AS_FXSAVEQ | ||
97 | asm volatile("1: fxrstorq %[fx]\n\t" | ||
98 | "2:\n" | ||
99 | ".section .fixup,\"ax\"\n" | ||
100 | "3: movl $-1,%[err]\n" | ||
101 | " jmp 2b\n" | ||
102 | ".previous\n" | ||
103 | _ASM_EXTABLE(1b, 3b) | ||
104 | : [err] "=r" (err) | ||
105 | : [fx] "m" (*fx), "0" (0)); | ||
106 | #else | ||
96 | asm volatile("1: rex64/fxrstor (%[fx])\n\t" | 107 | asm volatile("1: rex64/fxrstor (%[fx])\n\t" |
97 | "2:\n" | 108 | "2:\n" |
98 | ".section .fixup,\"ax\"\n" | 109 | ".section .fixup,\"ax\"\n" |
@@ -102,6 +113,7 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx) | |||
102 | _ASM_EXTABLE(1b, 3b) | 113 | _ASM_EXTABLE(1b, 3b) |
103 | : [err] "=r" (err) | 114 | : [err] "=r" (err) |
104 | : [fx] "R" (fx), "m" (*fx), "0" (0)); | 115 | : [fx] "R" (fx), "m" (*fx), "0" (0)); |
116 | #endif | ||
105 | return err; | 117 | return err; |
106 | } | 118 | } |
107 | 119 | ||
@@ -119,6 +131,17 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx) | |||
119 | return -EFAULT; | 131 | return -EFAULT; |
120 | 132 | ||
121 | /* See comment in fxsave() below. */ | 133 | /* See comment in fxsave() below. */ |
134 | #ifdef CONFIG_AS_FXSAVEQ | ||
135 | asm volatile("1: fxsaveq %[fx]\n\t" | ||
136 | "2:\n" | ||
137 | ".section .fixup,\"ax\"\n" | ||
138 | "3: movl $-1,%[err]\n" | ||
139 | " jmp 2b\n" | ||
140 | ".previous\n" | ||
141 | _ASM_EXTABLE(1b, 3b) | ||
142 | : [err] "=r" (err), [fx] "=m" (*fx) | ||
143 | : "0" (0)); | ||
144 | #else | ||
122 | asm volatile("1: rex64/fxsave (%[fx])\n\t" | 145 | asm volatile("1: rex64/fxsave (%[fx])\n\t" |
123 | "2:\n" | 146 | "2:\n" |
124 | ".section .fixup,\"ax\"\n" | 147 | ".section .fixup,\"ax\"\n" |
@@ -128,6 +151,7 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx) | |||
128 | _ASM_EXTABLE(1b, 3b) | 151 | _ASM_EXTABLE(1b, 3b) |
129 | : [err] "=r" (err), "=m" (*fx) | 152 | : [err] "=r" (err), "=m" (*fx) |
130 | : [fx] "R" (fx), "0" (0)); | 153 | : [fx] "R" (fx), "0" (0)); |
154 | #endif | ||
131 | if (unlikely(err) && | 155 | if (unlikely(err) && |
132 | __clear_user(fx, sizeof(struct i387_fxsave_struct))) | 156 | __clear_user(fx, sizeof(struct i387_fxsave_struct))) |
133 | err = -EFAULT; | 157 | err = -EFAULT; |
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index a6b28d017c2f..0c5ca4e30d7b 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -159,7 +159,7 @@ struct io_apic_irq_attr; | |||
159 | extern int io_apic_set_pci_routing(struct device *dev, int irq, | 159 | extern int io_apic_set_pci_routing(struct device *dev, int irq, |
160 | struct io_apic_irq_attr *irq_attr); | 160 | struct io_apic_irq_attr *irq_attr); |
161 | void setup_IO_APIC_irq_extra(u32 gsi); | 161 | void setup_IO_APIC_irq_extra(u32 gsi); |
162 | extern void ioapic_init_mappings(void); | 162 | extern void ioapic_and_gsi_init(void); |
163 | extern void ioapic_insert_resources(void); | 163 | extern void ioapic_insert_resources(void); |
164 | 164 | ||
165 | extern struct IO_APIC_route_entry **alloc_ioapic_entries(void); | 165 | extern struct IO_APIC_route_entry **alloc_ioapic_entries(void); |
@@ -168,10 +168,9 @@ extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); | |||
168 | extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); | 168 | extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); |
169 | extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); | 169 | extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries); |
170 | 170 | ||
171 | extern void probe_nr_irqs_gsi(void); | ||
172 | extern int get_nr_irqs_gsi(void); | 171 | extern int get_nr_irqs_gsi(void); |
173 | |||
174 | extern void setup_ioapic_ids_from_mpc(void); | 172 | extern void setup_ioapic_ids_from_mpc(void); |
173 | extern void setup_ioapic_ids_from_mpc_nocheck(void); | ||
175 | 174 | ||
176 | struct mp_ioapic_gsi{ | 175 | struct mp_ioapic_gsi{ |
177 | u32 gsi_base; | 176 | u32 gsi_base; |
@@ -189,9 +188,8 @@ extern void __init pre_init_apic_IRQ0(void); | |||
189 | #define io_apic_assign_pci_irqs 0 | 188 | #define io_apic_assign_pci_irqs 0 |
190 | #define setup_ioapic_ids_from_mpc x86_init_noop | 189 | #define setup_ioapic_ids_from_mpc x86_init_noop |
191 | static const int timer_through_8259 = 0; | 190 | static const int timer_through_8259 = 0; |
192 | static inline void ioapic_init_mappings(void) { } | 191 | static inline void ioapic_and_gsi_init(void) { } |
193 | static inline void ioapic_insert_resources(void) { } | 192 | static inline void ioapic_insert_resources(void) { } |
194 | static inline void probe_nr_irqs_gsi(void) { } | ||
195 | #define gsi_top (NR_IRQS_LEGACY) | 193 | #define gsi_top (NR_IRQS_LEGACY) |
196 | static inline int mp_find_ioapic(u32 gsi) { return 0; } | 194 | static inline int mp_find_ioapic(u32 gsi) { return 0; } |
197 | 195 | ||
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index c62c13cb9788..eb16e94ae04f 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h | |||
@@ -223,6 +223,9 @@ void intel_init_thermal(struct cpuinfo_x86 *c); | |||
223 | 223 | ||
224 | void mce_log_therm_throt_event(__u64 status); | 224 | void mce_log_therm_throt_event(__u64 status); |
225 | 225 | ||
226 | /* Interrupt Handler for core thermal thresholds */ | ||
227 | extern int (*platform_thermal_notify)(__u64 msr_val); | ||
228 | |||
226 | #ifdef CONFIG_X86_THERMAL_VECTOR | 229 | #ifdef CONFIG_X86_THERMAL_VECTOR |
227 | extern void mcheck_intel_therm_init(void); | 230 | extern void mcheck_intel_therm_init(void); |
228 | #else | 231 | #else |
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index ef51b501e22a..24215072d0e1 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h | |||
@@ -48,6 +48,12 @@ static inline struct microcode_ops * __init init_intel_microcode(void) | |||
48 | 48 | ||
49 | #ifdef CONFIG_MICROCODE_AMD | 49 | #ifdef CONFIG_MICROCODE_AMD |
50 | extern struct microcode_ops * __init init_amd_microcode(void); | 50 | extern struct microcode_ops * __init init_amd_microcode(void); |
51 | |||
52 | static inline void get_ucode_data(void *to, const u8 *from, size_t n) | ||
53 | { | ||
54 | memcpy(to, from, n); | ||
55 | } | ||
56 | |||
51 | #else | 57 | #else |
52 | static inline struct microcode_ops * __init init_amd_microcode(void) | 58 | static inline struct microcode_ops * __init init_amd_microcode(void) |
53 | { | 59 | { |
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index c82868e9f905..0c90dd9f0505 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h | |||
@@ -5,8 +5,9 @@ | |||
5 | 5 | ||
6 | #include <asm/mpspec_def.h> | 6 | #include <asm/mpspec_def.h> |
7 | #include <asm/x86_init.h> | 7 | #include <asm/x86_init.h> |
8 | #include <asm/apicdef.h> | ||
8 | 9 | ||
9 | extern int apic_version[MAX_APICS]; | 10 | extern int apic_version[]; |
10 | extern int pic_mode; | 11 | extern int pic_mode; |
11 | 12 | ||
12 | #ifdef CONFIG_X86_32 | 13 | #ifdef CONFIG_X86_32 |
@@ -107,7 +108,7 @@ extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level, | |||
107 | int active_high_low); | 108 | int active_high_low); |
108 | #endif /* CONFIG_ACPI */ | 109 | #endif /* CONFIG_ACPI */ |
109 | 110 | ||
110 | #define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS) | 111 | #define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_LOCAL_APIC) |
111 | 112 | ||
112 | struct physid_mask { | 113 | struct physid_mask { |
113 | unsigned long mask[PHYSID_ARRAY_SIZE]; | 114 | unsigned long mask[PHYSID_ARRAY_SIZE]; |
@@ -122,31 +123,31 @@ typedef struct physid_mask physid_mask_t; | |||
122 | test_and_set_bit(physid, (map).mask) | 123 | test_and_set_bit(physid, (map).mask) |
123 | 124 | ||
124 | #define physids_and(dst, src1, src2) \ | 125 | #define physids_and(dst, src1, src2) \ |
125 | bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_APICS) | 126 | bitmap_and((dst).mask, (src1).mask, (src2).mask, MAX_LOCAL_APIC) |
126 | 127 | ||
127 | #define physids_or(dst, src1, src2) \ | 128 | #define physids_or(dst, src1, src2) \ |
128 | bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_APICS) | 129 | bitmap_or((dst).mask, (src1).mask, (src2).mask, MAX_LOCAL_APIC) |
129 | 130 | ||
130 | #define physids_clear(map) \ | 131 | #define physids_clear(map) \ |
131 | bitmap_zero((map).mask, MAX_APICS) | 132 | bitmap_zero((map).mask, MAX_LOCAL_APIC) |
132 | 133 | ||
133 | #define physids_complement(dst, src) \ | 134 | #define physids_complement(dst, src) \ |
134 | bitmap_complement((dst).mask, (src).mask, MAX_APICS) | 135 | bitmap_complement((dst).mask, (src).mask, MAX_LOCAL_APIC) |
135 | 136 | ||
136 | #define physids_empty(map) \ | 137 | #define physids_empty(map) \ |
137 | bitmap_empty((map).mask, MAX_APICS) | 138 | bitmap_empty((map).mask, MAX_LOCAL_APIC) |
138 | 139 | ||
139 | #define physids_equal(map1, map2) \ | 140 | #define physids_equal(map1, map2) \ |
140 | bitmap_equal((map1).mask, (map2).mask, MAX_APICS) | 141 | bitmap_equal((map1).mask, (map2).mask, MAX_LOCAL_APIC) |
141 | 142 | ||
142 | #define physids_weight(map) \ | 143 | #define physids_weight(map) \ |
143 | bitmap_weight((map).mask, MAX_APICS) | 144 | bitmap_weight((map).mask, MAX_LOCAL_APIC) |
144 | 145 | ||
145 | #define physids_shift_right(d, s, n) \ | 146 | #define physids_shift_right(d, s, n) \ |
146 | bitmap_shift_right((d).mask, (s).mask, n, MAX_APICS) | 147 | bitmap_shift_right((d).mask, (s).mask, n, MAX_LOCAL_APIC) |
147 | 148 | ||
148 | #define physids_shift_left(d, s, n) \ | 149 | #define physids_shift_left(d, s, n) \ |
149 | bitmap_shift_left((d).mask, (s).mask, n, MAX_APICS) | 150 | bitmap_shift_left((d).mask, (s).mask, n, MAX_LOCAL_APIC) |
150 | 151 | ||
151 | static inline unsigned long physids_coerce(physid_mask_t *map) | 152 | static inline unsigned long physids_coerce(physid_mask_t *map) |
152 | { | 153 | { |
@@ -159,14 +160,6 @@ static inline void physids_promote(unsigned long physids, physid_mask_t *map) | |||
159 | map->mask[0] = physids; | 160 | map->mask[0] = physids; |
160 | } | 161 | } |
161 | 162 | ||
162 | /* Note: will create very large stack frames if physid_mask_t is big */ | ||
163 | #define physid_mask_of_physid(physid) \ | ||
164 | ({ \ | ||
165 | physid_mask_t __physid_mask = PHYSID_MASK_NONE; \ | ||
166 | physid_set(physid, __physid_mask); \ | ||
167 | __physid_mask; \ | ||
168 | }) | ||
169 | |||
170 | static inline void physid_set_mask_of_physid(int physid, physid_mask_t *map) | 163 | static inline void physid_set_mask_of_physid(int physid, physid_mask_t *map) |
171 | { | 164 | { |
172 | physids_clear(*map); | 165 | physids_clear(*map); |
diff --git a/arch/x86/include/asm/mpspec_def.h b/arch/x86/include/asm/mpspec_def.h index 4a7f96d7c188..c0a955a9a087 100644 --- a/arch/x86/include/asm/mpspec_def.h +++ b/arch/x86/include/asm/mpspec_def.h | |||
@@ -15,13 +15,6 @@ | |||
15 | 15 | ||
16 | #ifdef CONFIG_X86_32 | 16 | #ifdef CONFIG_X86_32 |
17 | # define MAX_MPC_ENTRY 1024 | 17 | # define MAX_MPC_ENTRY 1024 |
18 | # define MAX_APICS 256 | ||
19 | #else | ||
20 | # if NR_CPUS <= 255 | ||
21 | # define MAX_APICS 255 | ||
22 | # else | ||
23 | # define MAX_APICS 32768 | ||
24 | # endif | ||
25 | #endif | 18 | #endif |
26 | 19 | ||
27 | /* Intel MP Floating Pointer Structure */ | 20 | /* Intel MP Floating Pointer Structure */ |
diff --git a/arch/x86/include/asm/mrst-vrtc.h b/arch/x86/include/asm/mrst-vrtc.h new file mode 100644 index 000000000000..73668abdbedf --- /dev/null +++ b/arch/x86/include/asm/mrst-vrtc.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _MRST_VRTC_H | ||
2 | #define _MRST_VRTC_H | ||
3 | |||
4 | extern unsigned char vrtc_cmos_read(unsigned char reg); | ||
5 | extern void vrtc_cmos_write(unsigned char val, unsigned char reg); | ||
6 | extern unsigned long vrtc_get_time(void); | ||
7 | extern int vrtc_set_mmss(unsigned long nowtime); | ||
8 | |||
9 | #endif | ||
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h index 4a711a684b17..719f00b28ff5 100644 --- a/arch/x86/include/asm/mrst.h +++ b/arch/x86/include/asm/mrst.h | |||
@@ -14,7 +14,9 @@ | |||
14 | #include <linux/sfi.h> | 14 | #include <linux/sfi.h> |
15 | 15 | ||
16 | extern int pci_mrst_init(void); | 16 | extern int pci_mrst_init(void); |
17 | int __init sfi_parse_mrtc(struct sfi_table_header *table); | 17 | extern int __init sfi_parse_mrtc(struct sfi_table_header *table); |
18 | extern int sfi_mrtc_num; | ||
19 | extern struct sfi_rtc_table_entry sfi_mrtc_array[]; | ||
18 | 20 | ||
19 | /* | 21 | /* |
20 | * Medfield is the follow-up of Moorestown, it combines two chip solution into | 22 | * Medfield is the follow-up of Moorestown, it combines two chip solution into |
@@ -50,4 +52,14 @@ extern void mrst_early_console_init(void); | |||
50 | 52 | ||
51 | extern struct console early_hsu_console; | 53 | extern struct console early_hsu_console; |
52 | extern void hsu_early_console_init(void); | 54 | extern void hsu_early_console_init(void); |
55 | |||
56 | extern void intel_scu_devices_create(void); | ||
57 | extern void intel_scu_devices_destroy(void); | ||
58 | |||
59 | /* VRTC timer */ | ||
60 | #define MRST_VRTC_MAP_SZ (1024) | ||
61 | /*#define MRST_VRTC_PGOFFSET (0xc00) */ | ||
62 | |||
63 | extern void mrst_rtc_init(void); | ||
64 | |||
53 | #endif /* _ASM_X86_MRST_H */ | 65 | #endif /* _ASM_X86_MRST_H */ |
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 86030f63ba02..4d0dfa0d998e 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h | |||
@@ -257,6 +257,18 @@ | |||
257 | #define PACKAGE_THERM_INT_LOW_ENABLE (1 << 1) | 257 | #define PACKAGE_THERM_INT_LOW_ENABLE (1 << 1) |
258 | #define PACKAGE_THERM_INT_PLN_ENABLE (1 << 24) | 258 | #define PACKAGE_THERM_INT_PLN_ENABLE (1 << 24) |
259 | 259 | ||
260 | /* Thermal Thresholds Support */ | ||
261 | #define THERM_INT_THRESHOLD0_ENABLE (1 << 15) | ||
262 | #define THERM_SHIFT_THRESHOLD0 8 | ||
263 | #define THERM_MASK_THRESHOLD0 (0x7f << THERM_SHIFT_THRESHOLD0) | ||
264 | #define THERM_INT_THRESHOLD1_ENABLE (1 << 23) | ||
265 | #define THERM_SHIFT_THRESHOLD1 16 | ||
266 | #define THERM_MASK_THRESHOLD1 (0x7f << THERM_SHIFT_THRESHOLD1) | ||
267 | #define THERM_STATUS_THRESHOLD0 (1 << 6) | ||
268 | #define THERM_LOG_THRESHOLD0 (1 << 7) | ||
269 | #define THERM_STATUS_THRESHOLD1 (1 << 8) | ||
270 | #define THERM_LOG_THRESHOLD1 (1 << 9) | ||
271 | |||
260 | /* MISC_ENABLE bits: architectural */ | 272 | /* MISC_ENABLE bits: architectural */ |
261 | #define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0) | 273 | #define MSR_IA32_MISC_ENABLE_FAST_STRING (1ULL << 0) |
262 | #define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1) | 274 | #define MSR_IA32_MISC_ENABLE_TCC (1ULL << 1) |
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index ef9975812c77..7709c12431b8 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h | |||
@@ -112,7 +112,7 @@ static inline void arch_safe_halt(void) | |||
112 | 112 | ||
113 | static inline void halt(void) | 113 | static inline void halt(void) |
114 | { | 114 | { |
115 | PVOP_VCALL0(pv_irq_ops.safe_halt); | 115 | PVOP_VCALL0(pv_irq_ops.halt); |
116 | } | 116 | } |
117 | 117 | ||
118 | static inline void wbinvd(void) | 118 | static inline void wbinvd(void) |
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index ca0437c714b2..676129229630 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h | |||
@@ -65,6 +65,7 @@ extern unsigned long pci_mem_start; | |||
65 | 65 | ||
66 | #define PCIBIOS_MIN_CARDBUS_IO 0x4000 | 66 | #define PCIBIOS_MIN_CARDBUS_IO 0x4000 |
67 | 67 | ||
68 | extern int pcibios_enabled; | ||
68 | void pcibios_config_init(void); | 69 | void pcibios_config_init(void); |
69 | struct pci_bus *pcibios_scan_root(int bus); | 70 | struct pci_bus *pcibios_scan_root(int bus); |
70 | 71 | ||
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index d6763b139a84..db8aa19a08a2 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h | |||
@@ -53,6 +53,12 @@ extern void x86_mrst_early_setup(void); | |||
53 | static inline void x86_mrst_early_setup(void) { } | 53 | static inline void x86_mrst_early_setup(void) { } |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | #ifdef CONFIG_X86_INTEL_CE | ||
57 | extern void x86_ce4100_early_setup(void); | ||
58 | #else | ||
59 | static inline void x86_ce4100_early_setup(void) { } | ||
60 | #endif | ||
61 | |||
56 | #ifndef _SETUP | 62 | #ifndef _SETUP |
57 | 63 | ||
58 | /* | 64 | /* |
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index 42d412fd8b02..ce1d54c8a433 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h | |||
@@ -26,20 +26,22 @@ | |||
26 | * BAU_SB_DESCRIPTOR_BASE register, set 1 is located at BASE + 512, | 26 | * BAU_SB_DESCRIPTOR_BASE register, set 1 is located at BASE + 512, |
27 | * set 2 is at BASE + 2*512, set 3 at BASE + 3*512, and so on. | 27 | * set 2 is at BASE + 2*512, set 3 at BASE + 3*512, and so on. |
28 | * | 28 | * |
29 | * We will use 31 sets, one for sending BAU messages from each of the 32 | 29 | * We will use one set for sending BAU messages from each of the |
30 | * cpu's on the uvhub. | 30 | * cpu's on the uvhub. |
31 | * | 31 | * |
32 | * TLB shootdown will use the first of the 8 descriptors of each set. | 32 | * TLB shootdown will use the first of the 8 descriptors of each set. |
33 | * Each of the descriptors is 64 bytes in size (8*64 = 512 bytes in a set). | 33 | * Each of the descriptors is 64 bytes in size (8*64 = 512 bytes in a set). |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #define MAX_CPUS_PER_UVHUB 64 | ||
37 | #define MAX_CPUS_PER_SOCKET 32 | ||
38 | #define UV_ADP_SIZE 64 /* hardware-provided max. */ | ||
39 | #define UV_CPUS_PER_ACT_STATUS 32 /* hardware-provided max. */ | ||
36 | #define UV_ITEMS_PER_DESCRIPTOR 8 | 40 | #define UV_ITEMS_PER_DESCRIPTOR 8 |
37 | /* the 'throttle' to prevent the hardware stay-busy bug */ | 41 | /* the 'throttle' to prevent the hardware stay-busy bug */ |
38 | #define MAX_BAU_CONCURRENT 3 | 42 | #define MAX_BAU_CONCURRENT 3 |
39 | #define UV_CPUS_PER_ACT_STATUS 32 | ||
40 | #define UV_ACT_STATUS_MASK 0x3 | 43 | #define UV_ACT_STATUS_MASK 0x3 |
41 | #define UV_ACT_STATUS_SIZE 2 | 44 | #define UV_ACT_STATUS_SIZE 2 |
42 | #define UV_ADP_SIZE 32 | ||
43 | #define UV_DISTRIBUTION_SIZE 256 | 45 | #define UV_DISTRIBUTION_SIZE 256 |
44 | #define UV_SW_ACK_NPENDING 8 | 46 | #define UV_SW_ACK_NPENDING 8 |
45 | #define UV_NET_ENDPOINT_INTD 0x38 | 47 | #define UV_NET_ENDPOINT_INTD 0x38 |
@@ -100,7 +102,6 @@ | |||
100 | * number of destination side software ack resources | 102 | * number of destination side software ack resources |
101 | */ | 103 | */ |
102 | #define DEST_NUM_RESOURCES 8 | 104 | #define DEST_NUM_RESOURCES 8 |
103 | #define MAX_CPUS_PER_NODE 32 | ||
104 | /* | 105 | /* |
105 | * completion statuses for sending a TLB flush message | 106 | * completion statuses for sending a TLB flush message |
106 | */ | 107 | */ |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 1e994754d323..34244b2cd880 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -85,7 +85,6 @@ obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o | |||
85 | obj-$(CONFIG_KGDB) += kgdb.o | 85 | obj-$(CONFIG_KGDB) += kgdb.o |
86 | obj-$(CONFIG_VM86) += vm86_32.o | 86 | obj-$(CONFIG_VM86) += vm86_32.o |
87 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 87 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
88 | obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o | ||
89 | 88 | ||
90 | obj-$(CONFIG_HPET_TIMER) += hpet.o | 89 | obj-$(CONFIG_HPET_TIMER) += hpet.o |
91 | obj-$(CONFIG_APB_TIMER) += apb_timer.o | 90 | obj-$(CONFIG_APB_TIMER) += apb_timer.o |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 71232b941b6c..17c8090fabd4 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -198,6 +198,11 @@ static void __cpuinit acpi_register_lapic(int id, u8 enabled) | |||
198 | { | 198 | { |
199 | unsigned int ver = 0; | 199 | unsigned int ver = 0; |
200 | 200 | ||
201 | if (id >= (MAX_LOCAL_APIC-1)) { | ||
202 | printk(KERN_INFO PREFIX "skipped apicid that is too big\n"); | ||
203 | return; | ||
204 | } | ||
205 | |||
201 | if (!enabled) { | 206 | if (!enabled) { |
202 | ++disabled_cpus; | 207 | ++disabled_cpus; |
203 | return; | 208 | return; |
@@ -910,13 +915,13 @@ static int __init acpi_parse_madt_lapic_entries(void) | |||
910 | acpi_register_lapic_address(acpi_lapic_addr); | 915 | acpi_register_lapic_address(acpi_lapic_addr); |
911 | 916 | ||
912 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, | 917 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC, |
913 | acpi_parse_sapic, MAX_APICS); | 918 | acpi_parse_sapic, MAX_LOCAL_APIC); |
914 | 919 | ||
915 | if (!count) { | 920 | if (!count) { |
916 | x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC, | 921 | x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC, |
917 | acpi_parse_x2apic, MAX_APICS); | 922 | acpi_parse_x2apic, MAX_LOCAL_APIC); |
918 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, | 923 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, |
919 | acpi_parse_lapic, MAX_APICS); | 924 | acpi_parse_lapic, MAX_LOCAL_APIC); |
920 | } | 925 | } |
921 | if (!count && !x2count) { | 926 | if (!count && !x2count) { |
922 | printk(KERN_ERR PREFIX "No LAPIC entries present\n"); | 927 | printk(KERN_ERR PREFIX "No LAPIC entries present\n"); |
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 553d0b0d639b..123608531c8f 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -353,6 +353,7 @@ void __init_or_module alternatives_smp_module_del(struct module *mod) | |||
353 | mutex_unlock(&smp_alt); | 353 | mutex_unlock(&smp_alt); |
354 | } | 354 | } |
355 | 355 | ||
356 | bool skip_smp_alternatives; | ||
356 | void alternatives_smp_switch(int smp) | 357 | void alternatives_smp_switch(int smp) |
357 | { | 358 | { |
358 | struct smp_alt_module *mod; | 359 | struct smp_alt_module *mod; |
@@ -368,7 +369,7 @@ void alternatives_smp_switch(int smp) | |||
368 | printk("lockdep: fixing up alternatives.\n"); | 369 | printk("lockdep: fixing up alternatives.\n"); |
369 | #endif | 370 | #endif |
370 | 371 | ||
371 | if (noreplace_smp || smp_alt_once) | 372 | if (noreplace_smp || smp_alt_once || skip_smp_alternatives) |
372 | return; | 373 | return; |
373 | BUG_ON(!smp && (num_online_cpus() > 1)); | 374 | BUG_ON(!smp && (num_online_cpus() > 1)); |
374 | 375 | ||
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c index 8f6463d8ed0d..affacb5e0065 100644 --- a/arch/x86/kernel/amd_nb.c +++ b/arch/x86/kernel/amd_nb.c | |||
@@ -12,95 +12,116 @@ | |||
12 | 12 | ||
13 | static u32 *flush_words; | 13 | static u32 *flush_words; |
14 | 14 | ||
15 | struct pci_device_id k8_nb_ids[] = { | 15 | struct pci_device_id amd_nb_misc_ids[] = { |
16 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, | 16 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, |
17 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, | 17 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, |
18 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_MISC) }, | 18 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_MISC) }, |
19 | {} | 19 | {} |
20 | }; | 20 | }; |
21 | EXPORT_SYMBOL(k8_nb_ids); | 21 | EXPORT_SYMBOL(amd_nb_misc_ids); |
22 | 22 | ||
23 | struct k8_northbridge_info k8_northbridges; | 23 | struct amd_northbridge_info amd_northbridges; |
24 | EXPORT_SYMBOL(k8_northbridges); | 24 | EXPORT_SYMBOL(amd_northbridges); |
25 | 25 | ||
26 | static struct pci_dev *next_k8_northbridge(struct pci_dev *dev) | 26 | static struct pci_dev *next_northbridge(struct pci_dev *dev, |
27 | struct pci_device_id *ids) | ||
27 | { | 28 | { |
28 | do { | 29 | do { |
29 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); | 30 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); |
30 | if (!dev) | 31 | if (!dev) |
31 | break; | 32 | break; |
32 | } while (!pci_match_id(&k8_nb_ids[0], dev)); | 33 | } while (!pci_match_id(ids, dev)); |
33 | return dev; | 34 | return dev; |
34 | } | 35 | } |
35 | 36 | ||
36 | int cache_k8_northbridges(void) | 37 | int amd_cache_northbridges(void) |
37 | { | 38 | { |
38 | int i; | 39 | int i = 0; |
39 | struct pci_dev *dev; | 40 | struct amd_northbridge *nb; |
41 | struct pci_dev *misc; | ||
40 | 42 | ||
41 | if (k8_northbridges.num) | 43 | if (amd_nb_num()) |
42 | return 0; | 44 | return 0; |
43 | 45 | ||
44 | dev = NULL; | 46 | misc = NULL; |
45 | while ((dev = next_k8_northbridge(dev)) != NULL) | 47 | while ((misc = next_northbridge(misc, amd_nb_misc_ids)) != NULL) |
46 | k8_northbridges.num++; | 48 | i++; |
47 | 49 | ||
48 | /* some CPU families (e.g. family 0x11) do not support GART */ | 50 | if (i == 0) |
49 | if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 || | 51 | return 0; |
50 | boot_cpu_data.x86 == 0x15) | ||
51 | k8_northbridges.gart_supported = 1; | ||
52 | 52 | ||
53 | k8_northbridges.nb_misc = kmalloc((k8_northbridges.num + 1) * | 53 | nb = kzalloc(i * sizeof(struct amd_northbridge), GFP_KERNEL); |
54 | sizeof(void *), GFP_KERNEL); | 54 | if (!nb) |
55 | if (!k8_northbridges.nb_misc) | ||
56 | return -ENOMEM; | 55 | return -ENOMEM; |
57 | 56 | ||
58 | if (!k8_northbridges.num) { | 57 | amd_northbridges.nb = nb; |
59 | k8_northbridges.nb_misc[0] = NULL; | 58 | amd_northbridges.num = i; |
60 | return 0; | ||
61 | } | ||
62 | 59 | ||
63 | if (k8_northbridges.gart_supported) { | 60 | misc = NULL; |
64 | flush_words = kmalloc(k8_northbridges.num * sizeof(u32), | 61 | for (i = 0; i != amd_nb_num(); i++) { |
65 | GFP_KERNEL); | 62 | node_to_amd_nb(i)->misc = misc = |
66 | if (!flush_words) { | 63 | next_northbridge(misc, amd_nb_misc_ids); |
67 | kfree(k8_northbridges.nb_misc); | 64 | } |
68 | return -ENOMEM; | 65 | |
69 | } | 66 | /* some CPU families (e.g. family 0x11) do not support GART */ |
70 | } | 67 | if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10 || |
68 | boot_cpu_data.x86 == 0x15) | ||
69 | amd_northbridges.flags |= AMD_NB_GART; | ||
70 | |||
71 | /* | ||
72 | * Some CPU families support L3 Cache Index Disable. There are some | ||
73 | * limitations because of E382 and E388 on family 0x10. | ||
74 | */ | ||
75 | if (boot_cpu_data.x86 == 0x10 && | ||
76 | boot_cpu_data.x86_model >= 0x8 && | ||
77 | (boot_cpu_data.x86_model > 0x9 || | ||
78 | boot_cpu_data.x86_mask >= 0x1)) | ||
79 | amd_northbridges.flags |= AMD_NB_L3_INDEX_DISABLE; | ||
71 | 80 | ||
72 | dev = NULL; | ||
73 | i = 0; | ||
74 | while ((dev = next_k8_northbridge(dev)) != NULL) { | ||
75 | k8_northbridges.nb_misc[i] = dev; | ||
76 | if (k8_northbridges.gart_supported) | ||
77 | pci_read_config_dword(dev, 0x9c, &flush_words[i++]); | ||
78 | } | ||
79 | k8_northbridges.nb_misc[i] = NULL; | ||
80 | return 0; | 81 | return 0; |
81 | } | 82 | } |
82 | EXPORT_SYMBOL_GPL(cache_k8_northbridges); | 83 | EXPORT_SYMBOL_GPL(amd_cache_northbridges); |
83 | 84 | ||
84 | /* Ignores subdevice/subvendor but as far as I can figure out | 85 | /* Ignores subdevice/subvendor but as far as I can figure out |
85 | they're useless anyways */ | 86 | they're useless anyways */ |
86 | int __init early_is_k8_nb(u32 device) | 87 | int __init early_is_amd_nb(u32 device) |
87 | { | 88 | { |
88 | struct pci_device_id *id; | 89 | struct pci_device_id *id; |
89 | u32 vendor = device & 0xffff; | 90 | u32 vendor = device & 0xffff; |
90 | device >>= 16; | 91 | device >>= 16; |
91 | for (id = k8_nb_ids; id->vendor; id++) | 92 | for (id = amd_nb_misc_ids; id->vendor; id++) |
92 | if (vendor == id->vendor && device == id->device) | 93 | if (vendor == id->vendor && device == id->device) |
93 | return 1; | 94 | return 1; |
94 | return 0; | 95 | return 0; |
95 | } | 96 | } |
96 | 97 | ||
97 | void k8_flush_garts(void) | 98 | int amd_cache_gart(void) |
99 | { | ||
100 | int i; | ||
101 | |||
102 | if (!amd_nb_has_feature(AMD_NB_GART)) | ||
103 | return 0; | ||
104 | |||
105 | flush_words = kmalloc(amd_nb_num() * sizeof(u32), GFP_KERNEL); | ||
106 | if (!flush_words) { | ||
107 | amd_northbridges.flags &= ~AMD_NB_GART; | ||
108 | return -ENOMEM; | ||
109 | } | ||
110 | |||
111 | for (i = 0; i != amd_nb_num(); i++) | ||
112 | pci_read_config_dword(node_to_amd_nb(i)->misc, 0x9c, | ||
113 | &flush_words[i]); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | void amd_flush_garts(void) | ||
98 | { | 119 | { |
99 | int flushed, i; | 120 | int flushed, i; |
100 | unsigned long flags; | 121 | unsigned long flags; |
101 | static DEFINE_SPINLOCK(gart_lock); | 122 | static DEFINE_SPINLOCK(gart_lock); |
102 | 123 | ||
103 | if (!k8_northbridges.gart_supported) | 124 | if (!amd_nb_has_feature(AMD_NB_GART)) |
104 | return; | 125 | return; |
105 | 126 | ||
106 | /* Avoid races between AGP and IOMMU. In theory it's not needed | 127 | /* Avoid races between AGP and IOMMU. In theory it's not needed |
@@ -109,16 +130,16 @@ void k8_flush_garts(void) | |||
109 | that it doesn't matter to serialize more. -AK */ | 130 | that it doesn't matter to serialize more. -AK */ |
110 | spin_lock_irqsave(&gart_lock, flags); | 131 | spin_lock_irqsave(&gart_lock, flags); |
111 | flushed = 0; | 132 | flushed = 0; |
112 | for (i = 0; i < k8_northbridges.num; i++) { | 133 | for (i = 0; i < amd_nb_num(); i++) { |
113 | pci_write_config_dword(k8_northbridges.nb_misc[i], 0x9c, | 134 | pci_write_config_dword(node_to_amd_nb(i)->misc, 0x9c, |
114 | flush_words[i]|1); | 135 | flush_words[i] | 1); |
115 | flushed++; | 136 | flushed++; |
116 | } | 137 | } |
117 | for (i = 0; i < k8_northbridges.num; i++) { | 138 | for (i = 0; i < amd_nb_num(); i++) { |
118 | u32 w; | 139 | u32 w; |
119 | /* Make sure the hardware actually executed the flush*/ | 140 | /* Make sure the hardware actually executed the flush*/ |
120 | for (;;) { | 141 | for (;;) { |
121 | pci_read_config_dword(k8_northbridges.nb_misc[i], | 142 | pci_read_config_dword(node_to_amd_nb(i)->misc, |
122 | 0x9c, &w); | 143 | 0x9c, &w); |
123 | if (!(w & 1)) | 144 | if (!(w & 1)) |
124 | break; | 145 | break; |
@@ -129,19 +150,23 @@ void k8_flush_garts(void) | |||
129 | if (!flushed) | 150 | if (!flushed) |
130 | printk("nothing to flush?\n"); | 151 | printk("nothing to flush?\n"); |
131 | } | 152 | } |
132 | EXPORT_SYMBOL_GPL(k8_flush_garts); | 153 | EXPORT_SYMBOL_GPL(amd_flush_garts); |
133 | 154 | ||
134 | static __init int init_k8_nbs(void) | 155 | static __init int init_amd_nbs(void) |
135 | { | 156 | { |
136 | int err = 0; | 157 | int err = 0; |
137 | 158 | ||
138 | err = cache_k8_northbridges(); | 159 | err = amd_cache_northbridges(); |
139 | 160 | ||
140 | if (err < 0) | 161 | if (err < 0) |
141 | printk(KERN_NOTICE "K8 NB: Cannot enumerate AMD northbridges.\n"); | 162 | printk(KERN_NOTICE "AMD NB: Cannot enumerate AMD northbridges.\n"); |
163 | |||
164 | if (amd_cache_gart() < 0) | ||
165 | printk(KERN_NOTICE "AMD NB: Cannot initialize GART flush words, " | ||
166 | "GART support disabled.\n"); | ||
142 | 167 | ||
143 | return err; | 168 | return err; |
144 | } | 169 | } |
145 | 170 | ||
146 | /* This has to go after the PCI subsystem */ | 171 | /* This has to go after the PCI subsystem */ |
147 | fs_initcall(init_k8_nbs); | 172 | fs_initcall(init_amd_nbs); |
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c index 92543c73cf8e..7c9ab59653e8 100644 --- a/arch/x86/kernel/apb_timer.c +++ b/arch/x86/kernel/apb_timer.c | |||
@@ -315,6 +315,7 @@ static void apbt_setup_irq(struct apbt_dev *adev) | |||
315 | 315 | ||
316 | if (system_state == SYSTEM_BOOTING) { | 316 | if (system_state == SYSTEM_BOOTING) { |
317 | irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT); | 317 | irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT); |
318 | irq_set_affinity(adev->irq, cpumask_of(adev->cpu)); | ||
318 | /* APB timer irqs are set up as mp_irqs, timer is edge type */ | 319 | /* APB timer irqs are set up as mp_irqs, timer is edge type */ |
319 | __set_irq_handler(adev->irq, handle_edge_irq, 0, "edge"); | 320 | __set_irq_handler(adev->irq, handle_edge_irq, 0, "edge"); |
320 | if (request_irq(adev->irq, apbt_interrupt_handler, | 321 | if (request_irq(adev->irq, apbt_interrupt_handler, |
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index b3a16e8f0703..dcd7c83e1659 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c | |||
@@ -206,7 +206,7 @@ static u32 __init read_agp(int bus, int slot, int func, int cap, u32 *order) | |||
206 | * Do an PCI bus scan by hand because we're running before the PCI | 206 | * Do an PCI bus scan by hand because we're running before the PCI |
207 | * subsystem. | 207 | * subsystem. |
208 | * | 208 | * |
209 | * All K8 AGP bridges are AGPv3 compliant, so we can do this scan | 209 | * All AMD AGP bridges are AGPv3 compliant, so we can do this scan |
210 | * generically. It's probably overkill to always scan all slots because | 210 | * generically. It's probably overkill to always scan all slots because |
211 | * the AGP bridges should be always an own bus on the HT hierarchy, | 211 | * the AGP bridges should be always an own bus on the HT hierarchy, |
212 | * but do it here for future safety. | 212 | * but do it here for future safety. |
@@ -303,7 +303,7 @@ void __init early_gart_iommu_check(void) | |||
303 | dev_limit = bus_dev_ranges[i].dev_limit; | 303 | dev_limit = bus_dev_ranges[i].dev_limit; |
304 | 304 | ||
305 | for (slot = dev_base; slot < dev_limit; slot++) { | 305 | for (slot = dev_base; slot < dev_limit; slot++) { |
306 | if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00))) | 306 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) |
307 | continue; | 307 | continue; |
308 | 308 | ||
309 | ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL); | 309 | ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL); |
@@ -358,7 +358,7 @@ void __init early_gart_iommu_check(void) | |||
358 | dev_limit = bus_dev_ranges[i].dev_limit; | 358 | dev_limit = bus_dev_ranges[i].dev_limit; |
359 | 359 | ||
360 | for (slot = dev_base; slot < dev_limit; slot++) { | 360 | for (slot = dev_base; slot < dev_limit; slot++) { |
361 | if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00))) | 361 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) |
362 | continue; | 362 | continue; |
363 | 363 | ||
364 | ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL); | 364 | ctl = read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL); |
@@ -400,7 +400,7 @@ int __init gart_iommu_hole_init(void) | |||
400 | dev_limit = bus_dev_ranges[i].dev_limit; | 400 | dev_limit = bus_dev_ranges[i].dev_limit; |
401 | 401 | ||
402 | for (slot = dev_base; slot < dev_limit; slot++) { | 402 | for (slot = dev_base; slot < dev_limit; slot++) { |
403 | if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00))) | 403 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) |
404 | continue; | 404 | continue; |
405 | 405 | ||
406 | iommu_detected = 1; | 406 | iommu_detected = 1; |
@@ -518,7 +518,7 @@ out: | |||
518 | dev_base = bus_dev_ranges[i].dev_base; | 518 | dev_base = bus_dev_ranges[i].dev_base; |
519 | dev_limit = bus_dev_ranges[i].dev_limit; | 519 | dev_limit = bus_dev_ranges[i].dev_limit; |
520 | for (slot = dev_base; slot < dev_limit; slot++) { | 520 | for (slot = dev_base; slot < dev_limit; slot++) { |
521 | if (!early_is_k8_nb(read_pci_config(bus, slot, 3, 0x00))) | 521 | if (!early_is_amd_nb(read_pci_config(bus, slot, 3, 0x00))) |
522 | continue; | 522 | continue; |
523 | 523 | ||
524 | write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl); | 524 | write_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL, ctl); |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index fb7657822aad..879999a5230f 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -431,17 +431,18 @@ int setup_APIC_eilvt(u8 offset, u8 vector, u8 msg_type, u8 mask) | |||
431 | reserved = reserve_eilvt_offset(offset, new); | 431 | reserved = reserve_eilvt_offset(offset, new); |
432 | 432 | ||
433 | if (reserved != new) { | 433 | if (reserved != new) { |
434 | pr_err(FW_BUG "cpu %d, try to setup vector 0x%x, but " | 434 | pr_err(FW_BUG "cpu %d, try to use APIC%lX (LVT offset %d) for " |
435 | "vector 0x%x was already reserved by another core, " | 435 | "vector 0x%x, but the register is already in use for " |
436 | "APIC%lX=0x%x\n", | 436 | "vector 0x%x on another cpu\n", |
437 | smp_processor_id(), new, reserved, reg, old); | 437 | smp_processor_id(), reg, offset, new, reserved); |
438 | return -EINVAL; | 438 | return -EINVAL; |
439 | } | 439 | } |
440 | 440 | ||
441 | if (!eilvt_entry_is_changeable(old, new)) { | 441 | if (!eilvt_entry_is_changeable(old, new)) { |
442 | pr_err(FW_BUG "cpu %d, try to setup vector 0x%x but " | 442 | pr_err(FW_BUG "cpu %d, try to use APIC%lX (LVT offset %d) for " |
443 | "register already in use, APIC%lX=0x%x\n", | 443 | "vector 0x%x, but the register is already in use for " |
444 | smp_processor_id(), new, reg, old); | 444 | "vector 0x%x on this cpu\n", |
445 | smp_processor_id(), reg, offset, new, old); | ||
445 | return -EBUSY; | 446 | return -EBUSY; |
446 | } | 447 | } |
447 | 448 | ||
@@ -1532,13 +1533,60 @@ static int __init detect_init_APIC(void) | |||
1532 | return 0; | 1533 | return 0; |
1533 | } | 1534 | } |
1534 | #else | 1535 | #else |
1536 | |||
1537 | static int apic_verify(void) | ||
1538 | { | ||
1539 | u32 features, h, l; | ||
1540 | |||
1541 | /* | ||
1542 | * The APIC feature bit should now be enabled | ||
1543 | * in `cpuid' | ||
1544 | */ | ||
1545 | features = cpuid_edx(1); | ||
1546 | if (!(features & (1 << X86_FEATURE_APIC))) { | ||
1547 | pr_warning("Could not enable APIC!\n"); | ||
1548 | return -1; | ||
1549 | } | ||
1550 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); | ||
1551 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
1552 | |||
1553 | /* The BIOS may have set up the APIC at some other address */ | ||
1554 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1555 | if (l & MSR_IA32_APICBASE_ENABLE) | ||
1556 | mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; | ||
1557 | |||
1558 | pr_info("Found and enabled local APIC!\n"); | ||
1559 | return 0; | ||
1560 | } | ||
1561 | |||
1562 | int apic_force_enable(void) | ||
1563 | { | ||
1564 | u32 h, l; | ||
1565 | |||
1566 | if (disable_apic) | ||
1567 | return -1; | ||
1568 | |||
1569 | /* | ||
1570 | * Some BIOSes disable the local APIC in the APIC_BASE | ||
1571 | * MSR. This can only be done in software for Intel P6 or later | ||
1572 | * and AMD K7 (Model > 1) or later. | ||
1573 | */ | ||
1574 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1575 | if (!(l & MSR_IA32_APICBASE_ENABLE)) { | ||
1576 | pr_info("Local APIC disabled by BIOS -- reenabling.\n"); | ||
1577 | l &= ~MSR_IA32_APICBASE_BASE; | ||
1578 | l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; | ||
1579 | wrmsr(MSR_IA32_APICBASE, l, h); | ||
1580 | enabled_via_apicbase = 1; | ||
1581 | } | ||
1582 | return apic_verify(); | ||
1583 | } | ||
1584 | |||
1535 | /* | 1585 | /* |
1536 | * Detect and initialize APIC | 1586 | * Detect and initialize APIC |
1537 | */ | 1587 | */ |
1538 | static int __init detect_init_APIC(void) | 1588 | static int __init detect_init_APIC(void) |
1539 | { | 1589 | { |
1540 | u32 h, l, features; | ||
1541 | |||
1542 | /* Disabled by kernel option? */ | 1590 | /* Disabled by kernel option? */ |
1543 | if (disable_apic) | 1591 | if (disable_apic) |
1544 | return -1; | 1592 | return -1; |
@@ -1568,38 +1616,12 @@ static int __init detect_init_APIC(void) | |||
1568 | "you can enable it with \"lapic\"\n"); | 1616 | "you can enable it with \"lapic\"\n"); |
1569 | return -1; | 1617 | return -1; |
1570 | } | 1618 | } |
1571 | /* | 1619 | if (apic_force_enable()) |
1572 | * Some BIOSes disable the local APIC in the APIC_BASE | 1620 | return -1; |
1573 | * MSR. This can only be done in software for Intel P6 or later | 1621 | } else { |
1574 | * and AMD K7 (Model > 1) or later. | 1622 | if (apic_verify()) |
1575 | */ | 1623 | return -1; |
1576 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1577 | if (!(l & MSR_IA32_APICBASE_ENABLE)) { | ||
1578 | pr_info("Local APIC disabled by BIOS -- reenabling.\n"); | ||
1579 | l &= ~MSR_IA32_APICBASE_BASE; | ||
1580 | l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE; | ||
1581 | wrmsr(MSR_IA32_APICBASE, l, h); | ||
1582 | enabled_via_apicbase = 1; | ||
1583 | } | ||
1584 | } | ||
1585 | /* | ||
1586 | * The APIC feature bit should now be enabled | ||
1587 | * in `cpuid' | ||
1588 | */ | ||
1589 | features = cpuid_edx(1); | ||
1590 | if (!(features & (1 << X86_FEATURE_APIC))) { | ||
1591 | pr_warning("Could not enable APIC!\n"); | ||
1592 | return -1; | ||
1593 | } | 1624 | } |
1594 | set_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC); | ||
1595 | mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; | ||
1596 | |||
1597 | /* The BIOS may have set up the APIC at some other address */ | ||
1598 | rdmsr(MSR_IA32_APICBASE, l, h); | ||
1599 | if (l & MSR_IA32_APICBASE_ENABLE) | ||
1600 | mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; | ||
1601 | |||
1602 | pr_info("Found and enabled local APIC!\n"); | ||
1603 | 1625 | ||
1604 | apic_pm_activate(); | 1626 | apic_pm_activate(); |
1605 | 1627 | ||
@@ -1687,7 +1709,7 @@ void __init init_apic_mappings(void) | |||
1687 | * This initializes the IO-APIC and APIC hardware if this is | 1709 | * This initializes the IO-APIC and APIC hardware if this is |
1688 | * a UP kernel. | 1710 | * a UP kernel. |
1689 | */ | 1711 | */ |
1690 | int apic_version[MAX_APICS]; | 1712 | int apic_version[MAX_LOCAL_APIC]; |
1691 | 1713 | ||
1692 | int __init APIC_init_uniprocessor(void) | 1714 | int __init APIC_init_uniprocessor(void) |
1693 | { | 1715 | { |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 16c2db8750a2..f6cd5b410770 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -1933,8 +1933,7 @@ void disable_IO_APIC(void) | |||
1933 | * | 1933 | * |
1934 | * by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999 | 1934 | * by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999 |
1935 | */ | 1935 | */ |
1936 | 1936 | void __init setup_ioapic_ids_from_mpc_nocheck(void) | |
1937 | void __init setup_ioapic_ids_from_mpc(void) | ||
1938 | { | 1937 | { |
1939 | union IO_APIC_reg_00 reg_00; | 1938 | union IO_APIC_reg_00 reg_00; |
1940 | physid_mask_t phys_id_present_map; | 1939 | physid_mask_t phys_id_present_map; |
@@ -1943,15 +1942,6 @@ void __init setup_ioapic_ids_from_mpc(void) | |||
1943 | unsigned char old_id; | 1942 | unsigned char old_id; |
1944 | unsigned long flags; | 1943 | unsigned long flags; |
1945 | 1944 | ||
1946 | if (acpi_ioapic) | ||
1947 | return; | ||
1948 | /* | ||
1949 | * Don't check I/O APIC IDs for xAPIC systems. They have | ||
1950 | * no meaning without the serial APIC bus. | ||
1951 | */ | ||
1952 | if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) | ||
1953 | || APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) | ||
1954 | return; | ||
1955 | /* | 1945 | /* |
1956 | * This is broken; anything with a real cpu count has to | 1946 | * This is broken; anything with a real cpu count has to |
1957 | * circumvent this idiocy regardless. | 1947 | * circumvent this idiocy regardless. |
@@ -2005,7 +1995,6 @@ void __init setup_ioapic_ids_from_mpc(void) | |||
2005 | physids_or(phys_id_present_map, phys_id_present_map, tmp); | 1995 | physids_or(phys_id_present_map, phys_id_present_map, tmp); |
2006 | } | 1996 | } |
2007 | 1997 | ||
2008 | |||
2009 | /* | 1998 | /* |
2010 | * We need to adjust the IRQ routing table | 1999 | * We need to adjust the IRQ routing table |
2011 | * if the ID changed. | 2000 | * if the ID changed. |
@@ -2041,6 +2030,21 @@ void __init setup_ioapic_ids_from_mpc(void) | |||
2041 | apic_printk(APIC_VERBOSE, " ok.\n"); | 2030 | apic_printk(APIC_VERBOSE, " ok.\n"); |
2042 | } | 2031 | } |
2043 | } | 2032 | } |
2033 | |||
2034 | void __init setup_ioapic_ids_from_mpc(void) | ||
2035 | { | ||
2036 | |||
2037 | if (acpi_ioapic) | ||
2038 | return; | ||
2039 | /* | ||
2040 | * Don't check I/O APIC IDs for xAPIC systems. They have | ||
2041 | * no meaning without the serial APIC bus. | ||
2042 | */ | ||
2043 | if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) | ||
2044 | || APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) | ||
2045 | return; | ||
2046 | setup_ioapic_ids_from_mpc_nocheck(); | ||
2047 | } | ||
2044 | #endif | 2048 | #endif |
2045 | 2049 | ||
2046 | int no_timer_check __initdata; | 2050 | int no_timer_check __initdata; |
@@ -3593,7 +3597,7 @@ int __init io_apic_get_redir_entries (int ioapic) | |||
3593 | return reg_01.bits.entries + 1; | 3597 | return reg_01.bits.entries + 1; |
3594 | } | 3598 | } |
3595 | 3599 | ||
3596 | void __init probe_nr_irqs_gsi(void) | 3600 | static void __init probe_nr_irqs_gsi(void) |
3597 | { | 3601 | { |
3598 | int nr; | 3602 | int nr; |
3599 | 3603 | ||
@@ -3910,7 +3914,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics) | |||
3910 | return res; | 3914 | return res; |
3911 | } | 3915 | } |
3912 | 3916 | ||
3913 | void __init ioapic_init_mappings(void) | 3917 | void __init ioapic_and_gsi_init(void) |
3914 | { | 3918 | { |
3915 | unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; | 3919 | unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; |
3916 | struct resource *ioapic_res; | 3920 | struct resource *ioapic_res; |
@@ -3948,6 +3952,8 @@ fake_ioapic_page: | |||
3948 | ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1; | 3952 | ioapic_res->end = ioapic_phys + IO_APIC_SLOT_SIZE - 1; |
3949 | ioapic_res++; | 3953 | ioapic_res++; |
3950 | } | 3954 | } |
3955 | |||
3956 | probe_nr_irqs_gsi(); | ||
3951 | } | 3957 | } |
3952 | 3958 | ||
3953 | void __init ioapic_insert_resources(void) | 3959 | void __init ioapic_insert_resources(void) |
@@ -4057,7 +4063,8 @@ void __init pre_init_apic_IRQ0(void) | |||
4057 | 4063 | ||
4058 | printk(KERN_INFO "Early APIC setup for system timer0\n"); | 4064 | printk(KERN_INFO "Early APIC setup for system timer0\n"); |
4059 | #ifndef CONFIG_SMP | 4065 | #ifndef CONFIG_SMP |
4060 | phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); | 4066 | physid_set_mask_of_physid(boot_cpu_physical_apicid, |
4067 | &phys_cpu_present_map); | ||
4061 | #endif | 4068 | #endif |
4062 | /* Make sure the irq descriptor is set up */ | 4069 | /* Make sure the irq descriptor is set up */ |
4063 | cfg = alloc_irq_and_cfg_at(0, 0); | 4070 | cfg = alloc_irq_and_cfg_at(0, 0); |
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 927902d90fe6..936613e77113 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c | |||
@@ -48,6 +48,16 @@ unsigned int uv_apicid_hibits; | |||
48 | EXPORT_SYMBOL_GPL(uv_apicid_hibits); | 48 | EXPORT_SYMBOL_GPL(uv_apicid_hibits); |
49 | static DEFINE_SPINLOCK(uv_nmi_lock); | 49 | static DEFINE_SPINLOCK(uv_nmi_lock); |
50 | 50 | ||
51 | static unsigned long __init uv_early_read_mmr(unsigned long addr) | ||
52 | { | ||
53 | unsigned long val, *mmr; | ||
54 | |||
55 | mmr = early_ioremap(UV_LOCAL_MMR_BASE | addr, sizeof(*mmr)); | ||
56 | val = *mmr; | ||
57 | early_iounmap(mmr, sizeof(*mmr)); | ||
58 | return val; | ||
59 | } | ||
60 | |||
51 | static inline bool is_GRU_range(u64 start, u64 end) | 61 | static inline bool is_GRU_range(u64 start, u64 end) |
52 | { | 62 | { |
53 | return start >= gru_start_paddr && end <= gru_end_paddr; | 63 | return start >= gru_start_paddr && end <= gru_end_paddr; |
@@ -58,28 +68,24 @@ static bool uv_is_untracked_pat_range(u64 start, u64 end) | |||
58 | return is_ISA_range(start, end) || is_GRU_range(start, end); | 68 | return is_ISA_range(start, end) || is_GRU_range(start, end); |
59 | } | 69 | } |
60 | 70 | ||
61 | static int early_get_nodeid(void) | 71 | static int __init early_get_pnodeid(void) |
62 | { | 72 | { |
63 | union uvh_node_id_u node_id; | 73 | union uvh_node_id_u node_id; |
64 | unsigned long *mmr; | 74 | union uvh_rh_gam_config_mmr_u m_n_config; |
65 | 75 | int pnode; | |
66 | mmr = early_ioremap(UV_LOCAL_MMR_BASE | UVH_NODE_ID, sizeof(*mmr)); | ||
67 | node_id.v = *mmr; | ||
68 | early_iounmap(mmr, sizeof(*mmr)); | ||
69 | 76 | ||
70 | /* Currently, all blades have same revision number */ | 77 | /* Currently, all blades have same revision number */ |
78 | node_id.v = uv_early_read_mmr(UVH_NODE_ID); | ||
79 | m_n_config.v = uv_early_read_mmr(UVH_RH_GAM_CONFIG_MMR); | ||
71 | uv_min_hub_revision_id = node_id.s.revision; | 80 | uv_min_hub_revision_id = node_id.s.revision; |
72 | 81 | ||
73 | return node_id.s.node_id; | 82 | pnode = (node_id.s.node_id >> 1) & ((1 << m_n_config.s.n_skt) - 1); |
83 | return pnode; | ||
74 | } | 84 | } |
75 | 85 | ||
76 | static void __init early_get_apic_pnode_shift(void) | 86 | static void __init early_get_apic_pnode_shift(void) |
77 | { | 87 | { |
78 | unsigned long *mmr; | 88 | uvh_apicid.v = uv_early_read_mmr(UVH_APICID); |
79 | |||
80 | mmr = early_ioremap(UV_LOCAL_MMR_BASE | UVH_APICID, sizeof(*mmr)); | ||
81 | uvh_apicid.v = *mmr; | ||
82 | early_iounmap(mmr, sizeof(*mmr)); | ||
83 | if (!uvh_apicid.v) | 89 | if (!uvh_apicid.v) |
84 | /* | 90 | /* |
85 | * Old bios, use default value | 91 | * Old bios, use default value |
@@ -95,21 +101,17 @@ static void __init early_get_apic_pnode_shift(void) | |||
95 | static void __init uv_set_apicid_hibit(void) | 101 | static void __init uv_set_apicid_hibit(void) |
96 | { | 102 | { |
97 | union uvh_lb_target_physical_apic_id_mask_u apicid_mask; | 103 | union uvh_lb_target_physical_apic_id_mask_u apicid_mask; |
98 | unsigned long *mmr; | ||
99 | 104 | ||
100 | mmr = early_ioremap(UV_LOCAL_MMR_BASE | | 105 | apicid_mask.v = uv_early_read_mmr(UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK); |
101 | UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK, sizeof(*mmr)); | ||
102 | apicid_mask.v = *mmr; | ||
103 | early_iounmap(mmr, sizeof(*mmr)); | ||
104 | uv_apicid_hibits = apicid_mask.s.bit_enables & UV_APICID_HIBIT_MASK; | 106 | uv_apicid_hibits = apicid_mask.s.bit_enables & UV_APICID_HIBIT_MASK; |
105 | } | 107 | } |
106 | 108 | ||
107 | static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 109 | static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) |
108 | { | 110 | { |
109 | int nodeid; | 111 | int pnodeid; |
110 | 112 | ||
111 | if (!strcmp(oem_id, "SGI")) { | 113 | if (!strcmp(oem_id, "SGI")) { |
112 | nodeid = early_get_nodeid(); | 114 | pnodeid = early_get_pnodeid(); |
113 | early_get_apic_pnode_shift(); | 115 | early_get_apic_pnode_shift(); |
114 | x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; | 116 | x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; |
115 | x86_platform.nmi_init = uv_nmi_init; | 117 | x86_platform.nmi_init = uv_nmi_init; |
@@ -119,7 +121,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) | |||
119 | uv_system_type = UV_X2APIC; | 121 | uv_system_type = UV_X2APIC; |
120 | else if (!strcmp(oem_table_id, "UVH")) { | 122 | else if (!strcmp(oem_table_id, "UVH")) { |
121 | __get_cpu_var(x2apic_extra_bits) = | 123 | __get_cpu_var(x2apic_extra_bits) = |
122 | nodeid << (uvh_apicid.s.pnode_shift - 1); | 124 | pnodeid << uvh_apicid.s.pnode_shift; |
123 | uv_system_type = UV_NON_UNIQUE_APIC; | 125 | uv_system_type = UV_NON_UNIQUE_APIC; |
124 | uv_set_apicid_hibit(); | 126 | uv_set_apicid_hibit(); |
125 | return 1; | 127 | return 1; |
@@ -682,27 +684,32 @@ void uv_nmi_init(void) | |||
682 | void __init uv_system_init(void) | 684 | void __init uv_system_init(void) |
683 | { | 685 | { |
684 | union uvh_rh_gam_config_mmr_u m_n_config; | 686 | union uvh_rh_gam_config_mmr_u m_n_config; |
687 | union uvh_rh_gam_mmioh_overlay_config_mmr_u mmioh; | ||
685 | union uvh_node_id_u node_id; | 688 | union uvh_node_id_u node_id; |
686 | unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size; | 689 | unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size; |
687 | int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val; | 690 | int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val, n_io; |
688 | int gnode_extra, max_pnode = 0; | 691 | int gnode_extra, max_pnode = 0; |
689 | unsigned long mmr_base, present, paddr; | 692 | unsigned long mmr_base, present, paddr; |
690 | unsigned short pnode_mask; | 693 | unsigned short pnode_mask, pnode_io_mask; |
691 | 694 | ||
692 | map_low_mmrs(); | 695 | map_low_mmrs(); |
693 | 696 | ||
694 | m_n_config.v = uv_read_local_mmr(UVH_RH_GAM_CONFIG_MMR ); | 697 | m_n_config.v = uv_read_local_mmr(UVH_RH_GAM_CONFIG_MMR ); |
695 | m_val = m_n_config.s.m_skt; | 698 | m_val = m_n_config.s.m_skt; |
696 | n_val = m_n_config.s.n_skt; | 699 | n_val = m_n_config.s.n_skt; |
700 | mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR); | ||
701 | n_io = mmioh.s.n_io; | ||
697 | mmr_base = | 702 | mmr_base = |
698 | uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) & | 703 | uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) & |
699 | ~UV_MMR_ENABLE; | 704 | ~UV_MMR_ENABLE; |
700 | pnode_mask = (1 << n_val) - 1; | 705 | pnode_mask = (1 << n_val) - 1; |
706 | pnode_io_mask = (1 << n_io) - 1; | ||
707 | |||
701 | node_id.v = uv_read_local_mmr(UVH_NODE_ID); | 708 | node_id.v = uv_read_local_mmr(UVH_NODE_ID); |
702 | gnode_extra = (node_id.s.node_id & ~((1 << n_val) - 1)) >> 1; | 709 | gnode_extra = (node_id.s.node_id & ~((1 << n_val) - 1)) >> 1; |
703 | gnode_upper = ((unsigned long)gnode_extra << m_val); | 710 | gnode_upper = ((unsigned long)gnode_extra << m_val); |
704 | printk(KERN_DEBUG "UV: N %d, M %d, gnode_upper 0x%lx, gnode_extra 0x%x\n", | 711 | printk(KERN_INFO "UV: N %d, M %d, N_IO: %d, gnode_upper 0x%lx, gnode_extra 0x%x, pnode_mask 0x%x, pnode_io_mask 0x%x\n", |
705 | n_val, m_val, gnode_upper, gnode_extra); | 712 | n_val, m_val, n_io, gnode_upper, gnode_extra, pnode_mask, pnode_io_mask); |
706 | 713 | ||
707 | printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base); | 714 | printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base); |
708 | 715 | ||
@@ -735,7 +742,7 @@ void __init uv_system_init(void) | |||
735 | for (j = 0; j < 64; j++) { | 742 | for (j = 0; j < 64; j++) { |
736 | if (!test_bit(j, &present)) | 743 | if (!test_bit(j, &present)) |
737 | continue; | 744 | continue; |
738 | pnode = (i * 64 + j); | 745 | pnode = (i * 64 + j) & pnode_mask; |
739 | uv_blade_info[blade].pnode = pnode; | 746 | uv_blade_info[blade].pnode = pnode; |
740 | uv_blade_info[blade].nr_possible_cpus = 0; | 747 | uv_blade_info[blade].nr_possible_cpus = 0; |
741 | uv_blade_info[blade].nr_online_cpus = 0; | 748 | uv_blade_info[blade].nr_online_cpus = 0; |
@@ -756,6 +763,7 @@ void __init uv_system_init(void) | |||
756 | /* | 763 | /* |
757 | * apic_pnode_shift must be set before calling uv_apicid_to_pnode(); | 764 | * apic_pnode_shift must be set before calling uv_apicid_to_pnode(); |
758 | */ | 765 | */ |
766 | uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask; | ||
759 | uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift; | 767 | uv_cpu_hub_info(cpu)->apic_pnode_shift = uvh_apicid.s.pnode_shift; |
760 | pnode = uv_apicid_to_pnode(apicid); | 768 | pnode = uv_apicid_to_pnode(apicid); |
761 | blade = boot_pnode_to_blade(pnode); | 769 | blade = boot_pnode_to_blade(pnode); |
@@ -772,7 +780,6 @@ void __init uv_system_init(void) | |||
772 | uv_cpu_hub_info(cpu)->numa_blade_id = blade; | 780 | uv_cpu_hub_info(cpu)->numa_blade_id = blade; |
773 | uv_cpu_hub_info(cpu)->blade_processor_id = lcpu; | 781 | uv_cpu_hub_info(cpu)->blade_processor_id = lcpu; |
774 | uv_cpu_hub_info(cpu)->pnode = pnode; | 782 | uv_cpu_hub_info(cpu)->pnode = pnode; |
775 | uv_cpu_hub_info(cpu)->pnode_mask = pnode_mask; | ||
776 | uv_cpu_hub_info(cpu)->gpa_mask = (1UL << (m_val + n_val)) - 1; | 783 | uv_cpu_hub_info(cpu)->gpa_mask = (1UL << (m_val + n_val)) - 1; |
777 | uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper; | 784 | uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper; |
778 | uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra; | 785 | uv_cpu_hub_info(cpu)->gnode_extra = gnode_extra; |
@@ -796,7 +803,7 @@ void __init uv_system_init(void) | |||
796 | 803 | ||
797 | map_gru_high(max_pnode); | 804 | map_gru_high(max_pnode); |
798 | map_mmr_high(max_pnode); | 805 | map_mmr_high(max_pnode); |
799 | map_mmioh_high(max_pnode); | 806 | map_mmioh_high(max_pnode & pnode_io_mask); |
800 | 807 | ||
801 | uv_cpu_init(); | 808 | uv_cpu_init(); |
802 | uv_scir_register_cpu_notifier(); | 809 | uv_scir_register_cpu_notifier(); |
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 17ad03366211..9ecf81f9b90f 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
@@ -149,8 +149,7 @@ union _cpuid4_leaf_ecx { | |||
149 | }; | 149 | }; |
150 | 150 | ||
151 | struct amd_l3_cache { | 151 | struct amd_l3_cache { |
152 | struct pci_dev *dev; | 152 | struct amd_northbridge *nb; |
153 | bool can_disable; | ||
154 | unsigned indices; | 153 | unsigned indices; |
155 | u8 subcaches[4]; | 154 | u8 subcaches[4]; |
156 | }; | 155 | }; |
@@ -311,14 +310,12 @@ struct _cache_attr { | |||
311 | /* | 310 | /* |
312 | * L3 cache descriptors | 311 | * L3 cache descriptors |
313 | */ | 312 | */ |
314 | static struct amd_l3_cache **__cpuinitdata l3_caches; | ||
315 | |||
316 | static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) | 313 | static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) |
317 | { | 314 | { |
318 | unsigned int sc0, sc1, sc2, sc3; | 315 | unsigned int sc0, sc1, sc2, sc3; |
319 | u32 val = 0; | 316 | u32 val = 0; |
320 | 317 | ||
321 | pci_read_config_dword(l3->dev, 0x1C4, &val); | 318 | pci_read_config_dword(l3->nb->misc, 0x1C4, &val); |
322 | 319 | ||
323 | /* calculate subcache sizes */ | 320 | /* calculate subcache sizes */ |
324 | l3->subcaches[0] = sc0 = !(val & BIT(0)); | 321 | l3->subcaches[0] = sc0 = !(val & BIT(0)); |
@@ -330,47 +327,14 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) | |||
330 | l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1; | 327 | l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1; |
331 | } | 328 | } |
332 | 329 | ||
333 | static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node) | 330 | static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, |
334 | { | 331 | int index) |
335 | struct amd_l3_cache *l3; | ||
336 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
337 | |||
338 | l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC); | ||
339 | if (!l3) { | ||
340 | printk(KERN_WARNING "Error allocating L3 struct\n"); | ||
341 | return NULL; | ||
342 | } | ||
343 | |||
344 | l3->dev = dev; | ||
345 | |||
346 | amd_calc_l3_indices(l3); | ||
347 | |||
348 | return l3; | ||
349 | } | ||
350 | |||
351 | static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, | ||
352 | int index) | ||
353 | { | 332 | { |
333 | static struct amd_l3_cache *__cpuinitdata l3_caches; | ||
354 | int node; | 334 | int node; |
355 | 335 | ||
356 | if (boot_cpu_data.x86 != 0x10) | 336 | /* only for L3, and not in virtualized environments */ |
357 | return; | 337 | if (index < 3 || amd_nb_num() == 0) |
358 | |||
359 | if (index < 3) | ||
360 | return; | ||
361 | |||
362 | /* see errata #382 and #388 */ | ||
363 | if (boot_cpu_data.x86_model < 0x8) | ||
364 | return; | ||
365 | |||
366 | if ((boot_cpu_data.x86_model == 0x8 || | ||
367 | boot_cpu_data.x86_model == 0x9) | ||
368 | && | ||
369 | boot_cpu_data.x86_mask < 0x1) | ||
370 | return; | ||
371 | |||
372 | /* not in virtualized environments */ | ||
373 | if (k8_northbridges.num == 0) | ||
374 | return; | 338 | return; |
375 | 339 | ||
376 | /* | 340 | /* |
@@ -378,7 +342,7 @@ static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, | |||
378 | * never freed but this is done only on shutdown so it doesn't matter. | 342 | * never freed but this is done only on shutdown so it doesn't matter. |
379 | */ | 343 | */ |
380 | if (!l3_caches) { | 344 | if (!l3_caches) { |
381 | int size = k8_northbridges.num * sizeof(struct amd_l3_cache *); | 345 | int size = amd_nb_num() * sizeof(struct amd_l3_cache); |
382 | 346 | ||
383 | l3_caches = kzalloc(size, GFP_ATOMIC); | 347 | l3_caches = kzalloc(size, GFP_ATOMIC); |
384 | if (!l3_caches) | 348 | if (!l3_caches) |
@@ -387,14 +351,12 @@ static void __cpuinit amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, | |||
387 | 351 | ||
388 | node = amd_get_nb_id(smp_processor_id()); | 352 | node = amd_get_nb_id(smp_processor_id()); |
389 | 353 | ||
390 | if (!l3_caches[node]) { | 354 | if (!l3_caches[node].nb) { |
391 | l3_caches[node] = amd_init_l3_cache(node); | 355 | l3_caches[node].nb = node_to_amd_nb(node); |
392 | l3_caches[node]->can_disable = true; | 356 | amd_calc_l3_indices(&l3_caches[node]); |
393 | } | 357 | } |
394 | 358 | ||
395 | WARN_ON(!l3_caches[node]); | 359 | this_leaf->l3 = &l3_caches[node]; |
396 | |||
397 | this_leaf->l3 = l3_caches[node]; | ||
398 | } | 360 | } |
399 | 361 | ||
400 | /* | 362 | /* |
@@ -408,7 +370,7 @@ int amd_get_l3_disable_slot(struct amd_l3_cache *l3, unsigned slot) | |||
408 | { | 370 | { |
409 | unsigned int reg = 0; | 371 | unsigned int reg = 0; |
410 | 372 | ||
411 | pci_read_config_dword(l3->dev, 0x1BC + slot * 4, ®); | 373 | pci_read_config_dword(l3->nb->misc, 0x1BC + slot * 4, ®); |
412 | 374 | ||
413 | /* check whether this slot is activated already */ | 375 | /* check whether this slot is activated already */ |
414 | if (reg & (3UL << 30)) | 376 | if (reg & (3UL << 30)) |
@@ -422,7 +384,8 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, | |||
422 | { | 384 | { |
423 | int index; | 385 | int index; |
424 | 386 | ||
425 | if (!this_leaf->l3 || !this_leaf->l3->can_disable) | 387 | if (!this_leaf->l3 || |
388 | !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | ||
426 | return -EINVAL; | 389 | return -EINVAL; |
427 | 390 | ||
428 | index = amd_get_l3_disable_slot(this_leaf->l3, slot); | 391 | index = amd_get_l3_disable_slot(this_leaf->l3, slot); |
@@ -457,7 +420,7 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, | |||
457 | if (!l3->subcaches[i]) | 420 | if (!l3->subcaches[i]) |
458 | continue; | 421 | continue; |
459 | 422 | ||
460 | pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg); | 423 | pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); |
461 | 424 | ||
462 | /* | 425 | /* |
463 | * We need to WBINVD on a core on the node containing the L3 | 426 | * We need to WBINVD on a core on the node containing the L3 |
@@ -467,7 +430,7 @@ static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, | |||
467 | wbinvd_on_cpu(cpu); | 430 | wbinvd_on_cpu(cpu); |
468 | 431 | ||
469 | reg |= BIT(31); | 432 | reg |= BIT(31); |
470 | pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg); | 433 | pci_write_config_dword(l3->nb->misc, 0x1BC + slot * 4, reg); |
471 | } | 434 | } |
472 | } | 435 | } |
473 | 436 | ||
@@ -524,7 +487,8 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | |||
524 | if (!capable(CAP_SYS_ADMIN)) | 487 | if (!capable(CAP_SYS_ADMIN)) |
525 | return -EPERM; | 488 | return -EPERM; |
526 | 489 | ||
527 | if (!this_leaf->l3 || !this_leaf->l3->can_disable) | 490 | if (!this_leaf->l3 || |
491 | !amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | ||
528 | return -EINVAL; | 492 | return -EINVAL; |
529 | 493 | ||
530 | cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | 494 | cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); |
@@ -545,7 +509,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | |||
545 | #define STORE_CACHE_DISABLE(slot) \ | 509 | #define STORE_CACHE_DISABLE(slot) \ |
546 | static ssize_t \ | 510 | static ssize_t \ |
547 | store_cache_disable_##slot(struct _cpuid4_info *this_leaf, \ | 511 | store_cache_disable_##slot(struct _cpuid4_info *this_leaf, \ |
548 | const char *buf, size_t count) \ | 512 | const char *buf, size_t count) \ |
549 | { \ | 513 | { \ |
550 | return store_cache_disable(this_leaf, buf, count, slot); \ | 514 | return store_cache_disable(this_leaf, buf, count, slot); \ |
551 | } | 515 | } |
@@ -558,10 +522,7 @@ static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644, | |||
558 | show_cache_disable_1, store_cache_disable_1); | 522 | show_cache_disable_1, store_cache_disable_1); |
559 | 523 | ||
560 | #else /* CONFIG_AMD_NB */ | 524 | #else /* CONFIG_AMD_NB */ |
561 | static void __cpuinit | 525 | #define amd_init_l3_cache(x, y) |
562 | amd_check_l3_disable(struct _cpuid4_info_regs *this_leaf, int index) | ||
563 | { | ||
564 | }; | ||
565 | #endif /* CONFIG_AMD_NB */ | 526 | #endif /* CONFIG_AMD_NB */ |
566 | 527 | ||
567 | static int | 528 | static int |
@@ -575,7 +536,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index, | |||
575 | 536 | ||
576 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { | 537 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { |
577 | amd_cpuid4(index, &eax, &ebx, &ecx); | 538 | amd_cpuid4(index, &eax, &ebx, &ecx); |
578 | amd_check_l3_disable(this_leaf, index); | 539 | amd_init_l3_cache(this_leaf, index); |
579 | } else { | 540 | } else { |
580 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); | 541 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); |
581 | } | 542 | } |
@@ -983,30 +944,48 @@ define_one_ro(size); | |||
983 | define_one_ro(shared_cpu_map); | 944 | define_one_ro(shared_cpu_map); |
984 | define_one_ro(shared_cpu_list); | 945 | define_one_ro(shared_cpu_list); |
985 | 946 | ||
986 | #define DEFAULT_SYSFS_CACHE_ATTRS \ | ||
987 | &type.attr, \ | ||
988 | &level.attr, \ | ||
989 | &coherency_line_size.attr, \ | ||
990 | &physical_line_partition.attr, \ | ||
991 | &ways_of_associativity.attr, \ | ||
992 | &number_of_sets.attr, \ | ||
993 | &size.attr, \ | ||
994 | &shared_cpu_map.attr, \ | ||
995 | &shared_cpu_list.attr | ||
996 | |||
997 | static struct attribute *default_attrs[] = { | 947 | static struct attribute *default_attrs[] = { |
998 | DEFAULT_SYSFS_CACHE_ATTRS, | 948 | &type.attr, |
949 | &level.attr, | ||
950 | &coherency_line_size.attr, | ||
951 | &physical_line_partition.attr, | ||
952 | &ways_of_associativity.attr, | ||
953 | &number_of_sets.attr, | ||
954 | &size.attr, | ||
955 | &shared_cpu_map.attr, | ||
956 | &shared_cpu_list.attr, | ||
999 | NULL | 957 | NULL |
1000 | }; | 958 | }; |
1001 | 959 | ||
1002 | static struct attribute *default_l3_attrs[] = { | ||
1003 | DEFAULT_SYSFS_CACHE_ATTRS, | ||
1004 | #ifdef CONFIG_AMD_NB | 960 | #ifdef CONFIG_AMD_NB |
1005 | &cache_disable_0.attr, | 961 | static struct attribute ** __cpuinit amd_l3_attrs(void) |
1006 | &cache_disable_1.attr, | 962 | { |
963 | static struct attribute **attrs; | ||
964 | int n; | ||
965 | |||
966 | if (attrs) | ||
967 | return attrs; | ||
968 | |||
969 | n = sizeof (default_attrs) / sizeof (struct attribute *); | ||
970 | |||
971 | if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) | ||
972 | n += 2; | ||
973 | |||
974 | attrs = kzalloc(n * sizeof (struct attribute *), GFP_KERNEL); | ||
975 | if (attrs == NULL) | ||
976 | return attrs = default_attrs; | ||
977 | |||
978 | for (n = 0; default_attrs[n]; n++) | ||
979 | attrs[n] = default_attrs[n]; | ||
980 | |||
981 | if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE)) { | ||
982 | attrs[n++] = &cache_disable_0.attr; | ||
983 | attrs[n++] = &cache_disable_1.attr; | ||
984 | } | ||
985 | |||
986 | return attrs; | ||
987 | } | ||
1007 | #endif | 988 | #endif |
1008 | NULL | ||
1009 | }; | ||
1010 | 989 | ||
1011 | static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) | 990 | static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) |
1012 | { | 991 | { |
@@ -1117,11 +1096,11 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) | |||
1117 | 1096 | ||
1118 | this_leaf = CPUID4_INFO_IDX(cpu, i); | 1097 | this_leaf = CPUID4_INFO_IDX(cpu, i); |
1119 | 1098 | ||
1120 | if (this_leaf->l3 && this_leaf->l3->can_disable) | 1099 | ktype_cache.default_attrs = default_attrs; |
1121 | ktype_cache.default_attrs = default_l3_attrs; | 1100 | #ifdef CONFIG_AMD_NB |
1122 | else | 1101 | if (this_leaf->l3) |
1123 | ktype_cache.default_attrs = default_attrs; | 1102 | ktype_cache.default_attrs = amd_l3_attrs(); |
1124 | 1103 | #endif | |
1125 | retval = kobject_init_and_add(&(this_object->kobj), | 1104 | retval = kobject_init_and_add(&(this_object->kobj), |
1126 | &ktype_cache, | 1105 | &ktype_cache, |
1127 | per_cpu(ici_cache_kobject, cpu), | 1106 | per_cpu(ici_cache_kobject, cpu), |
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 80c482382d5c..5bf2fac52aca 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c | |||
@@ -31,8 +31,6 @@ | |||
31 | #include <asm/mce.h> | 31 | #include <asm/mce.h> |
32 | #include <asm/msr.h> | 32 | #include <asm/msr.h> |
33 | 33 | ||
34 | #define PFX "mce_threshold: " | ||
35 | #define VERSION "version 1.1.1" | ||
36 | #define NR_BANKS 6 | 34 | #define NR_BANKS 6 |
37 | #define NR_BLOCKS 9 | 35 | #define NR_BLOCKS 9 |
38 | #define THRESHOLD_MAX 0xFFF | 36 | #define THRESHOLD_MAX 0xFFF |
@@ -59,12 +57,6 @@ struct threshold_block { | |||
59 | struct list_head miscj; | 57 | struct list_head miscj; |
60 | }; | 58 | }; |
61 | 59 | ||
62 | /* defaults used early on boot */ | ||
63 | static struct threshold_block threshold_defaults = { | ||
64 | .interrupt_enable = 0, | ||
65 | .threshold_limit = THRESHOLD_MAX, | ||
66 | }; | ||
67 | |||
68 | struct threshold_bank { | 60 | struct threshold_bank { |
69 | struct kobject *kobj; | 61 | struct kobject *kobj; |
70 | struct threshold_block *blocks; | 62 | struct threshold_block *blocks; |
@@ -89,50 +81,101 @@ static void amd_threshold_interrupt(void); | |||
89 | struct thresh_restart { | 81 | struct thresh_restart { |
90 | struct threshold_block *b; | 82 | struct threshold_block *b; |
91 | int reset; | 83 | int reset; |
84 | int set_lvt_off; | ||
85 | int lvt_off; | ||
92 | u16 old_limit; | 86 | u16 old_limit; |
93 | }; | 87 | }; |
94 | 88 | ||
89 | static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi) | ||
90 | { | ||
91 | int msr = (hi & MASK_LVTOFF_HI) >> 20; | ||
92 | |||
93 | if (apic < 0) { | ||
94 | pr_err(FW_BUG "cpu %d, failed to setup threshold interrupt " | ||
95 | "for bank %d, block %d (MSR%08X=0x%x%08x)\n", b->cpu, | ||
96 | b->bank, b->block, b->address, hi, lo); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | if (apic != msr) { | ||
101 | pr_err(FW_BUG "cpu %d, invalid threshold interrupt offset %d " | ||
102 | "for bank %d, block %d (MSR%08X=0x%x%08x)\n", | ||
103 | b->cpu, apic, b->bank, b->block, b->address, hi, lo); | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | return 1; | ||
108 | }; | ||
109 | |||
95 | /* must be called with correct cpu affinity */ | 110 | /* must be called with correct cpu affinity */ |
96 | /* Called via smp_call_function_single() */ | 111 | /* Called via smp_call_function_single() */ |
97 | static void threshold_restart_bank(void *_tr) | 112 | static void threshold_restart_bank(void *_tr) |
98 | { | 113 | { |
99 | struct thresh_restart *tr = _tr; | 114 | struct thresh_restart *tr = _tr; |
100 | u32 mci_misc_hi, mci_misc_lo; | 115 | u32 hi, lo; |
101 | 116 | ||
102 | rdmsr(tr->b->address, mci_misc_lo, mci_misc_hi); | 117 | rdmsr(tr->b->address, lo, hi); |
103 | 118 | ||
104 | if (tr->b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX)) | 119 | if (tr->b->threshold_limit < (hi & THRESHOLD_MAX)) |
105 | tr->reset = 1; /* limit cannot be lower than err count */ | 120 | tr->reset = 1; /* limit cannot be lower than err count */ |
106 | 121 | ||
107 | if (tr->reset) { /* reset err count and overflow bit */ | 122 | if (tr->reset) { /* reset err count and overflow bit */ |
108 | mci_misc_hi = | 123 | hi = |
109 | (mci_misc_hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) | | 124 | (hi & ~(MASK_ERR_COUNT_HI | MASK_OVERFLOW_HI)) | |
110 | (THRESHOLD_MAX - tr->b->threshold_limit); | 125 | (THRESHOLD_MAX - tr->b->threshold_limit); |
111 | } else if (tr->old_limit) { /* change limit w/o reset */ | 126 | } else if (tr->old_limit) { /* change limit w/o reset */ |
112 | int new_count = (mci_misc_hi & THRESHOLD_MAX) + | 127 | int new_count = (hi & THRESHOLD_MAX) + |
113 | (tr->old_limit - tr->b->threshold_limit); | 128 | (tr->old_limit - tr->b->threshold_limit); |
114 | 129 | ||
115 | mci_misc_hi = (mci_misc_hi & ~MASK_ERR_COUNT_HI) | | 130 | hi = (hi & ~MASK_ERR_COUNT_HI) | |
116 | (new_count & THRESHOLD_MAX); | 131 | (new_count & THRESHOLD_MAX); |
117 | } | 132 | } |
118 | 133 | ||
134 | if (tr->set_lvt_off) { | ||
135 | if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) { | ||
136 | /* set new lvt offset */ | ||
137 | hi &= ~MASK_LVTOFF_HI; | ||
138 | hi |= tr->lvt_off << 20; | ||
139 | } | ||
140 | } | ||
141 | |||
119 | tr->b->interrupt_enable ? | 142 | tr->b->interrupt_enable ? |
120 | (mci_misc_hi = (mci_misc_hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) : | 143 | (hi = (hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) : |
121 | (mci_misc_hi &= ~MASK_INT_TYPE_HI); | 144 | (hi &= ~MASK_INT_TYPE_HI); |
122 | 145 | ||
123 | mci_misc_hi |= MASK_COUNT_EN_HI; | 146 | hi |= MASK_COUNT_EN_HI; |
124 | wrmsr(tr->b->address, mci_misc_lo, mci_misc_hi); | 147 | wrmsr(tr->b->address, lo, hi); |
148 | } | ||
149 | |||
150 | static void mce_threshold_block_init(struct threshold_block *b, int offset) | ||
151 | { | ||
152 | struct thresh_restart tr = { | ||
153 | .b = b, | ||
154 | .set_lvt_off = 1, | ||
155 | .lvt_off = offset, | ||
156 | }; | ||
157 | |||
158 | b->threshold_limit = THRESHOLD_MAX; | ||
159 | threshold_restart_bank(&tr); | ||
160 | }; | ||
161 | |||
162 | static int setup_APIC_mce(int reserved, int new) | ||
163 | { | ||
164 | if (reserved < 0 && !setup_APIC_eilvt(new, THRESHOLD_APIC_VECTOR, | ||
165 | APIC_EILVT_MSG_FIX, 0)) | ||
166 | return new; | ||
167 | |||
168 | return reserved; | ||
125 | } | 169 | } |
126 | 170 | ||
127 | /* cpu init entry point, called from mce.c with preempt off */ | 171 | /* cpu init entry point, called from mce.c with preempt off */ |
128 | void mce_amd_feature_init(struct cpuinfo_x86 *c) | 172 | void mce_amd_feature_init(struct cpuinfo_x86 *c) |
129 | { | 173 | { |
174 | struct threshold_block b; | ||
130 | unsigned int cpu = smp_processor_id(); | 175 | unsigned int cpu = smp_processor_id(); |
131 | u32 low = 0, high = 0, address = 0; | 176 | u32 low = 0, high = 0, address = 0; |
132 | unsigned int bank, block; | 177 | unsigned int bank, block; |
133 | struct thresh_restart tr; | 178 | int offset = -1; |
134 | int lvt_off = -1; | ||
135 | u8 offset; | ||
136 | 179 | ||
137 | for (bank = 0; bank < NR_BANKS; ++bank) { | 180 | for (bank = 0; bank < NR_BANKS; ++bank) { |
138 | for (block = 0; block < NR_BLOCKS; ++block) { | 181 | for (block = 0; block < NR_BLOCKS; ++block) { |
@@ -163,39 +206,16 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) | |||
163 | if (shared_bank[bank] && c->cpu_core_id) | 206 | if (shared_bank[bank] && c->cpu_core_id) |
164 | break; | 207 | break; |
165 | #endif | 208 | #endif |
166 | offset = (high & MASK_LVTOFF_HI) >> 20; | 209 | offset = setup_APIC_mce(offset, |
167 | if (lvt_off < 0) { | 210 | (high & MASK_LVTOFF_HI) >> 20); |
168 | if (setup_APIC_eilvt(offset, | ||
169 | THRESHOLD_APIC_VECTOR, | ||
170 | APIC_EILVT_MSG_FIX, 0)) { | ||
171 | pr_err(FW_BUG "cpu %d, failed to " | ||
172 | "setup threshold interrupt " | ||
173 | "for bank %d, block %d " | ||
174 | "(MSR%08X=0x%x%08x)", | ||
175 | smp_processor_id(), bank, block, | ||
176 | address, high, low); | ||
177 | continue; | ||
178 | } | ||
179 | lvt_off = offset; | ||
180 | } else if (lvt_off != offset) { | ||
181 | pr_err(FW_BUG "cpu %d, invalid threshold " | ||
182 | "interrupt offset %d for bank %d," | ||
183 | "block %d (MSR%08X=0x%x%08x)", | ||
184 | smp_processor_id(), lvt_off, bank, | ||
185 | block, address, high, low); | ||
186 | continue; | ||
187 | } | ||
188 | |||
189 | high &= ~MASK_LVTOFF_HI; | ||
190 | high |= lvt_off << 20; | ||
191 | wrmsr(address, low, high); | ||
192 | 211 | ||
193 | threshold_defaults.address = address; | 212 | memset(&b, 0, sizeof(b)); |
194 | tr.b = &threshold_defaults; | 213 | b.cpu = cpu; |
195 | tr.reset = 0; | 214 | b.bank = bank; |
196 | tr.old_limit = 0; | 215 | b.block = block; |
197 | threshold_restart_bank(&tr); | 216 | b.address = address; |
198 | 217 | ||
218 | mce_threshold_block_init(&b, offset); | ||
199 | mce_threshold_vector = amd_threshold_interrupt; | 219 | mce_threshold_vector = amd_threshold_interrupt; |
200 | } | 220 | } |
201 | } | 221 | } |
@@ -298,9 +318,8 @@ store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size) | |||
298 | 318 | ||
299 | b->interrupt_enable = !!new; | 319 | b->interrupt_enable = !!new; |
300 | 320 | ||
321 | memset(&tr, 0, sizeof(tr)); | ||
301 | tr.b = b; | 322 | tr.b = b; |
302 | tr.reset = 0; | ||
303 | tr.old_limit = 0; | ||
304 | 323 | ||
305 | smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1); | 324 | smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1); |
306 | 325 | ||
@@ -321,10 +340,10 @@ store_threshold_limit(struct threshold_block *b, const char *buf, size_t size) | |||
321 | if (new < 1) | 340 | if (new < 1) |
322 | new = 1; | 341 | new = 1; |
323 | 342 | ||
343 | memset(&tr, 0, sizeof(tr)); | ||
324 | tr.old_limit = b->threshold_limit; | 344 | tr.old_limit = b->threshold_limit; |
325 | b->threshold_limit = new; | 345 | b->threshold_limit = new; |
326 | tr.b = b; | 346 | tr.b = b; |
327 | tr.reset = 0; | ||
328 | 347 | ||
329 | smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1); | 348 | smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1); |
330 | 349 | ||
@@ -603,9 +622,9 @@ static __cpuinit int threshold_create_device(unsigned int cpu) | |||
603 | continue; | 622 | continue; |
604 | err = threshold_create_bank(cpu, bank); | 623 | err = threshold_create_bank(cpu, bank); |
605 | if (err) | 624 | if (err) |
606 | goto out; | 625 | return err; |
607 | } | 626 | } |
608 | out: | 627 | |
609 | return err; | 628 | return err; |
610 | } | 629 | } |
611 | 630 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 4b683267eca5..e12246ff5aa6 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c | |||
@@ -53,8 +53,13 @@ struct thermal_state { | |||
53 | struct _thermal_state core_power_limit; | 53 | struct _thermal_state core_power_limit; |
54 | struct _thermal_state package_throttle; | 54 | struct _thermal_state package_throttle; |
55 | struct _thermal_state package_power_limit; | 55 | struct _thermal_state package_power_limit; |
56 | struct _thermal_state core_thresh0; | ||
57 | struct _thermal_state core_thresh1; | ||
56 | }; | 58 | }; |
57 | 59 | ||
60 | /* Callback to handle core threshold interrupts */ | ||
61 | int (*platform_thermal_notify)(__u64 msr_val); | ||
62 | |||
58 | static DEFINE_PER_CPU(struct thermal_state, thermal_state); | 63 | static DEFINE_PER_CPU(struct thermal_state, thermal_state); |
59 | 64 | ||
60 | static atomic_t therm_throt_en = ATOMIC_INIT(0); | 65 | static atomic_t therm_throt_en = ATOMIC_INIT(0); |
@@ -200,6 +205,22 @@ static int therm_throt_process(bool new_event, int event, int level) | |||
200 | return 0; | 205 | return 0; |
201 | } | 206 | } |
202 | 207 | ||
208 | static int thresh_event_valid(int event) | ||
209 | { | ||
210 | struct _thermal_state *state; | ||
211 | unsigned int this_cpu = smp_processor_id(); | ||
212 | struct thermal_state *pstate = &per_cpu(thermal_state, this_cpu); | ||
213 | u64 now = get_jiffies_64(); | ||
214 | |||
215 | state = (event == 0) ? &pstate->core_thresh0 : &pstate->core_thresh1; | ||
216 | |||
217 | if (time_before64(now, state->next_check)) | ||
218 | return 0; | ||
219 | |||
220 | state->next_check = now + CHECK_INTERVAL; | ||
221 | return 1; | ||
222 | } | ||
223 | |||
203 | #ifdef CONFIG_SYSFS | 224 | #ifdef CONFIG_SYSFS |
204 | /* Add/Remove thermal_throttle interface for CPU device: */ | 225 | /* Add/Remove thermal_throttle interface for CPU device: */ |
205 | static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev, | 226 | static __cpuinit int thermal_throttle_add_dev(struct sys_device *sys_dev, |
@@ -313,6 +334,22 @@ device_initcall(thermal_throttle_init_device); | |||
313 | #define PACKAGE_THROTTLED ((__u64)2 << 62) | 334 | #define PACKAGE_THROTTLED ((__u64)2 << 62) |
314 | #define PACKAGE_POWER_LIMIT ((__u64)3 << 62) | 335 | #define PACKAGE_POWER_LIMIT ((__u64)3 << 62) |
315 | 336 | ||
337 | static void notify_thresholds(__u64 msr_val) | ||
338 | { | ||
339 | /* check whether the interrupt handler is defined; | ||
340 | * otherwise simply return | ||
341 | */ | ||
342 | if (!platform_thermal_notify) | ||
343 | return; | ||
344 | |||
345 | /* lower threshold reached */ | ||
346 | if ((msr_val & THERM_LOG_THRESHOLD0) && thresh_event_valid(0)) | ||
347 | platform_thermal_notify(msr_val); | ||
348 | /* higher threshold reached */ | ||
349 | if ((msr_val & THERM_LOG_THRESHOLD1) && thresh_event_valid(1)) | ||
350 | platform_thermal_notify(msr_val); | ||
351 | } | ||
352 | |||
316 | /* Thermal transition interrupt handler */ | 353 | /* Thermal transition interrupt handler */ |
317 | static void intel_thermal_interrupt(void) | 354 | static void intel_thermal_interrupt(void) |
318 | { | 355 | { |
@@ -321,6 +358,9 @@ static void intel_thermal_interrupt(void) | |||
321 | 358 | ||
322 | rdmsrl(MSR_IA32_THERM_STATUS, msr_val); | 359 | rdmsrl(MSR_IA32_THERM_STATUS, msr_val); |
323 | 360 | ||
361 | /* Check for violation of core thermal thresholds*/ | ||
362 | notify_thresholds(msr_val); | ||
363 | |||
324 | if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT, | 364 | if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT, |
325 | THERMAL_THROTTLING_EVENT, | 365 | THERMAL_THROTTLING_EVENT, |
326 | CORE_LEVEL) != 0) | 366 | CORE_LEVEL) != 0) |
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 4572f25f9325..cd28a350f7f9 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c | |||
@@ -240,7 +240,7 @@ static int __init setup_early_printk(char *buf) | |||
240 | if (!strncmp(buf, "xen", 3)) | 240 | if (!strncmp(buf, "xen", 3)) |
241 | early_console_register(&xenboot_console, keep); | 241 | early_console_register(&xenboot_console, keep); |
242 | #endif | 242 | #endif |
243 | #ifdef CONFIG_X86_MRST_EARLY_PRINTK | 243 | #ifdef CONFIG_EARLY_PRINTK_MRST |
244 | if (!strncmp(buf, "mrst", 4)) { | 244 | if (!strncmp(buf, "mrst", 4)) { |
245 | mrst_early_console_init(); | 245 | mrst_early_console_init(); |
246 | early_console_register(&early_mrst_console, keep); | 246 | early_console_register(&early_mrst_console, keep); |
@@ -250,7 +250,6 @@ static int __init setup_early_printk(char *buf) | |||
250 | hsu_early_console_init(); | 250 | hsu_early_console_init(); |
251 | early_console_register(&early_hsu_console, keep); | 251 | early_console_register(&early_hsu_console, keep); |
252 | } | 252 | } |
253 | |||
254 | #endif | 253 | #endif |
255 | buf++; | 254 | buf++; |
256 | } | 255 | } |
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 3afb33f14d2d..298448656b60 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/module.h> | ||
22 | 23 | ||
23 | #include <trace/syscall.h> | 24 | #include <trace/syscall.h> |
24 | 25 | ||
@@ -49,6 +50,7 @@ static DEFINE_PER_CPU(int, save_modifying_code); | |||
49 | int ftrace_arch_code_modify_prepare(void) | 50 | int ftrace_arch_code_modify_prepare(void) |
50 | { | 51 | { |
51 | set_kernel_text_rw(); | 52 | set_kernel_text_rw(); |
53 | set_all_modules_text_rw(); | ||
52 | modifying_code = 1; | 54 | modifying_code = 1; |
53 | return 0; | 55 | return 0; |
54 | } | 56 | } |
@@ -56,6 +58,7 @@ int ftrace_arch_code_modify_prepare(void) | |||
56 | int ftrace_arch_code_modify_post_process(void) | 58 | int ftrace_arch_code_modify_post_process(void) |
57 | { | 59 | { |
58 | modifying_code = 0; | 60 | modifying_code = 0; |
61 | set_all_modules_text_ro(); | ||
59 | set_kernel_text_ro(); | 62 | set_kernel_text_ro(); |
60 | return 0; | 63 | return 0; |
61 | } | 64 | } |
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 763310165fa0..7f138b3c3c52 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c | |||
@@ -61,6 +61,9 @@ void __init i386_start_kernel(void) | |||
61 | case X86_SUBARCH_MRST: | 61 | case X86_SUBARCH_MRST: |
62 | x86_mrst_early_setup(); | 62 | x86_mrst_early_setup(); |
63 | break; | 63 | break; |
64 | case X86_SUBARCH_CE4100: | ||
65 | x86_ce4100_early_setup(); | ||
66 | break; | ||
64 | default: | 67 | default: |
65 | i386_default_early_setup(); | 68 | i386_default_early_setup(); |
66 | break; | 69 | break; |
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index c0dbd9ac24f0..9f54b209c378 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S | |||
@@ -139,39 +139,6 @@ ENTRY(startup_32) | |||
139 | movl %eax, pa(olpc_ofw_pgd) | 139 | movl %eax, pa(olpc_ofw_pgd) |
140 | #endif | 140 | #endif |
141 | 141 | ||
142 | #ifdef CONFIG_PARAVIRT | ||
143 | /* This is can only trip for a broken bootloader... */ | ||
144 | cmpw $0x207, pa(boot_params + BP_version) | ||
145 | jb default_entry | ||
146 | |||
147 | /* Paravirt-compatible boot parameters. Look to see what architecture | ||
148 | we're booting under. */ | ||
149 | movl pa(boot_params + BP_hardware_subarch), %eax | ||
150 | cmpl $num_subarch_entries, %eax | ||
151 | jae bad_subarch | ||
152 | |||
153 | movl pa(subarch_entries)(,%eax,4), %eax | ||
154 | subl $__PAGE_OFFSET, %eax | ||
155 | jmp *%eax | ||
156 | |||
157 | bad_subarch: | ||
158 | WEAK(lguest_entry) | ||
159 | WEAK(xen_entry) | ||
160 | /* Unknown implementation; there's really | ||
161 | nothing we can do at this point. */ | ||
162 | ud2a | ||
163 | |||
164 | __INITDATA | ||
165 | |||
166 | subarch_entries: | ||
167 | .long default_entry /* normal x86/PC */ | ||
168 | .long lguest_entry /* lguest hypervisor */ | ||
169 | .long xen_entry /* Xen hypervisor */ | ||
170 | .long default_entry /* Moorestown MID */ | ||
171 | num_subarch_entries = (. - subarch_entries) / 4 | ||
172 | .previous | ||
173 | #endif /* CONFIG_PARAVIRT */ | ||
174 | |||
175 | /* | 142 | /* |
176 | * Initialize page tables. This creates a PDE and a set of page | 143 | * Initialize page tables. This creates a PDE and a set of page |
177 | * tables, which are located immediately beyond __brk_base. The variable | 144 | * tables, which are located immediately beyond __brk_base. The variable |
@@ -181,7 +148,6 @@ num_subarch_entries = (. - subarch_entries) / 4 | |||
181 | * | 148 | * |
182 | * Note that the stack is not yet set up! | 149 | * Note that the stack is not yet set up! |
183 | */ | 150 | */ |
184 | default_entry: | ||
185 | #ifdef CONFIG_X86_PAE | 151 | #ifdef CONFIG_X86_PAE |
186 | 152 | ||
187 | /* | 153 | /* |
@@ -261,7 +227,42 @@ page_pde_offset = (__PAGE_OFFSET >> 20); | |||
261 | movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax | 227 | movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax |
262 | movl %eax,pa(initial_page_table+0xffc) | 228 | movl %eax,pa(initial_page_table+0xffc) |
263 | #endif | 229 | #endif |
264 | jmp 3f | 230 | |
231 | #ifdef CONFIG_PARAVIRT | ||
232 | /* This is can only trip for a broken bootloader... */ | ||
233 | cmpw $0x207, pa(boot_params + BP_version) | ||
234 | jb default_entry | ||
235 | |||
236 | /* Paravirt-compatible boot parameters. Look to see what architecture | ||
237 | we're booting under. */ | ||
238 | movl pa(boot_params + BP_hardware_subarch), %eax | ||
239 | cmpl $num_subarch_entries, %eax | ||
240 | jae bad_subarch | ||
241 | |||
242 | movl pa(subarch_entries)(,%eax,4), %eax | ||
243 | subl $__PAGE_OFFSET, %eax | ||
244 | jmp *%eax | ||
245 | |||
246 | bad_subarch: | ||
247 | WEAK(lguest_entry) | ||
248 | WEAK(xen_entry) | ||
249 | /* Unknown implementation; there's really | ||
250 | nothing we can do at this point. */ | ||
251 | ud2a | ||
252 | |||
253 | __INITDATA | ||
254 | |||
255 | subarch_entries: | ||
256 | .long default_entry /* normal x86/PC */ | ||
257 | .long lguest_entry /* lguest hypervisor */ | ||
258 | .long xen_entry /* Xen hypervisor */ | ||
259 | .long default_entry /* Moorestown MID */ | ||
260 | num_subarch_entries = (. - subarch_entries) / 4 | ||
261 | .previous | ||
262 | #else | ||
263 | jmp default_entry | ||
264 | #endif /* CONFIG_PARAVIRT */ | ||
265 | |||
265 | /* | 266 | /* |
266 | * Non-boot CPU entry point; entered from trampoline.S | 267 | * Non-boot CPU entry point; entered from trampoline.S |
267 | * We can't lgdt here, because lgdt itself uses a data segment, but | 268 | * We can't lgdt here, because lgdt itself uses a data segment, but |
@@ -282,7 +283,7 @@ ENTRY(startup_32_smp) | |||
282 | movl %eax,%fs | 283 | movl %eax,%fs |
283 | movl %eax,%gs | 284 | movl %eax,%gs |
284 | #endif /* CONFIG_SMP */ | 285 | #endif /* CONFIG_SMP */ |
285 | 3: | 286 | default_entry: |
286 | 287 | ||
287 | /* | 288 | /* |
288 | * New page tables may be in 4Mbyte page mode and may | 289 | * New page tables may be in 4Mbyte page mode and may |
@@ -316,6 +317,10 @@ ENTRY(startup_32_smp) | |||
316 | subl $0x80000001, %eax | 317 | subl $0x80000001, %eax |
317 | cmpl $(0x8000ffff-0x80000001), %eax | 318 | cmpl $(0x8000ffff-0x80000001), %eax |
318 | ja 6f | 319 | ja 6f |
320 | |||
321 | /* Clear bogus XD_DISABLE bits */ | ||
322 | call verify_cpu | ||
323 | |||
319 | mov $0x80000001, %eax | 324 | mov $0x80000001, %eax |
320 | cpuid | 325 | cpuid |
321 | /* Execute Disable bit supported? */ | 326 | /* Execute Disable bit supported? */ |
@@ -611,6 +616,8 @@ ignore_int: | |||
611 | #endif | 616 | #endif |
612 | iret | 617 | iret |
613 | 618 | ||
619 | #include "verify_cpu.S" | ||
620 | |||
614 | __REFDATA | 621 | __REFDATA |
615 | .align 4 | 622 | .align 4 |
616 | ENTRY(initial_code) | 623 | ENTRY(initial_code) |
@@ -622,13 +629,13 @@ ENTRY(initial_code) | |||
622 | __PAGE_ALIGNED_BSS | 629 | __PAGE_ALIGNED_BSS |
623 | .align PAGE_SIZE_asm | 630 | .align PAGE_SIZE_asm |
624 | #ifdef CONFIG_X86_PAE | 631 | #ifdef CONFIG_X86_PAE |
625 | ENTRY(initial_pg_pmd) | 632 | initial_pg_pmd: |
626 | .fill 1024*KPMDS,4,0 | 633 | .fill 1024*KPMDS,4,0 |
627 | #else | 634 | #else |
628 | ENTRY(initial_page_table) | 635 | ENTRY(initial_page_table) |
629 | .fill 1024,4,0 | 636 | .fill 1024,4,0 |
630 | #endif | 637 | #endif |
631 | ENTRY(initial_pg_fixmap) | 638 | initial_pg_fixmap: |
632 | .fill 1024,4,0 | 639 | .fill 1024,4,0 |
633 | ENTRY(empty_zero_page) | 640 | ENTRY(empty_zero_page) |
634 | .fill 4096,1,0 | 641 | .fill 4096,1,0 |
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index ce0cb4721c9a..0fe6d1a66c38 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c | |||
@@ -155,12 +155,6 @@ static int apply_microcode_amd(int cpu) | |||
155 | return 0; | 155 | return 0; |
156 | } | 156 | } |
157 | 157 | ||
158 | static int get_ucode_data(void *to, const u8 *from, size_t n) | ||
159 | { | ||
160 | memcpy(to, from, n); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static void * | 158 | static void * |
165 | get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) | 159 | get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) |
166 | { | 160 | { |
@@ -168,8 +162,7 @@ get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) | |||
168 | u8 section_hdr[UCODE_CONTAINER_SECTION_HDR]; | 162 | u8 section_hdr[UCODE_CONTAINER_SECTION_HDR]; |
169 | void *mc; | 163 | void *mc; |
170 | 164 | ||
171 | if (get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR)) | 165 | get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR); |
172 | return NULL; | ||
173 | 166 | ||
174 | if (section_hdr[0] != UCODE_UCODE_TYPE) { | 167 | if (section_hdr[0] != UCODE_UCODE_TYPE) { |
175 | pr_err("error: invalid type field in container file section header\n"); | 168 | pr_err("error: invalid type field in container file section header\n"); |
@@ -183,16 +176,13 @@ get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size) | |||
183 | return NULL; | 176 | return NULL; |
184 | } | 177 | } |
185 | 178 | ||
186 | mc = vmalloc(UCODE_MAX_SIZE); | 179 | mc = vzalloc(UCODE_MAX_SIZE); |
187 | if (mc) { | 180 | if (!mc) |
188 | memset(mc, 0, UCODE_MAX_SIZE); | 181 | return NULL; |
189 | if (get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, | 182 | |
190 | total_size)) { | 183 | get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size); |
191 | vfree(mc); | 184 | *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR; |
192 | mc = NULL; | 185 | |
193 | } else | ||
194 | *mc_size = total_size + UCODE_CONTAINER_SECTION_HDR; | ||
195 | } | ||
196 | return mc; | 186 | return mc; |
197 | } | 187 | } |
198 | 188 | ||
@@ -202,8 +192,7 @@ static int install_equiv_cpu_table(const u8 *buf) | |||
202 | unsigned int *buf_pos = (unsigned int *)container_hdr; | 192 | unsigned int *buf_pos = (unsigned int *)container_hdr; |
203 | unsigned long size; | 193 | unsigned long size; |
204 | 194 | ||
205 | if (get_ucode_data(&container_hdr, buf, UCODE_CONTAINER_HEADER_SIZE)) | 195 | get_ucode_data(&container_hdr, buf, UCODE_CONTAINER_HEADER_SIZE); |
206 | return 0; | ||
207 | 196 | ||
208 | size = buf_pos[2]; | 197 | size = buf_pos[2]; |
209 | 198 | ||
@@ -219,10 +208,7 @@ static int install_equiv_cpu_table(const u8 *buf) | |||
219 | } | 208 | } |
220 | 209 | ||
221 | buf += UCODE_CONTAINER_HEADER_SIZE; | 210 | buf += UCODE_CONTAINER_HEADER_SIZE; |
222 | if (get_ucode_data(equiv_cpu_table, buf, size)) { | 211 | get_ucode_data(equiv_cpu_table, buf, size); |
223 | vfree(equiv_cpu_table); | ||
224 | return 0; | ||
225 | } | ||
226 | 212 | ||
227 | return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */ | 213 | return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */ |
228 | } | 214 | } |
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index ba0f0ca9f280..c01ffa5b9b87 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c | |||
@@ -143,7 +143,7 @@ static void flush_gart(void) | |||
143 | 143 | ||
144 | spin_lock_irqsave(&iommu_bitmap_lock, flags); | 144 | spin_lock_irqsave(&iommu_bitmap_lock, flags); |
145 | if (need_flush) { | 145 | if (need_flush) { |
146 | k8_flush_garts(); | 146 | amd_flush_garts(); |
147 | need_flush = false; | 147 | need_flush = false; |
148 | } | 148 | } |
149 | spin_unlock_irqrestore(&iommu_bitmap_lock, flags); | 149 | spin_unlock_irqrestore(&iommu_bitmap_lock, flags); |
@@ -561,17 +561,17 @@ static void enable_gart_translations(void) | |||
561 | { | 561 | { |
562 | int i; | 562 | int i; |
563 | 563 | ||
564 | if (!k8_northbridges.gart_supported) | 564 | if (!amd_nb_has_feature(AMD_NB_GART)) |
565 | return; | 565 | return; |
566 | 566 | ||
567 | for (i = 0; i < k8_northbridges.num; i++) { | 567 | for (i = 0; i < amd_nb_num(); i++) { |
568 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; | 568 | struct pci_dev *dev = node_to_amd_nb(i)->misc; |
569 | 569 | ||
570 | enable_gart_translation(dev, __pa(agp_gatt_table)); | 570 | enable_gart_translation(dev, __pa(agp_gatt_table)); |
571 | } | 571 | } |
572 | 572 | ||
573 | /* Flush the GART-TLB to remove stale entries */ | 573 | /* Flush the GART-TLB to remove stale entries */ |
574 | k8_flush_garts(); | 574 | amd_flush_garts(); |
575 | } | 575 | } |
576 | 576 | ||
577 | /* | 577 | /* |
@@ -596,13 +596,13 @@ static void gart_fixup_northbridges(struct sys_device *dev) | |||
596 | if (!fix_up_north_bridges) | 596 | if (!fix_up_north_bridges) |
597 | return; | 597 | return; |
598 | 598 | ||
599 | if (!k8_northbridges.gart_supported) | 599 | if (!amd_nb_has_feature(AMD_NB_GART)) |
600 | return; | 600 | return; |
601 | 601 | ||
602 | pr_info("PCI-DMA: Restoring GART aperture settings\n"); | 602 | pr_info("PCI-DMA: Restoring GART aperture settings\n"); |
603 | 603 | ||
604 | for (i = 0; i < k8_northbridges.num; i++) { | 604 | for (i = 0; i < amd_nb_num(); i++) { |
605 | struct pci_dev *dev = k8_northbridges.nb_misc[i]; | 605 | struct pci_dev *dev = node_to_amd_nb(i)->misc; |
606 | 606 | ||
607 | /* | 607 | /* |
608 | * Don't enable translations just yet. That is the next | 608 | * Don't enable translations just yet. That is the next |
@@ -644,7 +644,7 @@ static struct sys_device device_gart = { | |||
644 | * Private Northbridge GATT initialization in case we cannot use the | 644 | * Private Northbridge GATT initialization in case we cannot use the |
645 | * AGP driver for some reason. | 645 | * AGP driver for some reason. |
646 | */ | 646 | */ |
647 | static __init int init_k8_gatt(struct agp_kern_info *info) | 647 | static __init int init_amd_gatt(struct agp_kern_info *info) |
648 | { | 648 | { |
649 | unsigned aper_size, gatt_size, new_aper_size; | 649 | unsigned aper_size, gatt_size, new_aper_size; |
650 | unsigned aper_base, new_aper_base; | 650 | unsigned aper_base, new_aper_base; |
@@ -656,8 +656,8 @@ static __init int init_k8_gatt(struct agp_kern_info *info) | |||
656 | 656 | ||
657 | aper_size = aper_base = info->aper_size = 0; | 657 | aper_size = aper_base = info->aper_size = 0; |
658 | dev = NULL; | 658 | dev = NULL; |
659 | for (i = 0; i < k8_northbridges.num; i++) { | 659 | for (i = 0; i < amd_nb_num(); i++) { |
660 | dev = k8_northbridges.nb_misc[i]; | 660 | dev = node_to_amd_nb(i)->misc; |
661 | new_aper_base = read_aperture(dev, &new_aper_size); | 661 | new_aper_base = read_aperture(dev, &new_aper_size); |
662 | if (!new_aper_base) | 662 | if (!new_aper_base) |
663 | goto nommu; | 663 | goto nommu; |
@@ -725,13 +725,13 @@ static void gart_iommu_shutdown(void) | |||
725 | if (!no_agp) | 725 | if (!no_agp) |
726 | return; | 726 | return; |
727 | 727 | ||
728 | if (!k8_northbridges.gart_supported) | 728 | if (!amd_nb_has_feature(AMD_NB_GART)) |
729 | return; | 729 | return; |
730 | 730 | ||
731 | for (i = 0; i < k8_northbridges.num; i++) { | 731 | for (i = 0; i < amd_nb_num(); i++) { |
732 | u32 ctl; | 732 | u32 ctl; |
733 | 733 | ||
734 | dev = k8_northbridges.nb_misc[i]; | 734 | dev = node_to_amd_nb(i)->misc; |
735 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl); | 735 | pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl); |
736 | 736 | ||
737 | ctl &= ~GARTEN; | 737 | ctl &= ~GARTEN; |
@@ -749,14 +749,14 @@ int __init gart_iommu_init(void) | |||
749 | unsigned long scratch; | 749 | unsigned long scratch; |
750 | long i; | 750 | long i; |
751 | 751 | ||
752 | if (!k8_northbridges.gart_supported) | 752 | if (!amd_nb_has_feature(AMD_NB_GART)) |
753 | return 0; | 753 | return 0; |
754 | 754 | ||
755 | #ifndef CONFIG_AGP_AMD64 | 755 | #ifndef CONFIG_AGP_AMD64 |
756 | no_agp = 1; | 756 | no_agp = 1; |
757 | #else | 757 | #else |
758 | /* Makefile puts PCI initialization via subsys_initcall first. */ | 758 | /* Makefile puts PCI initialization via subsys_initcall first. */ |
759 | /* Add other K8 AGP bridge drivers here */ | 759 | /* Add other AMD AGP bridge drivers here */ |
760 | no_agp = no_agp || | 760 | no_agp = no_agp || |
761 | (agp_amd64_init() < 0) || | 761 | (agp_amd64_init() < 0) || |
762 | (agp_copy_info(agp_bridge, &info) < 0); | 762 | (agp_copy_info(agp_bridge, &info) < 0); |
@@ -765,7 +765,7 @@ int __init gart_iommu_init(void) | |||
765 | if (no_iommu || | 765 | if (no_iommu || |
766 | (!force_iommu && max_pfn <= MAX_DMA32_PFN) || | 766 | (!force_iommu && max_pfn <= MAX_DMA32_PFN) || |
767 | !gart_iommu_aperture || | 767 | !gart_iommu_aperture || |
768 | (no_agp && init_k8_gatt(&info) < 0)) { | 768 | (no_agp && init_amd_gatt(&info) < 0)) { |
769 | if (max_pfn > MAX_DMA32_PFN) { | 769 | if (max_pfn > MAX_DMA32_PFN) { |
770 | pr_warning("More than 4GB of memory but GART IOMMU not available.\n"); | 770 | pr_warning("More than 4GB of memory but GART IOMMU not available.\n"); |
771 | pr_warning("falling back to iommu=soft.\n"); | 771 | pr_warning("falling back to iommu=soft.\n"); |
diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c index fda313ebbb03..c8e41e90f59c 100644 --- a/arch/x86/kernel/reboot_fixups_32.c +++ b/arch/x86/kernel/reboot_fixups_32.c | |||
@@ -43,17 +43,33 @@ static void rdc321x_reset(struct pci_dev *dev) | |||
43 | outb(1, 0x92); | 43 | outb(1, 0x92); |
44 | } | 44 | } |
45 | 45 | ||
46 | static void ce4100_reset(struct pci_dev *dev) | ||
47 | { | ||
48 | int i; | ||
49 | |||
50 | for (i = 0; i < 10; i++) { | ||
51 | outb(0x2, 0xcf9); | ||
52 | udelay(50); | ||
53 | } | ||
54 | } | ||
55 | |||
46 | struct device_fixup { | 56 | struct device_fixup { |
47 | unsigned int vendor; | 57 | unsigned int vendor; |
48 | unsigned int device; | 58 | unsigned int device; |
49 | void (*reboot_fixup)(struct pci_dev *); | 59 | void (*reboot_fixup)(struct pci_dev *); |
50 | }; | 60 | }; |
51 | 61 | ||
62 | /* | ||
63 | * PCI ids solely used for fixups_table go here | ||
64 | */ | ||
65 | #define PCI_DEVICE_ID_INTEL_CE4100 0x0708 | ||
66 | |||
52 | static const struct device_fixup fixups_table[] = { | 67 | static const struct device_fixup fixups_table[] = { |
53 | { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset }, | 68 | { PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_LEGACY, cs5530a_warm_reset }, |
54 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset }, | 69 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, cs5536_warm_reset }, |
55 | { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset }, | 70 | { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE, cs5530a_warm_reset }, |
56 | { PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030, rdc321x_reset }, | 71 | { PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030, rdc321x_reset }, |
72 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100, ce4100_reset }, | ||
57 | }; | 73 | }; |
58 | 74 | ||
59 | /* | 75 | /* |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index a0f52af256a0..d3cfe26c0252 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -705,7 +705,7 @@ static u64 __init get_max_mapped(void) | |||
705 | void __init setup_arch(char **cmdline_p) | 705 | void __init setup_arch(char **cmdline_p) |
706 | { | 706 | { |
707 | int acpi = 0; | 707 | int acpi = 0; |
708 | int k8 = 0; | 708 | int amd = 0; |
709 | unsigned long flags; | 709 | unsigned long flags; |
710 | 710 | ||
711 | #ifdef CONFIG_X86_32 | 711 | #ifdef CONFIG_X86_32 |
@@ -991,12 +991,12 @@ void __init setup_arch(char **cmdline_p) | |||
991 | acpi = acpi_numa_init(); | 991 | acpi = acpi_numa_init(); |
992 | #endif | 992 | #endif |
993 | 993 | ||
994 | #ifdef CONFIG_K8_NUMA | 994 | #ifdef CONFIG_AMD_NUMA |
995 | if (!acpi) | 995 | if (!acpi) |
996 | k8 = !k8_numa_init(0, max_pfn); | 996 | amd = !amd_numa_init(0, max_pfn); |
997 | #endif | 997 | #endif |
998 | 998 | ||
999 | initmem_init(0, max_pfn, acpi, k8); | 999 | initmem_init(0, max_pfn, acpi, amd); |
1000 | memblock_find_dma_reserve(); | 1000 | memblock_find_dma_reserve(); |
1001 | dma32_reserve_bootmem(); | 1001 | dma32_reserve_bootmem(); |
1002 | 1002 | ||
@@ -1045,10 +1045,7 @@ void __init setup_arch(char **cmdline_p) | |||
1045 | #endif | 1045 | #endif |
1046 | 1046 | ||
1047 | init_apic_mappings(); | 1047 | init_apic_mappings(); |
1048 | ioapic_init_mappings(); | 1048 | ioapic_and_gsi_init(); |
1049 | |||
1050 | /* need to wait for io_apic is mapped */ | ||
1051 | probe_nr_irqs_gsi(); | ||
1052 | 1049 | ||
1053 | kvm_guest_init(); | 1050 | kvm_guest_init(); |
1054 | 1051 | ||
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 68f61ac632e1..ee886fe10ef4 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -1161,6 +1161,20 @@ out: | |||
1161 | preempt_enable(); | 1161 | preempt_enable(); |
1162 | } | 1162 | } |
1163 | 1163 | ||
1164 | void arch_disable_nonboot_cpus_begin(void) | ||
1165 | { | ||
1166 | /* | ||
1167 | * Avoid the smp alternatives switch during the disable_nonboot_cpus(). | ||
1168 | * In the suspend path, we will be back in the SMP mode shortly anyways. | ||
1169 | */ | ||
1170 | skip_smp_alternatives = true; | ||
1171 | } | ||
1172 | |||
1173 | void arch_disable_nonboot_cpus_end(void) | ||
1174 | { | ||
1175 | skip_smp_alternatives = false; | ||
1176 | } | ||
1177 | |||
1164 | void arch_enable_nonboot_cpus_begin(void) | 1178 | void arch_enable_nonboot_cpus_begin(void) |
1165 | { | 1179 | { |
1166 | set_mtrr_aps_delayed_init(); | 1180 | set_mtrr_aps_delayed_init(); |
diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S index 3af2dff58b21..075d130efcf9 100644 --- a/arch/x86/kernel/trampoline_64.S +++ b/arch/x86/kernel/trampoline_64.S | |||
@@ -127,7 +127,7 @@ startup_64: | |||
127 | no_longmode: | 127 | no_longmode: |
128 | hlt | 128 | hlt |
129 | jmp no_longmode | 129 | jmp no_longmode |
130 | #include "verify_cpu_64.S" | 130 | #include "verify_cpu.S" |
131 | 131 | ||
132 | # Careful these need to be in the same 64K segment as the above; | 132 | # Careful these need to be in the same 64K segment as the above; |
133 | tidt: | 133 | tidt: |
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 0c40d8b72416..356a0d455cf9 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
@@ -872,6 +872,9 @@ __cpuinit int unsynchronized_tsc(void) | |||
872 | 872 | ||
873 | if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) | 873 | if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) |
874 | return 0; | 874 | return 0; |
875 | |||
876 | if (tsc_clocksource_reliable) | ||
877 | return 0; | ||
875 | /* | 878 | /* |
876 | * Intel systems are normally all synchronized. | 879 | * Intel systems are normally all synchronized. |
877 | * Exceptions must mark TSC as unstable: | 880 | * Exceptions must mark TSC as unstable: |
@@ -879,14 +882,92 @@ __cpuinit int unsynchronized_tsc(void) | |||
879 | if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) { | 882 | if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) { |
880 | /* assume multi socket systems are not synchronized: */ | 883 | /* assume multi socket systems are not synchronized: */ |
881 | if (num_possible_cpus() > 1) | 884 | if (num_possible_cpus() > 1) |
882 | tsc_unstable = 1; | 885 | return 1; |
883 | } | 886 | } |
884 | 887 | ||
885 | return tsc_unstable; | 888 | return 0; |
889 | } | ||
890 | |||
891 | |||
892 | static void tsc_refine_calibration_work(struct work_struct *work); | ||
893 | static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work); | ||
894 | /** | ||
895 | * tsc_refine_calibration_work - Further refine tsc freq calibration | ||
896 | * @work - ignored. | ||
897 | * | ||
898 | * This functions uses delayed work over a period of a | ||
899 | * second to further refine the TSC freq value. Since this is | ||
900 | * timer based, instead of loop based, we don't block the boot | ||
901 | * process while this longer calibration is done. | ||
902 | * | ||
903 | * If there are any calibration anomolies (too many SMIs, etc), | ||
904 | * or the refined calibration is off by 1% of the fast early | ||
905 | * calibration, we throw out the new calibration and use the | ||
906 | * early calibration. | ||
907 | */ | ||
908 | static void tsc_refine_calibration_work(struct work_struct *work) | ||
909 | { | ||
910 | static u64 tsc_start = -1, ref_start; | ||
911 | static int hpet; | ||
912 | u64 tsc_stop, ref_stop, delta; | ||
913 | unsigned long freq; | ||
914 | |||
915 | /* Don't bother refining TSC on unstable systems */ | ||
916 | if (check_tsc_unstable()) | ||
917 | goto out; | ||
918 | |||
919 | /* | ||
920 | * Since the work is started early in boot, we may be | ||
921 | * delayed the first time we expire. So set the workqueue | ||
922 | * again once we know timers are working. | ||
923 | */ | ||
924 | if (tsc_start == -1) { | ||
925 | /* | ||
926 | * Only set hpet once, to avoid mixing hardware | ||
927 | * if the hpet becomes enabled later. | ||
928 | */ | ||
929 | hpet = is_hpet_enabled(); | ||
930 | schedule_delayed_work(&tsc_irqwork, HZ); | ||
931 | tsc_start = tsc_read_refs(&ref_start, hpet); | ||
932 | return; | ||
933 | } | ||
934 | |||
935 | tsc_stop = tsc_read_refs(&ref_stop, hpet); | ||
936 | |||
937 | /* hpet or pmtimer available ? */ | ||
938 | if (!hpet && !ref_start && !ref_stop) | ||
939 | goto out; | ||
940 | |||
941 | /* Check, whether the sampling was disturbed by an SMI */ | ||
942 | if (tsc_start == ULLONG_MAX || tsc_stop == ULLONG_MAX) | ||
943 | goto out; | ||
944 | |||
945 | delta = tsc_stop - tsc_start; | ||
946 | delta *= 1000000LL; | ||
947 | if (hpet) | ||
948 | freq = calc_hpet_ref(delta, ref_start, ref_stop); | ||
949 | else | ||
950 | freq = calc_pmtimer_ref(delta, ref_start, ref_stop); | ||
951 | |||
952 | /* Make sure we're within 1% */ | ||
953 | if (abs(tsc_khz - freq) > tsc_khz/100) | ||
954 | goto out; | ||
955 | |||
956 | tsc_khz = freq; | ||
957 | printk(KERN_INFO "Refined TSC clocksource calibration: " | ||
958 | "%lu.%03lu MHz.\n", (unsigned long)tsc_khz / 1000, | ||
959 | (unsigned long)tsc_khz % 1000); | ||
960 | |||
961 | out: | ||
962 | clocksource_register_khz(&clocksource_tsc, tsc_khz); | ||
886 | } | 963 | } |
887 | 964 | ||
888 | static void __init init_tsc_clocksource(void) | 965 | |
966 | static int __init init_tsc_clocksource(void) | ||
889 | { | 967 | { |
968 | if (!cpu_has_tsc || tsc_disabled > 0) | ||
969 | return 0; | ||
970 | |||
890 | if (tsc_clocksource_reliable) | 971 | if (tsc_clocksource_reliable) |
891 | clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; | 972 | clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY; |
892 | /* lower the rating if we already know its unstable: */ | 973 | /* lower the rating if we already know its unstable: */ |
@@ -894,8 +975,14 @@ static void __init init_tsc_clocksource(void) | |||
894 | clocksource_tsc.rating = 0; | 975 | clocksource_tsc.rating = 0; |
895 | clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS; | 976 | clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS; |
896 | } | 977 | } |
897 | clocksource_register_khz(&clocksource_tsc, tsc_khz); | 978 | schedule_delayed_work(&tsc_irqwork, 0); |
979 | return 0; | ||
898 | } | 980 | } |
981 | /* | ||
982 | * We use device_initcall here, to ensure we run after the hpet | ||
983 | * is fully initialized, which may occur at fs_initcall time. | ||
984 | */ | ||
985 | device_initcall(init_tsc_clocksource); | ||
899 | 986 | ||
900 | void __init tsc_init(void) | 987 | void __init tsc_init(void) |
901 | { | 988 | { |
@@ -949,6 +1036,5 @@ void __init tsc_init(void) | |||
949 | mark_tsc_unstable("TSCs unsynchronized"); | 1036 | mark_tsc_unstable("TSCs unsynchronized"); |
950 | 1037 | ||
951 | check_system_tsc_reliable(); | 1038 | check_system_tsc_reliable(); |
952 | init_tsc_clocksource(); | ||
953 | } | 1039 | } |
954 | 1040 | ||
diff --git a/arch/x86/kernel/verify_cpu_64.S b/arch/x86/kernel/verify_cpu.S index 56a8c2a867d9..0edefc19a113 100644 --- a/arch/x86/kernel/verify_cpu_64.S +++ b/arch/x86/kernel/verify_cpu.S | |||
@@ -7,6 +7,7 @@ | |||
7 | * Copyright (c) 2007 Andi Kleen (ak@suse.de) | 7 | * Copyright (c) 2007 Andi Kleen (ak@suse.de) |
8 | * Copyright (c) 2007 Eric Biederman (ebiederm@xmission.com) | 8 | * Copyright (c) 2007 Eric Biederman (ebiederm@xmission.com) |
9 | * Copyright (c) 2007 Vivek Goyal (vgoyal@in.ibm.com) | 9 | * Copyright (c) 2007 Vivek Goyal (vgoyal@in.ibm.com) |
10 | * Copyright (c) 2010 Kees Cook (kees.cook@canonical.com) | ||
10 | * | 11 | * |
11 | * This source code is licensed under the GNU General Public License, | 12 | * This source code is licensed under the GNU General Public License, |
12 | * Version 2. See the file COPYING for more details. | 13 | * Version 2. See the file COPYING for more details. |
@@ -14,18 +15,17 @@ | |||
14 | * This is a common code for verification whether CPU supports | 15 | * This is a common code for verification whether CPU supports |
15 | * long mode and SSE or not. It is not called directly instead this | 16 | * long mode and SSE or not. It is not called directly instead this |
16 | * file is included at various places and compiled in that context. | 17 | * file is included at various places and compiled in that context. |
17 | * Following are the current usage. | 18 | * This file is expected to run in 32bit code. Currently: |
18 | * | 19 | * |
19 | * This file is included by both 16bit and 32bit code. | 20 | * arch/x86/boot/compressed/head_64.S: Boot cpu verification |
21 | * arch/x86/kernel/trampoline_64.S: secondary processor verfication | ||
22 | * arch/x86/kernel/head_32.S: processor startup | ||
20 | * | 23 | * |
21 | * arch/x86_64/boot/setup.S : Boot cpu verification (16bit) | 24 | * verify_cpu, returns the status of longmode and SSE in register %eax. |
22 | * arch/x86_64/boot/compressed/head.S: Boot cpu verification (32bit) | ||
23 | * arch/x86_64/kernel/trampoline.S: secondary processor verfication (16bit) | ||
24 | * arch/x86_64/kernel/acpi/wakeup.S:Verfication at resume (16bit) | ||
25 | * | ||
26 | * verify_cpu, returns the status of cpu check in register %eax. | ||
27 | * 0: Success 1: Failure | 25 | * 0: Success 1: Failure |
28 | * | 26 | * |
27 | * On Intel, the XD_DISABLE flag will be cleared as a side-effect. | ||
28 | * | ||
29 | * The caller needs to check for the error code and take the action | 29 | * The caller needs to check for the error code and take the action |
30 | * appropriately. Either display a message or halt. | 30 | * appropriately. Either display a message or halt. |
31 | */ | 31 | */ |
@@ -62,8 +62,41 @@ verify_cpu: | |||
62 | cmpl $0x444d4163,%ecx | 62 | cmpl $0x444d4163,%ecx |
63 | jnz verify_cpu_noamd | 63 | jnz verify_cpu_noamd |
64 | mov $1,%di # cpu is from AMD | 64 | mov $1,%di # cpu is from AMD |
65 | jmp verify_cpu_check | ||
65 | 66 | ||
66 | verify_cpu_noamd: | 67 | verify_cpu_noamd: |
68 | cmpl $0x756e6547,%ebx # GenuineIntel? | ||
69 | jnz verify_cpu_check | ||
70 | cmpl $0x49656e69,%edx | ||
71 | jnz verify_cpu_check | ||
72 | cmpl $0x6c65746e,%ecx | ||
73 | jnz verify_cpu_check | ||
74 | |||
75 | # only call IA32_MISC_ENABLE when: | ||
76 | # family > 6 || (family == 6 && model >= 0xd) | ||
77 | movl $0x1, %eax # check CPU family and model | ||
78 | cpuid | ||
79 | movl %eax, %ecx | ||
80 | |||
81 | andl $0x0ff00f00, %eax # mask family and extended family | ||
82 | shrl $8, %eax | ||
83 | cmpl $6, %eax | ||
84 | ja verify_cpu_clear_xd # family > 6, ok | ||
85 | jb verify_cpu_check # family < 6, skip | ||
86 | |||
87 | andl $0x000f00f0, %ecx # mask model and extended model | ||
88 | shrl $4, %ecx | ||
89 | cmpl $0xd, %ecx | ||
90 | jb verify_cpu_check # family == 6, model < 0xd, skip | ||
91 | |||
92 | verify_cpu_clear_xd: | ||
93 | movl $MSR_IA32_MISC_ENABLE, %ecx | ||
94 | rdmsr | ||
95 | btrl $2, %edx # clear MSR_IA32_MISC_ENABLE_XD_DISABLE | ||
96 | jnc verify_cpu_check # only write MSR if bit was changed | ||
97 | wrmsr | ||
98 | |||
99 | verify_cpu_check: | ||
67 | movl $0x1,%eax # Does the cpu have what it takes | 100 | movl $0x1,%eax # Does the cpu have what it takes |
68 | cpuid | 101 | cpuid |
69 | andl $REQUIRED_MASK0,%edx | 102 | andl $REQUIRED_MASK0,%edx |
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index e03530aebfd0..bf4700755184 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S | |||
@@ -69,7 +69,7 @@ jiffies_64 = jiffies; | |||
69 | 69 | ||
70 | PHDRS { | 70 | PHDRS { |
71 | text PT_LOAD FLAGS(5); /* R_E */ | 71 | text PT_LOAD FLAGS(5); /* R_E */ |
72 | data PT_LOAD FLAGS(7); /* RWE */ | 72 | data PT_LOAD FLAGS(6); /* RW_ */ |
73 | #ifdef CONFIG_X86_64 | 73 | #ifdef CONFIG_X86_64 |
74 | user PT_LOAD FLAGS(5); /* R_E */ | 74 | user PT_LOAD FLAGS(5); /* R_E */ |
75 | #ifdef CONFIG_SMP | 75 | #ifdef CONFIG_SMP |
@@ -116,6 +116,10 @@ SECTIONS | |||
116 | 116 | ||
117 | EXCEPTION_TABLE(16) :text = 0x9090 | 117 | EXCEPTION_TABLE(16) :text = 0x9090 |
118 | 118 | ||
119 | #if defined(CONFIG_DEBUG_RODATA) | ||
120 | /* .text should occupy whole number of pages */ | ||
121 | . = ALIGN(PAGE_SIZE); | ||
122 | #endif | ||
119 | X64_ALIGN_DEBUG_RODATA_BEGIN | 123 | X64_ALIGN_DEBUG_RODATA_BEGIN |
120 | RO_DATA(PAGE_SIZE) | 124 | RO_DATA(PAGE_SIZE) |
121 | X64_ALIGN_DEBUG_RODATA_END | 125 | X64_ALIGN_DEBUG_RODATA_END |
@@ -335,7 +339,7 @@ SECTIONS | |||
335 | __bss_start = .; | 339 | __bss_start = .; |
336 | *(.bss..page_aligned) | 340 | *(.bss..page_aligned) |
337 | *(.bss) | 341 | *(.bss) |
338 | . = ALIGN(4); | 342 | . = ALIGN(PAGE_SIZE); |
339 | __bss_stop = .; | 343 | __bss_stop = .; |
340 | } | 344 | } |
341 | 345 | ||
diff --git a/arch/x86/lguest/i386_head.S b/arch/x86/lguest/i386_head.S index e7d5382ef263..4f420c2f2d55 100644 --- a/arch/x86/lguest/i386_head.S +++ b/arch/x86/lguest/i386_head.S | |||
@@ -4,7 +4,6 @@ | |||
4 | #include <asm/asm-offsets.h> | 4 | #include <asm/asm-offsets.h> |
5 | #include <asm/thread_info.h> | 5 | #include <asm/thread_info.h> |
6 | #include <asm/processor-flags.h> | 6 | #include <asm/processor-flags.h> |
7 | #include <asm/pgtable.h> | ||
8 | 7 | ||
9 | /*G:020 | 8 | /*G:020 |
10 | * Our story starts with the kernel booting into startup_32 in | 9 | * Our story starts with the kernel booting into startup_32 in |
@@ -38,113 +37,9 @@ ENTRY(lguest_entry) | |||
38 | /* Set up the initial stack so we can run C code. */ | 37 | /* Set up the initial stack so we can run C code. */ |
39 | movl $(init_thread_union+THREAD_SIZE),%esp | 38 | movl $(init_thread_union+THREAD_SIZE),%esp |
40 | 39 | ||
41 | call init_pagetables | ||
42 | |||
43 | /* Jumps are relative: we're running __PAGE_OFFSET too low. */ | 40 | /* Jumps are relative: we're running __PAGE_OFFSET too low. */ |
44 | jmp lguest_init+__PAGE_OFFSET | 41 | jmp lguest_init+__PAGE_OFFSET |
45 | 42 | ||
46 | /* | ||
47 | * Initialize page tables. This creates a PDE and a set of page | ||
48 | * tables, which are located immediately beyond __brk_base. The variable | ||
49 | * _brk_end is set up to point to the first "safe" location. | ||
50 | * Mappings are created both at virtual address 0 (identity mapping) | ||
51 | * and PAGE_OFFSET for up to _end. | ||
52 | * | ||
53 | * FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they | ||
54 | * don't have a stack at this point, so we can't just use call and ret. | ||
55 | */ | ||
56 | init_pagetables: | ||
57 | #if PTRS_PER_PMD > 1 | ||
58 | #define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD) | ||
59 | #else | ||
60 | #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD) | ||
61 | #endif | ||
62 | #define pa(X) ((X) - __PAGE_OFFSET) | ||
63 | |||
64 | /* Enough space to fit pagetables for the low memory linear map */ | ||
65 | MAPPING_BEYOND_END = \ | ||
66 | PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT | ||
67 | #ifdef CONFIG_X86_PAE | ||
68 | |||
69 | /* | ||
70 | * In PAE mode initial_page_table is statically defined to contain | ||
71 | * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3 | ||
72 | * entries). The identity mapping is handled by pointing two PGD entries | ||
73 | * to the first kernel PMD. | ||
74 | * | ||
75 | * Note the upper half of each PMD or PTE are always zero at this stage. | ||
76 | */ | ||
77 | |||
78 | #define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */ | ||
79 | |||
80 | xorl %ebx,%ebx /* %ebx is kept at zero */ | ||
81 | |||
82 | movl $pa(__brk_base), %edi | ||
83 | movl $pa(initial_pg_pmd), %edx | ||
84 | movl $PTE_IDENT_ATTR, %eax | ||
85 | 10: | ||
86 | leal PDE_IDENT_ATTR(%edi),%ecx /* Create PMD entry */ | ||
87 | movl %ecx,(%edx) /* Store PMD entry */ | ||
88 | /* Upper half already zero */ | ||
89 | addl $8,%edx | ||
90 | movl $512,%ecx | ||
91 | 11: | ||
92 | stosl | ||
93 | xchgl %eax,%ebx | ||
94 | stosl | ||
95 | xchgl %eax,%ebx | ||
96 | addl $0x1000,%eax | ||
97 | loop 11b | ||
98 | |||
99 | /* | ||
100 | * End condition: we must map up to the end + MAPPING_BEYOND_END. | ||
101 | */ | ||
102 | movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp | ||
103 | cmpl %ebp,%eax | ||
104 | jb 10b | ||
105 | 1: | ||
106 | addl $__PAGE_OFFSET, %edi | ||
107 | movl %edi, pa(_brk_end) | ||
108 | shrl $12, %eax | ||
109 | movl %eax, pa(max_pfn_mapped) | ||
110 | |||
111 | /* Do early initialization of the fixmap area */ | ||
112 | movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax | ||
113 | movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8) | ||
114 | #else /* Not PAE */ | ||
115 | |||
116 | page_pde_offset = (__PAGE_OFFSET >> 20); | ||
117 | |||
118 | movl $pa(__brk_base), %edi | ||
119 | movl $pa(initial_page_table), %edx | ||
120 | movl $PTE_IDENT_ATTR, %eax | ||
121 | 10: | ||
122 | leal PDE_IDENT_ATTR(%edi),%ecx /* Create PDE entry */ | ||
123 | movl %ecx,(%edx) /* Store identity PDE entry */ | ||
124 | movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */ | ||
125 | addl $4,%edx | ||
126 | movl $1024, %ecx | ||
127 | 11: | ||
128 | stosl | ||
129 | addl $0x1000,%eax | ||
130 | loop 11b | ||
131 | /* | ||
132 | * End condition: we must map up to the end + MAPPING_BEYOND_END. | ||
133 | */ | ||
134 | movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp | ||
135 | cmpl %ebp,%eax | ||
136 | jb 10b | ||
137 | addl $__PAGE_OFFSET, %edi | ||
138 | movl %edi, pa(_brk_end) | ||
139 | shrl $12, %eax | ||
140 | movl %eax, pa(max_pfn_mapped) | ||
141 | |||
142 | /* Do early initialization of the fixmap area */ | ||
143 | movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax | ||
144 | movl %eax,pa(initial_page_table+0xffc) | ||
145 | #endif | ||
146 | ret | ||
147 | |||
148 | /*G:055 | 43 | /*G:055 |
149 | * We create a macro which puts the assembler code between lgstart_ and lgend_ | 44 | * We create a macro which puts the assembler code between lgstart_ and lgend_ |
150 | * markers. These templates are put in the .text section: they can't be | 45 | * markers. These templates are put in the .text section: they can't be |
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 55543397a8a7..09df2f9a3d69 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile | |||
@@ -23,7 +23,7 @@ mmiotrace-y := kmmio.o pf_in.o mmio-mod.o | |||
23 | obj-$(CONFIG_MMIOTRACE_TEST) += testmmiotrace.o | 23 | obj-$(CONFIG_MMIOTRACE_TEST) += testmmiotrace.o |
24 | 24 | ||
25 | obj-$(CONFIG_NUMA) += numa.o numa_$(BITS).o | 25 | obj-$(CONFIG_NUMA) += numa.o numa_$(BITS).o |
26 | obj-$(CONFIG_K8_NUMA) += k8topology_64.o | 26 | obj-$(CONFIG_AMD_NUMA) += amdtopology_64.o |
27 | obj-$(CONFIG_ACPI_NUMA) += srat_$(BITS).o | 27 | obj-$(CONFIG_ACPI_NUMA) += srat_$(BITS).o |
28 | 28 | ||
29 | obj-$(CONFIG_HAVE_MEMBLOCK) += memblock.o | 29 | obj-$(CONFIG_HAVE_MEMBLOCK) += memblock.o |
diff --git a/arch/x86/mm/k8topology_64.c b/arch/x86/mm/amdtopology_64.c index 804a3b6c6e14..51fae9cfdecb 100644 --- a/arch/x86/mm/k8topology_64.c +++ b/arch/x86/mm/amdtopology_64.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * AMD K8 NUMA support. | 2 | * AMD NUMA support. |
3 | * Discover the memory map and associated nodes. | 3 | * Discover the memory map and associated nodes. |
4 | * | 4 | * |
5 | * This version reads it directly from the K8 northbridge. | 5 | * This version reads it directly from the AMD northbridge. |
6 | * | 6 | * |
7 | * Copyright 2002,2003 Andi Kleen, SuSE Labs. | 7 | * Copyright 2002,2003 Andi Kleen, SuSE Labs. |
8 | */ | 8 | */ |
@@ -57,7 +57,7 @@ static __init void early_get_boot_cpu_id(void) | |||
57 | { | 57 | { |
58 | /* | 58 | /* |
59 | * need to get the APIC ID of the BSP so can use that to | 59 | * need to get the APIC ID of the BSP so can use that to |
60 | * create apicid_to_node in k8_scan_nodes() | 60 | * create apicid_to_node in amd_scan_nodes() |
61 | */ | 61 | */ |
62 | #ifdef CONFIG_X86_MPPARSE | 62 | #ifdef CONFIG_X86_MPPARSE |
63 | /* | 63 | /* |
@@ -69,7 +69,7 @@ static __init void early_get_boot_cpu_id(void) | |||
69 | early_init_lapic_mapping(); | 69 | early_init_lapic_mapping(); |
70 | } | 70 | } |
71 | 71 | ||
72 | int __init k8_get_nodes(struct bootnode *physnodes) | 72 | int __init amd_get_nodes(struct bootnode *physnodes) |
73 | { | 73 | { |
74 | int i; | 74 | int i; |
75 | int ret = 0; | 75 | int ret = 0; |
@@ -82,7 +82,7 @@ int __init k8_get_nodes(struct bootnode *physnodes) | |||
82 | return ret; | 82 | return ret; |
83 | } | 83 | } |
84 | 84 | ||
85 | int __init k8_numa_init(unsigned long start_pfn, unsigned long end_pfn) | 85 | int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn) |
86 | { | 86 | { |
87 | unsigned long start = PFN_PHYS(start_pfn); | 87 | unsigned long start = PFN_PHYS(start_pfn); |
88 | unsigned long end = PFN_PHYS(end_pfn); | 88 | unsigned long end = PFN_PHYS(end_pfn); |
@@ -194,7 +194,7 @@ int __init k8_numa_init(unsigned long start_pfn, unsigned long end_pfn) | |||
194 | return 0; | 194 | return 0; |
195 | } | 195 | } |
196 | 196 | ||
197 | int __init k8_scan_nodes(void) | 197 | int __init amd_scan_nodes(void) |
198 | { | 198 | { |
199 | unsigned int bits; | 199 | unsigned int bits; |
200 | unsigned int cores; | 200 | unsigned int cores; |
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index c0e28a13de7d..947f42abe820 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
@@ -364,8 +364,9 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end) | |||
364 | /* | 364 | /* |
365 | * We just marked the kernel text read only above, now that | 365 | * We just marked the kernel text read only above, now that |
366 | * we are going to free part of that, we need to make that | 366 | * we are going to free part of that, we need to make that |
367 | * writeable first. | 367 | * writeable and non-executable first. |
368 | */ | 368 | */ |
369 | set_memory_nx(begin, (end - begin) >> PAGE_SHIFT); | ||
369 | set_memory_rw(begin, (end - begin) >> PAGE_SHIFT); | 370 | set_memory_rw(begin, (end - begin) >> PAGE_SHIFT); |
370 | 371 | ||
371 | printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10); | 372 | printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10); |
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index 0e969f9f401b..f89b5bb4e93f 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -226,7 +226,7 @@ page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base) | |||
226 | 226 | ||
227 | static inline int is_kernel_text(unsigned long addr) | 227 | static inline int is_kernel_text(unsigned long addr) |
228 | { | 228 | { |
229 | if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end) | 229 | if (addr >= (unsigned long)_text && addr <= (unsigned long)__init_end) |
230 | return 1; | 230 | return 1; |
231 | return 0; | 231 | return 0; |
232 | } | 232 | } |
@@ -912,6 +912,23 @@ void set_kernel_text_ro(void) | |||
912 | set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); | 912 | set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); |
913 | } | 913 | } |
914 | 914 | ||
915 | static void mark_nxdata_nx(void) | ||
916 | { | ||
917 | /* | ||
918 | * When this called, init has already been executed and released, | ||
919 | * so everything past _etext sould be NX. | ||
920 | */ | ||
921 | unsigned long start = PFN_ALIGN(_etext); | ||
922 | /* | ||
923 | * This comes from is_kernel_text upper limit. Also HPAGE where used: | ||
924 | */ | ||
925 | unsigned long size = (((unsigned long)__init_end + HPAGE_SIZE) & HPAGE_MASK) - start; | ||
926 | |||
927 | if (__supported_pte_mask & _PAGE_NX) | ||
928 | printk(KERN_INFO "NX-protecting the kernel data: %luk\n", size >> 10); | ||
929 | set_pages_nx(virt_to_page(start), size >> PAGE_SHIFT); | ||
930 | } | ||
931 | |||
915 | void mark_rodata_ro(void) | 932 | void mark_rodata_ro(void) |
916 | { | 933 | { |
917 | unsigned long start = PFN_ALIGN(_text); | 934 | unsigned long start = PFN_ALIGN(_text); |
@@ -946,6 +963,7 @@ void mark_rodata_ro(void) | |||
946 | printk(KERN_INFO "Testing CPA: write protecting again\n"); | 963 | printk(KERN_INFO "Testing CPA: write protecting again\n"); |
947 | set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); | 964 | set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); |
948 | #endif | 965 | #endif |
966 | mark_nxdata_nx(); | ||
949 | } | 967 | } |
950 | #endif | 968 | #endif |
951 | 969 | ||
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c index 7ffc9b727efd..7762a517d69d 100644 --- a/arch/x86/mm/numa_64.c +++ b/arch/x86/mm/numa_64.c | |||
@@ -264,7 +264,7 @@ static struct bootnode physnodes[MAX_NUMNODES] __initdata; | |||
264 | static char *cmdline __initdata; | 264 | static char *cmdline __initdata; |
265 | 265 | ||
266 | static int __init setup_physnodes(unsigned long start, unsigned long end, | 266 | static int __init setup_physnodes(unsigned long start, unsigned long end, |
267 | int acpi, int k8) | 267 | int acpi, int amd) |
268 | { | 268 | { |
269 | int nr_nodes = 0; | 269 | int nr_nodes = 0; |
270 | int ret = 0; | 270 | int ret = 0; |
@@ -274,13 +274,13 @@ static int __init setup_physnodes(unsigned long start, unsigned long end, | |||
274 | if (acpi) | 274 | if (acpi) |
275 | nr_nodes = acpi_get_nodes(physnodes); | 275 | nr_nodes = acpi_get_nodes(physnodes); |
276 | #endif | 276 | #endif |
277 | #ifdef CONFIG_K8_NUMA | 277 | #ifdef CONFIG_AMD_NUMA |
278 | if (k8) | 278 | if (amd) |
279 | nr_nodes = k8_get_nodes(physnodes); | 279 | nr_nodes = amd_get_nodes(physnodes); |
280 | #endif | 280 | #endif |
281 | /* | 281 | /* |
282 | * Basic sanity checking on the physical node map: there may be errors | 282 | * Basic sanity checking on the physical node map: there may be errors |
283 | * if the SRAT or K8 incorrectly reported the topology or the mem= | 283 | * if the SRAT or AMD code incorrectly reported the topology or the mem= |
284 | * kernel parameter is used. | 284 | * kernel parameter is used. |
285 | */ | 285 | */ |
286 | for (i = 0; i < nr_nodes; i++) { | 286 | for (i = 0; i < nr_nodes; i++) { |
@@ -549,7 +549,7 @@ static int __init split_nodes_size_interleave(u64 addr, u64 max_addr, u64 size) | |||
549 | * numa=fake command-line option. | 549 | * numa=fake command-line option. |
550 | */ | 550 | */ |
551 | static int __init numa_emulation(unsigned long start_pfn, | 551 | static int __init numa_emulation(unsigned long start_pfn, |
552 | unsigned long last_pfn, int acpi, int k8) | 552 | unsigned long last_pfn, int acpi, int amd) |
553 | { | 553 | { |
554 | u64 addr = start_pfn << PAGE_SHIFT; | 554 | u64 addr = start_pfn << PAGE_SHIFT; |
555 | u64 max_addr = last_pfn << PAGE_SHIFT; | 555 | u64 max_addr = last_pfn << PAGE_SHIFT; |
@@ -557,7 +557,7 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
557 | int num_nodes; | 557 | int num_nodes; |
558 | int i; | 558 | int i; |
559 | 559 | ||
560 | num_phys_nodes = setup_physnodes(addr, max_addr, acpi, k8); | 560 | num_phys_nodes = setup_physnodes(addr, max_addr, acpi, amd); |
561 | /* | 561 | /* |
562 | * If the numa=fake command-line contains a 'M' or 'G', it represents | 562 | * If the numa=fake command-line contains a 'M' or 'G', it represents |
563 | * the fixed node size. Otherwise, if it is just a single number N, | 563 | * the fixed node size. Otherwise, if it is just a single number N, |
@@ -602,7 +602,7 @@ static int __init numa_emulation(unsigned long start_pfn, | |||
602 | #endif /* CONFIG_NUMA_EMU */ | 602 | #endif /* CONFIG_NUMA_EMU */ |
603 | 603 | ||
604 | void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn, | 604 | void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn, |
605 | int acpi, int k8) | 605 | int acpi, int amd) |
606 | { | 606 | { |
607 | int i; | 607 | int i; |
608 | 608 | ||
@@ -610,7 +610,7 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn, | |||
610 | nodes_clear(node_online_map); | 610 | nodes_clear(node_online_map); |
611 | 611 | ||
612 | #ifdef CONFIG_NUMA_EMU | 612 | #ifdef CONFIG_NUMA_EMU |
613 | if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, k8)) | 613 | if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd)) |
614 | return; | 614 | return; |
615 | nodes_clear(node_possible_map); | 615 | nodes_clear(node_possible_map); |
616 | nodes_clear(node_online_map); | 616 | nodes_clear(node_online_map); |
@@ -624,8 +624,8 @@ void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn, | |||
624 | nodes_clear(node_online_map); | 624 | nodes_clear(node_online_map); |
625 | #endif | 625 | #endif |
626 | 626 | ||
627 | #ifdef CONFIG_K8_NUMA | 627 | #ifdef CONFIG_AMD_NUMA |
628 | if (!numa_off && k8 && !k8_scan_nodes()) | 628 | if (!numa_off && amd && !amd_scan_nodes()) |
629 | return; | 629 | return; |
630 | nodes_clear(node_possible_map); | 630 | nodes_clear(node_possible_map); |
631 | nodes_clear(node_online_map); | 631 | nodes_clear(node_online_map); |
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 532e7933d606..8b830ca14ac4 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/pfn.h> | 13 | #include <linux/pfn.h> |
14 | #include <linux/percpu.h> | 14 | #include <linux/percpu.h> |
15 | #include <linux/gfp.h> | 15 | #include <linux/gfp.h> |
16 | #include <linux/pci.h> | ||
16 | 17 | ||
17 | #include <asm/e820.h> | 18 | #include <asm/e820.h> |
18 | #include <asm/processor.h> | 19 | #include <asm/processor.h> |
@@ -255,13 +256,16 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, | |||
255 | unsigned long pfn) | 256 | unsigned long pfn) |
256 | { | 257 | { |
257 | pgprot_t forbidden = __pgprot(0); | 258 | pgprot_t forbidden = __pgprot(0); |
259 | pgprot_t required = __pgprot(0); | ||
258 | 260 | ||
259 | /* | 261 | /* |
260 | * The BIOS area between 640k and 1Mb needs to be executable for | 262 | * The BIOS area between 640k and 1Mb needs to be executable for |
261 | * PCI BIOS based config access (CONFIG_PCI_GOBIOS) support. | 263 | * PCI BIOS based config access (CONFIG_PCI_GOBIOS) support. |
262 | */ | 264 | */ |
263 | if (within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT)) | 265 | #ifdef CONFIG_PCI_BIOS |
266 | if (pcibios_enabled && within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT)) | ||
264 | pgprot_val(forbidden) |= _PAGE_NX; | 267 | pgprot_val(forbidden) |= _PAGE_NX; |
268 | #endif | ||
265 | 269 | ||
266 | /* | 270 | /* |
267 | * The kernel text needs to be executable for obvious reasons | 271 | * The kernel text needs to be executable for obvious reasons |
@@ -278,6 +282,12 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, | |||
278 | if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT, | 282 | if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT, |
279 | __pa((unsigned long)__end_rodata) >> PAGE_SHIFT)) | 283 | __pa((unsigned long)__end_rodata) >> PAGE_SHIFT)) |
280 | pgprot_val(forbidden) |= _PAGE_RW; | 284 | pgprot_val(forbidden) |= _PAGE_RW; |
285 | /* | ||
286 | * .data and .bss should always be writable. | ||
287 | */ | ||
288 | if (within(address, (unsigned long)_sdata, (unsigned long)_edata) || | ||
289 | within(address, (unsigned long)__bss_start, (unsigned long)__bss_stop)) | ||
290 | pgprot_val(required) |= _PAGE_RW; | ||
281 | 291 | ||
282 | #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) | 292 | #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) |
283 | /* | 293 | /* |
@@ -317,6 +327,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address, | |||
317 | #endif | 327 | #endif |
318 | 328 | ||
319 | prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden)); | 329 | prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden)); |
330 | prot = __pgprot(pgprot_val(prot) | pgprot_val(required)); | ||
320 | 331 | ||
321 | return prot; | 332 | return prot; |
322 | } | 333 | } |
@@ -393,7 +404,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
393 | { | 404 | { |
394 | unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn; | 405 | unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn; |
395 | pte_t new_pte, old_pte, *tmp; | 406 | pte_t new_pte, old_pte, *tmp; |
396 | pgprot_t old_prot, new_prot; | 407 | pgprot_t old_prot, new_prot, req_prot; |
397 | int i, do_split = 1; | 408 | int i, do_split = 1; |
398 | unsigned int level; | 409 | unsigned int level; |
399 | 410 | ||
@@ -438,10 +449,10 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
438 | * We are safe now. Check whether the new pgprot is the same: | 449 | * We are safe now. Check whether the new pgprot is the same: |
439 | */ | 450 | */ |
440 | old_pte = *kpte; | 451 | old_pte = *kpte; |
441 | old_prot = new_prot = pte_pgprot(old_pte); | 452 | old_prot = new_prot = req_prot = pte_pgprot(old_pte); |
442 | 453 | ||
443 | pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr); | 454 | pgprot_val(req_prot) &= ~pgprot_val(cpa->mask_clr); |
444 | pgprot_val(new_prot) |= pgprot_val(cpa->mask_set); | 455 | pgprot_val(req_prot) |= pgprot_val(cpa->mask_set); |
445 | 456 | ||
446 | /* | 457 | /* |
447 | * old_pte points to the large page base address. So we need | 458 | * old_pte points to the large page base address. So we need |
@@ -450,17 +461,17 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
450 | pfn = pte_pfn(old_pte) + ((address & (psize - 1)) >> PAGE_SHIFT); | 461 | pfn = pte_pfn(old_pte) + ((address & (psize - 1)) >> PAGE_SHIFT); |
451 | cpa->pfn = pfn; | 462 | cpa->pfn = pfn; |
452 | 463 | ||
453 | new_prot = static_protections(new_prot, address, pfn); | 464 | new_prot = static_protections(req_prot, address, pfn); |
454 | 465 | ||
455 | /* | 466 | /* |
456 | * We need to check the full range, whether | 467 | * We need to check the full range, whether |
457 | * static_protection() requires a different pgprot for one of | 468 | * static_protection() requires a different pgprot for one of |
458 | * the pages in the range we try to preserve: | 469 | * the pages in the range we try to preserve: |
459 | */ | 470 | */ |
460 | addr = address + PAGE_SIZE; | 471 | addr = address & pmask; |
461 | pfn++; | 472 | pfn = pte_pfn(old_pte); |
462 | for (i = 1; i < cpa->numpages; i++, addr += PAGE_SIZE, pfn++) { | 473 | for (i = 0; i < (psize >> PAGE_SHIFT); i++, addr += PAGE_SIZE, pfn++) { |
463 | pgprot_t chk_prot = static_protections(new_prot, addr, pfn); | 474 | pgprot_t chk_prot = static_protections(req_prot, addr, pfn); |
464 | 475 | ||
465 | if (pgprot_val(chk_prot) != pgprot_val(new_prot)) | 476 | if (pgprot_val(chk_prot) != pgprot_val(new_prot)) |
466 | goto out_unlock; | 477 | goto out_unlock; |
@@ -483,7 +494,7 @@ try_preserve_large_page(pte_t *kpte, unsigned long address, | |||
483 | * that we limited the number of possible pages already to | 494 | * that we limited the number of possible pages already to |
484 | * the number of pages in the large page. | 495 | * the number of pages in the large page. |
485 | */ | 496 | */ |
486 | if (address == (nextpage_addr - psize) && cpa->numpages == numpages) { | 497 | if (address == (address & pmask) && cpa->numpages == (psize >> PAGE_SHIFT)) { |
487 | /* | 498 | /* |
488 | * The address is aligned and the number of pages | 499 | * The address is aligned and the number of pages |
489 | * covers the full page. | 500 | * covers the full page. |
diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c index a3250aa34086..410531d3c292 100644 --- a/arch/x86/mm/setup_nx.c +++ b/arch/x86/mm/setup_nx.c | |||
@@ -41,7 +41,7 @@ void __init x86_report_nx(void) | |||
41 | { | 41 | { |
42 | if (!cpu_has_nx) { | 42 | if (!cpu_has_nx) { |
43 | printk(KERN_NOTICE "Notice: NX (Execute Disable) protection " | 43 | printk(KERN_NOTICE "Notice: NX (Execute Disable) protection " |
44 | "missing in CPU or disabled in BIOS!\n"); | 44 | "missing in CPU!\n"); |
45 | } else { | 45 | } else { |
46 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) | 46 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) |
47 | if (disable_nx) { | 47 | if (disable_nx) { |
diff --git a/arch/x86/mm/srat_32.c b/arch/x86/mm/srat_32.c index a17dffd136c1..f16434568a51 100644 --- a/arch/x86/mm/srat_32.c +++ b/arch/x86/mm/srat_32.c | |||
@@ -92,6 +92,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *cpu_affinity) | |||
92 | /* mark this node as "seen" in node bitmap */ | 92 | /* mark this node as "seen" in node bitmap */ |
93 | BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain_lo); | 93 | BMAP_SET(pxm_bitmap, cpu_affinity->proximity_domain_lo); |
94 | 94 | ||
95 | /* don't need to check apic_id here, because it is always 8 bits */ | ||
95 | apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain_lo; | 96 | apicid_to_pxm[cpu_affinity->apic_id] = cpu_affinity->proximity_domain_lo; |
96 | 97 | ||
97 | printk(KERN_DEBUG "CPU %02x in proximity domain %02x\n", | 98 | printk(KERN_DEBUG "CPU %02x in proximity domain %02x\n", |
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index a35cb9d8b060..171a0aacb99a 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c | |||
@@ -134,6 +134,10 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa) | |||
134 | } | 134 | } |
135 | 135 | ||
136 | apic_id = pa->apic_id; | 136 | apic_id = pa->apic_id; |
137 | if (apic_id >= MAX_LOCAL_APIC) { | ||
138 | printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u skipped apicid that is too big\n", pxm, apic_id, node); | ||
139 | return; | ||
140 | } | ||
137 | apicid_to_node[apic_id] = node; | 141 | apicid_to_node[apic_id] = node; |
138 | node_set(node, cpu_nodes_parsed); | 142 | node_set(node, cpu_nodes_parsed); |
139 | acpi_numa = 1; | 143 | acpi_numa = 1; |
@@ -168,6 +172,12 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) | |||
168 | apic_id = (pa->apic_id << 8) | pa->local_sapic_eid; | 172 | apic_id = (pa->apic_id << 8) | pa->local_sapic_eid; |
169 | else | 173 | else |
170 | apic_id = pa->apic_id; | 174 | apic_id = pa->apic_id; |
175 | |||
176 | if (apic_id >= MAX_LOCAL_APIC) { | ||
177 | printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u skipped apicid that is too big\n", pxm, apic_id, node); | ||
178 | return; | ||
179 | } | ||
180 | |||
171 | apicid_to_node[apic_id] = node; | 181 | apicid_to_node[apic_id] = node; |
172 | node_set(node, cpu_nodes_parsed); | 182 | node_set(node, cpu_nodes_parsed); |
173 | acpi_numa = 1; | 183 | acpi_numa = 1; |
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 51104b33fd51..c3b8e24f2b16 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c | |||
@@ -610,6 +610,7 @@ static int force_ibs_eilvt_setup(void) | |||
610 | ret = setup_ibs_ctl(i); | 610 | ret = setup_ibs_ctl(i); |
611 | if (ret) | 611 | if (ret) |
612 | return ret; | 612 | return ret; |
613 | pr_err(FW_BUG "using offset %d for IBS interrupts\n", i); | ||
613 | return 0; | 614 | return 0; |
614 | } | 615 | } |
615 | 616 | ||
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile index effd96e33f16..6b8759f7634e 100644 --- a/arch/x86/pci/Makefile +++ b/arch/x86/pci/Makefile | |||
@@ -7,6 +7,7 @@ obj-$(CONFIG_PCI_OLPC) += olpc.o | |||
7 | obj-$(CONFIG_PCI_XEN) += xen.o | 7 | obj-$(CONFIG_PCI_XEN) += xen.o |
8 | 8 | ||
9 | obj-y += fixup.o | 9 | obj-y += fixup.o |
10 | obj-$(CONFIG_X86_INTEL_CE) += ce4100.o | ||
10 | obj-$(CONFIG_ACPI) += acpi.o | 11 | obj-$(CONFIG_ACPI) += acpi.o |
11 | obj-y += legacy.o irq.o | 12 | obj-y += legacy.o irq.o |
12 | 13 | ||
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c new file mode 100644 index 000000000000..85b68ef5e809 --- /dev/null +++ b/arch/x86/pci/ce4100.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* | ||
2 | * GPL LICENSE SUMMARY | ||
3 | * | ||
4 | * Copyright(c) 2010 Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of version 2 of the GNU General Public License as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * The full GNU General Public License is included in this distribution | ||
19 | * in the file called LICENSE.GPL. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Corporation | ||
23 | * 2200 Mission College Blvd. | ||
24 | * Santa Clara, CA 97052 | ||
25 | * | ||
26 | * This provides access methods for PCI registers that mis-behave on | ||
27 | * the CE4100. Each register can be assigned a private init, read and | ||
28 | * write routine. The exception to this is the bridge device. The | ||
29 | * bridge device is the only device on bus zero (0) that requires any | ||
30 | * fixup so it is a special case ATM | ||
31 | */ | ||
32 | |||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/pci.h> | ||
35 | #include <linux/init.h> | ||
36 | |||
37 | #include <asm/pci_x86.h> | ||
38 | |||
39 | struct sim_reg { | ||
40 | u32 value; | ||
41 | u32 mask; | ||
42 | }; | ||
43 | |||
44 | struct sim_dev_reg { | ||
45 | int dev_func; | ||
46 | int reg; | ||
47 | void (*init)(struct sim_dev_reg *reg); | ||
48 | void (*read)(struct sim_dev_reg *reg, u32 *value); | ||
49 | void (*write)(struct sim_dev_reg *reg, u32 value); | ||
50 | struct sim_reg sim_reg; | ||
51 | }; | ||
52 | |||
53 | struct sim_reg_op { | ||
54 | void (*init)(struct sim_dev_reg *reg); | ||
55 | void (*read)(struct sim_dev_reg *reg, u32 value); | ||
56 | void (*write)(struct sim_dev_reg *reg, u32 value); | ||
57 | }; | ||
58 | |||
59 | #define MB (1024 * 1024) | ||
60 | #define KB (1024) | ||
61 | #define SIZE_TO_MASK(size) (~(size - 1)) | ||
62 | |||
63 | #define DEFINE_REG(device, func, offset, size, init_op, read_op, write_op)\ | ||
64 | { PCI_DEVFN(device, func), offset, init_op, read_op, write_op,\ | ||
65 | {0, SIZE_TO_MASK(size)} }, | ||
66 | |||
67 | static void reg_init(struct sim_dev_reg *reg) | ||
68 | { | ||
69 | pci_direct_conf1.read(0, 1, reg->dev_func, reg->reg, 4, | ||
70 | ®->sim_reg.value); | ||
71 | } | ||
72 | |||
73 | static void reg_read(struct sim_dev_reg *reg, u32 *value) | ||
74 | { | ||
75 | unsigned long flags; | ||
76 | |||
77 | raw_spin_lock_irqsave(&pci_config_lock, flags); | ||
78 | *value = reg->sim_reg.value; | ||
79 | raw_spin_unlock_irqrestore(&pci_config_lock, flags); | ||
80 | } | ||
81 | |||
82 | static void reg_write(struct sim_dev_reg *reg, u32 value) | ||
83 | { | ||
84 | unsigned long flags; | ||
85 | |||
86 | raw_spin_lock_irqsave(&pci_config_lock, flags); | ||
87 | reg->sim_reg.value = (value & reg->sim_reg.mask) | | ||
88 | (reg->sim_reg.value & ~reg->sim_reg.mask); | ||
89 | raw_spin_unlock_irqrestore(&pci_config_lock, flags); | ||
90 | } | ||
91 | |||
92 | static void sata_reg_init(struct sim_dev_reg *reg) | ||
93 | { | ||
94 | pci_direct_conf1.read(0, 1, PCI_DEVFN(14, 0), 0x10, 4, | ||
95 | ®->sim_reg.value); | ||
96 | reg->sim_reg.value += 0x400; | ||
97 | } | ||
98 | |||
99 | static void ehci_reg_read(struct sim_dev_reg *reg, u32 *value) | ||
100 | { | ||
101 | reg_read(reg, value); | ||
102 | if (*value != reg->sim_reg.mask) | ||
103 | *value |= 0x100; | ||
104 | } | ||
105 | |||
106 | void sata_revid_init(struct sim_dev_reg *reg) | ||
107 | { | ||
108 | reg->sim_reg.value = 0x01060100; | ||
109 | reg->sim_reg.mask = 0; | ||
110 | } | ||
111 | |||
112 | static void sata_revid_read(struct sim_dev_reg *reg, u32 *value) | ||
113 | { | ||
114 | reg_read(reg, value); | ||
115 | } | ||
116 | |||
117 | static struct sim_dev_reg bus1_fixups[] = { | ||
118 | DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write) | ||
119 | DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write) | ||
120 | DEFINE_REG(2, 1, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
121 | DEFINE_REG(3, 0, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
122 | DEFINE_REG(4, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) | ||
123 | DEFINE_REG(4, 1, 0x10, (128*KB), reg_init, reg_read, reg_write) | ||
124 | DEFINE_REG(6, 0, 0x10, (512*KB), reg_init, reg_read, reg_write) | ||
125 | DEFINE_REG(6, 1, 0x10, (512*KB), reg_init, reg_read, reg_write) | ||
126 | DEFINE_REG(6, 2, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
127 | DEFINE_REG(8, 0, 0x10, (1*MB), reg_init, reg_read, reg_write) | ||
128 | DEFINE_REG(8, 1, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
129 | DEFINE_REG(8, 2, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
130 | DEFINE_REG(9, 0, 0x10 , (1*MB), reg_init, reg_read, reg_write) | ||
131 | DEFINE_REG(9, 0, 0x14, (64*KB), reg_init, reg_read, reg_write) | ||
132 | DEFINE_REG(10, 0, 0x10, (256), reg_init, reg_read, reg_write) | ||
133 | DEFINE_REG(10, 0, 0x14, (256*MB), reg_init, reg_read, reg_write) | ||
134 | DEFINE_REG(11, 0, 0x10, (256), reg_init, reg_read, reg_write) | ||
135 | DEFINE_REG(11, 0, 0x14, (256), reg_init, reg_read, reg_write) | ||
136 | DEFINE_REG(11, 1, 0x10, (256), reg_init, reg_read, reg_write) | ||
137 | DEFINE_REG(11, 2, 0x10, (256), reg_init, reg_read, reg_write) | ||
138 | DEFINE_REG(11, 2, 0x14, (256), reg_init, reg_read, reg_write) | ||
139 | DEFINE_REG(11, 2, 0x18, (256), reg_init, reg_read, reg_write) | ||
140 | DEFINE_REG(11, 3, 0x10, (256), reg_init, reg_read, reg_write) | ||
141 | DEFINE_REG(11, 3, 0x14, (256), reg_init, reg_read, reg_write) | ||
142 | DEFINE_REG(11, 4, 0x10, (256), reg_init, reg_read, reg_write) | ||
143 | DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
144 | DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write) | ||
145 | DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
146 | DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) | ||
147 | DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write) | ||
148 | DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write) | ||
149 | DEFINE_REG(13, 0, 0x10, (32*KB), reg_init, ehci_reg_read, reg_write) | ||
150 | DEFINE_REG(13, 1, 0x10, (32*KB), reg_init, ehci_reg_read, reg_write) | ||
151 | DEFINE_REG(14, 0, 0x8, 0, sata_revid_init, sata_revid_read, 0) | ||
152 | DEFINE_REG(14, 0, 0x10, 0, reg_init, reg_read, reg_write) | ||
153 | DEFINE_REG(14, 0, 0x14, 0, reg_init, reg_read, reg_write) | ||
154 | DEFINE_REG(14, 0, 0x18, 0, reg_init, reg_read, reg_write) | ||
155 | DEFINE_REG(14, 0, 0x1C, 0, reg_init, reg_read, reg_write) | ||
156 | DEFINE_REG(14, 0, 0x20, 0, reg_init, reg_read, reg_write) | ||
157 | DEFINE_REG(14, 0, 0x24, (0x200), sata_reg_init, reg_read, reg_write) | ||
158 | DEFINE_REG(15, 0, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
159 | DEFINE_REG(15, 0, 0x14, (64*KB), reg_init, reg_read, reg_write) | ||
160 | DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write) | ||
161 | DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write) | ||
162 | DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write) | ||
163 | DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write) | ||
164 | DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write) | ||
165 | }; | ||
166 | |||
167 | static void __init init_sim_regs(void) | ||
168 | { | ||
169 | int i; | ||
170 | |||
171 | for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { | ||
172 | if (bus1_fixups[i].init) | ||
173 | bus1_fixups[i].init(&bus1_fixups[i]); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | static inline void extract_bytes(u32 *value, int reg, int len) | ||
178 | { | ||
179 | uint32_t mask; | ||
180 | |||
181 | *value >>= ((reg & 3) * 8); | ||
182 | mask = 0xFFFFFFFF >> ((4 - len) * 8); | ||
183 | *value &= mask; | ||
184 | } | ||
185 | |||
186 | int bridge_read(unsigned int devfn, int reg, int len, u32 *value) | ||
187 | { | ||
188 | u32 av_bridge_base, av_bridge_limit; | ||
189 | int retval = 0; | ||
190 | |||
191 | switch (reg) { | ||
192 | /* Make BARs appear to not request any memory. */ | ||
193 | case PCI_BASE_ADDRESS_0: | ||
194 | case PCI_BASE_ADDRESS_0 + 1: | ||
195 | case PCI_BASE_ADDRESS_0 + 2: | ||
196 | case PCI_BASE_ADDRESS_0 + 3: | ||
197 | *value = 0; | ||
198 | break; | ||
199 | |||
200 | /* Since subordinate bus number register is hardwired | ||
201 | * to zero and read only, so do the simulation. | ||
202 | */ | ||
203 | case PCI_PRIMARY_BUS: | ||
204 | if (len == 4) | ||
205 | *value = 0x00010100; | ||
206 | break; | ||
207 | |||
208 | case PCI_SUBORDINATE_BUS: | ||
209 | *value = 1; | ||
210 | break; | ||
211 | |||
212 | case PCI_MEMORY_BASE: | ||
213 | case PCI_MEMORY_LIMIT: | ||
214 | /* Get the A/V bridge base address. */ | ||
215 | pci_direct_conf1.read(0, 0, devfn, | ||
216 | PCI_BASE_ADDRESS_0, 4, &av_bridge_base); | ||
217 | |||
218 | av_bridge_limit = av_bridge_base + (512*MB - 1); | ||
219 | av_bridge_limit >>= 16; | ||
220 | av_bridge_limit &= 0xFFF0; | ||
221 | |||
222 | av_bridge_base >>= 16; | ||
223 | av_bridge_base &= 0xFFF0; | ||
224 | |||
225 | if (reg == PCI_MEMORY_LIMIT) | ||
226 | *value = av_bridge_limit; | ||
227 | else if (len == 2) | ||
228 | *value = av_bridge_base; | ||
229 | else | ||
230 | *value = (av_bridge_limit << 16) | av_bridge_base; | ||
231 | break; | ||
232 | /* Make prefetchable memory limit smaller than prefetchable | ||
233 | * memory base, so not claim prefetchable memory space. | ||
234 | */ | ||
235 | case PCI_PREF_MEMORY_BASE: | ||
236 | *value = 0xFFF0; | ||
237 | break; | ||
238 | case PCI_PREF_MEMORY_LIMIT: | ||
239 | *value = 0x0; | ||
240 | break; | ||
241 | /* Make IO limit smaller than IO base, so not claim IO space. */ | ||
242 | case PCI_IO_BASE: | ||
243 | *value = 0xF0; | ||
244 | break; | ||
245 | case PCI_IO_LIMIT: | ||
246 | *value = 0; | ||
247 | break; | ||
248 | default: | ||
249 | retval = 1; | ||
250 | } | ||
251 | return retval; | ||
252 | } | ||
253 | |||
254 | static int ce4100_conf_read(unsigned int seg, unsigned int bus, | ||
255 | unsigned int devfn, int reg, int len, u32 *value) | ||
256 | { | ||
257 | int i, retval = 1; | ||
258 | |||
259 | if (bus == 1) { | ||
260 | for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { | ||
261 | if (bus1_fixups[i].dev_func == devfn && | ||
262 | bus1_fixups[i].reg == (reg & ~3) && | ||
263 | bus1_fixups[i].read) { | ||
264 | bus1_fixups[i].read(&(bus1_fixups[i]), | ||
265 | value); | ||
266 | extract_bytes(value, reg, len); | ||
267 | return 0; | ||
268 | } | ||
269 | } | ||
270 | } | ||
271 | |||
272 | if (bus == 0 && (PCI_DEVFN(1, 0) == devfn) && | ||
273 | !bridge_read(devfn, reg, len, value)) | ||
274 | return 0; | ||
275 | |||
276 | return pci_direct_conf1.read(seg, bus, devfn, reg, len, value); | ||
277 | } | ||
278 | |||
279 | static int ce4100_conf_write(unsigned int seg, unsigned int bus, | ||
280 | unsigned int devfn, int reg, int len, u32 value) | ||
281 | { | ||
282 | int i; | ||
283 | |||
284 | if (bus == 1) { | ||
285 | for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) { | ||
286 | if (bus1_fixups[i].dev_func == devfn && | ||
287 | bus1_fixups[i].reg == (reg & ~3) && | ||
288 | bus1_fixups[i].write) { | ||
289 | bus1_fixups[i].write(&(bus1_fixups[i]), | ||
290 | value); | ||
291 | return 0; | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | /* Discard writes to A/V bridge BAR. */ | ||
297 | if (bus == 0 && PCI_DEVFN(1, 0) == devfn && | ||
298 | ((reg & ~3) == PCI_BASE_ADDRESS_0)) | ||
299 | return 0; | ||
300 | |||
301 | return pci_direct_conf1.write(seg, bus, devfn, reg, len, value); | ||
302 | } | ||
303 | |||
304 | struct pci_raw_ops ce4100_pci_conf = { | ||
305 | .read = ce4100_conf_read, | ||
306 | .write = ce4100_conf_write, | ||
307 | }; | ||
308 | |||
309 | static int __init ce4100_pci_init(void) | ||
310 | { | ||
311 | init_sim_regs(); | ||
312 | raw_pci_ops = &ce4100_pci_conf; | ||
313 | return 0; | ||
314 | } | ||
315 | subsys_initcall(ce4100_pci_init); | ||
diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c index 2492d165096a..a5f7d0d63de0 100644 --- a/arch/x86/pci/pcbios.c +++ b/arch/x86/pci/pcbios.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/uaccess.h> | 9 | #include <linux/uaccess.h> |
10 | #include <asm/pci_x86.h> | 10 | #include <asm/pci_x86.h> |
11 | #include <asm/pci-functions.h> | 11 | #include <asm/pci-functions.h> |
12 | #include <asm/cacheflush.h> | ||
12 | 13 | ||
13 | /* BIOS32 signature: "_32_" */ | 14 | /* BIOS32 signature: "_32_" */ |
14 | #define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) | 15 | #define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) |
@@ -25,6 +26,27 @@ | |||
25 | #define PCIBIOS_HW_TYPE1_SPEC 0x10 | 26 | #define PCIBIOS_HW_TYPE1_SPEC 0x10 |
26 | #define PCIBIOS_HW_TYPE2_SPEC 0x20 | 27 | #define PCIBIOS_HW_TYPE2_SPEC 0x20 |
27 | 28 | ||
29 | int pcibios_enabled; | ||
30 | |||
31 | /* According to the BIOS specification at: | ||
32 | * http://members.datafast.net.au/dft0802/specs/bios21.pdf, we could | ||
33 | * restrict the x zone to some pages and make it ro. But this may be | ||
34 | * broken on some bios, complex to handle with static_protections. | ||
35 | * We could make the 0xe0000-0x100000 range rox, but this can break | ||
36 | * some ISA mapping. | ||
37 | * | ||
38 | * So we let's an rw and x hole when pcibios is used. This shouldn't | ||
39 | * happen for modern system with mmconfig, and if you don't want it | ||
40 | * you could disable pcibios... | ||
41 | */ | ||
42 | static inline void set_bios_x(void) | ||
43 | { | ||
44 | pcibios_enabled = 1; | ||
45 | set_memory_x(PAGE_OFFSET + BIOS_BEGIN, (BIOS_END - BIOS_BEGIN) >> PAGE_SHIFT); | ||
46 | if (__supported_pte_mask & _PAGE_NX) | ||
47 | printk(KERN_INFO "PCI : PCI BIOS aera is rw and x. Use pci=nobios if you want it NX.\n"); | ||
48 | } | ||
49 | |||
28 | /* | 50 | /* |
29 | * This is the standard structure used to identify the entry point | 51 | * This is the standard structure used to identify the entry point |
30 | * to the BIOS32 Service Directory, as documented in | 52 | * to the BIOS32 Service Directory, as documented in |
@@ -332,6 +354,7 @@ static struct pci_raw_ops * __devinit pci_find_bios(void) | |||
332 | DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n", | 354 | DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n", |
333 | bios32_entry); | 355 | bios32_entry); |
334 | bios32_indirect.address = bios32_entry + PAGE_OFFSET; | 356 | bios32_indirect.address = bios32_entry + PAGE_OFFSET; |
357 | set_bios_x(); | ||
335 | if (check_pcibios()) | 358 | if (check_pcibios()) |
336 | return &pci_bios_access; | 359 | return &pci_bios_access; |
337 | } | 360 | } |
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile index 7bf70b812fa2..021eee91c056 100644 --- a/arch/x86/platform/Makefile +++ b/arch/x86/platform/Makefile | |||
@@ -1,5 +1,7 @@ | |||
1 | # Platform specific code goes here | 1 | # Platform specific code goes here |
2 | obj-y += ce4100/ | ||
2 | obj-y += efi/ | 3 | obj-y += efi/ |
4 | obj-y += iris/ | ||
3 | obj-y += mrst/ | 5 | obj-y += mrst/ |
4 | obj-y += olpc/ | 6 | obj-y += olpc/ |
5 | obj-y += scx200/ | 7 | obj-y += scx200/ |
diff --git a/arch/x86/platform/ce4100/Makefile b/arch/x86/platform/ce4100/Makefile new file mode 100644 index 000000000000..91fc92971d94 --- /dev/null +++ b/arch/x86/platform/ce4100/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_X86_INTEL_CE) += ce4100.o | |||
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c new file mode 100644 index 000000000000..d2c0d51a7178 --- /dev/null +++ b/arch/x86/platform/ce4100/ce4100.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * Intel CE4100 platform specific setup code | ||
3 | * | ||
4 | * (C) Copyright 2010 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; version 2 | ||
9 | * of the License. | ||
10 | */ | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/serial_reg.h> | ||
16 | #include <linux/serial_8250.h> | ||
17 | |||
18 | #include <asm/setup.h> | ||
19 | #include <asm/io.h> | ||
20 | |||
21 | static int ce4100_i8042_detect(void) | ||
22 | { | ||
23 | return 0; | ||
24 | } | ||
25 | |||
26 | static void __init sdv_find_smp_config(void) | ||
27 | { | ||
28 | } | ||
29 | |||
30 | #ifdef CONFIG_SERIAL_8250 | ||
31 | |||
32 | |||
33 | static unsigned int mem_serial_in(struct uart_port *p, int offset) | ||
34 | { | ||
35 | offset = offset << p->regshift; | ||
36 | return readl(p->membase + offset); | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * The UART Tx interrupts are not set under some conditions and therefore serial | ||
41 | * transmission hangs. This is a silicon issue and has not been root caused. The | ||
42 | * workaround for this silicon issue checks UART_LSR_THRE bit and UART_LSR_TEMT | ||
43 | * bit of LSR register in interrupt handler to see whether at least one of these | ||
44 | * two bits is set, if so then process the transmit request. If this workaround | ||
45 | * is not applied, then the serial transmission may hang. This workaround is for | ||
46 | * errata number 9 in Errata - B step. | ||
47 | */ | ||
48 | |||
49 | static unsigned int ce4100_mem_serial_in(struct uart_port *p, int offset) | ||
50 | { | ||
51 | unsigned int ret, ier, lsr; | ||
52 | |||
53 | if (offset == UART_IIR) { | ||
54 | offset = offset << p->regshift; | ||
55 | ret = readl(p->membase + offset); | ||
56 | if (ret & UART_IIR_NO_INT) { | ||
57 | /* see if the TX interrupt should have really set */ | ||
58 | ier = mem_serial_in(p, UART_IER); | ||
59 | /* see if the UART's XMIT interrupt is enabled */ | ||
60 | if (ier & UART_IER_THRI) { | ||
61 | lsr = mem_serial_in(p, UART_LSR); | ||
62 | /* now check to see if the UART should be | ||
63 | generating an interrupt (but isn't) */ | ||
64 | if (lsr & (UART_LSR_THRE | UART_LSR_TEMT)) | ||
65 | ret &= ~UART_IIR_NO_INT; | ||
66 | } | ||
67 | } | ||
68 | } else | ||
69 | ret = mem_serial_in(p, offset); | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | static void ce4100_mem_serial_out(struct uart_port *p, int offset, int value) | ||
74 | { | ||
75 | offset = offset << p->regshift; | ||
76 | writel(value, p->membase + offset); | ||
77 | } | ||
78 | |||
79 | static void ce4100_serial_fixup(int port, struct uart_port *up, | ||
80 | unsigned short *capabilites) | ||
81 | { | ||
82 | #ifdef CONFIG_EARLY_PRINTK | ||
83 | /* | ||
84 | * Over ride the legacy port configuration that comes from | ||
85 | * asm/serial.h. Using the ioport driver then switching to the | ||
86 | * PCI memmaped driver hangs the IOAPIC | ||
87 | */ | ||
88 | if (up->iotype != UPIO_MEM32) { | ||
89 | up->uartclk = 14745600; | ||
90 | up->mapbase = 0xdffe0200; | ||
91 | set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, | ||
92 | up->mapbase & PAGE_MASK); | ||
93 | up->membase = | ||
94 | (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); | ||
95 | up->membase += up->mapbase & ~PAGE_MASK; | ||
96 | up->iotype = UPIO_MEM32; | ||
97 | up->regshift = 2; | ||
98 | } | ||
99 | #endif | ||
100 | up->iobase = 0; | ||
101 | up->serial_in = ce4100_mem_serial_in; | ||
102 | up->serial_out = ce4100_mem_serial_out; | ||
103 | |||
104 | *capabilites |= (1 << 12); | ||
105 | } | ||
106 | |||
107 | static __init void sdv_serial_fixup(void) | ||
108 | { | ||
109 | serial8250_set_isa_configurator(ce4100_serial_fixup); | ||
110 | } | ||
111 | |||
112 | #else | ||
113 | static inline void sdv_serial_fixup(void); | ||
114 | #endif | ||
115 | |||
116 | static void __init sdv_arch_setup(void) | ||
117 | { | ||
118 | sdv_serial_fixup(); | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * CE4100 specific x86_init function overrides and early setup | ||
123 | * calls. | ||
124 | */ | ||
125 | void __init x86_ce4100_early_setup(void) | ||
126 | { | ||
127 | x86_init.oem.arch_setup = sdv_arch_setup; | ||
128 | x86_platform.i8042_detect = ce4100_i8042_detect; | ||
129 | x86_init.resources.probe_roms = x86_init_noop; | ||
130 | x86_init.mpparse.get_smp_config = x86_init_uint_noop; | ||
131 | x86_init.mpparse.find_smp_config = sdv_find_smp_config; | ||
132 | } | ||
diff --git a/arch/x86/platform/iris/Makefile b/arch/x86/platform/iris/Makefile new file mode 100644 index 000000000000..db921983a102 --- /dev/null +++ b/arch/x86/platform/iris/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_X86_32_IRIS) += iris.o | |||
diff --git a/arch/x86/platform/iris/iris.c b/arch/x86/platform/iris/iris.c new file mode 100644 index 000000000000..1ba7f5ed8c9b --- /dev/null +++ b/arch/x86/platform/iris/iris.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * Eurobraille/Iris power off support. | ||
3 | * | ||
4 | * Eurobraille's Iris machine is a PC with no APM or ACPI support. | ||
5 | * It is shutdown by a special I/O sequence which this module provides. | ||
6 | * | ||
7 | * Copyright (C) Shérab <Sebastien.Hinderer@ens-lyon.org> | ||
8 | * | ||
9 | * This program is free software ; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation ; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY ; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with the program ; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/pm.h> | ||
31 | #include <asm/io.h> | ||
32 | |||
33 | #define IRIS_GIO_BASE 0x340 | ||
34 | #define IRIS_GIO_INPUT IRIS_GIO_BASE | ||
35 | #define IRIS_GIO_OUTPUT (IRIS_GIO_BASE + 1) | ||
36 | #define IRIS_GIO_PULSE 0x80 /* First byte to send */ | ||
37 | #define IRIS_GIO_REST 0x00 /* Second byte to send */ | ||
38 | #define IRIS_GIO_NODEV 0xff /* Likely not an Iris */ | ||
39 | |||
40 | MODULE_LICENSE("GPL"); | ||
41 | MODULE_AUTHOR("Sébastien Hinderer <Sebastien.Hinderer@ens-lyon.org>"); | ||
42 | MODULE_DESCRIPTION("A power_off handler for Iris devices from EuroBraille"); | ||
43 | MODULE_SUPPORTED_DEVICE("Eurobraille/Iris"); | ||
44 | |||
45 | static int force; | ||
46 | |||
47 | module_param(force, bool, 0); | ||
48 | MODULE_PARM_DESC(force, "Set to one to force poweroff handler installation."); | ||
49 | |||
50 | static void (*old_pm_power_off)(void); | ||
51 | |||
52 | static void iris_power_off(void) | ||
53 | { | ||
54 | outb(IRIS_GIO_PULSE, IRIS_GIO_OUTPUT); | ||
55 | msleep(850); | ||
56 | outb(IRIS_GIO_REST, IRIS_GIO_OUTPUT); | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * Before installing the power_off handler, try to make sure the OS is | ||
61 | * running on an Iris. Since Iris does not support DMI, this is done | ||
62 | * by reading its input port and seeing whether the read value is | ||
63 | * meaningful. | ||
64 | */ | ||
65 | static int iris_init(void) | ||
66 | { | ||
67 | unsigned char status; | ||
68 | if (force != 1) { | ||
69 | printk(KERN_ERR "The force parameter has not been set to 1 so the Iris poweroff handler will not be installed.\n"); | ||
70 | return -ENODEV; | ||
71 | } | ||
72 | status = inb(IRIS_GIO_INPUT); | ||
73 | if (status == IRIS_GIO_NODEV) { | ||
74 | printk(KERN_ERR "This machine does not seem to be an Iris. Power_off handler not installed.\n"); | ||
75 | return -ENODEV; | ||
76 | } | ||
77 | old_pm_power_off = pm_power_off; | ||
78 | pm_power_off = &iris_power_off; | ||
79 | printk(KERN_INFO "Iris power_off handler installed.\n"); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static void iris_exit(void) | ||
85 | { | ||
86 | pm_power_off = old_pm_power_off; | ||
87 | printk(KERN_INFO "Iris power_off handler uninstalled.\n"); | ||
88 | } | ||
89 | |||
90 | module_init(iris_init); | ||
91 | module_exit(iris_exit); | ||
diff --git a/arch/x86/platform/mrst/Makefile b/arch/x86/platform/mrst/Makefile index efbbc552fa95..f61ccdd49341 100644 --- a/arch/x86/platform/mrst/Makefile +++ b/arch/x86/platform/mrst/Makefile | |||
@@ -1 +1,3 @@ | |||
1 | obj-$(CONFIG_X86_MRST) += mrst.o | 1 | obj-$(CONFIG_X86_MRST) += mrst.o |
2 | obj-$(CONFIG_X86_MRST) += vrtc.o | ||
3 | obj-$(CONFIG_EARLY_PRINTK_MRST) += early_printk_mrst.o | ||
diff --git a/arch/x86/kernel/early_printk_mrst.c b/arch/x86/platform/mrst/early_printk_mrst.c index 65df603622b2..65df603622b2 100644 --- a/arch/x86/kernel/early_printk_mrst.c +++ b/arch/x86/platform/mrst/early_printk_mrst.c | |||
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index 79ae68154e87..fee0b4914e07 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c | |||
@@ -9,9 +9,19 @@ | |||
9 | * as published by the Free Software Foundation; version 2 | 9 | * as published by the Free Software Foundation; version 2 |
10 | * of the License. | 10 | * of the License. |
11 | */ | 11 | */ |
12 | |||
13 | #define pr_fmt(fmt) "mrst: " fmt | ||
14 | |||
12 | #include <linux/init.h> | 15 | #include <linux/init.h> |
13 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
14 | #include <linux/sfi.h> | 17 | #include <linux/sfi.h> |
18 | #include <linux/intel_pmic_gpio.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/i2c/pca953x.h> | ||
22 | #include <linux/gpio_keys.h> | ||
23 | #include <linux/input.h> | ||
24 | #include <linux/platform_device.h> | ||
15 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
16 | #include <linux/module.h> | 26 | #include <linux/module.h> |
17 | 27 | ||
@@ -23,7 +33,9 @@ | |||
23 | #include <asm/mrst.h> | 33 | #include <asm/mrst.h> |
24 | #include <asm/io.h> | 34 | #include <asm/io.h> |
25 | #include <asm/i8259.h> | 35 | #include <asm/i8259.h> |
36 | #include <asm/intel_scu_ipc.h> | ||
26 | #include <asm/apb_timer.h> | 37 | #include <asm/apb_timer.h> |
38 | #include <asm/reboot.h> | ||
27 | 39 | ||
28 | /* | 40 | /* |
29 | * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, | 41 | * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, |
@@ -102,10 +114,10 @@ static int __init sfi_parse_mtmr(struct sfi_table_header *table) | |||
102 | memcpy(sfi_mtimer_array, pentry, totallen); | 114 | memcpy(sfi_mtimer_array, pentry, totallen); |
103 | } | 115 | } |
104 | 116 | ||
105 | printk(KERN_INFO "SFI: MTIMER info (num = %d):\n", sfi_mtimer_num); | 117 | pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num); |
106 | pentry = sfi_mtimer_array; | 118 | pentry = sfi_mtimer_array; |
107 | for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { | 119 | for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { |
108 | printk(KERN_INFO "timer[%d]: paddr = 0x%08x, freq = %dHz," | 120 | pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz," |
109 | " irq = %d\n", totallen, (u32)pentry->phys_addr, | 121 | " irq = %d\n", totallen, (u32)pentry->phys_addr, |
110 | pentry->freq_hz, pentry->irq); | 122 | pentry->freq_hz, pentry->irq); |
111 | if (!pentry->irq) | 123 | if (!pentry->irq) |
@@ -176,14 +188,14 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table) | |||
176 | memcpy(sfi_mrtc_array, pentry, totallen); | 188 | memcpy(sfi_mrtc_array, pentry, totallen); |
177 | } | 189 | } |
178 | 190 | ||
179 | printk(KERN_INFO "SFI: RTC info (num = %d):\n", sfi_mrtc_num); | 191 | pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num); |
180 | pentry = sfi_mrtc_array; | 192 | pentry = sfi_mrtc_array; |
181 | for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { | 193 | for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { |
182 | printk(KERN_INFO "RTC[%d]: paddr = 0x%08x, irq = %d\n", | 194 | pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n", |
183 | totallen, (u32)pentry->phys_addr, pentry->irq); | 195 | totallen, (u32)pentry->phys_addr, pentry->irq); |
184 | mp_irq.type = MP_IOAPIC; | 196 | mp_irq.type = MP_IOAPIC; |
185 | mp_irq.irqtype = mp_INT; | 197 | mp_irq.irqtype = mp_INT; |
186 | mp_irq.irqflag = 0; | 198 | mp_irq.irqflag = 0xf; /* level trigger and active low */ |
187 | mp_irq.srcbus = 0; | 199 | mp_irq.srcbus = 0; |
188 | mp_irq.srcbusirq = pentry->irq; /* IRQ */ | 200 | mp_irq.srcbusirq = pentry->irq; /* IRQ */ |
189 | mp_irq.dstapic = MP_APIC_ALL; | 201 | mp_irq.dstapic = MP_APIC_ALL; |
@@ -209,6 +221,7 @@ static unsigned long __init mrst_calibrate_tsc(void) | |||
209 | 221 | ||
210 | void __init mrst_time_init(void) | 222 | void __init mrst_time_init(void) |
211 | { | 223 | { |
224 | sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr); | ||
212 | switch (mrst_timer_options) { | 225 | switch (mrst_timer_options) { |
213 | case MRST_TIMER_APBT_ONLY: | 226 | case MRST_TIMER_APBT_ONLY: |
214 | break; | 227 | break; |
@@ -224,16 +237,10 @@ void __init mrst_time_init(void) | |||
224 | return; | 237 | return; |
225 | } | 238 | } |
226 | /* we need at least one APB timer */ | 239 | /* we need at least one APB timer */ |
227 | sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr); | ||
228 | pre_init_apic_IRQ0(); | 240 | pre_init_apic_IRQ0(); |
229 | apbt_time_init(); | 241 | apbt_time_init(); |
230 | } | 242 | } |
231 | 243 | ||
232 | void __init mrst_rtc_init(void) | ||
233 | { | ||
234 | sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc); | ||
235 | } | ||
236 | |||
237 | void __cpuinit mrst_arch_setup(void) | 244 | void __cpuinit mrst_arch_setup(void) |
238 | { | 245 | { |
239 | if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) | 246 | if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) |
@@ -256,6 +263,17 @@ static int mrst_i8042_detect(void) | |||
256 | return 0; | 263 | return 0; |
257 | } | 264 | } |
258 | 265 | ||
266 | /* Reboot and power off are handled by the SCU on a MID device */ | ||
267 | static void mrst_power_off(void) | ||
268 | { | ||
269 | intel_scu_ipc_simple_command(0xf1, 1); | ||
270 | } | ||
271 | |||
272 | static void mrst_reboot(void) | ||
273 | { | ||
274 | intel_scu_ipc_simple_command(0xf1, 0); | ||
275 | } | ||
276 | |||
259 | /* | 277 | /* |
260 | * Moorestown specific x86_init function overrides and early setup | 278 | * Moorestown specific x86_init function overrides and early setup |
261 | * calls. | 279 | * calls. |
@@ -281,6 +299,10 @@ void __init x86_mrst_early_setup(void) | |||
281 | 299 | ||
282 | legacy_pic = &null_legacy_pic; | 300 | legacy_pic = &null_legacy_pic; |
283 | 301 | ||
302 | /* Moorestown specific power_off/restart method */ | ||
303 | pm_power_off = mrst_power_off; | ||
304 | machine_ops.emergency_restart = mrst_reboot; | ||
305 | |||
284 | /* Avoid searching for BIOS MP tables */ | 306 | /* Avoid searching for BIOS MP tables */ |
285 | x86_init.mpparse.find_smp_config = x86_init_noop; | 307 | x86_init.mpparse.find_smp_config = x86_init_noop; |
286 | x86_init.mpparse.get_smp_config = x86_init_uint_noop; | 308 | x86_init.mpparse.get_smp_config = x86_init_uint_noop; |
@@ -309,3 +331,505 @@ static inline int __init setup_x86_mrst_timer(char *arg) | |||
309 | return 0; | 331 | return 0; |
310 | } | 332 | } |
311 | __setup("x86_mrst_timer=", setup_x86_mrst_timer); | 333 | __setup("x86_mrst_timer=", setup_x86_mrst_timer); |
334 | |||
335 | /* | ||
336 | * Parsing GPIO table first, since the DEVS table will need this table | ||
337 | * to map the pin name to the actual pin. | ||
338 | */ | ||
339 | static struct sfi_gpio_table_entry *gpio_table; | ||
340 | static int gpio_num_entry; | ||
341 | |||
342 | static int __init sfi_parse_gpio(struct sfi_table_header *table) | ||
343 | { | ||
344 | struct sfi_table_simple *sb; | ||
345 | struct sfi_gpio_table_entry *pentry; | ||
346 | int num, i; | ||
347 | |||
348 | if (gpio_table) | ||
349 | return 0; | ||
350 | sb = (struct sfi_table_simple *)table; | ||
351 | num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry); | ||
352 | pentry = (struct sfi_gpio_table_entry *)sb->pentry; | ||
353 | |||
354 | gpio_table = (struct sfi_gpio_table_entry *) | ||
355 | kmalloc(num * sizeof(*pentry), GFP_KERNEL); | ||
356 | if (!gpio_table) | ||
357 | return -1; | ||
358 | memcpy(gpio_table, pentry, num * sizeof(*pentry)); | ||
359 | gpio_num_entry = num; | ||
360 | |||
361 | pr_debug("GPIO pin info:\n"); | ||
362 | for (i = 0; i < num; i++, pentry++) | ||
363 | pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s," | ||
364 | " pin = %d\n", i, | ||
365 | pentry->controller_name, | ||
366 | pentry->pin_name, | ||
367 | pentry->pin_no); | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int get_gpio_by_name(const char *name) | ||
372 | { | ||
373 | struct sfi_gpio_table_entry *pentry = gpio_table; | ||
374 | int i; | ||
375 | |||
376 | if (!pentry) | ||
377 | return -1; | ||
378 | for (i = 0; i < gpio_num_entry; i++, pentry++) { | ||
379 | if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN)) | ||
380 | return pentry->pin_no; | ||
381 | } | ||
382 | return -1; | ||
383 | } | ||
384 | |||
385 | /* | ||
386 | * Here defines the array of devices platform data that IAFW would export | ||
387 | * through SFI "DEVS" table, we use name and type to match the device and | ||
388 | * its platform data. | ||
389 | */ | ||
390 | struct devs_id { | ||
391 | char name[SFI_NAME_LEN + 1]; | ||
392 | u8 type; | ||
393 | u8 delay; | ||
394 | void *(*get_platform_data)(void *info); | ||
395 | }; | ||
396 | |||
397 | /* the offset for the mapping of global gpio pin to irq */ | ||
398 | #define MRST_IRQ_OFFSET 0x100 | ||
399 | |||
400 | static void __init *pmic_gpio_platform_data(void *info) | ||
401 | { | ||
402 | static struct intel_pmic_gpio_platform_data pmic_gpio_pdata; | ||
403 | int gpio_base = get_gpio_by_name("pmic_gpio_base"); | ||
404 | |||
405 | if (gpio_base == -1) | ||
406 | gpio_base = 64; | ||
407 | pmic_gpio_pdata.gpio_base = gpio_base; | ||
408 | pmic_gpio_pdata.irq_base = gpio_base + MRST_IRQ_OFFSET; | ||
409 | pmic_gpio_pdata.gpiointr = 0xffffeff8; | ||
410 | |||
411 | return &pmic_gpio_pdata; | ||
412 | } | ||
413 | |||
414 | static void __init *max3111_platform_data(void *info) | ||
415 | { | ||
416 | struct spi_board_info *spi_info = info; | ||
417 | int intr = get_gpio_by_name("max3111_int"); | ||
418 | |||
419 | if (intr == -1) | ||
420 | return NULL; | ||
421 | spi_info->irq = intr + MRST_IRQ_OFFSET; | ||
422 | return NULL; | ||
423 | } | ||
424 | |||
425 | /* we have multiple max7315 on the board ... */ | ||
426 | #define MAX7315_NUM 2 | ||
427 | static void __init *max7315_platform_data(void *info) | ||
428 | { | ||
429 | static struct pca953x_platform_data max7315_pdata[MAX7315_NUM]; | ||
430 | static int nr; | ||
431 | struct pca953x_platform_data *max7315 = &max7315_pdata[nr]; | ||
432 | struct i2c_board_info *i2c_info = info; | ||
433 | int gpio_base, intr; | ||
434 | char base_pin_name[SFI_NAME_LEN + 1]; | ||
435 | char intr_pin_name[SFI_NAME_LEN + 1]; | ||
436 | |||
437 | if (nr == MAX7315_NUM) { | ||
438 | pr_err("too many max7315s, we only support %d\n", | ||
439 | MAX7315_NUM); | ||
440 | return NULL; | ||
441 | } | ||
442 | /* we have several max7315 on the board, we only need load several | ||
443 | * instances of the same pca953x driver to cover them | ||
444 | */ | ||
445 | strcpy(i2c_info->type, "max7315"); | ||
446 | if (nr++) { | ||
447 | sprintf(base_pin_name, "max7315_%d_base", nr); | ||
448 | sprintf(intr_pin_name, "max7315_%d_int", nr); | ||
449 | } else { | ||
450 | strcpy(base_pin_name, "max7315_base"); | ||
451 | strcpy(intr_pin_name, "max7315_int"); | ||
452 | } | ||
453 | |||
454 | gpio_base = get_gpio_by_name(base_pin_name); | ||
455 | intr = get_gpio_by_name(intr_pin_name); | ||
456 | |||
457 | if (gpio_base == -1) | ||
458 | return NULL; | ||
459 | max7315->gpio_base = gpio_base; | ||
460 | if (intr != -1) { | ||
461 | i2c_info->irq = intr + MRST_IRQ_OFFSET; | ||
462 | max7315->irq_base = gpio_base + MRST_IRQ_OFFSET; | ||
463 | } else { | ||
464 | i2c_info->irq = -1; | ||
465 | max7315->irq_base = -1; | ||
466 | } | ||
467 | return max7315; | ||
468 | } | ||
469 | |||
470 | static void __init *emc1403_platform_data(void *info) | ||
471 | { | ||
472 | static short intr2nd_pdata; | ||
473 | struct i2c_board_info *i2c_info = info; | ||
474 | int intr = get_gpio_by_name("thermal_int"); | ||
475 | int intr2nd = get_gpio_by_name("thermal_alert"); | ||
476 | |||
477 | if (intr == -1 || intr2nd == -1) | ||
478 | return NULL; | ||
479 | |||
480 | i2c_info->irq = intr + MRST_IRQ_OFFSET; | ||
481 | intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET; | ||
482 | |||
483 | return &intr2nd_pdata; | ||
484 | } | ||
485 | |||
486 | static void __init *lis331dl_platform_data(void *info) | ||
487 | { | ||
488 | static short intr2nd_pdata; | ||
489 | struct i2c_board_info *i2c_info = info; | ||
490 | int intr = get_gpio_by_name("accel_int"); | ||
491 | int intr2nd = get_gpio_by_name("accel_2"); | ||
492 | |||
493 | if (intr == -1 || intr2nd == -1) | ||
494 | return NULL; | ||
495 | |||
496 | i2c_info->irq = intr + MRST_IRQ_OFFSET; | ||
497 | intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET; | ||
498 | |||
499 | return &intr2nd_pdata; | ||
500 | } | ||
501 | |||
502 | static void __init *no_platform_data(void *info) | ||
503 | { | ||
504 | return NULL; | ||
505 | } | ||
506 | |||
507 | static const struct devs_id __initconst device_ids[] = { | ||
508 | {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data}, | ||
509 | {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data}, | ||
510 | {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, | ||
511 | {"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data}, | ||
512 | {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data}, | ||
513 | {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data}, | ||
514 | {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, | ||
515 | {"msic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data}, | ||
516 | {}, | ||
517 | }; | ||
518 | |||
519 | #define MAX_IPCDEVS 24 | ||
520 | static struct platform_device *ipc_devs[MAX_IPCDEVS]; | ||
521 | static int ipc_next_dev; | ||
522 | |||
523 | #define MAX_SCU_SPI 24 | ||
524 | static struct spi_board_info *spi_devs[MAX_SCU_SPI]; | ||
525 | static int spi_next_dev; | ||
526 | |||
527 | #define MAX_SCU_I2C 24 | ||
528 | static struct i2c_board_info *i2c_devs[MAX_SCU_I2C]; | ||
529 | static int i2c_bus[MAX_SCU_I2C]; | ||
530 | static int i2c_next_dev; | ||
531 | |||
532 | static void __init intel_scu_device_register(struct platform_device *pdev) | ||
533 | { | ||
534 | if(ipc_next_dev == MAX_IPCDEVS) | ||
535 | pr_err("too many SCU IPC devices"); | ||
536 | else | ||
537 | ipc_devs[ipc_next_dev++] = pdev; | ||
538 | } | ||
539 | |||
540 | static void __init intel_scu_spi_device_register(struct spi_board_info *sdev) | ||
541 | { | ||
542 | struct spi_board_info *new_dev; | ||
543 | |||
544 | if (spi_next_dev == MAX_SCU_SPI) { | ||
545 | pr_err("too many SCU SPI devices"); | ||
546 | return; | ||
547 | } | ||
548 | |||
549 | new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL); | ||
550 | if (!new_dev) { | ||
551 | pr_err("failed to alloc mem for delayed spi dev %s\n", | ||
552 | sdev->modalias); | ||
553 | return; | ||
554 | } | ||
555 | memcpy(new_dev, sdev, sizeof(*sdev)); | ||
556 | |||
557 | spi_devs[spi_next_dev++] = new_dev; | ||
558 | } | ||
559 | |||
560 | static void __init intel_scu_i2c_device_register(int bus, | ||
561 | struct i2c_board_info *idev) | ||
562 | { | ||
563 | struct i2c_board_info *new_dev; | ||
564 | |||
565 | if (i2c_next_dev == MAX_SCU_I2C) { | ||
566 | pr_err("too many SCU I2C devices"); | ||
567 | return; | ||
568 | } | ||
569 | |||
570 | new_dev = kzalloc(sizeof(*idev), GFP_KERNEL); | ||
571 | if (!new_dev) { | ||
572 | pr_err("failed to alloc mem for delayed i2c dev %s\n", | ||
573 | idev->type); | ||
574 | return; | ||
575 | } | ||
576 | memcpy(new_dev, idev, sizeof(*idev)); | ||
577 | |||
578 | i2c_bus[i2c_next_dev] = bus; | ||
579 | i2c_devs[i2c_next_dev++] = new_dev; | ||
580 | } | ||
581 | |||
582 | /* Called by IPC driver */ | ||
583 | void intel_scu_devices_create(void) | ||
584 | { | ||
585 | int i; | ||
586 | |||
587 | for (i = 0; i < ipc_next_dev; i++) | ||
588 | platform_device_add(ipc_devs[i]); | ||
589 | |||
590 | for (i = 0; i < spi_next_dev; i++) | ||
591 | spi_register_board_info(spi_devs[i], 1); | ||
592 | |||
593 | for (i = 0; i < i2c_next_dev; i++) { | ||
594 | struct i2c_adapter *adapter; | ||
595 | struct i2c_client *client; | ||
596 | |||
597 | adapter = i2c_get_adapter(i2c_bus[i]); | ||
598 | if (adapter) { | ||
599 | client = i2c_new_device(adapter, i2c_devs[i]); | ||
600 | if (!client) | ||
601 | pr_err("can't create i2c device %s\n", | ||
602 | i2c_devs[i]->type); | ||
603 | } else | ||
604 | i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1); | ||
605 | } | ||
606 | } | ||
607 | EXPORT_SYMBOL_GPL(intel_scu_devices_create); | ||
608 | |||
609 | /* Called by IPC driver */ | ||
610 | void intel_scu_devices_destroy(void) | ||
611 | { | ||
612 | int i; | ||
613 | |||
614 | for (i = 0; i < ipc_next_dev; i++) | ||
615 | platform_device_del(ipc_devs[i]); | ||
616 | } | ||
617 | EXPORT_SYMBOL_GPL(intel_scu_devices_destroy); | ||
618 | |||
619 | static void __init install_irq_resource(struct platform_device *pdev, int irq) | ||
620 | { | ||
621 | /* Single threaded */ | ||
622 | static struct resource __initdata res = { | ||
623 | .name = "IRQ", | ||
624 | .flags = IORESOURCE_IRQ, | ||
625 | }; | ||
626 | res.start = irq; | ||
627 | platform_device_add_resources(pdev, &res, 1); | ||
628 | } | ||
629 | |||
630 | static void __init sfi_handle_ipc_dev(struct platform_device *pdev) | ||
631 | { | ||
632 | const struct devs_id *dev = device_ids; | ||
633 | void *pdata = NULL; | ||
634 | |||
635 | while (dev->name[0]) { | ||
636 | if (dev->type == SFI_DEV_TYPE_IPC && | ||
637 | !strncmp(dev->name, pdev->name, SFI_NAME_LEN)) { | ||
638 | pdata = dev->get_platform_data(pdev); | ||
639 | break; | ||
640 | } | ||
641 | dev++; | ||
642 | } | ||
643 | pdev->dev.platform_data = pdata; | ||
644 | intel_scu_device_register(pdev); | ||
645 | } | ||
646 | |||
647 | static void __init sfi_handle_spi_dev(struct spi_board_info *spi_info) | ||
648 | { | ||
649 | const struct devs_id *dev = device_ids; | ||
650 | void *pdata = NULL; | ||
651 | |||
652 | while (dev->name[0]) { | ||
653 | if (dev->type == SFI_DEV_TYPE_SPI && | ||
654 | !strncmp(dev->name, spi_info->modalias, SFI_NAME_LEN)) { | ||
655 | pdata = dev->get_platform_data(spi_info); | ||
656 | break; | ||
657 | } | ||
658 | dev++; | ||
659 | } | ||
660 | spi_info->platform_data = pdata; | ||
661 | if (dev->delay) | ||
662 | intel_scu_spi_device_register(spi_info); | ||
663 | else | ||
664 | spi_register_board_info(spi_info, 1); | ||
665 | } | ||
666 | |||
667 | static void __init sfi_handle_i2c_dev(int bus, struct i2c_board_info *i2c_info) | ||
668 | { | ||
669 | const struct devs_id *dev = device_ids; | ||
670 | void *pdata = NULL; | ||
671 | |||
672 | while (dev->name[0]) { | ||
673 | if (dev->type == SFI_DEV_TYPE_I2C && | ||
674 | !strncmp(dev->name, i2c_info->type, SFI_NAME_LEN)) { | ||
675 | pdata = dev->get_platform_data(i2c_info); | ||
676 | break; | ||
677 | } | ||
678 | dev++; | ||
679 | } | ||
680 | i2c_info->platform_data = pdata; | ||
681 | |||
682 | if (dev->delay) | ||
683 | intel_scu_i2c_device_register(bus, i2c_info); | ||
684 | else | ||
685 | i2c_register_board_info(bus, i2c_info, 1); | ||
686 | } | ||
687 | |||
688 | |||
689 | static int __init sfi_parse_devs(struct sfi_table_header *table) | ||
690 | { | ||
691 | struct sfi_table_simple *sb; | ||
692 | struct sfi_device_table_entry *pentry; | ||
693 | struct spi_board_info spi_info; | ||
694 | struct i2c_board_info i2c_info; | ||
695 | struct platform_device *pdev; | ||
696 | int num, i, bus; | ||
697 | int ioapic; | ||
698 | struct io_apic_irq_attr irq_attr; | ||
699 | |||
700 | sb = (struct sfi_table_simple *)table; | ||
701 | num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry); | ||
702 | pentry = (struct sfi_device_table_entry *)sb->pentry; | ||
703 | |||
704 | for (i = 0; i < num; i++, pentry++) { | ||
705 | if (pentry->irq != (u8)0xff) { /* native RTE case */ | ||
706 | /* these SPI2 devices are not exposed to system as PCI | ||
707 | * devices, but they have separate RTE entry in IOAPIC | ||
708 | * so we have to enable them one by one here | ||
709 | */ | ||
710 | ioapic = mp_find_ioapic(pentry->irq); | ||
711 | irq_attr.ioapic = ioapic; | ||
712 | irq_attr.ioapic_pin = pentry->irq; | ||
713 | irq_attr.trigger = 1; | ||
714 | irq_attr.polarity = 1; | ||
715 | io_apic_set_pci_routing(NULL, pentry->irq, &irq_attr); | ||
716 | } | ||
717 | switch (pentry->type) { | ||
718 | case SFI_DEV_TYPE_IPC: | ||
719 | /* ID as IRQ is a hack that will go away */ | ||
720 | pdev = platform_device_alloc(pentry->name, pentry->irq); | ||
721 | if (pdev == NULL) { | ||
722 | pr_err("out of memory for SFI platform device '%s'.\n", | ||
723 | pentry->name); | ||
724 | continue; | ||
725 | } | ||
726 | install_irq_resource(pdev, pentry->irq); | ||
727 | pr_debug("info[%2d]: IPC bus, name = %16.16s, " | ||
728 | "irq = 0x%2x\n", i, pentry->name, pentry->irq); | ||
729 | sfi_handle_ipc_dev(pdev); | ||
730 | break; | ||
731 | case SFI_DEV_TYPE_SPI: | ||
732 | memset(&spi_info, 0, sizeof(spi_info)); | ||
733 | strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN); | ||
734 | spi_info.irq = pentry->irq; | ||
735 | spi_info.bus_num = pentry->host_num; | ||
736 | spi_info.chip_select = pentry->addr; | ||
737 | spi_info.max_speed_hz = pentry->max_freq; | ||
738 | pr_debug("info[%2d]: SPI bus = %d, name = %16.16s, " | ||
739 | "irq = 0x%2x, max_freq = %d, cs = %d\n", i, | ||
740 | spi_info.bus_num, | ||
741 | spi_info.modalias, | ||
742 | spi_info.irq, | ||
743 | spi_info.max_speed_hz, | ||
744 | spi_info.chip_select); | ||
745 | sfi_handle_spi_dev(&spi_info); | ||
746 | break; | ||
747 | case SFI_DEV_TYPE_I2C: | ||
748 | memset(&i2c_info, 0, sizeof(i2c_info)); | ||
749 | bus = pentry->host_num; | ||
750 | strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN); | ||
751 | i2c_info.irq = pentry->irq; | ||
752 | i2c_info.addr = pentry->addr; | ||
753 | pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, " | ||
754 | "irq = 0x%2x, addr = 0x%x\n", i, bus, | ||
755 | i2c_info.type, | ||
756 | i2c_info.irq, | ||
757 | i2c_info.addr); | ||
758 | sfi_handle_i2c_dev(bus, &i2c_info); | ||
759 | break; | ||
760 | case SFI_DEV_TYPE_UART: | ||
761 | case SFI_DEV_TYPE_HSI: | ||
762 | default: | ||
763 | ; | ||
764 | } | ||
765 | } | ||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | static int __init mrst_platform_init(void) | ||
770 | { | ||
771 | sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio); | ||
772 | sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs); | ||
773 | return 0; | ||
774 | } | ||
775 | arch_initcall(mrst_platform_init); | ||
776 | |||
777 | /* | ||
778 | * we will search these buttons in SFI GPIO table (by name) | ||
779 | * and register them dynamically. Please add all possible | ||
780 | * buttons here, we will shrink them if no GPIO found. | ||
781 | */ | ||
782 | static struct gpio_keys_button gpio_button[] = { | ||
783 | {KEY_POWER, -1, 1, "power_btn", EV_KEY, 0, 3000}, | ||
784 | {KEY_PROG1, -1, 1, "prog_btn1", EV_KEY, 0, 20}, | ||
785 | {KEY_PROG2, -1, 1, "prog_btn2", EV_KEY, 0, 20}, | ||
786 | {SW_LID, -1, 1, "lid_switch", EV_SW, 0, 20}, | ||
787 | {KEY_VOLUMEUP, -1, 1, "vol_up", EV_KEY, 0, 20}, | ||
788 | {KEY_VOLUMEDOWN, -1, 1, "vol_down", EV_KEY, 0, 20}, | ||
789 | {KEY_CAMERA, -1, 1, "camera_full", EV_KEY, 0, 20}, | ||
790 | {KEY_CAMERA_FOCUS, -1, 1, "camera_half", EV_KEY, 0, 20}, | ||
791 | {SW_KEYPAD_SLIDE, -1, 1, "MagSw1", EV_SW, 0, 20}, | ||
792 | {SW_KEYPAD_SLIDE, -1, 1, "MagSw2", EV_SW, 0, 20}, | ||
793 | }; | ||
794 | |||
795 | static struct gpio_keys_platform_data mrst_gpio_keys = { | ||
796 | .buttons = gpio_button, | ||
797 | .rep = 1, | ||
798 | .nbuttons = -1, /* will fill it after search */ | ||
799 | }; | ||
800 | |||
801 | static struct platform_device pb_device = { | ||
802 | .name = "gpio-keys", | ||
803 | .id = -1, | ||
804 | .dev = { | ||
805 | .platform_data = &mrst_gpio_keys, | ||
806 | }, | ||
807 | }; | ||
808 | |||
809 | /* | ||
810 | * Shrink the non-existent buttons, register the gpio button | ||
811 | * device if there is some | ||
812 | */ | ||
813 | static int __init pb_keys_init(void) | ||
814 | { | ||
815 | struct gpio_keys_button *gb = gpio_button; | ||
816 | int i, num, good = 0; | ||
817 | |||
818 | num = sizeof(gpio_button) / sizeof(struct gpio_keys_button); | ||
819 | for (i = 0; i < num; i++) { | ||
820 | gb[i].gpio = get_gpio_by_name(gb[i].desc); | ||
821 | if (gb[i].gpio == -1) | ||
822 | continue; | ||
823 | |||
824 | if (i != good) | ||
825 | gb[good] = gb[i]; | ||
826 | good++; | ||
827 | } | ||
828 | |||
829 | if (good) { | ||
830 | mrst_gpio_keys.nbuttons = good; | ||
831 | return platform_device_register(&pb_device); | ||
832 | } | ||
833 | return 0; | ||
834 | } | ||
835 | late_initcall(pb_keys_init); | ||
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c new file mode 100644 index 000000000000..32cd7edd71a0 --- /dev/null +++ b/arch/x86/platform/mrst/vrtc.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * vrtc.c: Driver for virtual RTC device on Intel MID platform | ||
3 | * | ||
4 | * (C) Copyright 2009 Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; version 2 | ||
9 | * of the License. | ||
10 | * | ||
11 | * Note: | ||
12 | * VRTC is emulated by system controller firmware, the real HW | ||
13 | * RTC is located in the PMIC device. SCU FW shadows PMIC RTC | ||
14 | * in a memory mapped IO space that is visible to the host IA | ||
15 | * processor. | ||
16 | * | ||
17 | * This driver is based on RTC CMOS driver. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/sfi.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | |||
25 | #include <asm/mrst.h> | ||
26 | #include <asm/mrst-vrtc.h> | ||
27 | #include <asm/time.h> | ||
28 | #include <asm/fixmap.h> | ||
29 | |||
30 | static unsigned char __iomem *vrtc_virt_base; | ||
31 | |||
32 | unsigned char vrtc_cmos_read(unsigned char reg) | ||
33 | { | ||
34 | unsigned char retval; | ||
35 | |||
36 | /* vRTC's registers range from 0x0 to 0xD */ | ||
37 | if (reg > 0xd || !vrtc_virt_base) | ||
38 | return 0xff; | ||
39 | |||
40 | lock_cmos_prefix(reg); | ||
41 | retval = __raw_readb(vrtc_virt_base + (reg << 2)); | ||
42 | lock_cmos_suffix(reg); | ||
43 | return retval; | ||
44 | } | ||
45 | EXPORT_SYMBOL_GPL(vrtc_cmos_read); | ||
46 | |||
47 | void vrtc_cmos_write(unsigned char val, unsigned char reg) | ||
48 | { | ||
49 | if (reg > 0xd || !vrtc_virt_base) | ||
50 | return; | ||
51 | |||
52 | lock_cmos_prefix(reg); | ||
53 | __raw_writeb(val, vrtc_virt_base + (reg << 2)); | ||
54 | lock_cmos_suffix(reg); | ||
55 | } | ||
56 | EXPORT_SYMBOL_GPL(vrtc_cmos_write); | ||
57 | |||
58 | unsigned long vrtc_get_time(void) | ||
59 | { | ||
60 | u8 sec, min, hour, mday, mon; | ||
61 | u32 year; | ||
62 | |||
63 | while ((vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) | ||
64 | cpu_relax(); | ||
65 | |||
66 | sec = vrtc_cmos_read(RTC_SECONDS); | ||
67 | min = vrtc_cmos_read(RTC_MINUTES); | ||
68 | hour = vrtc_cmos_read(RTC_HOURS); | ||
69 | mday = vrtc_cmos_read(RTC_DAY_OF_MONTH); | ||
70 | mon = vrtc_cmos_read(RTC_MONTH); | ||
71 | year = vrtc_cmos_read(RTC_YEAR); | ||
72 | |||
73 | /* vRTC YEAR reg contains the offset to 1960 */ | ||
74 | year += 1960; | ||
75 | |||
76 | printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d " | ||
77 | "mon: %d year: %d\n", sec, min, hour, mday, mon, year); | ||
78 | |||
79 | return mktime(year, mon, mday, hour, min, sec); | ||
80 | } | ||
81 | |||
82 | /* Only care about the minutes and seconds */ | ||
83 | int vrtc_set_mmss(unsigned long nowtime) | ||
84 | { | ||
85 | int real_sec, real_min; | ||
86 | int vrtc_min; | ||
87 | |||
88 | vrtc_min = vrtc_cmos_read(RTC_MINUTES); | ||
89 | |||
90 | real_sec = nowtime % 60; | ||
91 | real_min = nowtime / 60; | ||
92 | if (((abs(real_min - vrtc_min) + 15)/30) & 1) | ||
93 | real_min += 30; | ||
94 | real_min %= 60; | ||
95 | |||
96 | vrtc_cmos_write(real_sec, RTC_SECONDS); | ||
97 | vrtc_cmos_write(real_min, RTC_MINUTES); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | void __init mrst_rtc_init(void) | ||
102 | { | ||
103 | unsigned long rtc_paddr; | ||
104 | void __iomem *virt_base; | ||
105 | |||
106 | sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc); | ||
107 | if (!sfi_mrtc_num) | ||
108 | return; | ||
109 | |||
110 | rtc_paddr = sfi_mrtc_array[0].phys_addr; | ||
111 | |||
112 | /* vRTC's register address may not be page aligned */ | ||
113 | set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr); | ||
114 | |||
115 | virt_base = (void __iomem *)__fix_to_virt(FIX_LNW_VRTC); | ||
116 | virt_base += rtc_paddr & ~PAGE_MASK; | ||
117 | vrtc_virt_base = virt_base; | ||
118 | |||
119 | x86_platform.get_wallclock = vrtc_get_time; | ||
120 | x86_platform.set_wallclock = vrtc_set_mmss; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * The Moorestown platform has a memory mapped virtual RTC device that emulates | ||
125 | * the programming interface of the RTC. | ||
126 | */ | ||
127 | |||
128 | static struct resource vrtc_resources[] = { | ||
129 | [0] = { | ||
130 | .flags = IORESOURCE_MEM, | ||
131 | }, | ||
132 | [1] = { | ||
133 | .flags = IORESOURCE_IRQ, | ||
134 | } | ||
135 | }; | ||
136 | |||
137 | static struct platform_device vrtc_device = { | ||
138 | .name = "rtc_mrst", | ||
139 | .id = -1, | ||
140 | .resource = vrtc_resources, | ||
141 | .num_resources = ARRAY_SIZE(vrtc_resources), | ||
142 | }; | ||
143 | |||
144 | /* Register the RTC device if appropriate */ | ||
145 | static int __init mrst_device_create(void) | ||
146 | { | ||
147 | /* No Moorestown, no device */ | ||
148 | if (!mrst_identify_cpu()) | ||
149 | return -ENODEV; | ||
150 | /* No timer, no device */ | ||
151 | if (!sfi_mrtc_num) | ||
152 | return -ENODEV; | ||
153 | |||
154 | /* iomem resource */ | ||
155 | vrtc_resources[0].start = sfi_mrtc_array[0].phys_addr; | ||
156 | vrtc_resources[0].end = sfi_mrtc_array[0].phys_addr + | ||
157 | MRST_VRTC_MAP_SZ; | ||
158 | /* irq resource */ | ||
159 | vrtc_resources[1].start = sfi_mrtc_array[0].irq; | ||
160 | vrtc_resources[1].end = sfi_mrtc_array[0].irq; | ||
161 | |||
162 | return platform_device_register(&vrtc_device); | ||
163 | } | ||
164 | |||
165 | module_init(mrst_device_create); | ||
diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c index dd4c281ffe57..ca54875ac795 100644 --- a/arch/x86/platform/sfi/sfi.c +++ b/arch/x86/platform/sfi/sfi.c | |||
@@ -48,9 +48,9 @@ static void __init mp_sfi_register_lapic_address(unsigned long address) | |||
48 | /* All CPUs enumerated by SFI must be present and enabled */ | 48 | /* All CPUs enumerated by SFI must be present and enabled */ |
49 | static void __cpuinit mp_sfi_register_lapic(u8 id) | 49 | static void __cpuinit mp_sfi_register_lapic(u8 id) |
50 | { | 50 | { |
51 | if (MAX_APICS - id <= 0) { | 51 | if (MAX_LOCAL_APIC - id <= 0) { |
52 | pr_warning("Processor #%d invalid (max %d)\n", | 52 | pr_warning("Processor #%d invalid (max %d)\n", |
53 | id, MAX_APICS); | 53 | id, MAX_LOCAL_APIC); |
54 | return; | 54 | return; |
55 | } | 55 | } |
56 | 56 | ||
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index ba9caa808a9c..df58e9cad96a 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c | |||
@@ -1341,7 +1341,7 @@ uv_activation_descriptor_init(int node, int pnode) | |||
1341 | 1341 | ||
1342 | /* | 1342 | /* |
1343 | * each bau_desc is 64 bytes; there are 8 (UV_ITEMS_PER_DESCRIPTOR) | 1343 | * each bau_desc is 64 bytes; there are 8 (UV_ITEMS_PER_DESCRIPTOR) |
1344 | * per cpu; and up to 32 (UV_ADP_SIZE) cpu's per uvhub | 1344 | * per cpu; and one per cpu on the uvhub (UV_ADP_SIZE) |
1345 | */ | 1345 | */ |
1346 | bau_desc = kmalloc_node(sizeof(struct bau_desc) * UV_ADP_SIZE | 1346 | bau_desc = kmalloc_node(sizeof(struct bau_desc) * UV_ADP_SIZE |
1347 | * UV_ITEMS_PER_DESCRIPTOR, GFP_KERNEL, node); | 1347 | * UV_ITEMS_PER_DESCRIPTOR, GFP_KERNEL, node); |
@@ -1490,7 +1490,7 @@ calculate_destination_timeout(void) | |||
1490 | /* | 1490 | /* |
1491 | * initialize the bau_control structure for each cpu | 1491 | * initialize the bau_control structure for each cpu |
1492 | */ | 1492 | */ |
1493 | static void __init uv_init_per_cpu(int nuvhubs) | 1493 | static int __init uv_init_per_cpu(int nuvhubs) |
1494 | { | 1494 | { |
1495 | int i; | 1495 | int i; |
1496 | int cpu; | 1496 | int cpu; |
@@ -1507,7 +1507,7 @@ static void __init uv_init_per_cpu(int nuvhubs) | |||
1507 | struct bau_control *smaster = NULL; | 1507 | struct bau_control *smaster = NULL; |
1508 | struct socket_desc { | 1508 | struct socket_desc { |
1509 | short num_cpus; | 1509 | short num_cpus; |
1510 | short cpu_number[16]; | 1510 | short cpu_number[MAX_CPUS_PER_SOCKET]; |
1511 | }; | 1511 | }; |
1512 | struct uvhub_desc { | 1512 | struct uvhub_desc { |
1513 | unsigned short socket_mask; | 1513 | unsigned short socket_mask; |
@@ -1540,6 +1540,10 @@ static void __init uv_init_per_cpu(int nuvhubs) | |||
1540 | sdp = &bdp->socket[socket]; | 1540 | sdp = &bdp->socket[socket]; |
1541 | sdp->cpu_number[sdp->num_cpus] = cpu; | 1541 | sdp->cpu_number[sdp->num_cpus] = cpu; |
1542 | sdp->num_cpus++; | 1542 | sdp->num_cpus++; |
1543 | if (sdp->num_cpus > MAX_CPUS_PER_SOCKET) { | ||
1544 | printk(KERN_EMERG "%d cpus per socket invalid\n", sdp->num_cpus); | ||
1545 | return 1; | ||
1546 | } | ||
1543 | } | 1547 | } |
1544 | for (uvhub = 0; uvhub < nuvhubs; uvhub++) { | 1548 | for (uvhub = 0; uvhub < nuvhubs; uvhub++) { |
1545 | if (!(*(uvhub_mask + (uvhub/8)) & (1 << (uvhub%8)))) | 1549 | if (!(*(uvhub_mask + (uvhub/8)) & (1 << (uvhub%8)))) |
@@ -1570,6 +1574,12 @@ static void __init uv_init_per_cpu(int nuvhubs) | |||
1570 | bcp->uvhub_master = hmaster; | 1574 | bcp->uvhub_master = hmaster; |
1571 | bcp->uvhub_cpu = uv_cpu_hub_info(cpu)-> | 1575 | bcp->uvhub_cpu = uv_cpu_hub_info(cpu)-> |
1572 | blade_processor_id; | 1576 | blade_processor_id; |
1577 | if (bcp->uvhub_cpu >= MAX_CPUS_PER_UVHUB) { | ||
1578 | printk(KERN_EMERG | ||
1579 | "%d cpus per uvhub invalid\n", | ||
1580 | bcp->uvhub_cpu); | ||
1581 | return 1; | ||
1582 | } | ||
1573 | } | 1583 | } |
1574 | nextsocket: | 1584 | nextsocket: |
1575 | socket++; | 1585 | socket++; |
@@ -1595,6 +1605,7 @@ nextsocket: | |||
1595 | bcp->congested_reps = congested_reps; | 1605 | bcp->congested_reps = congested_reps; |
1596 | bcp->congested_period = congested_period; | 1606 | bcp->congested_period = congested_period; |
1597 | } | 1607 | } |
1608 | return 0; | ||
1598 | } | 1609 | } |
1599 | 1610 | ||
1600 | /* | 1611 | /* |
@@ -1625,7 +1636,10 @@ static int __init uv_bau_init(void) | |||
1625 | spin_lock_init(&disable_lock); | 1636 | spin_lock_init(&disable_lock); |
1626 | congested_cycles = microsec_2_cycles(congested_response_us); | 1637 | congested_cycles = microsec_2_cycles(congested_response_us); |
1627 | 1638 | ||
1628 | uv_init_per_cpu(nuvhubs); | 1639 | if (uv_init_per_cpu(nuvhubs)) { |
1640 | nobau = 1; | ||
1641 | return 0; | ||
1642 | } | ||
1629 | 1643 | ||
1630 | uv_partition_base_pnode = 0x7fffffff; | 1644 | uv_partition_base_pnode = 0x7fffffff; |
1631 | for (uvhub = 0; uvhub < nuvhubs; uvhub++) | 1645 | for (uvhub = 0; uvhub < nuvhubs; uvhub++) |
diff --git a/arch/x86/platform/visws/visws_quirks.c b/arch/x86/platform/visws/visws_quirks.c index 3371bd053b89..632037671746 100644 --- a/arch/x86/platform/visws/visws_quirks.c +++ b/arch/x86/platform/visws/visws_quirks.c | |||
@@ -171,7 +171,7 @@ static void __init MP_processor_info(struct mpc_cpu *m) | |||
171 | ver = m->apicver; | 171 | ver = m->apicver; |
172 | if ((ver >= 0x14 && m->apicid >= 0xff) || m->apicid >= 0xf) { | 172 | if ((ver >= 0x14 && m->apicid >= 0xff) || m->apicid >= 0xf) { |
173 | printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n", | 173 | printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n", |
174 | m->apicid, MAX_APICS); | 174 | m->apicid, MAX_LOCAL_APIC); |
175 | return; | 175 | return; |
176 | } | 176 | } |
177 | 177 | ||