* Avi Kivity <[EMAIL PROTECTED]> wrote:

> > about the 32-bit side: maybe it gives us a bit more options for 
> > later if we pick the natural order for 32-bit too: EBX for index, 
> > EAX, EDX, ECX for the first 3 parameters, with the remaining 3 
> > parameters in ESI, EDI, EBP? Most hypercalls will have 0, 1, 2 or 3 
> > parameters.
> 
> I don't mind, as long as it's clearly documented.

ok. Below is the current snapshot - hypercall calling convention 
documented and implemented for both 64-bit and 32-bit on the KVM side, 
and a small demo call done on the 32-bit guest side.

        Ingo

Index: linux/arch/i386/kernel/paravirt.c
===================================================================
--- linux.orig/arch/i386/kernel/paravirt.c
+++ linux/arch/i386/kernel/paravirt.c
@@ -888,29 +888,40 @@ asm (
        "               ret                             \n"
 );
 
-extern unsigned char hypercall_addr[4];
+extern unsigned char hypercall_addr[6];
 
-
-static inline int
-kvm_hypercall(void *param1, void *param2, void *param3, void *param4)
-{
-       int ret = -1;
-
-       asm (" call hypercall_addr\n"
-               : "=g" (ret)
-               : "eax" (param1),
-                 "ecx" (param2),
-                 "edx" (param3),
-                 "ebp" (param4));
-
-       return ret;
-}
+#define hypercall0(nr)                         \
+({                                             \
+       int __ret;                              \
+                                               \
+       asm (" call hypercall_addr\n"           \
+               : "=a" (__ret)                  \
+               : "b" (nr)                      \
+       );                                      \
+       __ret;                                  \
+})
+
+#define hypercall1(nr, p1)                     \
+({                                             \
+       int __ret;                              \
+                                               \
+       asm (" call hypercall_addr\n"           \
+               : "=a" (__ret)                  \
+               : "b" (nr),                     \
+                 "a" (p1)                      \
+       );                                      \
+       __ret;                                  \
+})
 
 void test_hypercall(void)
 {
-       int ret = kvm_hypercall((void *)1, (void *)2, (void *)3, (void *)4);
+       int ret;
+
+       ret = hypercall0(__NR_hypercall_load_cr3);
+       printk(KERN_DEBUG "hypercall test #1, ret: %d\n", ret);
 
-       printk(KERN_DEBUG "hypercall test, ret: %d\n", ret);
+       ret = hypercall1(0xbad, 0xbad);
+       printk(KERN_DEBUG "hypercall test #2, ret: %d\n", ret);
 }
 
 int kvm_guest_register_para(int cpu)
Index: linux/drivers/kvm/kvm.h
===================================================================
--- linux.orig/drivers/kvm/kvm.h
+++ linux/drivers/kvm/kvm.h
@@ -639,4 +639,6 @@ static inline u32 get_rdx_init_val(void)
 #define TSS_REDIRECTION_SIZE (256 / 8)
 #define RMODE_TSS_SIZE (TSS_BASE_SIZE + TSS_REDIRECTION_SIZE + TSS_IOPB_SIZE + 
1)
 
+extern int kvm_handle_hypercall(struct kvm_vcpu *vcpu);
+
 #endif
Index: linux/drivers/kvm/kvm_main.c
===================================================================
--- linux.orig/drivers/kvm/kvm_main.c
+++ linux/drivers/kvm/kvm_main.c
@@ -1138,6 +1138,62 @@ int emulate_instruction(struct kvm_vcpu 
 }
 EXPORT_SYMBOL_GPL(emulate_instruction);
 
