direct-io.hg

changeset 13322:160ff08f8b1f

[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@xensource.com>
author kfraser@localhost.localdomain
date Wed Jan 10 16:17:35 2007 +0000 (2007-01-10)
parents 5c5d9692f559
children aa127e545b73
files xen/arch/x86/hvm/vmx/vmcs.c xen/arch/x86/hvm/vmx/x86_32/exits.S xen/arch/x86/hvm/vmx/x86_64/exits.S xen/arch/x86/oprofile/nmi_int.c xen/arch/x86/traps.c
line diff
     1.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c	Wed Jan 10 15:05:00 2007 +0000
     1.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c	Wed Jan 10 16:17:35 2007 +0000
     1.3 @@ -278,7 +278,14 @@ static void vmx_set_host_env(struct vcpu
     1.4      host_env.tr_base = (unsigned long) &init_tss[cpu];
     1.5      __vmwrite(HOST_TR_SELECTOR, host_env.tr_selector);
     1.6      __vmwrite(HOST_TR_BASE, host_env.tr_base);
     1.7 -    __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom());
     1.8 +
     1.9 +    /*
    1.10 +     * Skip end of cpu_user_regs when entering the hypervisor because the
    1.11 +     * CPU does not save context onto the stack. SS,RSP,CS,RIP,RFLAGS,etc
    1.12 +     * all get saved into the VMCS instead.
    1.13 +     */
    1.14 +    __vmwrite(HOST_RSP,
    1.15 +              (unsigned long)&get_cpu_info()->guest_cpu_user_regs.error_code);
    1.16  }
    1.17  
    1.18  static void construct_vmcs(struct vcpu *v)
     2.1 --- a/xen/arch/x86/hvm/vmx/x86_32/exits.S	Wed Jan 10 15:05:00 2007 +0000
     2.2 +++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S	Wed Jan 10 16:17:35 2007 +0000
     2.3 @@ -29,35 +29,7 @@
     2.4          andl $~3,reg;            \
     2.5          movl (reg),reg;
     2.6  
     2.7 -/*
     2.8 - * At VMExit time the processor saves the guest selectors, esp, eip, 
     2.9 - * and eflags. Therefore we don't save them, but simply decrement 
    2.10 - * the kernel stack pointer to make it consistent with the stack frame 
    2.11 - * at usual interruption time. The eflags of the host is not saved by VMX, 
    2.12 - * and we set it to the fixed value.
    2.13 - *
    2.14 - * We also need the room, especially because orig_eax field is used 
    2.15 - * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
    2.16 - *   (10) u32 gs;                 
    2.17 - *   (9)  u32 fs;
    2.18 - *   (8)  u32 ds;
    2.19 - *   (7)  u32 es;
    2.20 - *               <- get_stack_bottom() (= HOST_ESP)
    2.21 - *   (6)  u32 ss;
    2.22 - *   (5)  u32 esp;
    2.23 - *   (4)  u32 eflags;
    2.24 - *   (3)  u32 cs;
    2.25 - *   (2)  u32 eip;
    2.26 - * (2/1)  u16 entry_vector;
    2.27 - * (1/1)  u16 error_code;
    2.28 - * However, get_stack_bottom() actually returns 20 bytes before the real
    2.29 - * bottom of the stack to allow space for:
    2.30 - * domain pointer, DS, ES, FS, GS. Therefore, we effectively skip 6 registers.
    2.31 - */
    2.32 -
    2.33 -#define NR_SKIPPED_REGS 6 /* See the above explanation */
    2.34  #define HVM_SAVE_ALL_NOSEGREGS                                              \
    2.35 -        subl $(NR_SKIPPED_REGS*4), %esp;                                    \
    2.36          movl $0, 0xc(%esp);  /* XXX why do we need to force eflags==0 ?? */ \
    2.37          pushl %eax;                                                         \
    2.38          pushl %ebp;                                                         \
    2.39 @@ -74,8 +46,7 @@
    2.40          popl %esi;                              \
    2.41          popl %edi;                              \
    2.42          popl %ebp;                              \
    2.43 -        popl %eax;                              \
    2.44 -        addl $(NR_SKIPPED_REGS*4), %esp
    2.45 +        popl %eax
    2.46  
    2.47          ALIGN
    2.48  ENTRY(vmx_asm_vmexit_handler)
     3.1 --- a/xen/arch/x86/hvm/vmx/x86_64/exits.S	Wed Jan 10 15:05:00 2007 +0000
     3.2 +++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S	Wed Jan 10 16:17:35 2007 +0000
     3.3 @@ -29,31 +29,7 @@
     3.4          andq $~7,reg;            \
     3.5          movq (reg),reg;
     3.6  
     3.7 -/*
     3.8 - * At VMExit time the processor saves the guest selectors, rsp, rip, 
     3.9 - * and rflags. Therefore we don't save them, but simply decrement 
    3.10 - * the kernel stack pointer to make it consistent with the stack frame 
    3.11 - * at usual interruption time. The rflags of the host is not saved by VMX, 
    3.12 - * and we set it to the fixed value.
    3.13 - *
    3.14 - * We also need the room, especially because orig_eax field is used 
    3.15 - * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
    3.16 - *   (10) u64 gs;                 
    3.17 - *   (9)  u64 fs;
    3.18 - *   (8)  u64 ds;
    3.19 - *   (7)  u64 es;
    3.20 - *               <- get_stack_bottom() (= HOST_ESP)
    3.21 - *   (6)  u64 ss;
    3.22 - *   (5)  u64 rsp;
    3.23 - *   (4)  u64 rflags;
    3.24 - *   (3)  u64 cs;
    3.25 - *   (2)  u64 rip;
    3.26 - * (2/1)  u32 entry_vector;
    3.27 - * (1/1)  u32 error_code;
    3.28 - */
    3.29 -#define NR_SKIPPED_REGS 6 /* See the above explanation */
    3.30  #define HVM_SAVE_ALL_NOSEGREGS                  \
    3.31 -        subq $(NR_SKIPPED_REGS*8), %rsp;        \
    3.32          pushq %rdi;                             \
    3.33          pushq %rsi;                             \
    3.34          pushq %rdx;                             \
    3.35 @@ -85,8 +61,7 @@
    3.36          popq %rcx;                              \
    3.37          popq %rdx;                              \
    3.38          popq %rsi;                              \
    3.39 -        popq %rdi;                              \
    3.40 -        addq $(NR_SKIPPED_REGS*8), %rsp;
    3.41 +        popq %rdi
    3.42  
    3.43          ALIGN
    3.44  ENTRY(vmx_asm_vmexit_handler)
     4.1 --- a/xen/arch/x86/oprofile/nmi_int.c	Wed Jan 10 15:05:00 2007 +0000
     4.2 +++ b/xen/arch/x86/oprofile/nmi_int.c	Wed Jan 10 16:17:35 2007 +0000
     4.3 @@ -42,7 +42,7 @@ extern int is_profiled(struct domain *d)
     4.4  extern size_t strlcpy(char *dest, const char *src, size_t size);
     4.5  
     4.6  
     4.7 -int nmi_callback(struct cpu_user_regs *regs, int cpu)
     4.8 +static int nmi_callback(struct cpu_user_regs *regs, int cpu)
     4.9  {
    4.10  	int xen_mode, ovf;
    4.11  
     5.1 --- a/xen/arch/x86/traps.c	Wed Jan 10 15:05:00 2007 +0000
     5.2 +++ b/xen/arch/x86/traps.c	Wed Jan 10 16:17:35 2007 +0000
     5.3 @@ -1854,7 +1854,7 @@ static int dummy_nmi_callback(struct cpu
     5.4  }
     5.5   
     5.6  static nmi_callback_t nmi_callback = dummy_nmi_callback;
     5.7 - 
     5.8 +
     5.9  asmlinkage void do_nmi(struct cpu_user_regs *regs)
    5.10  {
    5.11      unsigned int cpu = smp_processor_id();