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.


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