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.


Release 1.0
[palacios.git] / palacios / src / palacios / vmm_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) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.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
21 #include <palacios/vmm_intr.h>
22 #include <palacios/vmm.h>
23
24 #include <palacios/vm_guest.h>
25
26 #ifndef DEBUG_INTERRUPTS
27 #undef PrintDebug
28 #define PrintDebug(fmt, args...)
29 #endif
30
31
32
33
34 void v3_init_interrupt_state(struct guest_info * info) {
35   info->intr_state.excp_pending = 0;
36   info->intr_state.excp_num = 0;
37   info->intr_state.excp_error_code = 0;
38
39   memset((uchar_t *)(info->intr_state.hooks), 0, sizeof(struct v3_irq_hook *) * 256);
40 }
41
42 void v3_set_intr_controller(struct guest_info * info, struct intr_ctrl_ops * ops, void * state) {
43   info->intr_state.controller = ops;
44   info->intr_state.controller_state = state;
45 }
46
47
48
49
50 static inline struct v3_irq_hook * get_irq_hook(struct guest_info * info, uint_t irq) {
51   V3_ASSERT(irq <= 256);
52   return info->intr_state.hooks[irq];
53 }
54
55
56 int v3_hook_irq(struct guest_info * info, 
57                 uint_t irq,
58                 int (*handler)(struct guest_info * info, struct v3_interrupt * intr, void * priv_data),
59                 void  * priv_data) 
60 {
61   struct v3_irq_hook * hook = (struct v3_irq_hook *)V3_Malloc(sizeof(struct v3_irq_hook));
62
63   if (hook == NULL) { 
64     return -1; 
65   }
66
67   if (get_irq_hook(info, irq) != NULL) {
68     PrintError("IRQ %d already hooked\n", irq);
69     return -1;
70   }
71
72   hook->handler = handler;
73   hook->priv_data = priv_data;
74   
75   info->intr_state.hooks[irq] = hook;
76
77   if (V3_Hook_Interrupt(info, irq)) { 
78     PrintError("hook_irq: failed to hook irq %d\n", irq);
79     return -1;
80   } else {
81     PrintDebug("hook_irq: hooked irq %d\n", irq);
82     return 0;
83   }
84 }
85
86
87
88 static int passthrough_irq_handler(struct guest_info * info, struct v3_interrupt * intr, void * priv_data)
89 {
90
91   PrintDebug("[passthrough_irq_handler] raise_irq=%d (guest=0x%p)\n", 
92              intr->irq, (void *)info);
93   return v3_raise_irq(info, intr->irq);
94
95 }
96
97 int v3_hook_passthrough_irq(struct guest_info * info, uint_t irq)
98 {
99
100   int rc = v3_hook_irq(info, 
101                        irq,
102                        passthrough_irq_handler,
103                        NULL);
104
105   if (rc) { 
106     PrintError("guest_irq_injection: failed to hook irq 0x%x (guest=0x%p)\n", irq, (void *)info);
107     return -1;
108   } else {
109     PrintDebug("guest_irq_injection: hooked irq 0x%x (guest=0x%p)\n", irq, (void *)info);
110     return 0;
111   }
112 }
113
114
115
116
117
118 int v3_deliver_irq(struct guest_info * info, struct v3_interrupt * intr) {
119   PrintDebug("v3_deliver_irq: irq=%d state=0x%p, \n", intr->irq, (void *)intr);
120   
121   struct v3_irq_hook * hook = get_irq_hook(info, intr->irq);
122
123   if (hook == NULL) {
124     PrintError("Attempting to deliver interrupt to non registered hook(irq=%d)\n", intr->irq);
125     return -1;
126   }
127   
128   return hook->handler(info, intr, hook->priv_data);
129 }
130
131
132
133
134
135
136
137
138 int v3_raise_exception_with_error(struct guest_info * info, uint_t excp, uint_t error_code) {
139   struct v3_intr_state * intr_state = &(info->intr_state);
140
141   if (intr_state->excp_pending == 0) {
142     intr_state->excp_pending = 1;
143     intr_state->excp_num = excp;
144     intr_state->excp_error_code = error_code;
145     intr_state->excp_error_code_valid = 1;
146     PrintDebug("[v3_raise_exception_with_error] error code: %x\n", error_code);
147   } else {
148     PrintError("exception already pending, currently not implemented\n");
149     return -1;
150   }
151
152   return 0;
153 }
154
155 int v3_raise_exception(struct guest_info * info, uint_t excp) {
156   struct v3_intr_state * intr_state = &(info->intr_state);
157   PrintDebug("[v3_raise_exception]\n");
158   if (intr_state->excp_pending == 0) {
159     intr_state->excp_pending = 1;
160     intr_state->excp_num = excp;
161     intr_state->excp_error_code = 0;
162     intr_state->excp_error_code_valid = 0;
163   } else {
164     PrintError("exception already pending, currently not implemented\n");
165     return -1;
166   }
167
168   return 0;
169 }
170
171
172 int v3_lower_irq(struct guest_info * info, int irq) {
173   // Look up PIC and resend
174   V3_ASSERT(info);
175   V3_ASSERT(info->intr_state.controller);
176   V3_ASSERT(info->intr_state.controller->lower_intr);
177
178   PrintDebug("[v3_lower_irq]\n");
179
180   if ((info->intr_state.controller) && 
181       (info->intr_state.controller->lower_intr)) {
182     info->intr_state.controller->lower_intr(info->intr_state.controller_state, irq);
183   } else {
184     PrintError("There is no registered Interrupt Controller... (NULL POINTER)\n");
185     return -1;
186   }
187
188   return 0;
189 }
190
191 int v3_raise_irq(struct guest_info * info, int irq) {
192   // Look up PIC and resend
193   V3_ASSERT(info);
194   V3_ASSERT(info->intr_state.controller);
195   V3_ASSERT(info->intr_state.controller->raise_intr);
196
197   PrintDebug("[v3_raise_irq]\n");
198
199   if ((info->intr_state.controller) && 
200       (info->intr_state.controller->raise_intr)) {
201     info->intr_state.controller->raise_intr(info->intr_state.controller_state, irq);
202   } else {
203     PrintError("There is no registered Interrupt Controller... (NULL POINTER)\n");
204     return -1;
205   }
206
207   return 0;
208 }
209
210
211
212 int v3_intr_pending(struct guest_info * info) {
213   struct v3_intr_state * intr_state = &(info->intr_state);
214
215   //  PrintDebug("[intr_pending]\n");
216   if (intr_state->excp_pending == 1) {
217     return 1;
218   } else if (intr_state->controller->intr_pending(intr_state->controller_state) == 1) {
219     return 1;
220   }
221
222   /* Check [A]PIC */
223
224   return 0;
225 }
226
227
228 uint_t v3_get_intr_number(struct guest_info * info) {
229   struct v3_intr_state * intr_state = &(info->intr_state);
230
231   if (intr_state->excp_pending == 1) {
232     return intr_state->excp_num;
233   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
234     PrintDebug("[get_intr_number] intr_number = %d\n", intr_state->controller->get_intr_number(intr_state->controller_state));
235     return intr_state->controller->get_intr_number(intr_state->controller_state);
236   }
237
238   /* someway to get the [A]PIC intr */
239
240   return 0;
241 }
242
243
244 intr_type_t v3_get_intr_type(struct guest_info * info) {
245   struct v3_intr_state * intr_state = &(info->intr_state);
246
247   if (intr_state->excp_pending) {
248     PrintDebug("[get_intr_type] Exception\n");
249     return EXCEPTION;
250   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
251     PrintDebug("[get_intr_type] External_irq\n");
252     return EXTERNAL_IRQ;
253   }
254     PrintDebug("[get_intr_type] Invalid_Intr\n");
255   return INVALID_INTR;
256 }
257
258
259
260
261
262
263 int v3_injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type) {
264   struct v3_intr_state * intr_state = &(info->intr_state);
265
266   if (type == EXCEPTION) {
267     PrintDebug("[injecting_intr] Exception\n");
268     intr_state->excp_pending = 0;
269     intr_state->excp_num = 0;
270     intr_state->excp_error_code = 0;
271     intr_state->excp_error_code_valid = 0;
272     
273   } else if (type == EXTERNAL_IRQ) {
274     PrintDebug("[injecting_intr] External_Irq with intr_num = %x\n", intr_num);
275     return intr_state->controller->begin_irq(intr_state->controller_state, intr_num);
276   }
277
278   return 0;
279 }