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.


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