diff options
Diffstat (limited to 'arch/x86/xen/enlighten.c')
-rw-r--r-- | arch/x86/xen/enlighten.c | 99 |
1 files changed, 95 insertions, 4 deletions
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 4172af8ceeb3..b132ade26f77 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c | |||
@@ -62,6 +62,15 @@ | |||
62 | #include <asm/reboot.h> | 62 | #include <asm/reboot.h> |
63 | #include <asm/stackprotector.h> | 63 | #include <asm/stackprotector.h> |
64 | #include <asm/hypervisor.h> | 64 | #include <asm/hypervisor.h> |
65 | #include <asm/mwait.h> | ||
66 | |||
67 | #ifdef CONFIG_ACPI | ||
68 | #include <linux/acpi.h> | ||
69 | #include <asm/acpi.h> | ||
70 | #include <acpi/pdc_intel.h> | ||
71 | #include <acpi/processor.h> | ||
72 | #include <xen/interface/platform.h> | ||
73 | #endif | ||
65 | 74 | ||
66 | #include "xen-ops.h" | 75 | #include "xen-ops.h" |
67 | #include "mmu.h" | 76 | #include "mmu.h" |
@@ -200,13 +209,17 @@ static void __init xen_banner(void) | |||
200 | static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0; | 209 | static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0; |
201 | static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0; | 210 | static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0; |
202 | 211 | ||
212 | static __read_mostly unsigned int cpuid_leaf1_ecx_set_mask; | ||
213 | static __read_mostly unsigned int cpuid_leaf5_ecx_val; | ||
214 | static __read_mostly unsigned int cpuid_leaf5_edx_val; | ||
215 | |||
203 | static void xen_cpuid(unsigned int *ax, unsigned int *bx, | 216 | static void xen_cpuid(unsigned int *ax, unsigned int *bx, |
204 | unsigned int *cx, unsigned int *dx) | 217 | unsigned int *cx, unsigned int *dx) |
205 | { | 218 | { |
206 | unsigned maskebx = ~0; | 219 | unsigned maskebx = ~0; |
207 | unsigned maskecx = ~0; | 220 | unsigned maskecx = ~0; |
208 | unsigned maskedx = ~0; | 221 | unsigned maskedx = ~0; |
209 | 222 | unsigned setecx = 0; | |
210 | /* | 223 | /* |
211 | * Mask out inconvenient features, to try and disable as many | 224 | * Mask out inconvenient features, to try and disable as many |
212 | * unsupported kernel subsystems as possible. | 225 | * unsupported kernel subsystems as possible. |
@@ -214,9 +227,18 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, | |||
214 | switch (*ax) { | 227 | switch (*ax) { |
215 | case 1: | 228 | case 1: |
216 | maskecx = cpuid_leaf1_ecx_mask; | 229 | maskecx = cpuid_leaf1_ecx_mask; |
230 | setecx = cpuid_leaf1_ecx_set_mask; | ||
217 | maskedx = cpuid_leaf1_edx_mask; | 231 | maskedx = cpuid_leaf1_edx_mask; |
218 | break; | 232 | break; |
219 | 233 | ||
234 | case CPUID_MWAIT_LEAF: | ||
235 | /* Synthesize the values.. */ | ||
236 | *ax = 0; | ||
237 | *bx = 0; | ||
238 | *cx = cpuid_leaf5_ecx_val; | ||
239 | *dx = cpuid_leaf5_edx_val; | ||
240 | return; | ||
241 | |||
220 | case 0xb: | 242 | case 0xb: |
221 | /* Suppress extended topology stuff */ | 243 | /* Suppress extended topology stuff */ |
222 | maskebx = 0; | 244 | maskebx = 0; |
@@ -232,9 +254,75 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, | |||
232 | 254 | ||
233 | *bx &= maskebx; | 255 | *bx &= maskebx; |
234 | *cx &= maskecx; | 256 | *cx &= maskecx; |
257 | *cx |= setecx; | ||
235 | *dx &= maskedx; | 258 | *dx &= maskedx; |
259 | |||
236 | } | 260 | } |
237 | 261 | ||
262 | static bool __init xen_check_mwait(void) | ||
263 | { | ||
264 | #ifdef CONFIG_ACPI | ||
265 | struct xen_platform_op op = { | ||
266 | .cmd = XENPF_set_processor_pminfo, | ||
267 | .u.set_pminfo.id = -1, | ||
268 | .u.set_pminfo.type = XEN_PM_PDC, | ||
269 | }; | ||
270 | uint32_t buf[3]; | ||
271 | unsigned int ax, bx, cx, dx; | ||
272 | unsigned int mwait_mask; | ||
273 | |||
274 | /* We need to determine whether it is OK to expose the MWAIT | ||
275 | * capability to the kernel to harvest deeper than C3 states from ACPI | ||
276 | * _CST using the processor_harvest_xen.c module. For this to work, we | ||
277 | * need to gather the MWAIT_LEAF values (which the cstate.c code | ||
278 | * checks against). The hypervisor won't expose the MWAIT flag because | ||
279 | * it would break backwards compatibility; so we will find out directly | ||
280 | * from the hardware and hypercall. | ||
281 | */ | ||
282 | if (!xen_initial_domain()) | ||
283 | return false; | ||
284 | |||
285 | ax = 1; | ||
286 | cx = 0; | ||
287 | |||
288 | native_cpuid(&ax, &bx, &cx, &dx); | ||
289 | |||
290 | mwait_mask = (1 << (X86_FEATURE_EST % 32)) | | ||
291 | (1 << (X86_FEATURE_MWAIT % 32)); | ||
292 | |||
293 | if ((cx & mwait_mask) != mwait_mask) | ||
294 | return false; | ||
295 | |||
296 | /* We need to emulate the MWAIT_LEAF and for that we need both | ||
297 | * ecx and edx. The hypercall provides only partial information. | ||
298 | */ | ||
299 | |||
300 | ax = CPUID_MWAIT_LEAF; | ||
301 | bx = 0; | ||
302 | cx = 0; | ||
303 | dx = 0; | ||
304 | |||
305 | native_cpuid(&ax, &bx, &cx, &dx); | ||
306 | |||
307 | /* Ask the Hypervisor whether to clear ACPI_PDC_C_C2C3_FFH. If so, | ||
308 | * don't expose MWAIT_LEAF and let ACPI pick the IOPORT version of C3. | ||
309 | */ | ||
310 | buf[0] = ACPI_PDC_REVISION_ID; | ||
311 | buf[1] = 1; | ||
312 | buf[2] = (ACPI_PDC_C_CAPABILITY_SMP | ACPI_PDC_EST_CAPABILITY_SWSMP); | ||
313 | |||
314 | set_xen_guest_handle(op.u.set_pminfo.pdc, buf); | ||
315 | |||
316 | if ((HYPERVISOR_dom0_op(&op) == 0) && | ||
317 | (buf[2] & (ACPI_PDC_C_C1_FFH | ACPI_PDC_C_C2C3_FFH))) { | ||
318 | cpuid_leaf5_ecx_val = cx; | ||
319 | cpuid_leaf5_edx_val = dx; | ||
320 | } | ||
321 | return true; | ||
322 | #else | ||
323 | return false; | ||
324 | #endif | ||
325 | } | ||
238 | static void __init xen_init_cpuid_mask(void) | 326 | static void __init xen_init_cpuid_mask(void) |
239 | { | 327 | { |
240 | unsigned int ax, bx, cx, dx; | 328 | unsigned int ax, bx, cx, dx; |
@@ -261,6 +349,9 @@ static void __init xen_init_cpuid_mask(void) | |||
261 | /* Xen will set CR4.OSXSAVE if supported and not disabled by force */ | 349 | /* Xen will set CR4.OSXSAVE if supported and not disabled by force */ |
262 | if ((cx & xsave_mask) != xsave_mask) | 350 | if ((cx & xsave_mask) != xsave_mask) |
263 | cpuid_leaf1_ecx_mask &= ~xsave_mask; /* disable XSAVE & OSXSAVE */ | 351 | cpuid_leaf1_ecx_mask &= ~xsave_mask; /* disable XSAVE & OSXSAVE */ |
352 | |||
353 | if (xen_check_mwait()) | ||
354 | cpuid_leaf1_ecx_set_mask = (1 << (X86_FEATURE_MWAIT % 32)); | ||
264 | } | 355 | } |
265 | 356 | ||
266 | static void xen_set_debugreg(int reg, unsigned long val) | 357 | static void xen_set_debugreg(int reg, unsigned long val) |
@@ -777,11 +868,11 @@ static DEFINE_PER_CPU(unsigned long, xen_cr0_value); | |||
777 | 868 | ||
778 | static unsigned long xen_read_cr0(void) | 869 | static unsigned long xen_read_cr0(void) |
779 | { | 870 | { |
780 | unsigned long cr0 = percpu_read(xen_cr0_value); | 871 | unsigned long cr0 = this_cpu_read(xen_cr0_value); |
781 | 872 | ||
782 | if (unlikely(cr0 == 0)) { | 873 | if (unlikely(cr0 == 0)) { |
783 | cr0 = native_read_cr0(); | 874 | cr0 = native_read_cr0(); |
784 | percpu_write(xen_cr0_value, cr0); | 875 | this_cpu_write(xen_cr0_value, cr0); |
785 | } | 876 | } |
786 | 877 | ||
787 | return cr0; | 878 | return cr0; |
@@ -791,7 +882,7 @@ static void xen_write_cr0(unsigned long cr0) | |||
791 | { | 882 | { |
792 | struct multicall_space mcs; | 883 | struct multicall_space mcs; |
793 | 884 | ||
794 | percpu_write(xen_cr0_value, cr0); | 885 | this_cpu_write(xen_cr0_value, cr0); |
795 | 886 | ||
796 | /* Only pay attention to cr0.TS; everything else is | 887 | /* Only pay attention to cr0.TS; everything else is |
797 | ignored. */ | 888 | ignored. */ |