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.


source code clean up,
[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 v3_hook_irq(uint_t irq,
38              void (*handler)(struct vmm_intr_state *state),
39              void  *opaque)
40 {
41   struct vmm_intr_decode *d = (struct vmm_intr_decode *)V3_Malloc(sizeof(struct vmm_intr_decode));
42
43   if (!d) { return -1; }
44
45   d->handler = handler;
46   d->opaque = opaque;
47   
48   if (V3_Hook_Interrupt(irq,d)) { 
49     PrintError("hook_irq: failed to hook irq 0x%x to decode 0x%x\n", irq,d);
50     return -1;
51   } else {
52     PrintDebug("hook_irq: hooked irq 0x%x to decode 0x%x\n", irq,d);
53     return 0;
54   }
55 }
56
57
58 void deliver_interrupt_to_vmm(struct vmm_intr_state *state)
59 {
60
61   PrintDebug("deliver_interrupt_to_vmm: state=0x%x\n",state);
62
63   struct vmm_intr_decode *d = (struct vmm_intr_decode *)(state->opaque);
64   
65   void *temp = state->opaque;
66   state->opaque = d->opaque;
67
68   d->handler(state);
69   
70   state->opaque=temp;
71 }
72
73
74 static void guest_injection_irq_handler(struct vmm_intr_state *state)
75 {
76   PrintDebug("guest_irq_injection: state=0x%x\n",state);
77
78   struct guest_info *guest = (struct guest_info *)(state->opaque);
79
80   PrintDebug("guest_irq_injection: injecting irq 0x%x into guest 0x%x\n",state->irq,guest);
81   guest->vm_ops.raise_irq(guest,state->irq);
82 }
83
84
85 int v3_hook_irq_for_guest_injection(struct guest_info *info, int irq)
86 {
87
88   int rc = v3_hook_irq(irq,
89                        guest_injection_irq_handler,
90                        info);
91
92   if (rc) { 
93     PrintError("guest_irq_injection: failed to hook irq 0x%x for guest 0x%x\n", irq,info);
94     return -1;
95   } else {
96     PrintDebug("guest_irq_injection: hooked irq 0x%x for guest 0x%x\n", irq,info);
97     return 0;
98   }
99 }
100
101
102
103
104 int v3_raise_exception_with_error(struct guest_info * info, uint_t excp, uint_t error_code) {
105   struct vm_intr * intr_state = &(info->intr_state);
106
107   if (intr_state->excp_pending == 0) {
108     intr_state->excp_pending = 1;
109     intr_state->excp_num = excp;
110     intr_state->excp_error_code = error_code;
111     intr_state->excp_error_code_valid = 1;
112     PrintDebug("Raising exception with error code: %x\n", error_code);
113   } else {
114     PrintError("exception already pending, currently not implemented\n");
115     return -1;
116   }
117
118   return 0;
119 }
120
121 int v3_raise_exception(struct guest_info * info, uint_t excp) {
122   struct vm_intr * intr_state = &(info->intr_state);
123
124   if (intr_state->excp_pending == 0) {
125     intr_state->excp_pending = 1;
126     intr_state->excp_num = excp;
127     intr_state->excp_error_code = 0;
128     intr_state->excp_error_code_valid = 0;
129   } else {
130     PrintError("exception already pending, currently not implemented\n");
131     return -1;
132   }
133
134   return 0;
135 }
136
137
138 int v3_raise_irq(struct guest_info * info, int irq) {
139   // Look up PIC and resend
140   V3_ASSERT(info);
141   V3_ASSERT(info->intr_state.controller);
142   V3_ASSERT(info->intr_state.controller->raise_intr);
143
144   //  if ((info->intr_state.controller) && 
145   //  (info->intr_state.controller->raise_intr)) {
146     info->intr_state.controller->raise_intr(info->intr_state.controller_state, irq);
147     //} else {
148     // PrintDebug("There is no registered Interrupt Controller... (NULL POINTER)\n");
149     // return -1;
150     //}
151   return 0;
152 }
153
154
155
156 int intr_pending(struct guest_info * info) {
157   struct vm_intr * intr_state = &(info->intr_state);
158
159   if (intr_state->excp_pending == 1) {
160     return 1;
161   } else if (intr_state->controller->intr_pending(intr_state->controller_state) == 1) {
162     return 1;
163   }
164
165   /* Check [A]PIC */
166
167   return 0;
168 }
169
170
171 uint_t get_intr_number(struct guest_info * info) {
172   struct vm_intr * intr_state = &(info->intr_state);
173
174   if (intr_state->excp_pending == 1) {
175     return intr_state->excp_num;
176   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
177     return intr_state->controller->get_intr_number(intr_state->controller_state);
178   }
179
180   /* someway to get the [A]PIC intr */
181
182   return 0;
183 }
184
185
186 intr_type_t get_intr_type(struct guest_info * info) {
187  struct vm_intr * intr_state = &(info->intr_state);
188
189   if (intr_state->excp_pending) {
190     return EXCEPTION;
191   } else if (intr_state->controller->intr_pending(intr_state->controller_state)) {
192     return EXTERNAL_IRQ;
193   }
194
195   return INVALID_INTR;
196 }
197
198
199
200
201
202
203 int injecting_intr(struct guest_info * info, uint_t intr_num, intr_type_t type) {
204   struct vm_intr * intr_state = &(info->intr_state);
205
206   if (type == EXCEPTION) {
207
208     intr_state->excp_pending = 0;
209     intr_state->excp_num = 0;
210     intr_state->excp_error_code = 0;
211     intr_state->excp_error_code_valid = 0;
212     
213   } else if (type == EXTERNAL_IRQ) {
214     return intr_state->controller->begin_irq(intr_state->controller_state, intr_num);
215   }
216
217   return 0;
218 }