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.


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