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.


be7df883e1c1b96a472d29b40158cf7abc266b67
[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  * Authors: Jack Lange <jarusl@cs.northwestern.edu>
15  *          Peter Dinda <pdinda@northwestern.edu> (SMP)
16  *
17  * This is free software.  You are permitted to use,
18  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
19  */
20
21
22 #include <devices/apic.h>
23 #include <devices/apic_regs.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 #include <palacios/vmm_types.h>
29
30
31 #include <palacios/vmm_queue.h>
32 #include <palacios/vmm_lock.h>
33
34 /* The locking in this file is nasty.
35  * There are 3 different locking approaches that are taken, depending on the APIC operation
36  * 1. Queue locks. Actual irq insertions are done via queueing irq ops at the dest apic. 
37  *    The destination apic's core is responsible for draining the queue, and actually 
38  *    setting the vector table. 
39  * 2. State lock. This is a standard lock taken when internal apic state is read/written. 
40  *    When an irq's destination is determined this lock is taken to examine the apic's 
41  *    addressability. 
42  * 3. VM barrier lock. This is taken when actual VM core state is changed (via SIPI). 
43  */
44
45
46
47 #ifndef V3_CONFIG_DEBUG_APIC
48 #undef PrintDebug
49 #define PrintDebug(fmt, args...)
50 #else
51
52 static char * shorthand_str[] = { 
53     "(no shorthand)",
54     "(self)",
55     "(all)",
56     "(all-but-me)",
57 };
58
59 static char * deliverymode_str[] = { 
60     "(fixed)",
61     "(lowest priority)",
62     "(SMI)",
63     "(reserved)",
64     "(NMI)",
65     "(INIT)",
66     "(Start Up)",
67     "(ExtInt)",
68 };
69
70 #endif
71
72 typedef enum { APIC_TMR_INT, APIC_THERM_INT, APIC_PERF_INT, 
73                APIC_LINT0_INT, APIC_LINT1_INT, APIC_ERR_INT } apic_irq_type_t;
74
75
76 #define APIC_SHORTHAND_NONE        0x0
77 #define APIC_SHORTHAND_SELF        0x1
78 #define APIC_SHORTHAND_ALL         0x2
79 #define APIC_SHORTHAND_ALL_BUT_ME  0x3
80
81 #define APIC_DEST_PHYSICAL    0x0
82 #define APIC_DEST_LOGICAL     0x1
83
84
85 #define BASE_ADDR_MSR     0x0000001B
86 #define DEFAULT_BASE_ADDR 0xfee00000
87
88 #define APIC_ID_OFFSET                    0x020
89 #define APIC_VERSION_OFFSET               0x030
90 #define TPR_OFFSET                        0x080
91 #define APR_OFFSET                        0x090
92 #define PPR_OFFSET                        0x0a0
93 #define EOI_OFFSET                        0x0b0
94 #define REMOTE_READ_OFFSET                0x0c0
95 #define LDR_OFFSET                        0x0d0
96 #define DFR_OFFSET                        0x0e0
97 #define SPURIOUS_INT_VEC_OFFSET           0x0f0
98
99 #define ISR_OFFSET0                       0x100   // 0x100 - 0x170
100 #define ISR_OFFSET1                       0x110   // 0x100 - 0x170
101 #define ISR_OFFSET2                       0x120   // 0x100 - 0x170
102 #define ISR_OFFSET3                       0x130   // 0x100 - 0x170
103 #define ISR_OFFSET4                       0x140   // 0x100 - 0x170
104 #define ISR_OFFSET5                       0x150   // 0x100 - 0x170
105 #define ISR_OFFSET6                       0x160   // 0x100 - 0x170
106 #define ISR_OFFSET7                       0x170   // 0x100 - 0x170
107
108 #define TRIG_OFFSET0                      0x180   // 0x180 - 0x1f0
109 #define TRIG_OFFSET1                      0x190   // 0x180 - 0x1f0
110 #define TRIG_OFFSET2                      0x1a0   // 0x180 - 0x1f0
111 #define TRIG_OFFSET3                      0x1b0   // 0x180 - 0x1f0
112 #define TRIG_OFFSET4                      0x1c0   // 0x180 - 0x1f0
113 #define TRIG_OFFSET5                      0x1d0   // 0x180 - 0x1f0
114 #define TRIG_OFFSET6                      0x1e0   // 0x180 - 0x1f0
115 #define TRIG_OFFSET7                      0x1f0   // 0x180 - 0x1f0
116
117
118 #define IRR_OFFSET0                       0x200   // 0x200 - 0x270
119 #define IRR_OFFSET1                       0x210   // 0x200 - 0x270
120 #define IRR_OFFSET2                       0x220   // 0x200 - 0x270
121 #define IRR_OFFSET3                       0x230   // 0x200 - 0x270
122 #define IRR_OFFSET4                       0x240   // 0x200 - 0x270
123 #define IRR_OFFSET5                       0x250   // 0x200 - 0x270
124 #define IRR_OFFSET6                       0x260   // 0x200 - 0x270
125 #define IRR_OFFSET7                       0x270   // 0x200 - 0x270
126
127
128 #define ESR_OFFSET                        0x280
129 #define INT_CMD_LO_OFFSET                 0x300
130 #define INT_CMD_HI_OFFSET                 0x310
131 #define TMR_LOC_VEC_TBL_OFFSET            0x320
132 #define THERM_LOC_VEC_TBL_OFFSET          0x330
133 #define PERF_CTR_LOC_VEC_TBL_OFFSET       0x340
134 #define LINT0_VEC_TBL_OFFSET              0x350
135 #define LINT1_VEC_TBL_OFFSET              0x360
136 #define ERR_VEC_TBL_OFFSET                0x370
137 #define TMR_INIT_CNT_OFFSET               0x380
138 #define TMR_CUR_CNT_OFFSET                0x390
139 #define TMR_DIV_CFG_OFFSET                0x3e0
140 #define EXT_APIC_FEATURE_OFFSET           0x400
141 #define EXT_APIC_CMD_OFFSET               0x410
142 #define SEOI_OFFSET                       0x420
143
144 #define IER_OFFSET0                       0x480   // 0x480 - 0x4f0
145 #define IER_OFFSET1                       0x490   // 0x480 - 0x4f0
146 #define IER_OFFSET2                       0x4a0   // 0x480 - 0x4f0
147 #define IER_OFFSET3                       0x4b0   // 0x480 - 0x4f0
148 #define IER_OFFSET4                       0x4c0   // 0x480 - 0x4f0
149 #define IER_OFFSET5                       0x4d0   // 0x480 - 0x4f0
150 #define IER_OFFSET6                       0x4e0   // 0x480 - 0x4f0
151 #define IER_OFFSET7                       0x4f0   // 0x480 - 0x4f0
152
153 #define EXT_INT_LOC_VEC_TBL_OFFSET0       0x500   // 0x500 - 0x530
154 #define EXT_INT_LOC_VEC_TBL_OFFSET1       0x510   // 0x500 - 0x530
155 #define EXT_INT_LOC_VEC_TBL_OFFSET2       0x520   // 0x500 - 0x530
156 #define EXT_INT_LOC_VEC_TBL_OFFSET3       0x530   // 0x500 - 0x530
157
158 struct apic_msr {
159     union {
160         uint64_t value;
161         struct {
162             uint8_t rsvd;
163             uint8_t bootstrap_cpu : 1;
164             uint8_t rsvd2         : 2;
165             uint8_t apic_enable   : 1;
166             uint64_t base_addr    : 40;
167             uint32_t rsvd3        : 12;
168         } __attribute__((packed));
169     } __attribute__((packed));
170 } __attribute__((packed));
171
172
173
174
175
176 struct irq_queue_entry {
177     uint32_t vector;
178     int (*ack)(struct guest_info * core, uint32_t irq, void * private_data);
179     void * private_data;
180
181     struct list_head list_node;
182 };
183
184
185
186
187 typedef enum {INIT_ST, 
188               SIPI, 
189               STARTED} ipi_state_t; 
190
191 struct apic_dev_state;
192
193 struct apic_state {
194     addr_t base_addr;
195
196     /* MSRs */
197     struct apic_msr base_addr_msr;
198
199
200     /* memory map registers */
201
202     struct lapic_id_reg lapic_id;
203     struct apic_ver_reg apic_ver;
204     struct ext_apic_ctrl_reg ext_apic_ctrl;
205     struct local_vec_tbl_reg local_vec_tbl;
206     struct tmr_vec_tbl_reg tmr_vec_tbl;
207     struct tmr_div_cfg_reg tmr_div_cfg;
208     struct lint_vec_tbl_reg lint0_vec_tbl;
209     struct lint_vec_tbl_reg lint1_vec_tbl;
210     struct perf_ctr_loc_vec_tbl_reg perf_ctr_loc_vec_tbl;
211     struct therm_loc_vec_tbl_reg therm_loc_vec_tbl;
212     struct err_vec_tbl_reg err_vec_tbl;
213     struct err_status_reg err_status;
214     struct spurious_int_reg spurious_int;
215     struct int_cmd_reg int_cmd;
216     struct log_dst_reg log_dst;
217     struct dst_fmt_reg dst_fmt;
218     //struct arb_prio_reg arb_prio;     // computed on the fly
219     //struct task_prio_reg task_prio;   // stored in core.ctrl_regs.apic_tpr
220     //struct proc_prio_reg proc_prio;   // computed on the fly
221     struct ext_apic_feature_reg ext_apic_feature;
222     struct spec_eoi_reg spec_eoi;
223   
224
225     uint32_t tmr_cur_cnt;
226     uint32_t tmr_init_cnt;
227     uint32_t missed_ints;
228
229     struct local_vec_tbl_reg ext_intr_vec_tbl[4];
230
231     uint32_t rem_rd_data;
232
233
234     ipi_state_t ipi_state;
235
236     uint8_t int_req_reg[32];
237     uint8_t int_svc_reg[32];
238     uint8_t int_en_reg[32];
239     uint8_t trig_mode_reg[32];
240
241     struct {
242         int (*ack)(struct guest_info * core, uint32_t irq, void * private_data);
243         void * private_data;
244     } irq_ack_cbs[256];
245
246     struct guest_info * core;
247
248     void * controller_handle;
249
250     struct v3_timer * timer;
251
252
253     struct {
254         v3_lock_t lock;
255         
256         uint64_t num_entries;
257         struct list_head entries;
258     } irq_queue ;
259
260     uint32_t eoi;
261
262
263 };
264
265
266
267
268 struct apic_dev_state {
269     int num_apics;
270   
271     v3_lock_t state_lock;
272
273     struct apic_state apics[0];
274 } __attribute__((packed));
275
276
277
278 static void dump_all_apic_state(struct v3_vm_info *vm, struct apic_dev_state *a);
279 static void dump_apic_state(struct guest_info *core, struct apic_state * a) ;
280
281
282 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data);
283 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data);
284
285 static void set_apic_tpr(struct apic_state *apic, uint32_t val);
286
287 static int is_apic_bsp(struct apic_state * apic) {
288     return ((apic->base_addr_msr.value & 0x0000000000000100LL) != 0);
289 }
290
291
292
293
294 // No locking done
295 static void init_apic_state(struct apic_state * apic, uint32_t id) {
296     apic->base_addr = DEFAULT_BASE_ADDR;
297
298     if (id == 0) { 
299         // boot processor, enabled
300         apic->base_addr_msr.value = 0x0000000000000900LL;
301     } else {
302         // ap processor, enabled
303         apic->base_addr_msr.value = 0x0000000000000800LL;
304     }
305
306     // same base address regardless of ap or main
307     apic->base_addr_msr.value |= ((uint64_t)DEFAULT_BASE_ADDR); 
308
309     PrintDebug(VM_NONE, VCORE_NONE, "apic %u: (init_apic_state): msr=0x%llx\n",id, apic->base_addr_msr.value);
310
311     PrintDebug(VM_NONE, VCORE_NONE, "apic %u: (init_apic_state): Sizeof Interrupt Request Register %d, should be 32\n",
312                id, (uint_t)sizeof(apic->int_req_reg));
313
314     memset(apic->int_req_reg, 0, sizeof(apic->int_req_reg));
315     memset(apic->int_svc_reg, 0, sizeof(apic->int_svc_reg));
316     memset(apic->int_en_reg, 0xff, sizeof(apic->int_en_reg));
317     memset(apic->trig_mode_reg, 0, sizeof(apic->trig_mode_reg));
318
319     apic->eoi = 0x00000000;
320     apic->rem_rd_data = 0x00000000;
321     apic->tmr_init_cnt = 0x00000000;
322     apic->tmr_cur_cnt = 0x00000000;
323     apic->missed_ints = 0;
324
325     // note that it's the *lower* 24 bits that are
326     // reserved, not the upper 24.  
327     apic->lapic_id.val = 0;
328     apic->lapic_id.apic_id = id;
329     
330     apic->ipi_state = INIT_ST;
331
332     // The P6 has 6 LVT entries, so we set the value to (6-1)...
333     apic->apic_ver.val = 0x80050010;
334
335     set_apic_tpr(apic,0x00000000);
336     // note that arbitration priority and processor priority are derived values
337     // and are computed on the fly
338
339     apic->log_dst.val = 0x00000000;
340     apic->dst_fmt.val = 0xffffffff;
341     apic->spurious_int.val = 0x000000ff;
342     apic->err_status.val = 0x00000000;
343     apic->int_cmd.val = 0x0000000000000000LL;
344     apic->tmr_vec_tbl.val = 0x00010000;
345     apic->therm_loc_vec_tbl.val = 0x00010000;
346     apic->perf_ctr_loc_vec_tbl.val = 0x00010000;
347     apic->lint0_vec_tbl.val = 0x00010000;
348     apic->lint1_vec_tbl.val = 0x00010000;
349     apic->err_vec_tbl.val = 0x00010000;
350     apic->tmr_div_cfg.val = 0x00000000;
351     //apic->ext_apic_feature.val = 0x00000007;
352     apic->ext_apic_feature.val = 0x00040007;
353     apic->ext_apic_ctrl.val = 0x00000000;
354     apic->spec_eoi.val = 0x00000000;
355
356
357     INIT_LIST_HEAD(&(apic->irq_queue.entries));
358     v3_lock_init(&(apic->irq_queue.lock));
359     apic->irq_queue.num_entries = 0;
360
361 }
362
363
364
365
366
367 static int read_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
368     struct apic_dev_state * apic_dev = (struct apic_dev_state *)priv_data;
369     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]);
370
371     PrintDebug(core->vm_info, core, "apic %u: core %u: MSR read getting %llx\n", apic->lapic_id.val, core->vcpu_id, apic->base_addr_msr.value);
372  
373     dst->value = apic->base_addr_msr.value;
374  
375     return 0;
376 }
377
378
379 static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
380     struct apic_dev_state * apic_dev = (struct apic_dev_state *)priv_data;
381     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]);
382     struct v3_mem_region * old_reg = v3_get_mem_region(core->vm_info, core->vcpu_id, apic->base_addr);
383
384
385     PrintDebug(core->vm_info, core, "apic %u: core %u: MSR write of %llx\n", apic->lapic_id.val, core->vcpu_id, src.value);
386
387     if (old_reg == NULL) {
388         // uh oh...
389         PrintError(core->vm_info, core, "apic %u: core %u: APIC Base address region does not exit...\n",
390                    apic->lapic_id.val, core->vcpu_id);
391         return -1;
392     }
393     
394
395
396     v3_delete_mem_region(core->vm_info, old_reg);
397
398     apic->base_addr_msr.value = src.value;
399
400     // unhook from old location
401     v3_unhook_mem(core->vm_info,core->vcpu_id,apic->base_addr);
402
403     apic->base_addr = src.value & ~0xfffULL;
404
405     // hook to new location
406     if (v3_hook_full_mem(core->vm_info, core->vcpu_id, apic->base_addr, 
407                          apic->base_addr + PAGE_SIZE_4KB, 
408                          apic_read, apic_write, apic_dev) == -1) {
409         PrintError(core->vm_info, core, "apic %u: core %u: Could not hook new APIC Base address\n",
410                    apic->lapic_id.val, core->vcpu_id);
411
412         return -1;
413     }
414
415
416     return 0;
417 }
418
419
420
421
422
423 // irq_num is the bit offset into a 256 bit buffer...
424 static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num, 
425                              int (*ack)(struct guest_info * core, uint32_t irq, void * private_data), 
426                              void * private_data) {
427     int major_offset = (irq_num & ~0x00000007) >> 3;
428     int minor_offset = irq_num & 0x00000007;
429     uint8_t * req_location = apic->int_req_reg + major_offset;
430     uint8_t * en_location = apic->int_en_reg + major_offset;
431     uint8_t flag = 0x1 << minor_offset;
432
433
434     PrintDebug(VM_NONE, VCORE_NONE, "apic %u: core %d: Raising APIC IRQ %d\n", apic->lapic_id.val, apic->core->vcpu_id, irq_num);
435
436     if (*req_location & flag) {
437         PrintDebug(VM_NONE, VCORE_NONE, "Interrupt %d  coallescing\n", irq_num);
438         return 0;
439     }
440
441     if (*en_location & flag) {
442         *req_location |= flag;
443         apic->irq_ack_cbs[irq_num].ack = ack;
444         apic->irq_ack_cbs[irq_num].private_data = private_data;
445
446         return 1;
447     } else {
448         PrintDebug(VM_NONE, VCORE_NONE, "apic %u: core %d: Interrupt  not enabled... %.2x\n", 
449                    apic->lapic_id.val, apic->core->vcpu_id, *en_location);
450     }
451
452     return 0;
453 }
454
455
456
457 static int add_apic_irq_entry(struct apic_state * apic, uint32_t irq_num, 
458                               int (*ack)(struct guest_info * core, uint32_t irq, void * private_data),
459                               void * private_data) {
460     unsigned int flags = 0;
461     struct irq_queue_entry * entry = NULL;
462
463     if (irq_num <= 15) {
464         PrintError(VM_NONE, VCORE_NONE, "core %d: Attempting to raise an invalid interrupt: %d\n", 
465                     apic->core->vcpu_id, irq_num);
466         return -1;
467     }
468
469     entry = V3_Malloc(sizeof(struct irq_queue_entry));
470
471     if (entry == NULL) {
472         PrintError(VM_NONE, VCORE_NONE, "Could not allocate irq queue entry\n");
473         return -1;
474     }
475
476     entry->vector = irq_num;
477     entry->ack = ack;
478     entry->private_data = private_data;
479
480     flags = v3_lock_irqsave(apic->irq_queue.lock);
481     
482     list_add_tail(&(entry->list_node), &(apic->irq_queue.entries));
483     apic->irq_queue.num_entries++;
484
485     v3_unlock_irqrestore(apic->irq_queue.lock, flags);
486   
487
488     return 0;
489 }
490
491 static void drain_irq_entries(struct apic_state * apic) {
492
493     while (1) {
494         unsigned int flags = 0;
495         struct irq_queue_entry * entry = NULL;
496     
497         flags = v3_lock_irqsave(apic->irq_queue.lock);
498         
499         if (!list_empty(&(apic->irq_queue.entries))) {
500             struct list_head * q_entry = apic->irq_queue.entries.next;
501             entry = list_entry(q_entry, struct irq_queue_entry, list_node);
502
503             apic->irq_queue.num_entries--;
504             list_del(q_entry);
505         }
506         
507         v3_unlock_irqrestore(apic->irq_queue.lock, flags);
508
509         if (entry == NULL) {
510             break;
511         }
512
513         activate_apic_irq(apic, entry->vector, entry->ack, entry->private_data);
514
515         V3_Free(entry);
516     }
517
518 }
519
520
521
522 static int get_highest_isr(struct apic_state * apic) {
523     int i = 0, j = 0;
524
525     // We iterate backwards to find the highest priority in-service request
526     for (i = 31; i >= 0; i--) {
527         uint8_t  * svc_major = apic->int_svc_reg + i;
528     
529         if ((*svc_major) & 0xff) {
530             for (j = 7; j >= 0; j--) {
531                 uint8_t flag = 0x1 << j;
532                 if ((*svc_major) & flag) {
533                     return ((i * 8) + j);
534                 }
535             }
536         }
537     }
538
539     return -1;
540 }
541  
542
543
544 static int get_highest_irr(struct apic_state * apic) {
545     int i = 0, j = 0;
546
547     // We iterate backwards to find the highest priority enabled requested interrupt
548     for (i = 31; i >= 0; i--) {
549         uint8_t  * req_major = apic->int_req_reg + i;
550         uint8_t  * en_major = apic->int_en_reg + i;
551         
552         if ((*req_major) & 0xff) {
553             for (j = 7; j >= 0; j--) {
554                 uint8_t flag = 0x1 << j;
555                 if ((*req_major & *en_major) & flag) {
556                     return ((i * 8) + j);
557                 }
558             }
559         }
560     }
561
562     return -1;
563 }
564  
565
566 static uint32_t get_isrv(struct apic_state *apic)
567 {
568     int isr = get_highest_isr(apic);
569     
570     if (isr>=0) { 
571         return (uint32_t) isr;
572     } else {
573         return 0;
574     }
575 }
576
577 static uint32_t get_irrv(struct apic_state *apic)
578 {
579     int irr = get_highest_irr(apic);
580     
581     if (irr>=0) { 
582         return (uint32_t) irr;
583     } else {
584         return 0;
585     }
586 }
587
588
589 static uint32_t get_apic_tpr(struct apic_state *apic)
590 {
591     return (uint32_t) (apic->core->ctrl_regs.apic_tpr); // see comment in vmm_ctrl_regs.c for how this works
592
593 }
594
595 static void set_apic_tpr(struct apic_state *apic, uint32_t val)
596 {
597     PrintDebug(VM_NONE, VCORE_NONE, "Set apic_tpr to 0x%x from apic reg path\n",val);
598     apic->core->ctrl_regs.apic_tpr = (uint64_t) val; // see comment in vmm_ctrl_regs.c for how this works
599 }
600
601 static uint32_t get_apic_ppr(struct apic_state *apic)
602 {
603     uint32_t tpr = get_apic_tpr(apic);
604     uint32_t isrv = get_isrv(apic);
605     uint32_t tprlevel, isrlevel;
606     uint32_t ppr;
607
608     tprlevel = (tpr >> 4) & 0xf;
609     isrlevel = (isrv >> 4) & 0xf;
610
611     if (tprlevel>=isrlevel) { 
612         ppr = tpr;  // get class and subclass
613     } else { 
614         ppr = (isrlevel << 4); // get class only
615     }
616     
617     return ppr;
618 }
619
620
621
622 static uint32_t get_apic_apr(struct apic_state *apic)
623 {
624     uint32_t tpr = get_apic_tpr(apic);
625     uint32_t isrv = get_isrv(apic);
626     uint32_t irrv = get_irrv(apic);
627     uint32_t tprlevel, isrlevel, irrlevel;
628
629     tprlevel = (tpr >> 4) & 0xf;
630     isrlevel = (isrv >> 4) & 0xf;
631     irrlevel = (irrv >> 4) & 0xf;
632
633     if (tprlevel >= isrlevel) { 
634         if (tprlevel >= irrlevel) { 
635             return tpr;  // get both class and subclass
636         } else {
637             return irrlevel << 4; // get class only
638         }
639     } else {
640         if (isrlevel >= irrlevel) {
641             return isrlevel << 4; // get class only
642         } else {
643             return irrlevel << 4; // get class only
644         }
645     }
646     
647 }
648
649
650 static int apic_do_eoi(struct guest_info * core, struct apic_state * apic) {
651     int isr_irq = get_highest_isr(apic);
652
653     if (isr_irq != -1) {
654         int major_offset = (isr_irq & ~0x00000007) >> 3;
655         int minor_offset = isr_irq & 0x00000007;
656         uint8_t flag = 0x1 << minor_offset;
657         uint8_t * svc_location = apic->int_svc_reg + major_offset;
658         
659         PrintDebug(core->vm_info, core, "apic %u: core ?: Received APIC EOI for IRQ %d\n", apic->lapic_id.val,isr_irq);
660         
661         *svc_location &= ~flag;
662
663         if (apic->irq_ack_cbs[isr_irq].ack) {
664             apic->irq_ack_cbs[isr_irq].ack(core, isr_irq, apic->irq_ack_cbs[isr_irq].private_data);
665         }
666
667 #ifdef V3_CONFIG_CRAY_XT
668         
669         if ((isr_irq == 238) || 
670             (isr_irq == 239)) {
671             PrintDebug(core->vm_info, core, "apic %u: core ?: Acking IRQ %d\n", apic->lapic_id.val,isr_irq);
672         }
673         
674         if (isr_irq == 238) {
675             V3_ACK_IRQ(238);
676         }
677 #endif
678     } else {
679         //PrintError(core->vm_info, core, "apic %u: core ?: Spurious EOI...\n",apic->lapic_id.val);
680     }
681         
682     return 0;
683 }
684  
685
686 static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_type) {
687     uint32_t vec_num = 0;
688     uint32_t del_mode = 0;
689     int masked = 0;
690
691
692     switch (int_type) {
693         case APIC_TMR_INT:
694             vec_num = apic->tmr_vec_tbl.vec;
695             del_mode = IPI_FIXED;
696             masked = apic->tmr_vec_tbl.mask;
697             break;
698         case APIC_THERM_INT:
699             vec_num = apic->therm_loc_vec_tbl.vec;
700             del_mode = apic->therm_loc_vec_tbl.msg_type;
701             masked = apic->therm_loc_vec_tbl.mask;
702             break;
703         case APIC_PERF_INT:
704             vec_num = apic->perf_ctr_loc_vec_tbl.vec;
705             del_mode = apic->perf_ctr_loc_vec_tbl.msg_type;
706             masked = apic->perf_ctr_loc_vec_tbl.mask;
707             break;
708         case APIC_LINT0_INT:
709             vec_num = apic->lint0_vec_tbl.vec;
710             del_mode = apic->lint0_vec_tbl.msg_type;
711             masked = apic->lint0_vec_tbl.mask;
712             break;
713         case APIC_LINT1_INT:
714             vec_num = apic->lint1_vec_tbl.vec;
715             del_mode = apic->lint1_vec_tbl.msg_type;
716             masked = apic->lint1_vec_tbl.mask;
717             break;
718         case APIC_ERR_INT:
719             vec_num = apic->err_vec_tbl.vec;
720             del_mode = IPI_FIXED;
721             masked = apic->err_vec_tbl.mask;
722             break;
723         default:
724             PrintError(VM_NONE, VCORE_NONE, "apic %u: core ?: Invalid APIC interrupt type\n", apic->lapic_id.val);
725             return -1;
726     }
727
728     // interrupt is masked, don't send
729     if (masked == 1) {
730         PrintDebug(VM_NONE, VCORE_NONE, "apic %u: core ?: Inerrupt is masked\n", apic->lapic_id.val);
731         return 0;
732     }
733
734     if (del_mode == IPI_FIXED) {
735         //PrintDebug(VM_NONE, VCORE_NONE, "Activating internal APIC IRQ %d\n", vec_num);
736         return add_apic_irq_entry(apic, vec_num, NULL, NULL);
737     } else {
738         PrintError(VM_NONE, VCORE_NONE, "apic %u: core ?: Unhandled Delivery Mode\n", apic->lapic_id.val);
739         return -1;
740     }
741 }
742
743
744
745 static inline int should_deliver_cluster_ipi(struct apic_dev_state * apic_dev,
746                                              struct guest_info * dst_core, 
747                                              struct apic_state * dst_apic, uint8_t mda) {
748
749     int ret = 0;
750
751
752     if  ( ((mda & 0xf0) == (dst_apic->log_dst.dst_log_id & 0xf0)) &&  /* (I am in the cluster and */
753           ((mda & 0x0f) & (dst_apic->log_dst.dst_log_id & 0x0f)) ) {  /*  I am in the set)        */
754         ret = 1;
755     } else {
756         ret = 0;
757     }
758
759
760     if (ret == 1) {
761         PrintDebug(VM_NONE, VCORE_NONE, "apic %u core %u: accepting clustered IRQ (mda 0x%x == log_dst 0x%x)\n",
762                    dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
763                    dst_apic->log_dst.dst_log_id);
764     } else {
765         PrintDebug(VM_NONE, VCORE_NONE, "apic %u core %u: rejecting clustered IRQ (mda 0x%x != log_dst 0x%x)\n",
766                    dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
767                    dst_apic->log_dst.dst_log_id);
768     }
769
770     return ret;
771
772 }
773
774 static inline int should_deliver_flat_ipi(struct apic_dev_state * apic_dev,
775                                           struct guest_info * dst_core,
776                                           struct apic_state * dst_apic, uint8_t mda) {
777
778     int ret = 0;
779
780
781     if ((dst_apic->log_dst.dst_log_id & mda) != 0) {  // I am in the set 
782         ret = 1;
783     } else {
784         ret = 0;
785     }
786
787
788     if (ret == 1) {
789         PrintDebug(VM_NONE, VCORE_NONE, "apic %u core %u: accepting flat IRQ (mda 0x%x == log_dst 0x%x)\n",
790                    dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
791                    dst_apic->log_dst.dst_log_id);
792     } else {
793         PrintDebug(VM_NONE, VCORE_NONE, "apic %u core %u: rejecting flat IRQ (mda 0x%x != log_dst 0x%x)\n",
794                    dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
795                    dst_apic->log_dst.dst_log_id);
796     }
797
798
799     return ret;
800 }
801
802
803
804 static int should_deliver_ipi(struct apic_dev_state * apic_dev, 
805                               struct guest_info * dst_core, 
806                               struct apic_state * dst_apic, uint8_t mda) {
807     addr_t flags = 0;
808     int ret = 0;
809
810     flags = v3_lock_irqsave(apic_dev->state_lock);
811
812     if (dst_apic->dst_fmt.model == 0xf) {
813
814         if (mda == 0xff) {
815             /* always deliver broadcast */
816             ret = 1;
817         } else {
818             ret = should_deliver_flat_ipi(apic_dev, dst_core, dst_apic, mda);
819         }
820     } else if (dst_apic->dst_fmt.model == 0x0) {
821
822         if (mda == 0xff) {
823             /*  always deliver broadcast */
824             ret = 1;
825         } else {
826             ret = should_deliver_cluster_ipi(apic_dev, dst_core, dst_apic, mda);
827         }
828
829     } else {
830         ret = -1;
831     }
832     
833     v3_unlock_irqrestore(apic_dev->state_lock, flags);
834
835
836     if (ret == -1) {
837         PrintError(VM_NONE, VCORE_NONE, "apic %u core %u: invalid destination format register value 0x%x for logical mode delivery.\n", 
838                    dst_apic->lapic_id.val, dst_core->vcpu_id, dst_apic->dst_fmt.model);
839     }
840
841     return ret;
842 }
843
844
845
846
847 // Only the src_apic pointer is used
848 static int deliver_ipi(struct apic_state * src_apic, 
849                        struct apic_state * dst_apic, 
850                        struct v3_gen_ipi * ipi) {
851
852
853     struct guest_info * dst_core = dst_apic->core;
854
855
856     switch (ipi->mode) {
857
858         case IPI_FIXED:  
859         case IPI_LOWEST_PRIO: {
860             // lowest priority - 
861             // caller needs to have decided which apic to deliver to!
862
863             PrintDebug(VM_NONE, VCORE_NONE, "delivering IRQ %d to core %u\n", ipi->vector, dst_core->vcpu_id); 
864
865             add_apic_irq_entry(dst_apic, ipi->vector, ipi->ack, ipi->private_data);
866             
867             if (dst_apic != src_apic) { 
868                 PrintDebug(VM_NONE, VCORE_NONE, " non-local core with new interrupt, forcing it to exit now\n"); 
869                 v3_interrupt_cpu(dst_core->vm_info, dst_core->pcpu_id, 0);
870             }
871
872             break;
873         }
874         case IPI_INIT: { 
875
876             PrintDebug(VM_NONE, VCORE_NONE, " INIT delivery to core %u\n", dst_core->vcpu_id);
877
878             if (is_apic_bsp(dst_apic)) {
879                 PrintError(VM_NONE, VCORE_NONE, "Attempted to INIT BSP CPU. Ignoring since I have no idea what the hell to do...\n");
880                 break;
881             }
882
883
884             if (dst_apic->ipi_state != INIT_ST) { 
885                 v3_raise_barrier(dst_core->vm_info, src_apic->core);
886                 dst_core->core_run_state = CORE_STOPPED;
887                 dst_apic->ipi_state = INIT_ST;
888                 v3_lower_barrier(dst_core->vm_info);
889
890             }
891
892             // We transition the target core to SIPI state
893             dst_apic->ipi_state = SIPI;  // note: locking should not be needed here
894
895             // That should be it since the target core should be
896             // waiting in host on this transition
897             // either it's on another core or on a different preemptive thread
898             // in both cases, it will quickly notice this transition 
899             // in particular, we should not need to force an exit here
900
901             PrintDebug(VM_NONE, VCORE_NONE, " INIT delivery done\n");
902
903             break;                                                      
904         }
905         case IPI_SIPI: { 
906
907             // Sanity check
908             if (dst_apic->ipi_state != SIPI) { 
909                 PrintError(VM_NONE, VCORE_NONE, " core %u is not in SIPI state (mode = %d), ignored!\n",
910                            dst_core->vcpu_id, dst_apic->ipi_state);
911                 break;
912             }
913
914             v3_reset_vm_core(dst_core, ipi->vector);
915
916             PrintDebug(VM_NONE, VCORE_NONE, " SIPI delivery (0x%x -> 0x%x:0x0) to core %u\n",
917                        ipi->vector, dst_core->segments.cs.selector, dst_core->vcpu_id);
918             // Maybe need to adjust the APIC?
919             
920             // We transition the target core to SIPI state
921             dst_core->core_run_state = CORE_RUNNING;  // note: locking should not be needed here
922             dst_apic->ipi_state = STARTED;
923             
924             // As with INIT, we should not need to do anything else
925             
926             PrintDebug(VM_NONE, VCORE_NONE, " SIPI delivery done\n");
927             
928             break;                                                      
929         }
930
931         case IPI_EXTINT: // EXTINT
932             /* Two possible things to do here: 
933              * 1. Ignore the IPI and assume the 8259a (PIC) will handle it
934              * 2. Add 32 to the vector and inject it...
935              * We probably just want to do 1 here, and assume the raise_irq() will hit the 8259a.
936              */
937             return 0;
938
939         case IPI_SMI: 
940         case IPI_RES1: // reserved                                              
941         case IPI_NMI:
942         default:
943             PrintError(VM_NONE, VCORE_NONE, "IPI %d delivery is unsupported\n", ipi->mode); 
944             return -1;
945     }
946     
947     return 0;
948     
949 }
950
951 static struct apic_state * find_physical_apic(struct apic_dev_state * apic_dev, uint32_t dst_idx) {
952     struct apic_state * dst_apic = NULL;
953     addr_t flags;
954     int i;
955
956     flags = v3_lock_irqsave(apic_dev->state_lock);
957
958     if ( (dst_idx > 0) && (dst_idx < apic_dev->num_apics) ) { 
959         // see if it simply is the core id
960         if (apic_dev->apics[dst_idx].lapic_id.apic_id == dst_idx) { 
961              dst_apic = &(apic_dev->apics[dst_idx]);
962         }
963     }
964
965     for (i = 0; i < apic_dev->num_apics; i++) { 
966         if (apic_dev->apics[i].lapic_id.apic_id == dst_idx) { 
967             dst_apic =  &(apic_dev->apics[i]);
968         }
969     }
970
971     v3_unlock_irqrestore(apic_dev->state_lock, flags);
972
973     return dst_apic;
974
975 }
976
977
978 static int route_ipi(struct apic_dev_state * apic_dev,
979                      struct apic_state * src_apic, 
980                      struct v3_gen_ipi * ipi) {
981     struct apic_state * dest_apic = NULL;
982
983
984     PrintDebug(VM_NONE, VCORE_NONE, "apic: IPI %s %u from apic %p to %s %s %u\n",
985                deliverymode_str[ipi->mode], 
986                ipi->vector, 
987                src_apic,               
988                (ipi->logical == 0) ? "(physical)" : "(logical)", 
989                shorthand_str[ipi->dst_shorthand], 
990                ipi->dst);
991
992
993     switch (ipi->dst_shorthand) {
994
995         case APIC_SHORTHAND_NONE:  // no shorthand
996             if (ipi->logical == APIC_DEST_PHYSICAL) { 
997
998                 dest_apic = find_physical_apic(apic_dev, ipi->dst);
999                 
1000                 if (dest_apic == NULL) { 
1001                     PrintError(VM_NONE, VCORE_NONE, "apic: Attempted send to unregistered apic id=%u\n", ipi->dst);
1002                     return -1;
1003                 }
1004
1005                 if (deliver_ipi(src_apic, dest_apic, ipi) == -1) {
1006                     PrintError(VM_NONE, VCORE_NONE, "apic: Could not deliver IPI\n");
1007                     return -1;
1008                 }
1009
1010
1011                 PrintDebug(VM_NONE, VCORE_NONE, "apic: done\n");
1012
1013             } else if (ipi->logical == APIC_DEST_LOGICAL) {
1014                 
1015                 if (ipi->mode != IPI_LOWEST_PRIO) { 
1016                     int i;
1017                     uint8_t mda = ipi->dst;
1018
1019                     // logical, but not lowest priority
1020                     // we immediately trigger
1021                     // fixed, smi, reserved, nmi, init, sipi, etc
1022
1023                     
1024                     for (i = 0; i < apic_dev->num_apics; i++) { 
1025                         int del_flag = 0;
1026                         
1027                         dest_apic = &(apic_dev->apics[i]);
1028                         
1029                         del_flag = should_deliver_ipi(apic_dev, dest_apic->core, dest_apic, mda);
1030                         
1031                         if (del_flag == -1) {
1032
1033                             PrintError(VM_NONE, VCORE_NONE, "apic: Error checking delivery mode\n");
1034                             return -1;
1035                         } else if (del_flag == 1) {
1036
1037                             if (deliver_ipi(src_apic, dest_apic, ipi) == -1) {
1038                                 PrintError(VM_NONE, VCORE_NONE, "apic: Error: Could not deliver IPI\n");
1039                                 return -1;
1040                             }
1041                         }
1042                     }
1043                 } else {  // APIC_LOWEST_DELIVERY
1044                     struct apic_state * cur_best_apic = NULL;
1045                     uint32_t cur_best_apr;
1046                     uint8_t mda = ipi->dst;
1047                     int i;
1048
1049                     // logical, lowest priority
1050
1051                     for (i = 0; i < apic_dev->num_apics; i++) { 
1052                         int del_flag = 0;
1053
1054                         dest_apic = &(apic_dev->apics[i]);
1055                         
1056                         del_flag = should_deliver_ipi(apic_dev, dest_apic->core, dest_apic, mda);
1057                         
1058                         if (del_flag == -1) {
1059                             PrintError(VM_NONE, VCORE_NONE, "apic: Error checking delivery mode\n");
1060
1061                             return -1;
1062                         } else if (del_flag == 1) {
1063                             // update priority for lowest priority scan
1064                             addr_t flags = 0;
1065
1066                             flags = v3_lock_irqsave(apic_dev->state_lock);
1067
1068                             if (cur_best_apic == 0) {
1069                                 cur_best_apic = dest_apic;  
1070                                 cur_best_apr = get_apic_apr(dest_apic) & 0xf0;
1071                             } else {
1072                                 uint32_t dest_apr = get_apic_apr(dest_apic) & 0xf0;
1073                                 if (dest_apr < cur_best_apr) {
1074                                     cur_best_apic = dest_apic;
1075                                     cur_best_apr = dest_apr;
1076                                 }
1077                             } 
1078
1079                             v3_unlock_irqrestore(apic_dev->state_lock, flags);
1080
1081                         }
1082                     }
1083
1084                     // now we will deliver to the best one if it exists
1085                     if (!cur_best_apic) { 
1086                         PrintDebug(VM_NONE, VCORE_NONE, "apic: lowest priority deliver, but no destinations!\n");
1087                     } else {
1088                         if (deliver_ipi(src_apic, cur_best_apic, ipi) == -1) {
1089                             PrintError(VM_NONE, VCORE_NONE, "apic: Error: Could not deliver IPI\n");
1090                             return -1;
1091                         }
1092                         //V3_Print(VM_NONE, VCORE_NONE, "apic: logical, lowest priority delivery to apic %u\n",cur_best_apic->lapic_id.val);
1093                     }
1094                 }
1095             }
1096
1097             break;
1098             
1099         case APIC_SHORTHAND_SELF:  // self
1100
1101             if (src_apic == NULL) {    /* this is not an apic, but it's trying to send to itself??? */
1102                 PrintError(VM_NONE, VCORE_NONE, "apic: Sending IPI to self from generic IPI sender\n");
1103                 break;
1104             }
1105
1106
1107
1108             if (ipi->logical == APIC_DEST_PHYSICAL)  {  /* physical delivery */
1109                 if (deliver_ipi(src_apic, src_apic, ipi) == -1) {
1110                     PrintError(VM_NONE, VCORE_NONE, "apic: Could not deliver IPI to self (physical)\n");
1111                     return -1;
1112                 }
1113             } else if (ipi->logical == APIC_DEST_LOGICAL) {  /* logical delivery */
1114                 PrintError(VM_NONE, VCORE_NONE, "apic: use of logical delivery in self (untested)\n");
1115
1116                 if (deliver_ipi(src_apic, src_apic, ipi) == -1) {
1117                     PrintError(VM_NONE, VCORE_NONE, "apic: Could not deliver IPI to self (logical)\n");
1118                     return -1;
1119                 }
1120             }
1121
1122             break;
1123             
1124         case APIC_SHORTHAND_ALL: 
1125         case APIC_SHORTHAND_ALL_BUT_ME: { /* all and all-but-me */
1126             /* assuming that logical verus physical doesn't matter
1127                although it is odd that both are used */
1128             int i;
1129
1130             for (i = 0; i < apic_dev->num_apics; i++) { 
1131                 dest_apic = &(apic_dev->apics[i]);
1132                 
1133                 if ((dest_apic != src_apic) || (ipi->dst_shorthand == APIC_SHORTHAND_ALL)) { 
1134                     if (deliver_ipi(src_apic, dest_apic, ipi) == -1) {
1135                         PrintError(VM_NONE, VCORE_NONE, "apic: Error: Could not deliver IPI\n");
1136                         return -1;
1137                     }
1138                 }
1139             }
1140
1141             break;
1142         }
1143         default:
1144             PrintError(VM_NONE, VCORE_NONE, "apic: Error routing IPI, invalid Mode (%d)\n", ipi->dst_shorthand);
1145             return -1;
1146     }
1147  
1148     return 0;
1149 }
1150
1151
1152 // External function, expected to acquire lock on apic
1153 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
1154     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1155     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]);
1156     addr_t reg_addr  = guest_addr - apic->base_addr;
1157     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
1158     uint32_t val = 0;
1159
1160
1161     PrintDebug(core->vm_info, core, "apic %u: core %u: at %p: Read apic address space (%p)\n",
1162                apic->lapic_id.val, core->vcpu_id, apic, (void *)guest_addr);
1163
1164     if (msr->apic_enable == 0) {
1165         PrintError(core->vm_info, core, "apic %u: core %u: Read from APIC address space with disabled APIC, apic msr=0x%llx\n",
1166                    apic->lapic_id.val, core->vcpu_id, apic->base_addr_msr.value);
1167         return -1;
1168     }
1169
1170
1171     /* Because "May not be supported" doesn't matter to Linux developers... */
1172     /*   if (length != 4) { */
1173     /*     PrintError(core->vm_info, core, "Invalid apic read length (%d)\n", length); */
1174     /*     return -1; */
1175     /*   } */
1176
1177     switch (reg_addr & ~0x3) {
1178         case EOI_OFFSET:
1179             // Well, only an idiot would read from a architectural write only register
1180             // Oh, Hello Linux.
1181             //    PrintError(core->vm_info, core, "Attempting to read from write only register\n");
1182             //    return -1;
1183             break;
1184
1185             // data registers
1186         case APIC_ID_OFFSET:
1187             val = apic->lapic_id.val;
1188             break;
1189         case APIC_VERSION_OFFSET:
1190             val = apic->apic_ver.val;
1191             break;
1192         case TPR_OFFSET:
1193             val = get_apic_tpr(apic);
1194             break;
1195         case APR_OFFSET:
1196             val = get_apic_apr(apic);
1197             break;
1198         case PPR_OFFSET:
1199             val = get_apic_ppr(apic);
1200             break;
1201         case REMOTE_READ_OFFSET:
1202             val = apic->rem_rd_data;
1203             break;
1204         case LDR_OFFSET:
1205             val = apic->log_dst.val;
1206             break;
1207         case DFR_OFFSET:
1208             val = apic->dst_fmt.val;
1209             break;
1210         case SPURIOUS_INT_VEC_OFFSET:
1211             val = apic->spurious_int.val;
1212             break;
1213         case ESR_OFFSET:
1214             val = apic->err_status.val;
1215             break;
1216         case TMR_LOC_VEC_TBL_OFFSET:
1217             val = apic->tmr_vec_tbl.val;
1218             break;
1219         case LINT0_VEC_TBL_OFFSET:
1220             val = apic->lint0_vec_tbl.val;
1221             break;
1222         case LINT1_VEC_TBL_OFFSET:
1223             val = apic->lint1_vec_tbl.val;
1224             break;
1225         case ERR_VEC_TBL_OFFSET:
1226             val = apic->err_vec_tbl.val;
1227             break;
1228         case TMR_INIT_CNT_OFFSET:
1229             val = apic->tmr_init_cnt;
1230             break;
1231         case TMR_DIV_CFG_OFFSET:
1232             val = apic->tmr_div_cfg.val;
1233             break;
1234
1235         case IER_OFFSET0:
1236             val = *(uint32_t *)(apic->int_en_reg);
1237             break;
1238         case IER_OFFSET1:
1239             val = *(uint32_t *)(apic->int_en_reg + 4);
1240             break;
1241         case IER_OFFSET2:
1242             val = *(uint32_t *)(apic->int_en_reg + 8);
1243             break;
1244         case IER_OFFSET3:
1245             val = *(uint32_t *)(apic->int_en_reg + 12);
1246             break;
1247         case IER_OFFSET4:
1248             val = *(uint32_t *)(apic->int_en_reg + 16);
1249             break;
1250         case IER_OFFSET5:
1251             val = *(uint32_t *)(apic->int_en_reg + 20);
1252             break;
1253         case IER_OFFSET6:
1254             val = *(uint32_t *)(apic->int_en_reg + 24);
1255             break;
1256         case IER_OFFSET7:
1257             val = *(uint32_t *)(apic->int_en_reg + 28);
1258             break;
1259
1260         case ISR_OFFSET0:
1261             val = *(uint32_t *)(apic->int_svc_reg);
1262             break;
1263         case ISR_OFFSET1:
1264             val = *(uint32_t *)(apic->int_svc_reg + 4);
1265             break;
1266         case ISR_OFFSET2:
1267             val = *(uint32_t *)(apic->int_svc_reg + 8);
1268             break;
1269         case ISR_OFFSET3:
1270             val = *(uint32_t *)(apic->int_svc_reg + 12);
1271             break;
1272         case ISR_OFFSET4:
1273             val = *(uint32_t *)(apic->int_svc_reg + 16);
1274             break;
1275         case ISR_OFFSET5:
1276             val = *(uint32_t *)(apic->int_svc_reg + 20);
1277             break;
1278         case ISR_OFFSET6:
1279             val = *(uint32_t *)(apic->int_svc_reg + 24);
1280             break;
1281         case ISR_OFFSET7:
1282             val = *(uint32_t *)(apic->int_svc_reg + 28);
1283             break;
1284    
1285         case TRIG_OFFSET0:
1286             val = *(uint32_t *)(apic->trig_mode_reg);
1287             break;
1288         case TRIG_OFFSET1:
1289             val = *(uint32_t *)(apic->trig_mode_reg + 4);
1290             break;
1291         case TRIG_OFFSET2:
1292             val = *(uint32_t *)(apic->trig_mode_reg + 8);
1293             break;
1294         case TRIG_OFFSET3:
1295             val = *(uint32_t *)(apic->trig_mode_reg + 12);
1296             break;
1297         case TRIG_OFFSET4:
1298             val = *(uint32_t *)(apic->trig_mode_reg + 16);
1299             break;
1300         case TRIG_OFFSET5:
1301             val = *(uint32_t *)(apic->trig_mode_reg + 20);
1302             break;
1303         case TRIG_OFFSET6:
1304             val = *(uint32_t *)(apic->trig_mode_reg + 24);
1305             break;
1306         case TRIG_OFFSET7:
1307             val = *(uint32_t *)(apic->trig_mode_reg + 28);
1308             break;
1309
1310         case IRR_OFFSET0:
1311             val = *(uint32_t *)(apic->int_req_reg);
1312             break;
1313         case IRR_OFFSET1:
1314             val = *(uint32_t *)(apic->int_req_reg + 4);
1315             break;
1316         case IRR_OFFSET2:
1317             val = *(uint32_t *)(apic->int_req_reg + 8);
1318             break;
1319         case IRR_OFFSET3:
1320             val = *(uint32_t *)(apic->int_req_reg + 12);
1321             break;
1322         case IRR_OFFSET4:
1323             val = *(uint32_t *)(apic->int_req_reg + 16);
1324             break;
1325         case IRR_OFFSET5:
1326             val = *(uint32_t *)(apic->int_req_reg + 20);
1327             break;
1328         case IRR_OFFSET6:
1329             val = *(uint32_t *)(apic->int_req_reg + 24);
1330             break;
1331         case IRR_OFFSET7:
1332             val = *(uint32_t *)(apic->int_req_reg + 28);
1333             break;
1334         case TMR_CUR_CNT_OFFSET:
1335             val = apic->tmr_cur_cnt;
1336             break;
1337
1338             // We are not going to implement these....
1339         case THERM_LOC_VEC_TBL_OFFSET:
1340             val = apic->therm_loc_vec_tbl.val;
1341             break;
1342         case PERF_CTR_LOC_VEC_TBL_OFFSET:
1343             val = apic->perf_ctr_loc_vec_tbl.val;
1344             break;
1345
1346  
1347
1348             // handled registers
1349         case INT_CMD_LO_OFFSET:    
1350             val = apic->int_cmd.lo;
1351             break;
1352         case INT_CMD_HI_OFFSET:
1353             val = apic->int_cmd.hi;
1354             break;
1355
1356             // handle current timer count
1357
1358             // Unhandled Registers
1359         case EXT_INT_LOC_VEC_TBL_OFFSET0:
1360             val = apic->ext_intr_vec_tbl[0].val;
1361             break;
1362         case EXT_INT_LOC_VEC_TBL_OFFSET1:
1363             val = apic->ext_intr_vec_tbl[1].val;
1364             break;
1365         case EXT_INT_LOC_VEC_TBL_OFFSET2:
1366             val = apic->ext_intr_vec_tbl[2].val;
1367             break;
1368         case EXT_INT_LOC_VEC_TBL_OFFSET3:
1369             val = apic->ext_intr_vec_tbl[3].val;
1370             break;
1371     
1372
1373         case EXT_APIC_FEATURE_OFFSET:
1374         case EXT_APIC_CMD_OFFSET:
1375         case SEOI_OFFSET:
1376
1377         default:
1378             PrintError(core->vm_info, core, "apic %u: core %u: Read from Unhandled APIC Register: %x (getting zero)\n", 
1379                        apic->lapic_id.val, core->vcpu_id, (uint32_t)reg_addr);
1380             return -1;
1381     }
1382
1383
1384     if (length == 1) {
1385         uint_t byte_addr = reg_addr & 0x3;
1386         uint8_t * val_ptr = (uint8_t *)dst;
1387     
1388         *val_ptr = *(((uint8_t *)&val) + byte_addr);
1389
1390     } else if ((length == 2) && 
1391                ((reg_addr & 0x3) != 0x3)) {
1392         uint_t byte_addr = reg_addr & 0x3;
1393         uint16_t * val_ptr = (uint16_t *)dst;
1394         *val_ptr = *(((uint16_t *)&val) + byte_addr);
1395
1396     } else if (length == 4) {
1397         uint32_t * val_ptr = (uint32_t *)dst;
1398         *val_ptr = val;
1399
1400     } else {
1401         PrintError(core->vm_info, core, "apic %u: core %u: Invalid apic read length (%d)\n", 
1402                    apic->lapic_id.val, core->vcpu_id, length);
1403         return -1;
1404     }
1405
1406     PrintDebug(core->vm_info, core, "apic %u: core %u: Read finished (val=%x)\n", 
1407                apic->lapic_id.val, core->vcpu_id, *(uint32_t *)dst);
1408
1409     return length;
1410 }
1411
1412
1413 /**
1414  *
1415  */
1416 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data) {
1417     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1418     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1419     addr_t reg_addr  = guest_addr - apic->base_addr;
1420     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
1421     uint32_t op_val = *(uint32_t *)src;
1422     addr_t flags = 0;
1423
1424     PrintDebug(core->vm_info, core, "apic %u: core %u: at %p and priv_data is at %p\n",
1425                apic->lapic_id.val, core->vcpu_id, apic, priv_data);
1426
1427     PrintDebug(core->vm_info, core, "apic %u: core %u: write to address space (%p) (val=%x)\n", 
1428                apic->lapic_id.val, core->vcpu_id, (void *)guest_addr, *(uint32_t *)src);
1429
1430     if (msr->apic_enable == 0) {
1431         PrintError(core->vm_info, core, "apic %u: core %u: Write to APIC address space with disabled APIC, apic msr=0x%llx\n",
1432                    apic->lapic_id.val, core->vcpu_id, apic->base_addr_msr.value);
1433         return -1;
1434     }
1435
1436
1437     if (length != 4) {
1438         PrintError(core->vm_info, core, "apic %u: core %u: Invalid apic write length (%d)\n", 
1439                    apic->lapic_id.val, length, core->vcpu_id);
1440         return -1;
1441     }
1442
1443     switch (reg_addr) {
1444         case REMOTE_READ_OFFSET:
1445         case APIC_VERSION_OFFSET:
1446         case APR_OFFSET:
1447         case IRR_OFFSET0:
1448         case IRR_OFFSET1:
1449         case IRR_OFFSET2:
1450         case IRR_OFFSET3:
1451         case IRR_OFFSET4:
1452         case IRR_OFFSET5:
1453         case IRR_OFFSET6:
1454         case IRR_OFFSET7:
1455         case ISR_OFFSET0:
1456         case ISR_OFFSET1:
1457         case ISR_OFFSET2:
1458         case ISR_OFFSET3:
1459         case ISR_OFFSET4:
1460         case ISR_OFFSET5:
1461         case ISR_OFFSET6:
1462         case ISR_OFFSET7:
1463         case TRIG_OFFSET0:
1464         case TRIG_OFFSET1:
1465         case TRIG_OFFSET2:
1466         case TRIG_OFFSET3:
1467         case TRIG_OFFSET4:
1468         case TRIG_OFFSET5:
1469         case TRIG_OFFSET6:
1470         case TRIG_OFFSET7:
1471         case PPR_OFFSET:
1472         case EXT_APIC_FEATURE_OFFSET:
1473
1474             PrintError(core->vm_info, core, "apic %u: core %u: Attempting to write to read only register %p (error)\n", 
1475                        apic->lapic_id.val, core->vcpu_id, (void *)reg_addr);
1476
1477             break;
1478
1479             // Data registers
1480         case APIC_ID_OFFSET:
1481             //V3_Print(core->vm_info, core, "apic %u: core %u: my id is being changed to %u\n", 
1482             //       apic->lapic_id.val, core->vcpu_id, op_val);
1483
1484             apic->lapic_id.val = op_val;
1485             break;
1486         case TPR_OFFSET:
1487             set_apic_tpr(apic,op_val);
1488             break;
1489         case LDR_OFFSET:
1490             PrintDebug(core->vm_info, core, "apic %u: core %u: setting log_dst.val to 0x%x\n",
1491                        apic->lapic_id.val, core->vcpu_id, op_val);
1492             flags = v3_lock_irqsave(apic_dev->state_lock);
1493             apic->log_dst.val = op_val;
1494             v3_unlock_irqrestore(apic_dev->state_lock, flags);
1495             break;
1496         case DFR_OFFSET:
1497             flags = v3_lock_irqsave(apic_dev->state_lock);
1498             apic->dst_fmt.val = op_val;
1499             v3_unlock_irqrestore(apic_dev->state_lock, flags);
1500             break;
1501         case SPURIOUS_INT_VEC_OFFSET:
1502             apic->spurious_int.val = op_val;
1503             break;
1504         case ESR_OFFSET:
1505             apic->err_status.val = op_val;
1506             break;
1507         case TMR_LOC_VEC_TBL_OFFSET:
1508             apic->tmr_vec_tbl.val = op_val;
1509             break;
1510         case THERM_LOC_VEC_TBL_OFFSET:
1511             apic->therm_loc_vec_tbl.val = op_val;
1512             break;
1513         case PERF_CTR_LOC_VEC_TBL_OFFSET:
1514             apic->perf_ctr_loc_vec_tbl.val = op_val;
1515             break;
1516         case LINT0_VEC_TBL_OFFSET:
1517             apic->lint0_vec_tbl.val = op_val;
1518             break;
1519         case LINT1_VEC_TBL_OFFSET:
1520             apic->lint1_vec_tbl.val = op_val;
1521             break;
1522         case ERR_VEC_TBL_OFFSET:
1523             apic->err_vec_tbl.val = op_val;
1524             break;
1525         case TMR_INIT_CNT_OFFSET:
1526             apic->tmr_init_cnt = op_val;
1527             apic->tmr_cur_cnt = op_val;
1528             break;
1529         case TMR_CUR_CNT_OFFSET:
1530             apic->tmr_cur_cnt = op_val;
1531             break;
1532         case TMR_DIV_CFG_OFFSET:
1533             PrintDebug(core->vm_info, core, "apic %u: core %u: setting tmr_div_cfg to 0x%x\n",
1534                        apic->lapic_id.val, core->vcpu_id, op_val);
1535             apic->tmr_div_cfg.val = op_val;
1536             break;
1537
1538
1539             // Enable mask (256 bits)
1540         case IER_OFFSET0:
1541             *(uint32_t *)(apic->int_en_reg) = op_val;
1542             break;
1543         case IER_OFFSET1:
1544             *(uint32_t *)(apic->int_en_reg + 4) = op_val;
1545             break;
1546         case IER_OFFSET2:
1547             *(uint32_t *)(apic->int_en_reg + 8) = op_val;
1548             break;
1549         case IER_OFFSET3:
1550             *(uint32_t *)(apic->int_en_reg + 12) = op_val;
1551             break;
1552         case IER_OFFSET4:
1553             *(uint32_t *)(apic->int_en_reg + 16) = op_val;
1554             break;
1555         case IER_OFFSET5:
1556             *(uint32_t *)(apic->int_en_reg + 20) = op_val;
1557             break;
1558         case IER_OFFSET6:
1559             *(uint32_t *)(apic->int_en_reg + 24) = op_val;
1560             break;
1561         case IER_OFFSET7:
1562             *(uint32_t *)(apic->int_en_reg + 28) = op_val;
1563             break;
1564
1565         case EXT_INT_LOC_VEC_TBL_OFFSET0:
1566             apic->ext_intr_vec_tbl[0].val = op_val;
1567             break;
1568         case EXT_INT_LOC_VEC_TBL_OFFSET1:
1569             apic->ext_intr_vec_tbl[1].val = op_val;
1570             break;
1571         case EXT_INT_LOC_VEC_TBL_OFFSET2:
1572             apic->ext_intr_vec_tbl[2].val = op_val;
1573             break;
1574         case EXT_INT_LOC_VEC_TBL_OFFSET3:
1575             apic->ext_intr_vec_tbl[3].val = op_val;
1576             break;
1577
1578
1579             // Action Registers
1580         case EOI_OFFSET:
1581             // do eoi 
1582             apic_do_eoi(core, apic);
1583             break;
1584
1585         case INT_CMD_LO_OFFSET: {
1586             // execute command 
1587
1588             struct v3_gen_ipi tmp_ipi;
1589
1590             apic->int_cmd.lo = op_val;
1591
1592             tmp_ipi.vector = apic->int_cmd.vec;
1593             tmp_ipi.mode = apic->int_cmd.del_mode;
1594             tmp_ipi.logical = apic->int_cmd.dst_mode;
1595             tmp_ipi.trigger_mode = apic->int_cmd.trig_mode;
1596             tmp_ipi.dst_shorthand = apic->int_cmd.dst_shorthand;
1597             tmp_ipi.dst = apic->int_cmd.dst;
1598                 
1599             tmp_ipi.ack = NULL;
1600             tmp_ipi.private_data = NULL;
1601             
1602
1603             //      V3_Print(core->vm_info, core, "apic %u: core %u: sending cmd 0x%llx to apic %u\n", 
1604             //       apic->lapic_id.val, core->vcpu_id,
1605             //       apic->int_cmd.val, apic->int_cmd.dst);
1606
1607             if (route_ipi(apic_dev, apic, &tmp_ipi) == -1) { 
1608                 PrintError(core->vm_info, core, "IPI Routing failure\n");
1609                 return -1;
1610             }
1611
1612             break;
1613         }
1614         case INT_CMD_HI_OFFSET: {
1615             apic->int_cmd.hi = op_val;
1616             //V3_Print(core->vm_info, core, "apic %u: core %u: writing command high=0x%x\n", apic->lapic_id.val, core->vcpu_id,apic->int_cmd.hi);
1617             break;
1618         }
1619         // Unhandled Registers
1620         case EXT_APIC_CMD_OFFSET:
1621         case SEOI_OFFSET:
1622         default:
1623             PrintError(core->vm_info, core, "apic %u: core %u: Write to Unhandled APIC Register: %x (ignored)\n", 
1624                        apic->lapic_id.val, core->vcpu_id, (uint32_t)reg_addr);
1625
1626             return -1;
1627     }
1628
1629     PrintDebug(core->vm_info, core, "apic %u: core %u: Write finished\n", apic->lapic_id.val, core->vcpu_id);
1630
1631     return length;
1632
1633 }
1634
1635
1636
1637 /* Interrupt Controller Functions */
1638
1639
1640 static int apic_intr_pending(struct guest_info * core, void * private_data) {
1641     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
1642     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1643     int req_irq = 0;    
1644     int svc_irq = 0;
1645
1646     // Activate all queued IRQ entries
1647     drain_irq_entries(apic);
1648
1649     // Check for newly activated entries
1650     req_irq = get_highest_irr(apic);
1651     svc_irq = get_highest_isr(apic);
1652
1653     //    PrintDebug(core->vm_info, core, "apic %u: core %u: req_irq=%d, svc_irq=%d\n",apic->lapic_id.val,info->vcpu_id,req_irq,svc_irq);
1654
1655
1656     if ((req_irq >= 0) && 
1657         (req_irq > svc_irq)) {
1658
1659         // We have a new requested vector that is higher priority than
1660         // the vector that is in-service
1661
1662         uint32_t ppr = get_apic_ppr(apic);
1663
1664         if ((req_irq & 0xf0) > (ppr & 0xf0)) {
1665             // it's also higher priority than the current
1666             // processor priority.  Therefore this
1667             // interrupt can go in now.
1668             return 1;
1669         } else {
1670             // processor priority is currently too high
1671             // for this interrupt to go in now.  
1672             // note that if tpr=0xf?, then ppr=0xf?
1673             // and thus all vectors will be masked
1674             // as required (tpr=0xf? => all masked)
1675             return 0;
1676         }
1677     } else {
1678         // the vector that is in service is higher
1679         // priority than any new requested vector
1680         return 0;
1681     }
1682 }
1683
1684
1685
1686 static int apic_get_intr_number(struct guest_info * core, void * private_data) {
1687     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
1688     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1689     int req_irq = get_highest_irr(apic);
1690     int svc_irq = get_highest_isr(apic);
1691
1692
1693     // for the logic here, see the comments for apic_intr_pending
1694     if ((req_irq >=0) &&
1695         (req_irq > svc_irq)) { 
1696         
1697         uint32_t ppr = get_apic_ppr(apic);
1698         
1699         if ((req_irq & 0xf0) > (ppr & 0xf0)) {
1700             return req_irq;
1701         } else {
1702             // hmm, this should not have happened, but, anyway,
1703             // no interrupt is currently ready to go in
1704             return -1;
1705         }
1706     } else {
1707         return -1;
1708     }
1709 }
1710
1711
1712
1713 int v3_apic_send_ipi(struct v3_vm_info * vm, struct v3_gen_ipi * ipi, void * dev_data) {
1714     struct apic_dev_state * apic_dev = (struct apic_dev_state *)
1715         (((struct vm_device *)dev_data)->private_data);
1716
1717     return route_ipi(apic_dev, NULL, ipi);
1718 }
1719
1720
1721
1722 static int apic_begin_irq(struct guest_info * core, void * private_data, int irq) {
1723     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
1724     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1725     int major_offset = (irq & ~0x00000007) >> 3;
1726     int minor_offset = irq & 0x00000007;
1727     uint8_t *req_location = apic->int_req_reg + major_offset;
1728     uint8_t *svc_location = apic->int_svc_reg + major_offset;
1729     uint8_t flag = 0x01 << minor_offset;
1730
1731     if (*req_location & flag) {
1732         // we will only pay attention to a begin irq if we
1733         // know that we initiated it!
1734         *svc_location |= flag;
1735         *req_location &= ~flag;
1736     } else {
1737         // do nothing... 
1738         //PrintDebug(core->vm_info, core, "apic %u: core %u: begin irq for %d ignored since I don't own it\n",
1739         //         apic->lapic_id.val, core->vcpu_id, irq);
1740     }
1741
1742     return 0;
1743 }
1744
1745
1746 /* Timer Functions */
1747
1748 static void apic_inject_timer_intr(struct guest_info *core,
1749                                    void * priv_data) {
1750     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1751     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1752     // raise irq
1753     PrintDebug(core->vm_info, core, "apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d)\n",
1754                apic->lapic_id.val, core->vcpu_id,
1755                apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt);
1756
1757     if (apic_intr_pending(core, priv_data)) {
1758         PrintDebug(core->vm_info, core, "apic %u: core %u: Overriding pending IRQ %d\n", 
1759                    apic->lapic_id.val, core->vcpu_id, 
1760                    apic_get_intr_number(core, priv_data));
1761     }
1762
1763     if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
1764         PrintError(core->vm_info, core, "apic %u: core %u: Could not raise Timer interrupt\n",
1765                    apic->lapic_id.val, core->vcpu_id);
1766     }
1767
1768     return;
1769 }
1770         
1771
1772
1773
1774 static void apic_update_time(struct guest_info * core, 
1775                              uint64_t cpu_cycles, uint64_t cpu_freq, 
1776                              void * priv_data) {
1777     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1778     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1779
1780     // The 32 bit GCC runtime is a pile of shit
1781 #ifdef __V3_64BIT__
1782     uint64_t tmr_ticks = 0;
1783 #else 
1784     uint32_t tmr_ticks = 0;
1785 #endif
1786
1787     uint8_t tmr_div = *(uint8_t *)&(apic->tmr_div_cfg.val);
1788     uint_t shift_num = 0;
1789
1790
1791     // Check whether this is true:
1792     //   -> If the Init count is zero then the timer is disabled
1793     //      and doesn't just blitz interrupts to the CPU
1794     if ((apic->tmr_init_cnt == 0) || 
1795         ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
1796           (apic->tmr_cur_cnt == 0))) {
1797         //PrintDebug(core->vm_info, core, "apic %u: core %u: APIC timer not yet initialized\n",apic->lapic_id.val,info->vcpu_id);
1798         return;
1799     }
1800
1801
1802     switch (tmr_div) {
1803         case APIC_TMR_DIV1:
1804             shift_num = 0;
1805             break;
1806         case APIC_TMR_DIV2:
1807             shift_num = 1;
1808             break;
1809         case APIC_TMR_DIV4:
1810             shift_num = 2;
1811             break;
1812         case APIC_TMR_DIV8:
1813             shift_num = 3;
1814             break;
1815         case APIC_TMR_DIV16:
1816             shift_num = 4;
1817             break;
1818         case APIC_TMR_DIV32:
1819             shift_num = 5;
1820             break;
1821         case APIC_TMR_DIV64:
1822             shift_num = 6;
1823             break;
1824         case APIC_TMR_DIV128:
1825             shift_num = 7;
1826             break;
1827         default:
1828             PrintError(core->vm_info, core, "apic %u: core %u: Invalid Timer Divider configuration\n",
1829                        apic->lapic_id.val, core->vcpu_id);
1830             return;
1831     }
1832
1833     tmr_ticks = cpu_cycles >> shift_num;
1834     //    PrintDebug(core->vm_info, core, "Timer Ticks: %p\n", (void *)tmr_ticks);
1835
1836     if (tmr_ticks < apic->tmr_cur_cnt) {
1837         apic->tmr_cur_cnt -= tmr_ticks;
1838 #ifdef V3_CONFIG_APIC_ENQUEUE_MISSED_TMR_IRQS
1839         if (apic->missed_ints && !apic_intr_pending(core, priv_data)) {
1840             PrintDebug(core->vm_info, core, "apic %u: core %u: Injecting queued APIC timer interrupt.\n",
1841                        apic->lapic_id.val, core->vcpu_id);
1842             apic_inject_timer_intr(core, priv_data);
1843             apic->missed_ints--;
1844         }
1845 #endif /* CONFIG_APIC_ENQUEUE_MISSED_TMR_IRQS */ 
1846     } else {
1847         tmr_ticks -= apic->tmr_cur_cnt;
1848         apic->tmr_cur_cnt = 0;
1849
1850         apic_inject_timer_intr(core, priv_data);
1851
1852         if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
1853             int queued_ints = tmr_ticks / apic->tmr_init_cnt;
1854             tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
1855             apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
1856             apic->missed_ints += queued_ints;
1857         }
1858     }
1859
1860     return;
1861 }
1862
1863 static struct intr_ctrl_ops intr_ops = {
1864     .intr_pending = apic_intr_pending,
1865     .get_intr_number = apic_get_intr_number,
1866     .begin_irq = apic_begin_irq,
1867 };
1868
1869
1870 static struct v3_timer_ops timer_ops = {
1871     .update_timer = apic_update_time,
1872 };
1873
1874
1875
1876
1877 static int apic_free(struct apic_dev_state * apic_dev) {
1878     int i = 0;
1879     struct v3_vm_info * vm = NULL;
1880
1881     for (i = 0; i < apic_dev->num_apics; i++) {
1882         struct apic_state * apic = &(apic_dev->apics[i]);
1883         struct guest_info * core = apic->core;
1884         
1885         vm = core->vm_info;
1886
1887         v3_remove_intr_controller(core, apic->controller_handle);
1888
1889         if (apic->timer) {
1890             v3_remove_timer(core, apic->timer);
1891         }
1892
1893         v3_lock_deinit(&(apic->irq_queue.lock));
1894
1895         v3_unhook_mem(vm,core->vcpu_id,apic->base_addr);
1896
1897     }
1898
1899     v3_unhook_msr(vm, BASE_ADDR_MSR);
1900
1901     v3_lock_deinit(&(apic_dev->state_lock));
1902
1903     V3_Free(apic_dev);
1904     return 0;
1905 }
1906
1907 #ifdef V3_CONFIG_CHECKPOINT
1908
1909 #define KEY_MAX 128
1910 #define MAKE_KEY(x) snprintf(key,KEY_MAX,"%s%d",x,i);
1911
1912 static int apic_save(struct v3_chkpt_ctx * ctx, void * private_data) {
1913     struct apic_dev_state * apic_state = (struct apic_dev_state *)private_data;
1914     int i = 0;
1915     uint32_t temp;
1916     char key[KEY_MAX];
1917
1918     V3_CHKPT_SAVE(ctx, "NUM_APICS", apic_state->num_apics,savefailout);
1919
1920     for (i = 0; i < apic_state->num_apics; i++) {
1921       drain_irq_entries(&(apic_state->apics[i]));
1922
1923       MAKE_KEY("BASE_ADDR"); 
1924       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].base_addr,savefailout);
1925       MAKE_KEY("BASE_ADDR_MSR"); 
1926       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].base_addr_msr,savefailout);
1927       MAKE_KEY("LAPIC_ID");
1928       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].lapic_id,savefailout);
1929       MAKE_KEY("APIC_VER");
1930       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].apic_ver,savefailout);
1931       MAKE_KEY("EXT_APIC_CTRL");
1932       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ext_apic_ctrl,savefailout);
1933       MAKE_KEY("LOCAL_VEC_TBL");
1934       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].local_vec_tbl,savefailout);
1935       MAKE_KEY("TMR_VEC_TBL");
1936       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_vec_tbl,savefailout);
1937       MAKE_KEY("TMR_DIV_CFG");
1938       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_div_cfg,savefailout);
1939       MAKE_KEY("LINT0_VEC_TBL");
1940       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].lint0_vec_tbl,savefailout);
1941       MAKE_KEY("LINT1_VEC_TBL");
1942       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].lint1_vec_tbl,savefailout);
1943       MAKE_KEY("PERF_CTR_LOC_VEC_TBL");
1944       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].perf_ctr_loc_vec_tbl,savefailout);
1945       MAKE_KEY("THERM_LOC_VEC_TBL");
1946       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].therm_loc_vec_tbl,savefailout);
1947       MAKE_KEY("ERR_VEC_TBL");
1948       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].err_vec_tbl,savefailout);
1949       MAKE_KEY("ERR_STATUS");
1950       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].err_status,savefailout);
1951       MAKE_KEY("SPURIOUS_INT");
1952       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].spurious_int,savefailout);
1953       MAKE_KEY("INT_CMD");
1954       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_cmd,savefailout);
1955       MAKE_KEY("LOG_DST");
1956       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].log_dst,savefailout);
1957       MAKE_KEY("DST_FMT");
1958       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].dst_fmt,savefailout);
1959
1960       // APR and PPR are stored only for compatability
1961       // TPR is in APIC_TPR, APR and PPR are derived
1962         
1963       temp = get_apic_apr(&(apic_state->apics[i]));
1964       MAKE_KEY("ARB_PRIO");
1965       V3_CHKPT_SAVE(ctx, key, temp,savefailout);
1966       temp = get_apic_tpr(&(apic_state->apics[i]));
1967       MAKE_KEY("TASK_PRIO");
1968       V3_CHKPT_SAVE(ctx,key,temp,savefailout);
1969       temp = get_apic_ppr(&(apic_state->apics[i]));
1970       MAKE_KEY("PROC_PRIO");
1971       V3_CHKPT_SAVE(ctx, key,temp,savefailout);
1972
1973       MAKE_KEY("EXT_APIC_FEATURE");
1974       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ext_apic_feature,savefailout);
1975       MAKE_KEY("SPEC_EOI");
1976       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].spec_eoi,savefailout);
1977       MAKE_KEY("TMR_CUR_CNT");
1978       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_cur_cnt,savefailout);
1979       
1980       MAKE_KEY("TMR_INIT_CNT");
1981       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_init_cnt,savefailout);
1982       MAKE_KEY("EXT_INTR_VEC_TBL");
1983       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ext_intr_vec_tbl,savefailout);
1984
1985       MAKE_KEY("REM_RD_DATA");
1986       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].rem_rd_data,savefailout);
1987       MAKE_KEY("IPI_STATE");
1988       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ipi_state,savefailout);
1989       MAKE_KEY("INT_REQ_REG");
1990       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_req_reg,savefailout);
1991       MAKE_KEY("INT_SVC_REG");
1992       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_svc_reg,savefailout);
1993       MAKE_KEY("INT_EN_REG");
1994       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_en_reg,savefailout);
1995       MAKE_KEY("TRIG_MODE_REG");
1996       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].trig_mode_reg,savefailout);
1997       MAKE_KEY("EOI");
1998       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].eoi,savefailout);
1999
2000     }
2001
2002     return 0;
2003
2004  savefailout:
2005     PrintError(VM_NONE, VCORE_NONE, "Failed to save apic\n");
2006     return -1;
2007 }
2008
2009 static int apic_load(struct v3_chkpt_ctx * ctx, void * private_data) {
2010     struct apic_dev_state *apic_state = (struct apic_dev_state *)private_data;
2011     int i = 0;
2012     uint32_t temp;
2013     char key[KEY_MAX];
2014
2015     V3_CHKPT_LOAD(ctx,"NUM_APICS", apic_state->num_apics, loadfailout);
2016
2017     for (i = 0; i < apic_state->num_apics; i++) {
2018       drain_irq_entries(&(apic_state->apics[i]));
2019
2020       MAKE_KEY("BASE_ADDR"); 
2021       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].base_addr,loadfailout);
2022       MAKE_KEY("BASE_ADDR_MSR"); 
2023       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].base_addr_msr,loadfailout);
2024       MAKE_KEY("LAPIC_ID");
2025       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].lapic_id,loadfailout);
2026       MAKE_KEY("APIC_VER");
2027       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].apic_ver,loadfailout);
2028       MAKE_KEY("EXT_APIC_CTRL");
2029       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ext_apic_ctrl,loadfailout);
2030       MAKE_KEY("LOCAL_VEC_TBL");
2031       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].local_vec_tbl,loadfailout);
2032       MAKE_KEY("TMR_VEC_TBL");
2033       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_vec_tbl,loadfailout);
2034       MAKE_KEY("TMR_DIV_CFG");
2035       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_div_cfg,loadfailout);
2036       MAKE_KEY("LINT0_VEC_TBL");
2037       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].lint0_vec_tbl,loadfailout);
2038       MAKE_KEY("LINT1_VEC_TBL");
2039       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].lint1_vec_tbl,loadfailout);
2040       MAKE_KEY("PERF_CTR_LOC_VEC_TBL");
2041       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].perf_ctr_loc_vec_tbl,loadfailout);
2042       MAKE_KEY("THERM_LOC_VEC_TBL");
2043       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].therm_loc_vec_tbl,loadfailout);
2044       MAKE_KEY("ERR_VEC_TBL");
2045       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].err_vec_tbl,loadfailout);
2046       MAKE_KEY("ERR_STATUS");
2047       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].err_status,loadfailout);
2048       MAKE_KEY("SPURIOUS_INT");
2049       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].spurious_int,loadfailout);
2050       MAKE_KEY("INT_CMD");
2051       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_cmd,loadfailout);
2052       MAKE_KEY("LOG_DST");
2053       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].log_dst,loadfailout);
2054       MAKE_KEY("DST_FMT");
2055       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].dst_fmt,loadfailout);
2056
2057       // APR and PPR are stored only for compatability
2058       // TPR is in APIC_TPR, APR and PPR are derived
2059
2060       MAKE_KEY("ARB_PRIO");
2061       V3_CHKPT_LOAD(ctx, key, temp,loadfailout);
2062       // discarded
2063
2064       MAKE_KEY("TASK_PRIO");
2065       V3_CHKPT_LOAD(ctx,key,temp,loadfailout);
2066       set_apic_tpr(&(apic_state->apics[i]),temp);
2067       
2068       MAKE_KEY("PROC_PRIO");
2069       V3_CHKPT_LOAD(ctx, key,temp,loadfailout);
2070       // discarded
2071
2072
2073       MAKE_KEY("EXT_APIC_FEATURE");
2074       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ext_apic_feature,loadfailout);
2075       MAKE_KEY("SPEC_EOI");
2076       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].spec_eoi,loadfailout);
2077       MAKE_KEY("TMR_CUR_CNT");
2078       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_cur_cnt,loadfailout);
2079       
2080       MAKE_KEY("TMR_INIT_CNT");
2081       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_init_cnt,loadfailout);
2082       MAKE_KEY("EXT_INTR_VEC_TBL");
2083       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ext_intr_vec_tbl,loadfailout);
2084
2085       MAKE_KEY("REM_RD_DATA");
2086       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].rem_rd_data,loadfailout);
2087       MAKE_KEY("IPI_STATE");
2088       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ipi_state,loadfailout);
2089       MAKE_KEY("INT_REQ_REG");
2090       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_req_reg,loadfailout);
2091       MAKE_KEY("INT_SVC_REG");
2092       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_svc_reg,loadfailout);
2093       MAKE_KEY("INT_EN_REG");
2094       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_en_reg,loadfailout);
2095       MAKE_KEY("TRIG_MODE_REG");
2096       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].trig_mode_reg,loadfailout);
2097       MAKE_KEY("EOI");
2098       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].eoi,loadfailout);
2099     }
2100     
2101     
2102     return 0;
2103     
2104  loadfailout:
2105     PrintError(VM_NONE,VCORE_NONE, "Failed to load apic\n");
2106     return -1;
2107     
2108 }
2109
2110 #endif
2111
2112 static struct v3_device_ops dev_ops = {
2113     .free = (int (*)(void *))apic_free,
2114 #ifdef V3_CONFIG_CHECKPOINT
2115     .save = apic_save,
2116     .load = apic_load
2117 #endif
2118 };
2119
2120
2121
2122 static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2123     char * dev_id = v3_cfg_val(cfg, "ID");
2124     struct apic_dev_state * apic_dev = NULL;
2125     int i = 0;
2126
2127     PrintDebug(vm, VCORE_NONE, "apic: creating an APIC for each core\n");
2128
2129     apic_dev = (struct apic_dev_state *)V3_Malloc(sizeof(struct apic_dev_state) + 
2130                                                   sizeof(struct apic_state) * vm->num_cores);
2131
2132
2133     if (!apic_dev) {
2134         PrintError(vm, VCORE_NONE, "Failed to allocate space for APIC\n");
2135         return -1;
2136     }
2137
2138     memset(apic_dev,0,
2139            sizeof(struct apic_dev_state) + 
2140            sizeof(struct apic_state) * vm->num_cores);
2141
2142     apic_dev->num_apics = vm->num_cores;
2143     v3_lock_init(&(apic_dev->state_lock));
2144
2145     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, apic_dev);
2146
2147     if (dev == NULL) {
2148         PrintError(vm, VCORE_NONE, "apic: Could not attach device %s\n", dev_id);
2149         V3_Free(apic_dev);
2150         return -1;
2151     }
2152
2153     
2154     for (i = 0; i < vm->num_cores; i++) {
2155         struct apic_state * apic = &(apic_dev->apics[i]);
2156         struct guest_info * core = &(vm->cores[i]);
2157
2158         apic->core = core;
2159
2160         init_apic_state(apic, i);
2161
2162         apic->controller_handle = v3_register_intr_controller(core, &intr_ops, apic_dev);
2163
2164         apic->timer = v3_add_timer(core, &timer_ops, apic_dev);
2165
2166         if (apic->timer == NULL) {
2167             PrintError(vm, VCORE_NONE,"APIC: Failed to attach timer to core %d\n", i);
2168             v3_remove_device(dev);
2169             return -1;
2170         }
2171
2172         // hook to initial location
2173         v3_hook_full_mem(vm, core->vcpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, apic_dev);
2174
2175         PrintDebug(vm, VCORE_NONE, "apic %u: (setup device): done, my id is %u\n", i, apic->lapic_id.val);
2176     }
2177
2178 #ifdef V3_CONFIG_DEBUG_APIC
2179     for (i = 0; i < vm->num_cores; i++) {
2180         struct apic_state * apic = &(apic_dev->apics[i]);
2181         PrintDebug(vm, VCORE_NONE, "apic: sanity check: apic %u (at %p) has id %u and msr value %llx and core at %p\n",
2182                    i, apic, apic->lapic_id.val, apic->base_addr_msr.value,apic->core);
2183     }
2184 #endif
2185
2186
2187     PrintDebug(vm, VCORE_NONE, "apic: priv_data is at %p\n", apic_dev);
2188
2189     v3_hook_msr(vm, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, apic_dev);
2190
2191     return 0;
2192 }
2193
2194 static char hexify_nybble(char c)
2195 {
2196     if (c>=0 && c<=9) { 
2197         return '0'+c;
2198     } else if (c>=0xa && c<=0xf) { 
2199         return 'a'+(c-0xa);
2200     } else {
2201         return -1;
2202     }
2203 }
2204
2205
2206 static int hexify_byte(char *c, char b)
2207 {
2208     char n;
2209     n = hexify_nybble( (b >> 4) & 0xf);
2210     if (n==-1) { 
2211         return -1;
2212     }
2213     c[0] = n;
2214     n = hexify_nybble( b & 0xf);
2215     if (n==-1) { 
2216         return -1;
2217     }
2218     c[1] = n;
2219     return 0;
2220 }
2221
2222 // dest must be of length at least 2*n+1
2223 static int hexify_byte_string(char *dest, char *src, int n)
2224 {
2225     int i;
2226     for (i=0;i<n;i++) { 
2227         if (hexify_byte(dest,src[i])) { 
2228             return -1;
2229         }
2230         dest+=2;
2231     }
2232     *dest=0;
2233     return 0;
2234 }
2235
2236
2237 static __attribute__((unused)) void dump_all_apic_state(struct v3_vm_info *vm, struct apic_dev_state *a)
2238 {
2239     int i;
2240     for (i=0;i<a->num_apics;i++) { 
2241         dump_apic_state(&(vm->cores[i]),&(a->apics[i]));
2242     }
2243 }
2244         
2245 static void dump_apic_state(struct guest_info *core, struct apic_state * a) 
2246 {
2247     char buf[80];
2248     struct irq_queue_entry *ie;
2249
2250     V3_Print(core->vm_info, core, "APIC (vcore %d) {\n", core->vcpu_id);
2251     V3_Print(core->vm_info, core, "\tbase_addr: %llx\n", (uint64_t)(a->base_addr));
2252     V3_Print(core->vm_info, core, "\tlapic_id_reg {\n");
2253     V3_Print(core->vm_info, core, "\t\trsvd: 0x%x\n", a->lapic_id.rsvd);
2254     V3_Print(core->vm_info, core, "\t\tapic_id: 0x%x\n", a->lapic_id.apic_id);
2255     V3_Print(core->vm_info, core, "\t}\n");
2256     V3_Print(core->vm_info, core, "\tapic_ver_reg {\n");
2257     V3_Print(core->vm_info, core, "\t\tver: 0x%x\n", a->apic_ver.ver);
2258     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->apic_ver.rsvd1);
2259     V3_Print(core->vm_info, core, "\t\tmax_lvts: 0x%x\n", a->apic_ver.max_lvts);
2260     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->apic_ver.rsvd2);
2261     V3_Print(core->vm_info, core, "\t\text_reg_present: 0x%x\n", a->apic_ver.ext_reg_present);
2262     V3_Print(core->vm_info, core, "\t}\n");
2263     V3_Print(core->vm_info, core, "\text_apic_ctrl_reg {\n");
2264     V3_Print(core->vm_info, core, "\t\tver: 0x%x\n", a->ext_apic_ctrl.ver);
2265     V3_Print(core->vm_info, core, "\t\tseoi_enable: 0x%x\n", a->ext_apic_ctrl.seoi_enable);
2266     V3_Print(core->vm_info, core, "\t\text_id_enable: 0x%x\n", a->ext_apic_ctrl.ext_id_enable);
2267     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_apic_ctrl.rsvd2);
2268     V3_Print(core->vm_info, core, "\t}\n");
2269     V3_Print(core->vm_info, core, "\tlocal_vec_tbl_reg {\n");
2270     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->local_vec_tbl.vec);
2271     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->local_vec_tbl.msg_type);
2272     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->local_vec_tbl.rsvd1);
2273     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->local_vec_tbl.del_status);
2274     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->local_vec_tbl.rsvd2);
2275     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->local_vec_tbl.rem_irr);
2276     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->local_vec_tbl.trig_mode);
2277     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->local_vec_tbl.mask);
2278     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->local_vec_tbl.tmr_mode);
2279     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->local_vec_tbl.rsvd3);
2280     V3_Print(core->vm_info, core, "\t}\n");
2281     V3_Print(core->vm_info, core, "\ttmr_vec_tbl_reg {\n");
2282     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->tmr_vec_tbl.vec);
2283     V3_Print(core->vm_info, core, "\t\trsvd: 0x%x\n", a->tmr_vec_tbl.rsvd);
2284     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->tmr_vec_tbl.del_status);
2285     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->tmr_vec_tbl.rsvd2);
2286     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->tmr_vec_tbl.mask);
2287     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->tmr_vec_tbl.tmr_mode);
2288     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->tmr_vec_tbl.rsvd3);
2289     V3_Print(core->vm_info, core, "\t}\n");
2290     V3_Print(core->vm_info, core, "\ttmr_div_cfg_reg {\n");
2291     V3_Print(core->vm_info, core, "\t\tdiv_val: 0x%x\n", a->tmr_div_cfg.div_val);
2292     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->tmr_div_cfg.rsvd1);
2293     V3_Print(core->vm_info, core, "\t\tdiv_val2: 0x%x\n", a->tmr_div_cfg.div_val2);
2294     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->tmr_div_cfg.rsvd2);
2295     V3_Print(core->vm_info, core, "\t}\n");
2296     V3_Print(core->vm_info, core, "\tlint_vec_tbl_reg 0 {\n");
2297     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->lint0_vec_tbl.vec);
2298     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->lint0_vec_tbl.msg_type);
2299     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->lint0_vec_tbl.rsvd1);
2300     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->lint0_vec_tbl.del_status);
2301     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->lint0_vec_tbl.rsvd2);
2302     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->lint0_vec_tbl.rem_irr);
2303     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->lint0_vec_tbl.trig_mode);
2304     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->lint0_vec_tbl.mask);
2305     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->lint0_vec_tbl.rsvd3);
2306     V3_Print(core->vm_info, core, "\t}\n");
2307     V3_Print(core->vm_info, core, "\tlint_vec_tbl_reg 1 {\n");
2308     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->lint1_vec_tbl.vec);
2309     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->lint1_vec_tbl.msg_type);
2310     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->lint1_vec_tbl.rsvd1);
2311     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->lint1_vec_tbl.del_status);
2312     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->lint1_vec_tbl.rsvd2);
2313     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->lint1_vec_tbl.rem_irr);
2314     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->lint1_vec_tbl.trig_mode);
2315     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->lint1_vec_tbl.mask);
2316     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->lint1_vec_tbl.rsvd3);
2317     V3_Print(core->vm_info, core, "\t}\n");
2318     V3_Print(core->vm_info, core, "\tperf_ctr_loc_vec_tbl_reg {\n");
2319     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->perf_ctr_loc_vec_tbl.vec);
2320     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->perf_ctr_loc_vec_tbl.msg_type);
2321     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->perf_ctr_loc_vec_tbl.rsvd1);
2322     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->perf_ctr_loc_vec_tbl.del_status);
2323     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->perf_ctr_loc_vec_tbl.rsvd2);
2324     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->perf_ctr_loc_vec_tbl.mask);
2325     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->perf_ctr_loc_vec_tbl.rsvd3);
2326     V3_Print(core->vm_info, core, "\t}\n");
2327     V3_Print(core->vm_info, core, "\ttherm_loc_vec_tbl_reg {\n");
2328     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->therm_loc_vec_tbl.vec);
2329     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->therm_loc_vec_tbl.msg_type);
2330     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->therm_loc_vec_tbl.rsvd1);
2331     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->therm_loc_vec_tbl.del_status);
2332     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->therm_loc_vec_tbl.rsvd2);
2333     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->therm_loc_vec_tbl.mask);
2334     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->therm_loc_vec_tbl.rsvd3);
2335     V3_Print(core->vm_info, core, "\t}\n");
2336     V3_Print(core->vm_info, core, "\terr_vec_tbl_reg {\n");
2337     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->err_vec_tbl.vec);
2338     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->err_vec_tbl.msg_type);
2339     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->err_vec_tbl.rsvd1);
2340     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->err_vec_tbl.del_status);
2341     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->err_vec_tbl.rsvd2);
2342     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->err_vec_tbl.mask);
2343     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->err_vec_tbl.rsvd3);
2344     V3_Print(core->vm_info, core, "\t}\n");
2345     V3_Print(core->vm_info, core, "\terr_status_reg {\n");
2346     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->err_status.rsvd1);
2347     V3_Print(core->vm_info, core, "\t\tsent_acc_err: 0x%x\n", a->err_status.sent_acc_err);
2348     V3_Print(core->vm_info, core, "\t\trecv_acc_err: 0x%x\n", a->err_status.recv_acc_err);
2349     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->err_status.rsvd2);
2350     V3_Print(core->vm_info, core, "\t\tsent_ill_err: 0x%x\n", a->err_status.sent_ill_err);
2351     V3_Print(core->vm_info, core, "\t\trecv_ill_err: 0x%x\n", a->err_status.recv_ill_err);
2352     V3_Print(core->vm_info, core, "\t\till_reg_addr: 0x%x\n", a->err_status.ill_reg_addr);
2353     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->err_status.rsvd3);
2354     V3_Print(core->vm_info, core, "\t}\n");
2355     V3_Print(core->vm_info, core, "\tspurious_int_reg {\n");
2356     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->spurious_int.vec);
2357     V3_Print(core->vm_info, core, "\t\tapic_soft_en: 0x%x\n", a->spurious_int.apic_soft_en);
2358     V3_Print(core->vm_info, core, "\t\tfoc_cpu_chk: 0x%x\n", a->spurious_int.foc_cpu_chk);
2359     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->spurious_int.rsvd1);
2360     V3_Print(core->vm_info, core, "\t}\n");
2361     V3_Print(core->vm_info, core, "\tint_cmd_reg {\n");
2362     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->int_cmd.vec);
2363     V3_Print(core->vm_info, core, "\t\tdel_mode: 0x%x\n", a->int_cmd.del_mode);
2364     V3_Print(core->vm_info, core, "\t\tdst_mode: 0x%x\n", a->int_cmd.dst_mode);
2365     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->int_cmd.del_status);
2366     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->int_cmd.rsvd1);
2367     V3_Print(core->vm_info, core, "\t\tlvl: 0x%x\n", a->int_cmd.lvl);
2368     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->int_cmd.trig_mode);
2369     V3_Print(core->vm_info, core, "\t\trm_rd_status: 0x%x\n", a->int_cmd.rem_rd_status);
2370     V3_Print(core->vm_info, core, "\t\tdst_shorthand: 0x%x\n", a->int_cmd.dst_shorthand);
2371     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%llx\n", (uint64_t)(a->int_cmd.rsvd2));
2372     V3_Print(core->vm_info, core, "\t\tdst: 0x%x\n", a->int_cmd.dst);
2373     V3_Print(core->vm_info, core, "\t}\n");
2374     V3_Print(core->vm_info, core, "\tlog_dst_reg {\n");
2375     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->log_dst.rsvd1);
2376     V3_Print(core->vm_info, core, "\t\tdst_log_id: 0x%x\n", a->log_dst.dst_log_id);
2377     V3_Print(core->vm_info, core, "\t}\n");
2378     V3_Print(core->vm_info, core, "\tdst_fmt_reg {\n");
2379     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->dst_fmt.rsvd1);
2380     V3_Print(core->vm_info, core, "\t\tmodel: 0x%x\n", a->dst_fmt.model);
2381     V3_Print(core->vm_info, core, "\t}\n");
2382     V3_Print(core->vm_info, core, "\tarb_prio_reg: 0x%x\n",get_apic_apr(a));
2383     V3_Print(core->vm_info, core, "\ttask_prio_reg: 0x%x\n", get_apic_tpr(a));
2384     V3_Print(core->vm_info, core, "\tproc_prio_reg: 0x%x\n",get_apic_ppr(a));
2385     V3_Print(core->vm_info, core, "\text_apic_feature_reg {\n");
2386     V3_Print(core->vm_info, core, "\t\tint_en_reg_cap: 0x%x\n", a->ext_apic_feature.int_en_reg_cap);
2387     V3_Print(core->vm_info, core, "\t\tspec_eoi_cap: 0x%x\n", a->ext_apic_feature.spec_eoi_cap);
2388     V3_Print(core->vm_info, core, "\t\text_apic_id_cap: 0x%x\n", a->ext_apic_feature.ext_apic_id_cap);
2389     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->ext_apic_feature.rsvd1);
2390     V3_Print(core->vm_info, core, "\t\text_lvt_cnt: 0x%x\n", a->ext_apic_feature.ext_lvt_cnt);
2391     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_apic_feature.rsvd2);
2392     V3_Print(core->vm_info, core, "\t}\n");
2393     V3_Print(core->vm_info, core, "\tspec_eoi_reg {\n");
2394     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->spec_eoi.vec);
2395     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->spec_eoi.rsvd1);
2396     V3_Print(core->vm_info, core, "\t}\n");
2397     V3_Print(core->vm_info, core, "\ttmr_cur_cnt: 0x%x\n", a->tmr_cur_cnt);
2398     V3_Print(core->vm_info, core, "\ttmr_init_cnt: 0x%x\n", a->tmr_init_cnt);
2399     V3_Print(core->vm_info, core, "\tmissed_ints: 0x%x\n", a->missed_ints);
2400     V3_Print(core->vm_info, core, "\text_vec_tbl_reg 0 {\n");
2401     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->ext_intr_vec_tbl[0].vec);
2402     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->ext_intr_vec_tbl[0].msg_type);
2403     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->ext_intr_vec_tbl[0].rsvd1);
2404     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->ext_intr_vec_tbl[0].del_status);
2405     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_intr_vec_tbl[0].rsvd2);
2406     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->ext_intr_vec_tbl[0].rem_irr);
2407     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->ext_intr_vec_tbl[0].trig_mode);
2408     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->ext_intr_vec_tbl[0].mask);
2409     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->ext_intr_vec_tbl[0].tmr_mode);
2410     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->ext_intr_vec_tbl[0].rsvd3);
2411     V3_Print(core->vm_info, core, "\t}\n");
2412     V3_Print(core->vm_info, core, "\text_vec_tbl_reg 1 {\n");
2413     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->ext_intr_vec_tbl[1].vec);
2414     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->ext_intr_vec_tbl[1].msg_type);
2415     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->ext_intr_vec_tbl[1].rsvd1);
2416     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->ext_intr_vec_tbl[1].del_status);
2417     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_intr_vec_tbl[1].rsvd2);
2418     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->ext_intr_vec_tbl[1].rem_irr);
2419     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->ext_intr_vec_tbl[1].trig_mode);
2420     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->ext_intr_vec_tbl[1].mask);
2421     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->ext_intr_vec_tbl[1].tmr_mode);
2422     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->ext_intr_vec_tbl[1].rsvd3);
2423     V3_Print(core->vm_info, core, "\t}\n");
2424     V3_Print(core->vm_info, core, "\text_vec_tbl_reg 2 {\n");
2425     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->ext_intr_vec_tbl[2].vec);
2426     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->ext_intr_vec_tbl[2].msg_type);
2427     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->ext_intr_vec_tbl[2].rsvd1);
2428     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->ext_intr_vec_tbl[2].del_status);
2429     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_intr_vec_tbl[2].rsvd2);
2430     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->ext_intr_vec_tbl[2].rem_irr);
2431     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->ext_intr_vec_tbl[2].trig_mode);
2432     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->ext_intr_vec_tbl[2].mask);
2433     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->ext_intr_vec_tbl[2].tmr_mode);
2434     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->ext_intr_vec_tbl[2].rsvd3);
2435     V3_Print(core->vm_info, core, "\t}\n");
2436     V3_Print(core->vm_info, core, "\text_vec_tbl_reg 3 {\n");
2437     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->ext_intr_vec_tbl[3].vec);
2438     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->ext_intr_vec_tbl[3].msg_type);
2439     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->ext_intr_vec_tbl[3].rsvd1);
2440     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->ext_intr_vec_tbl[3].del_status);
2441     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_intr_vec_tbl[3].rsvd2);
2442     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->ext_intr_vec_tbl[3].rem_irr);
2443     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->ext_intr_vec_tbl[3].trig_mode);
2444     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->ext_intr_vec_tbl[3].mask);
2445     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->ext_intr_vec_tbl[3].tmr_mode);
2446     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->ext_intr_vec_tbl[3].rsvd3);
2447     V3_Print(core->vm_info, core, "\t}\n");
2448     V3_Print(core->vm_info, core, "\trem_rd_data: 0x%x\n", a->rem_rd_data);
2449     hexify_byte_string(buf,a->int_req_reg,32);
2450     V3_Print(core->vm_info, core, "\tint_req_reg: 0x%s\n",buf);
2451     hexify_byte_string(buf,a->int_svc_reg,32);
2452     V3_Print(core->vm_info, core, "\tint_svc_reg: 0x%s\n",buf);
2453     hexify_byte_string(buf,a->int_en_reg,32);
2454     V3_Print(core->vm_info, core, "\tint_en_reg: 0x%s\n",buf);
2455     hexify_byte_string(buf,a->trig_mode_reg,32);
2456     V3_Print(core->vm_info, core, "\ttrig_mode_reg: 0x%s\n",buf);
2457     V3_Print(core->vm_info, core, "\tirq_ack_cbs: SKIPPED\n");
2458     V3_Print(core->vm_info, core, "\tirq_queue: (follows)\n");
2459     // note we do not hold the lock for purposes of printing this list... 
2460     list_for_each_entry(ie,&(a->irq_queue.entries), list_node) {
2461         V3_Print(core->vm_info,core,"\t\tvector 0x%x ack %p priv %p\n", ie->vector, ie->ack, ie->private_data);
2462     }
2463     V3_Print(core->vm_info, core, "\t}\n");
2464     V3_Print(core->vm_info, core, "\teoi: 0x%x\n", a->eoi);
2465     V3_Print(core->vm_info, core,"}\n");
2466 }
2467
2468
2469
2470
2471
2472
2473 device_register("LAPIC", apic_init)