aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/xen/enlighten.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/xen/enlighten.c')
-rw-r--r--arch/x86/xen/enlighten.c99
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)
200static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0; 209static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0;
201static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0; 210static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0;
202 211
212static __read_mostly unsigned int cpuid_leaf1_ecx_set_mask;
213static __read_mostly unsigned int cpuid_leaf5_ecx_val;
214static __read_mostly unsigned int cpuid_leaf5_edx_val;
215
203static void xen_cpuid(unsigned int *ax, unsigned int *bx, 216static 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
262static 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}
238static void __init xen_init_cpuid_mask(void) 326static 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
266static void xen_set_debugreg(int reg, unsigned long val) 357static void xen_set_debugreg(int reg, unsigned long val)
@@ -777,11 +868,11 @@ static DEFINE_PER_CPU(unsigned long, xen_cr0_value);
777 868
778static unsigned long xen_read_cr0(void) 869static 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. */