# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1168530218 0
# Node ID 866a167bcb49020768825b264dc8d91e25b0b90c
# Parent a84fc0de350d276cb2b3359102f6fda32bc18922
[HVM][VMX] Some simplifications, particularly to vmx_load/save_cpu_regs.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/vmx/vmx.c | 133 ++++++++++++++----------------------
xen/arch/x86/hvm/vmx/x86_32/exits.S | 2
xen/arch/x86/hvm/vmx/x86_64/exits.S | 2
3 files changed, 54 insertions(+), 83 deletions(-)
diff -r a84fc0de350d -r 866a167bcb49 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Thu Jan 11 11:41:44 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Jan 11 15:43:38 2007 +0000
@@ -410,10 +410,6 @@ static void vmx_store_cpu_guest_regs(
regs->eflags = __vmread(GUEST_RFLAGS);
regs->ss = __vmread(GUEST_SS_SELECTOR);
regs->cs = __vmread(GUEST_CS_SELECTOR);
- regs->ds = __vmread(GUEST_DS_SELECTOR);
- regs->es = __vmread(GUEST_ES_SELECTOR);
- regs->gs = __vmread(GUEST_GS_SELECTOR);
- regs->fs = __vmread(GUEST_FS_SELECTOR);
regs->eip = __vmread(GUEST_RIP);
regs->esp = __vmread(GUEST_RSP);
}
@@ -429,62 +425,39 @@ static void vmx_store_cpu_guest_regs(
vmx_vmcs_exit(v);
}
-/*
- * The VMX spec (section 4.3.1.2, Checks on Guest Segment
- * Registers) says that virtual-8086 mode guests' segment
- * base-address fields in the VMCS must be equal to their
- * corresponding segment selector field shifted right by
- * four bits upon vmentry.
- *
- * This function (called only for VM86-mode guests) fixes
- * the bases to be consistent with the selectors in regs
- * if they're not already. Without this, we can fail the
- * vmentry check mentioned above.
- */
-static void fixup_vm86_seg_bases(struct cpu_user_regs *regs)
+static void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
{
unsigned long base;
- base = __vmread(GUEST_ES_BASE);
- if (regs->es << 4 != base)
- __vmwrite(GUEST_ES_BASE, regs->es << 4);
- base = __vmread(GUEST_CS_BASE);
- if (regs->cs << 4 != base)
- __vmwrite(GUEST_CS_BASE, regs->cs << 4);
- base = __vmread(GUEST_SS_BASE);
- if (regs->ss << 4 != base)
- __vmwrite(GUEST_SS_BASE, regs->ss << 4);
- base = __vmread(GUEST_DS_BASE);
- if (regs->ds << 4 != base)
- __vmwrite(GUEST_DS_BASE, regs->ds << 4);
- base = __vmread(GUEST_FS_BASE);
- if (regs->fs << 4 != base)
- __vmwrite(GUEST_FS_BASE, regs->fs << 4);
- base = __vmread(GUEST_GS_BASE);
- if (regs->gs << 4 != base)
- __vmwrite(GUEST_GS_BASE, regs->gs << 4);
-}
-
-static void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
-{
vmx_vmcs_enter(v);
__vmwrite(GUEST_SS_SELECTOR, regs->ss);
- __vmwrite(GUEST_DS_SELECTOR, regs->ds);
- __vmwrite(GUEST_ES_SELECTOR, regs->es);
- __vmwrite(GUEST_GS_SELECTOR, regs->gs);
- __vmwrite(GUEST_FS_SELECTOR, regs->fs);
-
__vmwrite(GUEST_RSP, regs->esp);
/* NB. Bit 1 of RFLAGS must be set for VMENTRY to succeed. */
__vmwrite(GUEST_RFLAGS, regs->eflags | 2UL);
- if (regs->eflags & EF_TF)
+
+ if ( regs->eflags & EF_TF )
__vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
else
__vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
- if (regs->eflags & EF_VM)
- fixup_vm86_seg_bases(regs);
+
+ if ( regs->eflags & EF_VM )
+ {
+ /*
+ * The VMX spec (section 4.3.1.2, Checks on Guest Segment
+ * Registers) says that virtual-8086 mode guests' segment
+ * base-address fields in the VMCS must be equal to their
+ * corresponding segment selector field shifted right by
+ * four bits upon vmentry.
+ */
+ base = __vmread(GUEST_CS_BASE);
+ if ( (regs->cs << 4) != base )
+ __vmwrite(GUEST_CS_BASE, regs->cs << 4);
+ base = __vmread(GUEST_SS_BASE);
+ if ( (regs->ss << 4) != base )
+ __vmwrite(GUEST_SS_BASE, regs->ss << 4);
+ }
__vmwrite(GUEST_CS_SELECTOR, regs->cs);
__vmwrite(GUEST_RIP, regs->eip);
@@ -2251,47 +2224,54 @@ static void vmx_reflect_exception(struct
}
}
+static void vmx_failed_vmentry(unsigned int exit_reason)
+{
+ unsigned int failed_vmentry_reason = (uint16_t)exit_reason;
+ unsigned long exit_qualification;
+
+ exit_qualification = __vmread(EXIT_QUALIFICATION);
+ printk("Failed vm entry (exit reason 0x%x) ", exit_reason);
+ switch ( failed_vmentry_reason )
+ {
+ case EXIT_REASON_INVALID_GUEST_STATE:
+ printk("caused by invalid guest state (%ld).\n", exit_qualification);
+ break;
+ case EXIT_REASON_MSR_LOADING:
+ printk("caused by MSR entry %ld loading.\n", exit_qualification);
+ break;
+ case EXIT_REASON_MACHINE_CHECK:
+ printk("caused by machine check.\n");
+ break;
+ default:
+ printk("reason not known yet!");
+ break;
+ }
+
+ printk("************* VMCS Area **************\n");
+ vmcs_dump_vcpu();
+ printk("**************************************\n");
+
+ domain_crash(current->domain);
+}
+
asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
{
unsigned int exit_reason;
unsigned long exit_qualification, inst_len = 0;
struct vcpu *v = current;
+ TRACE_3D(TRC_VMX_VMEXIT + v->vcpu_id, 0, 0, 0);
+
exit_reason = __vmread(VM_EXIT_REASON);
perfc_incra(vmexits, exit_reason);
+ TRACE_VMEXIT(0, exit_reason);
if ( exit_reason != EXIT_REASON_EXTERNAL_INTERRUPT )
local_irq_enable();
if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) )
- {
- unsigned int failed_vmentry_reason = exit_reason & 0xFFFF;
-
- exit_qualification = __vmread(EXIT_QUALIFICATION);
- printk("Failed vm entry (exit reason 0x%x) ", exit_reason);
- switch ( failed_vmentry_reason ) {
- case EXIT_REASON_INVALID_GUEST_STATE:
- printk("caused by invalid guest state (%ld).\n",
exit_qualification);
- break;
- case EXIT_REASON_MSR_LOADING:
- printk("caused by MSR entry %ld loading.\n", exit_qualification);
- break;
- case EXIT_REASON_MACHINE_CHECK:
- printk("caused by machine check.\n");
- break;
- default:
- printk("reason not known yet!");
- break;
- }
-
- printk("************* VMCS Area **************\n");
- vmcs_dump_vcpu();
- printk("**************************************\n");
- goto exit_and_crash;
- }
-
- TRACE_VMEXIT(0, exit_reason);
+ return vmx_failed_vmentry(exit_reason);
switch ( exit_reason )
{
@@ -2519,11 +2499,6 @@ asmlinkage void vmx_trace_vmentry(void)
TRACE_VMEXIT(4, 0);
}
-asmlinkage void vmx_trace_vmexit (void)
-{
- TRACE_3D(TRC_VMX_VMEXIT + current->vcpu_id, 0, 0, 0);
-}
-
/*
* Local variables:
* mode: C
diff -r a84fc0de350d -r 866a167bcb49 xen/arch/x86/hvm/vmx/x86_32/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_32/exits.S Thu Jan 11 11:41:44 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S Thu Jan 11 15:43:38 2007 +0000
@@ -50,9 +50,7 @@
ALIGN
ENTRY(vmx_asm_vmexit_handler)
- /* selectors are restored/saved by VMX */
HVM_SAVE_ALL_NOSEGREGS
- call vmx_trace_vmexit
movl %esp,%eax
push %eax
call vmx_vmexit_handler
diff -r a84fc0de350d -r 866a167bcb49 xen/arch/x86/hvm/vmx/x86_64/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_64/exits.S Thu Jan 11 11:41:44 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S Thu Jan 11 15:43:38 2007 +0000
@@ -65,9 +65,7 @@
ALIGN
ENTRY(vmx_asm_vmexit_handler)
- /* selectors are restored/saved by VMX */
HVM_SAVE_ALL_NOSEGREGS
- call vmx_trace_vmexit
movq %rsp,%rdi
call vmx_vmexit_handler
jmp vmx_asm_do_vmentry
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|