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.


Modifications to make apic.c compile with PrintDebug on. io_apic/apic interactions...
[palacios.git] / palacios / src / devices / apic.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21 #include <devices/apic.h>
22 #include <devices/apic_regs.h>
23 #include <palacios/vmm.h>
24 #include <palacios/vmm_msr.h>
25 #include <palacios/vmm_sprintf.h>
26 #include <palacios/vm_guest.h>
27 #include <palacios/vmm_types.h>
28
29
30 #ifndef CONFIG_DEBUG_APIC
31 #undef PrintDebug
32 #define PrintDebug(fmt, args...)
33 #endif
34
35 #ifdef CONFIG_DEBUG_APIC
36 static char *shorthand_str[] = { 
37     "(no shorthand)",
38     "(self)",
39     "(all)",
40     "(all-but-me)",
41 };
42
43 static char *deliverymode_str[] = { 
44     "(fixed)",
45     "(lowest priority)",
46     "(SMI)",
47     "(reserved)",
48     "(NMI)",
49     "(INIT)",
50     "(Start Up)",
51     "(ExtInt)",
52 };
53 #endif
54
55 typedef enum { APIC_TMR_INT, APIC_THERM_INT, APIC_PERF_INT, 
56                APIC_LINT0_INT, APIC_LINT1_INT, APIC_ERR_INT } apic_irq_type_t;
57
58 #define APIC_FIXED_DELIVERY  0x0
59 #define APIC_SMI_DELIVERY    0x2
60 #define APIC_NMI_DELIVERY    0x4
61 #define APIC_INIT_DELIVERY   0x5
62 #define APIC_EXTINT_DELIVERY 0x7
63
64
65 #define BASE_ADDR_MSR     0x0000001B
66 #define DEFAULT_BASE_ADDR 0xfee00000
67
68 #define APIC_ID_OFFSET                    0x020
69 #define APIC_VERSION_OFFSET               0x030
70 #define TPR_OFFSET                        0x080
71 #define APR_OFFSET                        0x090
72 #define PPR_OFFSET                        0x0a0
73 #define EOI_OFFSET                        0x0b0
74 #define REMOTE_READ_OFFSET                0x0c0
75 #define LDR_OFFSET                        0x0d0
76 #define DFR_OFFSET                        0x0e0
77 #define SPURIOUS_INT_VEC_OFFSET           0x0f0
78
79 #define ISR_OFFSET0                       0x100   // 0x100 - 0x170
80 #define ISR_OFFSET1                       0x110   // 0x100 - 0x170
81 #define ISR_OFFSET2                       0x120   // 0x100 - 0x170
82 #define ISR_OFFSET3                       0x130   // 0x100 - 0x170
83 #define ISR_OFFSET4                       0x140   // 0x100 - 0x170
84 #define ISR_OFFSET5                       0x150   // 0x100 - 0x170
85 #define ISR_OFFSET6                       0x160   // 0x100 - 0x170
86 #define ISR_OFFSET7                       0x170   // 0x100 - 0x170
87
88 #define TRIG_OFFSET0                      0x180   // 0x180 - 0x1f0
89 #define TRIG_OFFSET1                      0x190   // 0x180 - 0x1f0
90 #define TRIG_OFFSET2                      0x1a0   // 0x180 - 0x1f0
91 #define TRIG_OFFSET3                      0x1b0   // 0x180 - 0x1f0
92 #define TRIG_OFFSET4                      0x1c0   // 0x180 - 0x1f0
93 #define TRIG_OFFSET5                      0x1d0   // 0x180 - 0x1f0
94 #define TRIG_OFFSET6                      0x1e0   // 0x180 - 0x1f0
95 #define TRIG_OFFSET7                      0x1f0   // 0x180 - 0x1f0
96
97
98 #define IRR_OFFSET0                       0x200   // 0x200 - 0x270
99 #define IRR_OFFSET1                       0x210   // 0x200 - 0x270
100 #define IRR_OFFSET2                       0x220   // 0x200 - 0x270
101 #define IRR_OFFSET3                       0x230   // 0x200 - 0x270
102 #define IRR_OFFSET4                       0x240   // 0x200 - 0x270
103 #define IRR_OFFSET5                       0x250   // 0x200 - 0x270
104 #define IRR_OFFSET6                       0x260   // 0x200 - 0x270
105 #define IRR_OFFSET7                       0x270   // 0x200 - 0x270
106
107
108 #define ESR_OFFSET                        0x280
109 #define INT_CMD_LO_OFFSET                 0x300
110 #define INT_CMD_HI_OFFSET                 0x310
111 #define TMR_LOC_VEC_TBL_OFFSET            0x320
112 #define THERM_LOC_VEC_TBL_OFFSET          0x330
113 #define PERF_CTR_LOC_VEC_TBL_OFFSET       0x340
114 #define LINT0_VEC_TBL_OFFSET              0x350
115 #define LINT1_VEC_TBL_OFFSET              0x360
116 #define ERR_VEC_TBL_OFFSET                0x370
117 #define TMR_INIT_CNT_OFFSET               0x380
118 #define TMR_CUR_CNT_OFFSET                0x390
119 #define TMR_DIV_CFG_OFFSET                0x3e0
120 #define EXT_APIC_FEATURE_OFFSET           0x400
121 #define EXT_APIC_CMD_OFFSET               0x410
122 #define SEOI_OFFSET                       0x420
123
124 #define IER_OFFSET0                       0x480   // 0x480 - 0x4f0
125 #define IER_OFFSET1                       0x490   // 0x480 - 0x4f0
126 #define IER_OFFSET2                       0x4a0   // 0x480 - 0x4f0
127 #define IER_OFFSET3                       0x4b0   // 0x480 - 0x4f0
128 #define IER_OFFSET4                       0x4c0   // 0x480 - 0x4f0
129 #define IER_OFFSET5                       0x4d0   // 0x480 - 0x4f0
130 #define IER_OFFSET6                       0x4e0   // 0x480 - 0x4f0
131 #define IER_OFFSET7                       0x4f0   // 0x480 - 0x4f0
132
133 #define EXT_INT_LOC_VEC_TBL_OFFSET0       0x500   // 0x500 - 0x530
134 #define EXT_INT_LOC_VEC_TBL_OFFSET1       0x510   // 0x500 - 0x530
135 #define EXT_INT_LOC_VEC_TBL_OFFSET2       0x520   // 0x500 - 0x530
136 #define EXT_INT_LOC_VEC_TBL_OFFSET3       0x530   // 0x500 - 0x530
137
138
139
140
141
142 struct apic_msr {
143     union {
144         uint64_t value;
145         struct {
146             uint8_t rsvd;
147             uint8_t bootstrap_cpu : 1;
148             uint8_t rsvd2         : 2;
149             uint8_t apic_enable   : 1;
150             uint64_t base_addr   : 40;
151             uint32_t rsvd3         : 12;
152         } __attribute__((packed));
153     } __attribute__((packed));
154 } __attribute__((packed));
155
156
157
158 typedef enum {INIT, SIPI, STARTED} ipi_state_t; 
159
160 struct apic_dev_state;
161
162 struct apic_state {
163     addr_t base_addr;
164
165     /* MSRs */
166     struct apic_msr base_addr_msr;
167
168
169     /* memory map registers */
170
171     struct lapic_id_reg lapic_id;
172     struct apic_ver_reg apic_ver;
173     struct ext_apic_ctrl_reg ext_apic_ctrl;
174     struct local_vec_tbl_reg local_vec_tbl;
175     struct tmr_vec_tbl_reg tmr_vec_tbl;
176     struct tmr_div_cfg_reg tmr_div_cfg;
177     struct lint_vec_tbl_reg lint0_vec_tbl;
178     struct lint_vec_tbl_reg lint1_vec_tbl;
179     struct perf_ctr_loc_vec_tbl_reg perf_ctr_loc_vec_tbl;
180     struct therm_loc_vec_tbl_reg therm_loc_vec_tbl;
181     struct err_vec_tbl_reg err_vec_tbl;
182     struct err_status_reg err_status;
183     struct spurious_int_reg spurious_int;
184     struct int_cmd_reg int_cmd;
185     struct log_dst_reg log_dst;
186     struct dst_fmt_reg dst_fmt;
187     struct arb_prio_reg arb_prio;
188     struct task_prio_reg task_prio;
189     struct proc_prio_reg proc_prio;
190     struct ext_apic_feature_reg ext_apic_feature;
191     struct spec_eoi_reg spec_eoi;
192   
193
194     uint32_t tmr_cur_cnt;
195     uint32_t tmr_init_cnt;
196
197
198     struct local_vec_tbl_reg ext_intr_vec_tbl[4];
199
200     uint32_t rem_rd_data;
201
202
203     ipi_state_t ipi_state;
204
205     uint8_t int_req_reg[32];
206     uint8_t int_svc_reg[32];
207     uint8_t int_en_reg[32];
208     uint8_t trig_mode_reg[32];
209
210     struct guest_info * core;
211
212     uint32_t eoi;
213
214     v3_lock_t  lock;
215 };
216
217
218
219
220 struct apic_dev_state {
221     int num_apics;
222
223     struct apic_state apics[0];
224 } __attribute__((packed));
225
226
227
228 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data);
229 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data);
230
231 static void init_apic_state(struct apic_state * apic, uint32_t id) {
232     apic->base_addr = DEFAULT_BASE_ADDR;
233
234     if (id == 0) { 
235         // boot processor, enabled
236         apic->base_addr_msr.value = 0x0000000000000900LL;
237     } else {
238         // ap processor, enabled
239         apic->base_addr_msr.value = 0x0000000000000800LL;
240     }
241
242     // same base address regardless of ap or main
243     apic->base_addr_msr.value |= ((uint64_t)DEFAULT_BASE_ADDR); 
244
245     PrintDebug("apic %u: (init_apic_state): msr=0x%llx\n",id, apic->base_addr_msr.value);
246
247     PrintDebug("apic %u: (init_apic_state): Sizeof Interrupt Request Register %d, should be 32\n",
248                id, (uint_t)sizeof(apic->int_req_reg));
249
250     memset(apic->int_req_reg, 0, sizeof(apic->int_req_reg));
251     memset(apic->int_svc_reg, 0, sizeof(apic->int_svc_reg));
252     memset(apic->int_en_reg, 0xff, sizeof(apic->int_en_reg));
253     memset(apic->trig_mode_reg, 0, sizeof(apic->trig_mode_reg));
254
255     apic->eoi = 0x00000000;
256     apic->rem_rd_data = 0x00000000;
257     apic->tmr_init_cnt = 0x00000000;
258     apic->tmr_cur_cnt = 0x00000000;
259
260     apic->lapic_id.val = id;
261     
262     apic->ipi_state = INIT;
263
264     // The P6 has 6 LVT entries, so we set the value to (6-1)...
265     apic->apic_ver.val = 0x80050010;
266
267     apic->task_prio.val = 0x00000000;
268     apic->arb_prio.val = 0x00000000;
269     apic->proc_prio.val = 0x00000000;
270     apic->log_dst.val = 0x00000000;
271     apic->dst_fmt.val = 0xffffffff;
272     apic->spurious_int.val = 0x000000ff;
273     apic->err_status.val = 0x00000000;
274     apic->int_cmd.val = 0x0000000000000000LL;
275     apic->tmr_vec_tbl.val = 0x00010000;
276     apic->therm_loc_vec_tbl.val = 0x00010000;
277     apic->perf_ctr_loc_vec_tbl.val = 0x00010000;
278     apic->lint0_vec_tbl.val = 0x00010000;
279     apic->lint1_vec_tbl.val = 0x00010000;
280     apic->err_vec_tbl.val = 0x00010000;
281     apic->tmr_div_cfg.val = 0x00000000;
282     //apic->ext_apic_feature.val = 0x00000007;
283     apic->ext_apic_feature.val = 0x00040007;
284     apic->ext_apic_ctrl.val = 0x00000000;
285     apic->spec_eoi.val = 0x00000000;
286
287     v3_lock_init(&(apic->lock));
288 }
289
290
291
292
293 static int read_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
294     struct apic_dev_state * apic_dev = (struct apic_dev_state *)priv_data;
295     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]);
296
297     PrintDebug("apic %u: core %u: MSR read\n", apic->lapic_id.val, core->cpu_id);
298     v3_lock(apic->lock);
299     dst->value = apic->base_addr;
300     v3_unlock(apic->lock);
301     return 0;
302 }
303
304
305 static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
306     struct apic_dev_state * apic_dev = (struct apic_dev_state *)priv_data;
307     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]);
308     struct v3_mem_region * old_reg = v3_get_mem_region(core->vm_info, core->cpu_id, apic->base_addr);
309
310
311     PrintDebug("apic %u: core %u: MSR write\n", apic->lapic_id.val, core->cpu_id);
312
313     if (old_reg == NULL) {
314         // uh oh...
315         PrintError("apic %u: core %u: APIC Base address region does not exit...\n",
316                    apic->lapic_id.val, core->cpu_id);
317         return -1;
318     }
319     
320     v3_lock(apic->lock);
321
322     v3_delete_mem_region(core->vm_info, old_reg);
323
324     apic->base_addr = src.value;
325
326     if (v3_hook_full_mem(core->vm_info, core->cpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, apic_dev) == -1) {
327         PrintError("apic %u: core %u: Could not hook new APIC Base address\n",
328                    apic->lapic_id.val, core->cpu_id);
329         v3_unlock(apic->lock);
330         return -1;
331     }
332
333     v3_unlock(apic->lock);
334     return 0;
335 }
336
337
338 // irq_num is the bit offset into a 256 bit buffer...
339 static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
340     int major_offset = (irq_num & ~0x00000007) >> 3;
341     int minor_offset = irq_num & 0x00000007;
342     uint8_t * req_location = apic->int_req_reg + major_offset;
343     uint8_t * en_location = apic->int_en_reg + major_offset;
344     uint8_t flag = 0x1 << minor_offset;
345
346
347
348     if (irq_num <= 15) {
349         PrintError("apic %u: core ?: Attempting to raise an invalid interrupt: %d\n", apic->lapic_id.val,irq_num);
350         return -1;
351     }
352
353
354     PrintDebug("apic %u: core ?: Raising APIC IRQ %d\n", apic->lapic_id.val, irq_num);
355
356     if (*req_location & flag) {
357         //V3_Print("Interrupts coallescing\n");
358     }
359
360     if (*en_location & flag) {
361         *req_location |= flag;
362     } else {
363         PrintDebug("apic %u: core ?: Interrupt  not enabled... %.2x\n", 
364                    apic->lapic_id.val, *en_location);
365         return 0;
366     }
367
368     return 0;
369 }
370
371
372
373 static int get_highest_isr(struct apic_state * apic) {
374     int i = 0, j = 0;
375
376     // We iterate backwards to find the highest priority
377     for (i = 31; i >= 0; i--) {
378         uint8_t  * svc_major = apic->int_svc_reg + i;
379     
380         if ((*svc_major) & 0xff) {
381             for (j = 7; j >= 0; j--) {
382                 uint8_t flag = 0x1 << j;
383                 if ((*svc_major) & flag) {
384                     return ((i * 8) + j);
385                 }
386             }
387         }
388     }
389
390     return -1;
391 }
392  
393
394
395 static int get_highest_irr(struct apic_state * apic) {
396     int i = 0, j = 0;
397
398     // We iterate backwards to find the highest priority
399     for (i = 31; i >= 0; i--) {
400         uint8_t  * req_major = apic->int_req_reg + i;
401     
402         if ((*req_major) & 0xff) {
403             for (j = 7; j >= 0; j--) {
404                 uint8_t flag = 0x1 << j;
405                 if ((*req_major) & flag) {
406                     return ((i * 8) + j);
407                 }
408             }
409         }
410     }
411
412     return -1;
413 }
414  
415
416
417
418 static int apic_do_eoi(struct apic_state * apic) {
419     int isr_irq = get_highest_isr(apic);
420
421     if (isr_irq != -1) {
422         int major_offset = (isr_irq & ~0x00000007) >> 3;
423         int minor_offset = isr_irq & 0x00000007;
424         uint8_t flag = 0x1 << minor_offset;
425         uint8_t * svc_location = apic->int_svc_reg + major_offset;
426         
427         PrintDebug("apic %u: core ?: Received APIC EOI for IRQ %d\n", apic->lapic_id.val,isr_irq);
428         
429         *svc_location &= ~flag;
430
431 #ifdef CONFIG_CRAY_XT
432         
433         if ((isr_irq == 238) || 
434             (isr_irq == 239)) {
435             PrintDebug("apic %u: core ?: Acking IRQ %d\n", apic->lapic_id.val,isr_irq);
436         }
437         
438         if (isr_irq == 238) {
439             V3_ACK_IRQ(238);
440         }
441 #endif
442     } else {
443         //PrintError("apic %u: core ?: Spurious EOI...\n",apic->lapic_id.val);
444     }
445         
446     return 0;
447 }
448  
449
450 static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_type) {
451     uint32_t vec_num = 0;
452     uint32_t del_mode = 0;
453     int masked = 0;
454
455
456     switch (int_type) {
457         case APIC_TMR_INT:
458             vec_num = apic->tmr_vec_tbl.vec;
459             del_mode = APIC_FIXED_DELIVERY;
460             masked = apic->tmr_vec_tbl.mask;
461             break;
462         case APIC_THERM_INT:
463             vec_num = apic->therm_loc_vec_tbl.vec;
464             del_mode = apic->therm_loc_vec_tbl.msg_type;
465             masked = apic->therm_loc_vec_tbl.mask;
466             break;
467         case APIC_PERF_INT:
468             vec_num = apic->perf_ctr_loc_vec_tbl.vec;
469             del_mode = apic->perf_ctr_loc_vec_tbl.msg_type;
470             masked = apic->perf_ctr_loc_vec_tbl.mask;
471             break;
472         case APIC_LINT0_INT:
473             vec_num = apic->lint0_vec_tbl.vec;
474             del_mode = apic->lint0_vec_tbl.msg_type;
475             masked = apic->lint0_vec_tbl.mask;
476             break;
477         case APIC_LINT1_INT:
478             vec_num = apic->lint1_vec_tbl.vec;
479             del_mode = apic->lint1_vec_tbl.msg_type;
480             masked = apic->lint1_vec_tbl.mask;
481             break;
482         case APIC_ERR_INT:
483             vec_num = apic->err_vec_tbl.vec;
484             del_mode = APIC_FIXED_DELIVERY;
485             masked = apic->err_vec_tbl.mask;
486             break;
487         default:
488             PrintError("apic %u: core ?: Invalid APIC interrupt type\n", apic->lapic_id.val);
489             return -1;
490     }
491
492     // interrupt is masked, don't send
493     if (masked == 1) {
494         PrintDebug("apic %u: core ?: Inerrupt is masked\n", apic->lapic_id.val);
495         return 0;
496     }
497
498     if (del_mode == APIC_FIXED_DELIVERY) {
499         //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
500         return activate_apic_irq(apic, vec_num);
501     } else {
502         PrintError("apic %u: core ?: Unhandled Delivery Mode\n", apic->lapic_id.val);
503         return -1;
504     }
505 }
506
507
508
509 static inline int should_deliver_cluster_ipi(struct guest_info * dst_core, 
510                                              struct apic_state * dst_apic, uint8_t mda) {
511
512     if  ( ((mda & 0xf0) == (dst_apic->log_dst.dst_log_id & 0xf0)) &&     // (I am in the cluster and
513           ((mda & 0x0f) & (dst_apic->log_dst.dst_log_id & 0x0f)) ) {  //  I am in the set)
514
515         PrintDebug("apic %u core %u: accepting clustered IRQ (mda 0x%x == log_dst 0x%x)\n",
516                    dst_apic->lapic_id.val, dst_core->cpu_id, mda, 
517                    dst_apic->log_dst.dst_log_id);
518         
519         return 1;
520     } else {
521         PrintDebug("apic %u core %u: rejecting clustered IRQ (mda 0x%x != log_dst 0x%x)\n",
522                    dst_apic->lapic_id.val, dst_core->cpu_id, mda, 
523                    dst_apic->log_dst.dst_log_id);
524         return 0;
525     }
526 }
527
528 static inline int should_deliver_flat_ipi(struct guest_info * dst_core,
529                                           struct apic_state * dst_apic, uint8_t mda) {
530
531     if (dst_apic->log_dst.dst_log_id & mda) {  // I am in the set 
532
533         PrintDebug("apic %u core %u: accepting flat IRQ (mda 0x%x == log_dst 0x%x)\n",
534                    dst_apic->lapic_id.val, dst_core->cpu_id, mda, 
535                    dst_apic->log_dst.dst_log_id);
536       return 1;
537   } else {
538         PrintDebug("apic %u core %u: rejecting flat IRQ (mda 0x%x != log_dst 0x%x)\n",
539                    dst_apic->lapic_id.val, dst_core->cpu_id, mda, 
540                    dst_apic->log_dst.dst_log_id);
541       return 0;
542   }
543 }
544
545
546
547 static int should_deliver_ipi(struct guest_info * dst_core, 
548                               struct apic_state * dst_apic, uint8_t mda) {
549
550     if (mda == 0xff) {
551         // always deliver broadcast
552         return 1;
553     }
554
555     if (dst_apic->dst_fmt.model == 0xf) {
556         return should_deliver_cluster_ipi(dst_core, dst_apic, mda);
557     } else if (dst_apic->dst_fmt.model == 0x0) {
558         return should_deliver_flat_ipi(dst_core, dst_apic, mda);
559     } else {
560         PrintError("apic %u core %u: invalid destination format register value 0x%x for logical mode delivery.\n", 
561                    dst_apic->lapic_id.val, dst_core->cpu_id, dst_apic->dst_fmt.model);
562         return -1;
563     }
564 }
565
566
567 static int deliver_ipi(struct guest_info * core, 
568                        struct apic_state * src_apic, 
569                        struct apic_state * dst_apic, 
570                        uint32_t vector, uint8_t del_mode) {
571
572     struct guest_info * dst_core = dst_apic->core;
573
574     switch (del_mode) {
575
576         case 0:  //fixed
577         case 1: // lowest priority
578             PrintDebug(" delivering IRQ to core %u\n", dst_core->cpu_id); 
579
580             activate_apic_irq(dst_apic, vector);
581
582             if (dst_apic != src_apic) { 
583                 // Assume core # is same as logical processor for now
584                 // TODO FIX THIS FIX THIS
585                 // THERE SHOULD BE:  guestapicid->virtualapicid map,
586                 //                   cpu_id->logical processor map
587                 //     host maitains logical proc->phsysical proc
588                 PrintDebug(" non-local core, forcing it to exit\n"); 
589
590                 v3_interrupt_cpu(core->vm_info, dst_core->cpu_id, 0);
591             }
592
593             break;
594         case 5: { //INIT
595
596             PrintDebug(" INIT delivery to core %u\n", dst_core->cpu_id);
597
598             // TODO: any APIC reset on dest core (shouldn't be needed, but not sure...)
599
600             // Sanity check
601             if (dst_apic->ipi_state != INIT) { 
602                 PrintError(" Warning: core %u is not in INIT state (mode = %d), ignored\n",
603                            dst_core->cpu_id, dst_core->cpu_mode);
604                 // Only a warning, since INIT INIT SIPI is common
605                 break;
606             }
607
608             // We transition the target core to SIPI state
609             dst_apic->ipi_state = SIPI;  // note: locking should not be needed here
610
611             // That should be it since the target core should be
612             // waiting in host on this transition
613             // either it's on another core or on a different preemptive thread
614             // in both cases, it will quickly notice this transition 
615             // in particular, we should not need to force an exit here
616
617             PrintDebug(" INIT delivery done\n");
618
619             break;                                                      
620         }
621         case 6: { //SIPI
622
623             // Sanity check
624             if (dst_apic->ipi_state != SIPI) { 
625                 PrintError(" core %u is not in SIPI state (mode = %d), ignored!\n",
626                            dst_core->cpu_id, dst_core->cpu_mode);
627                 break;
628             }
629
630             // Write the RIP, CS, and descriptor
631             // assume the rest is already good to go
632             //
633             // vector VV -> rip at 0
634             //              CS = VV00
635             //  This means we start executing at linear address VV000
636             //
637             // So the selector needs to be VV00
638             // and the base needs to be VV000
639             //
640             dst_core->rip = 0;
641             dst_core->segments.cs.selector = vector << 8;
642             dst_core->segments.cs.limit = 0xffff;
643             dst_core->segments.cs.base = vector << 12;
644
645             PrintDebug(" SIPI delivery (0x%x -> 0x%x:0x0) to core %u\n",
646                        vector, dst_core->segments.cs.selector, dst_core->cpu_id);
647             // Maybe need to adjust the APIC?
648             
649             // We transition the target core to SIPI state
650             dst_core->core_run_state = CORE_RUNNING;  // note: locking should not be needed here
651             dst_apic->ipi_state = STARTED;
652
653             // As with INIT, we should not need to do anything else
654
655             PrintDebug(" SIPI delivery done\n");
656
657             break;                                                      
658         }
659         case 2: // SMI                  
660         case 3: // reserved                                             
661         case 4: // NMI                                  
662         case 7: // ExtInt
663         default:
664             PrintError("IPI %d delivery is unsupported\n", del_mode); 
665             return -1;
666     }
667
668     return 0;
669
670 }
671
672
673 static int route_ipi(struct guest_info * core, struct apic_dev_state * apic_dev,
674                      struct apic_state * src_apic,  uint32_t icr_val) {
675     struct int_cmd_reg * icr = (struct int_cmd_reg *)&icr_val;
676     struct apic_state * dest_apic = NULL;
677
678     PrintDebug("route_ipi: src_apic=%p, icr_data=%x", 
679                src_apic, icr_val);
680
681
682     // initial sanity checks
683     if (src_apic == NULL) { 
684         PrintError("route_ipi: Apparently sending from unregistered apic id=%d\n", 
685                    src_apic->core->cpu_id);
686         return -1;
687     }
688
689
690     if ((icr->dst_mode == 0) && (icr->dst >= apic_dev->num_apics)) { 
691         PrintError("route_ipi: Attempted send to unregistered apic id=%u\n", 
692                    icr->dst);
693         return -1;
694     }
695
696     dest_apic =  &(apic_dev->apics[icr->dst]);
697
698
699     PrintDebug("route_ipi: IPI %s %u from apic %p to %s %s %u (icr=0x%llx)\n",
700                deliverymode_str[icr->del_mode], 
701                icr->vec, 
702                src_apic,               
703                (icr->dst_mode == 0) ? "(physical)" : "(logical)", 
704                shorthand_str[icr->dst_shorthand], 
705                icr->dst,
706                icr->val);
707
708
709     switch (icr->dst_shorthand) {
710
711         case 0:  // no shorthand
712             if (icr->dst_mode == 0) { 
713                 // physical delivery
714
715                 if (deliver_ipi(core, src_apic, dest_apic, 
716                                 icr->vec, icr->del_mode) == -1) {
717                     PrintError("Error: Could not deliver IPI\n");
718                     return -1;
719                 }
720
721             } else {
722                 // logical delivery
723                 int i;
724                 uint8_t mda = icr->dst;
725
726                 for (i = 0; i < apic_dev->num_apics; i++) { 
727                      dest_apic = &(apic_dev->apics[i]);
728                      int del_flag = should_deliver_ipi(dest_apic->core, dest_apic, mda);
729                      
730                      if (del_flag == -1) {
731                          PrintError("Error checking delivery mode\n");
732                          return -1;
733                      } else if (del_flag == 1) {
734                         if (deliver_ipi(core, src_apic, dest_apic, 
735                                         icr->vec, icr->del_mode) == -1) {
736                             PrintError("Error: Could not deliver IPI\n");
737                             return -1;
738                         }
739                     }
740                 }
741             }
742             
743             break;
744             
745         case 1:  // self
746
747             if (icr->dst_mode == 0) { 
748                 if (deliver_ipi(core, src_apic, src_apic, icr->vec, icr->del_mode) == -1) {
749                     PrintError("Could not deliver IPI\n");
750                     return -1;
751                 }
752             } else {
753                 // logical delivery
754                 PrintError("icc_bus: use of logical delivery in self is not yet supported.\n");
755                 return -1;
756             }
757             break;
758             
759         case 2: 
760         case 3: { // all and all-but-me
761             // assuming that logical verus physical doesn't matter
762             // although it is odd that both are used
763             int i;
764
765             for (i = 0; i < apic_dev->num_apics; i++) { 
766                 dest_apic = &(apic_dev->apics[i]);
767
768                 if ((dest_apic != src_apic) || (icr->dst_shorthand == 2)) { 
769                     if (deliver_ipi(core, src_apic, dest_apic, icr->vec, icr->del_mode) == -1) {
770                         PrintError("Error: Could not deliver IPI\n");
771                         return -1;
772                     }
773                 }
774             }   
775
776             break;
777         }
778         default:
779             PrintError("Error routing IPI, invalid Mode (%d)\n", icr->dst_shorthand);
780             return -1;
781     }
782     
783
784     return 0;
785 }
786
787
788
789 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
790     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
791     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]);
792     addr_t reg_addr  = guest_addr - apic->base_addr;
793     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
794     uint32_t val = 0;
795
796
797     PrintDebug("apic %u: core %u: at %p: Read apic address space (%p)\n",
798                apic->lapic_id.val, core->cpu_id, apic, (void *)guest_addr);
799
800     if (msr->apic_enable == 0) {
801         PrintError("apic %u: core %u: Read from APIC address space with disabled APIC, apic msr=0x%llx\n",
802                    apic->lapic_id.val, core->cpu_id, apic->base_addr_msr.value);
803
804         return -1;
805     }
806
807
808     /* Because "May not be supported" doesn't matter to Linux developers... */
809     /*   if (length != 4) { */
810     /*     PrintError("Invalid apic read length (%d)\n", length); */
811     /*     return -1; */
812     /*   } */
813
814     switch (reg_addr & ~0x3) {
815         case EOI_OFFSET:
816             // Well, only an idiot would read from a architectural write only register
817             // Oh, Hello Linux.
818             //    PrintError("Attempting to read from write only register\n");
819             //    return -1;
820             break;
821
822             // data registers
823         case APIC_ID_OFFSET:
824             val = apic->lapic_id.val;
825             break;
826         case APIC_VERSION_OFFSET:
827             val = apic->apic_ver.val;
828             break;
829         case TPR_OFFSET:
830             val = apic->task_prio.val;
831             break;
832         case APR_OFFSET:
833             val = apic->arb_prio.val;
834             break;
835         case PPR_OFFSET:
836             val = apic->proc_prio.val;
837             break;
838         case REMOTE_READ_OFFSET:
839             val = apic->rem_rd_data;
840             break;
841         case LDR_OFFSET:
842             val = apic->log_dst.val;
843             break;
844         case DFR_OFFSET:
845             val = apic->dst_fmt.val;
846             break;
847         case SPURIOUS_INT_VEC_OFFSET:
848             val = apic->spurious_int.val;
849             break;
850         case ESR_OFFSET:
851             val = apic->err_status.val;
852             break;
853         case TMR_LOC_VEC_TBL_OFFSET:
854             val = apic->tmr_vec_tbl.val;
855             break;
856         case LINT0_VEC_TBL_OFFSET:
857             val = apic->lint0_vec_tbl.val;
858             break;
859         case LINT1_VEC_TBL_OFFSET:
860             val = apic->lint1_vec_tbl.val;
861             break;
862         case ERR_VEC_TBL_OFFSET:
863             val = apic->err_vec_tbl.val;
864             break;
865         case TMR_INIT_CNT_OFFSET:
866             val = apic->tmr_init_cnt;
867             break;
868         case TMR_DIV_CFG_OFFSET:
869             val = apic->tmr_div_cfg.val;
870             break;
871
872         case IER_OFFSET0:
873             val = *(uint32_t *)(apic->int_en_reg);
874             break;
875         case IER_OFFSET1:
876             val = *(uint32_t *)(apic->int_en_reg + 4);
877             break;
878         case IER_OFFSET2:
879             val = *(uint32_t *)(apic->int_en_reg + 8);
880             break;
881         case IER_OFFSET3:
882             val = *(uint32_t *)(apic->int_en_reg + 12);
883             break;
884         case IER_OFFSET4:
885             val = *(uint32_t *)(apic->int_en_reg + 16);
886             break;
887         case IER_OFFSET5:
888             val = *(uint32_t *)(apic->int_en_reg + 20);
889             break;
890         case IER_OFFSET6:
891             val = *(uint32_t *)(apic->int_en_reg + 24);
892             break;
893         case IER_OFFSET7:
894             val = *(uint32_t *)(apic->int_en_reg + 28);
895             break;
896
897         case ISR_OFFSET0:
898             val = *(uint32_t *)(apic->int_svc_reg);
899             break;
900         case ISR_OFFSET1:
901             val = *(uint32_t *)(apic->int_svc_reg + 4);
902             break;
903         case ISR_OFFSET2:
904             val = *(uint32_t *)(apic->int_svc_reg + 8);
905             break;
906         case ISR_OFFSET3:
907             val = *(uint32_t *)(apic->int_svc_reg + 12);
908             break;
909         case ISR_OFFSET4:
910             val = *(uint32_t *)(apic->int_svc_reg + 16);
911             break;
912         case ISR_OFFSET5:
913             val = *(uint32_t *)(apic->int_svc_reg + 20);
914             break;
915         case ISR_OFFSET6:
916             val = *(uint32_t *)(apic->int_svc_reg + 24);
917             break;
918         case ISR_OFFSET7:
919             val = *(uint32_t *)(apic->int_svc_reg + 28);
920             break;
921    
922         case TRIG_OFFSET0:
923             val = *(uint32_t *)(apic->trig_mode_reg);
924             break;
925         case TRIG_OFFSET1:
926             val = *(uint32_t *)(apic->trig_mode_reg + 4);
927             break;
928         case TRIG_OFFSET2:
929             val = *(uint32_t *)(apic->trig_mode_reg + 8);
930             break;
931         case TRIG_OFFSET3:
932             val = *(uint32_t *)(apic->trig_mode_reg + 12);
933             break;
934         case TRIG_OFFSET4:
935             val = *(uint32_t *)(apic->trig_mode_reg + 16);
936             break;
937         case TRIG_OFFSET5:
938             val = *(uint32_t *)(apic->trig_mode_reg + 20);
939             break;
940         case TRIG_OFFSET6:
941             val = *(uint32_t *)(apic->trig_mode_reg + 24);
942             break;
943         case TRIG_OFFSET7:
944             val = *(uint32_t *)(apic->trig_mode_reg + 28);
945             break;
946
947         case IRR_OFFSET0:
948             val = *(uint32_t *)(apic->int_req_reg);
949             break;
950         case IRR_OFFSET1:
951             val = *(uint32_t *)(apic->int_req_reg + 4);
952             break;
953         case IRR_OFFSET2:
954             val = *(uint32_t *)(apic->int_req_reg + 8);
955             break;
956         case IRR_OFFSET3:
957             val = *(uint32_t *)(apic->int_req_reg + 12);
958             break;
959         case IRR_OFFSET4:
960             val = *(uint32_t *)(apic->int_req_reg + 16);
961             break;
962         case IRR_OFFSET5:
963             val = *(uint32_t *)(apic->int_req_reg + 20);
964             break;
965         case IRR_OFFSET6:
966             val = *(uint32_t *)(apic->int_req_reg + 24);
967             break;
968         case IRR_OFFSET7:
969             val = *(uint32_t *)(apic->int_req_reg + 28);
970             break;
971         case TMR_CUR_CNT_OFFSET:
972             val = apic->tmr_cur_cnt;
973             break;
974
975             // We are not going to implement these....
976         case THERM_LOC_VEC_TBL_OFFSET:
977             val = apic->therm_loc_vec_tbl.val;
978             break;
979         case PERF_CTR_LOC_VEC_TBL_OFFSET:
980             val = apic->perf_ctr_loc_vec_tbl.val;
981             break;
982
983  
984
985             // handled registers
986         case INT_CMD_LO_OFFSET:    
987             val = apic->int_cmd.lo;
988             break;
989         case INT_CMD_HI_OFFSET:
990             val = apic->int_cmd.hi;
991             break;
992
993             // handle current timer count
994
995             // Unhandled Registers
996         case EXT_INT_LOC_VEC_TBL_OFFSET0:
997             val = apic->ext_intr_vec_tbl[0].val;
998             break;
999         case EXT_INT_LOC_VEC_TBL_OFFSET1:
1000             val = apic->ext_intr_vec_tbl[1].val;
1001             break;
1002         case EXT_INT_LOC_VEC_TBL_OFFSET2:
1003             val = apic->ext_intr_vec_tbl[2].val;
1004             break;
1005         case EXT_INT_LOC_VEC_TBL_OFFSET3:
1006             val = apic->ext_intr_vec_tbl[3].val;
1007             break;
1008     
1009
1010         case EXT_APIC_FEATURE_OFFSET:
1011         case EXT_APIC_CMD_OFFSET:
1012         case SEOI_OFFSET:
1013
1014         default:
1015             PrintError("apic %u: core %u: Read from Unhandled APIC Register: %x (getting zero)\n", 
1016                        apic->lapic_id.val, core->cpu_id, (uint32_t)reg_addr);
1017             return -1;
1018     }
1019
1020
1021     if (length == 1) {
1022         uint_t byte_addr = reg_addr & 0x3;
1023         uint8_t * val_ptr = (uint8_t *)dst;
1024     
1025         *val_ptr = *(((uint8_t *)&val) + byte_addr);
1026
1027     } else if ((length == 2) && 
1028                ((reg_addr & 0x3) == 0x3)) {
1029         uint_t byte_addr = reg_addr & 0x3;
1030         uint16_t * val_ptr = (uint16_t *)dst;
1031         *val_ptr = *(((uint16_t *)&val) + byte_addr);
1032
1033     } else if (length == 4) {
1034         uint32_t * val_ptr = (uint32_t *)dst;
1035         *val_ptr = val;
1036
1037     } else {
1038         PrintError("apic %u: core %u: Invalid apic read length (%d)\n", 
1039                    apic->lapic_id.val, core->cpu_id, length);
1040         return -1;
1041     }
1042
1043     PrintDebug("apic %u: core %u: Read finished (val=%x)\n", 
1044                apic->lapic_id.val, core->cpu_id, *(uint32_t *)dst);
1045
1046     return length;
1047 }
1048
1049
1050 /**
1051  *
1052  */
1053 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data) {
1054     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1055     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
1056     addr_t reg_addr  = guest_addr - apic->base_addr;
1057     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
1058     uint32_t op_val = *(uint32_t *)src;
1059
1060     PrintDebug("apic %u: core %u: at %p and priv_data is at %p\n",
1061                apic->lapic_id.val, core->cpu_id, apic, priv_data);
1062
1063     PrintDebug("Write to address space (%p) (val=%x)\n", 
1064                (void *)guest_addr, *(uint32_t *)src);
1065
1066     if (msr->apic_enable == 0) {
1067         PrintError("apic %u: core %u: Write to APIC address space with disabled APIC, apic msr=0x%llx\n",
1068                    apic->lapic_id.val, core->cpu_id, apic->base_addr_msr.value);
1069         return -1;
1070     }
1071
1072
1073     if (length != 4) {
1074         PrintError("apic %u: core %u: Invalid apic write length (%d)\n", 
1075                    apic->lapic_id.val, length, core->cpu_id);
1076         return -1;
1077     }
1078
1079     switch (reg_addr) {
1080         case REMOTE_READ_OFFSET:
1081         case APIC_VERSION_OFFSET:
1082         case APR_OFFSET:
1083         case IRR_OFFSET0:
1084         case IRR_OFFSET1:
1085         case IRR_OFFSET2:
1086         case IRR_OFFSET3:
1087         case IRR_OFFSET4:
1088         case IRR_OFFSET5:
1089         case IRR_OFFSET6:
1090         case IRR_OFFSET7:
1091         case ISR_OFFSET0:
1092         case ISR_OFFSET1:
1093         case ISR_OFFSET2:
1094         case ISR_OFFSET3:
1095         case ISR_OFFSET4:
1096         case ISR_OFFSET5:
1097         case ISR_OFFSET6:
1098         case ISR_OFFSET7:
1099         case TRIG_OFFSET0:
1100         case TRIG_OFFSET1:
1101         case TRIG_OFFSET2:
1102         case TRIG_OFFSET3:
1103         case TRIG_OFFSET4:
1104         case TRIG_OFFSET5:
1105         case TRIG_OFFSET6:
1106         case TRIG_OFFSET7:
1107         case PPR_OFFSET:
1108         case EXT_APIC_FEATURE_OFFSET:
1109
1110             PrintError("apic %u: core %u: Attempting to write to read only register %p (error)\n", 
1111                        apic->lapic_id.val, core->cpu_id, (void *)reg_addr);
1112             //  return -1;
1113
1114             break;
1115
1116             // Data registers
1117         case APIC_ID_OFFSET:
1118             PrintDebug("apic %u: core %u: my id is being changed to %u\n", 
1119                        apic->lapic_id.val, core->cpu_id, op_val);
1120
1121             apic->lapic_id.val = op_val;
1122             break;
1123         case TPR_OFFSET:
1124             apic->task_prio.val = op_val;
1125             break;
1126         case LDR_OFFSET:
1127             PrintDebug("apic %u: core %u: setting log_dst.val to 0x%x\n",
1128                        apic->lapic_id.val, core->cpu_id, op_val);
1129             apic->log_dst.val = op_val;
1130             break;
1131         case DFR_OFFSET:
1132             apic->dst_fmt.val = op_val;
1133             break;
1134         case SPURIOUS_INT_VEC_OFFSET:
1135             apic->spurious_int.val = op_val;
1136             break;
1137         case ESR_OFFSET:
1138             apic->err_status.val = op_val;
1139             break;
1140         case TMR_LOC_VEC_TBL_OFFSET:
1141             apic->tmr_vec_tbl.val = op_val;
1142             break;
1143         case THERM_LOC_VEC_TBL_OFFSET:
1144             apic->therm_loc_vec_tbl.val = op_val;
1145             break;
1146         case PERF_CTR_LOC_VEC_TBL_OFFSET:
1147             apic->perf_ctr_loc_vec_tbl.val = op_val;
1148             break;
1149         case LINT0_VEC_TBL_OFFSET:
1150             apic->lint0_vec_tbl.val = op_val;
1151             break;
1152         case LINT1_VEC_TBL_OFFSET:
1153             apic->lint1_vec_tbl.val = op_val;
1154             break;
1155         case ERR_VEC_TBL_OFFSET:
1156             apic->err_vec_tbl.val = op_val;
1157             break;
1158         case TMR_INIT_CNT_OFFSET:
1159             apic->tmr_init_cnt = op_val;
1160             apic->tmr_cur_cnt = op_val;
1161             break;
1162         case TMR_CUR_CNT_OFFSET:
1163             apic->tmr_cur_cnt = op_val;
1164             break;
1165         case TMR_DIV_CFG_OFFSET:
1166             apic->tmr_div_cfg.val = op_val;
1167             break;
1168
1169
1170             // Enable mask (256 bits)
1171         case IER_OFFSET0:
1172             *(uint32_t *)(apic->int_en_reg) = op_val;
1173             break;
1174         case IER_OFFSET1:
1175             *(uint32_t *)(apic->int_en_reg + 4) = op_val;
1176             break;
1177         case IER_OFFSET2:
1178             *(uint32_t *)(apic->int_en_reg + 8) = op_val;
1179             break;
1180         case IER_OFFSET3:
1181             *(uint32_t *)(apic->int_en_reg + 12) = op_val;
1182             break;
1183         case IER_OFFSET4:
1184             *(uint32_t *)(apic->int_en_reg + 16) = op_val;
1185             break;
1186         case IER_OFFSET5:
1187             *(uint32_t *)(apic->int_en_reg + 20) = op_val;
1188             break;
1189         case IER_OFFSET6:
1190             *(uint32_t *)(apic->int_en_reg + 24) = op_val;
1191             break;
1192         case IER_OFFSET7:
1193             *(uint32_t *)(apic->int_en_reg + 28) = op_val;
1194             break;
1195
1196         case EXT_INT_LOC_VEC_TBL_OFFSET0:
1197             apic->ext_intr_vec_tbl[0].val = op_val;
1198             break;
1199         case EXT_INT_LOC_VEC_TBL_OFFSET1:
1200             apic->ext_intr_vec_tbl[1].val = op_val;
1201             break;
1202         case EXT_INT_LOC_VEC_TBL_OFFSET2:
1203             apic->ext_intr_vec_tbl[2].val = op_val;
1204             break;
1205         case EXT_INT_LOC_VEC_TBL_OFFSET3:
1206             apic->ext_intr_vec_tbl[3].val = op_val;
1207             break;
1208
1209
1210             // Action Registers
1211         case EOI_OFFSET:
1212             // do eoi
1213             apic_do_eoi(apic);
1214             break;
1215
1216         case INT_CMD_LO_OFFSET:
1217             apic->int_cmd.lo = op_val;
1218
1219             PrintDebug("apic %u: core %u: sending cmd 0x%llx to apic %u\n", 
1220                        apic->lapic_id.val, core->cpu_id,
1221                        apic->int_cmd.val, apic->int_cmd.dst);
1222
1223             if (route_ipi(core, apic_dev, apic, apic->int_cmd.val) == -1) { 
1224                 PrintError("IPI Routing failure\n");
1225                 return -1;
1226             }
1227
1228             break;
1229
1230         case INT_CMD_HI_OFFSET:
1231             apic->int_cmd.hi = op_val;
1232             break;
1233
1234
1235         // Unhandled Registers
1236         case EXT_APIC_CMD_OFFSET:
1237         case SEOI_OFFSET:
1238         default:
1239             PrintError("apic %u: core %u: Write to Unhandled APIC Register: %x (ignored)\n", 
1240                        apic->lapic_id.val, core->cpu_id, (uint32_t)reg_addr);
1241
1242             return -1;
1243     }
1244
1245     PrintDebug("apic %u: core %u: Write finished\n", apic->lapic_id.val, core->cpu_id);
1246
1247     return length;
1248 }
1249
1250
1251
1252 /* Interrupt Controller Functions */
1253
1254 // returns 1 if an interrupt is pending, 0 otherwise
1255 static int apic_intr_pending(struct guest_info * core, void * private_data) {
1256     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
1257     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
1258     int req_irq = get_highest_irr(apic);
1259     int svc_irq = get_highest_isr(apic);
1260
1261     //    PrintDebug("apic %u: core %u: req_irq=%d, svc_irq=%d\n",apic->lapic_id.val,info->cpu_id,req_irq,svc_irq);
1262
1263     if ((req_irq >= 0) && 
1264         (req_irq > svc_irq)) {
1265         return 1;
1266     }
1267
1268     return 0;
1269 }
1270
1271 static int apic_get_intr_number(struct guest_info * core, void * private_data) {
1272     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
1273     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
1274     int req_irq = get_highest_irr(apic);
1275     int svc_irq = get_highest_isr(apic);
1276
1277     if (svc_irq == -1) {
1278         return req_irq;
1279     } else if (svc_irq < req_irq) {
1280         return req_irq;
1281     }
1282
1283     return -1;
1284 }
1285
1286
1287 int v3_apic_raise_intr(struct v3_vm_info * vm, struct vm_device * dev, 
1288                        uint32_t irq, uint32_t dst) {
1289     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(dev->private_data);
1290     struct apic_state * apic = &(apic_dev->apics[dst]); 
1291
1292     PrintDebug("apic %u core ?: raising interrupt IRQ %u (dst = %u).\n", apic->lapic_id.val, irq, dst); 
1293
1294     activate_apic_irq(apic, irq);
1295
1296     if (V3_Get_CPU() != dst) {
1297         v3_interrupt_cpu(vm, dst, 0);
1298     }
1299
1300     return 0;
1301 }
1302
1303
1304
1305 static int apic_begin_irq(struct guest_info * core, void * private_data, int irq) {
1306     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
1307     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
1308     int major_offset = (irq & ~0x00000007) >> 3;
1309     int minor_offset = irq & 0x00000007;
1310     uint8_t * req_location = apic->int_req_reg + major_offset;
1311     uint8_t * svc_location = apic->int_svc_reg + major_offset;
1312     uint8_t flag = 0x01 << minor_offset;
1313
1314     if (*req_location & flag) {
1315         // we will only pay attention to a begin irq if we
1316         // know that we initiated it!
1317         *svc_location |= flag;
1318         *req_location &= ~flag;
1319     } else {
1320         // do nothing... 
1321         //PrintDebug("apic %u: core %u: begin irq for %d ignored since I don't own it\n",
1322         //         apic->lapic_id.val, core->cpu_id, irq);
1323     }
1324
1325     return 0;
1326 }
1327
1328
1329
1330
1331 /* Timer Functions */
1332 static void apic_update_time(struct guest_info * core, 
1333                              uint64_t cpu_cycles, uint64_t cpu_freq, 
1334                              void * priv_data) {
1335     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1336     struct apic_state * apic = &(apic_dev->apics[core->cpu_id]); 
1337
1338     // The 32 bit GCC runtime is a pile of shit
1339 #ifdef __V3_64BIT__
1340     uint64_t tmr_ticks = 0;
1341 #else 
1342     uint32_t tmr_ticks = 0;
1343 #endif
1344
1345     uint8_t tmr_div = *(uint8_t *)&(apic->tmr_div_cfg.val);
1346     uint_t shift_num = 0;
1347
1348
1349     // Check whether this is true:
1350     //   -> If the Init count is zero then the timer is disabled
1351     //      and doesn't just blitz interrupts to the CPU
1352     if ((apic->tmr_init_cnt == 0) || 
1353         ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
1354           (apic->tmr_cur_cnt == 0))) {
1355         //PrintDebug("apic %u: core %u: APIC timer not yet initialized\n",apic->lapic_id.val,info->cpu_id);
1356         return;
1357     }
1358
1359
1360     switch (tmr_div) {
1361         case APIC_TMR_DIV1:
1362             shift_num = 0;
1363             break;
1364         case APIC_TMR_DIV2:
1365             shift_num = 1;
1366             break;
1367         case APIC_TMR_DIV4:
1368             shift_num = 2;
1369             break;
1370         case APIC_TMR_DIV8:
1371             shift_num = 3;
1372             break;
1373         case APIC_TMR_DIV16:
1374             shift_num = 4;
1375             break;
1376         case APIC_TMR_DIV32:
1377             shift_num = 5;
1378             break;
1379         case APIC_TMR_DIV64:
1380             shift_num = 6;
1381             break;
1382         case APIC_TMR_DIV128:
1383             shift_num = 7;
1384             break;
1385         default:
1386             PrintError("apic %u: core %u: Invalid Timer Divider configuration\n",
1387                        apic->lapic_id.val, core->cpu_id);
1388             return;
1389     }
1390
1391     tmr_ticks = cpu_cycles >> shift_num;
1392     //    PrintDebug("Timer Ticks: %p\n", (void *)tmr_ticks);
1393
1394     if (tmr_ticks < apic->tmr_cur_cnt) {
1395         apic->tmr_cur_cnt -= tmr_ticks;
1396     } else {
1397         tmr_ticks -= apic->tmr_cur_cnt;
1398         apic->tmr_cur_cnt = 0;
1399
1400         // raise irq
1401         PrintDebug("apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n",
1402                    apic->lapic_id.val, core->cpu_id,
1403                    apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
1404
1405         if (apic_intr_pending(core, priv_data)) {
1406             PrintDebug("apic %u: core %u: Overriding pending IRQ %d\n", 
1407                        apic->lapic_id.val, core->cpu_id, 
1408                        apic_get_intr_number(core, priv_data));
1409         }
1410
1411         if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
1412             PrintError("apic %u: core %u: Could not raise Timer interrupt\n",
1413                        apic->lapic_id.val, core->cpu_id);
1414         }
1415     
1416         if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
1417             tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
1418             apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
1419         }
1420     }
1421
1422
1423 }
1424
1425
1426 static struct intr_ctrl_ops intr_ops = {
1427     .intr_pending = apic_intr_pending,
1428     .get_intr_number = apic_get_intr_number,
1429     .begin_irq = apic_begin_irq,
1430 };
1431
1432
1433 static struct vm_timer_ops timer_ops = {
1434     .update_timer = apic_update_time,
1435 };
1436
1437
1438
1439
1440 static int apic_free(struct vm_device * dev) {
1441
1442     /* TODO: This should crosscall to force an unhook on each CPU */
1443
1444     //   struct apic_state * apic = (struct apic_state *)dev->private_data;
1445
1446     v3_unhook_msr(dev->vm, BASE_ADDR_MSR);
1447
1448     return 0;
1449 }
1450
1451
1452 static struct v3_device_ops dev_ops = {
1453     .free = apic_free,
1454     .reset = NULL,
1455     .start = NULL,
1456     .stop = NULL,
1457 };
1458
1459
1460
1461
1462
1463 static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1464     char * dev_id = v3_cfg_val(cfg, "ID");
1465     struct apic_dev_state * apic_dev = NULL;
1466     int i = 0;
1467
1468     PrintDebug("apic: creating an APIC for each core\n");
1469
1470     apic_dev = (struct apic_dev_state *)V3_Malloc(sizeof(struct apic_dev_state) + 
1471                                                   sizeof(struct apic_state) * vm->num_cores);
1472
1473     apic_dev->num_apics = vm->num_cores;
1474
1475     struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, apic_dev);
1476
1477     if (v3_attach_device(vm, dev) == -1) {
1478         PrintError("apic: Could not attach device %s\n", dev_id);
1479         return -1;
1480     }
1481
1482     
1483     for (i = 0; i < vm->num_cores; i++) {
1484         struct apic_state * apic = &(apic_dev->apics[i]);
1485         struct guest_info * core = &(vm->cores[i]);
1486
1487         apic->core = core;
1488
1489         init_apic_state(apic, i);
1490
1491         v3_register_intr_controller(core, &intr_ops, apic_dev);
1492
1493         v3_add_timer(core, &timer_ops, apic_dev);
1494
1495         v3_hook_full_mem(vm, core->cpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, apic_dev);
1496
1497         PrintDebug("apic %u: (setup device): done, my id is %u\n", i, apic->lapic_id.val);
1498     }
1499
1500 #ifdef CONFIG_DEBUG_APIC
1501     for (i = 0; i < vm->num_cores; i++) {
1502         struct apic_state * apic = &(apic_dev->apics[i]);
1503         PrintDebug("apic: sanity check: apic %u (at %p) has id %u and msr value %llx\n",
1504                    i, apic, apic->lapic_id.val, apic->base_addr_msr.value);
1505     }
1506 #endif
1507
1508
1509     PrintDebug("apic: priv_data is at %p\n", apic_dev);
1510
1511     v3_hook_msr(vm, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, apic_dev);
1512
1513     return 0;
1514 }
1515
1516
1517
1518 device_register("LAPIC", apic_init)