aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2010-10-24 13:17:07 +0100
committerKeir Fraser <keir@xen.org>2010-10-24 13:17:07 +0100
commitf9ee068de49cd18429fa786622b411044489cd5a (patch)
tree3bb0a5d243b7f64266ca3fa43d68d0a56fcb0568
parentc0d9c5e627c94e1712cd19a92e1e3c4d39efcae8 (diff)
downloadxen-f9ee068de49cd18429fa786622b411044489cd5a.tar.gz
xen-f9ee068de49cd18429fa786622b411044489cd5a.tar.bz2
xen-f9ee068de49cd18429fa786622b411044489cd5a.zip
x86: enable support for {rd,wr}{fs,gs}base instructions
... so that once in a while Xen knows of a new CPU feature before Linux starts making use of it. While (obviously) I wasn't able to test this, it seemed strait forward enough to enable anyway. Signed-off-by: Jan Beulich <jbeulich@novell.com>
-rw-r--r--xen/arch/x86/cpu/common.c5
-rw-r--r--xen/arch/x86/domain.c6
-rw-r--r--xen/arch/x86/traps.c2
-rw-r--r--xen/include/asm-x86/cpufeature.h7
-rw-r--r--xen/include/asm-x86/domain.h2
-rw-r--r--xen/include/asm-x86/processor.h1
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 */
/*