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.


fixed all the printf style warnings/errors
[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%x)\n", intr->irq, info);
92   return v3_raise_irq(info, intr->irq);
93
94 }
95
96 int v3_hook_passthrough_irq(struct guest_info * info, uint_t irq)
97 {
98
99   int rc = v3_hook_irq(info, 
100                        irq,
101                        passthrough_irq_handler,
102                        NULL);
103
104   if (rc) { 
105     PrintError("guest_irq_injection: failed to hook irq 0x%x (guest=0x%p)\n", irq, (void *)info);
106     return -1;
107   } else {
108     PrintDebug("guest_irq_injection: hooked irq 0x%x (guest=0x%p)\n", irq, (void *)info);
109     return 0;
110   }
111 }
112
113
114
115
116
117 int v3_deliver_irq(struct guest_info * info, struct v3_interrupt * intr) {
118   PrintDebug("v3_deliver_irq: irq=%d state=0x%x, \n", intr->irq, intr);
119   
120   struct v3_irq_hook * hook = get_irq_hook(info, intr->irq);
121
122   if (hook == NULL) {
123     PrintError("Attempting to deliver interrupt to non registered hook(irq=%d)\n", intr->irq);
124     return -1;
125   }
126   
127   return hook->handler(info, intr, hook->priv_data);
128 }
129
130
131
132
133
134
135
136
137 int v3_raise_exception_with_error(struct guest_info * info, uint_t excp, uint_t error_code) {
138   struct v3_intr_state * intr_state = &(info->intr_state);
139
140   if (intr_state->excp_pending == 0) {
141     intr_state->excp_pending = 1;
142     intr_state->excp_num = excp;
143     intr_state->excp_error_code = error_code;
144     intr_state->excp_error_code_valid = 1;
145     PrintDebug("[v3_raise_exception_with_error] error code: %x\n", error_code);
146   } else {
147     PrintError("exception already pending, currently not implemented\n");
148     return -1;
149   }
150
151   return 0;
152 }
153
154 int v3_raise_exception(struct guest_info * info, uint_t excp) {
155   struct v3_intr_state * intr_state = &(info->intr_state);
156   PrintDebug("[v3_raise_exception]\n");
157   if (intr_state->excp_pending == 0) {
158     intr_state->excp_pending = 1;
159     intr_state->excp_num = excp;
160     intr_state->excp_error_code = 0;
161     intr_state->excp_error_code_valid = 0;
162   } else {
163     PrintError("exception already pending, currently not implemented\n");
164     return -1;
165   }
166
167   return 0;
168 }
169
170
171 int v3_lower_irq(struct guest_info * info, int irq) {
172   // Look up PIC and resend
173   V3_ASSERT(info);
174   V3_ASSERT(info->intr_state.controller);
175   V3_ASSERT(info->intr_state.controller->lower_intr);
176
177   PrintDebug("[v3_lower_irq]\n");
178
179   if ((info->intr_state.controller) && 
180       (info->intr_state.controller->lower_intr)) {
181     info->intr_state.controller->lower_intr(info->intr_state.controller_state, irq);
182   } else {
183     PrintError("There is no registered Interrupt Controller... (NULL POINTER)\n");
184     return -1;
185   }
186
187   return 0;
188 }
189
190 int v3_raise_irq(struct guest_info * info, int irq) {
191   // Look up PIC and resend
192   V3_ASSERT(info);
193   V3_ASSERT(info->intr_state.controller);
194   V3_ASSERT(info->intr_state.controller->raise_intr);
195
196   PrintDebug("[v3_raise_irq]\n");
197
198   if ((info->intr_state.controller) && 
199       (info->intr_state.controller->raise_intr)) {
200     info->intr_state.controller->raise_intr(info->intr_state.controller_state, irq);
201   } else {
202     PrintError("There is no registered Interrupt Controller... (NULL POINTER)\n");
203     return -1;
204   }
205
206   return 0;
207 }
208
209
210
211 int v3_intr_pending(struct guest_info * info) {
212   struct v3_intr_state * intr_state = &(info->intr_state);
213
214   //  PrintDebug("[intr_pending]\n");
215   if (intr_state->excp_pending == 1) {
216     return 1;
217   } else if (intr_state->controller->intr_pending(intr_state->controller_state) == 1) {
218     return 1;
219   }
220
221   /* Check [A]PIC */
222
223   return 0;
224 }
225
226
227 uint_t v3_get_intr_number(struct guest_info * info) {
228   struct v3_intr_state * intr_state = &(info->intr_state);
229
230   if (intr_state->excp_pending == 1) {
231     return intr_state->excp_num;
232   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
233     PrintDebug("[get_intr_number] intr_number = %d\n", intr_state->controller->get_intr_number(intr_state->controller_state));
234     return intr_state->controller->get_intr_number(intr_state->controller_state);
235   }
236
237   /* someway to get the [A]PIC intr */
238
239   return 0;
240 }
241
242
243 intr_type_t v3_get_intr_type(struct guest_info * info) {
244   struct v3_intr_state * intr_state = &(info->intr_state);
245
246   if (intr_state->excp_pending) {
247     PrintDebug("[get_intr_type] Exception\n");
248     return EXCEPTION;
249   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
250     PrintDebug("[get_intr_type] External_irq\n");
251     return EXTERNAL_IRQ;
252   }
253     PrintDebug("[get_intr_type] Invalid_Intr\n");
254   return INVALID_INTR;
255 }
256
257
258
259
260
261
262 int v3_injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type) {
263   struct v3_intr_state * intr_state = &(info->intr_state);
264
265   if (type == EXCEPTION) {
266     PrintDebug("[injecting_intr] Exception\n");
267     intr_state->excp_pending = 0;
268     intr_state->excp_num = 0;
269     intr_state->excp_error_code = 0;
270     intr_state->excp_error_code_valid = 0;
271     
272   } else if (type == EXTERNAL_IRQ) {
273     PrintDebug("[injecting_intr] External_Irq with intr_num = %x\n", intr_num);
274     return intr_state->controller->begin_irq(intr_state->controller_state, intr_num);
275   }
276
277   return 0;
278 }