+int hypercall_load_cr3(struct kvm_vcpu *vcpu, unsigned long new_cr3)
+{
+       printk("not yet\n");
+
+       return -ENOSYS;
+}
+
+static inline int
+kvm_hypercall(struct kvm_vcpu *vcpu, unsigned int nr,
+             unsigned long p1, unsigned long p2, unsigned long p3,
+             unsigned long p4, unsigned long p5, unsigned long p6)
+{
+       int ret = -EINVAL;
+
+       switch (nr) {
+       case __NR_hypercall_load_cr3:
+               ret = hypercall_load_cr3(vcpu, p1);
+               break;
+       default:
+               printk(KERN_DEBUG "invalid hypercall %d\n", nr);
+       }
+       vcpu->regs[VCPU_REGS_RAX] = ret;
+
+       return 1;
+}
+
+static int kvm_handle_hypercall_32bit(struct kvm_vcpu *vcpu)
+{
+       int nr = vcpu->regs[VCPU_REGS_RBX];
+       unsigned long   p1 = vcpu->regs[VCPU_REGS_RAX],
+                       p2 = vcpu->regs[VCPU_REGS_RCX],
+                       p3 = vcpu->regs[VCPU_REGS_RDX],
+                       p4 = vcpu->regs[VCPU_REGS_RSI],
+                       p5 = vcpu->regs[VCPU_REGS_RDI],
+                       p6 = vcpu->regs[VCPU_REGS_RBP];
+
+       return kvm_hypercall(vcpu, nr, p1, p2, p3, p4, p5, p6);
+}
+
+int kvm_handle_hypercall(struct kvm_vcpu *vcpu)
+{
+       int nr = vcpu->regs[VCPU_REGS_RAX];
+       unsigned long   p1 = vcpu->regs[VCPU_REGS_RAX],
+                       p2 = vcpu->regs[VCPU_REGS_RCX],
+                       p3 = vcpu->regs[VCPU_REGS_RDX],
+                       p4 = vcpu->regs[VCPU_REGS_RSI],
+                       p5 = vcpu->regs[VCPU_REGS_RDI],
+                       p6 = vcpu->regs[VCPU_REGS_RBP];
+
+       if (unlikely(!is_long_mode(vcpu)))
+               return kvm_handle_hypercall_32bit(vcpu);
+
+       return kvm_hypercall(vcpu, nr, p1, p2, p3, p4, p5, p6);
+}
+EXPORT_SYMBOL_GPL(kvm_handle_hypercall);
+
 static u64 mk_cr_64(u64 curr_cr, u32 new_val)
 {
        return (curr_cr & ~((1ULL << 32) - 1)) | new_val;
Index: linux/drivers/kvm/vmx.c
===================================================================
--- linux.orig/drivers/kvm/vmx.c
+++ linux/drivers/kvm/vmx.c
@@ -1032,7 +1032,7 @@ static int vmcs_setup_cr3_cache(struct k
        cr3_target_values = (msr_val >> 16) & ((1 << 10) - 1);
        printk(KERN_DEBUG " cr3 target values: %d\n", cr3_target_values);
        if (cr3_target_values > KVM_CR3_CACHE_SIZE) {
-               printk(KERN_WARN "KVM: limiting cr3 cache size from %d to %d\n",
+               printk(KERN_WARNING "KVM: limiting cr3 cache size from %d to 
%d\n",
                        cr3_target_values, KVM_CR3_CACHE_SIZE);
                cr3_target_values = KVM_CR3_CACHE_SIZE;
        }
@@ -1726,16 +1726,12 @@ static int handle_halt(struct kvm_vcpu *
 static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        kvm_run->exit_reason = KVM_EXIT_DEBUG;
-       printk(KERN_DEBUG "got vmcall at RIP %08lx\n", vmcs_readl(GUEST_RIP));
-       printk(KERN_DEBUG "vmcall params: %08lx, %08lx, %08lx, %08lx\n",
-               vcpu->regs[VCPU_REGS_RAX],
-               vcpu->regs[VCPU_REGS_RCX],
-               vcpu->regs[VCPU_REGS_RDX],
-               vcpu->regs[VCPU_REGS_RBP]);
-       vcpu->regs[VCPU_REGS_RAX] = 0;
+       kvm_handle_hypercall(vcpu);
        vmcs_writel(GUEST_RIP, vmcs_readl(GUEST_RIP)+3);
+
        return 1;
 }
+
 /*
  * The exit handlers return 1 if the exit was handled fully and guest execution
  * may resume.  Otherwise they set the kvm_run parameter to indicate what needs
Index: linux/include/linux/kvm_para.h
===================================================================
--- linux.orig/include/linux/kvm_para.h
+++ linux/include/linux/kvm_para.h
@@ -72,4 +72,23 @@ struct kvm_vcpu_para_state {
 
 #define KVM_EINVAL EINVAL
 
+/*
+ * Hypercall calling convention:
+ *
+ * Each hypercall may have 0-6 parameters.
+ *
+ * 64-bit hypercall index is in RAX, goes from 0 to __NR_hypercalls-1
+ *
+ * 64-bit parameters 1-6 are in the standard gcc x86_64 calling convention
+ * order: RDI, RSI, RDX, RCX, R8, R9.
+ *
+ * 32-bit index is EBX, parameters are: EAX, ECX, EDX, ESI, EDI, EBP.
+ * (the first 3 are according to the gcc regparm calling convention)
+ *
+ * No registers are clobbered by the hypercall, except that the
+ * return value is in RAX.
+ */
+#define __NR_hypercall_load_cr3                0
+#define __NR_hypercalls                        1
+
 #endif

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to