All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH] Hypercalls from HVM guests (1/2)
@ 2006-04-12 18:40 Steve Ofsthun
  2006-04-13  7:42 ` Keir Fraser
  2006-04-13 17:11 ` [RFC][PATCH] Hypercalls from HVM guests (1/2) [RESUBMIT] Steve Ofsthun
  0 siblings, 2 replies; 4+ messages in thread
From: Steve Ofsthun @ 2006-04-12 18:40 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 157 bytes --]

Here is the main hypervisor/hvmloader patch.

Signed-off-by: Steve Ofsthun <sofsthun@virtualiron.com>

Steve
-- 
Steve Ofsthun - Virtual Iron Software, Inc.

[-- Attachment #2: hvm-hypercall.patch --]
[-- Type: text/x-patch, Size: 9440 bytes --]

--- ./tools/firmware/hvmloader/hvmloader.c	2006-04-07 14:39:43.000000000 -0400
+++ ../xen-unstable-test64/./tools/firmware/hvmloader/hvmloader.c	2006-04-12 10:28:18.000000000 -0400
@@ -23,15 +23,13 @@
  */
 #include "roms.h"
 #include "../acpi/acpi2_0.h"  /* for ACPI_PHYSICAL_ADDRESS */
+#include <asm/hvm/svm/vmmcall.h>
 
 /* memory map */
 #define VGABIOS_PHYSICAL_ADDRESS	0x000C0000
 #define	VMXASSIST_PHYSICAL_ADDRESS	0x000D0000
 #define	ROMBIOS_PHYSICAL_ADDRESS	0x000F0000
 
-/* invoke SVM's paged realmode support */
-#define SVM_VMMCALL_RESET_TO_REALMODE	0x00000001
-
 /*
  * C runtime start off
  */
@@ -138,7 +136,7 @@
         __asm__ __volatile__(
 		".byte 0x0F,0x01,0xD9"
                 : "=a" (eax)
-		: "a"(0x58454E00), /* XEN\0 key */
+		: "a"(VMMCALL_MAGIC), /* XEN\0 key */
 		  "b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi)
 	);
         return eax;
@@ -192,7 +190,7 @@
 	if (check_amd()) {
 		/* AMD implies this is SVM */
                 puts("SVM go ...\n");
-                vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0);
+                vmmcall(VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0);
 	} else {
 		puts("Loading VMXAssist ...\n");
 		memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS,
--- ./tools/firmware/hvmloader/Makefile	2006-04-12 09:07:37.000000000 -0400
+++ ../xen-unstable-test64/./tools/firmware/hvmloader/Makefile	2006-04-12 10:26:39.000000000 -0400
@@ -29,7 +29,7 @@
 LOADADDR = 0x100000
 
 DEFINES  =-DDEBUG
-XENINC   =-I$(XEN_ROOT)/tools/libxc
+XENINC   =-I$(XEN_ROOT)/tools/libxc -I$(XEN_ROOT)/xen/include
 
 OBJECTS	 = hvmloader.o acpi_madt.o 
 
--- ./xen/arch/x86/hvm/hvm.c	2006-04-07 14:39:47.000000000 -0400
+++ ../xen-unstable-test64/./xen/arch/x86/hvm/hvm.c	2006-04-12 11:16:38.000000000 -0400
@@ -357,6 +357,94 @@
 }
 
 /*
+ * Process HVM guest hypercalls.
+ */
+void hvm_hypercall(struct cpu_user_regs *pregs, unsigned long rip)
+{
+    unsigned long rc;
+    unsigned long cmd, a1, a2, a3, a4, a5;
+
+    /*
+     * Retreive the arguments from the appropriate registers.
+     */
+#if BITS_PER_LONG == 64
+    /*
+     * 64-bit hypervisor must handle 32-bit and 64-bit guests.
+     */
+    if (current->domain->arch.ops->guest_paging_levels != PAGING_L4) {
+	/*
+	 * 32-bit guest.
+	 */
+	cmd = pregs->eax;
+	a1 = pregs->ebx;
+	a2 = pregs->ecx;
+	a3 = pregs->edx;
+	a4 = pregs->esi;
+	a5 = pregs->edi;
+    } else {
+	/*
+	 * 64-bit guest.
+	 */
+	cmd = pregs->rax;
+	a1 = pregs->rdi;
+	a2 = pregs->rsi;
+	a3 = pregs->rdx;
+	a4 = pregs->r10;
+	a5 = pregs->r8;
+    }
+#else /* BITS_PER_LONG != 64 */
+    /*
+     * 32-bit hypervisor must handle 32-bit guests.
+     */
+    cmd = pregs->eax;
+    a1 = pregs->ebx;
+    a2 = pregs->ecx;
+    a3 = pregs->edx;
+    a4 = pregs->esi;
+    a5 = pregs->edi;
+#endif /* BITS_PER_LONG != 64 */
+    /*
+     * Don't allow user-mode hypercalls.
+     */
+    if (ring_3(pregs)) {
+	rc = -EPERM;
+	goto out;
+    }
+    /*
+     * Check the hypercall index.
+     */
+    if (cmd >= NR_hypercalls) {
+	rc = -ENOSYS;
+	goto out;
+    }
+#ifdef HYPERCALL_DEBUG
+    printf("VMCALL[%ld] @ %08lx (%08lx,%08lx,%08lx,%08lx,%08lx)\n",
+	    cmd, rip, a1, a2, a3, a4, a5);
+#endif
+
+    /*
+     * Execute the hypercall.
+     */
+    rc = hypercall_table[cmd](a1, a2, a3, a4, a5);
+
+out:
+#ifdef HYPERCALL_DEBUG
+    if (rc)
+	printf("VMCALL[%ld] @ %08lx (%08lx,%08lx,%08lx,%08lx,%08lx)"
+		" returns %ld\n", cmd, rip, a1, a2, a3, a4, a5, rc);
+#endif
+    /*
+     * Save the result in the proper return value register,
+     */
+#if BITS_PER_LONG == 64
+    pregs->rax = rc;
+#else
+    pregs->eax = rc;
+#endif
+    return;
+}
+
+/*
  * Local variables:
  * mode: C
  * c-set-style: "BSD"
--- ./xen/arch/x86/hvm/svm/svm.c	2006-04-07 14:39:47.000000000 -0400
+++ ../xen-unstable-test64/./xen/arch/x86/hvm/svm/svm.c	2006-04-11 17:49:56.000000000 -0400
@@ -2003,6 +2003,7 @@
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     int inst_len;
+    unsigned long eip;
 
     ASSERT(vmcb);
     ASSERT(regs);
@@ -2010,33 +2011,37 @@
     inst_len = __get_instruction_length(vmcb, INSTR_VMCALL, NULL);
     ASSERT(inst_len > 0);
 
-    /* VMMCALL sanity check */
-    if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
-    {
-        printf("VMMCALL CPL check failed\n");
-        return -1;
-    }
+    eip = vmcb->rip;
 
