From: Peter Dinda Date: Fri, 13 Apr 2012 23:15:53 +0000 (-0500) Subject: Host hypercall interface implementation (Palacios-side) X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=d6a4d7bf28c8962ad6a1499d0b74b9e5cdf892ad;p=palacios.git Host hypercall interface implementation (Palacios-side) --- diff --git a/palacios/include/interfaces/vmm_host_hypercall.h b/palacios/include/interfaces/vmm_host_hypercall.h new file mode 100644 index 0000000..611e700 --- /dev/null +++ b/palacios/include/interfaces/vmm_host_hypercall.h @@ -0,0 +1,112 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2012, Kyle C. Hale + * Copyright (c) 2012, Peter Dinda + * Copyright (c) 2012, The V3VEE Project + * All rights reserved. + * + * Authors: Kyle C. Hale + * Peter Dinda + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#ifndef __VMM_HOST_HYPERCALL_H__ +#define __VMM_HOST_HYPERCALL_H__ + +#include + +/* palacios v3_vm_info struct is opaque to the host */ +typedef void * host_vm_info_t; + +typedef void * palacios_core_t; + + +// Notice that host implementation is itself +// palacios-specific at this point. It must be +// include the palacios-headers needed to understand +// a guest_info, etc. +// +// The idea here is to make it possible to create something +// like a linux kernel module, that is compiled against +// palacios itself, but inserted after palacios. +// The module then make full use of palacios functions +// to manipulate guest state, as if it were a part of +// palacios +// + +#define GET_SET_REG_DECL(R) \ + uint64_t (*get_##R)(palacios_core_t core); \ + void (*set_##R)(palacios_core_t core, uint64_t val); + + + +struct guest_accessors { + // You can read/write the GPRs + GET_SET_REG_DECL(rax) + GET_SET_REG_DECL(rbx) + GET_SET_REG_DECL(rcx) + GET_SET_REG_DECL(rdx) + GET_SET_REG_DECL(rsi) + GET_SET_REG_DECL(rdi) + GET_SET_REG_DECL(rbp) + GET_SET_REG_DECL(rsp) + GET_SET_REG_DECL(r8) + GET_SET_REG_DECL(r9) + GET_SET_REG_DECL(r10) + GET_SET_REG_DECL(r11) + GET_SET_REG_DECL(r12) + GET_SET_REG_DECL(r13) + GET_SET_REG_DECL(r14) + GET_SET_REG_DECL(r15) + + GET_SET_REG_DECL(rip); + GET_SET_REG_DECL(rflags) + GET_SET_REG_DECL(cr0) + GET_SET_REG_DECL(cr2) + GET_SET_REG_DECL(cr3) + GET_SET_REG_DECL(cr4) + GET_SET_REG_DECL(cr8) + GET_SET_REG_DECL(efer) + + int (*gva_to_hva)(palacios_core_t core, uint64_t gva, uint64_t *hva); + int (*gva_to_gpa)(palacios_core_t core, uint64_t gva, uint64_t *gpa); + int (*gpa_to_hva)(palacios_core_t core, uint64_t gpa, uint64_t *hva); + + int (*read_gva)(palacios_core_t core, uint64_t addr, + int n, void *dest); + int (*read_gpa)(palacios_core_t core, uint64_t addr, + int n, void *dest); + + int (*write_gva)(palacios_core_t core, uint64_t addr, + int n, void *src); + int (*write_gpa)(palacios_core_t core, uint64_t addr, + int n, void *src); +}; + + + +int v3_register_host_hypercall(host_vm_info_t * vm, + unsigned int hypercall_id, + int (*hypercall)(palacios_core_t core, + unsigned int hcall_id, + struct guest_accessors *accessors, + void *priv_data), + void *priv_data); + +int v3_unregister_host_hypercall(host_vm_info_t *vm, + unsigned int hypercall_id); + +#ifdef __V3VEE__ + +#endif /* !__V3VEE__ */ +#endif + diff --git a/palacios/src/interfaces/Kconfig b/palacios/src/interfaces/Kconfig index 61a7965..d2962a6 100644 --- a/palacios/src/interfaces/Kconfig +++ b/palacios/src/interfaces/Kconfig @@ -68,5 +68,12 @@ config HOST_DEVICE This makes it possible for virtual devices such as the generic device and the pci_front device to make host-based device implementations appear within the guest +config HOST_HYPERCALL + bool "Host hypercall support" + default n + help + Select this if you would like to make it possible + to register host-based implementations of hypercalls, + for example, implemented in Linux kernel modules endmenu diff --git a/palacios/src/interfaces/Makefile b/palacios/src/interfaces/Makefile index 9d2c6f3..3c340de 100644 --- a/palacios/src/interfaces/Makefile +++ b/palacios/src/interfaces/Makefile @@ -6,6 +6,7 @@ obj-$(V3_CONFIG_STREAM) += vmm_stream.o obj-$(V3_CONFIG_GRAPHICS_CONSOLE) += vmm_graphics_console.o obj-$(V3_CONFIG_KEYED_STREAMS) += vmm_keyed_stream.o obj-$(V3_CONFIG_HOST_DEVICE) += vmm_host_dev.o +obj-$(V3_CONFIG_HOST_HYPERCALL) += vmm_host_hypercall.o obj-y += null.o diff --git a/palacios/src/interfaces/vmm_host_hypercall.c b/palacios/src/interfaces/vmm_host_hypercall.c new file mode 100644 index 0000000..0299268 --- /dev/null +++ b/palacios/src/interfaces/vmm_host_hypercall.c @@ -0,0 +1,166 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2012, Kyle C. Hale + * Copyright (c) 2012, Peter Dinda + * Copyright (c) 2012, The V3VEE Project + * All rights reserved. + * + * Authors: Kyle C. Hale + * Peter Dinda + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include +#include +#include + +#include + + +#define GET_SET_GPR_IMPL(R) \ + static uint64_t get_##R(palacios_core_t core) { return ((struct guest_info *)core)->vm_regs.R;} \ + static void set_##R(palacios_core_t core, uint64_t val) { ((struct guest_info *)core)->vm_regs.R = val; } + +#define GET_SET_CR_IMPL(R) \ + static uint64_t get_##R(palacios_core_t core) { return ((struct guest_info *)core)->ctrl_regs.R;} \ + static void set_##R(palacios_core_t core, uint64_t val) { ((struct guest_info *)core)->ctrl_regs.R = val; } + +#define DECL_IT(R) .get_##R = get_##R, .set_##R = set_##R, + +GET_SET_GPR_IMPL(rax) +GET_SET_GPR_IMPL(rbx) +GET_SET_GPR_IMPL(rcx) +GET_SET_GPR_IMPL(rdx) +GET_SET_GPR_IMPL(rsi) +GET_SET_GPR_IMPL(rdi) +GET_SET_GPR_IMPL(rbp) +GET_SET_GPR_IMPL(rsp) +GET_SET_GPR_IMPL(r8) +GET_SET_GPR_IMPL(r9) +GET_SET_GPR_IMPL(r10) +GET_SET_GPR_IMPL(r11) +GET_SET_GPR_IMPL(r12) +GET_SET_GPR_IMPL(r13) +GET_SET_GPR_IMPL(r14) +GET_SET_GPR_IMPL(r15) + +static uint64_t get_rip(palacios_core_t core) { return ((struct guest_info *)core)->rip;} + +static void set_rip(palacios_core_t core, uint64_t val) { ((struct guest_info *)core)->rip = val; } + + +GET_SET_CR_IMPL(cr0) +GET_SET_CR_IMPL(cr2) +GET_SET_CR_IMPL(cr3) +GET_SET_CR_IMPL(cr4) +GET_SET_CR_IMPL(cr8) +GET_SET_CR_IMPL(efer) +GET_SET_CR_IMPL(rflags) + + + +static struct guest_accessors guest_acc = { +DECL_IT(rax) +DECL_IT(rbx) +DECL_IT(rcx) +DECL_IT(rdx) +DECL_IT(rsi) +DECL_IT(rdi) +DECL_IT(rbp) +DECL_IT(rsp) +DECL_IT(r8) +DECL_IT(r9) +DECL_IT(r10) +DECL_IT(r11) +DECL_IT(r12) +DECL_IT(r13) +DECL_IT(r14) +DECL_IT(r15) + +DECL_IT(rip) +DECL_IT(cr0) +DECL_IT(cr2) +DECL_IT(cr3) +DECL_IT(cr4) +DECL_IT(cr8) +DECL_IT(efer) +DECL_IT(rflags) + +.gva_to_hva = (int (*)(palacios_core_t, uint64_t, uint64_t *)) v3_gva_to_hva, +.gpa_to_hva = (int (*)(palacios_core_t, uint64_t, uint64_t *)) v3_gpa_to_hva, +.gva_to_gpa = (int (*)(palacios_core_t, uint64_t, uint64_t *)) v3_gva_to_gpa, +.read_gva = (int (*)(palacios_core_t, uint64_t, int, void *)) v3_read_gva_memory, +.read_gpa = (int (*)(palacios_core_t, uint64_t, int, void *)) v3_read_gpa_memory, +.write_gva = (int (*)(palacios_core_t, uint64_t, int, void *)) v3_write_gva_memory, +.write_gpa = (int (*)(palacios_core_t, uint64_t, int, void *)) v3_write_gpa_memory, + + } ; + + + + + + +struct bounce_data { + int (*hypercall)(palacios_core_t core, + unsigned int hcall_id, + struct guest_accessors *accessors, + void *priv_data); + void *priv_data; +}; + +static int bounce(struct guest_info *core, + unsigned int hcall_id, + void *priv_data) +{ + struct bounce_data *b = (struct bounce_data *) priv_data; + + return b->hypercall(core,hcall_id,&guest_acc,b->priv_data); +} + + + +int v3_register_host_hypercall(host_vm_info_t * vm, + unsigned int hypercall_id, + int (*hypercall)(palacios_core_t core, + uint_t hcall_id, + struct guest_accessors *acc, + void * priv_data), + void * priv_data) { + + struct bounce_data *b = V3_Malloc(sizeof(struct bounce_data)); + + if (!b) { + return -1; + } + + b->hypercall=hypercall; + b->priv_data=priv_data; + + if (v3_register_hypercall((struct v3_vm_info*) vm, + hypercall_id, + bounce, + b) < 0) { + return -1; + } + + return 0; +} + +int v3_unregister_host_hypercall(host_vm_info_t * vm, + unsigned int hypercall_id) +{ + return v3_remove_hypercall((struct v3_vm_info*)vm, hypercall_id); +} +