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.


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