-    /* handle the request */
-    switch (regs->edi) 
+    /* VMMCALL sanity check */
+    if (regs->eax == VMMCALL_MAGIC)
     {
-    case VMMCALL_RESET_TO_REALMODE:
-        if (svm_do_vmmcall_reset_to_realmode(v, regs)) 
-        {
-            printf("svm_do_vmmcall_reset_to_realmode() failed\n");
-            return -1;
-        }
-    
-        /* since we just reset the VMCB, return without adjusting the eip */
-        return 0;
-    case VMMCALL_DEBUG:
-        printf("DEBUG features not implemented yet\n");
-        break;
-    default:
-    break;
+	if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
+	{
+	    /* Don't print anything on user mode errors */
+	    return -1;
+	}
+
+	/* handle the request */
+	switch (regs->edi) 
+	{
+	case VMMCALL_RESET_TO_REALMODE:
+	    if (svm_do_vmmcall_reset_to_realmode(v, regs)) 
+	    {
+		printf("svm_do_vmmcall_reset_to_realmode() failed\n");
+		return -1;
+	    }
+
+	    /* since we just reset the VMCB, return without adjusting the eip */
+	    return 0;
+	case VMMCALL_DEBUG:
+	    break;
+	default:
+	    break;
+	}
     }
 
-    hvm_print_line(v, regs->eax); /* provides the current domain */
+    hvm_hypercall(regs, eip);
 
     __update_guest_eip(vmcb, inst_len);
     return 0;
--- ./xen/arch/x86/hvm/vmx/vmx.c	2006-04-12 09:07:38.000000000 -0400
+++ ../xen-unstable-test64/./xen/arch/x86/hvm/vmx/vmx.c	2006-04-12 09:08:12.000000000 -0400
@@ -2207,16 +2207,15 @@
         __update_guest_eip(inst_len);
         break;
     }
-#if 0 /* keep this for debugging */
     case EXIT_REASON_VMCALL:
         __get_instruction_length(inst_len);
         __vmread(GUEST_RIP, &eip);
         __vmread(EXIT_QUALIFICATION, &exit_qualification);
 
-        hvm_print_line(v, regs.eax); /* provides the current domain */
+	hvm_hypercall(&regs, eip);
+
         __update_guest_eip(inst_len);
         break;
