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.


Working apic, ioapic, and icc_bus for 1 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 <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, uint32_t id) {
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     apic->lapic_id.val = id;
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     v3_lock_init(&(apic->lock));
238 }
239
240
241
242
243 static int read_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
244     struct vm_device * dev = (struct vm_device *)priv_data;
245     struct apic_state * apics = (struct apic_state *)(dev->private_data);
246     struct apic_state * apic = &(apics[core->cpu_id]);
247
248     v3_lock(apic->lock);
249     dst->value = apic->base_addr;
250     v3_unlock(apic->lock);
251     return 0;
252 }
253
254
255 static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
256     struct vm_device * dev = (struct vm_device *)priv_data;
257     struct apic_state * apics = (struct apic_state *)(dev->private_data);
258     struct apic_state * apic = &(apics[core->cpu_id]);
259     struct v3_mem_region * old_reg = v3_get_mem_region(dev->vm, core->cpu_id, apic->base_addr);
260
261
262     if (old_reg == NULL) {
263         // uh oh...
264         PrintError("APIC Base address region does not exit...\n");
265         return -1;
266     }
267     
268     v3_lock(apic->lock);
269
270     v3_delete_mem_region(dev->vm, old_reg);
271
272     apic->base_addr = src.value;
273
274     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) {
275         PrintError("Could not hook new APIC Base address\n");
276         v3_unlock(apic->lock);
277         return -1;
278     }
279
280     v3_unlock(apic->lock);
281     return 0;
282 }
283
284
285 // irq_num is the bit offset into a 256 bit buffer...
286 static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
287     int major_offset = (irq_num & ~0x00000007) >> 3;
288     int minor_offset = irq_num & 0x00000007;
289     uchar_t * req_location = apic->int_req_reg + major_offset;
290     uchar_t * en_location = apic->int_en_reg + major_offset;
291     uchar_t flag = 0x1 << minor_offset;
292
293     if (irq_num <= 15) {
294         PrintError("Attempting to raise an invalid interrupt: %d\n", irq_num);
295         return -1;
296     }
297
298     PrintDebug("Raising APIC IRQ %d\n", irq_num);
299
300     if (*req_location & flag) {
301         //V3_Print("Interrupts coallescing\n");
302     }
303
304     if (*en_location & flag) {
305         *req_location |= flag;
306     } else {
307         PrintDebug("Interrupt  not enabled... %.2x\n", *en_location);
308         return 0;
309     }
310
311     return 0;
312 }
313
314
315
316 static int get_highest_isr(struct apic_state * apic) {
317     int i = 0, j = 0;
318
319     // We iterate backwards to find the highest priority
320     for (i = 31; i >= 0; i--) {
321         uchar_t  * svc_major = apic->int_svc_reg + i;
322     
323         if ((*svc_major) & 0xff) {
324             for (j = 7; j >= 0; j--) {
325                 uchar_t flag = 0x1 << j;
326                 if ((*svc_major) & flag) {
327                     return ((i * 8) + j);
328                 }
329             }
330         }
331     }
332
333     return -1;
334 }
335  
336
337
338 static int get_highest_irr(struct apic_state * apic) {
339     int i = 0, j = 0;
340
341     // We iterate backwards to find the highest priority
342     for (i = 31; i >= 0; i--) {
343         uchar_t  * req_major = apic->int_req_reg + i;
344     
345         if ((*req_major) & 0xff) {
346             for (j = 7; j >= 0; j--) {
347                 uchar_t flag = 0x1 << j;
348                 if ((*req_major) & flag) {
349                     return ((i * 8) + j);
350                 }
351             }
352         }
353     }
354
355     return -1;
356 }
357  
358
359
360
361 static int apic_do_eoi(struct apic_state * apic) {
362     int isr_irq = get_highest_isr(apic);
363
364     if (isr_irq != -1) {
365         int major_offset = (isr_irq & ~0x00000007) >> 3;
366         int minor_offset = isr_irq & 0x00000007;
367         uchar_t flag = 0x1 << minor_offset;
368         uchar_t * svc_location = apic->int_svc_reg + major_offset;
369         
370         PrintDebug("Received APIC EOI for IRQ %d\n", isr_irq);
371         
372         *svc_location &= ~flag;
373
374 #ifdef CONFIG_CRAY_XT
375         
376         if ((isr_irq == 238) || 
377             (isr_irq == 239)) {
378             PrintError("Acking IRQ %d\n", isr_irq);
379         }
380         
381         if (isr_irq == 238) {
382             V3_ACK_IRQ(238);
383         }
384 #endif
385     } else {
386         //PrintError("Spurious EOI...\n");
387     }
388         
389     return 0;
390 }
391  
392
393 static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_type) {
394     uint32_t vec_num = 0;
395     uint32_t del_mode = 0;
396     int masked = 0;
397
398
399     switch (int_type) {
400         case APIC_TMR_INT:
401             vec_num = apic->tmr_vec_tbl.vec;
402             del_mode = APIC_FIXED_DELIVERY;
403             masked = apic->tmr_vec_tbl.mask;
404             break;
405         case APIC_THERM_INT:
406             vec_num = apic->therm_loc_vec_tbl.vec;
407             del_mode = apic->therm_loc_vec_tbl.msg_type;
408             masked = apic->therm_loc_vec_tbl.mask;
409             break;
410         case APIC_PERF_INT:
411             vec_num = apic->perf_ctr_loc_vec_tbl.vec;
412             del_mode = apic->perf_ctr_loc_vec_tbl.msg_type;
413             masked = apic->perf_ctr_loc_vec_tbl.mask;
414             break;
415         case APIC_LINT0_INT:
416             vec_num = apic->lint0_vec_tbl.vec;
417             del_mode = apic->lint0_vec_tbl.msg_type;
418             masked = apic->lint0_vec_tbl.mask;
419             break;
420         case APIC_LINT1_INT:
421             vec_num = apic->lint1_vec_tbl.vec;
422             del_mode = apic->lint1_vec_tbl.msg_type;
423             masked = apic->lint1_vec_tbl.mask;
424             break;
425         case APIC_ERR_INT:
426             vec_num = apic->err_vec_tbl.vec;
427             del_mode = APIC_FIXED_DELIVERY;
428             masked = apic->err_vec_tbl.mask;
429             break;
430         default:
431             PrintError("Invalid APIC interrupt type\n");
432             return -1;
433     }
434
435     // interrupt is masked, don't send
436     if (masked == 1) {
437         PrintDebug("Inerrupt is masked\n");
438         return 0;
439     }
440
441     if (del_mode == APIC_FIXED_DELIVERY) {
442         //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
443         return activate_apic_irq(apic, vec_num);
444     } else {
445         PrintError("Unhandled Delivery Mode\n");
446         return -1;
447     }
448 }
449
450
451 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
452     struct apic_state * apic = (struct apic_state *)priv_data;
453     addr_t reg_addr  = guest_addr - apic->base_addr;
454     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
455     uint32_t val = 0;
456
457
458     PrintDebug("Read apic address space (%p)\n", 
459                (void *)guest_addr);
460
461     if (msr->apic_enable == 0) {
462         PrintError("Write to APIC address space with disabled APIC\n");
463         return -1;
464     }
465
466
467     /* Because "May not be supported" doesn't matter to Linux developers... */
468     /*   if (length != 4) { */
469     /*     PrintError("Invalid apic read length (%d)\n", length); */
470     /*     return -1; */
471     /*   } */
472
473     switch (reg_addr & ~0x3) {
474         case EOI_OFFSET:
475             // Well, only an idiot would read from a architectural write only register
476             // Oh, Hello Linux.
477             //    PrintError("Attempting to read from write only register\n");
478             //    return -1;
479             break;
480
481             // data registers
482         case APIC_ID_OFFSET:
483             val = apic->lapic_id.val;
484             break;
485         case APIC_VERSION_OFFSET:
486             val = apic->apic_ver.val;
487             break;
488         case TPR_OFFSET:
489             val = apic->task_prio.val;
490             break;
491         case APR_OFFSET:
492             val = apic->arb_prio.val;
493             break;
494         case PPR_OFFSET:
495             val = apic->proc_prio.val;
496             break;
497         case REMOTE_READ_OFFSET:
498             val = apic->rem_rd_data;
499             break;
500         case LDR_OFFSET:
501             val = apic->log_dst.val;
502             break;
503         case DFR_OFFSET:
504             val = apic->dst_fmt.val;
505             break;
506         case SPURIOUS_INT_VEC_OFFSET:
507             val = apic->spurious_int.val;
508             break;
509         case ESR_OFFSET:
510             val = apic->err_status.val;
511             break;
512         case TMR_LOC_VEC_TBL_OFFSET:
513             val = apic->tmr_vec_tbl.val;
514             break;
515         case LINT0_VEC_TBL_OFFSET:
516             val = apic->lint0_vec_tbl.val;
517             break;
518         case LINT1_VEC_TBL_OFFSET:
519             val = apic->lint1_vec_tbl.val;
520             break;
521         case ERR_VEC_TBL_OFFSET:
522             val = apic->err_vec_tbl.val;
523             break;
524         case TMR_INIT_CNT_OFFSET:
525             val = apic->tmr_init_cnt;
526             break;
527         case TMR_DIV_CFG_OFFSET:
528             val = apic->tmr_div_cfg.val;
529             break;
530
531         case IER_OFFSET0:
532             val = *(uint32_t *)(apic->int_en_reg);
533             break;
534         case IER_OFFSET1:
535             val = *(uint32_t *)(apic->int_en_reg + 4);
536             break;
537         case IER_OFFSET2:
538             val = *(uint32_t *)(apic->int_en_reg + 8);
539             break;
540         case IER_OFFSET3:
541             val = *(uint32_t *)(apic->int_en_reg + 12);
542             break;
543         case IER_OFFSET4:
544             val = *(uint32_t *)(apic->int_en_reg + 16);
545             break;
546         case IER_OFFSET5:
547             val = *(uint32_t *)(apic->int_en_reg + 20);
548             break;
549         case IER_OFFSET6:
550             val = *(uint32_t *)(apic->int_en_reg + 24);
551             break;
552         case IER_OFFSET7:
553             val = *(uint32_t *)(apic->int_en_reg + 28);
554             break;
555
556         case ISR_OFFSET0:
557             val = *(uint32_t *)(apic->int_svc_reg);
558             break;
559         case ISR_OFFSET1:
560             val = *(uint32_t *)(apic->int_svc_reg + 4);
561             break;
562         case ISR_OFFSET2:
563             val = *(uint32_t *)(apic->int_svc_reg + 8);
564             break;
565         case ISR_OFFSET3:
566             val = *(uint32_t *)(apic->int_svc_reg + 12);
567             break;
568         case ISR_OFFSET4:
569             val = *(uint32_t *)(apic->int_svc_reg + 16);
570             break;
571         case ISR_OFFSET5:
572             val = *(uint32_t *)(apic->int_svc_reg + 20);
573             break;
574         case ISR_OFFSET6:
575             val = *(uint32_t *)(apic->int_svc_reg + 24);
576             break;
577         case ISR_OFFSET7:
578             val = *(uint32_t *)(apic->int_svc_reg + 28);
579             break;
580    
581         case TRIG_OFFSET0:
582             val = *(uint32_t *)(apic->trig_mode_reg);
583             break;
584         case TRIG_OFFSET1:
585             val = *(uint32_t *)(apic->trig_mode_reg + 4);
586             break;
587         case TRIG_OFFSET2:
588             val = *(uint32_t *)(apic->trig_mode_reg + 8);
589             break;
590         case TRIG_OFFSET3:
591             val = *(uint32_t *)(apic->trig_mode_reg + 12);
592             break;
593         case TRIG_OFFSET4:
594             val = *(uint32_t *)(apic->trig_mode_reg + 16);
595             break;
596         case TRIG_OFFSET5:
597             val = *(uint32_t *)(apic->trig_mode_reg + 20);
598             break;
599         case TRIG_OFFSET6:
600             val = *(uint32_t *)(apic->trig_mode_reg + 24);
601             break;
602         case TRIG_OFFSET7:
603             val = *(uint32_t *)(apic->trig_mode_reg + 28);
604             break;
605
606         case IRR_OFFSET0:
607             val = *(uint32_t *)(apic->int_req_reg);
608             break;
609         case IRR_OFFSET1:
610             val = *(uint32_t *)(apic->int_req_reg + 4);
611             break;
612         case IRR_OFFSET2:
613             val = *(uint32_t *)(apic->int_req_reg + 8);
614             break;
615         case IRR_OFFSET3:
616             val = *(uint32_t *)(apic->int_req_reg + 12);
617             break;
618         case IRR_OFFSET4:
619             val = *(uint32_t *)(apic->int_req_reg + 16);
620             break;
621         case IRR_OFFSET5:
622             val = *(uint32_t *)(apic->int_req_reg + 20);
623             break;
624         case IRR_OFFSET6:
625             val = *(uint32_t *)(apic->int_req_reg + 24);
626             break;
627         case IRR_OFFSET7:
628             val = *(uint32_t *)(apic->int_req_reg + 28);
629             break;
630         case TMR_CUR_CNT_OFFSET:
631             val = apic->tmr_cur_cnt;
632             break;
633
634             // We are not going to implement these....
635         case THERM_LOC_VEC_TBL_OFFSET:
636             val = apic->therm_loc_vec_tbl.val;
637             break;
638         case PERF_CTR_LOC_VEC_TBL_OFFSET:
639             val = apic->perf_ctr_loc_vec_tbl.val;
640             break;
641
642  
643
644             // handled registers
645         case INT_CMD_LO_OFFSET:    
646             val = apic->int_cmd.lo;
647             break;
648         case INT_CMD_HI_OFFSET:
649             val = apic->int_cmd.hi;
650             break;
651
652             // handle current timer count
653
654             // Unhandled Registers
655         case EXT_INT_LOC_VEC_TBL_OFFSET0:
656             val = apic->ext_intr_vec_tbl[0].val;
657             break;
658         case EXT_INT_LOC_VEC_TBL_OFFSET1:
659             val = apic->ext_intr_vec_tbl[1].val;
660             break;
661         case EXT_INT_LOC_VEC_TBL_OFFSET2:
662             val = apic->ext_intr_vec_tbl[2].val;
663             break;
664         case EXT_INT_LOC_VEC_TBL_OFFSET3:
665             val = apic->ext_intr_vec_tbl[3].val;
666             break;
667     
668
669         case EXT_APIC_FEATURE_OFFSET:
670         case EXT_APIC_CMD_OFFSET:
671         case SEOI_OFFSET:
672
673         default:
674             PrintError("Read from Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
675             return -1;
676     }
677
678
679     if (length == 1) {
680         uint_t byte_addr = reg_addr & 0x3;
681         uint8_t * val_ptr = (uint8_t *)dst;
682     
683         *val_ptr = *(((uint8_t *)&val) + byte_addr);
684
685     } else if ((length == 2) && 
686                ((reg_addr & 0x3) == 0x3)) {
687         uint_t byte_addr = reg_addr & 0x3;
688         uint16_t * val_ptr = (uint16_t *)dst;
689         *val_ptr = *(((uint16_t *)&val) + byte_addr);
690
691     } else if (length == 4) {
692         uint32_t * val_ptr = (uint32_t *)dst;
693         *val_ptr = val;
694
695     } else {
696         PrintError("Invalid apic read length (%d)\n", length);
697         return -1;
698     }
699
700     PrintDebug("Read finished (val=%x)\n", *(uint32_t *)dst);
701
702     return length;
703 }
704
705
706 /**
707  *
708  */
709 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data) {
710     struct apic_state * apic = (struct apic_state *)priv_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             // ICC???
865             v3_icc_send_irq(apic->icc_bus, apic->int_cmd.dst, apic->int_cmd.val);
866             break;
867         case INT_CMD_HI_OFFSET:
868             apic->int_cmd.hi = op_val;
869             break;
870             // Unhandled Registers
871
872         case EXT_APIC_CMD_OFFSET:
873         case SEOI_OFFSET:
874         default:
875             PrintError("Write to Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
876             return -1;
877     }
878
879     PrintDebug("Write finished\n");
880
881     return length;
882 }
883
884
885
886 /* Interrupt Controller Functions */
887
888 // returns 1 if an interrupt is pending, 0 otherwise
889 static int apic_intr_pending(struct guest_info * info, void * private_data) {
890     struct apic_state * apic = (struct apic_state *)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 apic_state * apic = (struct apic_state *)private_data;
904     int req_irq = get_highest_irr(apic);
905     int svc_irq = get_highest_isr(apic);
906
907     if (svc_irq == -1) {
908         return req_irq;
909     } else if (svc_irq < req_irq) {
910         return req_irq;
911     }
912
913     return -1;
914 }
915
916
917 static int apic_raise_intr(struct guest_info * info, int irq, void * private_data) {
918   struct apic_state * apic = (struct apic_state *)private_data;
919
920   return activate_apic_irq(apic, irq);
921 }
922
923
924
925 static int apic_begin_irq(struct guest_info * info, void * private_data, int irq) {
926     struct apic_state * apic = (struct apic_state *)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
937
938     return 0;
939 }
940
941
942
943
944 /* Timer Functions */
945 static void apic_update_time(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data) {
946     struct apic_state * apic = (struct apic_state *)priv_data;
947     // The 32 bit GCC runtime is a pile of shit
948 #ifdef __V3_64BIT__
949     uint64_t tmr_ticks = 0;
950 #else 
951     uint32_t tmr_ticks = 0;
952 #endif
953
954     uchar_t tmr_div = *(uchar_t *)&(apic->tmr_div_cfg.val);
955     uint_t shift_num = 0;
956
957
958     // Check whether this is true:
959     //   -> If the Init count is zero then the timer is disabled
960     //      and doesn't just blitz interrupts to the CPU
961     if ((apic->tmr_init_cnt == 0) || 
962         ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
963           (apic->tmr_cur_cnt == 0))) {
964         //PrintDebug("APIC timer not yet initialized\n");
965         return;
966     }
967
968
969     switch (tmr_div) {
970         case APIC_TMR_DIV1:
971             shift_num = 0;
972             break;
973         case APIC_TMR_DIV2:
974             shift_num = 1;
975             break;
976         case APIC_TMR_DIV4:
977             shift_num = 2;
978             break;
979         case APIC_TMR_DIV8:
980             shift_num = 3;
981             break;
982         case APIC_TMR_DIV16:
983             shift_num = 4;
984             break;
985         case APIC_TMR_DIV32:
986             shift_num = 5;
987             break;
988         case APIC_TMR_DIV64:
989             shift_num = 6;
990             break;
991         case APIC_TMR_DIV128:
992             shift_num = 7;
993             break;
994         default:
995             PrintError("Invalid Timer Divider configuration\n");
996             return;
997     }
998
999     tmr_ticks = cpu_cycles >> shift_num;
1000     //    PrintDebug("Timer Ticks: %p\n", (void *)tmr_ticks);
1001
1002     if (tmr_ticks < apic->tmr_cur_cnt) {
1003         apic->tmr_cur_cnt -= tmr_ticks;
1004     } else {
1005         tmr_ticks -= apic->tmr_cur_cnt;
1006         apic->tmr_cur_cnt = 0;
1007
1008         // raise irq
1009         PrintDebug("Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n", 
1010                    apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
1011
1012         if (apic_intr_pending(info, priv_data)) {
1013             PrintDebug("Overriding pending IRQ %d\n", apic_get_intr_number(info, priv_data));
1014         }
1015
1016         if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
1017             PrintError("Could not raise Timer interrupt\n");
1018         }
1019     
1020         if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
1021             tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
1022             apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
1023         }
1024     }
1025
1026
1027 }
1028
1029
1030 static struct intr_ctrl_ops intr_ops = {
1031     .intr_pending = apic_intr_pending,
1032     .get_intr_number = apic_get_intr_number,
1033     .begin_irq = apic_begin_irq,
1034 };
1035
1036
1037 static struct vm_timer_ops timer_ops = {
1038     .update_time = apic_update_time,
1039 };
1040
1041
1042
1043
1044 static int apic_free(struct vm_device * dev) {
1045     //   struct apic_state * apic = (struct apic_state *)dev->private_data;
1046
1047     v3_unhook_msr(dev->vm, BASE_ADDR_MSR);
1048
1049     return 0;
1050 }
1051
1052
1053 static struct v3_device_ops dev_ops = {
1054     .free = apic_free,
1055     .reset = NULL,
1056     .start = NULL,
1057     .stop = NULL,
1058 };
1059
1060
1061
1062 static struct v3_icc_ops icc_ops = {
1063     .raise_intr = apic_raise_intr,
1064 };
1065
1066
1067
1068 static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1069     PrintDebug("Creating an APIC for each core\n");
1070     char * name = v3_cfg_val(cfg, "name");
1071     char * icc_name = v3_cfg_val(cfg,"bus");
1072     struct vm_device * icc = v3_find_dev(vm, icc_name);
1073     int i;
1074
1075     if (!icc) {
1076         PrintError("Cannot find ICC Bus (%s)\n", icc_name);
1077         return -1;
1078     }
1079
1080     // We allocate one apic per core
1081     // APICs are accessed via index which correlates with the core's cpu_id 
1082     // 0..num_cores-1   at num_cores is the ioapic (one only)
1083     struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state) * vm->num_cores);
1084
1085     struct vm_device * dev = v3_allocate_device(name, &dev_ops, apic);
1086
1087     if (v3_attach_device(vm, dev) == -1) {
1088         PrintError("Could not attach device %s\n", name);
1089         return -1;
1090     }
1091
1092     
1093     for (i = 0; i < vm->num_cores; i++) {
1094         struct guest_info * core = &(vm->cores[i]);
1095
1096         init_apic_state(&(apic[i]),i);
1097
1098         v3_register_intr_controller(core, &intr_ops, &(apic[i]));
1099
1100         v3_add_timer(core, &timer_ops, &(apic[i]));
1101
1102         v3_hook_full_mem(vm, core->cpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, &(apic[i]));
1103
1104         v3_icc_register_apic(core, icc, i, &icc_ops, &(apic[i]));
1105
1106     }
1107
1108
1109
1110     v3_hook_msr(vm, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev);
1111
1112     return 0;
1113 }
1114
1115
1116
1117 device_register("LAPIC", apic_init)