From: Ingo Molnar <mingo-X9Un+BFzKDI@public.gmane.org>
To: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
Cc: kvm-devel <kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>
Subject: Re: [patch] KVM: add MSR based hypercall API
Date: Tue, 9 Jan 2007 16:04:24 +0100 [thread overview]
Message-ID: <20070109150424.GA16535@elte.hu> (raw)
In-Reply-To: <45A3ABAF.90208-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
* Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org> 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
next prev parent reply other threads:[~2007-01-09 15:04 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-01-09 9:27 [patch] KVM: add MSR based hypercall API Ingo Molnar
[not found] ` <20070109092705.GA8300-X9Un+BFzKDI@public.gmane.org>
2007-01-09 9:58 ` Avi Kivity
[not found] ` <45A36758.1000808-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-01-09 10:38 ` Ingo Molnar
[not found] ` <20070109103809.GA24515-X9Un+BFzKDI@public.gmane.org>
2007-01-09 11:24 ` Avi Kivity
[not found] ` <45A37B7A.8020709-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-01-09 11:36 ` Ingo Molnar
[not found] ` <20070109113628.GA4421-X9Un+BFzKDI@public.gmane.org>
2007-01-09 12:54 ` Avi Kivity
[not found] ` <45A39095.80005-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-01-09 13:17 ` Ingo Molnar
[not found] ` <20070109131733.GA28431-X9Un+BFzKDI@public.gmane.org>
2007-01-09 13:30 ` Ingo Molnar
2007-01-09 13:41 ` Avi Kivity
[not found] ` <45A39B90.6070908-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-01-09 13:53 ` Ingo Molnar
[not found] ` <20070109135318.GA3084-X9Un+BFzKDI@public.gmane.org>
2007-01-09 14:08 ` Avi Kivity
[not found] ` <45A3A1C6.201-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-01-09 14:22 ` Ingo Molnar
[not found] ` <20070109142203.GA6645-X9Un+BFzKDI@public.gmane.org>
2007-01-09 14:35 ` Avi Kivity
[not found] ` <45A3A816.6010308-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-01-09 14:38 ` Ingo Molnar
[not found] ` <20070109143832.GA10735-X9Un+BFzKDI@public.gmane.org>
2007-01-09 14:44 ` Ingo Molnar
[not found] ` <20070109144434.GA12152-X9Un+BFzKDI@public.gmane.org>
2007-01-09 14:50 ` Avi Kivity
[not found] ` <45A3ABAF.90208-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-01-09 15:04 ` Ingo Molnar [this message]
[not found] ` <20070109150424.GA16535-X9Un+BFzKDI@public.gmane.org>
2007-01-09 16:20 ` [patchset] KVM: paravirt/hypercall queue Ingo Molnar
[not found] ` <20070109162028.GA764-X9Un+BFzKDI@public.gmane.org>
2007-01-09 16:23 ` Ingo Molnar
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=20070109150424.GA16535@elte.hu \
--to=mingo-x9un+bfzkdi@public.gmane.org \
--cc=avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org \
--cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox