diff options
24 files changed, 594 insertions, 277 deletions
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 0cd82d068613..630e623f61e0 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h | |||
@@ -161,6 +161,7 @@ | |||
161 | */ | 161 | */ |
162 | #define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */ | 162 | #define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */ |
163 | #define X86_FEATURE_ARAT (7*32+ 1) /* Always Running APIC Timer */ | 163 | #define X86_FEATURE_ARAT (7*32+ 1) /* Always Running APIC Timer */ |
164 | #define X86_FEATURE_CPB (7*32+ 2) /* AMD Core Performance Boost */ | ||
164 | 165 | ||
165 | /* Virtualization flags: Linux defined */ | 166 | /* Virtualization flags: Linux defined */ |
166 | #define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ | 167 | #define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ |
diff --git a/arch/x86/include/asm/hyperv.h b/arch/x86/include/asm/hyperv.h index e153a2b3889a..5df477ac3af7 100644 --- a/arch/x86/include/asm/hyperv.h +++ b/arch/x86/include/asm/hyperv.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef _ASM_X86_KVM_HYPERV_H | 1 | #ifndef _ASM_X86_HYPERV_H |
2 | #define _ASM_X86_KVM_HYPERV_H | 2 | #define _ASM_X86_HYPERV_H |
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | 5 | ||
@@ -14,6 +14,10 @@ | |||
14 | #define HYPERV_CPUID_ENLIGHTMENT_INFO 0x40000004 | 14 | #define HYPERV_CPUID_ENLIGHTMENT_INFO 0x40000004 |
15 | #define HYPERV_CPUID_IMPLEMENT_LIMITS 0x40000005 | 15 | #define HYPERV_CPUID_IMPLEMENT_LIMITS 0x40000005 |
16 | 16 | ||
17 | #define HYPERV_HYPERVISOR_PRESENT_BIT 0x80000000 | ||
18 | #define HYPERV_CPUID_MIN 0x40000005 | ||
19 | #define HYPERV_CPUID_MAX 0x4000ffff | ||
20 | |||
17 | /* | 21 | /* |
18 | * Feature identification. EAX indicates which features are available | 22 | * Feature identification. EAX indicates which features are available |
19 | * to the partition based upon the current partition privileges. | 23 | * to the partition based upon the current partition privileges. |
@@ -129,6 +133,9 @@ | |||
129 | /* MSR used to provide vcpu index */ | 133 | /* MSR used to provide vcpu index */ |
130 | #define HV_X64_MSR_VP_INDEX 0x40000002 | 134 | #define HV_X64_MSR_VP_INDEX 0x40000002 |
131 | 135 | ||
136 | /* MSR used to read the per-partition time reference counter */ | ||
137 | #define HV_X64_MSR_TIME_REF_COUNT 0x40000020 | ||
138 | |||
132 | /* Define the virtual APIC registers */ | 139 | /* Define the virtual APIC registers */ |
133 | #define HV_X64_MSR_EOI 0x40000070 | 140 | #define HV_X64_MSR_EOI 0x40000070 |
134 | #define HV_X64_MSR_ICR 0x40000071 | 141 | #define HV_X64_MSR_ICR 0x40000071 |
diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h index b78c0941e422..70abda7058c8 100644 --- a/arch/x86/include/asm/hypervisor.h +++ b/arch/x86/include/asm/hypervisor.h | |||
@@ -17,10 +17,33 @@ | |||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * | 18 | * |
19 | */ | 19 | */ |
20 | #ifndef ASM_X86__HYPERVISOR_H | 20 | #ifndef _ASM_X86_HYPERVISOR_H |
21 | #define ASM_X86__HYPERVISOR_H | 21 | #define _ASM_X86_HYPERVISOR_H |
22 | 22 | ||
23 | extern void init_hypervisor(struct cpuinfo_x86 *c); | 23 | extern void init_hypervisor(struct cpuinfo_x86 *c); |
24 | extern void init_hypervisor_platform(void); | 24 | extern void init_hypervisor_platform(void); |
25 | 25 | ||
26 | /* | ||
27 | * x86 hypervisor information | ||
28 | */ | ||
29 | struct hypervisor_x86 { | ||
30 | /* Hypervisor name */ | ||
31 | const char *name; | ||
32 | |||
33 | /* Detection routine */ | ||
34 | bool (*detect)(void); | ||
35 | |||
36 | /* Adjust CPU feature bits (run once per CPU) */ | ||
37 | void (*set_cpu_features)(struct cpuinfo_x86 *); | ||
38 | |||
39 | /* Platform setup (run once per boot) */ | ||
40 | void (*init_platform)(void); | ||
41 | }; | ||
42 | |||
43 | extern const struct hypervisor_x86 *x86_hyper; | ||
44 | |||
45 | /* Recognized hypervisors */ | ||
46 | extern const struct hypervisor_x86 x86_hyper_vmware; | ||
47 | extern const struct hypervisor_x86 x86_hyper_ms_hyperv; | ||
48 | |||
26 | #endif | 49 | #endif |
diff --git a/arch/x86/include/asm/k8.h b/arch/x86/include/asm/k8.h index f70e60071fe8..af00bd1d2089 100644 --- a/arch/x86/include/asm/k8.h +++ b/arch/x86/include/asm/k8.h | |||
@@ -16,11 +16,16 @@ extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn); | |||
16 | extern int k8_scan_nodes(void); | 16 | extern int k8_scan_nodes(void); |
17 | 17 | ||
18 | #ifdef CONFIG_K8_NB | 18 | #ifdef CONFIG_K8_NB |
19 | extern int num_k8_northbridges; | ||
20 | |||
19 | static inline struct pci_dev *node_to_k8_nb_misc(int node) | 21 | static inline struct pci_dev *node_to_k8_nb_misc(int node) |
20 | { | 22 | { |
21 | return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL; | 23 | return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL; |
22 | } | 24 | } |
25 | |||
23 | #else | 26 | #else |
27 | #define num_k8_northbridges 0 | ||
28 | |||
24 | static inline struct pci_dev *node_to_k8_nb_misc(int node) | 29 | static inline struct pci_dev *node_to_k8_nb_misc(int node) |
25 | { | 30 | { |
26 | return NULL; | 31 | return NULL; |
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h new file mode 100644 index 000000000000..79ce5685ab64 --- /dev/null +++ b/arch/x86/include/asm/mshyperv.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef _ASM_X86_MSHYPER_H | ||
2 | #define _ASM_X86_MSHYPER_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | #include <asm/hyperv.h> | ||
6 | |||
7 | struct ms_hyperv_info { | ||
8 | u32 features; | ||
9 | u32 hints; | ||
10 | }; | ||
11 | |||
12 | extern struct ms_hyperv_info ms_hyperv; | ||
13 | |||
14 | #endif | ||
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index b753ea59703a..e4f1dfb2d05b 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -113,7 +113,6 @@ struct cpuinfo_x86 { | |||
113 | /* Index into per_cpu list: */ | 113 | /* Index into per_cpu list: */ |
114 | u16 cpu_index; | 114 | u16 cpu_index; |
115 | #endif | 115 | #endif |
116 | unsigned int x86_hyper_vendor; | ||
117 | } __attribute__((__aligned__(SMP_CACHE_BYTES))); | 116 | } __attribute__((__aligned__(SMP_CACHE_BYTES))); |
118 | 117 | ||
119 | #define X86_VENDOR_INTEL 0 | 118 | #define X86_VENDOR_INTEL 0 |
@@ -127,9 +126,6 @@ struct cpuinfo_x86 { | |||
127 | 126 | ||
128 | #define X86_VENDOR_UNKNOWN 0xff | 127 | #define X86_VENDOR_UNKNOWN 0xff |
129 | 128 | ||
130 | #define X86_HYPER_VENDOR_NONE 0 | ||
131 | #define X86_HYPER_VENDOR_VMWARE 1 | ||
132 | |||
133 | /* | 129 | /* |
134 | * capabilities of CPUs | 130 | * capabilities of CPUs |
135 | */ | 131 | */ |
diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h deleted file mode 100644 index e49ed6d2fd4e..000000000000 --- a/arch/x86/include/asm/vmware.h +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008, VMware, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
12 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
13 | * details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * | ||
19 | */ | ||
20 | #ifndef ASM_X86__VMWARE_H | ||
21 | #define ASM_X86__VMWARE_H | ||
22 | |||
23 | extern void vmware_platform_setup(void); | ||
24 | extern int vmware_platform(void); | ||
25 | extern void vmware_set_feature_bits(struct cpuinfo_x86 *c); | ||
26 | |||
27 | #endif | ||
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index c202b62f3671..3a785da34b6f 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile | |||
@@ -14,7 +14,7 @@ CFLAGS_common.o := $(nostackp) | |||
14 | 14 | ||
15 | obj-y := intel_cacheinfo.o addon_cpuid_features.o | 15 | obj-y := intel_cacheinfo.o addon_cpuid_features.o |
16 | obj-y += proc.o capflags.o powerflags.o common.o | 16 | obj-y += proc.o capflags.o powerflags.o common.o |
17 | obj-y += vmware.o hypervisor.o sched.o | 17 | obj-y += vmware.o hypervisor.o sched.o mshyperv.o |
18 | 18 | ||
19 | obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o | 19 | obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o |
20 | obj-$(CONFIG_X86_64) += bugs_64.o | 20 | obj-$(CONFIG_X86_64) += bugs_64.o |
diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 97ad79cdf688..10fa5684a662 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c | |||
@@ -30,12 +30,14 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) | |||
30 | const struct cpuid_bit *cb; | 30 | const struct cpuid_bit *cb; |
31 | 31 | ||
32 | static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { | 32 | static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { |
33 | { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, | 33 | { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, |
34 | { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 }, | 34 | { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 }, |
35 | { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a }, | 35 | { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006 }, |
36 | { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a }, | 36 | { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007 }, |
37 | { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a }, | 37 | { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a }, |
38 | { X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a }, | 38 | { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a }, |
39 | { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a }, | ||
40 | { X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a }, | ||
39 | { 0, 0, 0, 0 } | 41 | { 0, 0, 0, 0 } |
40 | }; | 42 | }; |
41 | 43 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/Makefile b/arch/x86/kernel/cpu/cpufreq/Makefile index 1840c0a5170b..bd54bf67e6fb 100644 --- a/arch/x86/kernel/cpu/cpufreq/Makefile +++ b/arch/x86/kernel/cpu/cpufreq/Makefile | |||
@@ -2,8 +2,8 @@ | |||
2 | # K8 systems. ACPI is preferred to all other hardware-specific drivers. | 2 | # K8 systems. ACPI is preferred to all other hardware-specific drivers. |
3 | # speedstep-* is preferred over p4-clockmod. | 3 | # speedstep-* is preferred over p4-clockmod. |
4 | 4 | ||
5 | obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o | 5 | obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o mperf.o |
6 | obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o | 6 | obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o mperf.o |
7 | obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o | 7 | obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o |
8 | obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o | 8 | obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o |
9 | obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o | 9 | obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o |
diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 459168083b77..1d3cddaa40ee 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <asm/msr.h> | 46 | #include <asm/msr.h> |
47 | #include <asm/processor.h> | 47 | #include <asm/processor.h> |
48 | #include <asm/cpufeature.h> | 48 | #include <asm/cpufeature.h> |
49 | #include "mperf.h" | ||
49 | 50 | ||
50 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ | 51 | #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ |
51 | "acpi-cpufreq", msg) | 52 | "acpi-cpufreq", msg) |
@@ -71,8 +72,6 @@ struct acpi_cpufreq_data { | |||
71 | 72 | ||
72 | static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data); | 73 | static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data); |
73 | 74 | ||
74 | static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf); | ||
75 | |||
76 | /* acpi_perf_data is a pointer to percpu data. */ | 75 | /* acpi_perf_data is a pointer to percpu data. */ |
77 | static struct acpi_processor_performance *acpi_perf_data; | 76 | static struct acpi_processor_performance *acpi_perf_data; |
78 | 77 | ||
@@ -240,45 +239,6 @@ static u32 get_cur_val(const struct cpumask *mask) | |||
240 | return cmd.val; | 239 | return cmd.val; |
241 | } | 240 | } |
242 | 241 | ||
243 | /* Called via smp_call_function_single(), on the target CPU */ | ||
244 | static void read_measured_perf_ctrs(void *_cur) | ||
245 | { | ||
246 | struct aperfmperf *am = _cur; | ||
247 | |||
248 | get_aperfmperf(am); | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * Return the measured active (C0) frequency on this CPU since last call | ||
253 | * to this function. | ||
254 | * Input: cpu number | ||
255 | * Return: Average CPU frequency in terms of max frequency (zero on error) | ||
256 | * | ||
257 | * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance | ||
258 | * over a period of time, while CPU is in C0 state. | ||
259 | * IA32_MPERF counts at the rate of max advertised frequency | ||
260 | * IA32_APERF counts at the rate of actual CPU frequency | ||
261 | * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and | ||
262 | * no meaning should be associated with absolute values of these MSRs. | ||
263 | */ | ||
264 | static unsigned int get_measured_perf(struct cpufreq_policy *policy, | ||
265 | unsigned int cpu) | ||
266 | { | ||
267 | struct aperfmperf perf; | ||
268 | unsigned long ratio; | ||
269 | unsigned int retval; | ||
270 | |||
271 | if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1)) | ||
272 | return 0; | ||
273 | |||
274 | ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf); | ||
275 | per_cpu(acfreq_old_perf, cpu) = perf; | ||
276 | |||
277 | retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT; | ||
278 | |||
279 | return retval; | ||
280 | } | ||
281 | |||
282 | static unsigned int get_cur_freq_on_cpu(unsigned int cpu) | 242 | static unsigned int get_cur_freq_on_cpu(unsigned int cpu) |
283 | { | 243 | { |
284 | struct acpi_cpufreq_data *data = per_cpu(acfreq_data, cpu); | 244 | struct acpi_cpufreq_data *data = per_cpu(acfreq_data, cpu); |
@@ -702,7 +662,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
702 | 662 | ||
703 | /* Check for APERF/MPERF support in hardware */ | 663 | /* Check for APERF/MPERF support in hardware */ |
704 | if (cpu_has(c, X86_FEATURE_APERFMPERF)) | 664 | if (cpu_has(c, X86_FEATURE_APERFMPERF)) |
705 | acpi_cpufreq_driver.getavg = get_measured_perf; | 665 | acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf; |
706 | 666 | ||
707 | dprintk("CPU%u - ACPI performance management activated.\n", cpu); | 667 | dprintk("CPU%u - ACPI performance management activated.\n", cpu); |
708 | for (i = 0; i < perf->state_count; i++) | 668 | for (i = 0; i < perf->state_count; i++) |
diff --git a/arch/x86/kernel/cpu/cpufreq/mperf.c b/arch/x86/kernel/cpu/cpufreq/mperf.c new file mode 100644 index 000000000000..911e193018ae --- /dev/null +++ b/arch/x86/kernel/cpu/cpufreq/mperf.c | |||
@@ -0,0 +1,51 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/smp.h> | ||
3 | #include <linux/module.h> | ||
4 | #include <linux/init.h> | ||
5 | #include <linux/cpufreq.h> | ||
6 | #include <linux/slab.h> | ||
7 | |||
8 | #include "mperf.h" | ||
9 | |||
10 | static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf); | ||
11 | |||
12 | /* Called via smp_call_function_single(), on the target CPU */ | ||
13 | static void read_measured_perf_ctrs(void *_cur) | ||
14 | { | ||
15 | struct aperfmperf *am = _cur; | ||
16 | |||
17 | get_aperfmperf(am); | ||
18 | } | ||
19 | |||
20 | /* | ||
21 | * Return the measured active (C0) frequency on this CPU since last call | ||
22 | * to this function. | ||
23 | * Input: cpu number | ||
24 | * Return: Average CPU frequency in terms of max frequency (zero on error) | ||
25 | * | ||
26 | * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance | ||
27 | * over a period of time, while CPU is in C0 state. | ||
28 | * IA32_MPERF counts at the rate of max advertised frequency | ||
29 | * IA32_APERF counts at the rate of actual CPU frequency | ||
30 | * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and | ||
31 | * no meaning should be associated with absolute values of these MSRs. | ||
32 | */ | ||
33 | unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy, | ||
34 | unsigned int cpu) | ||
35 | { | ||
36 | struct aperfmperf perf; | ||
37 | unsigned long ratio; | ||
38 | unsigned int retval; | ||
39 | |||
40 | if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1)) | ||
41 | return 0; | ||
42 | |||
43 | ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf); | ||
44 | per_cpu(acfreq_old_perf, cpu) = perf; | ||
45 | |||
46 | retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT; | ||
47 | |||
48 | return retval; | ||
49 | } | ||
50 | EXPORT_SYMBOL_GPL(cpufreq_get_measured_perf); | ||
51 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/mperf.h b/arch/x86/kernel/cpu/cpufreq/mperf.h new file mode 100644 index 000000000000..5dbf2950dc22 --- /dev/null +++ b/arch/x86/kernel/cpu/cpufreq/mperf.h | |||
@@ -0,0 +1,9 @@ | |||
1 | /* | ||
2 | * (c) 2010 Advanced Micro Devices, Inc. | ||
3 | * Your use of this code is subject to the terms and conditions of the | ||
4 | * GNU general public license version 2. See "COPYING" or | ||
5 | * http://www.gnu.org/licenses/gpl.html | ||
6 | */ | ||
7 | |||
8 | unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy, | ||
9 | unsigned int cpu); | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index d360b56e9825..6f3dc8fbbfdc 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c | |||
@@ -1,6 +1,5 @@ | |||
1 | |||
2 | /* | 1 | /* |
3 | * (c) 2003-2006 Advanced Micro Devices, Inc. | 2 | * (c) 2003-2010 Advanced Micro Devices, Inc. |
4 | * Your use of this code is subject to the terms and conditions of the | 3 | * Your use of this code is subject to the terms and conditions of the |
5 | * GNU general public license version 2. See "COPYING" or | 4 | * GNU general public license version 2. See "COPYING" or |
6 | * http://www.gnu.org/licenses/gpl.html | 5 | * http://www.gnu.org/licenses/gpl.html |
@@ -46,6 +45,7 @@ | |||
46 | #define PFX "powernow-k8: " | 45 | #define PFX "powernow-k8: " |
47 | #define VERSION "version 2.20.00" | 46 | #define VERSION "version 2.20.00" |
48 | #include "powernow-k8.h" | 47 | #include "powernow-k8.h" |
48 | #include "mperf.h" | ||
49 | 49 | ||
50 | /* serialize freq changes */ | 50 | /* serialize freq changes */ |
51 | static DEFINE_MUTEX(fidvid_mutex); | 51 | static DEFINE_MUTEX(fidvid_mutex); |
@@ -54,6 +54,12 @@ static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data); | |||
54 | 54 | ||
55 | static int cpu_family = CPU_OPTERON; | 55 | static int cpu_family = CPU_OPTERON; |
56 | 56 | ||
57 | /* core performance boost */ | ||
58 | static bool cpb_capable, cpb_enabled; | ||
59 | static struct msr __percpu *msrs; | ||
60 | |||
61 | static struct cpufreq_driver cpufreq_amd64_driver; | ||
62 | |||
57 | #ifndef CONFIG_SMP | 63 | #ifndef CONFIG_SMP |
58 | static inline const struct cpumask *cpu_core_mask(int cpu) | 64 | static inline const struct cpumask *cpu_core_mask(int cpu) |
59 | { | 65 | { |
@@ -929,7 +935,8 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, | |||
929 | powernow_table[i].index = index; | 935 | powernow_table[i].index = index; |
930 | 936 | ||
931 | /* Frequency may be rounded for these */ | 937 | /* Frequency may be rounded for these */ |
932 | if (boot_cpu_data.x86 == 0x10 || boot_cpu_data.x86 == 0x11) { | 938 | if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) |
939 | || boot_cpu_data.x86 == 0x11) { | ||
933 | powernow_table[i].frequency = | 940 | powernow_table[i].frequency = |
934 | freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7); | 941 | freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7); |
935 | } else | 942 | } else |
@@ -1248,6 +1255,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) | |||
1248 | struct powernow_k8_data *data; | 1255 | struct powernow_k8_data *data; |
1249 | struct init_on_cpu init_on_cpu; | 1256 | struct init_on_cpu init_on_cpu; |
1250 | int rc; | 1257 | int rc; |
1258 | struct cpuinfo_x86 *c = &cpu_data(pol->cpu); | ||
1251 | 1259 | ||
1252 | if (!cpu_online(pol->cpu)) | 1260 | if (!cpu_online(pol->cpu)) |
1253 | return -ENODEV; | 1261 | return -ENODEV; |
@@ -1322,6 +1330,10 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) | |||
1322 | return -EINVAL; | 1330 | return -EINVAL; |
1323 | } | 1331 | } |
1324 | 1332 | ||
1333 | /* Check for APERF/MPERF support in hardware */ | ||
1334 | if (cpu_has(c, X86_FEATURE_APERFMPERF)) | ||
1335 | cpufreq_amd64_driver.getavg = cpufreq_get_measured_perf; | ||
1336 | |||
1325 | cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); | 1337 | cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); |
1326 | 1338 | ||
1327 | if (cpu_family == CPU_HW_PSTATE) | 1339 | if (cpu_family == CPU_HW_PSTATE) |
@@ -1393,8 +1405,77 @@ out: | |||
1393 | return khz; | 1405 | return khz; |
1394 | } | 1406 | } |
1395 | 1407 | ||
1408 | static void _cpb_toggle_msrs(bool t) | ||
1409 | { | ||
1410 | int cpu; | ||
1411 | |||
1412 | get_online_cpus(); | ||
1413 | |||
1414 | rdmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs); | ||
1415 | |||
1416 | for_each_cpu(cpu, cpu_online_mask) { | ||
1417 | struct msr *reg = per_cpu_ptr(msrs, cpu); | ||
1418 | if (t) | ||
1419 | reg->l &= ~BIT(25); | ||
1420 | else | ||
1421 | reg->l |= BIT(25); | ||
1422 | } | ||
1423 | wrmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs); | ||
1424 | |||
1425 | put_online_cpus(); | ||
1426 | } | ||
1427 | |||
1428 | /* | ||
1429 | * Switch on/off core performance boosting. | ||
1430 | * | ||
1431 | * 0=disable | ||
1432 | * 1=enable. | ||
1433 | */ | ||
1434 | static void cpb_toggle(bool t) | ||
1435 | { | ||
1436 | if (!cpb_capable) | ||
1437 | return; | ||
1438 | |||
1439 | if (t && !cpb_enabled) { | ||
1440 | cpb_enabled = true; | ||
1441 | _cpb_toggle_msrs(t); | ||
1442 | printk(KERN_INFO PFX "Core Boosting enabled.\n"); | ||
1443 | } else if (!t && cpb_enabled) { | ||
1444 | cpb_enabled = false; | ||
1445 | _cpb_toggle_msrs(t); | ||
1446 | printk(KERN_INFO PFX "Core Boosting disabled.\n"); | ||
1447 | } | ||
1448 | } | ||
1449 | |||
1450 | static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf, | ||
1451 | size_t count) | ||
1452 | { | ||
1453 | int ret = -EINVAL; | ||
1454 | unsigned long val = 0; | ||
1455 | |||
1456 | ret = strict_strtoul(buf, 10, &val); | ||
1457 | if (!ret && (val == 0 || val == 1) && cpb_capable) | ||
1458 | cpb_toggle(val); | ||
1459 | else | ||
1460 | return -EINVAL; | ||
1461 | |||
1462 | return count; | ||
1463 | } | ||
1464 | |||
1465 | static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf) | ||
1466 | { | ||
1467 | return sprintf(buf, "%u\n", cpb_enabled); | ||
1468 | } | ||
1469 | |||
1470 | #define define_one_rw(_name) \ | ||
1471 | static struct freq_attr _name = \ | ||
1472 | __ATTR(_name, 0644, show_##_name, store_##_name) | ||
1473 | |||
1474 | define_one_rw(cpb); | ||
1475 | |||
1396 | static struct freq_attr *powernow_k8_attr[] = { | 1476 | static struct freq_attr *powernow_k8_attr[] = { |
1397 | &cpufreq_freq_attr_scaling_available_freqs, | 1477 | &cpufreq_freq_attr_scaling_available_freqs, |
1478 | &cpb, | ||
1398 | NULL, | 1479 | NULL, |
1399 | }; | 1480 | }; |
1400 | 1481 | ||
@@ -1410,10 +1491,51 @@ static struct cpufreq_driver cpufreq_amd64_driver = { | |||
1410 | .attr = powernow_k8_attr, | 1491 | .attr = powernow_k8_attr, |
1411 | }; | 1492 | }; |
1412 | 1493 | ||
1494 | /* | ||
1495 | * Clear the boost-disable flag on the CPU_DOWN path so that this cpu | ||
1496 | * cannot block the remaining ones from boosting. On the CPU_UP path we | ||
1497 | * simply keep the boost-disable flag in sync with the current global | ||
1498 | * state. | ||
1499 | */ | ||
1500 | static int __cpuinit cpb_notify(struct notifier_block *nb, unsigned long action, | ||
1501 | void *hcpu) | ||
1502 | { | ||
1503 | unsigned cpu = (long)hcpu; | ||
1504 | u32 lo, hi; | ||
1505 | |||
1506 | switch (action) { | ||
1507 | case CPU_UP_PREPARE: | ||
1508 | case CPU_UP_PREPARE_FROZEN: | ||
1509 | |||
1510 | if (!cpb_enabled) { | ||
1511 | rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi); | ||
1512 | lo |= BIT(25); | ||
1513 | wrmsr_on_cpu(cpu, MSR_K7_HWCR, lo, hi); | ||
1514 | } | ||
1515 | break; | ||
1516 | |||
1517 | case CPU_DOWN_PREPARE: | ||
1518 | case CPU_DOWN_PREPARE_FROZEN: | ||
1519 | rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi); | ||
1520 | lo &= ~BIT(25); | ||
1521 | wrmsr_on_cpu(cpu, MSR_K7_HWCR, lo, hi); | ||
1522 | break; | ||
1523 | |||
1524 | default: | ||
1525 | break; | ||
1526 | } | ||
1527 | |||
1528 | return NOTIFY_OK; | ||
1529 | } | ||
1530 | |||
1531 | static struct notifier_block __cpuinitdata cpb_nb = { | ||
1532 | .notifier_call = cpb_notify, | ||
1533 | }; | ||
1534 | |||
1413 | /* driver entry point for init */ | 1535 | /* driver entry point for init */ |
1414 | static int __cpuinit powernowk8_init(void) | 1536 | static int __cpuinit powernowk8_init(void) |
1415 | { | 1537 | { |
1416 | unsigned int i, supported_cpus = 0; | 1538 | unsigned int i, supported_cpus = 0, cpu; |
1417 | 1539 | ||
1418 | for_each_online_cpu(i) { | 1540 | for_each_online_cpu(i) { |
1419 | int rc; | 1541 | int rc; |
@@ -1422,15 +1544,36 @@ static int __cpuinit powernowk8_init(void) | |||
1422 | supported_cpus++; | 1544 | supported_cpus++; |
1423 | } | 1545 | } |
1424 | 1546 | ||
1425 | if (supported_cpus == num_online_cpus()) { | 1547 | if (supported_cpus != num_online_cpus()) |
1426 | printk(KERN_INFO PFX "Found %d %s " | 1548 | return -ENODEV; |
1427 | "processors (%d cpu cores) (" VERSION ")\n", | 1549 | |
1428 | num_online_nodes(), | 1550 | printk(KERN_INFO PFX "Found %d %s (%d cpu cores) (" VERSION ")\n", |
1429 | boot_cpu_data.x86_model_id, supported_cpus); | 1551 | num_online_nodes(), boot_cpu_data.x86_model_id, supported_cpus); |
1430 | return cpufreq_register_driver(&cpufreq_amd64_driver); | 1552 | |
1553 | if (boot_cpu_has(X86_FEATURE_CPB)) { | ||
1554 | |||
1555 | cpb_capable = true; | ||
1556 | |||
1557 | register_cpu_notifier(&cpb_nb); | ||
1558 | |||
1559 | msrs = msrs_alloc(); | ||
1560 | if (!msrs) { | ||
1561 | printk(KERN_ERR "%s: Error allocating msrs!\n", __func__); | ||
1562 | return -ENOMEM; | ||
1563 | } | ||
1564 | |||
1565 | rdmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs); | ||
1566 | |||
1567 | for_each_cpu(cpu, cpu_online_mask) { | ||
1568 | struct msr *reg = per_cpu_ptr(msrs, cpu); | ||
1569 | cpb_enabled |= !(!!(reg->l & BIT(25))); | ||
1570 | } | ||
1571 | |||
1572 | printk(KERN_INFO PFX "Core Performance Boosting: %s.\n", | ||
1573 | (cpb_enabled ? "on" : "off")); | ||
1431 | } | 1574 | } |
1432 | 1575 | ||
1433 | return -ENODEV; | 1576 | return cpufreq_register_driver(&cpufreq_amd64_driver); |
1434 | } | 1577 | } |
1435 | 1578 | ||
1436 | /* driver entry point for term */ | 1579 | /* driver entry point for term */ |
@@ -1438,6 +1581,13 @@ static void __exit powernowk8_exit(void) | |||
1438 | { | 1581 | { |
1439 | dprintk("exit\n"); | 1582 | dprintk("exit\n"); |
1440 | 1583 | ||
1584 | if (boot_cpu_has(X86_FEATURE_CPB)) { | ||
1585 | msrs_free(msrs); | ||
1586 | msrs = NULL; | ||
1587 | |||
1588 | unregister_cpu_notifier(&cpb_nb); | ||
1589 | } | ||
1590 | |||
1441 | cpufreq_unregister_driver(&cpufreq_amd64_driver); | 1591 | cpufreq_unregister_driver(&cpufreq_amd64_driver); |
1442 | } | 1592 | } |
1443 | 1593 | ||
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h index 02ce824073cb..df3529b1c02d 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h | |||
@@ -5,7 +5,6 @@ | |||
5 | * http://www.gnu.org/licenses/gpl.html | 5 | * http://www.gnu.org/licenses/gpl.html |
6 | */ | 6 | */ |
7 | 7 | ||
8 | |||
9 | enum pstate { | 8 | enum pstate { |
10 | HW_PSTATE_INVALID = 0xff, | 9 | HW_PSTATE_INVALID = 0xff, |
11 | HW_PSTATE_0 = 0, | 10 | HW_PSTATE_0 = 0, |
@@ -55,7 +54,6 @@ struct powernow_k8_data { | |||
55 | struct cpumask *available_cores; | 54 | struct cpumask *available_cores; |
56 | }; | 55 | }; |
57 | 56 | ||
58 | |||
59 | /* processor's cpuid instruction support */ | 57 | /* processor's cpuid instruction support */ |
60 | #define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */ | 58 | #define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */ |
61 | #define CPUID_XFAM 0x0ff00000 /* extended family */ | 59 | #define CPUID_XFAM 0x0ff00000 /* extended family */ |
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index 08be922de33a..87381759d3cb 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c | |||
@@ -22,36 +22,52 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <asm/processor.h> | 24 | #include <asm/processor.h> |
25 | #include <asm/vmware.h> | ||
26 | #include <asm/hypervisor.h> | 25 | #include <asm/hypervisor.h> |
27 | 26 | ||
28 | static inline void __cpuinit | 27 | /* |
29 | detect_hypervisor_vendor(struct cpuinfo_x86 *c) | 28 | * Hypervisor detect order. This is specified explicitly here because |
29 | * some hypervisors might implement compatibility modes for other | ||
30 | * hypervisors and therefore need to be detected in specific sequence. | ||
31 | */ | ||
32 | static const __initconst struct hypervisor_x86 * const hypervisors[] = | ||
30 | { | 33 | { |
31 | if (vmware_platform()) | 34 | &x86_hyper_vmware, |
32 | c->x86_hyper_vendor = X86_HYPER_VENDOR_VMWARE; | 35 | &x86_hyper_ms_hyperv, |
33 | else | 36 | }; |
34 | c->x86_hyper_vendor = X86_HYPER_VENDOR_NONE; | ||
35 | } | ||
36 | 37 | ||
37 | static inline void __cpuinit | 38 | const struct hypervisor_x86 *x86_hyper; |
38 | hypervisor_set_feature_bits(struct cpuinfo_x86 *c) | 39 | |
40 | static inline void __init | ||
41 | detect_hypervisor_vendor(void) | ||
39 | { | 42 | { |
40 | if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) { | 43 | const struct hypervisor_x86 *h, * const *p; |
41 | vmware_set_feature_bits(c); | 44 | |
42 | return; | 45 | for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) { |
46 | h = *p; | ||
47 | if (h->detect()) { | ||
48 | x86_hyper = h; | ||
49 | printk(KERN_INFO "Hypervisor detected: %s\n", h->name); | ||
50 | break; | ||
51 | } | ||
43 | } | 52 | } |
44 | } | 53 | } |
45 | 54 | ||
46 | void __cpuinit init_hypervisor(struct cpuinfo_x86 *c) | 55 | void __cpuinit init_hypervisor(struct cpuinfo_x86 *c) |
47 | { | 56 | { |
48 | detect_hypervisor_vendor(c); | 57 | if (x86_hyper && x86_hyper->set_cpu_features) |
49 | hypervisor_set_feature_bits(c); | 58 | x86_hyper->set_cpu_features(c); |
50 | } | 59 | } |
51 | 60 | ||
52 | void __init init_hypervisor_platform(void) | 61 | void __init init_hypervisor_platform(void) |
53 | { | 62 | { |
63 | |||
64 | detect_hypervisor_vendor(); | ||
65 | |||
66 | if (!x86_hyper) | ||
67 | return; | ||
68 | |||
54 | init_hypervisor(&boot_cpu_data); | 69 | init_hypervisor(&boot_cpu_data); |
55 | if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) | 70 | |
56 | vmware_platform_setup(); | 71 | if (x86_hyper->init_platform) |
72 | x86_hyper->init_platform(); | ||
57 | } | 73 | } |
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 1366c7cfd483..afeaa3e0bc43 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c | |||
@@ -373,12 +373,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) | |||
373 | set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); | 373 | set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); |
374 | } | 374 | } |
375 | 375 | ||
376 | if (c->cpuid_level > 6) { | ||
377 | unsigned ecx = cpuid_ecx(6); | ||
378 | if (ecx & 0x01) | ||
379 | set_cpu_cap(c, X86_FEATURE_APERFMPERF); | ||
380 | } | ||
381 | |||
382 | if (cpu_has_xmm2) | 376 | if (cpu_has_xmm2) |
383 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); | 377 | set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); |
384 | if (cpu_has_ds) { | 378 | if (cpu_has_ds) { |
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index b3eeb66c0a51..33eae2062cf5 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c | |||
@@ -148,13 +148,19 @@ union _cpuid4_leaf_ecx { | |||
148 | u32 full; | 148 | u32 full; |
149 | }; | 149 | }; |
150 | 150 | ||
151 | struct amd_l3_cache { | ||
152 | struct pci_dev *dev; | ||
153 | bool can_disable; | ||
154 | unsigned indices; | ||
155 | u8 subcaches[4]; | ||
156 | }; | ||
157 | |||
151 | struct _cpuid4_info { | 158 | struct _cpuid4_info { |
152 | union _cpuid4_leaf_eax eax; | 159 | union _cpuid4_leaf_eax eax; |
153 | union _cpuid4_leaf_ebx ebx; | 160 | union _cpuid4_leaf_ebx ebx; |
154 | union _cpuid4_leaf_ecx ecx; | 161 | union _cpuid4_leaf_ecx ecx; |
155 | unsigned long size; | 162 | unsigned long size; |
156 | bool can_disable; | 163 | struct amd_l3_cache *l3; |
157 | unsigned int l3_indices; | ||
158 | DECLARE_BITMAP(shared_cpu_map, NR_CPUS); | 164 | DECLARE_BITMAP(shared_cpu_map, NR_CPUS); |
159 | }; | 165 | }; |
160 | 166 | ||
@@ -164,8 +170,7 @@ struct _cpuid4_info_regs { | |||
164 | union _cpuid4_leaf_ebx ebx; | 170 | union _cpuid4_leaf_ebx ebx; |
165 | union _cpuid4_leaf_ecx ecx; | 171 | union _cpuid4_leaf_ecx ecx; |
166 | unsigned long size; | 172 | unsigned long size; |
167 | bool can_disable; | 173 | struct amd_l3_cache *l3; |
168 | unsigned int l3_indices; | ||
169 | }; | 174 | }; |
170 | 175 | ||
171 | unsigned short num_cache_leaves; | 176 | unsigned short num_cache_leaves; |
@@ -302,87 +307,163 @@ struct _cache_attr { | |||
302 | }; | 307 | }; |
303 | 308 | ||
304 | #ifdef CONFIG_CPU_SUP_AMD | 309 | #ifdef CONFIG_CPU_SUP_AMD |
305 | static unsigned int __cpuinit amd_calc_l3_indices(void) | 310 | |
311 | /* | ||
312 | * L3 cache descriptors | ||
313 | */ | ||
314 | static struct amd_l3_cache **__cpuinitdata l3_caches; | ||
315 | |||
316 | static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) | ||
306 | { | 317 | { |
307 | /* | ||
308 | * We're called over smp_call_function_single() and therefore | ||
309 | * are on the correct cpu. | ||
310 | */ | ||
311 | int cpu = smp_processor_id(); | ||
312 | int node = cpu_to_node(cpu); | ||
313 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
314 | unsigned int sc0, sc1, sc2, sc3; | 318 | unsigned int sc0, sc1, sc2, sc3; |
315 | u32 val = 0; | 319 | u32 val = 0; |
316 | 320 | ||
317 | pci_read_config_dword(dev, 0x1C4, &val); | 321 | pci_read_config_dword(l3->dev, 0x1C4, &val); |
318 | 322 | ||
319 | /* calculate subcache sizes */ | 323 | /* calculate subcache sizes */ |
320 | sc0 = !(val & BIT(0)); | 324 | l3->subcaches[0] = sc0 = !(val & BIT(0)); |
321 | sc1 = !(val & BIT(4)); | 325 | l3->subcaches[1] = sc1 = !(val & BIT(4)); |
322 | sc2 = !(val & BIT(8)) + !(val & BIT(9)); | 326 | l3->subcaches[2] = sc2 = !(val & BIT(8)) + !(val & BIT(9)); |
323 | sc3 = !(val & BIT(12)) + !(val & BIT(13)); | 327 | l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13)); |
324 | 328 | ||
325 | return (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1; | 329 | l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1; |
330 | } | ||
331 | |||
332 | static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node) | ||
333 | { | ||
334 | struct amd_l3_cache *l3; | ||
335 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
336 | |||
337 | l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC); | ||
338 | if (!l3) { | ||
339 | printk(KERN_WARNING "Error allocating L3 struct\n"); | ||
340 | return NULL; | ||
341 | } | ||
342 | |||
343 | l3->dev = dev; | ||
344 | |||
345 | amd_calc_l3_indices(l3); | ||
346 | |||
347 | return l3; | ||
326 | } | 348 | } |
327 | 349 | ||
328 | static void __cpuinit | 350 | static void __cpuinit |
329 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) | 351 | amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) |
330 | { | 352 | { |
331 | if (index < 3) | 353 | int node; |
354 | |||
355 | if (boot_cpu_data.x86 != 0x10) | ||
332 | return; | 356 | return; |
333 | 357 | ||
334 | if (boot_cpu_data.x86 == 0x11) | 358 | if (index < 3) |
335 | return; | 359 | return; |
336 | 360 | ||
337 | /* see errata #382 and #388 */ | 361 | /* see errata #382 and #388 */ |
338 | if ((boot_cpu_data.x86 == 0x10) && | 362 | if (boot_cpu_data.x86_model < 0x8) |
339 | ((boot_cpu_data.x86_model < 0x8) || | 363 | return; |
340 | (boot_cpu_data.x86_mask < 0x1))) | 364 | |
365 | if ((boot_cpu_data.x86_model == 0x8 || | ||
366 | boot_cpu_data.x86_model == 0x9) | ||
367 | && | ||
368 | boot_cpu_data.x86_mask < 0x1) | ||
369 | return; | ||
370 | |||
371 | /* not in virtualized environments */ | ||
372 | if (num_k8_northbridges == 0) | ||
341 | return; | 373 | return; |
342 | 374 | ||
343 | this_leaf->can_disable = true; | 375 | /* |
344 | this_leaf->l3_indices = amd_calc_l3_indices(); | 376 | * Strictly speaking, the amount in @size below is leaked since it is |
377 | * never freed but this is done only on shutdown so it doesn't matter. | ||
378 | */ | ||
379 | if (!l3_caches) { | ||
380 | int size = num_k8_northbridges * sizeof(struct amd_l3_cache *); | ||
381 | |||
382 | l3_caches = kzalloc(size, GFP_ATOMIC); | ||
383 | if (!l3_caches) | ||
384 | return; | ||
385 | } | ||
386 | |||
387 | node = amd_get_nb_id(smp_processor_id()); | ||
388 | |||
389 | if (!l3_caches[node]) { | ||
390 | l3_caches[node] = amd_init_l3_cache(node); | ||
391 | l3_caches[node]->can_disable = true; | ||
392 | } | ||
393 | |||
394 | WARN_ON(!l3_caches[node]); | ||
395 | |||
396 | this_leaf->l3 = l3_caches[node]; | ||
345 | } | 397 | } |
346 | 398 | ||
347 | static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, | 399 | static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, |
348 | unsigned int index) | 400 | unsigned int slot) |
349 | { | 401 | { |
350 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | 402 | struct pci_dev *dev = this_leaf->l3->dev; |
351 | int node = amd_get_nb_id(cpu); | ||
352 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
353 | unsigned int reg = 0; | 403 | unsigned int reg = 0; |
354 | 404 | ||
355 | if (!this_leaf->can_disable) | 405 | if (!this_leaf->l3 || !this_leaf->l3->can_disable) |
356 | return -EINVAL; | 406 | return -EINVAL; |
357 | 407 | ||
358 | if (!dev) | 408 | if (!dev) |
359 | return -EINVAL; | 409 | return -EINVAL; |
360 | 410 | ||
361 | pci_read_config_dword(dev, 0x1BC + index * 4, ®); | 411 | pci_read_config_dword(dev, 0x1BC + slot * 4, ®); |
362 | return sprintf(buf, "0x%08x\n", reg); | 412 | return sprintf(buf, "0x%08x\n", reg); |
363 | } | 413 | } |
364 | 414 | ||
365 | #define SHOW_CACHE_DISABLE(index) \ | 415 | #define SHOW_CACHE_DISABLE(slot) \ |
366 | static ssize_t \ | 416 | static ssize_t \ |
367 | show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf) \ | 417 | show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf) \ |
368 | { \ | 418 | { \ |
369 | return show_cache_disable(this_leaf, buf, index); \ | 419 | return show_cache_disable(this_leaf, buf, slot); \ |
370 | } | 420 | } |
371 | SHOW_CACHE_DISABLE(0) | 421 | SHOW_CACHE_DISABLE(0) |
372 | SHOW_CACHE_DISABLE(1) | 422 | SHOW_CACHE_DISABLE(1) |
373 | 423 | ||
424 | static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, | ||
425 | unsigned slot, unsigned long idx) | ||
426 | { | ||
427 | int i; | ||
428 | |||
429 | idx |= BIT(30); | ||
430 | |||
431 | /* | ||
432 | * disable index in all 4 subcaches | ||
433 | */ | ||
434 | for (i = 0; i < 4; i++) { | ||
435 | u32 reg = idx | (i << 20); | ||
436 | |||
437 | if (!l3->subcaches[i]) | ||
438 | continue; | ||
439 | |||
440 | pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg); | ||
441 | |||
442 | /* | ||
443 | * We need to WBINVD on a core on the node containing the L3 | ||
444 | * cache which indices we disable therefore a simple wbinvd() | ||
445 | * is not sufficient. | ||
446 | */ | ||
447 | wbinvd_on_cpu(cpu); | ||
448 | |||
449 | reg |= BIT(31); | ||
450 | pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg); | ||
451 | } | ||
452 | } | ||
453 | |||
454 | |||
374 | static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | 455 | static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, |
375 | const char *buf, size_t count, unsigned int index) | 456 | const char *buf, size_t count, |
457 | unsigned int slot) | ||
376 | { | 458 | { |
459 | struct pci_dev *dev = this_leaf->l3->dev; | ||
377 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); | 460 | int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); |
378 | int node = amd_get_nb_id(cpu); | ||
379 | struct pci_dev *dev = node_to_k8_nb_misc(node); | ||
380 | unsigned long val = 0; | 461 | unsigned long val = 0; |
381 | 462 | ||
382 | #define SUBCACHE_MASK (3UL << 20) | 463 | #define SUBCACHE_MASK (3UL << 20) |
383 | #define SUBCACHE_INDEX 0xfff | 464 | #define SUBCACHE_INDEX 0xfff |
384 | 465 | ||
385 | if (!this_leaf->can_disable) | 466 | if (!this_leaf->l3 || !this_leaf->l3->can_disable) |
386 | return -EINVAL; | 467 | return -EINVAL; |
387 | 468 | ||
388 | if (!capable(CAP_SYS_ADMIN)) | 469 | if (!capable(CAP_SYS_ADMIN)) |
@@ -396,26 +477,20 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, | |||
396 | 477 | ||
397 | /* do not allow writes outside of allowed bits */ | 478 | /* do not allow writes outside of allowed bits */ |
398 | if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) || | 479 | if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) || |
399 | ((val & SUBCACHE_INDEX) > this_leaf->l3_indices)) | 480 | ((val & SUBCACHE_INDEX) > this_leaf->l3->indices)) |
400 | return -EINVAL; | 481 | return -EINVAL; |
401 | 482 | ||
402 | val |= BIT(30); | 483 | amd_l3_disable_index(this_leaf->l3, cpu, slot, val); |
403 | pci_write_config_dword(dev, 0x1BC + index * 4, val); | 484 | |
404 | /* | ||
405 | * We need to WBINVD on a core on the node containing the L3 cache which | ||
406 | * indices we disable therefore a simple wbinvd() is not sufficient. | ||
407 | */ | ||
408 | wbinvd_on_cpu(cpu); | ||
409 | pci_write_config_dword(dev, 0x1BC + index * 4, val | BIT(31)); | ||
410 | return count; | 485 | return count; |
411 | } | 486 | } |
412 | 487 | ||
413 | #define STORE_CACHE_DISABLE(index) \ | 488 | #define STORE_CACHE_DISABLE(slot) \ |
414 | static ssize_t \ | 489 | static ssize_t \ |
415 | store_cache_disable_##index(struct _cpuid4_info *this_leaf, \ | 490 | store_cache_disable_##slot(struct _cpuid4_info *this_leaf, \ |
416 | const char *buf, size_t count) \ | 491 | const char *buf, size_t count) \ |
417 | { \ | 492 | { \ |
418 | return store_cache_disable(this_leaf, buf, count, index); \ | 493 | return store_cache_disable(this_leaf, buf, count, slot); \ |
419 | } | 494 | } |
420 | STORE_CACHE_DISABLE(0) | 495 | STORE_CACHE_DISABLE(0) |
421 | STORE_CACHE_DISABLE(1) | 496 | STORE_CACHE_DISABLE(1) |
@@ -443,8 +518,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index, | |||
443 | 518 | ||
444 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { | 519 | if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { |
445 | amd_cpuid4(index, &eax, &ebx, &ecx); | 520 | amd_cpuid4(index, &eax, &ebx, &ecx); |
446 | if (boot_cpu_data.x86 >= 0x10) | 521 | amd_check_l3_disable(index, this_leaf); |
447 | amd_check_l3_disable(index, this_leaf); | ||
448 | } else { | 522 | } else { |
449 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); | 523 | cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); |
450 | } | 524 | } |
@@ -701,6 +775,7 @@ static void __cpuinit free_cache_attributes(unsigned int cpu) | |||
701 | for (i = 0; i < num_cache_leaves; i++) | 775 | for (i = 0; i < num_cache_leaves; i++) |
702 | cache_remove_shared_cpu_map(cpu, i); | 776 | cache_remove_shared_cpu_map(cpu, i); |
703 | 777 | ||
778 | kfree(per_cpu(ici_cpuid4_info, cpu)->l3); | ||
704 | kfree(per_cpu(ici_cpuid4_info, cpu)); | 779 | kfree(per_cpu(ici_cpuid4_info, cpu)); |
705 | per_cpu(ici_cpuid4_info, cpu) = NULL; | 780 | per_cpu(ici_cpuid4_info, cpu) = NULL; |
706 | } | 781 | } |
@@ -985,7 +1060,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) | |||
985 | 1060 | ||
986 | this_leaf = CPUID4_INFO_IDX(cpu, i); | 1061 | this_leaf = CPUID4_INFO_IDX(cpu, i); |
987 | 1062 | ||
988 | if (this_leaf->can_disable) | 1063 | if (this_leaf->l3 && this_leaf->l3->can_disable) |
989 | ktype_cache.default_attrs = default_l3_attrs; | 1064 | ktype_cache.default_attrs = default_l3_attrs; |
990 | else | 1065 | else |
991 | ktype_cache.default_attrs = default_attrs; | 1066 | ktype_cache.default_attrs = default_attrs; |
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c new file mode 100644 index 000000000000..5969c3ee3186 --- /dev/null +++ b/arch/x86/kernel/cpu/mshyperv.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * HyperV Detection code. | ||
3 | * | ||
4 | * Copyright (C) 2010, Novell, Inc. | ||
5 | * Author : K. Y. Srinivasan <ksrinivasan@novell.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/types.h> | ||
14 | #include <asm/processor.h> | ||
15 | #include <asm/hypervisor.h> | ||
16 | #include <asm/hyperv.h> | ||
17 | #include <asm/mshyperv.h> | ||
18 | |||
19 | struct ms_hyperv_info ms_hyperv; | ||
20 | |||
21 | static bool __init ms_hyperv_platform(void) | ||
22 | { | ||
23 | u32 eax; | ||
24 | u32 hyp_signature[3]; | ||
25 | |||
26 | if (!boot_cpu_has(X86_FEATURE_HYPERVISOR)) | ||
27 | return false; | ||
28 | |||
29 | cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, | ||
30 | &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]); | ||
31 | |||
32 | return eax >= HYPERV_CPUID_MIN && | ||
33 | eax <= HYPERV_CPUID_MAX && | ||
34 | !memcmp("Microsoft Hv", hyp_signature, 12); | ||
35 | } | ||
36 | |||
37 | static void __init ms_hyperv_init_platform(void) | ||
38 | { | ||
39 | /* | ||
40 | * Extract the features and hints | ||
41 | */ | ||
42 | ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES); | ||
43 | ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO); | ||
44 | |||
45 | printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n", | ||
46 | ms_hyperv.features, ms_hyperv.hints); | ||
47 | } | ||
48 | |||
49 | const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { | ||
50 | .name = "Microsoft HyperV", | ||
51 | .detect = ms_hyperv_platform, | ||
52 | .init_platform = ms_hyperv_init_platform, | ||
53 | }; | ||
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index dfdb4dba2320..265b432f6e64 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c | |||
@@ -24,8 +24,8 @@ | |||
24 | #include <linux/dmi.h> | 24 | #include <linux/dmi.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <asm/div64.h> | 26 | #include <asm/div64.h> |
27 | #include <asm/vmware.h> | ||
28 | #include <asm/x86_init.h> | 27 | #include <asm/x86_init.h> |
28 | #include <asm/hypervisor.h> | ||
29 | 29 | ||
30 | #define CPUID_VMWARE_INFO_LEAF 0x40000000 | 30 | #define CPUID_VMWARE_INFO_LEAF 0x40000000 |
31 | #define VMWARE_HYPERVISOR_MAGIC 0x564D5868 | 31 | #define VMWARE_HYPERVISOR_MAGIC 0x564D5868 |
@@ -65,7 +65,7 @@ static unsigned long vmware_get_tsc_khz(void) | |||
65 | return tsc_hz; | 65 | return tsc_hz; |
66 | } | 66 | } |
67 | 67 | ||
68 | void __init vmware_platform_setup(void) | 68 | static void __init vmware_platform_setup(void) |
69 | { | 69 | { |
70 | uint32_t eax, ebx, ecx, edx; | 70 | uint32_t eax, ebx, ecx, edx; |
71 | 71 | ||
@@ -83,24 +83,21 @@ void __init vmware_platform_setup(void) | |||
83 | * serial key should be enough, as this will always have a VMware | 83 | * serial key should be enough, as this will always have a VMware |
84 | * specific string when running under VMware hypervisor. | 84 | * specific string when running under VMware hypervisor. |
85 | */ | 85 | */ |
86 | int vmware_platform(void) | 86 | static bool __init vmware_platform(void) |
87 | { | 87 | { |
88 | if (cpu_has_hypervisor) { | 88 | if (cpu_has_hypervisor) { |
89 | unsigned int eax, ebx, ecx, edx; | 89 | unsigned int eax; |
90 | char hyper_vendor_id[13]; | 90 | unsigned int hyper_vendor_id[3]; |
91 | 91 | ||
92 | cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &ebx, &ecx, &edx); | 92 | cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &hyper_vendor_id[0], |
93 | memcpy(hyper_vendor_id + 0, &ebx, 4); | 93 | &hyper_vendor_id[1], &hyper_vendor_id[2]); |
94 | memcpy(hyper_vendor_id + 4, &ecx, 4); | 94 | if (!memcmp(hyper_vendor_id, "VMwareVMware", 12)) |
95 | memcpy(hyper_vendor_id + 8, &edx, 4); | 95 | return true; |
96 | hyper_vendor_id[12] = '\0'; | ||
97 | if (!strcmp(hyper_vendor_id, "VMwareVMware")) | ||
98 | return 1; | ||
99 | } else if (dmi_available && dmi_name_in_serial("VMware") && | 96 | } else if (dmi_available && dmi_name_in_serial("VMware") && |
100 | __vmware_platform()) | 97 | __vmware_platform()) |
101 | return 1; | 98 | return true; |
102 | 99 | ||
103 | return 0; | 100 | return false; |
104 | } | 101 | } |
105 | EXPORT_SYMBOL(vmware_platform); | 102 | EXPORT_SYMBOL(vmware_platform); |
106 | 103 | ||
@@ -116,8 +113,15 @@ EXPORT_SYMBOL(vmware_platform); | |||
116 | * so that the kernel could just trust the hypervisor with providing a | 113 | * so that the kernel could just trust the hypervisor with providing a |
117 | * reliable virtual TSC that is suitable for timekeeping. | 114 | * reliable virtual TSC that is suitable for timekeeping. |
118 | */ | 115 | */ |
119 | void __cpuinit vmware_set_feature_bits(struct cpuinfo_x86 *c) | 116 | static void __cpuinit vmware_set_cpu_features(struct cpuinfo_x86 *c) |
120 | { | 117 | { |
121 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); | 118 | set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); |
122 | set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE); | 119 | set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE); |
123 | } | 120 | } |
121 | |||
122 | const __refconst struct hypervisor_x86 x86_hyper_vmware = { | ||
123 | .name = "VMware", | ||
124 | .detect = vmware_platform, | ||
125 | .set_cpu_features = vmware_set_cpu_features, | ||
126 | .init_platform = vmware_platform_setup, | ||
127 | }; | ||
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 75d293eeb3ee..063b2184caf5 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -662,32 +662,20 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) | |||
662 | return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); | 662 | return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); |
663 | } | 663 | } |
664 | 664 | ||
665 | #define define_one_ro(_name) \ | 665 | cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); |
666 | static struct freq_attr _name = \ | 666 | cpufreq_freq_attr_ro(cpuinfo_min_freq); |
667 | __ATTR(_name, 0444, show_##_name, NULL) | 667 | cpufreq_freq_attr_ro(cpuinfo_max_freq); |
668 | 668 | cpufreq_freq_attr_ro(cpuinfo_transition_latency); | |
669 | #define define_one_ro0400(_name) \ | 669 | cpufreq_freq_attr_ro(scaling_available_governors); |
670 | static struct freq_attr _name = \ | 670 | cpufreq_freq_attr_ro(scaling_driver); |
671 | __ATTR(_name, 0400, show_##_name, NULL) | 671 | cpufreq_freq_attr_ro(scaling_cur_freq); |
672 | 672 | cpufreq_freq_attr_ro(bios_limit); | |
673 | #define define_one_rw(_name) \ | 673 | cpufreq_freq_attr_ro(related_cpus); |
674 | static struct freq_attr _name = \ | 674 | cpufreq_freq_attr_ro(affected_cpus); |
675 | __ATTR(_name, 0644, show_##_name, store_##_name) | 675 | cpufreq_freq_attr_rw(scaling_min_freq); |
676 | 676 | cpufreq_freq_attr_rw(scaling_max_freq); | |
677 | define_one_ro0400(cpuinfo_cur_freq); | 677 | cpufreq_freq_attr_rw(scaling_governor); |
678 | define_one_ro(cpuinfo_min_freq); | 678 | cpufreq_freq_attr_rw(scaling_setspeed); |
679 | define_one_ro(cpuinfo_max_freq); | ||
680 | define_one_ro(cpuinfo_transition_latency); | ||
681 | define_one_ro(scaling_available_governors); | ||
682 | define_one_ro(scaling_driver); | ||
683 | define_one_ro(scaling_cur_freq); | ||
684 | define_one_ro(bios_limit); | ||
685 | define_one_ro(related_cpus); | ||
686 | define_one_ro(affected_cpus); | ||
687 | define_one_rw(scaling_min_freq); | ||
688 | define_one_rw(scaling_max_freq); | ||
689 | define_one_rw(scaling_governor); | ||
690 | define_one_rw(scaling_setspeed); | ||
691 | 679 | ||
692 | static struct attribute *default_attrs[] = { | 680 | static struct attribute *default_attrs[] = { |
693 | &cpuinfo_min_freq.attr, | 681 | &cpuinfo_min_freq.attr, |
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 3a147874a465..526bfbf69611 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c | |||
@@ -178,12 +178,8 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj, | |||
178 | return sprintf(buf, "%u\n", min_sampling_rate); | 178 | return sprintf(buf, "%u\n", min_sampling_rate); |
179 | } | 179 | } |
180 | 180 | ||
181 | #define define_one_ro(_name) \ | 181 | define_one_global_ro(sampling_rate_max); |
182 | static struct global_attr _name = \ | 182 | define_one_global_ro(sampling_rate_min); |
183 | __ATTR(_name, 0444, show_##_name, NULL) | ||
184 | |||
185 | define_one_ro(sampling_rate_max); | ||
186 | define_one_ro(sampling_rate_min); | ||
187 | 183 | ||
188 | /* cpufreq_conservative Governor Tunables */ | 184 | /* cpufreq_conservative Governor Tunables */ |
189 | #define show_one(file_name, object) \ | 185 | #define show_one(file_name, object) \ |
@@ -221,12 +217,8 @@ show_one_old(freq_step); | |||
221 | show_one_old(sampling_rate_min); | 217 | show_one_old(sampling_rate_min); |
222 | show_one_old(sampling_rate_max); | 218 | show_one_old(sampling_rate_max); |
223 | 219 | ||
224 | #define define_one_ro_old(object, _name) \ | 220 | cpufreq_freq_attr_ro_old(sampling_rate_min); |
225 | static struct freq_attr object = \ | 221 | cpufreq_freq_attr_ro_old(sampling_rate_max); |
226 | __ATTR(_name, 0444, show_##_name##_old, NULL) | ||
227 | |||
228 | define_one_ro_old(sampling_rate_min_old, sampling_rate_min); | ||
229 | define_one_ro_old(sampling_rate_max_old, sampling_rate_max); | ||
230 | 222 | ||
231 | /*** delete after deprecation time ***/ | 223 | /*** delete after deprecation time ***/ |
232 | 224 | ||
@@ -364,16 +356,12 @@ static ssize_t store_freq_step(struct kobject *a, struct attribute *b, | |||
364 | return count; | 356 | return count; |
365 | } | 357 | } |
366 | 358 | ||
367 | #define define_one_rw(_name) \ | 359 | define_one_global_rw(sampling_rate); |
368 | static struct global_attr _name = \ | 360 | define_one_global_rw(sampling_down_factor); |
369 | __ATTR(_name, 0644, show_##_name, store_##_name) | 361 | define_one_global_rw(up_threshold); |
370 | 362 | define_one_global_rw(down_threshold); | |
371 | define_one_rw(sampling_rate); | 363 | define_one_global_rw(ignore_nice_load); |
372 | define_one_rw(sampling_down_factor); | 364 | define_one_global_rw(freq_step); |
373 | define_one_rw(up_threshold); | ||
374 | define_one_rw(down_threshold); | ||
375 | define_one_rw(ignore_nice_load); | ||
376 | define_one_rw(freq_step); | ||
377 | 365 | ||
378 | static struct attribute *dbs_attributes[] = { | 366 | static struct attribute *dbs_attributes[] = { |
379 | &sampling_rate_max.attr, | 367 | &sampling_rate_max.attr, |
@@ -409,16 +397,12 @@ write_one_old(down_threshold); | |||
409 | write_one_old(ignore_nice_load); | 397 | write_one_old(ignore_nice_load); |
410 | write_one_old(freq_step); | 398 | write_one_old(freq_step); |
411 | 399 | ||
412 | #define define_one_rw_old(object, _name) \ | 400 | cpufreq_freq_attr_rw_old(sampling_rate); |
413 | static struct freq_attr object = \ | 401 | cpufreq_freq_attr_rw_old(sampling_down_factor); |
414 | __ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) | 402 | cpufreq_freq_attr_rw_old(up_threshold); |
415 | 403 | cpufreq_freq_attr_rw_old(down_threshold); | |
416 | define_one_rw_old(sampling_rate_old, sampling_rate); | 404 | cpufreq_freq_attr_rw_old(ignore_nice_load); |
417 | define_one_rw_old(sampling_down_factor_old, sampling_down_factor); | 405 | cpufreq_freq_attr_rw_old(freq_step); |
418 | define_one_rw_old(up_threshold_old, up_threshold); | ||
419 | define_one_rw_old(down_threshold_old, down_threshold); | ||
420 | define_one_rw_old(ignore_nice_load_old, ignore_nice_load); | ||
421 | define_one_rw_old(freq_step_old, freq_step); | ||
422 | 406 | ||
423 | static struct attribute *dbs_attributes_old[] = { | 407 | static struct attribute *dbs_attributes_old[] = { |
424 | &sampling_rate_max_old.attr, | 408 | &sampling_rate_max_old.attr, |
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index bd444dc93cf2..c00b25f4d243 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
@@ -234,12 +234,8 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj, | |||
234 | return sprintf(buf, "%u\n", min_sampling_rate); | 234 | return sprintf(buf, "%u\n", min_sampling_rate); |
235 | } | 235 | } |
236 | 236 | ||
237 | #define define_one_ro(_name) \ | 237 | define_one_global_ro(sampling_rate_max); |
238 | static struct global_attr _name = \ | 238 | define_one_global_ro(sampling_rate_min); |
239 | __ATTR(_name, 0444, show_##_name, NULL) | ||
240 | |||
241 | define_one_ro(sampling_rate_max); | ||
242 | define_one_ro(sampling_rate_min); | ||
243 | 239 | ||
244 | /* cpufreq_ondemand Governor Tunables */ | 240 | /* cpufreq_ondemand Governor Tunables */ |
245 | #define show_one(file_name, object) \ | 241 | #define show_one(file_name, object) \ |
@@ -274,12 +270,8 @@ show_one_old(powersave_bias); | |||
274 | show_one_old(sampling_rate_min); | 270 | show_one_old(sampling_rate_min); |
275 | show_one_old(sampling_rate_max); | 271 | show_one_old(sampling_rate_max); |
276 | 272 | ||
277 | #define define_one_ro_old(object, _name) \ | 273 | cpufreq_freq_attr_ro_old(sampling_rate_min); |
278 | static struct freq_attr object = \ | 274 | cpufreq_freq_attr_ro_old(sampling_rate_max); |
279 | __ATTR(_name, 0444, show_##_name##_old, NULL) | ||
280 | |||
281 | define_one_ro_old(sampling_rate_min_old, sampling_rate_min); | ||
282 | define_one_ro_old(sampling_rate_max_old, sampling_rate_max); | ||
283 | 275 | ||
284 | /*** delete after deprecation time ***/ | 276 | /*** delete after deprecation time ***/ |
285 | 277 | ||
@@ -376,14 +368,10 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, | |||
376 | return count; | 368 | return count; |
377 | } | 369 | } |
378 | 370 | ||
379 | #define define_one_rw(_name) \ | 371 | define_one_global_rw(sampling_rate); |
380 | static struct global_attr _name = \ | 372 | define_one_global_rw(up_threshold); |
381 | __ATTR(_name, 0644, show_##_name, store_##_name) | 373 | define_one_global_rw(ignore_nice_load); |
382 | 374 | define_one_global_rw(powersave_bias); | |
383 | define_one_rw(sampling_rate); | ||
384 | define_one_rw(up_threshold); | ||
385 | define_one_rw(ignore_nice_load); | ||
386 | define_one_rw(powersave_bias); | ||
387 | 375 | ||
388 | static struct attribute *dbs_attributes[] = { | 376 | static struct attribute *dbs_attributes[] = { |
389 | &sampling_rate_max.attr, | 377 | &sampling_rate_max.attr, |
@@ -415,14 +403,10 @@ write_one_old(up_threshold); | |||
415 | write_one_old(ignore_nice_load); | 403 | write_one_old(ignore_nice_load); |
416 | write_one_old(powersave_bias); | 404 | write_one_old(powersave_bias); |
417 | 405 | ||
418 | #define define_one_rw_old(object, _name) \ | 406 | cpufreq_freq_attr_rw_old(sampling_rate); |
419 | static struct freq_attr object = \ | 407 | cpufreq_freq_attr_rw_old(up_threshold); |
420 | __ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) | 408 | cpufreq_freq_attr_rw_old(ignore_nice_load); |
421 | 409 | cpufreq_freq_attr_rw_old(powersave_bias); | |
422 | define_one_rw_old(sampling_rate_old, sampling_rate); | ||
423 | define_one_rw_old(up_threshold_old, up_threshold); | ||
424 | define_one_rw_old(ignore_nice_load_old, ignore_nice_load); | ||
425 | define_one_rw_old(powersave_bias_old, powersave_bias); | ||
426 | 410 | ||
427 | static struct attribute *dbs_attributes_old[] = { | 411 | static struct attribute *dbs_attributes_old[] = { |
428 | &sampling_rate_max_old.attr, | 412 | &sampling_rate_max_old.attr, |
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 4de02b10007f..9f15150ce8d6 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
@@ -278,6 +278,27 @@ struct freq_attr { | |||
278 | ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count); | 278 | ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count); |
279 | }; | 279 | }; |
280 | 280 | ||
281 | #define cpufreq_freq_attr_ro(_name) \ | ||
282 | static struct freq_attr _name = \ | ||
283 | __ATTR(_name, 0444, show_##_name, NULL) | ||
284 | |||
285 | #define cpufreq_freq_attr_ro_perm(_name, _perm) \ | ||
286 | static struct freq_attr _name = \ | ||
287 | __ATTR(_name, _perm, show_##_name, NULL) | ||
288 | |||
289 | #define cpufreq_freq_attr_ro_old(_name) \ | ||
290 | static struct freq_attr _name##_old = \ | ||
291 | __ATTR(_name, 0444, show_##_name##_old, NULL) | ||
292 | |||
293 | #define cpufreq_freq_attr_rw(_name) \ | ||
294 | static struct freq_attr _name = \ | ||
295 | __ATTR(_name, 0644, show_##_name, store_##_name) | ||
296 | |||
297 | #define cpufreq_freq_attr_rw_old(_name) \ | ||
298 | static struct freq_attr _name##_old = \ | ||
299 | __ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) | ||
300 | |||
301 | |||
281 | struct global_attr { | 302 | struct global_attr { |
282 | struct attribute attr; | 303 | struct attribute attr; |
283 | ssize_t (*show)(struct kobject *kobj, | 304 | ssize_t (*show)(struct kobject *kobj, |
@@ -286,6 +307,15 @@ struct global_attr { | |||
286 | const char *c, size_t count); | 307 | const char *c, size_t count); |
287 | }; | 308 | }; |
288 | 309 | ||
310 | #define define_one_global_ro(_name) \ | ||
311 | static struct global_attr _name = \ | ||
312 | __ATTR(_name, 0444, show_##_name, NULL) | ||
313 | |||
314 | #define define_one_global_rw(_name) \ | ||
315 | static struct global_attr _name = \ | ||
316 | __ATTR(_name, 0644, show_##_name, store_##_name) | ||
317 | |||
318 | |||
289 | /********************************************************************* | 319 | /********************************************************************* |
290 | * CPUFREQ 2.6. INTERFACE * | 320 | * CPUFREQ 2.6. INTERFACE * |
291 | *********************************************************************/ | 321 | *********************************************************************/ |