diff options
Diffstat (limited to 'arch/i386/kernel')
41 files changed, 652 insertions, 637 deletions
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c index 4ee83577bf61..c42b5ab49deb 100644 --- a/arch/i386/kernel/acpi/sleep.c +++ b/arch/i386/kernel/acpi/sleep.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | /* address in low memory of the wakeup routine. */ | 15 | /* address in low memory of the wakeup routine. */ |
16 | unsigned long acpi_wakeup_address = 0; | 16 | unsigned long acpi_wakeup_address = 0; |
17 | unsigned long acpi_video_flags; | 17 | unsigned long acpi_realmode_flags; |
18 | extern char wakeup_start, wakeup_end; | 18 | extern char wakeup_start, wakeup_end; |
19 | 19 | ||
20 | extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long)); | 20 | extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long)); |
@@ -68,9 +68,11 @@ static int __init acpi_sleep_setup(char *str) | |||
68 | { | 68 | { |
69 | while ((str != NULL) && (*str != '\0')) { | 69 | while ((str != NULL) && (*str != '\0')) { |
70 | if (strncmp(str, "s3_bios", 7) == 0) | 70 | if (strncmp(str, "s3_bios", 7) == 0) |
71 | acpi_video_flags = 1; | 71 | acpi_realmode_flags |= 1; |
72 | if (strncmp(str, "s3_mode", 7) == 0) | 72 | if (strncmp(str, "s3_mode", 7) == 0) |
73 | acpi_video_flags |= 2; | 73 | acpi_realmode_flags |= 2; |
74 | if (strncmp(str, "s3_beep", 7) == 0) | ||
75 | acpi_realmode_flags |= 4; | ||
74 | str = strchr(str, ','); | 76 | str = strchr(str, ','); |
75 | if (str != NULL) | 77 | if (str != NULL) |
76 | str += strspn(str, ", \t"); | 78 | str += strspn(str, ", \t"); |
@@ -80,9 +82,11 @@ static int __init acpi_sleep_setup(char *str) | |||
80 | 82 | ||
81 | __setup("acpi_sleep=", acpi_sleep_setup); | 83 | __setup("acpi_sleep=", acpi_sleep_setup); |
82 | 84 | ||
85 | /* Ouch, we want to delete this. We already have better version in userspace, in | ||
86 | s2ram from suspend.sf.net project */ | ||
83 | static __init int reset_videomode_after_s3(struct dmi_system_id *d) | 87 | static __init int reset_videomode_after_s3(struct dmi_system_id *d) |
84 | { | 88 | { |
85 | acpi_video_flags |= 2; | 89 | acpi_realmode_flags |= 2; |
86 | return 0; | 90 | return 0; |
87 | } | 91 | } |
88 | 92 | ||
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S index a2295a34b2c7..ed0a0f2c1597 100644 --- a/arch/i386/kernel/acpi/wakeup.S +++ b/arch/i386/kernel/acpi/wakeup.S | |||
@@ -13,6 +13,21 @@ | |||
13 | # cs = 0x1234, eip = 0x05 | 13 | # cs = 0x1234, eip = 0x05 |
14 | # | 14 | # |
15 | 15 | ||
16 | #define BEEP \ | ||
17 | inb $97, %al; \ | ||
18 | outb %al, $0x80; \ | ||
19 | movb $3, %al; \ | ||
20 | outb %al, $97; \ | ||
21 | outb %al, $0x80; \ | ||
22 | movb $-74, %al; \ | ||
23 | outb %al, $67; \ | ||
24 | outb %al, $0x80; \ | ||
25 | movb $-119, %al; \ | ||
26 | outb %al, $66; \ | ||
27 | outb %al, $0x80; \ | ||
28 | movb $15, %al; \ | ||
29 | outb %al, $66; | ||
30 | |||
16 | ALIGN | 31 | ALIGN |
17 | .align 4096 | 32 | .align 4096 |
18 | ENTRY(wakeup_start) | 33 | ENTRY(wakeup_start) |
@@ -31,6 +46,11 @@ wakeup_code: | |||
31 | movw %cs, %ax | 46 | movw %cs, %ax |
32 | movw %ax, %ds # Make ds:0 point to wakeup_start | 47 | movw %ax, %ds # Make ds:0 point to wakeup_start |
33 | movw %ax, %ss | 48 | movw %ax, %ss |
49 | |||
50 | testl $4, realmode_flags - wakeup_code | ||
51 | jz 1f | ||
52 | BEEP | ||
53 | 1: | ||
34 | mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board | 54 | mov $(wakeup_stack - wakeup_code), %sp # Private stack is needed for ASUS board |
35 | movw $0x0e00 + 'S', %fs:(0x12) | 55 | movw $0x0e00 + 'S', %fs:(0x12) |
36 | 56 | ||
@@ -41,7 +61,7 @@ wakeup_code: | |||
41 | cmpl $0x12345678, %eax | 61 | cmpl $0x12345678, %eax |
42 | jne bogus_real_magic | 62 | jne bogus_real_magic |
43 | 63 | ||
44 | testl $1, video_flags - wakeup_code | 64 | testl $1, realmode_flags - wakeup_code |
45 | jz 1f | 65 | jz 1f |
46 | lcall $0xc000,$3 | 66 | lcall $0xc000,$3 |
47 | movw %cs, %ax | 67 | movw %cs, %ax |
@@ -49,7 +69,7 @@ wakeup_code: | |||
49 | movw %ax, %ss | 69 | movw %ax, %ss |
50 | 1: | 70 | 1: |
51 | 71 | ||
52 | testl $2, video_flags - wakeup_code | 72 | testl $2, realmode_flags - wakeup_code |
53 | jz 1f | 73 | jz 1f |
54 | mov video_mode - wakeup_code, %ax | 74 | mov video_mode - wakeup_code, %ax |
55 | call mode_set | 75 | call mode_set |
@@ -88,7 +108,11 @@ wakeup_code: | |||
88 | cmpl $0x12345678, %eax | 108 | cmpl $0x12345678, %eax |
89 | jne bogus_real_magic | 109 | jne bogus_real_magic |
90 | 110 | ||
91 | ljmpl $__KERNEL_CS,$wakeup_pmode_return | 111 | testl $8, realmode_flags - wakeup_code |
112 | jz 1f | ||
113 | BEEP | ||
114 | 1: | ||
115 | ljmpl $__KERNEL_CS, $wakeup_pmode_return | ||
92 | 116 | ||
93 | real_save_gdt: .word 0 | 117 | real_save_gdt: .word 0 |
94 | .long 0 | 118 | .long 0 |
@@ -97,7 +121,8 @@ real_save_cr3: .long 0 | |||
97 | real_save_cr4: .long 0 | 121 | real_save_cr4: .long 0 |
98 | real_magic: .long 0 | 122 | real_magic: .long 0 |
99 | video_mode: .long 0 | 123 | video_mode: .long 0 |
100 | video_flags: .long 0 | 124 | realmode_flags: .long 0 |
125 | beep_flags: .long 0 | ||
101 | real_efer_save_restore: .long 0 | 126 | real_efer_save_restore: .long 0 |
102 | real_save_efer_edx: .long 0 | 127 | real_save_efer_edx: .long 0 |
103 | real_save_efer_eax: .long 0 | 128 | real_save_efer_eax: .long 0 |
@@ -260,8 +285,8 @@ ENTRY(acpi_copy_wakeup_routine) | |||
260 | 285 | ||
261 | movl saved_videomode, %edx | 286 | movl saved_videomode, %edx |
262 | movl %edx, video_mode - wakeup_start (%eax) | 287 | movl %edx, video_mode - wakeup_start (%eax) |
263 | movl acpi_video_flags, %edx | 288 | movl acpi_realmode_flags, %edx |
264 | movl %edx, video_flags - wakeup_start (%eax) | 289 | movl %edx, realmode_flags - wakeup_start (%eax) |
265 | movl $0x12345678, real_magic - wakeup_start (%eax) | 290 | movl $0x12345678, real_magic - wakeup_start (%eax) |
266 | movl $0x12345678, saved_magic | 291 | movl $0x12345678, saved_magic |
267 | popl %ebx | 292 | popl %ebx |
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 4112afe712b9..47001d50a083 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c | |||
@@ -222,6 +222,7 @@ | |||
222 | #include <linux/capability.h> | 222 | #include <linux/capability.h> |
223 | #include <linux/device.h> | 223 | #include <linux/device.h> |
224 | #include <linux/kernel.h> | 224 | #include <linux/kernel.h> |
225 | #include <linux/freezer.h> | ||
225 | #include <linux/smp.h> | 226 | #include <linux/smp.h> |
226 | #include <linux/dmi.h> | 227 | #include <linux/dmi.h> |
227 | #include <linux/suspend.h> | 228 | #include <linux/suspend.h> |
@@ -2311,7 +2312,6 @@ static int __init apm_init(void) | |||
2311 | remove_proc_entry("apm", NULL); | 2312 | remove_proc_entry("apm", NULL); |
2312 | return err; | 2313 | return err; |
2313 | } | 2314 | } |
2314 | kapmd_task->flags |= PF_NOFREEZE; | ||
2315 | wake_up_process(kapmd_task); | 2315 | wake_up_process(kapmd_task); |
2316 | 2316 | ||
2317 | if (num_online_cpus() > 1 && !smp ) { | 2317 | if (num_online_cpus() > 1 && !smp ) { |
diff --git a/arch/i386/kernel/asm-offsets.c b/arch/i386/kernel/asm-offsets.c index 27a776c9044d..7288ac88d746 100644 --- a/arch/i386/kernel/asm-offsets.c +++ b/arch/i386/kernel/asm-offsets.c | |||
@@ -17,6 +17,13 @@ | |||
17 | #include <asm/thread_info.h> | 17 | #include <asm/thread_info.h> |
18 | #include <asm/elf.h> | 18 | #include <asm/elf.h> |
19 | 19 | ||
20 | #include <xen/interface/xen.h> | ||
21 | |||
22 | #ifdef CONFIG_LGUEST_GUEST | ||
23 | #include <linux/lguest.h> | ||
24 | #include "../../../drivers/lguest/lg.h" | ||
25 | #endif | ||
26 | |||
20 | #define DEFINE(sym, val) \ | 27 | #define DEFINE(sym, val) \ |
21 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | 28 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) |
22 | 29 | ||
@@ -59,6 +66,7 @@ void foo(void) | |||
59 | OFFSET(TI_addr_limit, thread_info, addr_limit); | 66 | OFFSET(TI_addr_limit, thread_info, addr_limit); |
60 | OFFSET(TI_restart_block, thread_info, restart_block); | 67 | OFFSET(TI_restart_block, thread_info, restart_block); |
61 | OFFSET(TI_sysenter_return, thread_info, sysenter_return); | 68 | OFFSET(TI_sysenter_return, thread_info, sysenter_return); |
69 | OFFSET(TI_cpu, thread_info, cpu); | ||
62 | BLANK(); | 70 | BLANK(); |
63 | 71 | ||
64 | OFFSET(GDS_size, Xgt_desc_struct, size); | 72 | OFFSET(GDS_size, Xgt_desc_struct, size); |
@@ -115,4 +123,25 @@ void foo(void) | |||
115 | OFFSET(PARAVIRT_iret, paravirt_ops, iret); | 123 | OFFSET(PARAVIRT_iret, paravirt_ops, iret); |
116 | OFFSET(PARAVIRT_read_cr0, paravirt_ops, read_cr0); | 124 | OFFSET(PARAVIRT_read_cr0, paravirt_ops, read_cr0); |
117 | #endif | 125 | #endif |
126 | |||
127 | #ifdef CONFIG_XEN | ||
128 | BLANK(); | ||
129 | OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask); | ||
130 | OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending); | ||
131 | #endif | ||
132 | |||
133 | #ifdef CONFIG_LGUEST_GUEST | ||
134 | BLANK(); | ||
135 | OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled); | ||
136 | OFFSET(LGUEST_PAGES_host_gdt_desc, lguest_pages, state.host_gdt_desc); | ||
137 | OFFSET(LGUEST_PAGES_host_idt_desc, lguest_pages, state.host_idt_desc); | ||
138 | OFFSET(LGUEST_PAGES_host_cr3, lguest_pages, state.host_cr3); | ||
139 | OFFSET(LGUEST_PAGES_host_sp, lguest_pages, state.host_sp); | ||
140 | OFFSET(LGUEST_PAGES_guest_gdt_desc, lguest_pages,state.guest_gdt_desc); | ||
141 | OFFSET(LGUEST_PAGES_guest_idt_desc, lguest_pages,state.guest_idt_desc); | ||
142 | OFFSET(LGUEST_PAGES_guest_gdt, lguest_pages, state.guest_gdt); | ||
143 | OFFSET(LGUEST_PAGES_regs_trapnum, lguest_pages, regs.trapnum); | ||
144 | OFFSET(LGUEST_PAGES_regs_errcode, lguest_pages, regs.errcode); | ||
145 | OFFSET(LGUEST_PAGES_regs, lguest_pages, regs); | ||
146 | #endif | ||
118 | } | 147 | } |
diff --git a/arch/i386/kernel/cpu/Makefile b/arch/i386/kernel/cpu/Makefile index 74f27a463db0..0b6a8551e9e2 100644 --- a/arch/i386/kernel/cpu/Makefile +++ b/arch/i386/kernel/cpu/Makefile | |||
@@ -8,7 +8,7 @@ obj-y += amd.o | |||
8 | obj-y += cyrix.o | 8 | obj-y += cyrix.o |
9 | obj-y += centaur.o | 9 | obj-y += centaur.o |
10 | obj-y += transmeta.o | 10 | obj-y += transmeta.o |
11 | obj-y += intel.o intel_cacheinfo.o | 11 | obj-y += intel.o intel_cacheinfo.o addon_cpuid_features.o |
12 | obj-y += rise.o | 12 | obj-y += rise.o |
13 | obj-y += nexgen.o | 13 | obj-y += nexgen.o |
14 | obj-y += umc.o | 14 | obj-y += umc.o |
diff --git a/arch/i386/kernel/cpu/addon_cpuid_features.c b/arch/i386/kernel/cpu/addon_cpuid_features.c new file mode 100644 index 000000000000..3e91d3ee26ec --- /dev/null +++ b/arch/i386/kernel/cpu/addon_cpuid_features.c | |||
@@ -0,0 +1,50 @@ | |||
1 | |||
2 | /* | ||
3 | * Routines to indentify additional cpu features that are scattered in | ||
4 | * cpuid space. | ||
5 | */ | ||
6 | |||
7 | #include <linux/cpu.h> | ||
8 | |||
9 | #include <asm/processor.h> | ||
10 | |||
11 | struct cpuid_bit { | ||
12 | u16 feature; | ||
13 | u8 reg; | ||
14 | u8 bit; | ||
15 | u32 level; | ||
16 | }; | ||
17 | |||
18 | enum cpuid_regs { | ||
19 | CR_EAX = 0, | ||
20 | CR_ECX, | ||
21 | CR_EDX, | ||
22 | CR_EBX | ||
23 | }; | ||
24 | |||
25 | void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) | ||
26 | { | ||
27 | u32 max_level; | ||
28 | u32 regs[4]; | ||
29 | const struct cpuid_bit *cb; | ||
30 | |||
31 | static const struct cpuid_bit cpuid_bits[] = { | ||
32 | { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, | ||
33 | { 0, 0, 0, 0 } | ||
34 | }; | ||
35 | |||
36 | for (cb = cpuid_bits; cb->feature; cb++) { | ||
37 | |||
38 | /* Verify that the level is valid */ | ||
39 | max_level = cpuid_eax(cb->level & 0xffff0000); | ||
40 | if (max_level < cb->level || | ||
41 | max_level > (cb->level | 0xffff)) | ||
42 | continue; | ||
43 | |||
44 | cpuid(cb->level, ®s[CR_EAX], ®s[CR_EBX], | ||
45 | ®s[CR_ECX], ®s[CR_EDX]); | ||
46 | |||
47 | if (regs[cb->reg] & (1 << cb->bit)) | ||
48 | set_bit(cb->feature, c->x86_capability); | ||
49 | } | ||
50 | } | ||
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 794d593c47eb..e5419a9dec88 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c | |||
@@ -353,6 +353,8 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 * c) | |||
353 | if ( xlvl >= 0x80000004 ) | 353 | if ( xlvl >= 0x80000004 ) |
354 | get_model_name(c); /* Default name */ | 354 | get_model_name(c); /* Default name */ |
355 | } | 355 | } |
356 | |||
357 | init_scattered_cpuid_features(c); | ||
356 | } | 358 | } |
357 | 359 | ||
358 | early_intel_workaround(c); | 360 | early_intel_workaround(c); |
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig index e912aae9473c..094118ba00da 100644 --- a/arch/i386/kernel/cpu/cpufreq/Kconfig +++ b/arch/i386/kernel/cpu/cpufreq/Kconfig | |||
@@ -90,10 +90,17 @@ config X86_POWERNOW_K8 | |||
90 | If in doubt, say N. | 90 | If in doubt, say N. |
91 | 91 | ||
92 | config X86_POWERNOW_K8_ACPI | 92 | config X86_POWERNOW_K8_ACPI |
93 | bool | 93 | bool "ACPI Support" |
94 | depends on X86_POWERNOW_K8 && ACPI_PROCESSOR | 94 | select ACPI_PROCESSOR |
95 | depends on !(X86_POWERNOW_K8 = y && ACPI_PROCESSOR = m) | 95 | depends on X86_POWERNOW_K8 |
96 | default y | 96 | default y |
97 | help | ||
98 | This provides access to the K8s Processor Performance States via ACPI. | ||
99 | This driver is probably required for CPUFreq to work with multi-socket and | ||
100 | SMP systems. It is not required on at least some single-socket yet | ||
101 | multi-core systems, even if SMP is enabled. | ||
102 | |||
103 | It is safe to say Y here. | ||
97 | 104 | ||
98 | config X86_GX_SUSPMOD | 105 | config X86_GX_SUSPMOD |
99 | tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation" | 106 | tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation" |
@@ -109,7 +116,7 @@ config X86_GX_SUSPMOD | |||
109 | config X86_SPEEDSTEP_CENTRINO | 116 | config X86_SPEEDSTEP_CENTRINO |
110 | tristate "Intel Enhanced SpeedStep" | 117 | tristate "Intel Enhanced SpeedStep" |
111 | select CPU_FREQ_TABLE | 118 | select CPU_FREQ_TABLE |
112 | select X86_SPEEDSTEP_CENTRINO_TABLE if (!X86_SPEEDSTEP_CENTRINO_ACPI) | 119 | select X86_SPEEDSTEP_CENTRINO_TABLE |
113 | help | 120 | help |
114 | This adds the CPUFreq driver for Enhanced SpeedStep enabled | 121 | This adds the CPUFreq driver for Enhanced SpeedStep enabled |
115 | mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However, | 122 | mobile CPUs. This means Intel Pentium M (Centrino) CPUs. However, |
@@ -121,20 +128,6 @@ config X86_SPEEDSTEP_CENTRINO | |||
121 | 128 | ||
122 | If in doubt, say N. | 129 | If in doubt, say N. |
123 | 130 | ||
124 | config X86_SPEEDSTEP_CENTRINO_ACPI | ||
125 | bool "Use ACPI tables to decode valid frequency/voltage (deprecated)" | ||
126 | depends on X86_SPEEDSTEP_CENTRINO && ACPI_PROCESSOR | ||
127 | depends on !(X86_SPEEDSTEP_CENTRINO = y && ACPI_PROCESSOR = m) | ||
128 | help | ||
129 | This is deprecated and this functionality is now merged into | ||
130 | acpi_cpufreq (X86_ACPI_CPUFREQ). Use that driver instead of | ||
131 | speedstep_centrino. | ||
132 | Use primarily the information provided in the BIOS ACPI tables | ||
133 | to determine valid CPU frequency and voltage pairings. It is | ||
134 | required for the driver to work on non-Banias CPUs. | ||
135 | |||
136 | If in doubt, say Y. | ||
137 | |||
138 | config X86_SPEEDSTEP_CENTRINO_TABLE | 131 | config X86_SPEEDSTEP_CENTRINO_TABLE |
139 | bool "Built-in tables for Banias CPUs" | 132 | bool "Built-in tables for Banias CPUs" |
140 | depends on X86_SPEEDSTEP_CENTRINO | 133 | depends on X86_SPEEDSTEP_CENTRINO |
@@ -230,7 +223,7 @@ comment "shared options" | |||
230 | config X86_ACPI_CPUFREQ_PROC_INTF | 223 | config X86_ACPI_CPUFREQ_PROC_INTF |
231 | bool "/proc/acpi/processor/../performance interface (deprecated)" | 224 | bool "/proc/acpi/processor/../performance interface (deprecated)" |
232 | depends on PROC_FS | 225 | depends on PROC_FS |
233 | depends on X86_ACPI_CPUFREQ || X86_SPEEDSTEP_CENTRINO_ACPI || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI | 226 | depends on X86_ACPI_CPUFREQ || X86_POWERNOW_K7_ACPI || X86_POWERNOW_K8_ACPI |
234 | help | 227 | help |
235 | This enables the deprecated /proc/acpi/processor/../performance | 228 | This enables the deprecated /proc/acpi/processor/../performance |
236 | interface. While it is helpful for debugging, the generic, | 229 | interface. While it is helpful for debugging, the generic, |
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 10baa3501ed3..18c8b67ea3a7 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
@@ -167,11 +167,13 @@ static void do_drv_read(struct drv_cmd *cmd) | |||
167 | 167 | ||
168 | static void do_drv_write(struct drv_cmd *cmd) | 168 | static void do_drv_write(struct drv_cmd *cmd) |
169 | { | 169 | { |
170 | u32 h = 0; | 170 | u32 lo, hi; |
171 | 171 | ||
172 | switch (cmd->type) { | 172 | switch (cmd->type) { |
173 | case SYSTEM_INTEL_MSR_CAPABLE: | 173 | case SYSTEM_INTEL_MSR_CAPABLE: |
174 | wrmsr(cmd->addr.msr.reg, cmd->val, h); | 174 | rdmsr(cmd->addr.msr.reg, lo, hi); |
175 | lo = (lo & ~INTEL_MSR_RANGE) | (cmd->val & INTEL_MSR_RANGE); | ||
176 | wrmsr(cmd->addr.msr.reg, lo, hi); | ||
175 | break; | 177 | break; |
176 | case SYSTEM_IO_CAPABLE: | 178 | case SYSTEM_IO_CAPABLE: |
177 | acpi_os_write_port((acpi_io_address)cmd->addr.io.port, | 179 | acpi_os_write_port((acpi_io_address)cmd->addr.io.port, |
@@ -372,7 +374,6 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, | |||
372 | struct cpufreq_freqs freqs; | 374 | struct cpufreq_freqs freqs; |
373 | cpumask_t online_policy_cpus; | 375 | cpumask_t online_policy_cpus; |
374 | struct drv_cmd cmd; | 376 | struct drv_cmd cmd; |
375 | unsigned int msr; | ||
376 | unsigned int next_state = 0; /* Index into freq_table */ | 377 | unsigned int next_state = 0; /* Index into freq_table */ |
377 | unsigned int next_perf_state = 0; /* Index into perf table */ | 378 | unsigned int next_perf_state = 0; /* Index into perf table */ |
378 | unsigned int i; | 379 | unsigned int i; |
@@ -417,11 +418,7 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy, | |||
417 | case SYSTEM_INTEL_MSR_CAPABLE: | 418 | case SYSTEM_INTEL_MSR_CAPABLE: |
418 | cmd.type = SYSTEM_INTEL_MSR_CAPABLE; | 419 | cmd.type = SYSTEM_INTEL_MSR_CAPABLE; |
419 | cmd.addr.msr.reg = MSR_IA32_PERF_CTL; | 420 | cmd.addr.msr.reg = MSR_IA32_PERF_CTL; |
420 | msr = | 421 | cmd.val = (u32) perf->states[next_perf_state].control; |
421 | (u32) perf->states[next_perf_state]. | ||
422 | control & INTEL_MSR_RANGE; | ||
423 | cmd.val = get_cur_val(online_policy_cpus); | ||
424 | cmd.val = (cmd.val & ~INTEL_MSR_RANGE) | msr; | ||
425 | break; | 422 | break; |
426 | case SYSTEM_IO_CAPABLE: | 423 | case SYSTEM_IO_CAPABLE: |
427 | cmd.type = SYSTEM_IO_CAPABLE; | 424 | cmd.type = SYSTEM_IO_CAPABLE; |
diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c index 0d49d73d1b71..66acd5039918 100644 --- a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c +++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c | |||
@@ -391,8 +391,6 @@ static struct cpufreq_driver nforce2_driver = { | |||
391 | */ | 391 | */ |
392 | static unsigned int nforce2_detect_chipset(void) | 392 | static unsigned int nforce2_detect_chipset(void) |
393 | { | 393 | { |
394 | u8 revision; | ||
395 | |||
396 | nforce2_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA, | 394 | nforce2_chipset_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA, |
397 | PCI_DEVICE_ID_NVIDIA_NFORCE2, | 395 | PCI_DEVICE_ID_NVIDIA_NFORCE2, |
398 | PCI_ANY_ID, PCI_ANY_ID, NULL); | 396 | PCI_ANY_ID, PCI_ANY_ID, NULL); |
@@ -400,10 +398,8 @@ static unsigned int nforce2_detect_chipset(void) | |||
400 | if (nforce2_chipset_dev == NULL) | 398 | if (nforce2_chipset_dev == NULL) |
401 | return -ENODEV; | 399 | return -ENODEV; |
402 | 400 | ||
403 | pci_read_config_byte(nforce2_chipset_dev, PCI_REVISION_ID, &revision); | ||
404 | |||
405 | printk(KERN_INFO "cpufreq: Detected nForce2 chipset revision %X\n", | 401 | printk(KERN_INFO "cpufreq: Detected nForce2 chipset revision %X\n", |
406 | revision); | 402 | nforce2_chipset_dev->revision); |
407 | printk(KERN_INFO | 403 | printk(KERN_INFO |
408 | "cpufreq: FSB changing is maybe unstable and can lead to crashes and data loss.\n"); | 404 | "cpufreq: FSB changing is maybe unstable and can lead to crashes and data loss.\n"); |
409 | 405 | ||
diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c index 6667e9cceb9f..194144539a6f 100644 --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c | |||
@@ -115,7 +115,6 @@ struct gxfreq_params { | |||
115 | u8 pci_suscfg; | 115 | u8 pci_suscfg; |
116 | u8 pci_pmer1; | 116 | u8 pci_pmer1; |
117 | u8 pci_pmer2; | 117 | u8 pci_pmer2; |
118 | u8 pci_rev; | ||
119 | struct pci_dev *cs55x0; | 118 | struct pci_dev *cs55x0; |
120 | }; | 119 | }; |
121 | 120 | ||
@@ -276,7 +275,7 @@ static void gx_set_cpuspeed(unsigned int khz) | |||
276 | pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */ | 275 | pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */ |
277 | pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1); | 276 | pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1); |
278 | 277 | ||
279 | if (gx_params->pci_rev < 0x10) { /* CS5530(rev 1.2, 1.3) */ | 278 | if (gx_params->cs55x0->revision < 0x10) { /* CS5530(rev 1.2, 1.3) */ |
280 | suscfg = gx_params->pci_suscfg | SUSMOD; | 279 | suscfg = gx_params->pci_suscfg | SUSMOD; |
281 | } else { /* CS5530A,B.. */ | 280 | } else { /* CS5530A,B.. */ |
282 | suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE; | 281 | suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE; |
@@ -471,7 +470,6 @@ static int __init cpufreq_gx_init(void) | |||
471 | pci_read_config_byte(params->cs55x0, PCI_PMER2, &(params->pci_pmer2)); | 470 | pci_read_config_byte(params->cs55x0, PCI_PMER2, &(params->pci_pmer2)); |
472 | pci_read_config_byte(params->cs55x0, PCI_MODON, &(params->on_duration)); | 471 | pci_read_config_byte(params->cs55x0, PCI_MODON, &(params->on_duration)); |
473 | pci_read_config_byte(params->cs55x0, PCI_MODOFF, &(params->off_duration)); | 472 | pci_read_config_byte(params->cs55x0, PCI_MODOFF, &(params->off_duration)); |
474 | pci_read_config_byte(params->cs55x0, PCI_REVISION_ID, ¶ms->pci_rev); | ||
475 | 473 | ||
476 | if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) { | 474 | if ((ret = cpufreq_register_driver(&gx_suspmod_driver))) { |
477 | kfree(params); | 475 | kfree(params); |
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index a3df9c039bd4..ef8f0bc3fc71 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
32 | #include <linux/delay.h> | ||
32 | 33 | ||
33 | #include <asm/msr.h> | 34 | #include <asm/msr.h> |
34 | #include <asm/timex.h> | 35 | #include <asm/timex.h> |
@@ -55,7 +56,6 @@ | |||
55 | /* Flags */ | 56 | /* Flags */ |
56 | #define USE_ACPI_C3 (1 << 1) | 57 | #define USE_ACPI_C3 (1 << 1) |
57 | #define USE_NORTHBRIDGE (1 << 2) | 58 | #define USE_NORTHBRIDGE (1 << 2) |
58 | #define USE_VT8235 (1 << 3) | ||
59 | 59 | ||
60 | static int cpu_model; | 60 | static int cpu_model; |
61 | static unsigned int numscales=16; | 61 | static unsigned int numscales=16; |
@@ -63,22 +63,19 @@ static unsigned int fsb; | |||
63 | 63 | ||
64 | static const struct mV_pos *vrm_mV_table; | 64 | static const struct mV_pos *vrm_mV_table; |
65 | static const unsigned char *mV_vrm_table; | 65 | static const unsigned char *mV_vrm_table; |
66 | struct f_msr { | ||
67 | u8 vrm; | ||
68 | u8 pos; | ||
69 | }; | ||
70 | static struct f_msr f_msr_table[32]; | ||
71 | 66 | ||
72 | static unsigned int highest_speed, lowest_speed; /* kHz */ | 67 | static unsigned int highest_speed, lowest_speed; /* kHz */ |
73 | static unsigned int minmult, maxmult; | 68 | static unsigned int minmult, maxmult; |
74 | static int can_scale_voltage; | 69 | static int can_scale_voltage; |
75 | static struct acpi_processor *pr = NULL; | 70 | static struct acpi_processor *pr = NULL; |
76 | static struct acpi_processor_cx *cx = NULL; | 71 | static struct acpi_processor_cx *cx = NULL; |
72 | static u32 acpi_regs_addr; | ||
77 | static u8 longhaul_flags; | 73 | static u8 longhaul_flags; |
78 | static u8 longhaul_pos; | 74 | static unsigned int longhaul_index; |
79 | 75 | ||
80 | /* Module parameters */ | 76 | /* Module parameters */ |
81 | static int scale_voltage; | 77 | static int scale_voltage; |
78 | static int disable_acpi_c3; | ||
82 | 79 | ||
83 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) | 80 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg) |
84 | 81 | ||
@@ -144,7 +141,7 @@ static void do_longhaul1(unsigned int clock_ratio_index) | |||
144 | rdmsrl(MSR_VIA_BCR2, bcr2.val); | 141 | rdmsrl(MSR_VIA_BCR2, bcr2.val); |
145 | /* Enable software clock multiplier */ | 142 | /* Enable software clock multiplier */ |
146 | bcr2.bits.ESOFTBF = 1; | 143 | bcr2.bits.ESOFTBF = 1; |
147 | bcr2.bits.CLOCKMUL = clock_ratio_index; | 144 | bcr2.bits.CLOCKMUL = clock_ratio_index & 0xff; |
148 | 145 | ||
149 | /* Sync to timer tick */ | 146 | /* Sync to timer tick */ |
150 | safe_halt(); | 147 | safe_halt(); |
@@ -163,14 +160,12 @@ static void do_longhaul1(unsigned int clock_ratio_index) | |||
163 | 160 | ||
164 | /* For processor with Longhaul MSR */ | 161 | /* For processor with Longhaul MSR */ |
165 | 162 | ||
166 | static void do_powersaver(int cx_address, unsigned int clock_ratio_index) | 163 | static void do_powersaver(int cx_address, unsigned int clock_ratio_index, |
164 | unsigned int dir) | ||
167 | { | 165 | { |
168 | union msr_longhaul longhaul; | 166 | union msr_longhaul longhaul; |
169 | u8 dest_pos; | ||
170 | u32 t; | 167 | u32 t; |
171 | 168 | ||
172 | dest_pos = f_msr_table[clock_ratio_index].pos; | ||
173 | |||
174 | rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); | 169 | rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); |
175 | /* Setup new frequency */ | 170 | /* Setup new frequency */ |
176 | longhaul.bits.RevisionKey = longhaul.bits.RevisionID; | 171 | longhaul.bits.RevisionKey = longhaul.bits.RevisionID; |
@@ -178,11 +173,11 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index) | |||
178 | longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; | 173 | longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; |
179 | /* Setup new voltage */ | 174 | /* Setup new voltage */ |
180 | if (can_scale_voltage) | 175 | if (can_scale_voltage) |
181 | longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm; | 176 | longhaul.bits.SoftVID = (clock_ratio_index >> 8) & 0x1f; |
182 | /* Sync to timer tick */ | 177 | /* Sync to timer tick */ |
183 | safe_halt(); | 178 | safe_halt(); |
184 | /* Raise voltage if necessary */ | 179 | /* Raise voltage if necessary */ |
185 | if (can_scale_voltage && longhaul_pos < dest_pos) { | 180 | if (can_scale_voltage && dir) { |
186 | longhaul.bits.EnableSoftVID = 1; | 181 | longhaul.bits.EnableSoftVID = 1; |
187 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); | 182 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); |
188 | /* Change voltage */ | 183 | /* Change voltage */ |
@@ -199,7 +194,6 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index) | |||
199 | } | 194 | } |
200 | longhaul.bits.EnableSoftVID = 0; | 195 | longhaul.bits.EnableSoftVID = 0; |
201 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); | 196 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); |
202 | longhaul_pos = dest_pos; | ||
203 | } | 197 | } |
204 | 198 | ||
205 | /* Change frequency on next halt or sleep */ | 199 | /* Change frequency on next halt or sleep */ |
@@ -220,7 +214,7 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index) | |||
220 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); | 214 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); |
221 | 215 | ||
222 | /* Reduce voltage if necessary */ | 216 | /* Reduce voltage if necessary */ |
223 | if (can_scale_voltage && longhaul_pos > dest_pos) { | 217 | if (can_scale_voltage && !dir) { |
224 | longhaul.bits.EnableSoftVID = 1; | 218 | longhaul.bits.EnableSoftVID = 1; |
225 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); | 219 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); |
226 | /* Change voltage */ | 220 | /* Change voltage */ |
@@ -237,7 +231,6 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index) | |||
237 | } | 231 | } |
238 | longhaul.bits.EnableSoftVID = 0; | 232 | longhaul.bits.EnableSoftVID = 0; |
239 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); | 233 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); |
240 | longhaul_pos = dest_pos; | ||
241 | } | 234 | } |
242 | } | 235 | } |
243 | 236 | ||
@@ -248,25 +241,28 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index) | |||
248 | * Sets a new clock ratio. | 241 | * Sets a new clock ratio. |
249 | */ | 242 | */ |
250 | 243 | ||
251 | static void longhaul_setstate(unsigned int clock_ratio_index) | 244 | static void longhaul_setstate(unsigned int table_index) |
252 | { | 245 | { |
246 | unsigned int clock_ratio_index; | ||
253 | int speed, mult; | 247 | int speed, mult; |
254 | struct cpufreq_freqs freqs; | 248 | struct cpufreq_freqs freqs; |
255 | static unsigned int old_ratio=-1; | ||
256 | unsigned long flags; | 249 | unsigned long flags; |
257 | unsigned int pic1_mask, pic2_mask; | 250 | unsigned int pic1_mask, pic2_mask; |
251 | u16 bm_status = 0; | ||
252 | u32 bm_timeout = 1000; | ||
253 | unsigned int dir = 0; | ||
258 | 254 | ||
259 | if (old_ratio == clock_ratio_index) | 255 | clock_ratio_index = longhaul_table[table_index].index; |
260 | return; | 256 | /* Safety precautions */ |
261 | old_ratio = clock_ratio_index; | 257 | mult = clock_ratio[clock_ratio_index & 0x1f]; |
262 | |||
263 | mult = clock_ratio[clock_ratio_index]; | ||
264 | if (mult == -1) | 258 | if (mult == -1) |
265 | return; | 259 | return; |
266 | |||
267 | speed = calc_speed(mult); | 260 | speed = calc_speed(mult); |
268 | if ((speed > highest_speed) || (speed < lowest_speed)) | 261 | if ((speed > highest_speed) || (speed < lowest_speed)) |
269 | return; | 262 | return; |
263 | /* Voltage transition before frequency transition? */ | ||
264 | if (can_scale_voltage && longhaul_index < table_index) | ||
265 | dir = 1; | ||
270 | 266 | ||
271 | freqs.old = calc_speed(longhaul_get_cpu_mult()); | 267 | freqs.old = calc_speed(longhaul_get_cpu_mult()); |
272 | freqs.new = speed; | 268 | freqs.new = speed; |
@@ -285,11 +281,24 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
285 | outb(0xFF,0xA1); /* Overkill */ | 281 | outb(0xFF,0xA1); /* Overkill */ |
286 | outb(0xFE,0x21); /* TMR0 only */ | 282 | outb(0xFE,0x21); /* TMR0 only */ |
287 | 283 | ||
284 | /* Wait while PCI bus is busy. */ | ||
285 | if (acpi_regs_addr && (longhaul_flags & USE_NORTHBRIDGE | ||
286 | || ((pr != NULL) && pr->flags.bm_control))) { | ||
287 | bm_status = inw(acpi_regs_addr); | ||
288 | bm_status &= 1 << 4; | ||
289 | while (bm_status && bm_timeout) { | ||
290 | outw(1 << 4, acpi_regs_addr); | ||
291 | bm_timeout--; | ||
292 | bm_status = inw(acpi_regs_addr); | ||
293 | bm_status &= 1 << 4; | ||
294 | } | ||
295 | } | ||
296 | |||
288 | if (longhaul_flags & USE_NORTHBRIDGE) { | 297 | if (longhaul_flags & USE_NORTHBRIDGE) { |
289 | /* Disable AGP and PCI arbiters */ | 298 | /* Disable AGP and PCI arbiters */ |
290 | outb(3, 0x22); | 299 | outb(3, 0x22); |
291 | } else if ((pr != NULL) && pr->flags.bm_control) { | 300 | } else if ((pr != NULL) && pr->flags.bm_control) { |
292 | /* Disable bus master arbitration */ | 301 | /* Disable bus master arbitration */ |
293 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); | 302 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); |
294 | } | 303 | } |
295 | switch (longhaul_version) { | 304 | switch (longhaul_version) { |
@@ -314,9 +323,9 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
314 | if (longhaul_flags & USE_ACPI_C3) { | 323 | if (longhaul_flags & USE_ACPI_C3) { |
315 | /* Don't allow wakeup */ | 324 | /* Don't allow wakeup */ |
316 | acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0); | 325 | acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0); |
317 | do_powersaver(cx->address, clock_ratio_index); | 326 | do_powersaver(cx->address, clock_ratio_index, dir); |
318 | } else { | 327 | } else { |
319 | do_powersaver(0, clock_ratio_index); | 328 | do_powersaver(0, clock_ratio_index, dir); |
320 | } | 329 | } |
321 | break; | 330 | break; |
322 | } | 331 | } |
@@ -336,6 +345,9 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
336 | 345 | ||
337 | freqs.new = calc_speed(longhaul_get_cpu_mult()); | 346 | freqs.new = calc_speed(longhaul_get_cpu_mult()); |
338 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 347 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |
348 | |||
349 | if (!bm_timeout) | ||
350 | printk(KERN_INFO PFX "Warning: Timeout while waiting for idle PCI bus.\n"); | ||
339 | } | 351 | } |
340 | 352 | ||
341 | /* | 353 | /* |
@@ -369,7 +381,8 @@ static int guess_fsb(int mult) | |||
369 | 381 | ||
370 | static int __init longhaul_get_ranges(void) | 382 | static int __init longhaul_get_ranges(void) |
371 | { | 383 | { |
372 | unsigned int j, k = 0; | 384 | unsigned int i, j, k = 0; |
385 | unsigned int ratio; | ||
373 | int mult; | 386 | int mult; |
374 | 387 | ||
375 | /* Get current frequency */ | 388 | /* Get current frequency */ |
@@ -423,8 +436,7 @@ static int __init longhaul_get_ranges(void) | |||
423 | if(!longhaul_table) | 436 | if(!longhaul_table) |
424 | return -ENOMEM; | 437 | return -ENOMEM; |
425 | 438 | ||
426 | for (j=0; j < numscales; j++) { | 439 | for (j = 0; j < numscales; j++) { |
427 | unsigned int ratio; | ||
428 | ratio = clock_ratio[j]; | 440 | ratio = clock_ratio[j]; |
429 | if (ratio == -1) | 441 | if (ratio == -1) |
430 | continue; | 442 | continue; |
@@ -434,13 +446,41 @@ static int __init longhaul_get_ranges(void) | |||
434 | longhaul_table[k].index = j; | 446 | longhaul_table[k].index = j; |
435 | k++; | 447 | k++; |
436 | } | 448 | } |
449 | if (k <= 1) { | ||
450 | kfree(longhaul_table); | ||
451 | return -ENODEV; | ||
452 | } | ||
453 | /* Sort */ | ||
454 | for (j = 0; j < k - 1; j++) { | ||
455 | unsigned int min_f, min_i; | ||
456 | min_f = longhaul_table[j].frequency; | ||
457 | min_i = j; | ||
458 | for (i = j + 1; i < k; i++) { | ||
459 | if (longhaul_table[i].frequency < min_f) { | ||
460 | min_f = longhaul_table[i].frequency; | ||
461 | min_i = i; | ||
462 | } | ||
463 | } | ||
464 | if (min_i != j) { | ||
465 | unsigned int temp; | ||
466 | temp = longhaul_table[j].frequency; | ||
467 | longhaul_table[j].frequency = longhaul_table[min_i].frequency; | ||
468 | longhaul_table[min_i].frequency = temp; | ||
469 | temp = longhaul_table[j].index; | ||
470 | longhaul_table[j].index = longhaul_table[min_i].index; | ||
471 | longhaul_table[min_i].index = temp; | ||
472 | } | ||
473 | } | ||
437 | 474 | ||
438 | longhaul_table[k].frequency = CPUFREQ_TABLE_END; | 475 | longhaul_table[k].frequency = CPUFREQ_TABLE_END; |
439 | if (!k) { | ||
440 | kfree (longhaul_table); | ||
441 | return -EINVAL; | ||
442 | } | ||
443 | 476 | ||
477 | /* Find index we are running on */ | ||
478 | for (j = 0; j < k; j++) { | ||
479 | if (clock_ratio[longhaul_table[j].index & 0x1f] == mult) { | ||
480 | longhaul_index = j; | ||
481 | break; | ||
482 | } | ||
483 | } | ||
444 | return 0; | 484 | return 0; |
445 | } | 485 | } |
446 | 486 | ||
@@ -448,7 +488,7 @@ static int __init longhaul_get_ranges(void) | |||
448 | static void __init longhaul_setup_voltagescaling(void) | 488 | static void __init longhaul_setup_voltagescaling(void) |
449 | { | 489 | { |
450 | union msr_longhaul longhaul; | 490 | union msr_longhaul longhaul; |
451 | struct mV_pos minvid, maxvid; | 491 | struct mV_pos minvid, maxvid, vid; |
452 | unsigned int j, speed, pos, kHz_step, numvscales; | 492 | unsigned int j, speed, pos, kHz_step, numvscales; |
453 | int min_vid_speed; | 493 | int min_vid_speed; |
454 | 494 | ||
@@ -459,11 +499,11 @@ static void __init longhaul_setup_voltagescaling(void) | |||
459 | } | 499 | } |
460 | 500 | ||
461 | if (!longhaul.bits.VRMRev) { | 501 | if (!longhaul.bits.VRMRev) { |
462 | printk (KERN_INFO PFX "VRM 8.5\n"); | 502 | printk(KERN_INFO PFX "VRM 8.5\n"); |
463 | vrm_mV_table = &vrm85_mV[0]; | 503 | vrm_mV_table = &vrm85_mV[0]; |
464 | mV_vrm_table = &mV_vrm85[0]; | 504 | mV_vrm_table = &mV_vrm85[0]; |
465 | } else { | 505 | } else { |
466 | printk (KERN_INFO PFX "Mobile VRM\n"); | 506 | printk(KERN_INFO PFX "Mobile VRM\n"); |
467 | if (cpu_model < CPU_NEHEMIAH) | 507 | if (cpu_model < CPU_NEHEMIAH) |
468 | return; | 508 | return; |
469 | vrm_mV_table = &mobilevrm_mV[0]; | 509 | vrm_mV_table = &mobilevrm_mV[0]; |
@@ -523,7 +563,6 @@ static void __init longhaul_setup_voltagescaling(void) | |||
523 | /* Calculate kHz for one voltage step */ | 563 | /* Calculate kHz for one voltage step */ |
524 | kHz_step = (highest_speed - min_vid_speed) / numvscales; | 564 | kHz_step = (highest_speed - min_vid_speed) / numvscales; |
525 | 565 | ||
526 | |||
527 | j = 0; | 566 | j = 0; |
528 | while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) { | 567 | while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) { |
529 | speed = longhaul_table[j].frequency; | 568 | speed = longhaul_table[j].frequency; |
@@ -531,15 +570,14 @@ static void __init longhaul_setup_voltagescaling(void) | |||
531 | pos = (speed - min_vid_speed) / kHz_step + minvid.pos; | 570 | pos = (speed - min_vid_speed) / kHz_step + minvid.pos; |
532 | else | 571 | else |
533 | pos = minvid.pos; | 572 | pos = minvid.pos; |
534 | f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos]; | 573 | longhaul_table[j].index |= mV_vrm_table[pos] << 8; |
535 | f_msr_table[longhaul_table[j].index].pos = pos; | 574 | vid = vrm_mV_table[mV_vrm_table[pos]]; |
575 | printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n", speed, j, vid.mV); | ||
536 | j++; | 576 | j++; |
537 | } | 577 | } |
538 | 578 | ||
539 | longhaul_pos = maxvid.pos; | ||
540 | can_scale_voltage = 1; | 579 | can_scale_voltage = 1; |
541 | printk(KERN_INFO PFX "Voltage scaling enabled. " | 580 | printk(KERN_INFO PFX "Voltage scaling enabled.\n"); |
542 | "Use of \"conservative\" governor is highly recommended.\n"); | ||
543 | } | 581 | } |
544 | 582 | ||
545 | 583 | ||
@@ -553,15 +591,44 @@ static int longhaul_target(struct cpufreq_policy *policy, | |||
553 | unsigned int target_freq, unsigned int relation) | 591 | unsigned int target_freq, unsigned int relation) |
554 | { | 592 | { |
555 | unsigned int table_index = 0; | 593 | unsigned int table_index = 0; |
556 | unsigned int new_clock_ratio = 0; | 594 | unsigned int i; |
595 | unsigned int dir = 0; | ||
596 | u8 vid, current_vid; | ||
557 | 597 | ||
558 | if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index)) | 598 | if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index)) |
559 | return -EINVAL; | 599 | return -EINVAL; |
560 | 600 | ||
561 | new_clock_ratio = longhaul_table[table_index].index & 0xFF; | 601 | /* Don't set same frequency again */ |
562 | 602 | if (longhaul_index == table_index) | |
563 | longhaul_setstate(new_clock_ratio); | 603 | return 0; |
564 | 604 | ||
605 | if (!can_scale_voltage) | ||
606 | longhaul_setstate(table_index); | ||
607 | else { | ||
608 | /* On test system voltage transitions exceeding single | ||
609 | * step up or down were turning motherboard off. Both | ||
610 | * "ondemand" and "userspace" are unsafe. C7 is doing | ||
611 | * this in hardware, C3 is old and we need to do this | ||
612 | * in software. */ | ||
613 | i = longhaul_index; | ||
614 | current_vid = (longhaul_table[longhaul_index].index >> 8) & 0x1f; | ||
615 | if (table_index > longhaul_index) | ||
616 | dir = 1; | ||
617 | while (i != table_index) { | ||
618 | vid = (longhaul_table[i].index >> 8) & 0x1f; | ||
619 | if (vid != current_vid) { | ||
620 | longhaul_setstate(i); | ||
621 | current_vid = vid; | ||
622 | msleep(200); | ||
623 | } | ||
624 | if (dir) | ||
625 | i++; | ||
626 | else | ||
627 | i--; | ||
628 | } | ||
629 | longhaul_setstate(table_index); | ||
630 | } | ||
631 | longhaul_index = table_index; | ||
565 | return 0; | 632 | return 0; |
566 | } | 633 | } |
567 | 634 | ||
@@ -590,11 +657,10 @@ static acpi_status longhaul_walk_callback(acpi_handle obj_handle, | |||
590 | static int enable_arbiter_disable(void) | 657 | static int enable_arbiter_disable(void) |
591 | { | 658 | { |
592 | struct pci_dev *dev; | 659 | struct pci_dev *dev; |
593 | int status; | 660 | int status = 1; |
594 | int reg; | 661 | int reg; |
595 | u8 pci_cmd; | 662 | u8 pci_cmd; |
596 | 663 | ||
597 | status = 1; | ||
598 | /* Find PLE133 host bridge */ | 664 | /* Find PLE133 host bridge */ |
599 | reg = 0x78; | 665 | reg = 0x78; |
600 | dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, | 666 | dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, |
@@ -627,13 +693,17 @@ static int enable_arbiter_disable(void) | |||
627 | return 0; | 693 | return 0; |
628 | } | 694 | } |
629 | 695 | ||
630 | static int longhaul_setup_vt8235(void) | 696 | static int longhaul_setup_southbridge(void) |
631 | { | 697 | { |
632 | struct pci_dev *dev; | 698 | struct pci_dev *dev; |
633 | u8 pci_cmd; | 699 | u8 pci_cmd; |
634 | 700 | ||
635 | /* Find VT8235 southbridge */ | 701 | /* Find VT8235 southbridge */ |
636 | dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL); | 702 | dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL); |
703 | if (dev == NULL) | ||
704 | /* Find VT8237 southbridge */ | ||
705 | dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
706 | PCI_DEVICE_ID_VIA_8237, NULL); | ||
637 | if (dev != NULL) { | 707 | if (dev != NULL) { |
638 | /* Set transition time to max */ | 708 | /* Set transition time to max */ |
639 | pci_read_config_byte(dev, 0xec, &pci_cmd); | 709 | pci_read_config_byte(dev, 0xec, &pci_cmd); |
@@ -645,6 +715,14 @@ static int longhaul_setup_vt8235(void) | |||
645 | pci_read_config_byte(dev, 0xe5, &pci_cmd); | 715 | pci_read_config_byte(dev, 0xe5, &pci_cmd); |
646 | pci_cmd |= 1 << 7; | 716 | pci_cmd |= 1 << 7; |
647 | pci_write_config_byte(dev, 0xe5, pci_cmd); | 717 | pci_write_config_byte(dev, 0xe5, pci_cmd); |
718 | /* Get address of ACPI registers block*/ | ||
719 | pci_read_config_byte(dev, 0x81, &pci_cmd); | ||
720 | if (pci_cmd & 1 << 7) { | ||
721 | pci_read_config_dword(dev, 0x88, &acpi_regs_addr); | ||
722 | acpi_regs_addr &= 0xff00; | ||
723 | printk(KERN_INFO PFX "ACPI I/O at 0x%x\n", acpi_regs_addr); | ||
724 | } | ||
725 | |||
648 | pci_dev_put(dev); | 726 | pci_dev_put(dev); |
649 | return 1; | 727 | return 1; |
650 | } | 728 | } |
@@ -657,7 +735,6 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
657 | char *cpuname=NULL; | 735 | char *cpuname=NULL; |
658 | int ret; | 736 | int ret; |
659 | u32 lo, hi; | 737 | u32 lo, hi; |
660 | int vt8235_present; | ||
661 | 738 | ||
662 | /* Check what we have on this motherboard */ | 739 | /* Check what we have on this motherboard */ |
663 | switch (c->x86_model) { | 740 | switch (c->x86_model) { |
@@ -755,7 +832,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
755 | }; | 832 | }; |
756 | 833 | ||
757 | /* Doesn't hurt */ | 834 | /* Doesn't hurt */ |
758 | vt8235_present = longhaul_setup_vt8235(); | 835 | longhaul_setup_southbridge(); |
759 | 836 | ||
760 | /* Find ACPI data for processor */ | 837 | /* Find ACPI data for processor */ |
761 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, | 838 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, |
@@ -765,35 +842,29 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
765 | /* Check ACPI support for C3 state */ | 842 | /* Check ACPI support for C3 state */ |
766 | if (pr != NULL && longhaul_version == TYPE_POWERSAVER) { | 843 | if (pr != NULL && longhaul_version == TYPE_POWERSAVER) { |
767 | cx = &pr->power.states[ACPI_STATE_C3]; | 844 | cx = &pr->power.states[ACPI_STATE_C3]; |
768 | if (cx->address > 0 && cx->latency <= 1000) { | 845 | if (cx->address > 0 && cx->latency <= 1000) |
769 | longhaul_flags |= USE_ACPI_C3; | 846 | longhaul_flags |= USE_ACPI_C3; |
770 | goto print_support_type; | ||
771 | } | ||
772 | } | 847 | } |
848 | /* Disable if it isn't working */ | ||
849 | if (disable_acpi_c3) | ||
850 | longhaul_flags &= ~USE_ACPI_C3; | ||
773 | /* Check if northbridge is friendly */ | 851 | /* Check if northbridge is friendly */ |
774 | if (enable_arbiter_disable()) { | 852 | if (enable_arbiter_disable()) |
775 | longhaul_flags |= USE_NORTHBRIDGE; | 853 | longhaul_flags |= USE_NORTHBRIDGE; |
776 | goto print_support_type; | 854 | |
777 | } | ||
778 | /* Use VT8235 southbridge if present */ | ||
779 | if (longhaul_version == TYPE_POWERSAVER && vt8235_present) { | ||
780 | longhaul_flags |= USE_VT8235; | ||
781 | goto print_support_type; | ||
782 | } | ||
783 | /* Check ACPI support for bus master arbiter disable */ | 855 | /* Check ACPI support for bus master arbiter disable */ |
784 | if ((pr == NULL) || !(pr->flags.bm_control)) { | 856 | if (!(longhaul_flags & USE_ACPI_C3 |
857 | || longhaul_flags & USE_NORTHBRIDGE) | ||
858 | && ((pr == NULL) || !(pr->flags.bm_control))) { | ||
785 | printk(KERN_ERR PFX | 859 | printk(KERN_ERR PFX |
786 | "No ACPI support. Unsupported northbridge.\n"); | 860 | "No ACPI support. Unsupported northbridge.\n"); |
787 | return -ENODEV; | 861 | return -ENODEV; |
788 | } | 862 | } |
789 | 863 | ||
790 | print_support_type: | ||
791 | if (longhaul_flags & USE_NORTHBRIDGE) | 864 | if (longhaul_flags & USE_NORTHBRIDGE) |
792 | printk (KERN_INFO PFX "Using northbridge support.\n"); | 865 | printk(KERN_INFO PFX "Using northbridge support.\n"); |
793 | else if (longhaul_flags & USE_VT8235) | 866 | if (longhaul_flags & USE_ACPI_C3) |
794 | printk (KERN_INFO PFX "Using VT8235 support.\n"); | 867 | printk(KERN_INFO PFX "Using ACPI support.\n"); |
795 | else | ||
796 | printk (KERN_INFO PFX "Using ACPI support.\n"); | ||
797 | 868 | ||
798 | ret = longhaul_get_ranges(); | 869 | ret = longhaul_get_ranges(); |
799 | if (ret != 0) | 870 | if (ret != 0) |
@@ -885,6 +956,9 @@ static void __exit longhaul_exit(void) | |||
885 | kfree(longhaul_table); | 956 | kfree(longhaul_table); |
886 | } | 957 | } |
887 | 958 | ||
959 | module_param (disable_acpi_c3, int, 0644); | ||
960 | MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support"); | ||
961 | |||
888 | module_param (scale_voltage, int, 0644); | 962 | module_param (scale_voltage, int, 0644); |
889 | MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); | 963 | MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); |
890 | 964 | ||
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.h b/arch/i386/kernel/cpu/cpufreq/longhaul.h index 102548f12842..4fcc320997df 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.h +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.h | |||
@@ -180,7 +180,7 @@ static const int __initdata ezrat_clock_ratio[32] = { | |||
180 | 180 | ||
181 | -1, /* 0000 -> RESERVED (10.0x) */ | 181 | -1, /* 0000 -> RESERVED (10.0x) */ |
182 | 110, /* 0001 -> 11.0x */ | 182 | 110, /* 0001 -> 11.0x */ |
183 | 120, /* 0010 -> 12.0x */ | 183 | -1, /* 0010 -> 12.0x */ |
184 | -1, /* 0011 -> RESERVED (9.0x)*/ | 184 | -1, /* 0011 -> RESERVED (9.0x)*/ |
185 | 105, /* 0100 -> 10.5x */ | 185 | 105, /* 0100 -> 10.5x */ |
186 | 115, /* 0101 -> 11.5x */ | 186 | 115, /* 0101 -> 11.5x */ |
@@ -237,7 +237,7 @@ static const int __initdata ezrat_eblcr[32] = { | |||
237 | 237 | ||
238 | static const int __initdata nehemiah_clock_ratio[32] = { | 238 | static const int __initdata nehemiah_clock_ratio[32] = { |
239 | 100, /* 0000 -> 10.0x */ | 239 | 100, /* 0000 -> 10.0x */ |
240 | 160, /* 0001 -> 16.0x */ | 240 | -1, /* 0001 -> 16.0x */ |
241 | 40, /* 0010 -> 4.0x */ | 241 | 40, /* 0010 -> 4.0x */ |
242 | 90, /* 0011 -> 9.0x */ | 242 | 90, /* 0011 -> 9.0x */ |
243 | 95, /* 0100 -> 9.5x */ | 243 | 95, /* 0100 -> 9.5x */ |
@@ -252,10 +252,10 @@ static const int __initdata nehemiah_clock_ratio[32] = { | |||
252 | 75, /* 1101 -> 7.5x */ | 252 | 75, /* 1101 -> 7.5x */ |
253 | 85, /* 1110 -> 8.5x */ | 253 | 85, /* 1110 -> 8.5x */ |
254 | 120, /* 1111 -> 12.0x */ | 254 | 120, /* 1111 -> 12.0x */ |
255 | 100, /* 0000 -> 10.0x */ | 255 | -1, /* 0000 -> 10.0x */ |
256 | 110, /* 0001 -> 11.0x */ | 256 | 110, /* 0001 -> 11.0x */ |
257 | 120, /* 0010 -> 12.0x */ | 257 | -1, /* 0010 -> 12.0x */ |
258 | 90, /* 0011 -> 9.0x */ | 258 | -1, /* 0011 -> 9.0x */ |
259 | 105, /* 0100 -> 10.5x */ | 259 | 105, /* 0100 -> 10.5x */ |
260 | 115, /* 0101 -> 11.5x */ | 260 | 115, /* 0101 -> 11.5x */ |
261 | 125, /* 0110 -> 12.5x */ | 261 | 125, /* 0110 -> 12.5x */ |
@@ -267,7 +267,7 @@ static const int __initdata nehemiah_clock_ratio[32] = { | |||
267 | 145, /* 1100 -> 14.5x */ | 267 | 145, /* 1100 -> 14.5x */ |
268 | 155, /* 1101 -> 15.5x */ | 268 | 155, /* 1101 -> 15.5x */ |
269 | -1, /* 1110 -> RESERVED (13.0x) */ | 269 | -1, /* 1110 -> RESERVED (13.0x) */ |
270 | 120, /* 1111 -> 12.0x */ | 270 | -1, /* 1111 -> 12.0x */ |
271 | }; | 271 | }; |
272 | 272 | ||
273 | static const int __initdata nehemiah_eblcr[32] = { | 273 | static const int __initdata nehemiah_eblcr[32] = { |
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 4ade55c5f333..34ed53a06730 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c | |||
@@ -599,14 +599,17 @@ static void print_basics(struct powernow_k8_data *data) | |||
599 | for (j = 0; j < data->numps; j++) { | 599 | for (j = 0; j < data->numps; j++) { |
600 | if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) { | 600 | if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) { |
601 | if (cpu_family == CPU_HW_PSTATE) { | 601 | if (cpu_family == CPU_HW_PSTATE) { |
602 | printk(KERN_INFO PFX " %d : fid 0x%x gid 0x%x (%d MHz)\n", j, (data->powernow_table[j].index & 0xff00) >> 8, | 602 | printk(KERN_INFO PFX " %d : fid 0x%x did 0x%x (%d MHz)\n", |
603 | (data->powernow_table[j].index & 0xff0000) >> 16, | 603 | j, |
604 | data->powernow_table[j].frequency/1000); | 604 | (data->powernow_table[j].index & 0xff00) >> 8, |
605 | (data->powernow_table[j].index & 0xff0000) >> 16, | ||
606 | data->powernow_table[j].frequency/1000); | ||
605 | } else { | 607 | } else { |
606 | printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", j, | 608 | printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", |
607 | data->powernow_table[j].index & 0xff, | 609 | j, |
608 | data->powernow_table[j].frequency/1000, | 610 | data->powernow_table[j].index & 0xff, |
609 | data->powernow_table[j].index >> 8); | 611 | data->powernow_table[j].frequency/1000, |
612 | data->powernow_table[j].index >> 8); | ||
610 | } | 613 | } |
611 | } | 614 | } |
612 | } | 615 | } |
@@ -1086,7 +1089,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi | |||
1086 | 1089 | ||
1087 | if (cpu_family == CPU_HW_PSTATE) | 1090 | if (cpu_family == CPU_HW_PSTATE) |
1088 | dprintk("targ: curr fid 0x%x, did 0x%x\n", | 1091 | dprintk("targ: curr fid 0x%x, did 0x%x\n", |
1089 | data->currfid, data->currvid); | 1092 | data->currfid, data->currdid); |
1090 | else { | 1093 | else { |
1091 | dprintk("targ: curr fid 0x%x, vid 0x%x\n", | 1094 | dprintk("targ: curr fid 0x%x, vid 0x%x\n", |
1092 | data->currfid, data->currvid); | 1095 | data->currfid, data->currvid); |
@@ -1322,16 +1325,22 @@ static struct cpufreq_driver cpufreq_amd64_driver = { | |||
1322 | static int __cpuinit powernowk8_init(void) | 1325 | static int __cpuinit powernowk8_init(void) |
1323 | { | 1326 | { |
1324 | unsigned int i, supported_cpus = 0; | 1327 | unsigned int i, supported_cpus = 0; |
1328 | unsigned int booted_cores = 1; | ||
1325 | 1329 | ||
1326 | for_each_online_cpu(i) { | 1330 | for_each_online_cpu(i) { |
1327 | if (check_supported_cpu(i)) | 1331 | if (check_supported_cpu(i)) |
1328 | supported_cpus++; | 1332 | supported_cpus++; |
1329 | } | 1333 | } |
1330 | 1334 | ||
1335 | #ifdef CONFIG_SMP | ||
1336 | booted_cores = cpu_data[0].booted_cores; | ||
1337 | #endif | ||
1338 | |||
1331 | if (supported_cpus == num_online_cpus()) { | 1339 | if (supported_cpus == num_online_cpus()) { |
1332 | printk(KERN_INFO PFX "Found %d %s " | 1340 | printk(KERN_INFO PFX "Found %d %s " |
1333 | "processors (" VERSION ")\n", supported_cpus, | 1341 | "processors (%d cpu cores) (" VERSION ")\n", |
1334 | boot_cpu_data.x86_model_id); | 1342 | supported_cpus/booted_cores, |
1343 | boot_cpu_data.x86_model_id, supported_cpus); | ||
1335 | return cpufreq_register_driver(&cpufreq_amd64_driver); | 1344 | return cpufreq_register_driver(&cpufreq_amd64_driver); |
1336 | } | 1345 | } |
1337 | 1346 | ||
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c index 35489fd68852..6c5dc2c85aeb 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c | |||
@@ -21,12 +21,6 @@ | |||
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/compiler.h> | 22 | #include <linux/compiler.h> |
23 | 23 | ||
24 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | ||
25 | #include <linux/acpi.h> | ||
26 | #include <linux/dmi.h> | ||
27 | #include <acpi/processor.h> | ||
28 | #endif | ||
29 | |||
30 | #include <asm/msr.h> | 24 | #include <asm/msr.h> |
31 | #include <asm/processor.h> | 25 | #include <asm/processor.h> |
32 | #include <asm/cpufeature.h> | 26 | #include <asm/cpufeature.h> |
@@ -257,9 +251,7 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy) | |||
257 | /* Matched a non-match */ | 251 | /* Matched a non-match */ |
258 | dprintk("no table support for CPU model \"%s\"\n", | 252 | dprintk("no table support for CPU model \"%s\"\n", |
259 | cpu->x86_model_id); | 253 | cpu->x86_model_id); |
260 | #ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | 254 | dprintk("try using the acpi-cpufreq driver\n"); |
261 | dprintk("try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n"); | ||
262 | #endif | ||
263 | return -ENOENT; | 255 | return -ENOENT; |
264 | } | 256 | } |
265 | 257 | ||
@@ -346,213 +338,6 @@ static unsigned int get_cur_freq(unsigned int cpu) | |||
346 | } | 338 | } |
347 | 339 | ||
348 | 340 | ||
349 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | ||
350 | |||
351 | static struct acpi_processor_performance *acpi_perf_data[NR_CPUS]; | ||
352 | |||
353 | /* | ||
354 | * centrino_cpu_early_init_acpi - Do the preregistering with ACPI P-States | ||
355 | * library | ||
356 | * | ||
357 | * Before doing the actual init, we need to do _PSD related setup whenever | ||
358 | * supported by the BIOS. These are handled by this early_init routine. | ||
359 | */ | ||
360 | static int centrino_cpu_early_init_acpi(void) | ||
361 | { | ||
362 | unsigned int i, j; | ||
363 | struct acpi_processor_performance *data; | ||
364 | |||
365 | for_each_possible_cpu(i) { | ||
366 | data = kzalloc(sizeof(struct acpi_processor_performance), | ||
367 | GFP_KERNEL); | ||
368 | if (!data) { | ||
369 | for_each_possible_cpu(j) { | ||
370 | kfree(acpi_perf_data[j]); | ||
371 | acpi_perf_data[j] = NULL; | ||
372 | } | ||
373 | return (-ENOMEM); | ||
374 | } | ||
375 | acpi_perf_data[i] = data; | ||
376 | } | ||
377 | |||
378 | acpi_processor_preregister_performance(acpi_perf_data); | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | |||
383 | #ifdef CONFIG_SMP | ||
384 | /* | ||
385 | * Some BIOSes do SW_ANY coordination internally, either set it up in hw | ||
386 | * or do it in BIOS firmware and won't inform about it to OS. If not | ||
387 | * detected, this has a side effect of making CPU run at a different speed | ||
388 | * than OS intended it to run at. Detect it and handle it cleanly. | ||
389 | */ | ||
390 | static int bios_with_sw_any_bug; | ||
391 | static int sw_any_bug_found(struct dmi_system_id *d) | ||
392 | { | ||
393 | bios_with_sw_any_bug = 1; | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | static struct dmi_system_id sw_any_bug_dmi_table[] = { | ||
398 | { | ||
399 | .callback = sw_any_bug_found, | ||
400 | .ident = "Supermicro Server X6DLP", | ||
401 | .matches = { | ||
402 | DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"), | ||
403 | DMI_MATCH(DMI_BIOS_VERSION, "080010"), | ||
404 | DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"), | ||
405 | }, | ||
406 | }, | ||
407 | { } | ||
408 | }; | ||
409 | #endif | ||
410 | |||
411 | /* | ||
412 | * centrino_cpu_init_acpi - register with ACPI P-States library | ||
413 | * | ||
414 | * Register with the ACPI P-States library (part of drivers/acpi/processor.c) | ||
415 | * in order to determine correct frequency and voltage pairings by reading | ||
416 | * the _PSS of the ACPI DSDT or SSDT tables. | ||
417 | */ | ||
418 | static int centrino_cpu_init_acpi(struct cpufreq_policy *policy) | ||
419 | { | ||
420 | unsigned long cur_freq; | ||
421 | int result = 0, i; | ||
422 | unsigned int cpu = policy->cpu; | ||
423 | struct acpi_processor_performance *p; | ||
424 | |||
425 | p = acpi_perf_data[cpu]; | ||
426 | |||
427 | /* register with ACPI core */ | ||
428 | if (acpi_processor_register_performance(p, cpu)) { | ||
429 | dprintk(PFX "obtaining ACPI data failed\n"); | ||
430 | return -EIO; | ||
431 | } | ||
432 | |||
433 | policy->shared_type = p->shared_type; | ||
434 | /* | ||
435 | * Will let policy->cpus know about dependency only when software | ||
436 | * coordination is required. | ||
437 | */ | ||
438 | if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || | ||
439 | policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { | ||
440 | policy->cpus = p->shared_cpu_map; | ||
441 | } | ||
442 | |||
443 | #ifdef CONFIG_SMP | ||
444 | dmi_check_system(sw_any_bug_dmi_table); | ||
445 | if (bios_with_sw_any_bug && cpus_weight(policy->cpus) == 1) { | ||
446 | policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; | ||
447 | policy->cpus = cpu_core_map[cpu]; | ||
448 | } | ||
449 | #endif | ||
450 | |||
451 | /* verify the acpi_data */ | ||
452 | if (p->state_count <= 1) { | ||
453 | dprintk("No P-States\n"); | ||
454 | result = -ENODEV; | ||
455 | goto err_unreg; | ||
456 | } | ||
457 | |||
458 | if ((p->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) || | ||
459 | (p->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) { | ||
460 | dprintk("Invalid control/status registers (%x - %x)\n", | ||
461 | p->control_register.space_id, p->status_register.space_id); | ||
462 | result = -EIO; | ||
463 | goto err_unreg; | ||
464 | } | ||
465 | |||
466 | for (i=0; i<p->state_count; i++) { | ||
467 | if ((p->states[i].control & INTEL_MSR_RANGE) != | ||
468 | (p->states[i].status & INTEL_MSR_RANGE)) { | ||
469 | dprintk("Different MSR bits in control (%llu) and status (%llu)\n", | ||
470 | p->states[i].control, p->states[i].status); | ||
471 | result = -EINVAL; | ||
472 | goto err_unreg; | ||
473 | } | ||
474 | |||
475 | if (!p->states[i].core_frequency) { | ||
476 | dprintk("Zero core frequency for state %u\n", i); | ||
477 | result = -EINVAL; | ||
478 | goto err_unreg; | ||
479 | } | ||
480 | |||
481 | if (p->states[i].core_frequency > p->states[0].core_frequency) { | ||
482 | dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i, | ||
483 | p->states[i].core_frequency, p->states[0].core_frequency); | ||
484 | p->states[i].core_frequency = 0; | ||
485 | continue; | ||
486 | } | ||
487 | } | ||
488 | |||
489 | centrino_model[cpu] = kzalloc(sizeof(struct cpu_model), GFP_KERNEL); | ||
490 | if (!centrino_model[cpu]) { | ||
491 | result = -ENOMEM; | ||
492 | goto err_unreg; | ||
493 | } | ||
494 | |||
495 | centrino_model[cpu]->model_name=NULL; | ||
496 | centrino_model[cpu]->max_freq = p->states[0].core_frequency * 1000; | ||
497 | centrino_model[cpu]->op_points = kmalloc(sizeof(struct cpufreq_frequency_table) * | ||
498 | (p->state_count + 1), GFP_KERNEL); | ||
499 | if (!centrino_model[cpu]->op_points) { | ||
500 | result = -ENOMEM; | ||
501 | goto err_kfree; | ||
502 | } | ||
503 | |||
504 | for (i=0; i<p->state_count; i++) { | ||
505 | centrino_model[cpu]->op_points[i].index = p->states[i].control & INTEL_MSR_RANGE; | ||
506 | centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000; | ||
507 | dprintk("adding state %i with frequency %u and control value %04x\n", | ||
508 | i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index); | ||
509 | } | ||
510 | centrino_model[cpu]->op_points[p->state_count].frequency = CPUFREQ_TABLE_END; | ||
511 | |||
512 | cur_freq = get_cur_freq(cpu); | ||
513 | |||
514 | for (i=0; i<p->state_count; i++) { | ||
515 | if (!p->states[i].core_frequency) { | ||
516 | dprintk("skipping state %u\n", i); | ||
517 | centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID; | ||
518 | continue; | ||
519 | } | ||
520 | |||
521 | if (extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0) != | ||
522 | (centrino_model[cpu]->op_points[i].frequency)) { | ||
523 | dprintk("Invalid encoded frequency (%u vs. %u)\n", | ||
524 | extract_clock(centrino_model[cpu]->op_points[i].index, cpu, 0), | ||
525 | centrino_model[cpu]->op_points[i].frequency); | ||
526 | result = -EINVAL; | ||
527 | goto err_kfree_all; | ||
528 | } | ||
529 | |||
530 | if (cur_freq == centrino_model[cpu]->op_points[i].frequency) | ||
531 | p->state = i; | ||
532 | } | ||
533 | |||
534 | /* notify BIOS that we exist */ | ||
535 | acpi_processor_notify_smm(THIS_MODULE); | ||
536 | printk("speedstep-centrino with X86_SPEEDSTEP_CENTRINO_ACPI " | ||
537 | "config is deprecated.\n " | ||
538 | "Use X86_ACPI_CPUFREQ (acpi-cpufreq) instead.\n" ); | ||
539 | |||
540 | return 0; | ||
541 | |||
542 | err_kfree_all: | ||
543 | kfree(centrino_model[cpu]->op_points); | ||
544 | err_kfree: | ||
545 | kfree(centrino_model[cpu]); | ||
546 | err_unreg: | ||
547 | acpi_processor_unregister_performance(p, cpu); | ||
548 | dprintk(PFX "invalid ACPI data\n"); | ||
549 | return (result); | ||
550 | } | ||
551 | #else | ||
552 | static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; } | ||
553 | static inline int centrino_cpu_early_init_acpi(void) { return 0; } | ||
554 | #endif | ||
555 | |||
556 | static int centrino_cpu_init(struct cpufreq_policy *policy) | 341 | static int centrino_cpu_init(struct cpufreq_policy *policy) |
557 | { | 342 | { |
558 | struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; | 343 | struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu]; |
@@ -568,27 +353,25 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) | |||
568 | if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC)) | 353 | if (cpu_has(cpu, X86_FEATURE_CONSTANT_TSC)) |
569 | centrino_driver.flags |= CPUFREQ_CONST_LOOPS; | 354 | centrino_driver.flags |= CPUFREQ_CONST_LOOPS; |
570 | 355 | ||
571 | if (centrino_cpu_init_acpi(policy)) { | 356 | if (policy->cpu != 0) |
572 | if (policy->cpu != 0) | 357 | return -ENODEV; |
573 | return -ENODEV; | ||
574 | 358 | ||
575 | for (i = 0; i < N_IDS; i++) | 359 | for (i = 0; i < N_IDS; i++) |
576 | if (centrino_verify_cpu_id(cpu, &cpu_ids[i])) | 360 | if (centrino_verify_cpu_id(cpu, &cpu_ids[i])) |
577 | break; | 361 | break; |
578 | 362 | ||
579 | if (i != N_IDS) | 363 | if (i != N_IDS) |
580 | centrino_cpu[policy->cpu] = &cpu_ids[i]; | 364 | centrino_cpu[policy->cpu] = &cpu_ids[i]; |
581 | 365 | ||
582 | if (!centrino_cpu[policy->cpu]) { | 366 | if (!centrino_cpu[policy->cpu]) { |
583 | dprintk("found unsupported CPU with " | 367 | dprintk("found unsupported CPU with " |
584 | "Enhanced SpeedStep: send /proc/cpuinfo to " | 368 | "Enhanced SpeedStep: send /proc/cpuinfo to " |
585 | MAINTAINER "\n"); | 369 | MAINTAINER "\n"); |
586 | return -ENODEV; | 370 | return -ENODEV; |
587 | } | 371 | } |
588 | 372 | ||
589 | if (centrino_cpu_init_table(policy)) { | 373 | if (centrino_cpu_init_table(policy)) { |
590 | return -ENODEV; | 374 | return -ENODEV; |
591 | } | ||
592 | } | 375 | } |
593 | 376 | ||
594 | /* Check to see if Enhanced SpeedStep is enabled, and try to | 377 | /* Check to see if Enhanced SpeedStep is enabled, and try to |
@@ -634,20 +417,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy) | |||
634 | 417 | ||
635 | cpufreq_frequency_table_put_attr(cpu); | 418 | cpufreq_frequency_table_put_attr(cpu); |
636 | 419 | ||
637 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | ||
638 | if (!centrino_model[cpu]->model_name) { | ||
639 | static struct acpi_processor_performance *p; | ||
640 | |||
641 | if (acpi_perf_data[cpu]) { | ||
642 | p = acpi_perf_data[cpu]; | ||
643 | dprintk("unregistering and freeing ACPI data\n"); | ||
644 | acpi_processor_unregister_performance(p, cpu); | ||
645 | kfree(centrino_model[cpu]->op_points); | ||
646 | kfree(centrino_model[cpu]); | ||
647 | } | ||
648 | } | ||
649 | #endif | ||
650 | |||
651 | centrino_model[cpu] = NULL; | 420 | centrino_model[cpu] = NULL; |
652 | 421 | ||
653 | return 0; | 422 | return 0; |
@@ -849,25 +618,12 @@ static int __init centrino_init(void) | |||
849 | if (!cpu_has(cpu, X86_FEATURE_EST)) | 618 | if (!cpu_has(cpu, X86_FEATURE_EST)) |
850 | return -ENODEV; | 619 | return -ENODEV; |
851 | 620 | ||
852 | centrino_cpu_early_init_acpi(); | ||
853 | |||
854 | return cpufreq_register_driver(¢rino_driver); | 621 | return cpufreq_register_driver(¢rino_driver); |
855 | } | 622 | } |
856 | 623 | ||
857 | static void __exit centrino_exit(void) | 624 | static void __exit centrino_exit(void) |
858 | { | 625 | { |
859 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | ||
860 | unsigned int j; | ||
861 | #endif | ||
862 | |||
863 | cpufreq_unregister_driver(¢rino_driver); | 626 | cpufreq_unregister_driver(¢rino_driver); |
864 | |||
865 | #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI | ||
866 | for_each_possible_cpu(j) { | ||
867 | kfree(acpi_perf_data[j]); | ||
868 | acpi_perf_data[j] = NULL; | ||
869 | } | ||
870 | #endif | ||
871 | } | 627 | } |
872 | 628 | ||
873 | MODULE_AUTHOR ("Jeremy Fitzhardinge <jeremy@goop.org>"); | 629 | MODULE_AUTHOR ("Jeremy Fitzhardinge <jeremy@goop.org>"); |
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index 698f980eb443..a5b2346faf1f 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c | |||
@@ -205,7 +205,6 @@ static unsigned int speedstep_detect_chipset (void) | |||
205 | * host brige. Abort on these systems. | 205 | * host brige. Abort on these systems. |
206 | */ | 206 | */ |
207 | static struct pci_dev *hostbridge; | 207 | static struct pci_dev *hostbridge; |
208 | u8 rev = 0; | ||
209 | 208 | ||
210 | hostbridge = pci_get_subsys(PCI_VENDOR_ID_INTEL, | 209 | hostbridge = pci_get_subsys(PCI_VENDOR_ID_INTEL, |
211 | PCI_DEVICE_ID_INTEL_82815_MC, | 210 | PCI_DEVICE_ID_INTEL_82815_MC, |
@@ -216,8 +215,7 @@ static unsigned int speedstep_detect_chipset (void) | |||
216 | if (!hostbridge) | 215 | if (!hostbridge) |
217 | return 2; /* 2-M */ | 216 | return 2; /* 2-M */ |
218 | 217 | ||
219 | pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev); | 218 | if (hostbridge->revision < 5) { |
220 | if (rev < 5) { | ||
221 | dprintk("hostbridge does not support speedstep\n"); | 219 | dprintk("hostbridge does not support speedstep\n"); |
222 | speedstep_chipset_dev = NULL; | 220 | speedstep_chipset_dev = NULL; |
223 | pci_dev_put(hostbridge); | 221 | pci_dev_put(hostbridge); |
diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c index 7ba7c3abd3a4..1203dc5ab87a 100644 --- a/arch/i386/kernel/cpu/mcheck/therm_throt.c +++ b/arch/i386/kernel/cpu/mcheck/therm_throt.c | |||
@@ -134,19 +134,21 @@ static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb, | |||
134 | int err; | 134 | int err; |
135 | 135 | ||
136 | sys_dev = get_cpu_sysdev(cpu); | 136 | sys_dev = get_cpu_sysdev(cpu); |
137 | mutex_lock(&therm_cpu_lock); | ||
138 | switch (action) { | 137 | switch (action) { |
139 | case CPU_ONLINE: | 138 | case CPU_ONLINE: |
140 | case CPU_ONLINE_FROZEN: | 139 | case CPU_ONLINE_FROZEN: |
140 | mutex_lock(&therm_cpu_lock); | ||
141 | err = thermal_throttle_add_dev(sys_dev); | 141 | err = thermal_throttle_add_dev(sys_dev); |
142 | mutex_unlock(&therm_cpu_lock); | ||
142 | WARN_ON(err); | 143 | WARN_ON(err); |
143 | break; | 144 | break; |
144 | case CPU_DEAD: | 145 | case CPU_DEAD: |
145 | case CPU_DEAD_FROZEN: | 146 | case CPU_DEAD_FROZEN: |
147 | mutex_lock(&therm_cpu_lock); | ||
146 | thermal_throttle_remove_dev(sys_dev); | 148 | thermal_throttle_remove_dev(sys_dev); |
149 | mutex_unlock(&therm_cpu_lock); | ||
147 | break; | 150 | break; |
148 | } | 151 | } |
149 | mutex_unlock(&therm_cpu_lock); | ||
150 | return NOTIFY_OK; | 152 | return NOTIFY_OK; |
151 | } | 153 | } |
152 | 154 | ||
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index 89d91e6cc972..1e31b6caffb1 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c | |||
@@ -29,7 +29,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
29 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 29 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
30 | NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, | 30 | NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, |
31 | NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, | 31 | NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, |
32 | NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow", | 32 | NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", |
33 | "3dnowext", "3dnow", | ||
33 | 34 | ||
34 | /* Transmeta-defined */ | 35 | /* Transmeta-defined */ |
35 | "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, | 36 | "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, |
@@ -40,8 +41,9 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
40 | /* Other (Linux-defined) */ | 41 | /* Other (Linux-defined) */ |
41 | "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", | 42 | "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", |
42 | NULL, NULL, NULL, NULL, | 43 | NULL, NULL, NULL, NULL, |
43 | "constant_tsc", "up", NULL, NULL, NULL, NULL, NULL, NULL, | 44 | "constant_tsc", "up", NULL, "arch_perfmon", |
44 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 45 | "pebs", "bts", NULL, "sync_rdtsc", |
46 | "rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
45 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 47 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
46 | 48 | ||
47 | /* Intel-defined (#2) */ | 49 | /* Intel-defined (#2) */ |
@@ -57,9 +59,16 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
57 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 59 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
58 | 60 | ||
59 | /* AMD-defined (#2) */ | 61 | /* AMD-defined (#2) */ |
60 | "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8legacy", "abm", | 62 | "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8_legacy", |
61 | "sse4a", "misalignsse", | 63 | "altmovcr8", "abm", "sse4a", |
62 | "3dnowprefetch", "osvw", "ibs", NULL, NULL, NULL, NULL, NULL, | 64 | "misalignsse", "3dnowprefetch", |
65 | "osvw", "ibs", NULL, NULL, NULL, NULL, | ||
66 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
67 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
68 | |||
69 | /* Auxiliary (Linux-defined) */ | ||
70 | "ida", NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
71 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
63 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 72 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
64 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | 73 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, |
65 | }; | 74 | }; |
diff --git a/arch/i386/kernel/e820.c b/arch/i386/kernel/e820.c index 9645bb51f76a..fc822a46897a 100644 --- a/arch/i386/kernel/e820.c +++ b/arch/i386/kernel/e820.c | |||
@@ -734,7 +734,7 @@ void __init print_memory_map(char *who) | |||
734 | case E820_NVS: | 734 | case E820_NVS: |
735 | printk("(ACPI NVS)\n"); | 735 | printk("(ACPI NVS)\n"); |
736 | break; | 736 | break; |
737 | default: printk("type %lu\n", e820.map[i].type); | 737 | default: printk("type %u\n", e820.map[i].type); |
738 | break; | 738 | break; |
739 | } | 739 | } |
740 | } | 740 | } |
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index a1808022ea19..2452c6fbe992 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c | |||
@@ -278,7 +278,7 @@ void efi_memmap_walk(efi_freemem_callback_t callback, void *arg) | |||
278 | struct range { | 278 | struct range { |
279 | unsigned long start; | 279 | unsigned long start; |
280 | unsigned long end; | 280 | unsigned long end; |
281 | } prev, curr; | 281 | } uninitialized_var(prev), curr; |
282 | efi_memory_desc_t *md; | 282 | efi_memory_desc_t *md; |
283 | unsigned long start, end; | 283 | unsigned long start, end; |
284 | void *p; | 284 | void *p; |
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 3c3c220488c9..a714d6b43506 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S | |||
@@ -409,8 +409,6 @@ restore_nocheck_notrace: | |||
409 | 1: INTERRUPT_RETURN | 409 | 1: INTERRUPT_RETURN |
410 | .section .fixup,"ax" | 410 | .section .fixup,"ax" |
411 | iret_exc: | 411 | iret_exc: |
412 | TRACE_IRQS_ON | ||
413 | ENABLE_INTERRUPTS(CLBR_NONE) | ||
414 | pushl $0 # no error code | 412 | pushl $0 # no error code |
415 | pushl $do_iret_error | 413 | pushl $do_iret_error |
416 | jmp error_code | 414 | jmp error_code |
@@ -1023,6 +1021,91 @@ ENTRY(kernel_thread_helper) | |||
1023 | CFI_ENDPROC | 1021 | CFI_ENDPROC |
1024 | ENDPROC(kernel_thread_helper) | 1022 | ENDPROC(kernel_thread_helper) |
1025 | 1023 | ||
1024 | #ifdef CONFIG_XEN | ||
1025 | ENTRY(xen_hypervisor_callback) | ||
1026 | CFI_STARTPROC | ||
1027 | pushl $0 | ||
1028 | CFI_ADJUST_CFA_OFFSET 4 | ||
1029 | SAVE_ALL | ||
1030 | TRACE_IRQS_OFF | ||
1031 | |||
1032 | /* Check to see if we got the event in the critical | ||
1033 | region in xen_iret_direct, after we've reenabled | ||
1034 | events and checked for pending events. This simulates | ||
1035 | iret instruction's behaviour where it delivers a | ||
1036 | pending interrupt when enabling interrupts. */ | ||
1037 | movl PT_EIP(%esp),%eax | ||
1038 | cmpl $xen_iret_start_crit,%eax | ||
1039 | jb 1f | ||
1040 | cmpl $xen_iret_end_crit,%eax | ||
1041 | jae 1f | ||
1042 | |||
1043 | call xen_iret_crit_fixup | ||
1044 | |||
1045 | 1: mov %esp, %eax | ||
1046 | call xen_evtchn_do_upcall | ||
1047 | jmp ret_from_intr | ||
1048 | CFI_ENDPROC | ||
1049 | ENDPROC(xen_hypervisor_callback) | ||
1050 | |||
1051 | # Hypervisor uses this for application faults while it executes. | ||
1052 | # We get here for two reasons: | ||
1053 | # 1. Fault while reloading DS, ES, FS or GS | ||
1054 | # 2. Fault while executing IRET | ||
1055 | # Category 1 we fix up by reattempting the load, and zeroing the segment | ||
1056 | # register if the load fails. | ||
1057 | # Category 2 we fix up by jumping to do_iret_error. We cannot use the | ||
1058 | # normal Linux return path in this case because if we use the IRET hypercall | ||
1059 | # to pop the stack frame we end up in an infinite loop of failsafe callbacks. | ||
1060 | # We distinguish between categories by maintaining a status value in EAX. | ||
1061 | ENTRY(xen_failsafe_callback) | ||
1062 | CFI_STARTPROC | ||
1063 | pushl %eax | ||
1064 | CFI_ADJUST_CFA_OFFSET 4 | ||
1065 | movl $1,%eax | ||
1066 | 1: mov 4(%esp),%ds | ||
1067 | 2: mov 8(%esp),%es | ||
1068 | 3: mov 12(%esp),%fs | ||
1069 | 4: mov 16(%esp),%gs | ||
1070 | testl %eax,%eax | ||
1071 | popl %eax | ||
1072 | CFI_ADJUST_CFA_OFFSET -4 | ||
1073 | lea 16(%esp),%esp | ||
1074 | CFI_ADJUST_CFA_OFFSET -16 | ||
1075 | jz 5f | ||
1076 | addl $16,%esp | ||
1077 | jmp iret_exc # EAX != 0 => Category 2 (Bad IRET) | ||
1078 | 5: pushl $0 # EAX == 0 => Category 1 (Bad segment) | ||
1079 | CFI_ADJUST_CFA_OFFSET 4 | ||
1080 | SAVE_ALL | ||
1081 | jmp ret_from_exception | ||
1082 | CFI_ENDPROC | ||
1083 | |||
1084 | .section .fixup,"ax" | ||
1085 | 6: xorl %eax,%eax | ||
1086 | movl %eax,4(%esp) | ||
1087 | jmp 1b | ||
1088 | 7: xorl %eax,%eax | ||
1089 | movl %eax,8(%esp) | ||
1090 | jmp 2b | ||
1091 | 8: xorl %eax,%eax | ||
1092 | movl %eax,12(%esp) | ||
1093 | jmp 3b | ||
1094 | 9: xorl %eax,%eax | ||
1095 | movl %eax,16(%esp) | ||
1096 | jmp 4b | ||
1097 | .previous | ||
1098 | .section __ex_table,"a" | ||
1099 | .align 4 | ||
1100 | .long 1b,6b | ||
1101 | .long 2b,7b | ||
1102 | .long 3b,8b | ||
1103 | .long 4b,9b | ||
1104 | .previous | ||
1105 | ENDPROC(xen_failsafe_callback) | ||
1106 | |||
1107 | #endif /* CONFIG_XEN */ | ||
1108 | |||
1026 | .section .rodata,"a" | 1109 | .section .rodata,"a" |
1027 | #include "syscall_table.S" | 1110 | #include "syscall_table.S" |
1028 | 1111 | ||
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index f74dfc419b56..7c52b222207e 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S | |||
@@ -168,6 +168,12 @@ page_pde_offset = (__PAGE_OFFSET >> 20); | |||
168 | .section .init.text,"ax",@progbits | 168 | .section .init.text,"ax",@progbits |
169 | #endif | 169 | #endif |
170 | 170 | ||
171 | /* Do an early initialization of the fixmap area */ | ||
172 | movl $(swapper_pg_dir - __PAGE_OFFSET), %edx | ||
173 | movl $(swapper_pg_pmd - __PAGE_OFFSET), %eax | ||
174 | addl $0x007, %eax /* 0x007 = PRESENT+RW+USER */ | ||
175 | movl %eax, 4092(%edx) | ||
176 | |||
171 | #ifdef CONFIG_SMP | 177 | #ifdef CONFIG_SMP |
172 | ENTRY(startup_32_smp) | 178 | ENTRY(startup_32_smp) |
173 | cld | 179 | cld |
@@ -504,9 +510,12 @@ ENTRY(_stext) | |||
504 | /* | 510 | /* |
505 | * BSS section | 511 | * BSS section |
506 | */ | 512 | */ |
507 | .section ".bss.page_aligned","w" | 513 | .section ".bss.page_aligned","wa" |
514 | .align PAGE_SIZE_asm | ||
508 | ENTRY(swapper_pg_dir) | 515 | ENTRY(swapper_pg_dir) |
509 | .fill 1024,4,0 | 516 | .fill 1024,4,0 |
517 | ENTRY(swapper_pg_pmd) | ||
518 | .fill 1024,4,0 | ||
510 | ENTRY(empty_zero_page) | 519 | ENTRY(empty_zero_page) |
511 | .fill 4096,1,0 | 520 | .fill 4096,1,0 |
512 | 521 | ||
@@ -530,6 +539,8 @@ fault_msg: | |||
530 | .ascii "Int %d: CR2 %p err %p EIP %p CS %p flags %p\n" | 539 | .ascii "Int %d: CR2 %p err %p EIP %p CS %p flags %p\n" |
531 | .asciz "Stack: %p %p %p %p %p %p %p %p\n" | 540 | .asciz "Stack: %p %p %p %p %p %p %p %p\n" |
532 | 541 | ||
542 | #include "../xen/xen-head.S" | ||
543 | |||
533 | /* | 544 | /* |
534 | * The IDT and GDT 'descriptors' are a strange 48-bit object | 545 | * The IDT and GDT 'descriptors' are a strange 48-bit object |
535 | * only used by the lidt and lgdt instructions. They are not | 546 | * only used by the lidt and lgdt instructions. They are not |
diff --git a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c index cff95d10a4d8..d26fc063a760 100644 --- a/arch/i386/kernel/init_task.c +++ b/arch/i386/kernel/init_task.c | |||
@@ -42,5 +42,5 @@ EXPORT_SYMBOL(init_task); | |||
42 | * per-CPU TSS segments. Threads are completely 'soft' on Linux, | 42 | * per-CPU TSS segments. Threads are completely 'soft' on Linux, |
43 | * no more per-task TSS's. | 43 | * no more per-task TSS's. |
44 | */ | 44 | */ |
45 | DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS; | 45 | DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS; |
46 | 46 | ||
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 7f8b7af2b95f..21db8f56c9a1 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -667,6 +667,7 @@ static int balanced_irq(void *unused) | |||
667 | set_pending_irq(i, cpumask_of_cpu(0)); | 667 | set_pending_irq(i, cpumask_of_cpu(0)); |
668 | } | 668 | } |
669 | 669 | ||
670 | set_freezable(); | ||
670 | for ( ; ; ) { | 671 | for ( ; ; ) { |
671 | time_remaining = schedule_timeout_interruptible(time_remaining); | 672 | time_remaining = schedule_timeout_interruptible(time_remaining); |
672 | try_to_freeze(); | 673 | try_to_freeze(); |
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index d2daf672f4a2..ba44d40b066d 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c | |||
@@ -21,7 +21,7 @@ | |||
21 | #include <asm/apic.h> | 21 | #include <asm/apic.h> |
22 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
23 | 23 | ||
24 | DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp; | 24 | DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); |
25 | EXPORT_PER_CPU_SYMBOL(irq_stat); | 25 | EXPORT_PER_CPU_SYMBOL(irq_stat); |
26 | 26 | ||
27 | DEFINE_PER_CPU(struct pt_regs *, irq_regs); | 27 | DEFINE_PER_CPU(struct pt_regs *, irq_regs); |
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index fba121f7973f..03b7f5584d71 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c | |||
@@ -295,7 +295,7 @@ static unsigned int | |||
295 | last_irq_sums [NR_CPUS], | 295 | last_irq_sums [NR_CPUS], |
296 | alert_counter [NR_CPUS]; | 296 | alert_counter [NR_CPUS]; |
297 | 297 | ||
298 | void touch_nmi_watchdog (void) | 298 | void touch_nmi_watchdog(void) |
299 | { | 299 | { |
300 | if (nmi_watchdog > 0) { | 300 | if (nmi_watchdog > 0) { |
301 | unsigned cpu; | 301 | unsigned cpu; |
@@ -304,8 +304,10 @@ void touch_nmi_watchdog (void) | |||
304 | * Just reset the alert counters, (other CPUs might be | 304 | * Just reset the alert counters, (other CPUs might be |
305 | * spinning on locks we hold): | 305 | * spinning on locks we hold): |
306 | */ | 306 | */ |
307 | for_each_present_cpu (cpu) | 307 | for_each_present_cpu(cpu) { |
308 | alert_counter[cpu] = 0; | 308 | if (alert_counter[cpu]) |
309 | alert_counter[cpu] = 0; | ||
310 | } | ||
309 | } | 311 | } |
310 | 312 | ||
311 | /* | 313 | /* |
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c index faab09abca5e..53f07a8275e3 100644 --- a/arch/i386/kernel/paravirt.c +++ b/arch/i386/kernel/paravirt.c | |||
@@ -228,6 +228,41 @@ static int __init print_banner(void) | |||
228 | } | 228 | } |
229 | core_initcall(print_banner); | 229 | core_initcall(print_banner); |
230 | 230 | ||
231 | static struct resource reserve_ioports = { | ||
232 | .start = 0, | ||
233 | .end = IO_SPACE_LIMIT, | ||
234 | .name = "paravirt-ioport", | ||
235 | .flags = IORESOURCE_IO | IORESOURCE_BUSY, | ||
236 | }; | ||
237 | |||
238 | static struct resource reserve_iomem = { | ||
239 | .start = 0, | ||
240 | .end = -1, | ||
241 | .name = "paravirt-iomem", | ||
242 | .flags = IORESOURCE_MEM | IORESOURCE_BUSY, | ||
243 | }; | ||
244 | |||
245 | /* | ||
246 | * Reserve the whole legacy IO space to prevent any legacy drivers | ||
247 | * from wasting time probing for their hardware. This is a fairly | ||
248 | * brute-force approach to disabling all non-virtual drivers. | ||
249 | * | ||
250 | * Note that this must be called very early to have any effect. | ||
251 | */ | ||
252 | int paravirt_disable_iospace(void) | ||
253 | { | ||
254 | int ret; | ||
255 | |||
256 | ret = request_resource(&ioport_resource, &reserve_ioports); | ||
257 | if (ret == 0) { | ||
258 | ret = request_resource(&iomem_resource, &reserve_iomem); | ||
259 | if (ret) | ||
260 | release_resource(&reserve_ioports); | ||
261 | } | ||
262 | |||
263 | return ret; | ||
264 | } | ||
265 | |||
231 | struct paravirt_ops paravirt_ops = { | 266 | struct paravirt_ops paravirt_ops = { |
232 | .name = "bare hardware", | 267 | .name = "bare hardware", |
233 | .paravirt_enabled = 0, | 268 | .paravirt_enabled = 0, |
@@ -267,7 +302,7 @@ struct paravirt_ops paravirt_ops = { | |||
267 | .write_msr = native_write_msr_safe, | 302 | .write_msr = native_write_msr_safe, |
268 | .read_tsc = native_read_tsc, | 303 | .read_tsc = native_read_tsc, |
269 | .read_pmc = native_read_pmc, | 304 | .read_pmc = native_read_pmc, |
270 | .get_scheduled_cycles = native_read_tsc, | 305 | .sched_clock = native_sched_clock, |
271 | .get_cpu_khz = native_calculate_cpu_khz, | 306 | .get_cpu_khz = native_calculate_cpu_khz, |
272 | .load_tr_desc = native_load_tr_desc, | 307 | .load_tr_desc = native_load_tr_desc, |
273 | .set_ldt = native_set_ldt, | 308 | .set_ldt = native_set_ldt, |
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 06dfa65ad180..6c49acb96982 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
@@ -538,8 +538,31 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) | |||
538 | return 1; | 538 | return 1; |
539 | } | 539 | } |
540 | 540 | ||
541 | static noinline void __switch_to_xtra(struct task_struct *next_p, | 541 | #ifdef CONFIG_SECCOMP |
542 | struct tss_struct *tss) | 542 | void hard_disable_TSC(void) |
543 | { | ||
544 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
545 | } | ||
546 | void disable_TSC(void) | ||
547 | { | ||
548 | preempt_disable(); | ||
549 | if (!test_and_set_thread_flag(TIF_NOTSC)) | ||
550 | /* | ||
551 | * Must flip the CPU state synchronously with | ||
552 | * TIF_NOTSC in the current running context. | ||
553 | */ | ||
554 | hard_disable_TSC(); | ||
555 | preempt_enable(); | ||
556 | } | ||
557 | void hard_enable_TSC(void) | ||
558 | { | ||
559 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
560 | } | ||
561 | #endif /* CONFIG_SECCOMP */ | ||
562 | |||
563 | static noinline void | ||
564 | __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | ||
565 | struct tss_struct *tss) | ||
543 | { | 566 | { |
544 | struct thread_struct *next; | 567 | struct thread_struct *next; |
545 | 568 | ||
@@ -555,6 +578,17 @@ static noinline void __switch_to_xtra(struct task_struct *next_p, | |||
555 | set_debugreg(next->debugreg[7], 7); | 578 | set_debugreg(next->debugreg[7], 7); |
556 | } | 579 | } |
557 | 580 | ||
581 | #ifdef CONFIG_SECCOMP | ||
582 | if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ | ||
583 | test_tsk_thread_flag(next_p, TIF_NOTSC)) { | ||
584 | /* prev and next are different */ | ||
585 | if (test_tsk_thread_flag(next_p, TIF_NOTSC)) | ||
586 | hard_disable_TSC(); | ||
587 | else | ||
588 | hard_enable_TSC(); | ||
589 | } | ||
590 | #endif | ||
591 | |||
558 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | 592 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { |
559 | /* | 593 | /* |
560 | * Disable the bitmap via an invalid offset. We still cache | 594 | * Disable the bitmap via an invalid offset. We still cache |
@@ -586,33 +620,6 @@ static noinline void __switch_to_xtra(struct task_struct *next_p, | |||
586 | } | 620 | } |
587 | 621 | ||
588 | /* | 622 | /* |
589 | * This function selects if the context switch from prev to next | ||
590 | * has to tweak the TSC disable bit in the cr4. | ||
591 | */ | ||
592 | static inline void disable_tsc(struct task_struct *prev_p, | ||
593 | struct task_struct *next_p) | ||
594 | { | ||
595 | struct thread_info *prev, *next; | ||
596 | |||
597 | /* | ||
598 | * gcc should eliminate the ->thread_info dereference if | ||
599 | * has_secure_computing returns 0 at compile time (SECCOMP=n). | ||
600 | */ | ||
601 | prev = task_thread_info(prev_p); | ||
602 | next = task_thread_info(next_p); | ||
603 | |||
604 | if (has_secure_computing(prev) || has_secure_computing(next)) { | ||
605 | /* slow path here */ | ||
606 | if (has_secure_computing(prev) && | ||
607 | !has_secure_computing(next)) { | ||
608 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
609 | } else if (!has_secure_computing(prev) && | ||
610 | has_secure_computing(next)) | ||
611 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
612 | } | ||
613 | } | ||
614 | |||
615 | /* | ||
616 | * switch_to(x,yn) should switch tasks from x to y. | 623 | * switch_to(x,yn) should switch tasks from x to y. |
617 | * | 624 | * |
618 | * We fsave/fwait so that an exception goes off at the right time | 625 | * We fsave/fwait so that an exception goes off at the right time |
@@ -689,11 +696,9 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas | |||
689 | /* | 696 | /* |
690 | * Now maybe handle debug registers and/or IO bitmaps | 697 | * Now maybe handle debug registers and/or IO bitmaps |
691 | */ | 698 | */ |
692 | if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW) | 699 | if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV || |
693 | || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))) | 700 | task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT)) |
694 | __switch_to_xtra(next_p, tss); | 701 | __switch_to_xtra(prev_p, next_p, tss); |
695 | |||
696 | disable_tsc(prev_p, next_p); | ||
697 | 702 | ||
698 | /* | 703 | /* |
699 | * Leave lazy mode, flushing any hypercalls made here. | 704 | * Leave lazy mode, flushing any hypercalls made here. |
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 0c0ceec5de00..0c8f00e69c4d 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c | |||
@@ -164,14 +164,22 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_ | |||
164 | u32 *desc; | 164 | u32 *desc; |
165 | unsigned long base; | 165 | unsigned long base; |
166 | 166 | ||
167 | down(&child->mm->context.sem); | 167 | seg &= ~7UL; |
168 | desc = child->mm->context.ldt + (seg & ~7); | ||
169 | base = (desc[0] >> 16) | ((desc[1] & 0xff) << 16) | (desc[1] & 0xff000000); | ||
170 | 168 | ||
171 | /* 16-bit code segment? */ | 169 | down(&child->mm->context.sem); |
172 | if (!((desc[1] >> 22) & 1)) | 170 | if (unlikely((seg >> 3) >= child->mm->context.size)) |
173 | addr &= 0xffff; | 171 | addr = -1L; /* bogus selector, access would fault */ |
174 | addr += base; | 172 | else { |
173 | desc = child->mm->context.ldt + seg; | ||
174 | base = ((desc[0] >> 16) | | ||
175 | ((desc[1] & 0xff) << 16) | | ||
176 | (desc[1] & 0xff000000)); | ||
177 | |||
178 | /* 16-bit code segment? */ | ||
179 | if (!((desc[1] >> 22) & 1)) | ||
180 | addr &= 0xffff; | ||
181 | addr += base; | ||
182 | } | ||
175 | up(&child->mm->context.sem); | 183 | up(&child->mm->context.sem); |
176 | } | 184 | } |
177 | return addr; | 185 | return addr; |
@@ -358,17 +366,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
358 | switch (request) { | 366 | switch (request) { |
359 | /* when I and D space are separate, these will need to be fixed. */ | 367 | /* when I and D space are separate, these will need to be fixed. */ |
360 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 368 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
361 | case PTRACE_PEEKDATA: { | 369 | case PTRACE_PEEKDATA: |
362 | unsigned long tmp; | 370 | ret = generic_ptrace_peekdata(child, addr, data); |
363 | int copied; | ||
364 | |||
365 | copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); | ||
366 | ret = -EIO; | ||
367 | if (copied != sizeof(tmp)) | ||
368 | break; | ||
369 | ret = put_user(tmp, datap); | ||
370 | break; | 371 | break; |
371 | } | ||
372 | 372 | ||
373 | /* read the word at location addr in the USER area. */ | 373 | /* read the word at location addr in the USER area. */ |
374 | case PTRACE_PEEKUSR: { | 374 | case PTRACE_PEEKUSR: { |
@@ -395,10 +395,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
395 | /* when I and D space are separate, this will have to be fixed. */ | 395 | /* when I and D space are separate, this will have to be fixed. */ |
396 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 396 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
397 | case PTRACE_POKEDATA: | 397 | case PTRACE_POKEDATA: |
398 | ret = 0; | 398 | ret = generic_ptrace_pokedata(child, addr, data); |
399 | if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) | ||
400 | break; | ||
401 | ret = -EIO; | ||
402 | break; | 399 | break; |
403 | 400 | ||
404 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 401 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 698c24fe482e..74871d066c2b 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -102,19 +102,10 @@ static unsigned int highmem_pages = -1; | |||
102 | /* | 102 | /* |
103 | * Setup options | 103 | * Setup options |
104 | */ | 104 | */ |
105 | struct drive_info_struct { char dummy[32]; } drive_info; | ||
106 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \ | ||
107 | defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE) | ||
108 | EXPORT_SYMBOL(drive_info); | ||
109 | #endif | ||
110 | struct screen_info screen_info; | 105 | struct screen_info screen_info; |
111 | EXPORT_SYMBOL(screen_info); | 106 | EXPORT_SYMBOL(screen_info); |
112 | struct apm_info apm_info; | 107 | struct apm_info apm_info; |
113 | EXPORT_SYMBOL(apm_info); | 108 | EXPORT_SYMBOL(apm_info); |
114 | struct sys_desc_table_struct { | ||
115 | unsigned short length; | ||
116 | unsigned char table[0]; | ||
117 | }; | ||
118 | struct edid_info edid_info; | 109 | struct edid_info edid_info; |
119 | EXPORT_SYMBOL_GPL(edid_info); | 110 | EXPORT_SYMBOL_GPL(edid_info); |
120 | struct ist_info ist_info; | 111 | struct ist_info ist_info; |
@@ -134,7 +125,7 @@ unsigned long saved_videomode; | |||
134 | 125 | ||
135 | static char __initdata command_line[COMMAND_LINE_SIZE]; | 126 | static char __initdata command_line[COMMAND_LINE_SIZE]; |
136 | 127 | ||
137 | unsigned char __initdata boot_params[PARAM_SIZE]; | 128 | struct boot_params __initdata boot_params; |
138 | 129 | ||
139 | #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) | 130 | #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) |
140 | struct edd edd; | 131 | struct edd edd; |
@@ -528,7 +519,6 @@ void __init setup_arch(char **cmdline_p) | |||
528 | #endif | 519 | #endif |
529 | 520 | ||
530 | ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); | 521 | ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); |
531 | drive_info = DRIVE_INFO; | ||
532 | screen_info = SCREEN_INFO; | 522 | screen_info = SCREEN_INFO; |
533 | edid_info = EDID_INFO; | 523 | edid_info = EDID_INFO; |
534 | apm_info.bios = APM_BIOS_INFO; | 524 | apm_info.bios = APM_BIOS_INFO; |
@@ -611,6 +601,8 @@ void __init setup_arch(char **cmdline_p) | |||
611 | * NOTE: at this point the bootmem allocator is fully available. | 601 | * NOTE: at this point the bootmem allocator is fully available. |
612 | */ | 602 | */ |
613 | 603 | ||
604 | paravirt_post_allocator_init(); | ||
605 | |||
614 | dmi_scan_machine(); | 606 | dmi_scan_machine(); |
615 | 607 | ||
616 | #ifdef CONFIG_X86_GENERICARCH | 608 | #ifdef CONFIG_X86_GENERICARCH |
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 6299c080f6e2..2d35d8502029 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <asm/mtrr.h> | 23 | #include <asm/mtrr.h> |
24 | #include <asm/tlbflush.h> | 24 | #include <asm/tlbflush.h> |
25 | #include <asm/mmu_context.h> | ||
25 | #include <mach_apic.h> | 26 | #include <mach_apic.h> |
26 | 27 | ||
27 | /* | 28 | /* |
@@ -249,13 +250,13 @@ static unsigned long flush_va; | |||
249 | static DEFINE_SPINLOCK(tlbstate_lock); | 250 | static DEFINE_SPINLOCK(tlbstate_lock); |
250 | 251 | ||
251 | /* | 252 | /* |
252 | * We cannot call mmdrop() because we are in interrupt context, | 253 | * We cannot call mmdrop() because we are in interrupt context, |
253 | * instead update mm->cpu_vm_mask. | 254 | * instead update mm->cpu_vm_mask. |
254 | * | 255 | * |
255 | * We need to reload %cr3 since the page tables may be going | 256 | * We need to reload %cr3 since the page tables may be going |
256 | * away from under us.. | 257 | * away from under us.. |
257 | */ | 258 | */ |
258 | static inline void leave_mm (unsigned long cpu) | 259 | void leave_mm(unsigned long cpu) |
259 | { | 260 | { |
260 | if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) | 261 | if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) |
261 | BUG(); | 262 | BUG(); |
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 88baed1e7e83..5910d3fac561 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
@@ -148,7 +148,7 @@ void __init smp_alloc_memory(void) | |||
148 | * a given CPU | 148 | * a given CPU |
149 | */ | 149 | */ |
150 | 150 | ||
151 | static void __cpuinit smp_store_cpu_info(int id) | 151 | void __cpuinit smp_store_cpu_info(int id) |
152 | { | 152 | { |
153 | struct cpuinfo_x86 *c = cpu_data + id; | 153 | struct cpuinfo_x86 *c = cpu_data + id; |
154 | 154 | ||
@@ -308,8 +308,7 @@ cpumask_t cpu_coregroup_map(int cpu) | |||
308 | /* representing cpus for which sibling maps can be computed */ | 308 | /* representing cpus for which sibling maps can be computed */ |
309 | static cpumask_t cpu_sibling_setup_map; | 309 | static cpumask_t cpu_sibling_setup_map; |
310 | 310 | ||
311 | static inline void | 311 | void set_cpu_sibling_map(int cpu) |
312 | set_cpu_sibling_map(int cpu) | ||
313 | { | 312 | { |
314 | int i; | 313 | int i; |
315 | struct cpuinfo_x86 *c = cpu_data; | 314 | struct cpuinfo_x86 *c = cpu_data; |
@@ -941,17 +940,6 @@ exit: | |||
941 | } | 940 | } |
942 | #endif | 941 | #endif |
943 | 942 | ||
944 | static void smp_tune_scheduling(void) | ||
945 | { | ||
946 | if (cpu_khz) { | ||
947 | /* cache size in kB */ | ||
948 | long cachesize = boot_cpu_data.x86_cache_size; | ||
949 | |||
950 | if (cachesize > 0) | ||
951 | max_cache_size = cachesize * 1024; | ||
952 | } | ||
953 | } | ||
954 | |||
955 | /* | 943 | /* |
956 | * Cycle through the processors sending APIC IPIs to boot each. | 944 | * Cycle through the processors sending APIC IPIs to boot each. |
957 | */ | 945 | */ |
@@ -980,7 +968,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus) | |||
980 | x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; | 968 | x86_cpu_to_apicid[0] = boot_cpu_physical_apicid; |
981 | 969 | ||
982 | current_thread_info()->cpu = 0; | 970 | current_thread_info()->cpu = 0; |
983 | smp_tune_scheduling(); | ||
984 | 971 | ||
985 | set_cpu_sibling_map(0); | 972 | set_cpu_sibling_map(0); |
986 | 973 | ||
@@ -1156,8 +1143,7 @@ void __init native_smp_prepare_boot_cpu(void) | |||
1156 | } | 1143 | } |
1157 | 1144 | ||
1158 | #ifdef CONFIG_HOTPLUG_CPU | 1145 | #ifdef CONFIG_HOTPLUG_CPU |
1159 | static void | 1146 | void remove_siblinginfo(int cpu) |
1160 | remove_siblinginfo(int cpu) | ||
1161 | { | 1147 | { |
1162 | int sibling; | 1148 | int sibling; |
1163 | struct cpuinfo_x86 *c = cpu_data; | 1149 | struct cpuinfo_x86 *c = cpu_data; |
diff --git a/arch/i386/kernel/smpcommon.c b/arch/i386/kernel/smpcommon.c index 1868ae18eb4d..bbfe85a0f699 100644 --- a/arch/i386/kernel/smpcommon.c +++ b/arch/i386/kernel/smpcommon.c | |||
@@ -47,7 +47,7 @@ int smp_call_function(void (*func) (void *info), void *info, int nonatomic, | |||
47 | EXPORT_SYMBOL(smp_call_function); | 47 | EXPORT_SYMBOL(smp_call_function); |
48 | 48 | ||
49 | /** | 49 | /** |
50 | * smp_call_function_single - Run a function on another CPU | 50 | * smp_call_function_single - Run a function on a specific CPU |
51 | * @cpu: The target CPU. Cannot be the calling CPU. | 51 | * @cpu: The target CPU. Cannot be the calling CPU. |
52 | * @func: The function to run. This must be fast and non-blocking. | 52 | * @func: The function to run. This must be fast and non-blocking. |
53 | * @info: An arbitrary pointer to pass to the function. | 53 | * @info: An arbitrary pointer to pass to the function. |
@@ -66,9 +66,11 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, | |||
66 | int ret; | 66 | int ret; |
67 | int me = get_cpu(); | 67 | int me = get_cpu(); |
68 | if (cpu == me) { | 68 | if (cpu == me) { |
69 | WARN_ON(1); | 69 | local_irq_disable(); |
70 | func(info); | ||
71 | local_irq_enable(); | ||
70 | put_cpu(); | 72 | put_cpu(); |
71 | return -EBUSY; | 73 | return 0; |
72 | } | 74 | } |
73 | 75 | ||
74 | ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait); | 76 | ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait); |
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index bf6adce52267..8344c70adf61 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S | |||
@@ -323,3 +323,4 @@ ENTRY(sys_call_table) | |||
323 | .long sys_signalfd | 323 | .long sys_signalfd |
324 | .long sys_timerfd | 324 | .long sys_timerfd |
325 | .long sys_eventfd | 325 | .long sys_eventfd |
326 | .long sys_fallocate | ||
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 90da0575fcff..3e7753c78b9b 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -41,6 +41,10 @@ | |||
41 | #include <linux/mca.h> | 41 | #include <linux/mca.h> |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | #if defined(CONFIG_EDAC) | ||
45 | #include <linux/edac.h> | ||
46 | #endif | ||
47 | |||
44 | #include <asm/processor.h> | 48 | #include <asm/processor.h> |
45 | #include <asm/system.h> | 49 | #include <asm/system.h> |
46 | #include <asm/io.h> | 50 | #include <asm/io.h> |
@@ -390,7 +394,7 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
390 | unsigned long esp; | 394 | unsigned long esp; |
391 | unsigned short ss; | 395 | unsigned short ss; |
392 | 396 | ||
393 | report_bug(regs->eip); | 397 | report_bug(regs->eip, regs); |
394 | 398 | ||
395 | printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); | 399 | printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); |
396 | #ifdef CONFIG_PREEMPT | 400 | #ifdef CONFIG_PREEMPT |
@@ -433,6 +437,7 @@ void die(const char * str, struct pt_regs * regs, long err) | |||
433 | 437 | ||
434 | bust_spinlocks(0); | 438 | bust_spinlocks(0); |
435 | die.lock_owner = -1; | 439 | die.lock_owner = -1; |
440 | add_taint(TAINT_DIE); | ||
436 | spin_unlock_irqrestore(&die.lock, flags); | 441 | spin_unlock_irqrestore(&die.lock, flags); |
437 | 442 | ||
438 | if (!regs) | 443 | if (!regs) |
@@ -517,10 +522,12 @@ fastcall void do_##name(struct pt_regs * regs, long error_code) \ | |||
517 | do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \ | 522 | do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \ |
518 | } | 523 | } |
519 | 524 | ||
520 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ | 525 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \ |
521 | fastcall void do_##name(struct pt_regs * regs, long error_code) \ | 526 | fastcall void do_##name(struct pt_regs * regs, long error_code) \ |
522 | { \ | 527 | { \ |
523 | siginfo_t info; \ | 528 | siginfo_t info; \ |
529 | if (irq) \ | ||
530 | local_irq_enable(); \ | ||
524 | info.si_signo = signr; \ | 531 | info.si_signo = signr; \ |
525 | info.si_errno = 0; \ | 532 | info.si_errno = 0; \ |
526 | info.si_code = sicode; \ | 533 | info.si_code = sicode; \ |
@@ -560,13 +567,13 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) | |||
560 | #endif | 567 | #endif |
561 | DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) | 568 | DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) |
562 | DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) | 569 | DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) |
563 | DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip) | 570 | DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip, 0) |
564 | DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) | 571 | DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) |
565 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) | 572 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) |
566 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) | 573 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) |
567 | DO_ERROR(12, SIGBUS, "stack segment", stack_segment) | 574 | DO_ERROR(12, SIGBUS, "stack segment", stack_segment) |
568 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) | 575 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0) |
569 | DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0) | 576 | DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1) |
570 | 577 | ||
571 | fastcall void __kprobes do_general_protection(struct pt_regs * regs, | 578 | fastcall void __kprobes do_general_protection(struct pt_regs * regs, |
572 | long error_code) | 579 | long error_code) |
@@ -635,6 +642,14 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs) | |||
635 | printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on " | 642 | printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on " |
636 | "CPU %d.\n", reason, smp_processor_id()); | 643 | "CPU %d.\n", reason, smp_processor_id()); |
637 | printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n"); | 644 | printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n"); |
645 | |||
646 | #if defined(CONFIG_EDAC) | ||
647 | if(edac_handler_set()) { | ||
648 | edac_atomic_assert_error(); | ||
649 | return; | ||
650 | } | ||
651 | #endif | ||
652 | |||
638 | if (panic_on_unrecovered_nmi) | 653 | if (panic_on_unrecovered_nmi) |
639 | panic("NMI: Not continuing"); | 654 | panic("NMI: Not continuing"); |
640 | 655 | ||
@@ -1053,6 +1068,7 @@ asmlinkage void math_state_restore(void) | |||
1053 | thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ | 1068 | thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ |
1054 | tsk->fpu_counter++; | 1069 | tsk->fpu_counter++; |
1055 | } | 1070 | } |
1071 | EXPORT_SYMBOL_GPL(math_state_restore); | ||
1056 | 1072 | ||
1057 | #ifndef CONFIG_MATH_EMULATION | 1073 | #ifndef CONFIG_MATH_EMULATION |
1058 | 1074 | ||
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c index f64b81f3033b..debd7dbb4158 100644 --- a/arch/i386/kernel/tsc.c +++ b/arch/i386/kernel/tsc.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * See comments there for proper credits. | 4 | * See comments there for proper credits. |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/sched.h> | ||
7 | #include <linux/clocksource.h> | 8 | #include <linux/clocksource.h> |
8 | #include <linux/workqueue.h> | 9 | #include <linux/workqueue.h> |
9 | #include <linux/cpufreq.h> | 10 | #include <linux/cpufreq.h> |
@@ -26,6 +27,7 @@ static int tsc_enabled; | |||
26 | * an extra value to store the TSC freq | 27 | * an extra value to store the TSC freq |
27 | */ | 28 | */ |
28 | unsigned int tsc_khz; | 29 | unsigned int tsc_khz; |
30 | EXPORT_SYMBOL_GPL(tsc_khz); | ||
29 | 31 | ||
30 | int tsc_disable; | 32 | int tsc_disable; |
31 | 33 | ||
@@ -57,10 +59,11 @@ __setup("notsc", tsc_setup); | |||
57 | */ | 59 | */ |
58 | static int tsc_unstable; | 60 | static int tsc_unstable; |
59 | 61 | ||
60 | static inline int check_tsc_unstable(void) | 62 | int check_tsc_unstable(void) |
61 | { | 63 | { |
62 | return tsc_unstable; | 64 | return tsc_unstable; |
63 | } | 65 | } |
66 | EXPORT_SYMBOL_GPL(check_tsc_unstable); | ||
64 | 67 | ||
65 | /* Accellerators for sched_clock() | 68 | /* Accellerators for sched_clock() |
66 | * convert from cycles(64bits) => nanoseconds (64bits) | 69 | * convert from cycles(64bits) => nanoseconds (64bits) |
@@ -83,7 +86,7 @@ static inline int check_tsc_unstable(void) | |||
83 | * | 86 | * |
84 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" | 87 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" |
85 | */ | 88 | */ |
86 | static unsigned long cyc2ns_scale __read_mostly; | 89 | unsigned long cyc2ns_scale __read_mostly; |
87 | 90 | ||
88 | #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ | 91 | #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ |
89 | 92 | ||
@@ -92,32 +95,44 @@ static inline void set_cyc2ns_scale(unsigned long cpu_khz) | |||
92 | cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; | 95 | cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; |
93 | } | 96 | } |
94 | 97 | ||
95 | static inline unsigned long long cycles_2_ns(unsigned long long cyc) | ||
96 | { | ||
97 | return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; | ||
98 | } | ||
99 | |||
100 | /* | 98 | /* |
101 | * Scheduler clock - returns current time in nanosec units. | 99 | * Scheduler clock - returns current time in nanosec units. |
102 | */ | 100 | */ |
103 | unsigned long long sched_clock(void) | 101 | unsigned long long native_sched_clock(void) |
104 | { | 102 | { |
105 | unsigned long long this_offset; | 103 | unsigned long long this_offset; |
106 | 104 | ||
107 | /* | 105 | /* |
108 | * Fall back to jiffies if there's no TSC available: | 106 | * Fall back to jiffies if there's no TSC available: |
107 | * ( But note that we still use it if the TSC is marked | ||
108 | * unstable. We do this because unlike Time Of Day, | ||
109 | * the scheduler clock tolerates small errors and it's | ||
110 | * very important for it to be as fast as the platform | ||
111 | * can achive it. ) | ||
109 | */ | 112 | */ |
110 | if (unlikely(!tsc_enabled)) | 113 | if (unlikely(!tsc_enabled && !tsc_unstable)) |
111 | /* No locking but a rare wrong value is not a big deal: */ | 114 | /* No locking but a rare wrong value is not a big deal: */ |
112 | return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ); | 115 | return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ); |
113 | 116 | ||
114 | /* read the Time Stamp Counter: */ | 117 | /* read the Time Stamp Counter: */ |
115 | get_scheduled_cycles(this_offset); | 118 | rdtscll(this_offset); |
116 | 119 | ||
117 | /* return the value in ns */ | 120 | /* return the value in ns */ |
118 | return cycles_2_ns(this_offset); | 121 | return cycles_2_ns(this_offset); |
119 | } | 122 | } |
120 | 123 | ||
124 | /* We need to define a real function for sched_clock, to override the | ||
125 | weak default version */ | ||
126 | #ifdef CONFIG_PARAVIRT | ||
127 | unsigned long long sched_clock(void) | ||
128 | { | ||
129 | return paravirt_sched_clock(); | ||
130 | } | ||
131 | #else | ||
132 | unsigned long long sched_clock(void) | ||
133 | __attribute__((alias("native_sched_clock"))); | ||
134 | #endif | ||
135 | |||
121 | unsigned long native_calculate_cpu_khz(void) | 136 | unsigned long native_calculate_cpu_khz(void) |
122 | { | 137 | { |
123 | unsigned long long start, end; | 138 | unsigned long long start, end; |
@@ -277,6 +292,7 @@ static struct clocksource clocksource_tsc = { | |||
277 | 292 | ||
278 | void mark_tsc_unstable(char *reason) | 293 | void mark_tsc_unstable(char *reason) |
279 | { | 294 | { |
295 | sched_clock_unstable_event(); | ||
280 | if (!tsc_unstable) { | 296 | if (!tsc_unstable) { |
281 | tsc_unstable = 1; | 297 | tsc_unstable = 1; |
282 | tsc_enabled = 0; | 298 | tsc_enabled = 0; |
diff --git a/arch/i386/kernel/verify_cpu.S b/arch/i386/kernel/verify_cpu.S deleted file mode 100644 index f1d1eacf4ab0..000000000000 --- a/arch/i386/kernel/verify_cpu.S +++ /dev/null | |||
@@ -1,94 +0,0 @@ | |||
1 | /* Check if CPU has some minimum CPUID bits | ||
2 | This runs in 16bit mode so that the caller can still use the BIOS | ||
3 | to output errors on the screen */ | ||
4 | #include <asm/cpufeature.h> | ||
5 | #include <asm/msr.h> | ||
6 | |||
7 | verify_cpu: | ||
8 | pushfl # Save caller passed flags | ||
9 | pushl $0 # Kill any dangerous flags | ||
10 | popfl | ||
11 | |||
12 | #if CONFIG_X86_MINIMUM_CPU_MODEL >= 4 | ||
13 | pushfl | ||
14 | pop %eax | ||
15 | orl $(1<<18),%eax # try setting AC | ||
16 | push %eax | ||
17 | popfl | ||
18 | pushfl | ||
19 | popl %eax | ||
20 | testl $(1<<18),%eax | ||
21 | jz bad | ||
22 | #endif | ||
23 | #if REQUIRED_MASK1 != 0 | ||
24 | pushfl # standard way to check for cpuid | ||
25 | popl %eax | ||
26 | movl %eax,%ebx | ||
27 | xorl $0x200000,%eax | ||
28 | pushl %eax | ||
29 | popfl | ||
30 | pushfl | ||
31 | popl %eax | ||
32 | cmpl %eax,%ebx | ||
33 | pushfl # standard way to check for cpuid | ||
34 | popl %eax | ||
35 | movl %eax,%ebx | ||
36 | xorl $0x200000,%eax | ||
37 | pushl %eax | ||
38 | popfl | ||
39 | pushfl | ||
40 | popl %eax | ||
41 | cmpl %eax,%ebx | ||
42 | jz bad # REQUIRED_MASK1 != 0 requires CPUID | ||
43 | |||
44 | movl $0x0,%eax # See if cpuid 1 is implemented | ||
45 | cpuid | ||
46 | cmpl $0x1,%eax | ||
47 | jb bad # no cpuid 1 | ||
48 | |||
49 | #if REQUIRED_MASK1 & NEED_CMPXCHG64 | ||
50 | /* Some VIA C3s need magic MSRs to enable CX64. Do this here */ | ||
51 | cmpl $0x746e6543,%ebx # Cent | ||
52 | jne 1f | ||
53 | cmpl $0x48727561,%edx # aurH | ||
54 | jne 1f | ||
55 | cmpl $0x736c7561,%ecx # auls | ||
56 | jne 1f | ||
57 | movl $1,%eax # check model | ||
58 | cpuid | ||
59 | movl %eax,%ebx | ||
60 | shr $8,%ebx | ||
61 | andl $0xf,%ebx | ||
62 | cmp $6,%ebx # check family == 6 | ||
63 | jne 1f | ||
64 | shr $4,%eax | ||
65 | andl $0xf,%eax | ||
66 | cmpl $6,%eax # check model >= 6 | ||
67 | jb 1f | ||
68 | # assume models >= 6 all support this MSR | ||
69 | movl $MSR_VIA_FCR,%ecx | ||
70 | rdmsr | ||
71 | orl $((1<<1)|(1<<7)),%eax # enable CMPXCHG64 and PGE | ||
72 | wrmsr | ||
73 | 1: | ||
74 | #endif | ||
75 | movl $0x1,%eax # Does the cpu have what it takes | ||
76 | cpuid | ||
77 | |||
78 | #if CONFIG_X86_MINIMUM_CPU_MODEL > 4 | ||
79 | #error add proper model checking here | ||
80 | #endif | ||
81 | |||
82 | andl $REQUIRED_MASK1,%edx | ||
83 | xorl $REQUIRED_MASK1,%edx | ||
84 | jnz bad | ||
85 | #endif /* REQUIRED_MASK1 */ | ||
86 | |||
87 | popfl | ||
88 | xor %eax,%eax | ||
89 | ret | ||
90 | |||
91 | bad: | ||
92 | popfl | ||
93 | movl $1,%eax | ||
94 | ret | ||
diff --git a/arch/i386/kernel/vmi.c b/arch/i386/kernel/vmi.c index c12720d7cbc5..72042bb7ec94 100644 --- a/arch/i386/kernel/vmi.c +++ b/arch/i386/kernel/vmi.c | |||
@@ -362,7 +362,7 @@ static void *vmi_kmap_atomic_pte(struct page *page, enum km_type type) | |||
362 | } | 362 | } |
363 | #endif | 363 | #endif |
364 | 364 | ||
365 | static void vmi_allocate_pt(u32 pfn) | 365 | static void vmi_allocate_pt(struct mm_struct *mm, u32 pfn) |
366 | { | 366 | { |
367 | vmi_set_page_type(pfn, VMI_PAGE_L1); | 367 | vmi_set_page_type(pfn, VMI_PAGE_L1); |
368 | vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0); | 368 | vmi_ops.allocate_page(pfn, VMI_PAGE_L1, 0, 0, 0); |
@@ -891,7 +891,7 @@ static inline int __init activate_vmi(void) | |||
891 | paravirt_ops.setup_boot_clock = vmi_time_bsp_init; | 891 | paravirt_ops.setup_boot_clock = vmi_time_bsp_init; |
892 | paravirt_ops.setup_secondary_clock = vmi_time_ap_init; | 892 | paravirt_ops.setup_secondary_clock = vmi_time_ap_init; |
893 | #endif | 893 | #endif |
894 | paravirt_ops.get_scheduled_cycles = vmi_get_sched_cycles; | 894 | paravirt_ops.sched_clock = vmi_sched_clock; |
895 | paravirt_ops.get_cpu_khz = vmi_cpu_khz; | 895 | paravirt_ops.get_cpu_khz = vmi_cpu_khz; |
896 | 896 | ||
897 | /* We have true wallclock functions; disable CMOS clock sync */ | 897 | /* We have true wallclock functions; disable CMOS clock sync */ |
diff --git a/arch/i386/kernel/vmiclock.c b/arch/i386/kernel/vmiclock.c index 26a37f8a8762..f9b845f4e692 100644 --- a/arch/i386/kernel/vmiclock.c +++ b/arch/i386/kernel/vmiclock.c | |||
@@ -64,10 +64,10 @@ int vmi_set_wallclock(unsigned long now) | |||
64 | return 0; | 64 | return 0; |
65 | } | 65 | } |
66 | 66 | ||
67 | /* paravirt_ops.get_scheduled_cycles = vmi_get_sched_cycles */ | 67 | /* paravirt_ops.sched_clock = vmi_sched_clock */ |
68 | unsigned long long vmi_get_sched_cycles(void) | 68 | unsigned long long vmi_sched_clock(void) |
69 | { | 69 | { |
70 | return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE); | 70 | return cycles_2_ns(vmi_timer_ops.get_cycle_counter(VMI_CYCLES_AVAILABLE)); |
71 | } | 71 | } |
72 | 72 | ||
73 | /* paravirt_ops.get_cpu_khz = vmi_cpu_khz */ | 73 | /* paravirt_ops.get_cpu_khz = vmi_cpu_khz */ |
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index aa87b06c7c82..7d72cce00529 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S | |||
@@ -60,7 +60,9 @@ SECTIONS | |||
60 | __stop___ex_table = .; | 60 | __stop___ex_table = .; |
61 | } | 61 | } |
62 | 62 | ||
63 | BUG_TABLE | 63 | NOTES :text :note |
64 | |||
65 | BUG_TABLE :text | ||
64 | 66 | ||
65 | . = ALIGN(4); | 67 | . = ALIGN(4); |
66 | .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { | 68 | .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) { |
@@ -88,6 +90,7 @@ SECTIONS | |||
88 | 90 | ||
89 | . = ALIGN(4096); | 91 | . = ALIGN(4096); |
90 | .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { | 92 | .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { |
93 | *(.data.page_aligned) | ||
91 | *(.data.idt) | 94 | *(.data.idt) |
92 | } | 95 | } |
93 | 96 | ||
@@ -180,6 +183,7 @@ SECTIONS | |||
180 | .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { | 183 | .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { |
181 | __per_cpu_start = .; | 184 | __per_cpu_start = .; |
182 | *(.data.percpu) | 185 | *(.data.percpu) |
186 | *(.data.percpu.shared_aligned) | ||
183 | __per_cpu_end = .; | 187 | __per_cpu_end = .; |
184 | } | 188 | } |
185 | . = ALIGN(4096); | 189 | . = ALIGN(4096); |
@@ -206,6 +210,4 @@ SECTIONS | |||
206 | STABS_DEBUG | 210 | STABS_DEBUG |
207 | 211 | ||
208 | DWARF_DEBUG | 212 | DWARF_DEBUG |
209 | |||
210 | NOTES | ||
211 | } | 213 | } |
diff --git a/arch/i386/kernel/vsyscall-note.S b/arch/i386/kernel/vsyscall-note.S index d4b5be4f3d5f..271f16a8ca01 100644 --- a/arch/i386/kernel/vsyscall-note.S +++ b/arch/i386/kernel/vsyscall-note.S | |||
@@ -3,23 +3,40 @@ | |||
3 | * Here we can supply some information useful to userland. | 3 | * Here we can supply some information useful to userland. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/uts.h> | ||
7 | #include <linux/version.h> | 6 | #include <linux/version.h> |
7 | #include <linux/elfnote.h> | ||
8 | 8 | ||
9 | #define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type) \ | 9 | /* Ideally this would use UTS_NAME, but using a quoted string here |
10 | .section name, flags; \ | 10 | doesn't work. Remember to change this when changing the |
11 | .balign 4; \ | 11 | kernel's name. */ |
12 | .long 1f - 0f; /* name length */ \ | 12 | ELFNOTE_START(Linux, 0, "a") |
13 | .long 3f - 2f; /* data length */ \ | 13 | .long LINUX_VERSION_CODE |
14 | .long type; /* note type */ \ | 14 | ELFNOTE_END |
15 | 0: .asciz vendor; /* vendor name */ \ | ||
16 | 1: .balign 4; \ | ||
17 | 2: | ||
18 | 15 | ||
19 | #define ASM_ELF_NOTE_END \ | 16 | #ifdef CONFIG_XEN |
20 | 3: .balign 4; /* pad out section */ \ | ||
21 | .previous | ||
22 | 17 | ||
23 | ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0) | 18 | /* |
24 | .long LINUX_VERSION_CODE | 19 | * Add a special note telling glibc's dynamic linker a fake hardware |
25 | ASM_ELF_NOTE_END | 20 | * flavor that it will use to choose the search path for libraries in the |
21 | * same way it uses real hardware capabilities like "mmx". | ||
22 | * We supply "nosegneg" as the fake capability, to indicate that we | ||
23 | * do not like negative offsets in instructions using segment overrides, | ||
24 | * since we implement those inefficiently. This makes it possible to | ||
25 | * install libraries optimized to avoid those access patterns in someplace | ||
26 | * like /lib/i686/tls/nosegneg. Note that an /etc/ld.so.conf.d/file | ||
27 | * corresponding to the bits here is needed to make ldconfig work right. | ||
28 | * It should contain: | ||
29 | * hwcap 1 nosegneg | ||
30 | * to match the mapping of bit to name that we give here. | ||
31 | */ | ||
32 | |||
33 | /* Bit used for the pseudo-hwcap for non-negative segments. We use | ||
34 | bit 1 to avoid bugs in some versions of glibc when bit 0 is | ||
35 | used; the choice is otherwise arbitrary. */ | ||
36 | #define VDSO_NOTE_NONEGSEG_BIT 1 | ||
37 | |||
38 | ELFNOTE_START(GNU, 2, "a") | ||
39 | .long 1, 1<<VDSO_NOTE_NONEGSEG_BIT /* ncaps, mask */ | ||
40 | .byte VDSO_NOTE_NONEGSEG_BIT; .asciz "nosegneg" /* bit, name */ | ||
41 | ELFNOTE_END | ||
42 | #endif | ||