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.


Fixed ioapic bug that caused interrupt routing entries to be stored incorrectly and...
[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             PrintDebug("apic %u: core %u: setting log_dst.val to 0x%x\n",
814                        apic->lapic_id.val, core->cpu_id, op_val);
815             apic->log_dst.val = op_val;
816             break;
817         case DFR_OFFSET:
818             apic->dst_fmt.val = op_val;
819             break;
820         case SPURIOUS_INT_VEC_OFFSET:
821             apic->spurious_int.val = op_val;
822             break;
823         case ESR_OFFSET:
824             apic->err_status.val = op_val;
825             break;
826         case TMR_LOC_VEC_TBL_OFFSET:
827             apic->tmr_vec_tbl.val = op_val;
828             break;
829         case THERM_LOC_VEC_TBL_OFFSET:
830             apic->therm_loc_vec_tbl.val = op_val;
831             break;
832         case PERF_CTR_LOC_VEC_TBL_OFFSET:
833             apic->perf_ctr_loc_vec_tbl.val = op_val;
834             break;
835         case LINT0_VEC_TBL_OFFSET:
836             apic->lint0_vec_tbl.val = op_val;
837             break;
838         case LINT1_VEC_TBL_OFFSET:
839             apic->lint1_vec_tbl.val = op_val;
840             break;
841         case ERR_VEC_TBL_OFFSET:
842             apic->err_vec_tbl.val = op_val;
843             break;
844         case TMR_INIT_CNT_OFFSET:
845             apic->tmr_init_cnt = op_val;
846             apic->tmr_cur_cnt = op_val;
847             break;
848         case TMR_CUR_CNT_OFFSET:
849             apic->tmr_cur_cnt = op_val;
850             break;
851         case TMR_DIV_CFG_OFFSET:
852             apic->tmr_div_cfg.val = op_val;
853             break;
854
855
856             // Enable mask (256 bits)
857         case IER_OFFSET0:
858             *(uint32_t *)(apic->int_en_reg) = op_val;
859             break;
860         case IER_OFFSET1:
861             *(uint32_t *)(apic->int_en_reg + 4) = op_val;
862             break;
863         case IER_OFFSET2:
864             *(uint32_t *)(apic->int_en_reg + 8) = op_val;
865             break;
866         case IER_OFFSET3:
867             *(uint32_t *)(apic->int_en_reg + 12) = op_val;
868             break;
869         case IER_OFFSET4:
870             *(uint32_t *)(apic->int_en_reg + 16) = op_val;
871             break;
872         case IER_OFFSET5:
873             *(uint32_t *)(apic->int_en_reg + 20) = op_val;
874             break;
875         case IER_OFFSET6:
876             *(uint32_t *)(apic->int_en_reg + 24) = op_val;
877             break;
878         case IER_OFFSET7:
879             *(uint32_t *)(apic->int_en_reg + 28) = op_val;
880             break;
881
882         case EXT_INT_LOC_VEC_TBL_OFFSET0:
883             apic->ext_intr_vec_tbl[0].val = op_val;
884             break;
885         case EXT_INT_LOC_VEC_TBL_OFFSET1:
886             apic->ext_intr_vec_tbl[1].val = op_val;
887             break;
888         case EXT_INT_LOC_VEC_TBL_OFFSET2:
889             apic->ext_intr_vec_tbl[2].val = op_val;
890             break;
891         case EXT_INT_LOC_VEC_TBL_OFFSET3:
892             apic->ext_intr_vec_tbl[3].val = op_val;
893             break;
894
895
896             // Action Registers
897         case EOI_OFFSET:
898             // do eoi
899             apic_do_eoi(apic);
900             break;
901
902         case INT_CMD_LO_OFFSET:
903             apic->int_cmd.lo = op_val;
904
905             // ICC???
906             PrintDebug("apic %u: core %u: sending cmd 0x%llx to apic %u\n", 
907                        apic->lapic_id.val, core->cpu_id,
908                        apic->int_cmd.val, apic->int_cmd.dst);
909             if (v3_icc_send_ipi(apic->icc_bus, apic->lapic_id.val, apic->int_cmd.val,apic->dst_fmt.val,0)==-1) { 
910                 return -1;
911             }
912             break;
913
914         case INT_CMD_HI_OFFSET:
915             apic->int_cmd.hi = op_val;
916             break;
917
918
919         // Unhandled Registers
920         case EXT_APIC_CMD_OFFSET:
921         case SEOI_OFFSET:
922         default:
923             PrintError("apic %u: core %u: Write to Unhandled APIC Register: %x (ignored)\n", 
924                        apic->lapic_id.val, core->cpu_id, (uint32_t)reg_addr);
925
926             return -1;
927     }
928
929     PrintDebug("apic %u: core %u: Write finished\n", apic->lapic_id.val, core->cpu_id);
930
931     return length;
932 }
933
934
935
936 /* Interrupt Controller Functions */
937
938 // returns 1 if an interrupt is pending, 0 otherwise
939 static int apic_intr_pending(struct guest_info * info, void * private_data) {
940     struct apic_state * apic = (struct apic_state *)private_data;
941     int req_irq = get_highest_irr(apic);
942     int svc_irq = get_highest_isr(apic);
943
944     //    PrintDebug("apic %u: core %u: req_irq=%d, svc_irq=%d\n",apic->lapic_id.val,info->cpu_id,req_irq,svc_irq);
945
946     if ((req_irq >= 0) && 
947         (req_irq > svc_irq)) {
948         return 1;
949     }
950
951     return 0;
952 }
953
954 static int apic_get_intr_number(struct guest_info * info, void * private_data) {
955     struct apic_state * apic = (struct apic_state *)private_data;
956     int req_irq = get_highest_irr(apic);
957     int svc_irq = get_highest_isr(apic);
958
959     if (svc_irq == -1) {
960         return req_irq;
961     } else if (svc_irq < req_irq) {
962         return req_irq;
963     }
964
965     return -1;
966 }
967
968
969 static int apic_raise_intr(struct guest_info * info, int irq, void * private_data) {
970   struct apic_state * apic = (struct apic_state *)private_data;
971
972   return activate_apic_irq(apic, irq);
973 }
974
975
976
977 static int apic_begin_irq(struct guest_info * info, void * private_data, int irq) {
978     struct apic_state * apic = (struct apic_state *)private_data;
979     int major_offset = (irq & ~0x00000007) >> 3;
980     int minor_offset = irq & 0x00000007;
981     uint8_t * req_location = apic->int_req_reg + major_offset;
982     uint8_t * svc_location = apic->int_svc_reg + major_offset;
983     uint8_t flag = 0x01 << minor_offset;
984
985     if (*req_location & flag) {
986         // we will only pay attention to a begin irq if we
987         // know that we initiated it!
988         *svc_location |= flag;
989         *req_location &= ~flag;
990     } else {
991         // do nothing... 
992         PrintDebug("apic %u: core %u: begin irq for %d ignored since I don't own it\n",
993                    apic->lapic_id.val, info->cpu_id, irq);
994     }
995
996     return 0;
997 }
998
999
1000
1001
1002 /* Timer Functions */
1003 static void apic_update_time(struct guest_info * info, 
1004                              uint64_t cpu_cycles, uint64_t cpu_freq, 
1005                              void * priv_data) {
1006     struct apic_state * apic = (struct apic_state *)(priv_data);
1007     // The 32 bit GCC runtime is a pile of shit
1008 #ifdef __V3_64BIT__
1009     uint64_t tmr_ticks = 0;
1010 #else 
1011     uint32_t tmr_ticks = 0;
1012 #endif
1013
1014     uint8_t tmr_div = *(uint8_t *)&(apic->tmr_div_cfg.val);
1015     uint_t shift_num = 0;
1016
1017
1018     // Check whether this is true:
1019     //   -> If the Init count is zero then the timer is disabled
1020     //      and doesn't just blitz interrupts to the CPU
1021     if ((apic->tmr_init_cnt == 0) || 
1022         ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
1023           (apic->tmr_cur_cnt == 0))) {
1024         //PrintDebug("apic %u: core %u: APIC timer not yet initialized\n",apic->lapic_id.val,info->cpu_id);
1025         return;
1026     }
1027
1028
1029     switch (tmr_div) {
1030         case APIC_TMR_DIV1:
1031             shift_num = 0;
1032             break;
1033         case APIC_TMR_DIV2:
1034             shift_num = 1;
1035             break;
1036         case APIC_TMR_DIV4:
1037             shift_num = 2;
1038             break;
1039         case APIC_TMR_DIV8:
1040             shift_num = 3;
1041             break;
1042         case APIC_TMR_DIV16:
1043             shift_num = 4;
1044             break;
1045         case APIC_TMR_DIV32:
1046             shift_num = 5;
1047             break;
1048         case APIC_TMR_DIV64:
1049             shift_num = 6;
1050             break;
1051         case APIC_TMR_DIV128:
1052             shift_num = 7;
1053             break;
1054         default:
1055             PrintError("apic %u: core %u: Invalid Timer Divider configuration\n",
1056                        apic->lapic_id.val, info->cpu_id);
1057             return;
1058     }
1059
1060     tmr_ticks = cpu_cycles >> shift_num;
1061     //    PrintDebug("Timer Ticks: %p\n", (void *)tmr_ticks);
1062
1063     if (tmr_ticks < apic->tmr_cur_cnt) {
1064         apic->tmr_cur_cnt -= tmr_ticks;
1065     } else {
1066         tmr_ticks -= apic->tmr_cur_cnt;
1067         apic->tmr_cur_cnt = 0;
1068
1069         // raise irq
1070         PrintDebug("apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n",
1071                    apic->lapic_id.val, info->cpu_id,
1072                    apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
1073
1074         if (apic_intr_pending(info, priv_data)) {
1075             PrintDebug("apic %u: core %u: Overriding pending IRQ %d\n", 
1076                        apic->lapic_id.val, info->cpu_id, 
1077                        apic_get_intr_number(info, priv_data));
1078         }
1079
1080         if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
1081             PrintError("apic %u: core %u: Could not raise Timer interrupt\n",
1082                        apic->lapic_id.val, info->cpu_id);
1083         }
1084     
1085         if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
1086             tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
1087             apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
1088         }
1089     }
1090
1091
1092 }
1093
1094
1095 static struct intr_ctrl_ops intr_ops = {
1096     .intr_pending = apic_intr_pending,
1097     .get_intr_number = apic_get_intr_number,
1098     .begin_irq = apic_begin_irq,
1099 };
1100
1101
1102 static struct vm_timer_ops timer_ops = {
1103     .update_time = apic_update_time,
1104 };
1105
1106
1107
1108
1109 static int apic_free(struct vm_device * dev) {
1110
1111     /* TODO: This should crosscall to force an unhook on each CPU */
1112
1113     //   struct apic_state * apic = (struct apic_state *)dev->private_data;
1114
1115     v3_unhook_msr(dev->vm, BASE_ADDR_MSR);
1116
1117     return 0;
1118 }
1119
1120
1121 static struct v3_device_ops dev_ops = {
1122     .free = apic_free,
1123     .reset = NULL,
1124     .start = NULL,
1125     .stop = NULL,
1126 };
1127
1128
1129
1130 static int apic_should_deliver_flat(struct guest_info * core, uint8_t mda, void * private_data)
1131 {
1132   struct apic_state * apic = (struct apic_state *)private_data;
1133
1134   if (mda==0xff ||                         // broadcast or
1135       (apic->log_dst.dst_log_id & mda)) {  // I am in the set 
1136         PrintDebug("apic %u core %u: accepting flat IRQ (mda 0x%x == log_dst 0x%x)\n",
1137                    apic->lapic_id.val, core->cpu_id, mda, apic->log_dst.dst_log_id);
1138       return 1;
1139   } else {
1140         PrintDebug("apic %u core %u: rejecting flat IRQ (mda 0x%x != log_dst 0x%x)\n",
1141                    apic->lapic_id.val, core->cpu_id, mda, apic->log_dst.dst_log_id);
1142       return 0;
1143   }
1144 }
1145
1146 static int apic_should_deliver_cluster(struct guest_info * core, uint8_t mda, void * private_data)
1147 {
1148   struct apic_state * apic = (struct apic_state *)private_data;
1149
1150   if (mda==0xff ||                                                 // broadcast or
1151       ( ((mda & 0xf0) == (apic->log_dst.dst_log_id & 0xf0)) &&     // (I am in the cluster and
1152         ((mda & 0x0f)  & (apic->log_dst.dst_log_id & 0x0f)) ) ) {  //  I am in the set)
1153         PrintDebug("apic %u core %u: accepting clustered IRQ (mda 0x%x == log_dst 0x%x)\n",
1154                    apic->lapic_id.val, core->cpu_id, mda, apic->log_dst.dst_log_id);
1155                    
1156       return 1;
1157   } else {
1158         PrintDebug("apic %u core %u: rejecting clustered IRQ (mda 0x%x != log_dst 0x%x)\n",
1159                    apic->lapic_id.val, core->cpu_id, mda, apic->log_dst.dst_log_id);
1160       return 0;
1161   }
1162 }
1163
1164 static struct v3_icc_ops icc_ops = {
1165     .raise_intr = apic_raise_intr,
1166     .should_deliver_flat = apic_should_deliver_flat,
1167     .should_deliver_cluster = apic_should_deliver_cluster,
1168 };
1169
1170
1171
1172 static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1173     PrintDebug("apic: creating an APIC for each core\n");
1174     char * dev_id = v3_cfg_val(cfg, "ID");
1175     char * icc_bus_id = v3_cfg_val(cfg, "bus");
1176     struct vm_device * icc = v3_find_dev(vm, icc_bus_id);
1177     int i;
1178
1179     if (!icc) {
1180         PrintError("apic: Cannot find ICC Bus (%s)\n", icc_bus_id);
1181         return -1;
1182     }
1183
1184     // We allocate one apic per core
1185     // APICs are accessed via index which correlates with the core's cpu_id 
1186     // 0..num_cores-1   at num_cores is the ioapic (one only)
1187     struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state) * vm->num_cores);
1188
1189     struct vm_device * dev = v3_allocate_device(dev_id, &dev_ops, apic);
1190
1191     if (v3_attach_device(vm, dev) == -1) {
1192         PrintError("apic: Could not attach device %s\n", dev_id);
1193         return -1;
1194     }
1195
1196     
1197     for (i = 0; i < vm->num_cores; i++) {
1198         struct guest_info * core = &(vm->cores[i]);
1199
1200         init_apic_state(&(apic[i]),i,icc);
1201
1202         v3_register_intr_controller(core, &intr_ops, &(apic[i]));
1203
1204         v3_add_timer(core, &timer_ops, &(apic[i]));
1205
1206         v3_hook_full_mem(vm, core->cpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, &(apic[i]));
1207
1208         v3_icc_register_apic(core, icc, i, &icc_ops, &(apic[i]));
1209
1210         PrintDebug("apic %u: (setup device): done, my id is %u\n", i, apic[i].lapic_id.val);
1211
1212     }
1213
1214     for (i = 0; i < vm->num_cores; i++) {
1215         PrintDebug("apic: sanity check: apic %u (at %p) has id %u and msr value %llx\n",
1216                    i, &(apic[i]), apic[i].lapic_id.val, apic[i].base_addr_msr.value);
1217     }
1218
1219     PrintDebug("apic: priv_data is at %p\n", apic);
1220
1221     v3_hook_msr(vm, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev);
1222
1223     return 0;
1224 }
1225
1226
1227
1228 device_register("LAPIC", apic_init)