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.


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