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.


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