# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1168445855 0
# Node ID 160ff08f8b1ff4c7dbd79d2b54efc49cc6bd079a
# Parent 5c5d9692f559ab6b8f7cddc32d6f656e1ed3b888
[HVM][VMX] Fix problem taking an NMI on entry/exit
to/from VMX mode. Also cleans up code a bit.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/hvm/vmx/vmcs.c | 9 ++++++++-
xen/arch/x86/hvm/vmx/x86_32/exits.S | 31 +------------------------------
xen/arch/x86/hvm/vmx/x86_64/exits.S | 27 +--------------------------
xen/arch/x86/oprofile/nmi_int.c | 2 +-
xen/arch/x86/traps.c | 2 +-
5 files changed, 12 insertions(+), 59 deletions(-)
diff -r 5c5d9692f559 -r 160ff08f8b1f xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c Wed Jan 10 15:05:00 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/vmcs.c Wed Jan 10 16:17:35 2007 +0000
@@ -278,7 +278,14 @@ static void vmx_set_host_env(struct vcpu
host_env.tr_base = (unsigned long) &init_tss[cpu];
__vmwrite(HOST_TR_SELECTOR, host_env.tr_selector);
__vmwrite(HOST_TR_BASE, host_env.tr_base);
- __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom());
+
+ /*
+ * Skip end of cpu_user_regs when entering the hypervisor because the
+ * CPU does not save context onto the stack. SS,RSP,CS,RIP,RFLAGS,etc
+ * all get saved into the VMCS instead.
+ */
+ __vmwrite(HOST_RSP,
+ (unsigned long)&get_cpu_info()->guest_cpu_user_regs.error_code);
}
static void construct_vmcs(struct vcpu *v)
diff -r 5c5d9692f559 -r 160ff08f8b1f xen/arch/x86/hvm/vmx/x86_32/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_32/exits.S Wed Jan 10 15:05:00 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S Wed Jan 10 16:17:35 2007 +0000
@@ -29,35 +29,7 @@
andl $~3,reg; \
movl (reg),reg;
-/*
- * At VMExit time the processor saves the guest selectors, esp, eip,
- * and eflags. Therefore we don't save them, but simply decrement
- * the kernel stack pointer to make it consistent with the stack frame
- * at usual interruption time. The eflags of the host is not saved by VMX,
- * and we set it to the fixed value.
- *
- * We also need the room, especially because orig_eax field is used
- * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
- * (10) u32 gs;
- * (9) u32 fs;
- * (8) u32 ds;
- * (7) u32 es;
- * <- get_stack_bottom() (= HOST_ESP)
- * (6) u32 ss;
- * (5) u32 esp;
- * (4) u32 eflags;
- * (3) u32 cs;
- * (2) u32 eip;
- * (2/1) u16 entry_vector;
- * (1/1) u16 error_code;
- * However, get_stack_bottom() actually returns 20 bytes before the real
- * bottom of the stack to allow space for:
- * domain pointer, DS, ES, FS, GS. Therefore, we effectively skip 6 registers.
- */
-
-#define NR_SKIPPED_REGS 6 /* See the above explanation */
#define HVM_SAVE_ALL_NOSEGREGS \
- subl $(NR_SKIPPED_REGS*4), %esp; \
movl $0, 0xc(%esp); /* XXX why do we need to force eflags==0 ?? */ \
pushl %eax; \
pushl %ebp; \
@@ -74,8 +46,7 @@
popl %esi; \
popl %edi; \
popl %ebp; \
- popl %eax; \
- addl $(NR_SKIPPED_REGS*4), %esp
+ popl %eax
ALIGN
ENTRY(vmx_asm_vmexit_handler)
diff -r 5c5d9692f559 -r 160ff08f8b1f xen/arch/x86/hvm/vmx/x86_64/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_64/exits.S Wed Jan 10 15:05:00 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S Wed Jan 10 16:17:35 2007 +0000
@@ -29,31 +29,7 @@
andq $~7,reg; \
movq (reg),reg;
-/*
- * At VMExit time the processor saves the guest selectors, rsp, rip,
- * and rflags. Therefore we don't save them, but simply decrement
- * the kernel stack pointer to make it consistent with the stack frame
- * at usual interruption time. The rflags of the host is not saved by VMX,
- * and we set it to the fixed value.
- *
- * We also need the room, especially because orig_eax field is used
- * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
- * (10) u64 gs;
- * (9) u64 fs;
- * (8) u64 ds;
- * (7) u64 es;
- * <- get_stack_bottom() (= HOST_ESP)
- * (6) u64 ss;
- * (5) u64 rsp;
- * (4) u64 rflags;
- * (3) u64 cs;
- * (2) u64 rip;
- * (2/1) u32 entry_vector;
- * (1/1) u32 error_code;
- */
-#define NR_SKIPPED_REGS 6 /* See the above explanation */
#define HVM_SAVE_ALL_NOSEGREGS \
- subq $(NR_SKIPPED_REGS*8), %rsp; \
pushq %rdi; \
pushq %rsi; \
pushq %rdx; \
@@ -85,8 +61,7 @@
popq %rcx; \
popq %rdx; \
popq %rsi; \
- popq %rdi; \
- addq $(NR_SKIPPED_REGS*8), %rsp;
+ popq %rdi
ALIGN
ENTRY(vmx_asm_vmexit_handler)
diff -r 5c5d9692f559 -r 160ff08f8b1f xen/arch/x86/oprofile/nmi_int.c
--- a/xen/arch/x86/oprofile/nmi_int.c Wed Jan 10 15:05:00 2007 +0000
+++ b/xen/arch/x86/oprofile/nmi_int.c Wed Jan 10 16:17:35 2007 +0000
@@ -42,7 +42,7 @@ extern size_t strlcpy(char *dest, const
extern size_t strlcpy(char *dest, const char *src, size_t size);
-int nmi_callback(struct cpu_user_regs *regs, int cpu)
+static int nmi_callback(struct cpu_user_regs *regs, int cpu)
{
int xen_mode, ovf;
diff -r 5c5d9692f559 -r 160ff08f8b1f xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Wed Jan 10 15:05:00 2007 +0000
+++ b/xen/arch/x86/traps.c Wed Jan 10 16:17:35 2007 +0000
@@ -1854,7 +1854,7 @@ static int dummy_nmi_callback(struct cpu
}
static nmi_callback_t nmi_callback = dummy_nmi_callback;
-
+
asmlinkage void do_nmi(struct cpu_user_regs *regs)
{
unsigned int cpu = smp_processor_id();
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|