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-OLD.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   return 0;
177 }
178
179 int v3_raise_irq(struct guest_info * info, int irq) {
180   // Look up PIC and resend
181   V3_ASSERT(info);
182   V3_ASSERT(info->intr_state.controller);
183   V3_ASSERT(info->intr_state.controller->raise_intr);
184
185   PrintDebug("[v3_raise_irq]\n");
186
187   //  if ((info->intr_state.controller) && 
188   //  (info->intr_state.controller->raise_intr)) {
189     info->intr_state.controller->raise_intr(info->intr_state.controller_state, irq);
190     //} else {
191     // PrintDebug("There is no registered Interrupt Controller... (NULL POINTER)\n");
192     // return -1;
193     //}
194   return 0;
195 }
196
197  
198
199 int intr_pending(struct guest_info * info) {
200   struct vm_intr * intr_state = &(info->intr_state);
201
202   //  PrintDebug("[intr_pending]\n");
203   if (intr_state->excp_pending == 1) {
204     return 1;
205   } else if (intr_state->controller->intr_pending(intr_state->controller_state) == 1) {
206     return 1;
207   }
208
209   /* Check [A]PIC */
210
211   return 0;
212 }
213
214
215 uint_t get_intr_number(struct guest_info * info) {
216   struct vm_intr * intr_state = &(info->intr_state);
217
218   if (intr_state->excp_pending == 1) {
219     return intr_state->excp_num;
220   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
221     PrintDebug("[get_intr_number] intr_number = %d\n", intr_state->controller->get_intr_number(intr_state->controller_state));
222     return intr_state->controller->get_intr_number(intr_state->controller_state);
223   }
224
225   /* someway to get the [A]PIC intr */
226
227   return 0;
228 }
229
230
231 intr_type_t get_intr_type(struct guest_info * info) {
232  struct vm_intr * intr_state = &(info->intr_state);
233
234   if (intr_state->excp_pending) {
235     PrintDebug("[get_intr_type] Exception\n");
236     return EXCEPTION;
237   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
238     PrintDebug("[get_intr_type] External_irq\n");
239     return EXTERNAL_IRQ;
240   }
241     PrintDebug("[get_intr_type] Invalid_Intr\n");
242   return INVALID_INTR;
243 }
244
245
246
247
248
249
250 int injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type) {
251   struct vm_intr * intr_state = &(info->intr_state);
252
253   if (type == EXCEPTION) {
254     PrintDebug("[injecting_intr] Exception\n");
255     intr_state->excp_pending = 0;
256     intr_state->excp_num = 0;
257     intr_state->excp_error_code = 0;
258     intr_state->excp_error_code_valid = 0;
259     
260   } else if (type == EXTERNAL_IRQ) {
261     PrintDebug("[injecting_intr] External_Irq with intr_num = %x\n", intr_num);
262     return intr_state->controller->begin_irq(intr_state->controller_state, intr_num);
263   }
264
265   return 0;
266 }