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.


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