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.


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