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
|