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.


code for new irq hooking mechanism
[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
7
8 void init_interrupt_state(struct guest_info * info) {
9   info->intr_state.excp_pending = 0;
10   info->intr_state.excp_num = 0;
11   info->intr_state.excp_error_code = 0;
12
13   info->vm_ops.raise_irq = &v3_raise_irq;
14 }
15
16 void set_intr_controller(struct guest_info * info, struct intr_ctrl_ops * ops, void * state) {
17   info->intr_state.controller = ops;
18   info->intr_state.controller_state = state;
19 }
20
21
22
23 // This structure is used to dispatch
24 // interrupts delivered to vmm via deliver interrupt to vmm 
25 // it is what we put into the opaque field given to 
26 // the host os when we install the handler
27 struct vmm_intr_decode { 
28   void              (*handler)(struct vmm_intr_state *state);
29   // This opaque is user supplied by the caller
30   // of hook_irq_new
31   void              *opaque;
32 };
33
34 int hook_irq_new(uint_t irq,
35                  void (*handler)(struct vmm_intr_state *state),
36                  void  *opaque)
37 {
38   extern struct vmm_os_hooks * os_hooks;
39
40   struct vmm_intr_decode *d = V3_Malloc(sizeof(struct vmm_intr_decode));
41
42   if (!d) { return -1; }
43
44   d->handler = handler;
45   d->opaque = opaque;
46   
47   if (os_hooks->hook_interrupt_new(irq,d)) { 
48     PrintDebug("hook_irq_new: failed to hook irq 0x%x to decode 0x%x\n", irq,d);
49     return -1;
50   } else {
51     PrintDebug("hook_irq_new: hooked irq 0x%x to decode 0x%x\n", irq,d);
52     return 0;
53   }
54 }
55
56
57 void deliver_interrupt_to_vmm(struct vmm_intr_state *state)
58 {
59
60   PrintDebug("deliver_interrupt_to_vmm: state=0x%x\n",state);
61
62   struct vmm_intr_decode *d = (struct vmm_intr_decode *)(state->opaque);
63   
64   void *temp = state->opaque;
65   state->opaque = d->opaque;
66
67   d->handler(state);
68   
69   state->opaque=temp;
70 }
71
72
73 void guest_injection_irq_handler(struct vmm_intr_state *state)
74 {
75   PrintDebug("guest_irq_injection: state=0x%x\n",state);
76
77   struct guest_info *guest = (struct guest_info *)(state->opaque);
78
79   PrintDebug("guest_irq_injection: injecting irq 0x%x into guest 0x%x\n",state->irq,guest);
80   guest->vm_ops.raise_irq(guest,state->irq);
81 }
82
83
84 int hook_irq_for_guest_injection(struct guest_info *info, int irq)
85 {
86
87   int rc = hook_irq_new(irq,
88                         guest_injection_irq_handler,
89                         info);
90
91   if (rc) { 
92     PrintDebug("guest_irq_injection: failed to hook irq 0x%x for guest 0x%x\n", irq,info);
93     return -1;
94   } else {
95     PrintDebug("guest_irq_injection: hooked irq 0x%x for guest 0x%x\n", irq,info);
96     return 0;
97   }
98 }
99
100
101
102
103 int hook_irq(struct guest_info * info, int irq) {
104   extern struct vmm_os_hooks * os_hooks;
105
106   return os_hooks->hook_interrupt(info, irq);
107 }
108
109 int 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("Raising exception with error code: %x\n", error_code);
118   } else {
119     PrintDebug("exception already pending, currently not implemented\n");
120     return -1;
121   }
122
123   return 0;
124 }
125
126 int raise_exception(struct guest_info * info, uint_t excp) {
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 = 0;
133     intr_state->excp_error_code_valid = 0;
134   } else {
135     PrintDebug("exception already pending, currently not implemented\n");
136     return -1;
137   }
138
139   return 0;
140 }
141
142
143 int v3_raise_irq(struct guest_info * info, int irq) {
144   // Look up PIC and resend
145   V3_ASSERT(info);
146   V3_ASSERT(info->intr_state.controller);
147   V3_ASSERT(info->intr_state.controller->raise_intr);
148
149   //  if ((info->intr_state.controller) && 
150   //  (info->intr_state.controller->raise_intr)) {
151     info->intr_state.controller->raise_intr(info->intr_state.controller_state, irq);
152     //} else {
153     // PrintDebug("There is no registered Interrupt Controller... (NULL POINTER)\n");
154     // return -1;
155     //}
156   return 0;
157 }
158
159
160
161 int intr_pending(struct guest_info * info) {
162   struct vm_intr * intr_state = &(info->intr_state);
163
164   if (intr_state->excp_pending == 1) {
165     return 1;
166   } else if (intr_state->controller->intr_pending(intr_state->controller_state) == 1) {
167     return 1;
168   }
169
170   /* Check [A]PIC */
171
172   return 0;
173 }
174
175
176 uint_t get_intr_number(struct guest_info * info) {
177   struct vm_intr * intr_state = &(info->intr_state);
178
179   if (intr_state->excp_pending == 1) {
180     return intr_state->excp_num;
181   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
182     return intr_state->controller->get_intr_number(intr_state->controller_state);
183   }
184
185   /* someway to get the [A]PIC intr */
186
187   return 0;
188 }
189
190
191 intr_type_t get_intr_type(struct guest_info * info) {
192  struct vm_intr * intr_state = &(info->intr_state);
193
194   if (intr_state->excp_pending) {
195     return EXCEPTION;
196   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
197     return EXTERNAL_IRQ;
198   }
199
200   return INVALID_INTR;
201 }
202
203
204
205
206
207
208 int injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type) {
209   struct vm_intr * intr_state = &(info->intr_state);
210
211   if (type == EXCEPTION) {
212
213     intr_state->excp_pending = 0;
214     intr_state->excp_num = 0;
215     intr_state->excp_error_code = 0;
216     intr_state->excp_error_code_valid = 0;
217     
218   } else if (type == EXTERNAL_IRQ) {
219     return intr_state->controller->begin_irq(intr_state->controller_state, intr_num);
220   }
221
222   return 0;
223 }