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.


typo fix
[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 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
172     uint32_t rem_rd_data;
173
174
175     uchar_t int_req_reg[32];
176     uchar_t int_svc_reg[32];
177     uchar_t int_en_reg[32];
178     uchar_t trig_mode_reg[32];
179   
180     uint32_t eoi;
181
182
183 };
184
185
186 static void init_apic_state(struct apic_state * apic) {
187     apic->base_addr = DEFAULT_BASE_ADDR;
188     apic->base_addr_msr.value = 0x0000000000000900LL;
189     apic->base_addr_msr.value |= ((uint64_t)DEFAULT_BASE_ADDR); 
190
191     PrintDebug("Sizeof Interrupt Request Register %d, should be 32\n", 
192                (uint_t)sizeof(apic->int_req_reg));
193
194     memset(apic->int_req_reg, 0, sizeof(apic->int_req_reg));
195     memset(apic->int_svc_reg, 0, sizeof(apic->int_svc_reg));
196     memset(apic->int_en_reg, 0xff, sizeof(apic->int_en_reg));
197     memset(apic->trig_mode_reg, 0, sizeof(apic->trig_mode_reg));
198
199     apic->eoi = 0x00000000;
200     apic->rem_rd_data = 0x00000000;
201     apic->tmr_init_cnt = 0x00000000;
202     apic->tmr_cur_cnt = 0x00000000;
203
204     // TODO:
205     // We need to figure out what the APIC ID is....
206     apic->lapic_id.val = 0x00000000;
207
208     // The P6 has 6 LVT entries, so we set the value to (6-1)...
209     apic->apic_ver.val = 0x80050010;
210
211     apic->task_prio.val = 0x00000000;
212     apic->arb_prio.val = 0x00000000;
213     apic->proc_prio.val = 0x00000000;
214     apic->log_dst.val = 0x00000000;
215     apic->dst_fmt.val = 0xffffffff;
216     apic->spurious_int.val = 0x000000ff;
217     apic->err_status.val = 0x00000000;
218     apic->int_cmd.val = 0x0000000000000000LL;
219     apic->tmr_vec_tbl.val = 0x00010000;
220     apic->therm_loc_vec_tbl.val = 0x00010000;
221     apic->perf_ctr_loc_vec_tbl.val = 0x00010000;
222     apic->lint0_vec_tbl.val = 0x00010000;
223     apic->lint1_vec_tbl.val = 0x00010000;
224     apic->err_vec_tbl.val = 0x00010000;
225     apic->tmr_div_cfg.val = 0x00000000;
226     apic->ext_apic_feature.val = 0x00040007;
227     apic->ext_apic_ctrl.val = 0x00000000;
228     apic->spec_eoi.val = 0x00000000;
229 }
230
231
232
233
234 static int read_apic_msr(uint_t msr, v3_msr_t * dst, void * priv_data) {
235     struct vm_device * dev = (struct vm_device *)priv_data;
236     struct apic_state * apic = (struct apic_state *)dev->private_data;
237     PrintError("READING APIC BASE ADDR: HI=%x LO=%x\n", apic->base_addr_msr.hi, apic->base_addr_msr.lo);
238
239     return -1;
240 }
241
242
243 static int write_apic_msr(uint_t msr, v3_msr_t src, void * priv_data) {
244     //  struct vm_device * dev = (struct vm_device *)priv_data;
245     //  struct apic_state * apic = (struct apic_state *)dev->private_data;
246
247     PrintError("WRITING APIC BASE ADDR: HI=%x LO=%x\n", src.hi, src.lo);
248
249     return -1;
250 }
251
252
253 // irq_num is the bit offset into a 256 bit buffer...
254 static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
255     int major_offset = (irq_num & ~0x00000007) >> 3;
256     int minor_offset = irq_num & 0x00000007;
257     uchar_t * req_location = apic->int_req_reg + major_offset;
258     uchar_t * en_location = apic->int_en_reg + major_offset;
259     uchar_t flag = 0x1 << minor_offset;
260
261     if (irq_num <= 15) {
262         PrintError("Attempting to raise an invalid interrupt: %d\n", irq_num);
263         return -1;
264     }
265
266     PrintDebug("Raising APIC IRQ %d\n", irq_num);
267
268     if (*en_location & flag) {
269         *req_location |= flag;
270     } else {
271         PrintDebug("Interrupt  not enabled... %.2x\n", *en_location);
272         return 0;
273     }
274
275     return 0;
276 }
277
278
279
280 static int apic_do_eoi(struct apic_state * apic) {
281     int i = 0, j = 0;
282
283     PrintDebug("Received APIC EOI\n");
284
285     // We iterate backwards to find the highest priority
286     for (i = 31; i >= 0; i--) {
287         uchar_t  * svc_major = apic->int_svc_reg + i;
288     
289         if ((*svc_major) & 0xff) {
290             for (j = 7; j >= 0; j--) {
291                 uchar_t flag = 0x1 << j;
292                 if ((*svc_major) & flag) {
293                     *svc_major &= ~flag;
294
295 #ifdef CRAY_XT
296
297                     if ((((i * 8) + j) == 238) || 
298                         (((i * 8) + j) == 239)) {
299                         PrintError("Acking IRQ %d\n", ((i * 8) + j));
300                     }
301                     
302                     if (((i * 8) + j) == 238) {
303                         V3_ACK_IRQ(238);
304                     }
305 #endif
306                     return 0;
307                 }
308             }
309         }
310     }
311
312     return 0;
313 }
314  
315
316 static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_type) {
317     uint32_t vec_num = 0;
318     uint32_t del_mode = 0;
319     int masked = 0;
320
321
322     switch (int_type) {
323         case APIC_TMR_INT:
324             vec_num = apic->tmr_vec_tbl.vec;
325             del_mode = APIC_FIXED_DELIVERY;
326             masked = apic->tmr_vec_tbl.mask;
327             break;
328         case APIC_THERM_INT:
329             vec_num = apic->therm_loc_vec_tbl.vec;
330             del_mode = apic->therm_loc_vec_tbl.msg_type;
331             masked = apic->therm_loc_vec_tbl.mask;
332             break;
333         case APIC_PERF_INT:
334             vec_num = apic->perf_ctr_loc_vec_tbl.vec;
335             del_mode = apic->perf_ctr_loc_vec_tbl.msg_type;
336             masked = apic->perf_ctr_loc_vec_tbl.mask;
337             break;
338         case APIC_LINT0_INT:
339             vec_num = apic->lint0_vec_tbl.vec;
340             del_mode = apic->lint0_vec_tbl.msg_type;
341             masked = apic->lint0_vec_tbl.mask;
342             break;
343         case APIC_LINT1_INT:
344             vec_num = apic->lint1_vec_tbl.vec;
345             del_mode = apic->lint1_vec_tbl.msg_type;
346             masked = apic->lint1_vec_tbl.mask;
347             break;
348         case APIC_ERR_INT:
349             vec_num = apic->err_vec_tbl.vec;
350             del_mode = APIC_FIXED_DELIVERY;
351             masked = apic->err_vec_tbl.mask;
352             break;
353         default:
354             PrintError("Invalid APIC interrupt type\n");
355             return -1;
356     }
357
358     // interrupt is masked, don't send
359     if (masked == 1) {
360         PrintDebug("Inerrupt is masked\n");
361         return 0;
362     }
363
364     if (del_mode == APIC_FIXED_DELIVERY) {
365         //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
366         return activate_apic_irq(apic, vec_num);
367     } else {
368         PrintError("Unhandled Delivery Mode\n");
369         return -1;
370     }
371 }
372
373
374 static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
375     struct vm_device * dev = (struct vm_device *)priv_data;
376     struct apic_state * apic = (struct apic_state *)dev->private_data;
377     addr_t reg_addr  = guest_addr - apic->base_addr;
378     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
379     uint32_t val = 0;
380
381
382     PrintDebug("Read apic address space (%p)\n", 
383                (void *)guest_addr);
384
385     if (msr->apic_enable == 0) {
386         PrintError("Write to APIC address space with disabled APIC\n");
387         return -1;
388     }
389
390
391     /* Because "May not be supported" doesn't matter to Linux developers... */
392     /*   if (length != 4) { */
393     /*     PrintError("Invalid apic read length (%d)\n", length); */
394     /*     return -1; */
395     /*   } */
396
397     switch (reg_addr & ~0x3) {
398         case EOI_OFFSET:
399             // Well, only an idiot would read from a architectural write only register
400             // Oh, Hello Linux.
401             //    PrintError("Attempting to read from write only register\n");
402             //    return -1;
403             break;
404
405             // data registers
406         case APIC_ID_OFFSET:
407             val = apic->lapic_id.val;
408             break;
409         case APIC_VERSION_OFFSET:
410             val = apic->apic_ver.val;
411             break;
412         case TPR_OFFSET:
413             val = apic->task_prio.val;
414             break;
415         case APR_OFFSET:
416             val = apic->arb_prio.val;
417             break;
418         case PPR_OFFSET:
419             val = apic->proc_prio.val;
420             break;
421         case REMOTE_READ_OFFSET:
422             val = apic->rem_rd_data;
423             break;
424         case LDR_OFFSET:
425             val = apic->log_dst.val;
426             break;
427         case DFR_OFFSET:
428             val = apic->dst_fmt.val;
429             break;
430         case SPURIOUS_INT_VEC_OFFSET:
431             val = apic->spurious_int.val;
432             break;
433         case ESR_OFFSET:
434             val = apic->err_status.val;
435             break;
436         case TMR_LOC_VEC_TBL_OFFSET:
437             val = apic->tmr_vec_tbl.val;
438             break;
439         case LINT0_VEC_TBL_OFFSET:
440             val = apic->lint0_vec_tbl.val;
441             break;
442         case LINT1_VEC_TBL_OFFSET:
443             val = apic->lint1_vec_tbl.val;
444             break;
445         case ERR_VEC_TBL_OFFSET:
446             val = apic->err_vec_tbl.val;
447             break;
448         case TMR_INIT_CNT_OFFSET:
449             val = apic->tmr_init_cnt;
450             break;
451         case TMR_DIV_CFG_OFFSET:
452             val = apic->tmr_div_cfg.val;
453             break;
454
455         case IER_OFFSET0:
456             val = *(uint32_t *)(apic->int_en_reg);
457             break;
458         case IER_OFFSET1:
459             val = *(uint32_t *)(apic->int_en_reg + 4);
460             break;
461         case IER_OFFSET2:
462             val = *(uint32_t *)(apic->int_en_reg + 8);
463             break;
464         case IER_OFFSET3:
465             val = *(uint32_t *)(apic->int_en_reg + 12);
466             break;
467         case IER_OFFSET4:
468             val = *(uint32_t *)(apic->int_en_reg + 16);
469             break;
470         case IER_OFFSET5:
471             val = *(uint32_t *)(apic->int_en_reg + 20);
472             break;
473         case IER_OFFSET6:
474             val = *(uint32_t *)(apic->int_en_reg + 24);
475             break;
476         case IER_OFFSET7:
477             val = *(uint32_t *)(apic->int_en_reg + 28);
478             break;
479
480         case ISR_OFFSET0:
481             val = *(uint32_t *)(apic->int_svc_reg);
482             break;
483         case ISR_OFFSET1:
484             val = *(uint32_t *)(apic->int_svc_reg + 4);
485             break;
486         case ISR_OFFSET2:
487             val = *(uint32_t *)(apic->int_svc_reg + 8);
488             break;
489         case ISR_OFFSET3:
490             val = *(uint32_t *)(apic->int_svc_reg + 12);
491             break;
492         case ISR_OFFSET4:
493             val = *(uint32_t *)(apic->int_svc_reg + 16);
494             break;
495         case ISR_OFFSET5:
496             val = *(uint32_t *)(apic->int_svc_reg + 20);
497             break;
498         case ISR_OFFSET6:
499             val = *(uint32_t *)(apic->int_svc_reg + 24);
500             break;
501         case ISR_OFFSET7:
502             val = *(uint32_t *)(apic->int_svc_reg + 28);
503             break;
504    
505         case TRIG_OFFSET0:
506             val = *(uint32_t *)(apic->trig_mode_reg);
507             break;
508         case TRIG_OFFSET1:
509             val = *(uint32_t *)(apic->trig_mode_reg + 4);
510             break;
511         case TRIG_OFFSET2:
512             val = *(uint32_t *)(apic->trig_mode_reg + 8);
513             break;
514         case TRIG_OFFSET3:
515             val = *(uint32_t *)(apic->trig_mode_reg + 12);
516             break;
517         case TRIG_OFFSET4:
518             val = *(uint32_t *)(apic->trig_mode_reg + 16);
519             break;
520         case TRIG_OFFSET5:
521             val = *(uint32_t *)(apic->trig_mode_reg + 20);
522             break;
523         case TRIG_OFFSET6:
524             val = *(uint32_t *)(apic->trig_mode_reg + 24);
525             break;
526         case TRIG_OFFSET7:
527             val = *(uint32_t *)(apic->trig_mode_reg + 28);
528             break;
529
530         case IRR_OFFSET0:
531             val = *(uint32_t *)(apic->int_req_reg);
532             break;
533         case IRR_OFFSET1:
534             val = *(uint32_t *)(apic->int_req_reg + 4);
535             break;
536         case IRR_OFFSET2:
537             val = *(uint32_t *)(apic->int_req_reg + 8);
538             break;
539         case IRR_OFFSET3:
540             val = *(uint32_t *)(apic->int_req_reg + 12);
541             break;
542         case IRR_OFFSET4:
543             val = *(uint32_t *)(apic->int_req_reg + 16);
544             break;
545         case IRR_OFFSET5:
546             val = *(uint32_t *)(apic->int_req_reg + 20);
547             break;
548         case IRR_OFFSET6:
549             val = *(uint32_t *)(apic->int_req_reg + 24);
550             break;
551         case IRR_OFFSET7:
552             val = *(uint32_t *)(apic->int_req_reg + 28);
553             break;
554         case TMR_CUR_CNT_OFFSET:
555             val = apic->tmr_cur_cnt;
556             break;
557
558             // We are not going to implement these....
559         case THERM_LOC_VEC_TBL_OFFSET:
560             val = apic->therm_loc_vec_tbl.val;
561             break;
562         case PERF_CTR_LOC_VEC_TBL_OFFSET:
563             val = apic->perf_ctr_loc_vec_tbl.val;
564             break;
565
566  
567
568             // handled registers
569         case INT_CMD_LO_OFFSET:    
570             val = apic->int_cmd.lo;
571             break;
572         case INT_CMD_HI_OFFSET:
573             val = apic->int_cmd.hi;
574             break;
575
576             // handle current timer count
577
578             // Unhandled Registers
579         case EXT_INT_LOC_VEC_TBL_OFFSET0:
580         case EXT_INT_LOC_VEC_TBL_OFFSET1:
581         case EXT_INT_LOC_VEC_TBL_OFFSET2:
582         case EXT_INT_LOC_VEC_TBL_OFFSET3:
583         case EXT_APIC_FEATURE_OFFSET:
584         case EXT_APIC_CMD_OFFSET:
585         case SEOI_OFFSET:
586
587         default:
588             PrintError("Read from Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
589             return -1;
590     }
591
592
593     if (length == 1) {
594         uint_t byte_addr = reg_addr & 0x3;
595         uint8_t * val_ptr = (uint8_t *)dst;
596     
597         *val_ptr = *(((uint8_t *)&val) + byte_addr);
598
599     } else if ((length == 2) && 
600                ((reg_addr & 0x3) == 0x3)) {
601         uint_t byte_addr = reg_addr & 0x3;
602         uint16_t * val_ptr = (uint16_t *)dst;
603         *val_ptr = *(((uint16_t *)&val) + byte_addr);
604
605     } else if (length == 4) {
606         uint32_t * val_ptr = (uint32_t *)dst;
607         *val_ptr = val;
608
609     } else {
610         PrintError("Invalid apic read length (%d)\n", length);
611         return -1;
612     }
613
614     PrintDebug("Read finished (val=%x)\n", *(uint32_t *)dst);
615
616     return length;
617 }
618
619
620 static int apic_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
621     struct vm_device * dev = (struct vm_device *)priv_data;
622     struct apic_state * apic = (struct apic_state *)dev->private_data;
623     addr_t reg_addr  = guest_addr - apic->base_addr;
624     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
625     uint32_t op_val = *(uint32_t *)src;
626
627     PrintDebug("Write to apic address space (%p) (val=%x)\n", 
628                (void *)guest_addr, *(uint32_t *)src);
629
630     if (msr->apic_enable == 0) {
631         PrintError("Write to APIC address space with disabled APIC\n");
632         return -1;
633     }
634
635
636     if (length != 4) {
637         PrintError("Invalid apic write length (%d)\n", length);
638         return -1;
639     }
640
641     switch (reg_addr) {
642         case REMOTE_READ_OFFSET:
643         case APIC_VERSION_OFFSET:
644         case APR_OFFSET:
645         case IRR_OFFSET0:
646         case IRR_OFFSET1:
647         case IRR_OFFSET2:
648         case IRR_OFFSET3:
649         case IRR_OFFSET4:
650         case IRR_OFFSET5:
651         case IRR_OFFSET6:
652         case IRR_OFFSET7:
653         case ISR_OFFSET0:
654         case ISR_OFFSET1:
655         case ISR_OFFSET2:
656         case ISR_OFFSET3:
657         case ISR_OFFSET4:
658         case ISR_OFFSET5:
659         case ISR_OFFSET6:
660         case ISR_OFFSET7:
661         case TRIG_OFFSET0:
662         case TRIG_OFFSET1:
663         case TRIG_OFFSET2:
664         case TRIG_OFFSET3:
665         case TRIG_OFFSET4:
666         case TRIG_OFFSET5:
667         case TRIG_OFFSET6:
668         case TRIG_OFFSET7:
669         case PPR_OFFSET:
670         case EXT_APIC_FEATURE_OFFSET:
671 #if 1
672             PrintError("Attempting to write to read only register %p (ignored)\n", (void *)reg_addr);
673 #else   
674             PrintError("Attempting to write to read only register %p (error)\n", (void *)reg_addr);
675             return -1;
676 #endif
677             break;
678
679             // Data registers
680         case APIC_ID_OFFSET:
681             apic->lapic_id.val = op_val;
682             break;
683         case TPR_OFFSET:
684             apic->task_prio.val = op_val;
685             break;
686         case LDR_OFFSET:
687             apic->log_dst.val = op_val;
688             break;
689         case DFR_OFFSET:
690             apic->dst_fmt.val = op_val;
691             break;
692         case SPURIOUS_INT_VEC_OFFSET:
693             apic->spurious_int.val = op_val;
694             break;
695         case ESR_OFFSET:
696             apic->err_status.val = op_val;
697             break;
698         case TMR_LOC_VEC_TBL_OFFSET:
699             apic->tmr_vec_tbl.val = op_val;
700             break;
701         case THERM_LOC_VEC_TBL_OFFSET:
702             apic->therm_loc_vec_tbl.val = op_val;
703             break;
704         case PERF_CTR_LOC_VEC_TBL_OFFSET:
705             apic->perf_ctr_loc_vec_tbl.val = op_val;
706             break;
707         case LINT0_VEC_TBL_OFFSET:
708             apic->lint0_vec_tbl.val = op_val;
709             break;
710         case LINT1_VEC_TBL_OFFSET:
711             apic->lint1_vec_tbl.val = op_val;
712             break;
713         case ERR_VEC_TBL_OFFSET:
714             apic->err_vec_tbl.val = op_val;
715             break;
716         case TMR_INIT_CNT_OFFSET:
717             apic->tmr_init_cnt = op_val;
718             apic->tmr_cur_cnt = op_val;
719             break;
720         case TMR_CUR_CNT_OFFSET:
721             apic->tmr_cur_cnt = op_val;
722             break;
723         case TMR_DIV_CFG_OFFSET:
724             apic->tmr_div_cfg.val = op_val;
725             break;
726
727
728             // Enable mask (256 bits)
729         case IER_OFFSET0:
730             *(uint32_t *)(apic->int_en_reg) = op_val;
731             break;
732         case IER_OFFSET1:
733             *(uint32_t *)(apic->int_en_reg + 4) = op_val;
734             break;
735         case IER_OFFSET2:
736             *(uint32_t *)(apic->int_en_reg + 8) = op_val;
737             break;
738         case IER_OFFSET3:
739             *(uint32_t *)(apic->int_en_reg + 12) = op_val;
740             break;
741         case IER_OFFSET4:
742             *(uint32_t *)(apic->int_en_reg + 16) = op_val;
743             break;
744         case IER_OFFSET5:
745             *(uint32_t *)(apic->int_en_reg + 20) = op_val;
746             break;
747         case IER_OFFSET6:
748             *(uint32_t *)(apic->int_en_reg + 24) = op_val;
749             break;
750         case IER_OFFSET7:
751             *(uint32_t *)(apic->int_en_reg + 28) = op_val;
752             break;
753    
754
755             // Action Registers
756         case EOI_OFFSET:
757             // do eoi
758             apic_do_eoi(apic);
759             break;
760
761         case INT_CMD_LO_OFFSET:
762         case INT_CMD_HI_OFFSET:
763             // Unhandled Registers
764         case EXT_INT_LOC_VEC_TBL_OFFSET0:
765         case EXT_INT_LOC_VEC_TBL_OFFSET1:
766         case EXT_INT_LOC_VEC_TBL_OFFSET2:
767         case EXT_INT_LOC_VEC_TBL_OFFSET3:
768         case EXT_APIC_CMD_OFFSET:
769         case SEOI_OFFSET:
770         default:
771             PrintError("Write to Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
772             return -1;
773     }
774
775     PrintDebug("Write finished\n");
776
777     return length;
778 }
779
780
781
782 /* Interrupt Controller Functions */
783
784 static int apic_intr_pending(void * private_data) {
785     struct vm_device * dev = (struct vm_device *)private_data;
786     struct apic_state * apic = (struct apic_state *)dev->private_data;
787     int i = 0;
788
789
790     // just scan the request register looking for any set bit
791     // we should probably just do this with uint64 casts 
792     for (i = 0; i < 32; i++) {
793         if (apic->int_req_reg[i] & 0xff) {
794             return 1;
795         }
796     }
797     return 0;
798 }
799
800 static int apic_get_intr_number(void * private_data) {
801     struct vm_device * dev = (struct vm_device *)private_data;
802     struct apic_state * apic = (struct apic_state *)dev->private_data;
803     int i = 0, j = 0;
804
805
806     // We iterate backwards to find the highest priority
807     for (i = 31; i >= 0; i--) {
808         uchar_t req_major = apic->int_req_reg[i];
809     
810         if (req_major & 0xff) {
811             for (j = 7; j >= 0; j--) {
812                 if ((req_major >> j) == 0x1) {
813                     return (i * 8) + j;
814                 }
815             }
816         }
817     }
818
819     return -1;
820 }
821
822 static int apic_raise_intr(void * private_data, int irq) {
823 #ifdef CRAY_XT
824     // The Seastar is connected directly to the LAPIC via LINT0 on the ICC bus
825
826     if (irq == 238) {
827         struct vm_device * dev = (struct vm_device *)private_data;
828         struct apic_state * apic = (struct apic_state *)dev->private_data;
829
830         return activate_apic_irq(apic, irq);
831     }
832 #endif
833     return 0;
834 }
835
836 static int apic_lower_intr(void * private_data, int irq) {
837     return 0;
838 }
839
840 static int apic_begin_irq(void * private_data, int irq) {
841     struct vm_device * dev = (struct vm_device *)private_data;
842     struct apic_state * apic = (struct apic_state *)dev->private_data;
843     int major_offset = (irq & ~0x00000007) >> 3;
844     int minor_offset = irq & 0x00000007;
845     uchar_t * req_location = apic->int_req_reg + major_offset;
846     uchar_t * svc_location = apic->int_svc_reg + major_offset;
847     uchar_t flag = 0x01 << minor_offset;
848
849     *svc_location |= flag;
850     *req_location &= ~flag;
851
852 #ifdef CRAY_XT
853     if ((irq == 238) || (irq == 239)) {
854         PrintError("APIC: Begin IRQ %d (ISR=%x), (IRR=%x)\n", irq, *svc_location, *req_location);
855     }
856 #endif
857
858     return 0;
859 }
860
861
862
863 int v3_apic_raise_intr(struct vm_device * apic_dev, int intr_num) {
864     struct apic_state * apic = (struct apic_state *)apic_dev->private_data;
865     return activate_apic_irq(apic, intr_num);
866 }
867
868
869
870 /* Timer Functions */
871 static void apic_update_time(ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data) {
872     struct vm_device * dev = (struct vm_device *)priv_data;
873     struct apic_state * apic = (struct apic_state *)dev->private_data;
874     // The 32 bit GCC runtime is a pile of shit
875 #ifdef __V3_64BIT__
876     uint64_t tmr_ticks = 0;
877 #else 
878     uint32_t tmr_ticks = 0;
879 #endif
880
881     uchar_t tmr_div = *(uchar_t *)&(apic->tmr_div_cfg.val);
882     uint_t shift_num = 0;
883
884
885     // Check whether this is true:
886     //   -> If the Init count is zero then the timer is disabled
887     //      and doesn't just blitz interrupts to the CPU
888     if ((apic->tmr_init_cnt == 0) || 
889         ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
890           (apic->tmr_cur_cnt == 0))) {
891         //PrintDebug("APIC timer not yet initialized\n");
892         return;
893     }
894
895
896     switch (tmr_div) {
897         case APIC_TMR_DIV1:
898             shift_num = 0;
899             break;
900         case APIC_TMR_DIV2:
901             shift_num = 1;
902             break;
903         case APIC_TMR_DIV4:
904             shift_num = 2;
905             break;
906         case APIC_TMR_DIV8:
907             shift_num = 3;
908             break;
909         case APIC_TMR_DIV16:
910             shift_num = 4;
911             break;
912         case APIC_TMR_DIV32:
913             shift_num = 5;
914             break;
915         case APIC_TMR_DIV64:
916             shift_num = 6;
917             break;
918         case APIC_TMR_DIV128:
919             shift_num = 7;
920             break;
921         default:
922             PrintError("Invalid Timer Divider configuration\n");
923             return;
924     }
925
926     tmr_ticks = cpu_cycles >> shift_num;
927     PrintDebug("Timer Ticks: %p\n", (void *)tmr_ticks);
928
929     if (tmr_ticks < apic->tmr_cur_cnt) {
930         apic->tmr_cur_cnt -= tmr_ticks;
931     } else {
932         tmr_ticks -= apic->tmr_cur_cnt;
933         apic->tmr_cur_cnt = 0;
934
935         // raise irq
936         PrintDebug("Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n", 
937                    apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
938
939         if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
940             PrintError("Could not raise Timer interrupt\n");
941         }
942     
943         if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
944             tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
945             apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
946         }
947     }
948
949
950 }
951
952
953
954 static struct intr_ctrl_ops intr_ops = {
955     .intr_pending = apic_intr_pending,
956     .get_intr_number = apic_get_intr_number,
957     .raise_intr = apic_raise_intr,
958     .begin_irq = apic_begin_irq,
959     .lower_intr = apic_lower_intr, 
960 };
961
962
963 static struct vm_timer_ops timer_ops = {
964     .update_time = apic_update_time,
965 };
966
967
968 static int apic_init(struct vm_device * dev) {
969     struct guest_info * info = dev->vm;
970     struct apic_state * apic = (struct apic_state *)(dev->private_data);
971
972     v3_register_intr_controller(dev->vm, &intr_ops, dev);
973     v3_add_timer(dev->vm, &timer_ops, dev);
974
975     init_apic_state(apic);
976
977     v3_hook_msr(info, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev);
978
979     v3_hook_full_mem(info, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, dev);
980
981     return 0;
982 }
983
984 static int apic_deinit(struct vm_device * dev) {
985     struct guest_info * info = dev->vm;
986
987     v3_unhook_msr(info, BASE_ADDR_MSR);
988
989     return 0;
990 }
991
992
993 static struct vm_device_ops dev_ops = {
994     .init = apic_init,
995     .deinit = apic_deinit,
996     .reset = NULL,
997     .start = NULL,
998     .stop = NULL,
999 };
1000
1001
1002 struct vm_device * v3_create_apic() {
1003     PrintDebug("Creating APIC\n");
1004
1005     struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state));
1006
1007     struct vm_device * device = v3_create_device("APIC", &dev_ops, apic);
1008   
1009     return device;
1010 }