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.


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