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.


Partially functional icc_bus (works for UP)
[palacios.git] / palacios / src / devices / apic.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21 #include <devices/apic.h>
22 #include <devices/apic_regs.h>
23 #include <devices/icc_bus.h>
24 #include <palacios/vmm.h>
25 #include <palacios/vmm_msr.h>
26 #include <palacios/vmm_sprintf.h>
27 #include <palacios/vm_guest.h>
28
29
30 #ifndef CONFIG_DEBUG_APIC
31 #undef PrintDebug
32 #define PrintDebug(fmt, args...)
33 #endif
34
35
36 typedef enum { APIC_TMR_INT, APIC_THERM_INT, APIC_PERF_INT, 
37                APIC_LINT0_INT, APIC_LINT1_INT, APIC_ERR_INT } apic_irq_type_t;
38
39 #define APIC_FIXED_DELIVERY  0x0
40 #define APIC_SMI_DELIVERY    0x2
41 #define APIC_NMI_DELIVERY    0x4
42 #define APIC_INIT_DELIVERY   0x5
43 #define APIC_EXTINT_DELIVERY 0x7
44
45
46 #define BASE_ADDR_MSR 0x0000001B
47 #define DEFAULT_BASE_ADDR 0xfee00000
48
49 #define APIC_ID_OFFSET                    0x020
50 #define APIC_VERSION_OFFSET               0x030
51 #define TPR_OFFSET                        0x080
52 #define APR_OFFSET                        0x090
53 #define PPR_OFFSET                        0x0a0
54 #define EOI_OFFSET                        0x0b0
55 #define REMOTE_READ_OFFSET                0x0c0
56 #define LDR_OFFSET                        0x0d0
57 #define DFR_OFFSET                        0x0e0
58 #define SPURIOUS_INT_VEC_OFFSET           0x0f0
59
60 #define ISR_OFFSET0                       0x100   // 0x100 - 0x170
61 #define ISR_OFFSET1                       0x110   // 0x100 - 0x170
62 #define ISR_OFFSET2                       0x120   // 0x100 - 0x170
63 #define ISR_OFFSET3                       0x130   // 0x100 - 0x170
64 #define ISR_OFFSET4                       0x140   // 0x100 - 0x170
65 #define ISR_OFFSET5                       0x150   // 0x100 - 0x170
66 #define ISR_OFFSET6                       0x160   // 0x100 - 0x170
67 #define ISR_OFFSET7                       0x170   // 0x100 - 0x170
68
69 #define TRIG_OFFSET0                      0x180   // 0x180 - 0x1f0
70 #define TRIG_OFFSET1                      0x190   // 0x180 - 0x1f0
71 #define TRIG_OFFSET2                      0x1a0   // 0x180 - 0x1f0
72 #define TRIG_OFFSET3                      0x1b0   // 0x180 - 0x1f0
73 #define TRIG_OFFSET4                      0x1c0   // 0x180 - 0x1f0
74 #define TRIG_OFFSET5                      0x1d0   // 0x180 - 0x1f0
75 #define TRIG_OFFSET6                      0x1e0   // 0x180 - 0x1f0
76 #define TRIG_OFFSET7                      0x1f0   // 0x180 - 0x1f0
77
78
79 #define IRR_OFFSET0                       0x200   // 0x200 - 0x270
80 #define IRR_OFFSET1                       0x210   // 0x200 - 0x270
81 #define IRR_OFFSET2                       0x220   // 0x200 - 0x270
82 #define IRR_OFFSET3                       0x230   // 0x200 - 0x270
83 #define IRR_OFFSET4                       0x240   // 0x200 - 0x270
84 #define IRR_OFFSET5                       0x250   // 0x200 - 0x270
85 #define IRR_OFFSET6                       0x260   // 0x200 - 0x270
86 #define IRR_OFFSET7                       0x270   // 0x200 - 0x270
87
88
89 #define ESR_OFFSET                        0x280
90 #define INT_CMD_LO_OFFSET                 0x300
91 #define INT_CMD_HI_OFFSET                 0x310
92 #define TMR_LOC_VEC_TBL_OFFSET            0x320
93 #define THERM_LOC_VEC_TBL_OFFSET          0x330
94 #define PERF_CTR_LOC_VEC_TBL_OFFSET       0x340
95 #define LINT0_VEC_TBL_OFFSET              0x350
96 #define LINT1_VEC_TBL_OFFSET              0x360
97 #define ERR_VEC_TBL_OFFSET                0x370
98 #define TMR_INIT_CNT_OFFSET               0x380
99 #define TMR_CUR_CNT_OFFSET                0x390
100 #define TMR_DIV_CFG_OFFSET                0x3e0
101 #define EXT_APIC_FEATURE_OFFSET           0x400
102 #define EXT_APIC_CMD_OFFSET               0x410
103 #define SEOI_OFFSET                       0x420
104
105 #define IER_OFFSET0                       0x480   // 0x480 - 0x4f0
106 #define IER_OFFSET1                       0x490   // 0x480 - 0x4f0
107 #define IER_OFFSET2                       0x4a0   // 0x480 - 0x4f0
108 #define IER_OFFSET3                       0x4b0   // 0x480 - 0x4f0
109 #define IER_OFFSET4                       0x4c0   // 0x480 - 0x4f0
110 #define IER_OFFSET5                       0x4d0   // 0x480 - 0x4f0
111 #define IER_OFFSET6                       0x4e0   // 0x480 - 0x4f0
112 #define IER_OFFSET7                       0x4f0   // 0x480 - 0x4f0
113
114 #define EXT_INT_LOC_VEC_TBL_OFFSET0       0x500   // 0x500 - 0x530
115 #define EXT_INT_LOC_VEC_TBL_OFFSET1       0x510   // 0x500 - 0x530
116 #define EXT_INT_LOC_VEC_TBL_OFFSET2       0x520   // 0x500 - 0x530
117 #define EXT_INT_LOC_VEC_TBL_OFFSET3       0x530   // 0x500 - 0x530
118
119
120
121 struct apic_msr {
122     union {
123         uint64_t val;
124         struct {
125             uchar_t rsvd;
126             uint_t bootstrap_cpu : 1;
127             uint_t rsvd2         : 2;
128             uint_t apic_enable   : 1;
129             ullong_t base_addr   : 40;
130             uint_t rsvd3         : 12;
131         } __attribute__((packed));
132     } __attribute__((packed));
133 } __attribute__((packed));
134
135
136
137
138 struct apic_state {
139     addr_t base_addr;
140
141     /* MSRs */
142     v3_msr_t base_addr_msr;
143
144
145     /* memory map registers */
146
147     struct lapic_id_reg lapic_id;
148     struct apic_ver_reg apic_ver;
149     struct ext_apic_ctrl_reg ext_apic_ctrl;
150     struct local_vec_tbl_reg local_vec_tbl;
151     struct tmr_vec_tbl_reg tmr_vec_tbl;
152     struct tmr_div_cfg_reg tmr_div_cfg;
153     struct lint_vec_tbl_reg lint0_vec_tbl;
154     struct lint_vec_tbl_reg lint1_vec_tbl;
155     struct perf_ctr_loc_vec_tbl_reg perf_ctr_loc_vec_tbl;
156     struct therm_loc_vec_tbl_reg therm_loc_vec_tbl;
157     struct err_vec_tbl_reg err_vec_tbl;
158     struct err_status_reg err_status;
159     struct spurious_int_reg spurious_int;
160     struct int_cmd_reg int_cmd;
161     struct log_dst_reg log_dst;
162     struct dst_fmt_reg dst_fmt;
163     struct arb_prio_reg arb_prio;
164     struct task_prio_reg task_prio;
165     struct proc_prio_reg proc_prio;
166     struct ext_apic_feature_reg ext_apic_feature;
167     struct spec_eoi_reg spec_eoi;
168   
169
170     uint32_t tmr_cur_cnt;
171     uint32_t tmr_init_cnt;
172
173
174     struct local_vec_tbl_reg ext_intr_vec_tbl[4];
175
176     uint32_t rem_rd_data;
177
178
179     uchar_t int_req_reg[32];
180     uchar_t int_svc_reg[32];
181     uchar_t int_en_reg[32];
182     uchar_t trig_mode_reg[32];
183   
184     uint32_t eoi;
185
186     struct vm_device * icc_bus;
187
188     v3_lock_t  lock;
189 };
190
191 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data);
192 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data);
193
194 static void init_apic_state(struct apic_state * apic, uint32_t id, struct vm_device * icc) {
195     apic->base_addr = DEFAULT_BASE_ADDR;
196     apic->base_addr_msr.value = 0x0000000000000900LL;
197     apic->base_addr_msr.value |= ((uint64_t)DEFAULT_BASE_ADDR); 
198
199     PrintDebug("apic %u: Sizeof Interrupt Request Register %d, should be 32\n", apic->lapic_id.val,
200                (uint_t)sizeof(apic->int_req_reg));
201
202     memset(apic->int_req_reg, 0, sizeof(apic->int_req_reg));
203     memset(apic->int_svc_reg, 0, sizeof(apic->int_svc_reg));
204     memset(apic->int_en_reg, 0xff, sizeof(apic->int_en_reg));
205     memset(apic->trig_mode_reg, 0, sizeof(apic->trig_mode_reg));
206
207     apic->eoi = 0x00000000;
208     apic->rem_rd_data = 0x00000000;
209     apic->tmr_init_cnt = 0x00000000;
210     apic->tmr_cur_cnt = 0x00000000;
211
212     apic->lapic_id.val = id;
213     
214     apic->icc_bus = icc;
215
216     // The P6 has 6 LVT entries, so we set the value to (6-1)...
217     apic->apic_ver.val = 0x80050010;
218
219     apic->task_prio.val = 0x00000000;
220     apic->arb_prio.val = 0x00000000;
221     apic->proc_prio.val = 0x00000000;
222     apic->log_dst.val = 0x00000000;
223     apic->dst_fmt.val = 0xffffffff;
224     apic->spurious_int.val = 0x000000ff;
225     apic->err_status.val = 0x00000000;
226     apic->int_cmd.val = 0x0000000000000000LL;
227     apic->tmr_vec_tbl.val = 0x00010000;
228     apic->therm_loc_vec_tbl.val = 0x00010000;
229     apic->perf_ctr_loc_vec_tbl.val = 0x00010000;
230     apic->lint0_vec_tbl.val = 0x00010000;
231     apic->lint1_vec_tbl.val = 0x00010000;
232     apic->err_vec_tbl.val = 0x00010000;
233     apic->tmr_div_cfg.val = 0x00000000;
234     //apic->ext_apic_feature.val = 0x00000007;
235     apic->ext_apic_feature.val = 0x00040007;
236     apic->ext_apic_ctrl.val = 0x00000000;
237     apic->spec_eoi.val = 0x00000000;
238
239     v3_lock_init(&(apic->lock));
240 }
241
242
243
244
245 static int read_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
246     struct vm_device * dev = (struct vm_device *)priv_data;
247     struct apic_state * apics = (struct apic_state *)(dev->private_data);
248     struct apic_state * apic = &(apics[core->cpu_id]);
249
250     v3_lock(apic->lock);
251     dst->value = apic->base_addr;
252     v3_unlock(apic->lock);
253     return 0;
254 }
255
256
257 static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
258     struct vm_device * dev = (struct vm_device *)priv_data;
259     struct apic_state * apics = (struct apic_state *)(dev->private_data);
260     struct apic_state * apic = &(apics[core->cpu_id]);
261     struct v3_mem_region * old_reg = v3_get_mem_region(dev->vm, core->cpu_id, apic->base_addr);
262
263
264     if (old_reg == NULL) {
265         // uh oh...
266         PrintError("apic %u: APIC Base address region does not exit...\n",apic->lapic_id.val);
267         return -1;
268     }
269     
270     v3_lock(apic->lock);
271
272     v3_delete_mem_region(dev->vm, old_reg);
273
274     apic->base_addr = src.value;
275
276     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) {
277         PrintError("apic %u: Could not hook new APIC Base address\n",apic->lapic_id.val);
278         v3_unlock(apic->lock);
279         return -1;
280     }
281
282     v3_unlock(apic->lock);
283     return 0;
284 }
285
286
287 // irq_num is the bit offset into a 256 bit buffer...
288 static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
289     int major_offset = (irq_num & ~0x00000007) >> 3;
290     int minor_offset = irq_num & 0x00000007;
291     uchar_t * req_location = apic->int_req_reg + major_offset;
292     uchar_t * en_location = apic->int_en_reg + major_offset;
293     uchar_t flag = 0x1 << minor_offset;
294
295
296 #if 1
297
298     if (irq_num <= 15) {
299         PrintError("apic %u: Attempting to raise an invalid interrupt: %d\n", apic->lapic_id.val,irq_num);
300         return -1;
301     }
302
303 #endif
304
305
306     PrintDebug("apic %u: Raising APIC IRQ %d\n", apic->lapic_id.val,irq_num);
307
308     if (*req_location & flag) {
309         //V3_Print("Interrupts coallescing\n");
310     }
311
312     if (*en_location & flag) {
313         *req_location |= flag;
314     } else {
315         PrintDebug("apic %u: Interrupt  not enabled... %.2x\n", apic->lapic_id.val, *en_location);
316         return 0;
317     }
318
319     return 0;
320 }
321
322
323
324 static int get_highest_isr(struct apic_state * apic) {
325     int i = 0, j = 0;
326
327     // We iterate backwards to find the highest priority
328     for (i = 31; i >= 0; i--) {
329         uchar_t  * svc_major = apic->int_svc_reg + i;
330     
331         if ((*svc_major) & 0xff) {
332             for (j = 7; j >= 0; j--) {
333                 uchar_t flag = 0x1 << j;
334                 if ((*svc_major) & flag) {
335                     return ((i * 8) + j);
336                 }
337             }
338         }
339     }
340
341     return -1;
342 }
343  
344
345
346 static int get_highest_irr(struct apic_state * apic) {
347     int i = 0, j = 0;
348
349     // We iterate backwards to find the highest priority
350     for (i = 31; i >= 0; i--) {
351         uchar_t  * req_major = apic->int_req_reg + i;
352     
353         if ((*req_major) & 0xff) {
354             for (j = 7; j >= 0; j--) {
355                 uchar_t flag = 0x1 << j;
356                 if ((*req_major) & flag) {
357                     return ((i * 8) + j);
358                 }
359             }
360         }
361     }
362
363     return -1;
364 }
365  
366
367
368
369 static int apic_do_eoi(struct apic_state * apic) {
370     int isr_irq = get_highest_isr(apic);
371
372     if (isr_irq != -1) {
373         int major_offset = (isr_irq & ~0x00000007) >> 3;
374         int minor_offset = isr_irq & 0x00000007;
375         uchar_t flag = 0x1 << minor_offset;
376         uchar_t * svc_location = apic->int_svc_reg + major_offset;
377         
378         PrintDebug("Received APIC EOI for IRQ %d\n", isr_irq);
379         
380         *svc_location &= ~flag;
381
382 #ifdef CONFIG_CRAY_XT
383         
384         if ((isr_irq == 238) || 
385             (isr_irq == 239)) {
386             PrintError("Acking IRQ %d\n", isr_irq);
387         }
388         
389         if (isr_irq == 238) {
390             V3_ACK_IRQ(238);
391         }
392 #endif
393     } else {
394         //PrintError("Spurious EOI...\n");
395     }
396         
397     return 0;
398 }
399  
400
401 static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_type) {
402     uint32_t vec_num = 0;
403     uint32_t del_mode = 0;
404     int masked = 0;
405
406
407     switch (int_type) {
408         case APIC_TMR_INT:
409             vec_num = apic->tmr_vec_tbl.vec;
410             del_mode = APIC_FIXED_DELIVERY;
411             masked = apic->tmr_vec_tbl.mask;
412             break;
413         case APIC_THERM_INT:
414             vec_num = apic->therm_loc_vec_tbl.vec;
415             del_mode = apic->therm_loc_vec_tbl.msg_type;
416             masked = apic->therm_loc_vec_tbl.mask;
417             break;
418         case APIC_PERF_INT:
419             vec_num = apic->perf_ctr_loc_vec_tbl.vec;
420             del_mode = apic->perf_ctr_loc_vec_tbl.msg_type;
421             masked = apic->perf_ctr_loc_vec_tbl.mask;
422             break;
423         case APIC_LINT0_INT:
424             vec_num = apic->lint0_vec_tbl.vec;
425             del_mode = apic->lint0_vec_tbl.msg_type;
426             masked = apic->lint0_vec_tbl.mask;
427             break;
428         case APIC_LINT1_INT:
429             vec_num = apic->lint1_vec_tbl.vec;
430             del_mode = apic->lint1_vec_tbl.msg_type;
431             masked = apic->lint1_vec_tbl.mask;
432             break;
433         case APIC_ERR_INT:
434             vec_num = apic->err_vec_tbl.vec;
435             del_mode = APIC_FIXED_DELIVERY;
436             masked = apic->err_vec_tbl.mask;
437             break;
438         default:
439             PrintError("apic %u: Invalid APIC interrupt type\n",apic->lapic_id.val);
440             return -1;
441     }
442
443     // interrupt is masked, don't send
444     if (masked == 1) {
445         PrintDebug("apic %u: Inerrupt is masked\n",apic->lapic_id.val);
446         return 0;
447     }
448
449     if (del_mode == APIC_FIXED_DELIVERY) {
450         //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
451         return activate_apic_irq(apic, vec_num);
452     } else {
453         PrintError("apic %u: Unhandled Delivery Mode\n",apic->lapic_id.val);
454         return -1;
455     }
456 }
457
458
459 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
460     struct apic_state * apics = (struct apic_state *)(priv_data);
461     struct apic_state * apic = &(apics[core->cpu_id]);
462     addr_t reg_addr  = guest_addr - apic->base_addr;
463     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
464     uint32_t val = 0;
465
466
467     PrintDebug("apic %u: Read apic address space (%p)\n",apic->lapic_id.val, 
468                (void *)guest_addr);
469
470     if (msr->apic_enable == 0) {
471         PrintError("apic %u: Write to APIC address space with disabled APIC\n",apic->lapic_id.val);
472         return -1;
473     }
474
475
476     /* Because "May not be supported" doesn't matter to Linux developers... */
477     /*   if (length != 4) { */
478     /*     PrintError("Invalid apic read length (%d)\n", length); */
479     /*     return -1; */
480     /*   } */
481
482     switch (reg_addr & ~0x3) {
483         case EOI_OFFSET:
484             // Well, only an idiot would read from a architectural write only register
485             // Oh, Hello Linux.
486             //    PrintError("Attempting to read from write only register\n");
487             //    return -1;
488             break;
489
490             // data registers
491         case APIC_ID_OFFSET:
492             val = apic->lapic_id.val;
493             break;
494         case APIC_VERSION_OFFSET:
495             val = apic->apic_ver.val;
496             break;
497         case TPR_OFFSET:
498             val = apic->task_prio.val;
499             break;
500         case APR_OFFSET:
501             val = apic->arb_prio.val;
502             break;
503         case PPR_OFFSET:
504             val = apic->proc_prio.val;
505             break;
506         case REMOTE_READ_OFFSET:
507             val = apic->rem_rd_data;
508             break;
509         case LDR_OFFSET:
510             val = apic->log_dst.val;
511             break;
512         case DFR_OFFSET:
513             val = apic->dst_fmt.val;
514             break;
515         case SPURIOUS_INT_VEC_OFFSET:
516             val = apic->spurious_int.val;
517             break;
518         case ESR_OFFSET:
519             val = apic->err_status.val;
520             break;
521         case TMR_LOC_VEC_TBL_OFFSET:
522             val = apic->tmr_vec_tbl.val;
523             break;
524         case LINT0_VEC_TBL_OFFSET:
525             val = apic->lint0_vec_tbl.val;
526             break;
527         case LINT1_VEC_TBL_OFFSET:
528             val = apic->lint1_vec_tbl.val;
529             break;
530         case ERR_VEC_TBL_OFFSET:
531             val = apic->err_vec_tbl.val;
532             break;
533         case TMR_INIT_CNT_OFFSET:
534             val = apic->tmr_init_cnt;
535             break;
536         case TMR_DIV_CFG_OFFSET:
537             val = apic->tmr_div_cfg.val;
538             break;
539
540         case IER_OFFSET0:
541             val = *(uint32_t *)(apic->int_en_reg);
542             break;
543         case IER_OFFSET1:
544             val = *(uint32_t *)(apic->int_en_reg + 4);
545             break;
546         case IER_OFFSET2:
547             val = *(uint32_t *)(apic->int_en_reg + 8);
548             break;
549         case IER_OFFSET3:
550             val = *(uint32_t *)(apic->int_en_reg + 12);
551             break;
552         case IER_OFFSET4:
553             val = *(uint32_t *)(apic->int_en_reg + 16);
554             break;
555         case IER_OFFSET5:
556             val = *(uint32_t *)(apic->int_en_reg + 20);
557             break;
558         case IER_OFFSET6:
559             val = *(uint32_t *)(apic->int_en_reg + 24);
560             break;
561         case IER_OFFSET7:
562             val = *(uint32_t *)(apic->int_en_reg + 28);
563             break;
564
565         case ISR_OFFSET0:
566             val = *(uint32_t *)(apic->int_svc_reg);
567             break;
568         case ISR_OFFSET1:
569             val = *(uint32_t *)(apic->int_svc_reg + 4);
570             break;
571         case ISR_OFFSET2:
572             val = *(uint32_t *)(apic->int_svc_reg + 8);
573             break;
574         case ISR_OFFSET3:
575             val = *(uint32_t *)(apic->int_svc_reg + 12);
576             break;
577         case ISR_OFFSET4:
578             val = *(uint32_t *)(apic->int_svc_reg + 16);
579             break;
580         case ISR_OFFSET5:
581             val = *(uint32_t *)(apic->int_svc_reg + 20);
582             break;
583         case ISR_OFFSET6:
584             val = *(uint32_t *)(apic->int_svc_reg + 24);
585             break;
586         case ISR_OFFSET7:
587             val = *(uint32_t *)(apic->int_svc_reg + 28);
588             break;
589    
590         case TRIG_OFFSET0:
591             val = *(uint32_t *)(apic->trig_mode_reg);
592             break;
593         case TRIG_OFFSET1:
594             val = *(uint32_t *)(apic->trig_mode_reg + 4);
595             break;
596         case TRIG_OFFSET2:
597             val = *(uint32_t *)(apic->trig_mode_reg + 8);
598             break;
599         case TRIG_OFFSET3:
600             val = *(uint32_t *)(apic->trig_mode_reg + 12);
601             break;
602         case TRIG_OFFSET4:
603             val = *(uint32_t *)(apic->trig_mode_reg + 16);
604             break;
605         case TRIG_OFFSET5:
606             val = *(uint32_t *)(apic->trig_mode_reg + 20);
607             break;
608         case TRIG_OFFSET6:
609             val = *(uint32_t *)(apic->trig_mode_reg + 24);
610             break;
611         case TRIG_OFFSET7:
612             val = *(uint32_t *)(apic->trig_mode_reg + 28);
613             break;
614
615         case IRR_OFFSET0:
616             val = *(uint32_t *)(apic->int_req_reg);
617             break;
618         case IRR_OFFSET1:
619             val = *(uint32_t *)(apic->int_req_reg + 4);
620             break;
621         case IRR_OFFSET2:
622             val = *(uint32_t *)(apic->int_req_reg + 8);
623             break;
624         case IRR_OFFSET3:
625             val = *(uint32_t *)(apic->int_req_reg + 12);
626             break;
627         case IRR_OFFSET4:
628             val = *(uint32_t *)(apic->int_req_reg + 16);
629             break;
630         case IRR_OFFSET5:
631             val = *(uint32_t *)(apic->int_req_reg + 20);
632             break;
633         case IRR_OFFSET6:
634             val = *(uint32_t *)(apic->int_req_reg + 24);
635             break;
636         case IRR_OFFSET7:
637             val = *(uint32_t *)(apic->int_req_reg + 28);
638             break;
639         case TMR_CUR_CNT_OFFSET:
640             val = apic->tmr_cur_cnt;
641             break;
642
643             // We are not going to implement these....
644         case THERM_LOC_VEC_TBL_OFFSET:
645             val = apic->therm_loc_vec_tbl.val;
646             break;
647         case PERF_CTR_LOC_VEC_TBL_OFFSET:
648             val = apic->perf_ctr_loc_vec_tbl.val;
649             break;
650
651  
652
653             // handled registers
654         case INT_CMD_LO_OFFSET:    
655             val = apic->int_cmd.lo;
656             break;
657         case INT_CMD_HI_OFFSET:
658             val = apic->int_cmd.hi;
659             break;
660
661             // handle current timer count
662
663             // Unhandled Registers
664         case EXT_INT_LOC_VEC_TBL_OFFSET0:
665             val = apic->ext_intr_vec_tbl[0].val;
666             break;
667         case EXT_INT_LOC_VEC_TBL_OFFSET1:
668             val = apic->ext_intr_vec_tbl[1].val;
669             break;
670         case EXT_INT_LOC_VEC_TBL_OFFSET2:
671             val = apic->ext_intr_vec_tbl[2].val;
672             break;
673         case EXT_INT_LOC_VEC_TBL_OFFSET3:
674             val = apic->ext_intr_vec_tbl[3].val;
675             break;
676     
677
678         case EXT_APIC_FEATURE_OFFSET:
679         case EXT_APIC_CMD_OFFSET:
680         case SEOI_OFFSET:
681
682         default:
683             PrintError("apic %u: Read from Unhandled APIC Register: %x (getting zero)\n", apic->lapic_id.val, (uint32_t)reg_addr);
684             //      return -1;
685             val=0;
686     }
687
688
689     if (length == 1) {
690         uint_t byte_addr = reg_addr & 0x3;
691         uint8_t * val_ptr = (uint8_t *)dst;
692     
693         *val_ptr = *(((uint8_t *)&val) + byte_addr);
694
695     } else if ((length == 2) && 
696                ((reg_addr & 0x3) == 0x3)) {
697         uint_t byte_addr = reg_addr & 0x3;
698         uint16_t * val_ptr = (uint16_t *)dst;
699         *val_ptr = *(((uint16_t *)&val) + byte_addr);
700
701     } else if (length == 4) {
702         uint32_t * val_ptr = (uint32_t *)dst;
703         *val_ptr = val;
704
705     } else {
706         PrintError("apic %u: Invalid apic read length (%d)\n", apic->lapic_id.val, length);
707         return -1;
708     }
709
710     PrintDebug("apic %u: Read finished (val=%x)\n", apic->lapic_id.val, *(uint32_t *)dst);
711
712     return length;
713 }
714
715
716 /**
717  *
718  */
719 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data) {
720     struct apic_state * apics = (struct apic_state *)(priv_data);
721     struct apic_state * apic = &(apics[core->cpu_id]);
722     addr_t reg_addr  = guest_addr - apic->base_addr;
723     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
724     uint32_t op_val = *(uint32_t *)src;
725
726     PrintDebug("apic %u: Write to address space (%p) (val=%x)\n", 
727                apic->lapic_id.val,
728                (void *)guest_addr, *(uint32_t *)src);
729
730     if (msr->apic_enable == 0) {
731         PrintError("apic %u: Write to APIC address space with disabled APIC\n",apic->lapic_id.val);
732         return -1;
733     }
734
735
736     if (length != 4) {
737         PrintError("apic %u: Invalid apic write length (%d)\n", apic->lapic_id.val, length);
738         return -1;
739     }
740
741     switch (reg_addr) {
742         case REMOTE_READ_OFFSET:
743         case APIC_VERSION_OFFSET:
744         case APR_OFFSET:
745         case IRR_OFFSET0:
746         case IRR_OFFSET1:
747         case IRR_OFFSET2:
748         case IRR_OFFSET3:
749         case IRR_OFFSET4:
750         case IRR_OFFSET5:
751         case IRR_OFFSET6:
752         case IRR_OFFSET7:
753         case ISR_OFFSET0:
754         case ISR_OFFSET1:
755         case ISR_OFFSET2:
756         case ISR_OFFSET3:
757         case ISR_OFFSET4:
758         case ISR_OFFSET5:
759         case ISR_OFFSET6:
760         case ISR_OFFSET7:
761         case TRIG_OFFSET0:
762         case TRIG_OFFSET1:
763         case TRIG_OFFSET2:
764         case TRIG_OFFSET3:
765         case TRIG_OFFSET4:
766         case TRIG_OFFSET5:
767         case TRIG_OFFSET6:
768         case TRIG_OFFSET7:
769         case PPR_OFFSET:
770         case EXT_APIC_FEATURE_OFFSET:
771 #if 1
772             PrintError("apic %u: Attempting to write to read only register %p (ignored)\n", apic->lapic_id.val, (void *)reg_addr);
773 #else   
774             PrintError("apic %u: Attempting to write to read only register %p (error)\n", apic->lapic_id.val, (void *)reg_addr);
775             return -1;
776 #endif
777             break;
778
779             // Data registers
780         case APIC_ID_OFFSET:
781             apic->lapic_id.val = op_val;
782             break;
783         case TPR_OFFSET:
784             apic->task_prio.val = op_val;
785             break;
786         case LDR_OFFSET:
787             apic->log_dst.val = op_val;
788             break;
789         case DFR_OFFSET:
790             apic->dst_fmt.val = op_val;
791             break;
792         case SPURIOUS_INT_VEC_OFFSET:
793             apic->spurious_int.val = op_val;
794             break;
795         case ESR_OFFSET:
796             apic->err_status.val = op_val;
797             break;
798         case TMR_LOC_VEC_TBL_OFFSET:
799             apic->tmr_vec_tbl.val = op_val;
800             break;
801         case THERM_LOC_VEC_TBL_OFFSET:
802             apic->therm_loc_vec_tbl.val = op_val;
803             break;
804         case PERF_CTR_LOC_VEC_TBL_OFFSET:
805             apic->perf_ctr_loc_vec_tbl.val = op_val;
806             break;
807         case LINT0_VEC_TBL_OFFSET:
808             apic->lint0_vec_tbl.val = op_val;
809             break;
810         case LINT1_VEC_TBL_OFFSET:
811             apic->lint1_vec_tbl.val = op_val;
812             break;
813         case ERR_VEC_TBL_OFFSET:
814             apic->err_vec_tbl.val = op_val;
815             break;
816         case TMR_INIT_CNT_OFFSET:
817             apic->tmr_init_cnt = op_val;
818             apic->tmr_cur_cnt = op_val;
819             break;
820         case TMR_CUR_CNT_OFFSET:
821             apic->tmr_cur_cnt = op_val;
822             break;
823         case TMR_DIV_CFG_OFFSET:
824             apic->tmr_div_cfg.val = op_val;
825             break;
826
827
828             // Enable mask (256 bits)
829         case IER_OFFSET0:
830             *(uint32_t *)(apic->int_en_reg) = op_val;
831             break;
832         case IER_OFFSET1:
833             *(uint32_t *)(apic->int_en_reg + 4) = op_val;
834             break;
835         case IER_OFFSET2:
836             *(uint32_t *)(apic->int_en_reg + 8) = op_val;
837             break;
838         case IER_OFFSET3:
839             *(uint32_t *)(apic->int_en_reg + 12) = op_val;
840             break;
841         case IER_OFFSET4:
842             *(uint32_t *)(apic->int_en_reg + 16) = op_val;
843             break;
844         case IER_OFFSET5:
845             *(uint32_t *)(apic->int_en_reg + 20) = op_val;
846             break;
847         case IER_OFFSET6:
848             *(uint32_t *)(apic->int_en_reg + 24) = op_val;
849             break;
850         case IER_OFFSET7:
851             *(uint32_t *)(apic->int_en_reg + 28) = op_val;
852             break;
853
854         case EXT_INT_LOC_VEC_TBL_OFFSET0:
855             apic->ext_intr_vec_tbl[0].val = op_val;
856             break;
857         case EXT_INT_LOC_VEC_TBL_OFFSET1:
858             apic->ext_intr_vec_tbl[1].val = op_val;
859             break;
860         case EXT_INT_LOC_VEC_TBL_OFFSET2:
861             apic->ext_intr_vec_tbl[2].val = op_val;
862             break;
863         case EXT_INT_LOC_VEC_TBL_OFFSET3:
864             apic->ext_intr_vec_tbl[3].val = op_val;
865             break;
866
867
868             // Action Registers
869         case EOI_OFFSET:
870             // do eoi
871             apic_do_eoi(apic);
872             break;
873
874         case INT_CMD_LO_OFFSET:
875             apic->int_cmd.lo = op_val;
876             // ICC???
877             PrintDebug("apic %u: sending cmd 0x%llx to apic %u\n",apic->lapic_id.val,
878                        apic->int_cmd.val, apic->int_cmd.dst);
879             v3_icc_send_ipi(apic->icc_bus, apic->lapic_id.val, apic->int_cmd.val);
880             break;
881         case INT_CMD_HI_OFFSET:
882             apic->int_cmd.hi = op_val;
883             break;
884             // Unhandled Registers
885
886         case EXT_APIC_CMD_OFFSET:
887         case SEOI_OFFSET:
888         default:
889             PrintError("apic %u: Write to Unhandled APIC Register: %x (ignored)\n", apic->lapic_id.val, (uint32_t)reg_addr);
890             //      return -1;
891     }
892
893     PrintDebug("apic %u: Write finished\n",apic->lapic_id.val);
894
895     return length;
896 }
897
898
899
900 /* Interrupt Controller Functions */
901
902 // returns 1 if an interrupt is pending, 0 otherwise
903 static int apic_intr_pending(struct guest_info * info, void * private_data) {
904     struct apic_state * apic = (struct apic_state *)private_data;
905     int req_irq = get_highest_irr(apic);
906     int svc_irq = get_highest_isr(apic);
907
908     if ((req_irq >= 0) && 
909         (req_irq > svc_irq)) {
910         return 1;
911     }
912
913     return 0;
914 }
915
916 static int apic_get_intr_number(struct guest_info * info, void * private_data) {
917     struct apic_state * apic = (struct apic_state *)private_data;
918     int req_irq = get_highest_irr(apic);
919     int svc_irq = get_highest_isr(apic);
920
921     if (svc_irq == -1) {
922         return req_irq;
923     } else if (svc_irq < req_irq) {
924         return req_irq;
925     }
926
927     return -1;
928 }
929
930
931 static int apic_raise_intr(struct guest_info * info, int irq, void * private_data) {
932   struct apic_state * apic = (struct apic_state *)private_data;
933
934   return activate_apic_irq(apic, irq);
935 }
936
937
938
939 static int apic_begin_irq(struct guest_info * info, void * private_data, int irq) {
940     struct apic_state * apic = (struct apic_state *)private_data;
941     int major_offset = (irq & ~0x00000007) >> 3;
942     int minor_offset = irq & 0x00000007;
943     uchar_t * req_location = apic->int_req_reg + major_offset;
944     uchar_t * svc_location = apic->int_svc_reg + major_offset;
945     uchar_t flag = 0x01 << minor_offset;
946
947     *svc_location |= flag;
948     *req_location &= ~flag;
949
950
951
952     return 0;
953 }
954
955
956
957
958 /* Timer Functions */
959 static void apic_update_time(struct guest_info * info, ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data) {
960     struct apic_state * apics = (struct apic_state *)(priv_data);
961     struct apic_state * apic = &(apics[info->cpu_id]);
962     // The 32 bit GCC runtime is a pile of shit
963 #ifdef __V3_64BIT__
964     uint64_t tmr_ticks = 0;
965 #else 
966     uint32_t tmr_ticks = 0;
967 #endif
968
969     uchar_t tmr_div = *(uchar_t *)&(apic->tmr_div_cfg.val);
970     uint_t shift_num = 0;
971
972
973     // Check whether this is true:
974     //   -> If the Init count is zero then the timer is disabled
975     //      and doesn't just blitz interrupts to the CPU
976     if ((apic->tmr_init_cnt == 0) || 
977         ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
978           (apic->tmr_cur_cnt == 0))) {
979         //PrintDebug("apic %u: APIC timer not yet initialized\n",apic->lapic_id.val);
980         return;
981     }
982
983
984     switch (tmr_div) {
985         case APIC_TMR_DIV1:
986             shift_num = 0;
987             break;
988         case APIC_TMR_DIV2:
989             shift_num = 1;
990             break;
991         case APIC_TMR_DIV4:
992             shift_num = 2;
993             break;
994         case APIC_TMR_DIV8:
995             shift_num = 3;
996             break;
997         case APIC_TMR_DIV16:
998             shift_num = 4;
999             break;
1000         case APIC_TMR_DIV32:
1001             shift_num = 5;
1002             break;
1003         case APIC_TMR_DIV64:
1004             shift_num = 6;
1005             break;
1006         case APIC_TMR_DIV128:
1007             shift_num = 7;
1008             break;
1009         default:
1010             PrintError("apic %u: Invalid Timer Divider configuration\n",apic->lapic_id.val);
1011             return;
1012     }
1013
1014     tmr_ticks = cpu_cycles >> shift_num;
1015     //    PrintDebug("Timer Ticks: %p\n", (void *)tmr_ticks);
1016
1017     if (tmr_ticks < apic->tmr_cur_cnt) {
1018         apic->tmr_cur_cnt -= tmr_ticks;
1019     } else {
1020         tmr_ticks -= apic->tmr_cur_cnt;
1021         apic->tmr_cur_cnt = 0;
1022
1023         // raise irq
1024         PrintDebug("apic %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n", apic->lapic_id.val,
1025                    apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
1026
1027         if (apic_intr_pending(info, priv_data)) {
1028             PrintDebug("apic %u: Overriding pending IRQ %d\n", apic->lapic_id.val, apic_get_intr_number(info, priv_data));
1029         }
1030
1031         if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
1032             PrintError("apic %u: Could not raise Timer interrupt\n",apic->lapic_id.val);
1033         }
1034     
1035         if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
1036             tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
1037             apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
1038         }
1039     }
1040
1041
1042 }
1043
1044
1045 static struct intr_ctrl_ops intr_ops = {
1046     .intr_pending = apic_intr_pending,
1047     .get_intr_number = apic_get_intr_number,
1048     .begin_irq = apic_begin_irq,
1049 };
1050
1051
1052 static struct vm_timer_ops timer_ops = {
1053     .update_time = apic_update_time,
1054 };
1055
1056
1057
1058
1059 static int apic_free(struct vm_device * dev) {
1060
1061     /* TODO: This should crosscall to force an unhook on each CPU */
1062
1063     //   struct apic_state * apic = (struct apic_state *)dev->private_data;
1064
1065     v3_unhook_msr(dev->vm, BASE_ADDR_MSR);
1066
1067     return 0;
1068 }
1069
1070
1071 static struct v3_device_ops dev_ops = {
1072     .free = apic_free,
1073     .reset = NULL,
1074     .start = NULL,
1075     .stop = NULL,
1076 };
1077
1078
1079
1080 static struct v3_icc_ops icc_ops = {
1081     .raise_intr = apic_raise_intr,
1082 };
1083
1084
1085
1086 static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
1087     PrintDebug("apic: creating an APIC for each core\n");
1088     char * name = v3_cfg_val(cfg, "name");
1089     char * icc_name = v3_cfg_val(cfg,"bus");
1090     struct vm_device * icc = v3_find_dev(vm, icc_name);
1091     int i;
1092
1093     if (!icc) {
1094         PrintError("apic: Cannot find ICC Bus (%s)\n", icc_name);
1095         return -1;
1096     }
1097
1098     // We allocate one apic per core
1099     // APICs are accessed via index which correlates with the core's cpu_id 
1100     // 0..num_cores-1   at num_cores is the ioapic (one only)
1101     struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state) * vm->num_cores);
1102
1103     struct vm_device * dev = v3_allocate_device(name, &dev_ops, apic);
1104
1105     if (v3_attach_device(vm, dev) == -1) {
1106         PrintError("apic: Could not attach device %s\n", name);
1107         return -1;
1108     }
1109
1110     
1111     for (i = 0; i < vm->num_cores; i++) {
1112         struct guest_info * core = &(vm->cores[i]);
1113
1114         init_apic_state(&(apic[i]),i,icc);
1115
1116         v3_register_intr_controller(core, &intr_ops, &(apic[i]));
1117
1118         v3_add_timer(core, &timer_ops, &(apic[i]));
1119
1120         v3_hook_full_mem(vm, core->cpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, &(apic[i]));
1121
1122         v3_icc_register_apic(core, icc, i, &icc_ops, &(apic[i]));
1123
1124     }
1125
1126
1127
1128     v3_hook_msr(vm, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev);
1129
1130     return 0;
1131 }
1132
1133
1134
1135 device_register("LAPIC", apic_init)