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 copyright tags
[palacios.git] / palacios / src / palacios / vmm_intr.c
1 /* Northwestern University */
2 /* (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> */
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   return 0;
160 }
161
162 int v3_raise_irq(struct guest_info * info, int irq) {
163   // Look up PIC and resend
164   V3_ASSERT(info);
165   V3_ASSERT(info->intr_state.controller);
166   V3_ASSERT(info->intr_state.controller->raise_intr);
167
168   PrintDebug("[v3_raise_irq]\n");
169
170   //  if ((info->intr_state.controller) && 
171   //  (info->intr_state.controller->raise_intr)) {
172     info->intr_state.controller->raise_intr(info->intr_state.controller_state, irq);
173     //} else {
174     // PrintDebug("There is no registered Interrupt Controller... (NULL POINTER)\n");
175     // return -1;
176     //}
177   return 0;
178 }
179
180  
181
182 int intr_pending(struct guest_info * info) {
183   struct vm_intr * intr_state = &(info->intr_state);
184
185   //  PrintDebug("[intr_pending]\n");
186   if (intr_state->excp_pending == 1) {
187     return 1;
188   } else if (intr_state->controller->intr_pending(intr_state->controller_state) == 1) {
189     return 1;
190   }
191
192   /* Check [A]PIC */
193
194   return 0;
195 }
196
197
198 uint_t get_intr_number(struct guest_info * info) {
199   struct vm_intr * intr_state = &(info->intr_state);
200
201   if (intr_state->excp_pending == 1) {
202     return intr_state->excp_num;
203   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
204     PrintDebug("[get_intr_number] intr_number = %d\n", intr_state->controller->get_intr_number(intr_state->controller_state));
205     return intr_state->controller->get_intr_number(intr_state->controller_state);
206   }
207
208   /* someway to get the [A]PIC intr */
209
210   return 0;
211 }
212
213
214 intr_type_t get_intr_type(struct guest_info * info) {
215  struct vm_intr * intr_state = &(info->intr_state);
216
217   if (intr_state->excp_pending) {
218     PrintDebug("[get_intr_type] Exception\n");
219     return EXCEPTION;
220   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
221     PrintDebug("[get_intr_type] External_irq\n");
222     return EXTERNAL_IRQ;
223   }
224     PrintDebug("[get_intr_type] Invalid_Intr\n");
225   return INVALID_INTR;
226 }
227
228
229
230
231
232
233 int injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type) {
234   struct vm_intr * intr_state = &(info->intr_state);
235
236   if (type == EXCEPTION) {
237     PrintDebug("[injecting_intr] Exception\n");
238     intr_state->excp_pending = 0;
239     intr_state->excp_num = 0;
240     intr_state->excp_error_code = 0;
241     intr_state->excp_error_code_valid = 0;
242     
243   } else if (type == EXTERNAL_IRQ) {
244     PrintDebug("[injecting_intr] External_Irq with intr_num = %x\n", intr_num);
245     return intr_state->controller->begin_irq(intr_state->controller_state, intr_num);
246   }
247
248   return 0;
249 }