mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
vmx: add the support of XSAVE/XRSTOR to VMX guest
XSAVE/XRSTOR manages the existing and future processor extended states on x86 architecture. The XSAVE/XRSTOR infrastructure is defined in Intel SDMs: http://www.intel.com/products/processor/manuals/ The patch uses the classical CR0.TS based algorithm to manage the states on context switch. At present, we know 3 bits in the XFEATURE_ENABLED_MASK: FPU, SSE and YMM. YMM is defined in Intel AVX Programming Reference: http://software.intel.com/sites/avx/ Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
This commit is contained in:
1 parent
341c0e113f
commit
fb7925518f
13 files changed
+295
-11
No files matched your search
@@ -28,7 +28,7 @@
|
||||
#define clear_bit(idx, dst) ((dst) &= ~(1u << ((idx) & 31)))
|
||||
#define set_bit(idx, dst) ((dst) |= (1u << ((idx) & 31)))
|
||||
|
||||
#define DEF_MAX_BASE 0x00000004u
|
||||
#define DEF_MAX_BASE 0x0000000du
|
||||
#define DEF_MAX_EXT 0x80000008u
|
||||
|
||||
static int hypervisor_is_64bit(int xc)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/mpspec.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/i387.h>
|
||||
#include <mach_apic.h>
|
||||
#include <asm/hvm/support.h>
|
||||
|
||||
@@ -28,6 +29,9 @@ static unsigned int opt_cpuid_mask_ecx, opt_cpuid_mask_edx;
|
||||
integer_param("cpuid_mask_ecx", opt_cpuid_mask_ecx);
|
||||
integer_param("cpuid_mask_edx", opt_cpuid_mask_edx);
|
||||
|
||||
static int use_xsave = 1;
|
||||
boolean_param("xsave", use_xsave);
|
||||
|
||||
#ifdef CONFIG_X86_INTEL_USERCOPY
|
||||
/*
|
||||
* Alignment at which movsl is preferred for bulk memory copies.
|
||||
@@ -233,6 +237,12 @@ static void __devinit init_intel(struct cpuinfo_x86 *c)
|
||||
set_bit(X86_FEATURE_ARAT, c->x86_capability);
|
||||
|
||||
start_vmx();
|
||||
|
||||
if ( !use_xsave )
|
||||
clear_bit(X86_FEATURE_XSAVE, boot_cpu_data.x86_capability);
|
||||
|
||||
if ( cpu_has_xsave )
|
||||
xsave_init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/i387.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/mc146818rtc.h>
|
||||
#include <asm/spinlock.h>
|
||||
@@ -753,6 +754,18 @@ int hvm_vcpu_initialise(struct vcpu *v)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ( cpu_has_xsave )
|
||||
{
|
||||
/* XSAVE/XRSTOR requires the save area be 64-byte-boundary aligned. */
|
||||
void *xsave_area = _xmalloc(xsave_cntxt_size, 64);
|
||||
if ( xsave_area == NULL )
|
||||
return -ENOMEM;
|
||||
|
||||
xsave_init_save_area(xsave_area);
|
||||
v->arch.hvm_vcpu.xsave_area = xsave_area;
|
||||
v->arch.hvm_vcpu.xfeature_mask = XSTATE_FP_SSE;
|
||||
}
|
||||
|
||||
if ( (rc = vlapic_init(v)) != 0 )
|
||||
goto fail1;
|
||||
|
||||
@@ -815,6 +828,7 @@ void hvm_vcpu_destroy(struct vcpu *v)
|
||||
hvm_vcpu_cacheattr_destroy(v);
|
||||
vlapic_destroy(v);
|
||||
hvm_funcs.vcpu_destroy(v);
|
||||
xfree(v->arch.hvm_vcpu.xsave_area);
|
||||
|
||||
/* Event channel is already freed by evtchn_destroy(). */
|
||||
/*free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port);*/
|
||||
@@ -1771,6 +1785,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
|
||||
unsigned int *ecx, unsigned int *edx)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
unsigned int count = *ecx;
|
||||
|
||||
if ( cpuid_viridian_leaves(input, eax, ebx, ecx, edx) )
|
||||
return;
|
||||
@@ -1788,11 +1803,53 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
|
||||
*ebx |= (v->vcpu_id * 2) << 24;
|
||||
if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
|
||||
__clear_bit(X86_FEATURE_APIC & 31, edx);
|
||||
|
||||
/* Fix up XSAVE and OSXSAVE. */
|
||||
*ecx &= ~(bitmaskof(X86_FEATURE_XSAVE) |
|
||||
bitmaskof(X86_FEATURE_OSXSAVE));
|
||||
if ( cpu_has_xsave )
|
||||
{
|
||||
*ecx |= bitmaskof(X86_FEATURE_XSAVE);
|
||||
*ecx |= (v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSXSAVE) ?
|
||||
bitmaskof(X86_FEATURE_OSXSAVE) : 0;
|
||||
}
|
||||
break;
|
||||
case 0xb:
|
||||
/* Fix the x2APIC identifier. */
|
||||
*edx = v->vcpu_id * 2;
|
||||
break;
|
||||
case 0xd:
|
||||
if ( cpu_has_xsave )
|
||||
{
|
||||
/*
|
||||
* Fix up "Processor Extended State Enumeration". We only present
|
||||
* FPU(bit0) and SSE(bit1) to HVM guest for now.
|
||||
*/
|
||||
*eax = *ebx = *ecx = *edx = 0;
|
||||
switch ( count )
|
||||
{
|
||||
case 0:
|
||||
/* No HW defines bit in EDX yet. */
|
||||
*edx = 0;
|
||||
/* We only enable the features we know. */
|
||||
*eax = xfeature_low;
|
||||
/* FP/SSE + XSAVE.HEADER + YMM. */
|
||||
*ecx = 512 + 64 + ((*eax & XSTATE_YMM) ? XSTATE_YMM_SIZE : 0);
|
||||
/* Let ebx equal ecx at present. */
|
||||
*ebx = *ecx;
|
||||
break;
|
||||
case 2:
|
||||
if ( !(xfeature_low & XSTATE_YMM) )
|
||||
break;
|
||||
*eax = XSTATE_YMM_SIZE;
|
||||
*ebx = XSTATE_YMM_OFFSET;
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -629,7 +629,7 @@ static int construct_vmcs(struct vcpu *v)
|
||||
/* Host control registers. */
|
||||
v->arch.hvm_vmx.host_cr0 = read_cr0() | X86_CR0_TS;
|
||||
__vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0);
|
||||
__vmwrite(HOST_CR4, mmu_cr4_features);
|
||||
__vmwrite(HOST_CR4, mmu_cr4_features | (cpu_has_xsave ? X86_CR4_OSXSAVE : 0));
|
||||
|
||||
/* Host CS:RIP. */
|
||||
__vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS);
|
||||
|
||||
@@ -669,10 +669,14 @@ static void vmx_ctxt_switch_from(struct vcpu *v)
|
||||
static void vmx_ctxt_switch_to(struct vcpu *v)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
unsigned long old_cr4 = read_cr4(), new_cr4 = mmu_cr4_features;
|
||||
|
||||
/* HOST_CR4 in VMCS is always mmu_cr4_features. Sync CR4 now. */
|
||||
if ( unlikely(read_cr4() != mmu_cr4_features) )
|
||||
write_cr4(mmu_cr4_features);
|
||||
/* HOST_CR4 in VMCS is always mmu_cr4_features and
|
||||
* CR4_OSXSAVE(if supported). Sync CR4 now. */
|
||||
if ( cpu_has_xsave )
|
||||
new_cr4 |= X86_CR4_OSXSAVE;
|
||||
if ( old_cr4 != new_cr4 )
|
||||
write_cr4(new_cr4);
|
||||
|
||||
if ( d->arch.hvm_domain.hap_enabled )
|
||||
{
|
||||
@@ -2317,6 +2321,30 @@ static int vmx_handle_eoi_write(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vmx_handle_xsetbv(u64 new_bv)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
u64 xfeature = (((u64)xfeature_high) << 32) | xfeature_low;
|
||||
struct segment_register sreg;
|
||||
|
||||
hvm_get_segment_register(v, x86_seg_ss, &sreg);
|
||||
if ( sreg.attr.fields.dpl != 0 )
|
||||
goto err;
|
||||
|
||||
if ( ((new_bv ^ xfeature) & ~xfeature) || !(new_bv & 1) )
|
||||
goto err;
|
||||
|
||||
if ( (xfeature & XSTATE_YMM & new_bv) && !(new_bv & XSTATE_SSE) )
|
||||
goto err;
|
||||
|
||||
v->arch.hvm_vcpu.xfeature_mask = new_bv;
|
||||
set_xcr0(new_bv);
|
||||
return 0;
|
||||
err:
|
||||
vmx_inject_hw_exception(TRAP_gp_fault, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
{
|
||||
unsigned int exit_reason, idtv_info;
|
||||
@@ -2668,6 +2696,17 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
do_sched_op_compat(SCHEDOP_yield, 0);
|
||||
break;
|
||||
|
||||
case EXIT_REASON_XSETBV:
|
||||
{
|
||||
u64 new_bv = (((u64)regs->edx) << 32) | regs->eax;
|
||||
if ( vmx_handle_xsetbv(new_bv) == 0 )
|
||||
{
|
||||
inst_len = __get_instruction_length();
|
||||
__update_guest_eip(inst_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
exit_and_crash:
|
||||
gdprintk(XENLOG_ERR, "Bad vmexit (reason %x)\n", exit_reason);
|
||||
|
||||
+75
-1
@@ -33,7 +33,11 @@ void save_init_fpu(struct vcpu *v)
|
||||
if ( cr0 & X86_CR0_TS )
|
||||
clts();
|
||||
|
||||
if ( cpu_has_fxsr )
|
||||
if ( cpu_has_xsave && is_hvm_vcpu(v) )
|
||||
{
|
||||
xsave(v);
|
||||
}
|
||||
else if ( cpu_has_fxsr )
|
||||
{
|
||||
#ifdef __i386__
|
||||
asm volatile (
|
||||
@@ -128,6 +132,76 @@ void restore_fpu(struct vcpu *v)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Maximum size (in byte) of the XSAVE/XRSTOR save area required by all
|
||||
* the supported and enabled features on the processor, including the
|
||||
* XSAVE.HEADER. We only enable XCNTXT_MASK that we have known.
|
||||
*/
|
||||
u32 xsave_cntxt_size;
|
||||
|
||||
/* A 64-bit bitmask of the XSAVE/XRSTOR features supported by processor. */
|
||||
u32 xfeature_low, xfeature_high;
|
||||
|
||||
void xsave_init(void)
|
||||
{
|
||||
u32 eax, ebx, ecx, edx;
|
||||
int cpu = smp_processor_id();
|
||||
u32 min_size;
|
||||
|
||||
cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
printk("%s: cpu%d: cntxt_max_size: 0x%x and states: %08x:%08x\n",
|
||||
__func__, cpu, ecx, edx, eax);
|
||||
|
||||
if ( ((eax & XSTATE_FP_SSE) != XSTATE_FP_SSE) ||
|
||||
((eax & XSTATE_YMM) && !(eax & XSTATE_SSE)) )
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* FP/SSE, XSAVE.HEADER, YMM */
|
||||
min_size = 512 + 64 + ((eax & XSTATE_YMM) ? XSTATE_YMM_SIZE : 0);
|
||||
BUG_ON(ecx < min_size);
|
||||
|
||||
/*
|
||||
* We will only enable the features we know for hvm guest. Here we use
|
||||
* set/clear CR4_OSXSAVE and re-run cpuid to get xsave_cntxt_size.
|
||||
*/
|
||||
set_in_cr4(X86_CR4_OSXSAVE);
|
||||
set_xcr0(eax & XCNTXT_MASK);
|
||||
cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
|
||||
clear_in_cr4(X86_CR4_OSXSAVE);
|
||||
|
||||
if ( cpu == 0 )
|
||||
{
|
||||
/*
|
||||
* xsave_cntxt_size is the max size required by enabled features.
|
||||
* We know FP/SSE and YMM about eax, and nothing about edx at present.
|
||||
*/
|
||||
xsave_cntxt_size = ebx;
|
||||
xfeature_low = eax & XCNTXT_MASK;
|
||||
xfeature_high = 0;
|
||||
printk("%s: using cntxt_size: 0x%x and states: %08x:%08x\n",
|
||||
__func__, xsave_cntxt_size, xfeature_high, xfeature_low);
|
||||
}
|
||||
else
|
||||
{
|
||||
BUG_ON(xsave_cntxt_size != ebx);
|
||||
BUG_ON(xfeature_low != (eax & XCNTXT_MASK));
|
||||
}
|
||||
}
|
||||
|
||||
void xsave_init_save_area(void *save_area)
|
||||
{
|
||||
memset(save_area, 0, xsave_cntxt_size);
|
||||
|
||||
((u16 *)save_area)[0] = 0x37f; /* FCW */
|
||||
((u16 *)save_area)[2] = 0xffff; /* FTW */
|
||||
((u32 *)save_area)[6] = 0x1f80; /* MXCSR */
|
||||
|
||||
((struct xsave_struct *)save_area)->xsave_hdr.xstate_bv = XSTATE_FP_SSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
#define X86_FEATURE_X2APIC (4*32+21) /* Extended xAPIC */
|
||||
#define X86_FEATURE_POPCNT (4*32+23) /* POPCNT instruction */
|
||||
#define X86_FEATURE_XSAVE (4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
|
||||
#define X86_FEATURE_OSXSAVE (4*32+27) /* OSXSAVE */
|
||||
#define X86_FEATURE_HYPERVISOR (4*32+31) /* Running under some hypervisor */
|
||||
|
||||
/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
|
||||
@@ -189,6 +190,9 @@
|
||||
&& boot_cpu_has(X86_FEATURE_FFXSR))
|
||||
|
||||
#define cpu_has_x2apic boot_cpu_has(X86_FEATURE_X2APIC)
|
||||
|
||||
#define cpu_has_xsave boot_cpu_has(X86_FEATURE_XSAVE)
|
||||
|
||||
#define cpu_has_arch_perfmon boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
|
||||
|
||||
#endif /* __ASM_I386_CPUFEATURE_H */
|
||||
|
||||
@@ -440,7 +440,7 @@ unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4);
|
||||
| ((v)->domain->arch.vtsc ? X86_CR4_TSD : 0)) \
|
||||
& ~X86_CR4_DE)
|
||||
#define real_cr4_to_pv_guest_cr4(c) \
|
||||
((c) & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_TSD))
|
||||
((c) & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_TSD | X86_CR4_OSXSAVE))
|
||||
|
||||
void domain_cpuid(struct domain *d,
|
||||
unsigned int input,
|
||||
|
||||
@@ -268,7 +268,8 @@ static inline int hvm_do_pmu_interrupt(struct cpu_user_regs *regs)
|
||||
(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | \
|
||||
X86_CR4_DE | X86_CR4_PSE | X86_CR4_PAE | \
|
||||
X86_CR4_MCE | X86_CR4_PGE | X86_CR4_PCE | \
|
||||
X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT)))
|
||||
X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT | \
|
||||
(cpu_has_xsave ? X86_CR4_OSXSAVE : 0))))
|
||||
|
||||
/* These exceptions must always be intercepted. */
|
||||
#define HVM_TRAP_MASK ((1U << TRAP_machine_check) | (1U << TRAP_invalid_op))
|
||||
|
||||
@@ -47,6 +47,15 @@ struct hvm_vcpu {
|
||||
*/
|
||||
unsigned long hw_cr[5];
|
||||
|
||||
/*
|
||||
* The save area for Processor Extended States and the bitmask of the
|
||||
* XSAVE/XRSTOR features. They are used by: 1) when a vcpu (which has
|
||||
* dirtied FPU/SSE) is scheduled out we XSAVE the states here; 2) in
|
||||
* #NM handler, we XRSTOR the states we XSAVE-ed;
|
||||
*/
|
||||
void *xsave_area;
|
||||
uint64_t xfeature_mask;
|
||||
|
||||
struct vlapic vlapic;
|
||||
s64 cache_tsc_offset;
|
||||
u64 guest_time;
|
||||
|
||||
@@ -111,6 +111,7 @@ void vmx_update_debug_state(struct vcpu *v);
|
||||
#define EXIT_REASON_EPT_VIOLATION 48
|
||||
#define EXIT_REASON_EPT_MISCONFIG 49
|
||||
#define EXIT_REASON_WBINVD 54
|
||||
#define EXIT_REASON_XSETBV 55
|
||||
|
||||
/*
|
||||
* Interruption-information format
|
||||
|
||||
@@ -14,6 +14,82 @@
|
||||
#include <xen/sched.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
extern unsigned int xsave_cntxt_size;
|
||||
extern u32 xfeature_low, xfeature_high;
|
||||
|
||||
extern void xsave_init(void);
|
||||
extern void xsave_init_save_area(void *save_area);
|
||||
|
||||
#define XSTATE_FP (1 << 0)
|
||||
#define XSTATE_SSE (1 << 1)
|
||||
#define XSTATE_YMM (1 << 2)
|
||||
#define XSTATE_FP_SSE (XSTATE_FP | XSTATE_SSE)
|
||||
#define XCNTXT_MASK (XSTATE_FP | XSTATE_SSE | XSTATE_YMM)
|
||||
#define XSTATE_YMM_OFFSET (512 + 64)
|
||||
#define XSTATE_YMM_SIZE 256
|
||||
|
||||
struct xsave_struct
|
||||
{
|
||||
struct { char x[512]; } fpu_sse; /* FPU/MMX, SSE */
|
||||
|
||||
struct {
|
||||
u64 xstate_bv;
|
||||
u64 reserved[7];
|
||||
} xsave_hdr; /* The 64-byte header */
|
||||
|
||||
struct { char x[XSTATE_YMM_SIZE]; } ymm; /* YMM */
|
||||
char data[]; /* Future new states */
|
||||
} __attribute__ ((packed, aligned (64)));
|
||||
|
||||
#define XCR_XFEATURE_ENABLED_MASK 0
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
#define REX_PREFIX "0x48, "
|
||||
#else
|
||||
#define REX_PREFIX
|
||||
#endif
|
||||
|
||||
static inline void xsetbv(u32 index, u64 xfeature_mask)
|
||||
{
|
||||
u32 hi = xfeature_mask >> 32;
|
||||
u32 lo = (u32)xfeature_mask;
|
||||
|
||||
asm volatile (".byte 0x0f,0x01,0xd1" :: "c" (index),
|
||||
"a" (lo), "d" (hi));
|
||||
}
|
||||
|
||||
static inline void set_xcr0(u64 xfeature_mask)
|
||||
{
|
||||
xsetbv(XCR_XFEATURE_ENABLED_MASK, xfeature_mask);
|
||||
}
|
||||
|
||||
static inline void xsave(struct vcpu *v)
|
||||
{
|
||||
u64 mask = v->arch.hvm_vcpu.xfeature_mask | XSTATE_FP_SSE;
|
||||
u32 lo = mask, hi = mask >> 32;
|
||||
struct xsave_struct *ptr;
|
||||
|
||||
ptr =(struct xsave_struct *)v->arch.hvm_vcpu.xsave_area;
|
||||
|
||||
asm volatile (".byte " REX_PREFIX "0x0f,0xae,0x27"
|
||||
:
|
||||
: "a" (lo), "d" (hi), "D"(ptr)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static inline void xrstor(struct vcpu *v)
|
||||
{
|
||||
u64 mask = v->arch.hvm_vcpu.xfeature_mask | XSTATE_FP_SSE;
|
||||
u32 lo = mask, hi = mask >> 32;
|
||||
struct xsave_struct *ptr;
|
||||
|
||||
ptr =(struct xsave_struct *)v->arch.hvm_vcpu.xsave_area;
|
||||
|
||||
asm volatile (".byte " REX_PREFIX "0x0f,0xae,0x2f"
|
||||
:
|
||||
: "m" (*ptr), "a" (lo), "d" (hi), "D"(ptr));
|
||||
}
|
||||
|
||||
extern void init_fpu(void);
|
||||
extern void save_init_fpu(struct vcpu *v);
|
||||
extern void restore_fpu(struct vcpu *v);
|
||||
@@ -36,10 +112,22 @@ static inline void setup_fpu(struct vcpu *v)
|
||||
if ( !v->fpu_dirtied )
|
||||
{
|
||||
v->fpu_dirtied = 1;
|
||||
if ( v->fpu_initialised )
|
||||
restore_fpu(v);
|
||||
if ( cpu_has_xsave && is_hvm_vcpu(v) )
|
||||
{
|
||||
if ( !v->fpu_initialised )
|
||||
v->fpu_initialised = 1;
|
||||
|
||||
set_xcr0(v->arch.hvm_vcpu.xfeature_mask | XSTATE_FP_SSE);
|
||||
xrstor(v);
|
||||
set_xcr0(v->arch.hvm_vcpu.xfeature_mask);
|
||||
}
|
||||
else
|
||||
init_fpu();
|
||||
{
|
||||
if ( v->fpu_initialised )
|
||||
restore_fpu(v);
|
||||
else
|
||||
init_fpu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
#define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */
|
||||
#define X86_CR4_VMXE 0x2000 /* enable VMX */
|
||||
#define X86_CR4_SMXE 0x4000 /* enable SMX */
|
||||
#define X86_CR4_OSXSAVE 0x40000 /* enable XSAVE/XRSTOR */
|
||||
|
||||
/*
|
||||
* Trap/fault mnemonics.
|
||||
|
||||