WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: Ian Pratt <Ian.Pratt@xxxxxxxxxxxx>, Keir Fraser <Keir.Fraser@xxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH][4/5] x86-64-enable-vmx.patch
From: Arun Sharma <arun.sharma@xxxxxxxxx>
Date: Tue, 19 Apr 2005 15:51:54 -0700
Cc: xen-devel@xxxxxxxxxxxxxxxxxxx
Delivery-date: Tue, 19 Apr 2005 22:47:20 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.4.1i
   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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH][4/5] x86-64-enable-vmx.patch, Arun Sharma <=