Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


moved software interrupt injection to core interrupt code
[palacios.git] / palacios / src / extensions / ext_sw_intr.c
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
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.
13  *
14  * Author: Kyle C. Hale <kh@u.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
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>
27
28 #include <interfaces/sw_intr.h>
29
30 #ifndef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS
31 #undef PrintDebug
32 #define PrintDebug(fmt, args...)
33 #endif
34
35
36 static int init_swintr_intercept (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
37
38     return 0;
39 }
40
41
42 static int init_swintr_intercept_core (struct guest_info * core, void * priv_data) {
43     vmcb_t * vmcb = (vmcb_t*)core->vmm_data;
44     vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
45
46     ctrl_area->instrs.INTn = 1;
47
48     return 0;
49 }
50
51
52 struct v3_swintr_hook {
53     int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data);
54     void * priv_data;
55 };
56
57
58 static struct v3_swintr_hook * swintr_hooks[256];
59
60
61 static inline struct v3_swintr_hook * get_swintr_hook (struct guest_info * core, uint8_t vector) {
62     return swintr_hooks[vector];
63 }
64
65
66 static struct v3_extension_impl swintr_impl = {
67     .name = "swintr_intercept",
68     .init = init_swintr_intercept,
69     .deinit = NULL,
70     .core_init = init_swintr_intercept_core,
71     .core_deinit = NULL,
72     .on_entry = NULL,
73     .on_exit = NULL
74 };
75
76
77 register_extension(&swintr_impl);
78
79
80 int v3_handle_swintr (struct guest_info * core) {
81
82     int ret = 0;
83     void * instr_ptr = NULL;
84     struct x86_instr instr;
85
86     if (core->mem_mode == PHYSICAL_MEM) { 
87         ret = v3_gpa_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
88     } else { 
89         ret = v3_gva_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
90     }   
91     
92     if (ret == -1) {
93         PrintError("V3 SWintr Handler: Could not translate Instruction Address (%p)\n", (void *)core->rip);
94         return -1; 
95     }   
96
97     if (v3_decode(core, (addr_t)instr_ptr, &instr) == -1) {
98         PrintError("V3 SWintr Handler: Decoding Error\n");
99         return -1; 
100     }   
101
102     uint8_t vector = instr.dst_operand.operand;
103
104     struct v3_swintr_hook * hook = swintr_hooks[vector];
105     if (hook == NULL) {
106 #ifdef V3_CONFIG_EXT_SWINTR_PASSTHROUGH
107         if (v3_hook_passthrough_swintr(core, vector) == -1) {
108             PrintDebug("V3 SWintr Handler: Error hooking passthrough swintr\n");
109             return -1; 
110         }
111         hook = swintr_hooks[vector];
112 #else
113         core->rip += instr.instr_length;
114         return v3_raise_swintr(core, vector);
115 #endif
116     }   
117
118     ret = hook->handler(core, vector, NULL);
119     if (ret == -1) {
120         PrintDebug("V3 SWintr Handler: Error in swintr hook\n");
121         return -1; 
122     }   
123
124     /* at some point we _may_ need to prioritize swints 
125        so that they finish in time for the next
126        instruction... */
127     core->rip += instr.instr_length;
128     return v3_raise_swintr(core, vector);
129 }
130
131
132
133 int v3_hook_swintr (struct guest_info * core,
134         uint8_t vector,
135         int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data),
136         void * priv_data)
137 {
138     struct v3_swintr_hook * hook = (struct v3_swintr_hook*)V3_Malloc(sizeof(struct v3_swintr_hook));
139
140     if (hook == NULL) {
141         return -1;
142     }
143
144     if (get_swintr_hook(core, vector) != NULL) {
145         PrintError("swint %d already hooked\n", vector);
146         return -1;
147     }
148     
149     hook->handler = handler;
150     hook->priv_data = priv_data;
151
152     swintr_hooks[vector] = hook;
153
154     return 0;
155 }
156     
157
158 static int passthrough_swintr_handler (struct guest_info * core, uint8_t vector, void * priv_data) {
159     PrintDebug("[passthrough_swint_handler] INT vector=%d (guest=0x%p)\n",
160         vector, (void*)core);
161     return 0;
162 }
163
164
165 int v3_hook_passthrough_swintr (struct guest_info * core, uint8_t vector) {
166     
167     int rc = v3_hook_swintr(core, vector, passthrough_swintr_handler, NULL);
168     
169     if (rc) {
170         PrintError("guest_swintr_injection: failed to hook swint 0x%x (guest=0x%p)\n", vector, (void*)core);
171         return -1;
172     } else {
173         PrintDebug("guest_swintr_injection: hooked swint 0x%x (guest=0x%p)\n", vector, (void*)core);
174         return 0;
175     }
176     
177     /* shouldn't get here */
178     return 0;
179 }
180
181