2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2011, Kyle C. Hale <kh@u.norhtwestern.edu>
11 * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Kyle C. Hale <kh@u.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm.h>
21 #include <palacios/vmcb.h>
22 #include <palacios/vm_guest.h>
23 #include <palacios/vm_guest_mem.h>
24 #include <palacios/vmm_decoder.h>
25 #include <palacios/vmm_extensions.h>
26 #include <palacios/vmm_intr.h>
28 #include <gears/sw_intr.h>
30 #ifdef V3_CONFIG_EXT_CODE_INJECT
31 #include <gears/code_inject.h>
34 #ifndef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS
36 #define PrintDebug(fmt, args...)
40 struct v3_swintr_hook {
41 int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data);
46 static struct v3_swintr_hook * swintr_hooks[MAX_SWINTR_HOOKS];
49 static int init_swintr_intercept (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
54 static int deinit_swintr_intercept (struct v3_vm_info * vm, void * priv_data) {
57 for (; i < MAX_SWINTR_HOOKS; i++) {
59 V3_Free(swintr_hooks[i]);
66 static int init_swintr_core_svm (struct guest_info * core, void * priv_data) {
67 vmcb_t * vmcb = (vmcb_t*)core->vmm_data;
68 vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
70 ctrl_area->instrs.INTn = 1;
75 static int init_swintr_core_vmx (struct guest_info * core, void * priv_data) {
76 PrintError(core->vm_info, core, "Not implemented!\n");
81 static int init_swintr_intercept_core (struct guest_info * core, void * priv_data, void ** core_data) {
82 v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU());
86 case V3_SVM_REV3_CPU: {
87 if (init_swintr_core_svm(core, priv_data) == -1) {
88 PrintError(core->vm_info, core, "Problem initializing svm software interrupt intercept\n");
95 case V3_VMX_EPT_UG_CPU: {
96 if (init_swintr_core_vmx(core, priv_data) == -1) {
97 PrintError(core->vm_info, core, "Problem initializing vmx software interrupt intercept\n");
103 PrintError(core->vm_info, core, "software interrupt interception not supported on this architecture\n");
110 static inline struct v3_swintr_hook * get_swintr_hook (struct guest_info * core, uint8_t vector) {
111 return swintr_hooks[vector];
115 static struct v3_extension_impl swintr_impl = {
116 .name = "swintr_intercept",
117 .vm_init = init_swintr_intercept,
118 .vm_deinit = deinit_swintr_intercept,
119 .core_init = init_swintr_intercept_core,
126 register_extension(&swintr_impl);
129 int v3_handle_swintr (struct guest_info * core) {
132 void * instr_ptr = NULL;
133 struct x86_instr instr;
135 if (core->mem_mode == PHYSICAL_MEM) {
136 ret = v3_gpa_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
138 ret = v3_gva_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
142 PrintError(core->vm_info, core, "V3 SWintr Handler: Could not translate Instruction Address (%p)\n", (void *)core->rip);
146 if (v3_decode(core, (addr_t)instr_ptr, &instr) == -1) {
147 PrintError(core->vm_info, core, "V3 SWintr Handler: Decoding Error\n");
151 uint8_t vector = instr.dst_operand.operand;
153 struct v3_swintr_hook * hook = swintr_hooks[vector];
155 #ifdef V3_CONFIG_EXT_SWINTR_PASSTHROUGH
156 if (v3_hook_passthrough_swintr(core, vector) == -1) {
157 PrintDebug(core->vm_info, core, "V3 SWintr Handler: Error hooking passthrough swintr\n");
160 hook = swintr_hooks[vector];
162 core->rip += instr.instr_length;
163 return v3_raise_swintr(core, vector);
167 ret = hook->handler(core, vector, NULL);
169 PrintDebug(core->vm_info, core, "V3 SWintr Handler: Error in swintr hook\n");
173 #ifdef V3_CONFIG_EXT_CODE_INJECT
174 // this is for injecting page faults
175 // we don't want to increment rip or inject
176 // the swint if we need to fault a page in
177 if (ret == E_NEED_PF) {
181 /* at some point we _may_ need to prioritize swints
182 so that they finish in time for the next
184 core->rip += instr.instr_length;
185 return v3_raise_swintr(core, vector);
190 int v3_hook_swintr (struct guest_info * core,
192 int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data),
195 struct v3_swintr_hook * hook = (struct v3_swintr_hook*)V3_Malloc(sizeof(struct v3_swintr_hook));
198 PrintError(core->vm_info, core, "Cannot allocate for swintr hook\n");
202 if (get_swintr_hook(core, vector) != NULL) {
203 PrintError(core->vm_info, core, "swint %d already hooked\n", vector);
207 hook->handler = handler;
208 hook->priv_data = priv_data;
210 swintr_hooks[vector] = hook;
212 PrintDebug(core->vm_info, core, "Hooked Swintr #%d\n", vector);
218 static int passthrough_swintr_handler (struct guest_info * core, uint8_t vector, void * priv_data) {
219 PrintDebug(core->vm_info, core, "[passthrough_swint_handler] INT vector=%d (guest=0x%p)\n",
220 vector, (void*)core);
225 int v3_hook_passthrough_swintr (struct guest_info * core, uint8_t vector) {
227 int rc = v3_hook_swintr(core, vector, passthrough_swintr_handler, NULL);
230 PrintError(core->vm_info, core, "guest_swintr_injection: failed to hook swint 0x%x (guest=0x%p)\n", vector, (void*)core);
233 PrintDebug(core->vm_info, core, "guest_swintr_injection: hooked swint 0x%x (guest=0x%p)\n", vector, (void*)core);
237 /* shouldn't get here */