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.


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