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.


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