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.


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