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.


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