aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2007-12-19 15:51:01 +0000
committerKeir Fraser <keir.fraser@citrix.com>2007-12-19 15:51:01 +0000
commit7f96e0454bd58cc3a5af4f3936fe18e9234e40e5 (patch)
tree64b17edf8337b89762491dab9de80395c9b33f73
parentdb9b8625ccaa654a9f0395ef500ee83f7b662320 (diff)
downloadxen-7f96e0454bd58cc3a5af4f3936fe18e9234e40e5.tar.gz
xen-7f96e0454bd58cc3a5af4f3936fe18e9234e40e5.tar.bz2
xen-7f96e0454bd58cc3a5af4f3936fe18e9234e40e5.zip
vmx: Do not set bit 1 of FEATURE_CONTROL MSR if SMX is not supported
by the CPU. Also generally beef up robustness of VMXON instruction. Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--xen/arch/x86/hvm/vmx/vmcs.c14
-rw-r--r--xen/arch/x86/traps.c6
-rw-r--r--xen/include/asm-x86/hvm/vmx/vmx.h30
3 files changed, 29 insertions, 21 deletions
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 1cb1746516..4ecbccef66 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -274,19 +274,13 @@ int vmx_cpu_up(void)
}
else
{
- eax = (IA32_FEATURE_CONTROL_MSR_LOCK |
- IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON_OUTSIDE_SMX |
- IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON_INSIDE_SMX);
+ eax = IA32_FEATURE_CONTROL_MSR_LOCK;
+ eax |= IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON_OUTSIDE_SMX;
+ if ( test_bit(X86_FEATURE_SMXE, &boot_cpu_data.x86_capability) )
+ eax |= IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON_INSIDE_SMX;
wrmsr(IA32_FEATURE_CONTROL_MSR, eax, 0);
}
- if ( !tboot_in_measured_env() &&
- !(eax & IA32_FEATURE_CONTROL_MSR_ENABLE_VMXON_OUTSIDE_SMX) )
- {
- printk("VMX only allowed in SMX but SMX not active.\n");
- return 0;
- }
-
vmx_init_vmcs_config();
INIT_LIST_HEAD(&this_cpu(active_vmcs_list));
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index d814e296aa..e8aa866239 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -719,6 +719,7 @@ asmlinkage void do_invalid_op(struct cpu_user_regs *regs)
struct bug_frame bug;
struct bug_frame_str bug_str;
char *filename, *predicate, *eip = (char *)regs->eip;
+ unsigned long fixup;
int id, lineno;
DEBUGGER_trap_entry(TRAP_invalid_op, regs);
@@ -789,6 +790,11 @@ asmlinkage void do_invalid_op(struct cpu_user_regs *regs)
predicate, filename, lineno);
die:
+ if ( (fixup = search_exception_table(regs->eip)) != 0 )
+ {
+ regs->eip = fixup;
+ return;
+ }
DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
show_execution_state(regs);
panic("FATAL TRAP: vector = %d (invalid opcode)\n", TRAP_invalid_op);
diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h
index be6e2d7429..af50427ed3 100644
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -240,23 +240,31 @@ static inline void __vm_clear_bit(unsigned long field, unsigned int bit)
__vmwrite(field, __vmread(field) & ~(1UL << bit));
}
-static inline void __vmxoff (void)
+static inline void __vmxoff(void)
{
- __asm__ __volatile__ ( VMXOFF_OPCODE
- ::: "memory");
+ asm volatile (
+ VMXOFF_OPCODE
+ : : : "memory" );
}
-static inline int __vmxon (u64 addr)
+static inline int __vmxon(u64 addr)
{
int rc;
- __asm__ __volatile__ ( VMXON_OPCODE
- MODRM_EAX_06
- /* CF==1 or ZF==1 --> rc = -1 */
- "setna %b0 ; neg %0"
- : "=q" (rc)
- : "0" (0), "a" (&addr)
- : "memory");
+ asm volatile (
+ "1: " VMXON_OPCODE MODRM_EAX_06 "\n"
+ " setna %b0 ; neg %0\n" /* CF==1 or ZF==1 --> rc = -1 */
+ "2:\n"
+ ".section .fixup,\"ax\"\n"
+ "3: not %0 ; jmp 2b\n" /* #UD --> rc = -1 */
+ ".previous\n"
+ ".section __ex_table,\"a\"\n"
+ " "__FIXUP_ALIGN"\n"
+ " "__FIXUP_WORD" 1b,3b\n"
+ ".previous\n"
+ : "=q" (rc)
+ : "0" (0), "a" (&addr)
+ : "memory");
return rc;
}