From: Kyle Hale Date: Wed, 22 Jun 2011 23:11:09 +0000 (-0500) Subject: added extension code for software interrupts X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=3da6af957c0c6d8b478898278969c0b5efb77365;p=palacios.git added extension code for software interrupts --- diff --git a/palacios/include/interfaces/sw_intr.h b/palacios/include/interfaces/sw_intr.h index eb63cc9..5eedb3f 100644 --- a/palacios/include/interfaces/sw_intr.h +++ b/palacios/include/interfaces/sw_intr.h @@ -25,7 +25,12 @@ int v3_handle_swintr (struct guest_info * core); -int v3_signal_swintr (struct guest_info * core, int vec); +int v3_signal_swintr (struct guest_info * core, uint8_t vector); +int v3_hook_swintr (struct guest_info * core, + uint8_t vector, + int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data), + void * priv_data); +int v3_hook_passthrough_swintr (struct guest_info * core, uint8_t vector); #endif diff --git a/palacios/src/extensions/ext_sw_intr.c b/palacios/src/extensions/ext_sw_intr.c index 26e8bb4..ff43f3f 100644 --- a/palacios/src/extensions/ext_sw_intr.c +++ b/palacios/src/extensions/ext_sw_intr.c @@ -20,18 +20,15 @@ #include #include #include +#include +#include #include #include -static int init_swintr_intercept (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data); - - return 0; -} +static int init_swintr_intercept (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) { -static int deinit_swintr_intercept (struct v3_vm_info * vm, void * priv_data) { - return 0; } @@ -40,47 +37,164 @@ static int init_swintr_intercept_core (struct guest_info * core, void * priv_dat vmcb_t * vmcb = (vmcb_t*)core->vmm_data; vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); - ctrl_rea->instrs.INTn = 1; + ctrl_area->instrs.INTn = 1; return 0; } -static int deinit_swintr_intercept_core (struct guest_info * core, void * priv_data) { - - return 0; -} - +struct v3_swintr_hook { + int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data); + void * priv_data; +}; -static int swintr_entry (struct guest_info * core, void * priv_data) { - return 0; -} +static struct v3_swintr_hook * swintr_hooks[256]; -static int swintr_exit (struct guest_info * core, void * priv_data) { - return 0; +static inline struct v3_swintr_hook * get_swintr_hook (struct guest_info * core, uint8_t vector) { + return swintr_hooks[vector]; } - static struct v3_extension_impl swintr_impl = { .name = "swintr_intercept", .init = init_swintr_intercept, - .deinit = deinit_swintr_intercept, + .deinit = NULL, .core_init = init_swintr_intercept_core, - .core_deinit = deinit_swintr_intercept_core, - .on_entry = swintr_entry, - .on_exit = swintr_exit + .core_deinit = NULL, + .on_entry = NULL, + .on_exit = NULL }; + register_extension(&swintr_impl); int v3_handle_swintr (struct guest_info * core) { + int ret = 0; + void * instr_ptr = NULL; + struct x86_instr instr; + + if (core->mem_mode == PHYSICAL_MEM) { + ret = v3_gpa_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr); + } else { + ret = v3_gva_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr); + } + + if (ret == -1) { + PrintError("V3 SWintr Handler: Could not translate Instruction Address (%p)\n", (void *)core->rip); + return -1; + } + + if (v3_decode(core, (addr_t)instr_ptr, &instr) == -1) { + PrintError("V3 SWintr Handler: Decoding Error\n"); + return -1; + } + + uint8_t vector = instr.dst_operand.operand; + + struct v3_swintr_hook * hook = swintr_hooks[vector]; + if (hook == NULL) { +#ifdef V3_CONFIG_EXT_SWINTR_PASSTHROUGH + if (v3_hook_passthrough_swintr(core, vector) == -1) { + PrintDebug("V3 SWintr Handler: Error hooking passthrough swintr\n"); + return -1; + } + hook = swintr_hooks[vector]; +#else + core->rip += instr.instr_length; + return v3_signal_swintr(core, vector); +#endif + } + + ret = hook->handler(core, vector, NULL); + if (ret == -1) { +#ifdef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS + PrintDebug("V3 SWintr Handler: Error in swintr hook\n"); +#endif + return -1; + } + + /* at some point we _may_ need to prioritize swints + so that they finish in time for the next + instruction... */ + core->rip += instr.instr_length; + return v3_signal_swintr(core, vector); +} + +int v3_signal_swintr (struct guest_info * core, uint8_t vector) { + struct v3_intr_core_state * intr_state = &(core->intr_core_state); + +#ifdef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS + PrintDebug("Signaling software interrupt in v3_signal_swintr()\n"); + PrintDebug("\tINT vector: %d\n", vector); +#endif + + intr_state->swintr_posted = 1; + intr_state->swintr_vector = vector; + return 0; +} + + +int v3_hook_swintr (struct guest_info * core, + uint8_t vector, + int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data), + void * priv_data) +{ + struct v3_swintr_hook * hook = (struct v3_swintr_hook*)V3_Malloc(sizeof(struct v3_swintr_hook)); + + if (hook == NULL) { + return -1; + } + + if (get_swintr_hook(core, vector) != NULL) { + PrintError("swint %d already hooked\n", vector); + return -1; + } + + hook->handler = handler; + hook->priv_data = priv_data; + + swintr_hooks[vector] = hook; + return 0; } + + +static int passthrough_swintr_handler (struct guest_info * core, uint8_t vector, void * priv_data) { +#ifdef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS + PrintDebug("[passthrough_swint_handler] INT vector=%d (guest=0x%p)\n", + vector, (void*)core); +#endif + return 0; +} + + +int v3_hook_passthrough_swintr (struct guest_info * core, uint8_t vector) { + + int rc = v3_hook_swintr(core, vector, passthrough_swintr_handler, NULL); + + if (rc) { + PrintError("guest_swintr_injection: failed to hook swint 0x%x (guest=0x%p)\n", vector, (void*)core); + return -1; + } else { +#ifdef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS + PrintDebug("guest_swintr_injection: hooked swint 0x%x (guest=0x%p)\n", vector, (void*)core); +#endif + return 0; + } + + /* shouldn't get here */ + return 0; +} + + + + + +