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 new copyright and license
[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 /*Zheng 07/30/2008*/
34 void 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   info->vm_ops.raise_irq = &v3_raise_irq;
40   info->vm_ops.lower_irq = &v3_lower_irq; //Zheng added
41 }
42
43 void set_intr_controller(struct guest_info * info, struct intr_ctrl_ops * ops, void * state) {
44   info->intr_state.controller = ops;
45   info->intr_state.controller_state = state;
46 }
47
48
49
50 // This structure is used to dispatch
51 // interrupts delivered to vmm via deliver interrupt to vmm 
52 // it is what we put into the opaque field given to 
53 // the host os when we install the handler
54 struct vmm_intr_decode { 
55   void              (*handler)(struct vmm_intr_state *state);
56   // This opaque is user supplied by the caller
57   // of hook_irq_new
58   void              *opaque;
59 };
60
61 int v3_hook_irq(uint_t irq,
62              void (*handler)(struct vmm_intr_state *state),
63              void  *opaque)
64 {
65   struct vmm_intr_decode *d = (struct vmm_intr_decode *)V3_Malloc(sizeof(struct vmm_intr_decode));
66
67   if (!d) { return -1; }
68
69   d->handler = handler;
70   d->opaque = opaque;
71   
72   if (V3_Hook_Interrupt(irq,d)) { 
73     PrintError("hook_irq: failed to hook irq 0x%x to decode 0x%x\n", irq,d);
74     return -1;
75   } else {
76     PrintDebug("hook_irq: hooked irq 0x%x to decode 0x%x\n", irq,d);
77     return 0;
78   }
79 }
80
81
82 void deliver_interrupt_to_vmm(struct vmm_intr_state *state)
83 {
84
85   PrintDebug("deliver_interrupt_to_vmm: state=0x%x\n",state);
86
87   struct vmm_intr_decode *d = (struct vmm_intr_decode *)(state->opaque);
88   
89   void *temp = state->opaque;
90   state->opaque = d->opaque;
91
92   d->handler(state);
93   
94   state->opaque=temp;
95 }
96
97
98 static void guest_injection_irq_handler(struct vmm_intr_state *state)
99 {
100   struct guest_info *guest = (struct guest_info *)(state->opaque);
101   PrintDebug("[guest_injection_irq_handler] raise_irq=0x%x (guest=0x%x)\n", state->irq, guest);
102   PrintDebug("guest_irq_injection: state=0x%x\n", state);
103   guest->vm_ops.raise_irq(guest,state->irq);
104 }
105
106
107 int v3_hook_irq_for_guest_injection(struct guest_info *info, int irq)
108 {
109
110   int rc = v3_hook_irq(irq,
111                        guest_injection_irq_handler,
112                        info);
113
114   if (rc) { 
115     PrintError("guest_irq_injection: failed to hook irq 0x%x (guest=0x%x)\n", irq, info);
116     return -1;
117   } else {
118     PrintDebug("guest_irq_injection: hooked irq 0x%x (guest=0x%x)\n", irq, info);
119     return 0;
120   }
121 }
122
123
124
125
126 int v3_raise_exception_with_error(struct guest_info * info, uint_t excp, uint_t error_code) {
127   struct vm_intr * intr_state = &(info->intr_state);
128
129   if (intr_state->excp_pending == 0) {
130     intr_state->excp_pending = 1;
131     intr_state->excp_num = excp;
132     intr_state->excp_error_code = error_code;
133     intr_state->excp_error_code_valid = 1;
134     PrintDebug("[v3_raise_exception_with_error] error code: %x\n", error_code);
135   } else {
136     PrintError("exception already pending, currently not implemented\n");
137     return -1;
138   }
139
140   return 0;
141 }
142
143 int v3_raise_exception(struct guest_info * info, uint_t excp) {
144   struct vm_intr * intr_state = &(info->intr_state);
145   PrintDebug("[v3_raise_exception]\n");
146   if (intr_state->excp_pending == 0) {
147     intr_state->excp_pending = 1;
148     intr_state->excp_num = excp;
149     intr_state->excp_error_code = 0;
150     intr_state->excp_error_code_valid = 0;
151   } else {
152     PrintError("exception already pending, currently not implemented\n");
153     return -1;
154   }
155
156   return 0;
157 }
158
159 /*Zheng 07/30/2008*/
160
161 int v3_lower_irq(struct guest_info * info, int irq) {
162   // Look up PIC and resend
163   V3_ASSERT(info);
164   V3_ASSERT(info->intr_state.controller);
165   V3_ASSERT(info->intr_state.controller->raise_intr);
166
167   PrintDebug("[v3_lower_irq]\n");
168
169   if ((info->intr_state.controller) && 
170       (info->intr_state.controller->raise_intr)) {
171     info->intr_state.controller->lower_intr(info->intr_state.controller_state, irq);
172   } else {
173     PrintDebug("There is no registered Interrupt Controller... (NULL POINTER)\n");
174     return -1;
175   }
176
177   return 0;
178 }
179
180 int v3_raise_irq(struct guest_info * info, int irq) {
181   // Look up PIC and resend
182   V3_ASSERT(info);
183   V3_ASSERT(info->intr_state.controller);
184   V3_ASSERT(info->intr_state.controller->raise_intr);
185
186   PrintDebug("[v3_raise_irq]\n");
187
188   if ((info->intr_state.controller) && 
189       (info->intr_state.controller->raise_intr)) {
190     info->intr_state.controller->raise_intr(info->intr_state.controller_state, irq);
191   } else {
192     PrintDebug("There is no registered Interrupt Controller... (NULL POINTER)\n");
193     return -1;
194   }
195
196   return 0;
197 }
198
199  
200
201 int intr_pending(struct guest_info * info) {
202   struct vm_intr * intr_state = &(info->intr_state);
203
204   //  PrintDebug("[intr_pending]\n");
205   if (intr_state->excp_pending == 1) {
206     return 1;
207   } else if (intr_state->controller->intr_pending(intr_state->controller_state) == 1) {
208     return 1;
209   }
210
211   /* Check [A]PIC */
212
213   return 0;
214 }
215
216
217 uint_t get_intr_number(struct guest_info * info) {
218   struct vm_intr * intr_state = &(info->intr_state);
219
220   if (intr_state->excp_pending == 1) {
221     return intr_state->excp_num;
222   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
223     PrintDebug("[get_intr_number] intr_number = %d\n", intr_state->controller->get_intr_number(intr_state->controller_state));
224     return intr_state->controller->get_intr_number(intr_state->controller_state);
225   }
226
227   /* someway to get the [A]PIC intr */
228
229   return 0;
230 }
231
232
233 intr_type_t get_intr_type(struct guest_info * info) {
234  struct vm_intr * intr_state = &(info->intr_state);
235
236   if (intr_state->excp_pending) {
237     PrintDebug("[get_intr_type] Exception\n");
238     return EXCEPTION;
239   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
240     PrintDebug("[get_intr_type] External_irq\n");
241     return EXTERNAL_IRQ;
242   }
243     PrintDebug("[get_intr_type] Invalid_Intr\n");
244   return INVALID_INTR;
245 }
246
247
248
249
250
251
252 int injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type) {
253   struct vm_intr * intr_state = &(info->intr_state);
254
255   if (type == EXCEPTION) {
256     PrintDebug("[injecting_intr] Exception\n");
257     intr_state->excp_pending = 0;
258     intr_state->excp_num = 0;
259     intr_state->excp_error_code = 0;
260     intr_state->excp_error_code_valid = 0;
261     
262   } else if (type == EXTERNAL_IRQ) {
263     PrintDebug("[injecting_intr] External_Irq with intr_num = %x\n", intr_num);
264     return intr_state->controller->begin_irq(intr_state->controller_state, intr_num);
265   }
266
267   return 0;
268 }