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.


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