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.


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