All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arun Sharma <arun.sharma@intel.com>
To: Ian Pratt <Ian.Pratt@cl.cam.ac.uk>,
	Keir Fraser <Keir.Fraser@cl.cam.ac.uk>
Cc: xen-devel@lists.xensource.com
Subject: [PATCH][4/5] x86-64-enable-vmx.patch
Date: Tue, 19 Apr 2005 15:51:54 -0700	[thread overview]
Message-ID: <20050419225154.GA26389@intel.com> (raw)

   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@intel.com>
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

                 reply	other threads:[~2005-04-19 22:51 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20050419225154.GA26389@intel.com \
    --to=arun.sharma@intel.com \
    --cc=Ian.Pratt@cl.cam.ac.uk \
    --cc=Keir.Fraser@cl.cam.ac.uk \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.