From: Peter Dinda Date: Fri, 13 Apr 2012 21:41:08 +0000 (-0500) Subject: Linux host hypercall interface implementation X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=ad56fb16a79581bf088c8e5a9143d88e8c2f0055;p=palacios.git Linux host hypercall interface implementation --- diff --git a/linux_module/iface-host-hypercall.c b/linux_module/iface-host-hypercall.c new file mode 100644 index 0000000..f5682db --- /dev/null +++ b/linux_module/iface-host-hypercall.c @@ -0,0 +1,150 @@ +/* + * Linux interface for guest-context code injection + * + * (c) Kyle C. Hale 2011 + * + */ + +#include +#include +#include + +#include + +#include + +#include "palacios.h" +#include "vm.h" +#include "linux-exts.h" +#include "iface-host-hypercall.h" + +static int host_hypercall_nop(palacios_core_t core, + unsigned int hcall_id, + struct guest_accessors *acc, + void *priv_data) { + printk("palacios: host_hypercall_nop dummy handler invoked\n"); + printk(" rip=%p\n rsp=%p\n rbp=%p\n rflags=%p\n", + (void*)(acc->get_rip(core)), + (void*)(acc->get_rsp(core)), + (void*)(acc->get_rbp(core)), + (void*)(acc->get_rflags(core))); + + printk(" rax=%p\n rbx=%p\n rcx=%p\n rdx=%p\n rsi=%p\n rdi=%p\n", + (void*)(acc->get_rax(core)), + (void*)(acc->get_rbx(core)), + (void*)(acc->get_rcx(core)), + (void*)(acc->get_rdx(core)), + (void*)(acc->get_rsi(core)), + (void*)(acc->get_rdi(core))); + printk(" r8=%p\n r9=%p\n r10=%p\n r11=%p\n r12=%p\n r13=%p\n r14=%p\n r15=%p\n", + (void*)(acc->get_r8(core)), + (void*)(acc->get_r9(core)), + (void*)(acc->get_r10(core)), + (void*)(acc->get_r11(core)), + (void*)(acc->get_r12(core)), + (void*)(acc->get_r13(core)), + (void*)(acc->get_r14(core)), + (void*)(acc->get_r15(core))); + printk(" cr0=%p\n cr2=%p\n cr3=%p\n cr4=%p\n cr8=%p\n efer=%p\n", + (void*)(acc->get_cr0(core)), + (void*)(acc->get_cr2(core)), + (void*)(acc->get_cr3(core)), + (void*)(acc->get_cr4(core)), + (void*)(acc->get_cr8(core)), + (void*)(acc->get_efer(core))); + return 0; +} + + +static int vm_hypercall_add (struct v3_guest *guest, + unsigned int cmd, + unsigned long arg, + void *priv_data) { + + struct hcall_data hdata; + void *func; + + if (copy_from_user(&hdata,(void __user *) arg, sizeof(struct hcall_data))) { + printk("palacios: copy from user in getting input for hypercall add\n"); + return -EFAULT; + } + + if (0==strcmp(hdata.fn,"")) { + printk("palacios: no hypercall function supplied, using default\n"); + func = (void*) host_hypercall_nop; + } else { + func = __symbol_get(hdata.fn); + } + + if (func == NULL) { + printk("palacios: cannot find function '%s' for hypercall addition - perhaps your module hasn't been loaded yet?\n",hdata.fn); + return -EFAULT; + } + + if (v3_register_host_hypercall(guest->v3_ctx, + hdata.hcall_nr, + func, + NULL)) { + printk("palacios: cannot register hypercall 0x%x for function %s (%p)\n", + hdata.hcall_nr, hdata.fn, func); + return -EFAULT; + } + + printk("palacios: hypercall %d (0x%x) registered for function %s (%p)\n", + hdata.hcall_nr,hdata.hcall_nr,hdata.fn,func); + return 0; +} + +static int vm_hypercall_remove (struct v3_guest *guest, + unsigned int cmd, + unsigned long arg, + void *priv_data) { + + struct hcall_data hdata; + + if (copy_from_user(&hdata,(void __user *) arg, sizeof(struct hcall_data))) { + printk("palacios: copy from user in getting input for hypercall remove\n"); + return -EFAULT; + } + if (v3_unregister_host_hypercall(guest->v3_ctx, + hdata.hcall_nr)) { + printk("palacios: cannot unregister hypercall 0x%x\n", hdata.hcall_nr); + return -EFAULT; + } + + printk("palacios: hypercall %d (0x%x) unregistered\n", + hdata.hcall_nr,hdata.hcall_nr); + + return 0; +} + +static int init_host_hypercall (void) { + return 0; +} + + +static int deinit_host_hypercall (void) { + return 0; +} + +static int guest_init_host_hypercall (struct v3_guest * guest, void ** vm_data) { + add_guest_ctrl(guest, V3_VM_HYPERCALL_ADD, vm_hypercall_add, NULL); + add_guest_ctrl(guest, V3_VM_HYPERCALL_REMOVE, vm_hypercall_remove, NULL); + return 0; +} + + +static int guest_deinit_host_hypercall (struct v3_guest * guest, void * vm_data) { + return 0; +} + + +static struct linux_ext host_hypercall_ext = { + .name = "HOST_HYPERCALL", + .init = init_host_hypercall, + .deinit = deinit_host_hypercall, + .guest_init = guest_init_host_hypercall, + .guest_deinit = guest_deinit_host_hypercall +}; + +register_extension(&host_hypercall_ext); diff --git a/linux_module/iface-host-hypercall.h b/linux_module/iface-host-hypercall.h new file mode 100644 index 0000000..8b0f91c --- /dev/null +++ b/linux_module/iface-host-hypercall.h @@ -0,0 +1,15 @@ +#ifndef __IFACE_HOST_HYPERCALL_H__ +#define __IFACE_HOST_HYPERCALL_H__ + +#define V3_VM_HYPERCALL_ADD 12124 +#define V3_VM_HYPERCALL_REMOVE 12125 + + +#define HCALL_NAME_MAX 256 + +struct hcall_data { + int hcall_nr; + char fn[HCALL_NAME_MAX]; +}; + +#endif