[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH][4/5] x86-64-enable-vmx.patch



   Enable CONFIG_VMX for x86_64.
   
   - Provides vmexit/entry handling code based on the x86_32 code
   - Fix find_highest_vector for 64 bit (Benjamin Liu)
   
   Signed-off-by: Arun Sharma <arun.sharma@xxxxxxxxx>
diff -Nru a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
--- a/xen/arch/x86/Makefile     2005-04-18 16:49:38 -07:00
+++ b/xen/arch/x86/Makefile     2005-04-18 16:49:38 -07:00
@@ -7,10 +7,6 @@
 
 OBJS := $(subst $(TARGET_SUBARCH)/asm-offsets.o,,$(OBJS))
 
-ifneq ($(TARGET_SUBARCH),x86_32)
-OBJS := $(patsubst vmx%.o,,$(OBJS))
-endif
-
 ifneq ($(crash_debug),y)
 OBJS := $(patsubst cdb%.o,,$(OBJS))
 endif
diff -Nru a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c
--- a/xen/arch/x86/vmx.c        2005-04-18 16:49:38 -07:00
+++ b/xen/arch/x86/vmx.c        2005-04-18 16:49:38 -07:00
@@ -959,7 +959,12 @@
     struct exec_domain *d = current;
 
     local_irq_disable();        
+#ifdef __i386__
     asm volatile("movl %0,%%cr2": :"r" (d->arch.arch_vmx.cpu_cr2));
+#else
+    asm volatile("movq %0,%%cr2": :"r" (d->arch.arch_vmx.cpu_cr2));
+#endif
+
 }
 
 #endif /* CONFIG_VMX */
diff -Nru a/xen/arch/x86/vmx_intercept.c b/xen/arch/x86/vmx_intercept.c
--- a/xen/arch/x86/vmx_intercept.c      2005-04-18 16:49:38 -07:00
+++ b/xen/arch/x86/vmx_intercept.c      2005-04-18 16:49:38 -07:00
@@ -37,7 +37,7 @@
     struct exec_domain *d = current;
     struct vmx_handler_t *handler = 
&(d->arch.arch_vmx.vmx_platform.vmx_handler);
     int i;
-    unsigned addr, offset;
+    unsigned long addr, offset;
     for (i = 0; i < handler->num_slot; i++) {
         addr   = handler->hdl_list[i].addr;
         offset = handler->hdl_list[i].offset;
diff -Nru a/xen/arch/x86/vmx_io.c b/xen/arch/x86/vmx_io.c
--- a/xen/arch/x86/vmx_io.c     2005-04-18 16:49:38 -07:00
+++ b/xen/arch/x86/vmx_io.c     2005-04-18 16:49:38 -07:00
@@ -169,6 +169,17 @@
         break;
     }
 }
+#else
+static void load_xen_regs(struct xen_regs *regs)
+{ 
+       /* XXX: TBD */
+       return;
+}
+static void set_reg_value (int size, int index, int seg, struct xen_regs 
*regs, long value)
+{
+       /* XXX: TBD */
+       return;
+}
 #endif
 
 void vmx_io_assist(struct exec_domain *ed) 
@@ -271,7 +282,8 @@
     }
 }
 
-static inline int __fls(unsigned long word)
+#ifdef __i386__
+static inline int __fls(u32 word)
 {
     int bit;
 
@@ -280,26 +292,57 @@
             :"rm" (word));
     return word ? bit : -1;
 }
+#else
+#define __fls(x)       generic_fls(x)
+static __inline__ int generic_fls(u32 x)
+{
+       int r = 32;
+
+       if (!x)
+               return 0;
+       if (!(x & 0xffff0000u)) {
+               x <<= 16;
+               r -= 16;
+       }
+       if (!(x & 0xff000000u)) {
+               x <<= 8;
+               r -= 8;
+       }
+       if (!(x & 0xf0000000u)) {
+               x <<= 4;
+               r -= 4;
+       }
+       if (!(x & 0xc0000000u)) {
+               x <<= 2;
+               r -= 2;
+       }
+       if (!(x & 0x80000000u)) {
+                x <<= 1;
+                r -= 1;
+       }
+       return r;
+}
+#endif
 
 
 /* Simple minded Local APIC priority implementation. Fix later */
-static __inline__ int find_highest_irq(unsigned long *pintr)
+static __inline__ int find_highest_irq(u32 *pintr)
 {
     if (pintr[7])
-        return __fls(pintr[7]) + (256-32*1);
+        return __fls(pintr[7]) + (255-32*1);
     if (pintr[6])
-        return __fls(pintr[6]) + (256-32*2);
+        return __fls(pintr[6]) + (255-32*2);
     if (pintr[5])
-        return __fls(pintr[5]) + (256-32*3);
+        return __fls(pintr[5]) + (255-32*3);
     if (pintr[4])
-        return __fls(pintr[4]) + (256-32*4);
+        return __fls(pintr[4]) + (255-32*4);
     if (pintr[3])
-        return __fls(pintr[3]) + (256-32*5);
+        return __fls(pintr[3]) + (255-32*5);
     if (pintr[2])
-        return __fls(pintr[2]) + (256-32*6);
+        return __fls(pintr[2]) + (255-32*6);
     if (pintr[1])
-        return __fls(pintr[1]) + (256-32*7);
-    return __fls(pintr[0]);
+        return __fls(pintr[1]) + (255-32*7);
+    return (__fls(pintr[0])-1);
 }
 
 /*
@@ -317,7 +360,7 @@
         domain_crash_synchronous();
     }
         
-    return find_highest_irq(&vio->vp_intr[0]);
+    return find_highest_irq((unsigned int *)&vio->vp_intr[0]);
 }
 
 static inline void clear_highest_bit(struct exec_domain *d, int vector)
diff -Nru a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c
--- a/xen/arch/x86/vmx_vmcs.c   2005-04-18 16:49:38 -07:00
+++ b/xen/arch/x86/vmx_vmcs.c   2005-04-18 16:49:38 -07:00
@@ -327,7 +327,11 @@
     error |= __vmwrite(GUEST_EFLAGS, eflags);
 
     error |= __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
+#ifdef __i386__
     __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (dr7));
+#else
+    __asm__ __volatile__ ("movq %%dr7, %0\n" : "=r" (dr7));
+#endif
     error |= __vmwrite(GUEST_DR7, dr7);
     error |= __vmwrite(GUEST_VMCS0, 0xffffffff);
     error |= __vmwrite(GUEST_VMCS1, 0xffffffff);
@@ -363,12 +367,21 @@
     host_env->idtr_base = desc.address;
     error |= __vmwrite(HOST_IDTR_BASE, host_env->idtr_base);
 
+#ifdef __i386__
     __asm__ __volatile__ ("movl %%cr0,%0" : "=r" (crn) : );
+#else
+    __asm__ __volatile__ ("movq %%cr0,%0" : "=r" (crn) : );
+#endif
+
     host_env->cr0 = crn;
     error |= __vmwrite(HOST_CR0, crn); /* same CR0 */
 
     /* CR3 is set in vmx_final_setup_hostos */
+#ifdef __i386__
     __asm__ __volatile__ ("movl %%cr4,%0" : "=r" (crn) : ); 
+#else
+    __asm__ __volatile__ ("movq %%cr4,%0" : "=r" (crn) : ); 
+#endif
     host_env->cr4 = crn;
     error |= __vmwrite(HOST_CR4, crn);
     error |= __vmwrite(HOST_EIP, (unsigned long) vmx_asm_vmexit_handler);
diff -Nru a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
--- a/xen/arch/x86/x86_64/entry.S       2005-04-18 16:49:38 -07:00
+++ b/xen/arch/x86/x86_64/entry.S       2005-04-18 16:49:38 -07:00
@@ -151,6 +151,139 @@
         movb  $1,VCPUINFO_upcall_mask(%rax) # Upcalls masked during delivery
         jmp   test_all_events
 
