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.


Philip's changes along with some minor changes from Kevin.
[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
28 #ifndef CONFIG_DEBUG_APIC
29 #undef PrintDebug
30 #define PrintDebug(fmt, args...)
31 #endif
32
33
34 typedef enum { APIC_TMR_INT, APIC_THERM_INT, APIC_PERF_INT, 
35                APIC_LINT0_INT, APIC_LINT1_INT, APIC_ERR_INT } apic_irq_type_t;
36
37 #define APIC_FIXED_DELIVERY  0x0
38 #define APIC_SMI_DELIVERY    0x2
39 #define APIC_NMI_DELIVERY    0x4
40 #define APIC_INIT_DELIVERY   0x5
41 #define APIC_EXTINT_DELIVERY 0x7
42
43
44 #define BASE_ADDR_MSR 0x0000001B
45 #define DEFAULT_BASE_ADDR 0xfee00000
46
47 #define APIC_ID_OFFSET                    0x020
48 #define APIC_VERSION_OFFSET               0x030
49 #define TPR_OFFSET                        0x080
50 #define APR_OFFSET                        0x090
51 #define PPR_OFFSET                        0x0a0
52 #define EOI_OFFSET                        0x0b0
53 #define REMOTE_READ_OFFSET                0x0c0
54 #define LDR_OFFSET                        0x0d0
55 #define DFR_OFFSET                        0x0e0
56 #define SPURIOUS_INT_VEC_OFFSET           0x0f0
57
58 #define ISR_OFFSET0                       0x100   // 0x100 - 0x170
59 #define ISR_OFFSET1                       0x110   // 0x100 - 0x170
60 #define ISR_OFFSET2                       0x120   // 0x100 - 0x170
61 #define ISR_OFFSET3                       0x130   // 0x100 - 0x170
62 #define ISR_OFFSET4                       0x140   // 0x100 - 0x170
63 #define ISR_OFFSET5                       0x150   // 0x100 - 0x170
64 #define ISR_OFFSET6                       0x160   // 0x100 - 0x170
65 #define ISR_OFFSET7                       0x170   // 0x100 - 0x170
66
67 #define TRIG_OFFSET0                      0x180   // 0x180 - 0x1f0
68 #define TRIG_OFFSET1                      0x190   // 0x180 - 0x1f0
69 #define TRIG_OFFSET2                      0x1a0   // 0x180 - 0x1f0
70 #define TRIG_OFFSET3                      0x1b0   // 0x180 - 0x1f0
71 #define TRIG_OFFSET4                      0x1c0   // 0x180 - 0x1f0
72 #define TRIG_OFFSET5                      0x1d0   // 0x180 - 0x1f0
73 #define TRIG_OFFSET6                      0x1e0   // 0x180 - 0x1f0
74 #define TRIG_OFFSET7                      0x1f0   // 0x180 - 0x1f0
75
76
77 #define IRR_OFFSET0                       0x200   // 0x200 - 0x270
78 #define IRR_OFFSET1                       0x210   // 0x200 - 0x270
79 #define IRR_OFFSET2                       0x220   // 0x200 - 0x270
80 #define IRR_OFFSET3                       0x230   // 0x200 - 0x270
81 #define IRR_OFFSET4                       0x240   // 0x200 - 0x270
82 #define IRR_OFFSET5                       0x250   // 0x200 - 0x270
83 #define IRR_OFFSET6                       0x260   // 0x200 - 0x270
84 #define IRR_OFFSET7                       0x270   // 0x200 - 0x270
85
86
87 #define ESR_OFFSET                        0x280
88 #define INT_CMD_LO_OFFSET                 0x300
89 #define INT_CMD_HI_OFFSET                 0x310
90 #define TMR_LOC_VEC_TBL_OFFSET            0x320
91 #define THERM_LOC_VEC_TBL_OFFSET          0x330
92 #define PERF_CTR_LOC_VEC_TBL_OFFSET       0x340
93 #define LINT0_VEC_TBL_OFFSET              0x350
94 #define LINT1_VEC_TBL_OFFSET              0x360
95 #define ERR_VEC_TBL_OFFSET                0x370
96 #define TMR_INIT_CNT_OFFSET               0x380
97 #define TMR_CUR_CNT_OFFSET                0x390
98 #define TMR_DIV_CFG_OFFSET                0x3e0
99 #define EXT_APIC_FEATURE_OFFSET           0x400
100 #define EXT_APIC_CMD_OFFSET               0x410
101 #define SEOI_OFFSET                       0x420
102
103 #define IER_OFFSET0                       0x480   // 0x480 - 0x4f0
104 #define IER_OFFSET1                       0x490   // 0x480 - 0x4f0
105 #define IER_OFFSET2                       0x4a0   // 0x480 - 0x4f0
106 #define IER_OFFSET3                       0x4b0   // 0x480 - 0x4f0
107 #define IER_OFFSET4                       0x4c0   // 0x480 - 0x4f0
108 #define IER_OFFSET5                       0x4d0   // 0x480 - 0x4f0
109 #define IER_OFFSET6                       0x4e0   // 0x480 - 0x4f0
110 #define IER_OFFSET7                       0x4f0   // 0x480 - 0x4f0
111
112 #define EXT_INT_LOC_VEC_TBL_OFFSET0       0x500   // 0x500 - 0x530
113 #define EXT_INT_LOC_VEC_TBL_OFFSET1       0x510   // 0x500 - 0x530
114 #define EXT_INT_LOC_VEC_TBL_OFFSET2       0x520   // 0x500 - 0x530
115 #define EXT_INT_LOC_VEC_TBL_OFFSET3       0x530   // 0x500 - 0x530
116
117
118
119 struct apic_msr {
120     union {
121         uint64_t val;
122         struct {
123             uchar_t rsvd;
124             uint_t bootstrap_cpu : 1;
125             uint_t rsvd2         : 2;
126             uint_t apic_enable   : 1;
127             ullong_t base_addr   : 40;
128             uint_t rsvd3         : 12;
129         } __attribute__((packed));
130     } __attribute__((packed));
131 } __attribute__((packed));
132
133
134
135
136 struct apic_state {
137     addr_t base_addr;
138
139     /* MSRs */
140     v3_msr_t base_addr_msr;
141
142
143     /* memory map registers */
144
145     struct lapic_id_reg lapic_id;
146     struct apic_ver_reg apic_ver;
147     struct ext_apic_ctrl_reg ext_apic_ctrl;
148     struct local_vec_tbl_reg local_vec_tbl;
149     struct tmr_vec_tbl_reg tmr_vec_tbl;
150     struct tmr_div_cfg_reg tmr_div_cfg;
151     struct lint_vec_tbl_reg lint0_vec_tbl;
152     struct lint_vec_tbl_reg lint1_vec_tbl;
153     struct perf_ctr_loc_vec_tbl_reg perf_ctr_loc_vec_tbl;
154     struct therm_loc_vec_tbl_reg therm_loc_vec_tbl;
155     struct err_vec_tbl_reg err_vec_tbl;
156     struct err_status_reg err_status;
157     struct spurious_int_reg spurious_int;
158     struct int_cmd_reg int_cmd;
159     struct log_dst_reg log_dst;
160     struct dst_fmt_reg dst_fmt;
161     struct arb_prio_reg arb_prio;
162     struct task_prio_reg task_prio;
163     struct proc_prio_reg proc_prio;
164     struct ext_apic_feature_reg ext_apic_feature;
165     struct spec_eoi_reg spec_eoi;
166   
167
168     uint32_t tmr_cur_cnt;
169     uint32_t tmr_init_cnt;
170
171
172     struct local_vec_tbl_reg ext_intr_vec_tbl[4];
173
174     uint32_t rem_rd_data;
175
176
177     uchar_t int_req_reg[32];
178     uchar_t int_svc_reg[32];
179     uchar_t int_en_reg[32];
180     uchar_t trig_mode_reg[32];
181   
182     uint32_t eoi;
183
184
185 };
186
187 static void apic_incoming_ipi(void *val);
188 static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data);
189 static int apic_write(addr_t guest_addr, void * src, uint_t length, void * priv_data);
190
191 static void init_apic_state(struct apic_state * apic) {
192     apic->base_addr = DEFAULT_BASE_ADDR;
193     apic->base_addr_msr.value = 0x0000000000000900LL;
194     apic->base_addr_msr.value |= ((uint64_t)DEFAULT_BASE_ADDR); 
195
196     PrintDebug("Sizeof Interrupt Request Register %d, should be 32\n", 
197                (uint_t)sizeof(apic->int_req_reg));
198
199     memset(apic->int_req_reg, 0, sizeof(apic->int_req_reg));
200     memset(apic->int_svc_reg, 0, sizeof(apic->int_svc_reg));
201     memset(apic->int_en_reg, 0xff, sizeof(apic->int_en_reg));
202     memset(apic->trig_mode_reg, 0, sizeof(apic->trig_mode_reg));
203
204     apic->eoi = 0x00000000;
205     apic->rem_rd_data = 0x00000000;
206     apic->tmr_init_cnt = 0x00000000;
207     apic->tmr_cur_cnt = 0x00000000;
208
209     // TODO:
210     // We need to figure out what the APIC ID is....
211     apic->lapic_id.val = 0x00000000;
212
213     // The P6 has 6 LVT entries, so we set the value to (6-1)...
214     apic->apic_ver.val = 0x80050010;
215
216     apic->task_prio.val = 0x00000000;
217     apic->arb_prio.val = 0x00000000;
218     apic->proc_prio.val = 0x00000000;
219     apic->log_dst.val = 0x00000000;
220     apic->dst_fmt.val = 0xffffffff;
221     apic->spurious_int.val = 0x000000ff;
222     apic->err_status.val = 0x00000000;
223     apic->int_cmd.val = 0x0000000000000000LL;
224     apic->tmr_vec_tbl.val = 0x00010000;
225     apic->therm_loc_vec_tbl.val = 0x00010000;
226     apic->perf_ctr_loc_vec_tbl.val = 0x00010000;
227     apic->lint0_vec_tbl.val = 0x00010000;
228     apic->lint1_vec_tbl.val = 0x00010000;
229     apic->err_vec_tbl.val = 0x00010000;
230     apic->tmr_div_cfg.val = 0x00000000;
231     //apic->ext_apic_feature.val = 0x00000007;
232     apic->ext_apic_feature.val = 0x00040007;
233     apic->ext_apic_ctrl.val = 0x00000000;
234     apic->spec_eoi.val = 0x00000000;
235 }
236
237
238
239
240 static int read_apic_msr(uint_t msr, v3_msr_t * dst, void * priv_data) {
241     struct vm_device * dev = (struct vm_device *)priv_data;
242     struct apic_state * apic = (struct apic_state *)dev->private_data;
243     dst->value = apic->base_addr;
244     return 0;
245 }
246
247
248 static int write_apic_msr(uint_t msr, v3_msr_t src, void * priv_data) {
249     struct vm_device * dev = (struct vm_device *)priv_data;
250     struct apic_state * apic = (struct apic_state *)dev->private_data;
251     struct v3_shadow_region * old_reg = v3_get_shadow_region(dev->vm, apic->base_addr);
252
253     if (old_reg == NULL) {
254         // uh oh...
255         PrintError("APIC Base address region does not exit...\n");
256         return -1;
257     }
258     
259     v3_delete_shadow_region(dev->vm, old_reg);
260
261     apic->base_addr = src.value;
262
263     if (v3_hook_full_mem(dev->vm, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, dev) == -1) {
264         PrintError("Could not hook new APIC Base address\n");
265         return -1;
266     }
267
268     return 0;
269 }
270
271
272 // irq_num is the bit offset into a 256 bit buffer...
273 static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
274     int major_offset = (irq_num & ~0x00000007) >> 3;
275     int minor_offset = irq_num & 0x00000007;
276     uchar_t * req_location = apic->int_req_reg + major_offset;
277     uchar_t * en_location = apic->int_en_reg + major_offset;
278     uchar_t flag = 0x1 << minor_offset;
279
280     if (irq_num <= 15) {
281         PrintError("Attempting to raise an invalid interrupt: %d\n", irq_num);
282         return -1;
283     }
284
285     PrintDebug("Raising APIC IRQ %d\n", irq_num);
286
287     if (*req_location & flag) {
288         //V3_Print("Interrupts coallescing\n");
289     }
290
291     if (*en_location & flag) {
292         *req_location |= flag;
293     } else {
294         PrintDebug("Interrupt  not enabled... %.2x\n", *en_location);
295         return 0;
296     }
297
298     return 0;
299 }
300
301
302
303 static int get_highest_isr(struct apic_state * apic) {
304     int i = 0, j = 0;
305
306     // We iterate backwards to find the highest priority
307     for (i = 31; i >= 0; i--) {
308         uchar_t  * svc_major = apic->int_svc_reg + i;
309     
310         if ((*svc_major) & 0xff) {
311             for (j = 7; j >= 0; j--) {
312                 uchar_t flag = 0x1 << j;
313                 if ((*svc_major) & flag) {
314                     return ((i * 8) + j);
315                 }
316             }
317         }
318     }
319
320     return -1;
321 }
322  
323
324
325 static int get_highest_irr(struct apic_state * apic) {
326     int i = 0, j = 0;
327
328     // We iterate backwards to find the highest priority
329     for (i = 31; i >= 0; i--) {
330         uchar_t  * req_major = apic->int_req_reg + i;
331     
332         if ((*req_major) & 0xff) {
333             for (j = 7; j >= 0; j--) {
334                 uchar_t flag = 0x1 << j;
335                 if ((*req_major) & flag) {
336                     return ((i * 8) + j);
337                 }
338             }
339         }
340     }
341
342     return -1;
343 }
344  
345
346
347
348 static int apic_do_eoi(struct apic_state * apic) {
349     int isr_irq = get_highest_isr(apic);
350
351     if (isr_irq != -1) {
352         int major_offset = (isr_irq & ~0x00000007) >> 3;
353         int minor_offset = isr_irq & 0x00000007;
354         uchar_t flag = 0x1 << minor_offset;
355         uchar_t * svc_location = apic->int_svc_reg + major_offset;
356         
357         PrintDebug("Received APIC EOI for IRQ %d\n", isr_irq);
358         
359         *svc_location &= ~flag;
360
361 #ifdef CONFIG_CRAY_XT
362         
363         if ((isr_irq == 238) || 
364             (isr_irq == 239)) {
365             PrintError("Acking IRQ %d\n", isr_irq);
366         }
367         
368         if (isr_irq == 238) {
369             V3_ACK_IRQ(238);
370         }
371 #endif
372     } else {
373         //PrintError("Spurious EOI...\n");
374     }
375         
376     return 0;
377 }
378  
379
380 static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_type) {
381     uint32_t vec_num = 0;
382     uint32_t del_mode = 0;
383     int masked = 0;
384
385
386     switch (int_type) {
387         case APIC_TMR_INT:
388             vec_num = apic->tmr_vec_tbl.vec;
389             del_mode = APIC_FIXED_DELIVERY;
390             masked = apic->tmr_vec_tbl.mask;
391             break;
392         case APIC_THERM_INT:
393             vec_num = apic->therm_loc_vec_tbl.vec;
394             del_mode = apic->therm_loc_vec_tbl.msg_type;
395             masked = apic->therm_loc_vec_tbl.mask;
396             break;
397         case APIC_PERF_INT:
398             vec_num = apic->perf_ctr_loc_vec_tbl.vec;
399             del_mode = apic->perf_ctr_loc_vec_tbl.msg_type;
400             masked = apic->perf_ctr_loc_vec_tbl.mask;
401             break;
402         case APIC_LINT0_INT:
403             vec_num = apic->lint0_vec_tbl.vec;
404             del_mode = apic->lint0_vec_tbl.msg_type;
405             masked = apic->lint0_vec_tbl.mask;
406             break;
407         case APIC_LINT1_INT:
408             vec_num = apic->lint1_vec_tbl.vec;
409             del_mode = apic->lint1_vec_tbl.msg_type;
410             masked = apic->lint1_vec_tbl.mask;
411             break;
412         case APIC_ERR_INT:
413             vec_num = apic->err_vec_tbl.vec;
414             del_mode = APIC_FIXED_DELIVERY;
415             masked = apic->err_vec_tbl.mask;
416             break;
417         default:
418             PrintError("Invalid APIC interrupt type\n");
419             return -1;
420     }
421
422     // interrupt is masked, don't send
423     if (masked == 1) {
424         PrintDebug("Inerrupt is masked\n");
425         return 0;
426     }
427
428     if (del_mode == APIC_FIXED_DELIVERY) {
429         //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
430         return activate_apic_irq(apic, vec_num);
431     } else {
432         PrintError("Unhandled Delivery Mode\n");
433         return -1;
434     }
435 }
436
437
438 static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
439     struct vm_device * dev = (struct vm_device *)priv_data;
440     struct apic_state * apic = (struct apic_state *)dev->private_data;
441     addr_t reg_addr  = guest_addr - apic->base_addr;
442     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
443     uint32_t val = 0;
444
445
446     PrintDebug("Read apic address space (%p)\n", 
447                (void *)guest_addr);
448
449     if (msr->apic_enable == 0) {
450         PrintError("Write to APIC address space with disabled APIC\n");
451         return -1;
452     }
453
454
455     /* Because "May not be supported" doesn't matter to Linux developers... */
456     /*   if (length != 4) { */
457     /*     PrintError("Invalid apic read length (%d)\n", length); */
458     /*     return -1; */
459     /*   } */
460
461     switch (reg_addr & ~0x3) {
462         case EOI_OFFSET:
463             // Well, only an idiot would read from a architectural write only register
464             // Oh, Hello Linux.
465             //    PrintError("Attempting to read from write only register\n");
466             //    return -1;
467             break;
468
469             // data registers
470         case APIC_ID_OFFSET:
471             val = apic->lapic_id.val;
472             break;
473         case APIC_VERSION_OFFSET:
474             val = apic->apic_ver.val;
475             break;
476         case TPR_OFFSET:
477             val = apic->task_prio.val;
478             break;
479         case APR_OFFSET:
480             val = apic->arb_prio.val;
481             break;
482         case PPR_OFFSET:
483             val = apic->proc_prio.val;
484             break;
485         case REMOTE_READ_OFFSET:
486             val = apic->rem_rd_data;
487             break;
488         case LDR_OFFSET:
489             val = apic->log_dst.val;
490             break;
491         case DFR_OFFSET:
492             val = apic->dst_fmt.val;
493             break;
494         case SPURIOUS_INT_VEC_OFFSET:
495             val = apic->spurious_int.val;
496             break;
497         case ESR_OFFSET:
498             val = apic->err_status.val;
499             break;
500         case TMR_LOC_VEC_TBL_OFFSET:
501             val = apic->tmr_vec_tbl.val;
502             break;
503         case LINT0_VEC_TBL_OFFSET:
504             val = apic->lint0_vec_tbl.val;
505             break;
506         case LINT1_VEC_TBL_OFFSET:
507             val = apic->lint1_vec_tbl.val;
508             break;
509         case ERR_VEC_TBL_OFFSET:
510             val = apic->err_vec_tbl.val;
511             break;
512         case TMR_INIT_CNT_OFFSET:
513             val = apic->tmr_init_cnt;
514             break;
515         case TMR_DIV_CFG_OFFSET:
516             val = apic->tmr_div_cfg.val;
517             break;
518
519         case IER_OFFSET0:
520             val = *(uint32_t *)(apic->int_en_reg);
521             break;
522         case IER_OFFSET1:
523             val = *(uint32_t *)(apic->int_en_reg + 4);
524             break;
525         case IER_OFFSET2:
526             val = *(uint32_t *)(apic->int_en_reg + 8);
527             break;
528         case IER_OFFSET3:
529             val = *(uint32_t *)(apic->int_en_reg + 12);
530             break;
531         case IER_OFFSET4:
532             val = *(uint32_t *)(apic->int_en_reg + 16);
533             break;
534         case IER_OFFSET5:
535             val = *(uint32_t *)(apic->int_en_reg + 20);
536             break;
537         case IER_OFFSET6:
538             val = *(uint32_t *)(apic->int_en_reg + 24);
539             break;
540         case IER_OFFSET7:
541             val = *(uint32_t *)(apic->int_en_reg + 28);
542             break;
543
544         case ISR_OFFSET0:
545             val = *(uint32_t *)(apic->int_svc_reg);
546             break;
547         case ISR_OFFSET1:
548             val = *(uint32_t *)(apic->int_svc_reg + 4);
549             break;
550         case ISR_OFFSET2:
551             val = *(uint32_t *)(apic->int_svc_reg + 8);
552             break;
553         case ISR_OFFSET3:
554             val = *(uint32_t *)(apic->int_svc_reg + 12);
555             break;
556         case ISR_OFFSET4:
557             val = *(uint32_t *)(apic->int_svc_reg + 16);
558             break;
559         case ISR_OFFSET5:
560             val = *(uint32_t *)(apic->int_svc_reg + 20);
561             break;
562         case ISR_OFFSET6:
563             val = *(uint32_t *)(apic->int_svc_reg + 24);
564             break;
565         case ISR_OFFSET7:
566             val = *(uint32_t *)(apic->int_svc_reg + 28);
567             break;
568    
569         case TRIG_OFFSET0:
570             val = *(uint32_t *)(apic->trig_mode_reg);
571             break;
572         case TRIG_OFFSET1:
573             val = *(uint32_t *)(apic->trig_mode_reg + 4);
574             break;
575         case TRIG_OFFSET2:
576             val = *(uint32_t *)(apic->trig_mode_reg + 8);
577             break;
578         case TRIG_OFFSET3:
579             val = *(uint32_t *)(apic->trig_mode_reg + 12);
580             break;
581         case TRIG_OFFSET4:
582             val = *(uint32_t *)(apic->trig_mode_reg + 16);
583             break;
584         case TRIG_OFFSET5:
585             val = *(uint32_t *)(apic->trig_mode_reg + 20);
586             break;
587         case TRIG_OFFSET6:
588             val = *(uint32_t *)(apic->trig_mode_reg + 24);
589             break;
590         case TRIG_OFFSET7:
591             val = *(uint32_t *)(apic->trig_mode_reg + 28);
592             break;
593
594         case IRR_OFFSET0:
595             val = *(uint32_t *)(apic->int_req_reg);
596             break;
597         case IRR_OFFSET1:
598             val = *(uint32_t *)(apic->int_req_reg + 4);
599             break;
600         case IRR_OFFSET2:
601             val = *(uint32_t *)(apic->int_req_reg + 8);
602             break;
603         case IRR_OFFSET3:
604             val = *(uint32_t *)(apic->int_req_reg + 12);
605             break;
606         case IRR_OFFSET4:
607             val = *(uint32_t *)(apic->int_req_reg + 16);
608             break;
609         case IRR_OFFSET5:
610             val = *(uint32_t *)(apic->int_req_reg + 20);
611             break;
612         case IRR_OFFSET6:
613             val = *(uint32_t *)(apic->int_req_reg + 24);
614             break;
615         case IRR_OFFSET7:
616             val = *(uint32_t *)(apic->int_req_reg + 28);
617             break;
618         case TMR_CUR_CNT_OFFSET:
619             val = apic->tmr_cur_cnt;
620             break;
621
622             // We are not going to implement these....
623         case THERM_LOC_VEC_TBL_OFFSET:
624             val = apic->therm_loc_vec_tbl.val;
625             break;
626         case PERF_CTR_LOC_VEC_TBL_OFFSET:
627             val = apic->perf_ctr_loc_vec_tbl.val;
628             break;
629
630  
631
632             // handled registers
633         case INT_CMD_LO_OFFSET:    
634             val = apic->int_cmd.lo;
635             break;
636         case INT_CMD_HI_OFFSET:
637             val = apic->int_cmd.hi;
638             break;
639
640             // handle current timer count
641
642             // Unhandled Registers
643         case EXT_INT_LOC_VEC_TBL_OFFSET0:
644             val = apic->ext_intr_vec_tbl[0].val;
645             break;
646         case EXT_INT_LOC_VEC_TBL_OFFSET1:
647             val = apic->ext_intr_vec_tbl[1].val;
648             break;
649         case EXT_INT_LOC_VEC_TBL_OFFSET2:
650             val = apic->ext_intr_vec_tbl[2].val;
651             break;
652         case EXT_INT_LOC_VEC_TBL_OFFSET3:
653             val = apic->ext_intr_vec_tbl[3].val;
654             break;
655     
656
657         case EXT_APIC_FEATURE_OFFSET:
658         case EXT_APIC_CMD_OFFSET:
659         case SEOI_OFFSET:
660
661         default:
662             PrintError("Read from Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
663             return -1;
664     }
665
666
667     if (length == 1) {
668         uint_t byte_addr = reg_addr & 0x3;
669         uint8_t * val_ptr = (uint8_t *)dst;
670     
671         *val_ptr = *(((uint8_t *)&val) + byte_addr);
672
673     } else if ((length == 2) && 
674                ((reg_addr & 0x3) == 0x3)) {
675         uint_t byte_addr = reg_addr & 0x3;
676         uint16_t * val_ptr = (uint16_t *)dst;
677         *val_ptr = *(((uint16_t *)&val) + byte_addr);
678
679     } else if (length == 4) {
680         uint32_t * val_ptr = (uint32_t *)dst;
681         *val_ptr = val;
682
683     } else {
684         PrintError("Invalid apic read length (%d)\n", length);
685         return -1;
686     }
687
688     PrintDebug("Read finished (val=%x)\n", *(uint32_t *)dst);
689
690     return length;
691 }
692
693
694 static int apic_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
695     struct vm_device * dev = (struct vm_device *)priv_data;
696     struct apic_state * apic = (struct apic_state *)dev->private_data;
697     addr_t reg_addr  = guest_addr - apic->base_addr;
698     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
699     uint32_t op_val = *(uint32_t *)src;
700
701     PrintDebug("Write to apic address space (%p) (val=%x)\n", 
702                (void *)guest_addr, *(uint32_t *)src);
703
704     if (msr->apic_enable == 0) {
705         PrintError("Write to APIC address space with disabled APIC\n");
706         return -1;
707     }
708
709
710     if (length != 4) {
711         PrintError("Invalid apic write length (%d)\n", length);
712         return -1;
713     }
714
715     switch (reg_addr) {
716         case REMOTE_READ_OFFSET:
717         case APIC_VERSION_OFFSET:
718         case APR_OFFSET:
719         case IRR_OFFSET0:
720         case IRR_OFFSET1:
721         case IRR_OFFSET2:
722         case IRR_OFFSET3:
723         case IRR_OFFSET4:
724         case IRR_OFFSET5:
725         case IRR_OFFSET6:
726         case IRR_OFFSET7:
727         case ISR_OFFSET0:
728         case ISR_OFFSET1:
729         case ISR_OFFSET2:
730         case ISR_OFFSET3:
731         case ISR_OFFSET4:
732         case ISR_OFFSET5:
733         case ISR_OFFSET6:
734         case ISR_OFFSET7:
735         case TRIG_OFFSET0:
736         case TRIG_OFFSET1:
737         case TRIG_OFFSET2:
738         case TRIG_OFFSET3:
739         case TRIG_OFFSET4:
740         case TRIG_OFFSET5:
741         case TRIG_OFFSET6:
742         case TRIG_OFFSET7:
743         case PPR_OFFSET:
744         case EXT_APIC_FEATURE_OFFSET:
745 #if 1
746             PrintError("Attempting to write to read only register %p (ignored)\n", (void *)reg_addr);
747 #else   
748             PrintError("Attempting to write to read only register %p (error)\n", (void *)reg_addr);
749             return -1;
750 #endif
751             break;
752
753             // Data registers
754         case APIC_ID_OFFSET:
755             apic->lapic_id.val = op_val;
756             break;
757         case TPR_OFFSET:
758             apic->task_prio.val = op_val;
759             break;
760         case LDR_OFFSET:
761             apic->log_dst.val = op_val;
762             break;
763         case DFR_OFFSET:
764             apic->dst_fmt.val = op_val;
765             break;
766         case SPURIOUS_INT_VEC_OFFSET:
767             apic->spurious_int.val = op_val;
768             break;
769         case ESR_OFFSET:
770             apic->err_status.val = op_val;
771             break;
772         case TMR_LOC_VEC_TBL_OFFSET:
773             apic->tmr_vec_tbl.val = op_val;
774             break;
775         case THERM_LOC_VEC_TBL_OFFSET:
776             apic->therm_loc_vec_tbl.val = op_val;
777             break;
778         case PERF_CTR_LOC_VEC_TBL_OFFSET:
779             apic->perf_ctr_loc_vec_tbl.val = op_val;
780             break;
781         case LINT0_VEC_TBL_OFFSET:
782             apic->lint0_vec_tbl.val = op_val;
783             break;
784         case LINT1_VEC_TBL_OFFSET:
785             apic->lint1_vec_tbl.val = op_val;
786             break;
787         case ERR_VEC_TBL_OFFSET:
788             apic->err_vec_tbl.val = op_val;
789             break;
790         case TMR_INIT_CNT_OFFSET:
791             apic->tmr_init_cnt = op_val;
792             apic->tmr_cur_cnt = op_val;
793             break;
794         case TMR_CUR_CNT_OFFSET:
795             apic->tmr_cur_cnt = op_val;
796             break;
797         case TMR_DIV_CFG_OFFSET:
798             apic->tmr_div_cfg.val = op_val;
799             break;
800
801
802             // Enable mask (256 bits)
803         case IER_OFFSET0:
804             *(uint32_t *)(apic->int_en_reg) = op_val;
805             break;
806         case IER_OFFSET1:
807             *(uint32_t *)(apic->int_en_reg + 4) = op_val;
808             break;
809         case IER_OFFSET2:
810             *(uint32_t *)(apic->int_en_reg + 8) = op_val;
811             break;
812         case IER_OFFSET3:
813             *(uint32_t *)(apic->int_en_reg + 12) = op_val;
814             break;
815         case IER_OFFSET4:
816             *(uint32_t *)(apic->int_en_reg + 16) = op_val;
817             break;
818         case IER_OFFSET5:
819             *(uint32_t *)(apic->int_en_reg + 20) = op_val;
820             break;
821         case IER_OFFSET6:
822             *(uint32_t *)(apic->int_en_reg + 24) = op_val;
823             break;
824         case IER_OFFSET7:
825             *(uint32_t *)(apic->int_en_reg + 28) = op_val;
826             break;
827
828         case EXT_INT_LOC_VEC_TBL_OFFSET0:
829             apic->ext_intr_vec_tbl[0].val = op_val;
830             break;
831         case EXT_INT_LOC_VEC_TBL_OFFSET1:
832             apic->ext_intr_vec_tbl[1].val = op_val;
833             break;
834         case EXT_INT_LOC_VEC_TBL_OFFSET2:
835             apic->ext_intr_vec_tbl[2].val = op_val;
836             break;
837         case EXT_INT_LOC_VEC_TBL_OFFSET3:
838             apic->ext_intr_vec_tbl[3].val = op_val;
839             break;
840
841
842             // Action Registers
843         case EOI_OFFSET:
844             // do eoi
845             apic_do_eoi(apic);
846             break;
847
848         case INT_CMD_LO_OFFSET:
849             apic->int_cmd.lo = op_val;
850             V3_Call_On_CPU(apic->int_cmd.dst, apic_incoming_ipi, (void *)apic->int_cmd.val);
851     
852             break;
853         case INT_CMD_HI_OFFSET:
854             apic->int_cmd.hi = op_val;
855             break;
856             // Unhandled Registers
857
858         case EXT_APIC_CMD_OFFSET:
859         case SEOI_OFFSET:
860         default:
861             PrintError("Write to Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
862             return -1;
863     }
864
865     PrintDebug("Write finished\n");
866
867     return length;
868 }
869
870
871
872 /* Interrupt Controller Functions */
873
874 // returns 1 if an interrupt is pending, 0 otherwise
875 static int apic_intr_pending(struct guest_info * info, void * private_data) {
876     struct vm_device * dev = (struct vm_device *)private_data;
877     struct apic_state * apic = (struct apic_state *)dev->private_data;
878     int req_irq = get_highest_irr(apic);
879     int svc_irq = get_highest_isr(apic);
880
881     if ((req_irq >= 0) && 
882         (req_irq > svc_irq)) {
883         return 1;
884     }
885
886     return 0;
887 }
888
889 static int apic_get_intr_number(struct guest_info * info, void * private_data) {
890     struct vm_device * dev = (struct vm_device *)private_data;
891     struct apic_state * apic = (struct apic_state *)dev->private_data;
892     int req_irq = get_highest_irr(apic);
893     int svc_irq = get_highest_isr(apic);
894
895     if (svc_irq == -1) {
896         return req_irq;
897     } else if (svc_irq < req_irq) {
898         return req_irq;
899     }
900
901     return -1;
902 }
903
904 static int apic_raise_intr(struct guest_info * info, void * private_data, int irq) {
905 #ifdef CONFIG_CRAY_XT
906     // The Seastar is connected directly to the LAPIC via LINT0 on the ICC bus
907
908     if (irq == 238) {
909         struct vm_device * dev = (struct vm_device *)private_data;
910         struct apic_state * apic = (struct apic_state *)dev->private_data;
911
912         return activate_apic_irq(apic, irq);
913     }
914 #endif
915
916     return 0;
917 }
918
919 static int apic_lower_intr(struct guest_info * info, void * private_data, int irq) {
920     return 0;
921 }
922
923 static int apic_begin_irq(struct guest_info * info, void * private_data, int irq) {
924     struct vm_device * dev = (struct vm_device *)private_data;
925     struct apic_state * apic = (struct apic_state *)dev->private_data;
926     int major_offset = (irq & ~0x00000007) >> 3;
927     int minor_offset = irq & 0x00000007;
928     uchar_t * req_location = apic->int_req_reg + major_offset;
929     uchar_t * svc_location = apic->int_svc_reg + major_offset;
930     uchar_t flag = 0x01 << minor_offset;
931
932     *svc_location |= flag;
933     *req_location &= ~flag;
934
935 #ifdef CONFIG_CRAY_XT
936     if ((irq == 238) || (irq == 239)) {
937         PrintError("APIC: Begin IRQ %d (ISR=%x), (IRR=%x)\n", irq, *svc_location, *req_location);
938     }
939 #endif
940
941     return 0;
942 }
943
944
945
946 int v3_apic_raise_intr(struct guest_info * info, struct vm_device * apic_dev, int intr_num) {
947     struct apic_state * apic = (struct apic_state *)apic_dev->private_data;
948
949     if (activate_apic_irq(apic, intr_num) == -1) {
950         PrintError("Error: Could not activate apic_irq\n");
951         return -1;
952     } 
953
954     v3_interrupt_cpu(info, 0);
955
956     return 0;
957 }
958
959
960
961 /* Timer Functions */
962 static void apic_update_time(ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data) {
963     struct vm_device * dev = (struct vm_device *)priv_data;
964     struct apic_state * apic = (struct apic_state *)dev->private_data;
965     // The 32 bit GCC runtime is a pile of shit
966 #ifdef __V3_64BIT__
967     uint64_t tmr_ticks = 0;
968 #else 
969     uint32_t tmr_ticks = 0;
970 #endif
971
972     uchar_t tmr_div = *(uchar_t *)&(apic->tmr_div_cfg.val);
973     uint_t shift_num = 0;
974
975
976     // Check whether this is true:
977     //   -> If the Init count is zero then the timer is disabled
978     //      and doesn't just blitz interrupts to the CPU
979     if ((apic->tmr_init_cnt == 0) || 
980         ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
981           (apic->tmr_cur_cnt == 0))) {
982         //PrintDebug("APIC timer not yet initialized\n");
983         return;
984     }
985
986
987     switch (tmr_div) {
988         case APIC_TMR_DIV1:
989             shift_num = 0;
990             break;
991         case APIC_TMR_DIV2:
992             shift_num = 1;
993             break;
994         case APIC_TMR_DIV4:
995             shift_num = 2;
996             break;
997         case APIC_TMR_DIV8:
998             shift_num = 3;
999             break;
1000         case APIC_TMR_DIV16:
1001             shift_num = 4;
1002             break;
1003         case APIC_TMR_DIV32:
1004             shift_num = 5;
1005             break;
1006         case APIC_TMR_DIV64:
1007             shift_num = 6;
1008             break;
1009         case APIC_TMR_DIV128:
1010             shift_num = 7;
1011             break;
1012         default:
1013             PrintError("Invalid Timer Divider configuration\n");
1014             return;
1015     }
1016
1017     tmr_ticks = cpu_cycles >> shift_num;
1018     //    PrintDebug("Timer Ticks: %p\n", (void *)tmr_ticks);
1019
1020     if (tmr_ticks < apic->tmr_cur_cnt) {
1021         apic->tmr_cur_cnt -= tmr_ticks;
1022     } else {
1023         tmr_ticks -= apic->tmr_cur_cnt;
1024         apic->tmr_cur_cnt = 0;
1025
1026         // raise irq
1027         PrintDebug("Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n", 
1028                    apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
1029
1030         if (apic_intr_pending(dev->vm, priv_data)) {
1031             PrintDebug("Overriding pending IRQ %d\n", apic_get_intr_number(dev->vm, priv_data));
1032         }
1033
1034         if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
1035             PrintError("Could not raise Timer interrupt\n");
1036         }
1037     
1038         if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
1039             tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
1040             apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
1041         }
1042     }
1043
1044
1045 }
1046
1047 static void apic_incoming_ipi(void *val)
1048 {
1049 PrintError("In apic_incoming_ipi, val=%p\n", val);
1050         struct int_cmd_reg int_cmd;
1051         char *type = NULL, *dest;
1052         char foo[8];
1053         int_cmd.val = (uint64_t)val;
1054         switch (int_cmd.dst_shorthand)
1055         {
1056         case 0x0:
1057                 sprintf(foo, "%d", int_cmd.dst);
1058                 dest = foo;
1059                 break;
1060         case 0x1:
1061                 dest = "(self)";
1062                 break;
1063         case 0x2:
1064                 dest = "(broadcast inclusive)";
1065                 break;
1066         case 0x3:
1067                 dest = "(broadcast)";
1068                 break;
1069         }
1070         switch (int_cmd.msg_type) 
1071         {
1072         case 0x0:
1073                 type = "";
1074                 break;
1075         case 0x4:
1076                 type = "(NMI)";
1077                 break;
1078         case 0x5:
1079                 type = "(INIT)";
1080                 break;
1081         case 0x6:
1082                 type = "(Startup)";
1083                 break;
1084         }
1085         PrintError("Receieved IPI on CPU %d type=%s dest=%s\n",
1086                         V3_Get_CPU(), type, dest);
1087 //%p %s to CPU %d on CPU %d.\n", val, foo, type, dest, (int)V3_Get_CPU());
1088         return;
1089 }
1090
1091
1092 static struct intr_ctrl_ops intr_ops = {
1093     .intr_pending = apic_intr_pending,
1094     .get_intr_number = apic_get_intr_number,
1095     .raise_intr = apic_raise_intr,
1096     .begin_irq = apic_begin_irq,
1097     .lower_intr = apic_lower_intr, 
1098 };
1099
1100
1101 static struct vm_timer_ops timer_ops = {
1102     .update_time = apic_update_time,
1103 };
1104
1105
1106
1107
1108 static int apic_free(struct vm_device * dev) {
1109     struct guest_info * info = dev->vm;
1110
1111     v3_unhook_msr(info, BASE_ADDR_MSR);
1112
1113     return 0;
1114 }
1115
1116
1117 static struct v3_device_ops dev_ops = {
1118     .free = apic_free,
1119     .reset = NULL,
1120     .start = NULL,
1121     .stop = NULL,
1122 };
1123
1124
1125
1126 static int apic_init(struct guest_info * vm, v3_cfg_tree_t * cfg) {
1127     PrintDebug("Creating APIC\n");
1128     char * name = v3_cfg_val(cfg, "name");
1129
1130     struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state));
1131
1132     struct vm_device * dev = v3_allocate_device(name, &dev_ops, apic);
1133
1134     if (v3_attach_device(vm, dev) == -1) {
1135         PrintError("Could not attach device %s\n", name);
1136         return -1;
1137     }
1138
1139     v3_register_intr_controller(vm, &intr_ops, dev);
1140     v3_add_timer(vm, &timer_ops, dev);
1141
1142     init_apic_state(apic);
1143
1144     v3_hook_msr(vm, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev);
1145
1146     v3_hook_full_mem(vm, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, dev);
1147
1148     return 0;
1149 }
1150
1151
1152
1153 device_register("LAPIC", apic_init)