diff options
-rw-r--r-- | xen/arch/x86/cpu/common.c | 5 | ||||
-rw-r--r-- | xen/arch/x86/domain.c | 6 | ||||
-rw-r--r-- | xen/arch/x86/traps.c | 2 | ||||
-rw-r--r-- | xen/include/asm-x86/cpufeature.h | 7 | ||||
-rw-r--r-- | xen/include/asm-x86/domain.h | 2 | ||||
-rw-r--r-- | xen/include/asm-x86/processor.h | 1 |
6 files changed, 18 insertions, 5 deletions
diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c index ebe96a2f0d..fb6d67c983 100644 --- a/xen/arch/x86/cpu/common.c +++ b/xen/arch/x86/cpu/common.c @@ -311,6 +311,11 @@ void __cpuinit generic_identify(struct cpuinfo_x86 * c) if ( xlvl >= 0x80000004 ) get_model_name(c); /* Default name */ } + + /* Intel-defined flags: level 0x00000007 */ + if ( c->cpuid_level >= 0x00000007 ) + c->x86_capability[X86_FEATURE_FSGSBASE / 32] + = cpuid_ebx(0x00000007); } early_intel_workaround(c); diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 9c5a7b5a97..b67ddd6a00 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -583,13 +583,15 @@ void arch_domain_destroy(struct domain *d) xfree(d->arch.irq_pirq); } -unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4) +unsigned long pv_guest_cr4_fixup(const struct vcpu *v, unsigned long guest_cr4) { unsigned long hv_cr4_mask, hv_cr4 = real_cr4_to_pv_guest_cr4(read_cr4()); hv_cr4_mask = ~X86_CR4_TSD; if ( cpu_has_de ) hv_cr4_mask &= ~X86_CR4_DE; + if ( cpu_has_fsgsbase && !is_pv_32bit_domain(v->domain) ) + hv_cr4_mask &= ~X86_CR4_FSGSBASE; if ( (guest_cr4 & hv_cr4_mask) != (hv_cr4 & hv_cr4_mask) ) gdprintk(XENLOG_WARNING, @@ -700,7 +702,7 @@ int arch_set_info_guest( v->arch.guest_context.user_regs.eflags |= X86_EFLAGS_IF; cr4 = v->arch.guest_context.ctrlreg[4]; - v->arch.guest_context.ctrlreg[4] = cr4 ? pv_guest_cr4_fixup(cr4) : + v->arch.guest_context.ctrlreg[4] = cr4 ? pv_guest_cr4_fixup(v, cr4) : real_cr4_to_pv_guest_cr4(mmu_cr4_features); memset(v->arch.guest_context.debugreg, 0, diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index e811f6257c..fa3f48ebb8 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -2176,7 +2176,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) break; case 4: /* Write CR4 */ - v->arch.guest_context.ctrlreg[4] = pv_guest_cr4_fixup(*reg); + v->arch.guest_context.ctrlreg[4] = pv_guest_cr4_fixup(v, *reg); write_cr4(pv_guest_cr4_to_real_cr4(v)); break; diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h index 09d8307fca..f9b42f8636 100644 --- a/xen/include/asm-x86/cpufeature.h +++ b/xen/include/asm-x86/cpufeature.h @@ -9,7 +9,7 @@ #include <xen/bitops.h> -#define NCAPINTS 7 /* N 32-bit words worth of info */ +#define NCAPINTS 8 /* N 32-bit words worth of info */ /* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ #define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ @@ -131,6 +131,9 @@ #define X86_FEATURE_SKINIT (6*32+ 12) /* SKINIT, STGI/CLGI, DEV */ #define X86_FEATURE_WDT (6*32+ 13) /* Watchdog Timer */ +/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ +#define X86_FEATURE_FSGSBASE (7*32+ 0) /* {RD,WR}{FS,GS}BASE instructions */ + #define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) #define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability) @@ -159,6 +162,7 @@ #define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLSH) #define cpu_has_page1gb 0 #define cpu_has_efer (boot_cpu_data.x86_capability[1] & 0x20100800) +#define cpu_has_fsgsbase 0 #else /* __x86_64__ */ #define cpu_has_vme 0 #define cpu_has_de 1 @@ -184,6 +188,7 @@ #define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLSH) #define cpu_has_page1gb boot_cpu_has(X86_FEATURE_PAGE1GB) #define cpu_has_efer 1 +#define cpu_has_fsgsbase boot_cpu_has(X86_FEATURE_FSGSBASE) #endif #define cpu_has_ffxsr ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) \ diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 559a1deea1..7549126504 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -429,7 +429,7 @@ void vcpu_show_execution_state(struct vcpu *); void vcpu_show_registers(const struct vcpu *); /* Clean up CR4 bits that are not under guest control. */ -unsigned long pv_guest_cr4_fixup(unsigned long guest_cr4); +unsigned long pv_guest_cr4_fixup(const struct vcpu *, unsigned long guest_cr4); /* Convert between guest-visible and real CR4 values. */ #define pv_guest_cr4_to_real_cr4(v) \ diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index 35efc68468..7c24013cc2 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -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_FSGSBASE 0x10000 /* enable {rd,wr}{fs,gs}base */ #define X86_CR4_OSXSAVE 0x40000 /* enable XSAVE/XRSTOR */ /* |