-#endif
     case EXIT_REASON_CR_ACCESS:
     {
         __vmread(GUEST_RIP, &eip);
@@ -2257,7 +2256,6 @@
     case EXIT_REASON_MWAIT_INSTRUCTION:
         __hvm_bug(&regs);
         break;
-    case EXIT_REASON_VMCALL:
     case EXIT_REASON_VMCLEAR:
     case EXIT_REASON_VMLAUNCH:
     case EXIT_REASON_VMPTRLD:
--- ./xen/arch/x86/usercopy.c	2006-04-07 14:39:47.000000000 -0400
+++ ../xen-unstable-test64/./xen/arch/x86/usercopy.c	2006-04-11 15:52:49.000000000 -0400
@@ -91,6 +91,8 @@
 	return (unsigned)__n;
 }
 
+#include <asm/hvm/support.h>
+
 /**
  * copy_to_user: - Copy a block of data into user space.
  * @to:   Destination address, in user space.
@@ -107,6 +109,11 @@
 unsigned long
 copy_to_user(void __user *to, const void *from, unsigned n)
 {
+	if (hvm_guest(current) && !hypervisor_va(to)) {
+		if (hvm_copy((void *)from, (unsigned long)to, n, HVM_COPY_OUT))
+			return 0;
+		return n;
+	}
 	if (access_ok(to, n))
 		n = __copy_to_user(to, from, n);
 	return n;
@@ -131,6 +138,11 @@
 unsigned long
 copy_from_user(void *to, const void __user *from, unsigned n)
 {
+	if (hvm_guest(current) && !hypervisor_va(from)) {
+		if (hvm_copy((void *)to, (unsigned long)from, n, HVM_COPY_IN))
+			return 0;
+		return n;
+	}
 	if (access_ok(from, n))
 		n = __copy_from_user(to, from, n);
 	else
--- ./xen/include/asm-x86/hvm/support.h	2006-04-07 14:39:49.000000000 -0400
+++ ../xen-unstable-test64/./xen/include/asm-x86/hvm/support.h	2006-04-11 08:46:07.000000000 -0400
@@ -149,4 +149,8 @@
 extern void hvm_print_line(struct vcpu *v, const char c);
 extern void hlt_timer_fn(void *data);
 
+typedef unsigned long (*hypercall_ptr_t)(unsigned long, ...);
+extern hypercall_ptr_t hypercall_table[];
+extern void hvm_hypercall(struct cpu_user_regs *pregs, unsigned long rip);
+
 #endif /* __ASM_X86_HVM_SUPPORT_H__ */
--- ./xen/include/asm-x86/hvm/svm/vmmcall.h	2006-04-07 14:39:49.000000000 -0400
+++ ../xen-unstable-test64/./xen/include/asm-x86/hvm/svm/vmmcall.h	2006-04-11 17:32:36.000000000 -0400
@@ -22,6 +22,9 @@
 #ifndef __ASM_X86_HVM_SVM_VMMCALL_H__
 #define __ASM_X86_HVM_SVM_VMMCALL_H__
 
+/* VMMCALL signature field */
+#define VMMCALL_MAGIC 0x58454E00 /* XEN\0 key */
+
 /* VMMCALL command fields */
 #define VMMCALL_CODE_CPL_MASK     0xC0000000
 #define VMMCALL_CODE_MBZ_MASK     0x3FFF0000
--- ./xen/include/public/arch-x86_32.h	2006-04-07 14:39:49.000000000 -0400
+++ ../xen-unstable-test64/./xen/include/public/arch-x86_32.h	2006-04-11 15:52:49.000000000 -0400
@@ -80,6 +80,8 @@
 #define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
 #endif
 
+#define hypervisor_va(va) (__HYPERVISOR_VIRT_START <= (unsigned long)(va))
+
 #ifndef machine_to_phys_mapping
 #define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
 #endif
--- ./xen/include/public/arch-x86_64.h	2006-04-07 14:39:49.000000000 -0400
+++ ../xen-unstable-test64/./xen/include/public/arch-x86_64.h	2006-04-11 15:52:49.000000000 -0400
@@ -89,6 +89,9 @@
 #define HYPERVISOR_VIRT_END   mk_unsigned_long(__HYPERVISOR_VIRT_END)
 #endif
 
+#define hypervisor_va(va) (__HYPERVISOR_VIRT_START <= (unsigned long)(va) && \
+				(unsigned long)(va) < __HYPERVISOR_VIRT_END)
+
 /* Maximum number of virtual CPUs in multi-processor guests. */
 #define MAX_VIRT_CPUS 32
 

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2006-04-13 17:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-12 18:40 [RFC][PATCH] Hypercalls from HVM guests (1/2) Steve Ofsthun
2006-04-13  7:42 ` Keir Fraser
2006-04-13 13:25   ` Steve Ofsthun
2006-04-13 17:11 ` [RFC][PATCH] Hypercalls from HVM guests (1/2) [RESUBMIT] Steve Ofsthun

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.