+#ifdef CONFIG_VMX
+/*
+ * 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 xen_regs, we skip pushing for the following:
+ *   (13) u64 gs_base_user;                 
+ *   (12) u64 gs_base_kernel;                 
+ *   (11) u64 fs_base;                 
+ *   (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;
+ * However, get_stack_bottom() actually returns 64 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 VMX_MONITOR_RFLAGS     0x202 /* IF on */
+#define NR_SKIPPED_REGS        6       /* See the above explanation */
+#define VMX_SAVE_ALL_NOSEGREGS \
+        pushq $VMX_MONITOR_RFLAGS; \
+        popfq; \
+        subq $(NR_SKIPPED_REGS*8), %rsp; \
+        pushq %rdi; \
+        pushq %rsi; \
+        pushq %rdx; \
+        pushq %rcx; \
+        pushq %rax; \
+        pushq %r8;  \
+        pushq %r9;  \
+        pushq %r10; \
+        pushq %r11; \
+        pushq %rbx; \
+        pushq %rbp; \
+        pushq %r12; \
+        pushq %r13; \
+        pushq %r14; \
+        pushq %r15; \
+
+ENTRY(vmx_asm_vmexit_handler)
+        /* selectors are restored/saved by VMX */
+        VMX_SAVE_ALL_NOSEGREGS
+        call SYMBOL_NAME(vmx_vmexit_handler)
+        jmp vmx_asm_do_resume
+
+ENTRY(vmx_asm_do_launch)
+        popq %r15
+        popq %r14
+        popq %r13
+        popq %r12
+        popq %rbp
+        popq %rbx
+        popq %r11
+        popq %r10
+        popq %r9
+        popq %r8
+        popq %rax
+        popq %rcx
+        popq %rdx
+        popq %rsi
+        popq %rdi
+        addq $(NR_SKIPPED_REGS*8), %rsp
+        /* VMLUANCH */
+        .byte 0x0f,0x01,0xc2
+        pushfq
+        call SYMBOL_NAME(vm_launch_fail)
+        hlt
+        
+        ALIGN
+        
+ENTRY(vmx_asm_do_resume)
+vmx_test_all_events:
+        GET_CURRENT(%rbx)
+/* test_all_events: */
+        xorq %rcx,%rcx
+        notq %rcx
+        cli                             # tests must not race interrupts
+/*test_softirqs:*/  
+        movq EDOMAIN_processor(%rbx),%rax
+#if 0
+        shl  $6,%rax                    # sizeof(irq_cpustat) == 64
+        test %rcx,SYMBOL_NAME(irq_stat)(%rax,1)
+#endif
+        jnz  vmx_process_softirqs
+
+vmx_restore_all_guest:
+        call SYMBOL_NAME(load_cr2)
+        /* 
+         * Check if we are going back to VMX-based VM
+         * By this time, all the setups in the VMCS must be complete.
+         */
+        popq %r15
+        popq %r14
+        popq %r13
+        popq %r12
+        popq %rbp
+        popq %rbx
+        popq %r11
+        popq %r10
+        popq %r9
+        popq %r8
+        popq %rax
+        popq %rcx
+        popq %rdx
+        popq %rsi
+        popq %rdi
+        addq $(NR_SKIPPED_REGS*8), %rsp
+        /* VMRESUME */
+        .byte 0x0f,0x01,0xc3
+        pushfq
+        call SYMBOL_NAME(vm_resume_fail)
+        /* Should never reach here */
+        hlt
+
+        ALIGN
+vmx_process_softirqs:
+        sti       
+        call SYMBOL_NAME(do_softirq)
+        jmp  vmx_test_all_events
+#endif
+
         ALIGN
 /* %rbx: struct exec_domain */
 process_softirqs:
diff -Nru a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h
--- a/xen/include/asm-x86/config.h      2005-04-18 16:49:38 -07:00
+++ b/xen/include/asm-x86/config.h      2005-04-18 16:49:38 -07:00
@@ -7,9 +7,7 @@
 #ifndef __X86_CONFIG_H__
 #define __X86_CONFIG_H__
 
-#ifdef __i386__
 #define CONFIG_VMX 1
-#endif
 
 #define CONFIG_X86 1
 #define CONFIG_SHADOW 1

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.