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.


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