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.


added extension code for software interrupts
[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
27 #include <interfaces/sw_intr.h>
28
29
30 static int init_swintr_intercept (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
31
32     return 0;
33 }
34
35
36 static int init_swintr_intercept_core (struct guest_info * core, void * priv_data) {
37     vmcb_t * vmcb = (vmcb_t*)core->vmm_data;
38     vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb);
39
40     ctrl_area->instrs.INTn = 1;
41
42     return 0;
43 }
44
45
46 struct v3_swintr_hook {
47     int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data);
48     void * priv_data;
49 };
50
51
52 static struct v3_swintr_hook * swintr_hooks[256];
53
54
55 static inline struct v3_swintr_hook * get_swintr_hook (struct guest_info * core, uint8_t vector) {
56     return swintr_hooks[vector];
57 }
58
59
60 static struct v3_extension_impl swintr_impl = {
61     .name = "swintr_intercept",
62     .init = init_swintr_intercept,
63     .deinit = NULL,
64     .core_init = init_swintr_intercept_core,
65     .core_deinit = NULL,
66     .on_entry = NULL,
67     .on_exit = NULL
68 };
69
70
71 register_extension(&swintr_impl);
72
73
74 int v3_handle_swintr (struct guest_info * core) {
75
76     int ret = 0;
77     void * instr_ptr = NULL;
78     struct x86_instr instr;
79
80     if (core->mem_mode == PHYSICAL_MEM) { 
81         ret = v3_gpa_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
82     } else { 
83         ret = v3_gva_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
84     }   
85     
86     if (ret == -1) {
87         PrintError("V3 SWintr Handler: Could not translate Instruction Address (%p)\n", (void *)core->rip);
88         return -1; 
89     }   
90
91     if (v3_decode(core, (addr_t)instr_ptr, &instr) == -1) {
92         PrintError("V3 SWintr Handler: Decoding Error\n");
93         return -1; 
94     }   
95
96     uint8_t vector = instr.dst_operand.operand;
97
98     struct v3_swintr_hook * hook = swintr_hooks[vector];
99     if (hook == NULL) {
100 #ifdef V3_CONFIG_EXT_SWINTR_PASSTHROUGH
101         if (v3_hook_passthrough_swintr(core, vector) == -1) {
102             PrintDebug("V3 SWintr Handler: Error hooking passthrough swintr\n");
103             return -1; 
104         }
105         hook = swintr_hooks[vector];
106 #else
107         core->rip += instr.instr_length;
108         return v3_signal_swintr(core, vector);
109 #endif
110     }   
111
112     ret = hook->handler(core, vector, NULL);
113     if (ret == -1) {
114 #ifdef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS
115         PrintDebug("V3 SWintr Handler: Error in swintr hook\n");
116 #endif
117         return -1; 
118     }   
119
120     /* at some point we _may_ need to prioritize swints 
121        so that they finish in time for the next
122        instruction... */
123     core->rip += instr.instr_length;
124     return v3_signal_swintr(core, vector);
125 }
126
127 int v3_signal_swintr (struct guest_info * core, uint8_t vector) {
128     struct v3_intr_core_state * intr_state = &(core->intr_core_state);
129
130 #ifdef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS
131     PrintDebug("Signaling software interrupt in v3_signal_swintr()\n");
132     PrintDebug("\tINT vector: %d\n", vector);
133 #endif
134     
135     intr_state->swintr_posted = 1;
136     intr_state->swintr_vector = vector;
137     return 0;
138 }
139
140
141 int v3_hook_swintr (struct guest_info * core,
142         uint8_t vector,
143         int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data),
144         void * priv_data)
145 {
146     struct v3_swintr_hook * hook = (struct v3_swintr_hook*)V3_Malloc(sizeof(struct v3_swintr_hook));
147
148     if (hook == NULL) {
149         return -1;
150     }
151
152     if (get_swintr_hook(core, vector) != NULL) {
153         PrintError("swint %d already hooked\n", vector);
154         return -1;
155     }
156     
157     hook->handler = handler;
158     hook->priv_data = priv_data;
159
160     swintr_hooks[vector] = hook;
161
162     return 0;
163 }
164     
165
166 static int passthrough_swintr_handler (struct guest_info * core, uint8_t vector, void * priv_data) {
167 #ifdef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS
168     PrintDebug("[passthrough_swint_handler] INT vector=%d (guest=0x%p)\n",
169         vector, (void*)core);
170 #endif
171     return 0;
172 }
173
174
175 int v3_hook_passthrough_swintr (struct guest_info * core, uint8_t vector) {
176     
177     int rc = v3_hook_swintr(core, vector, passthrough_swintr_handler, NULL);
178     
179     if (rc) {
180         PrintError("guest_swintr_injection: failed to hook swint 0x%x (guest=0x%p)\n", vector, (void*)core);
181         return -1;
182     } else {
183 #ifdef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS
184         PrintDebug("guest_swintr_injection: hooked swint 0x%x (guest=0x%p)\n", vector, (void*)core);
185 #endif
186         return 0;
187     }
188     
189     /* shouldn't get here */
190     return 0;
191 }
192
193
194
195
196
197
198
199
200