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.


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