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.


APIC bug fixes and cleanup
[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 (dst_apic->ipi_state != INIT_ST) { 
898                 v3_raise_barrier(dst_core->vm_info, src_apic->core);
899                 dst_core->core_run_state = CORE_STOPPED;
900                 dst_apic->ipi_state = INIT_ST;
901                 v3_lower_barrier(dst_core->vm_info);
902
903             }
904
905             // We transition the target core to SIPI state
906             dst_apic->ipi_state = SIPI;  // note: locking should not be needed here
907
908             // That should be it since the target core should be
909             // waiting in host on this transition
910             // either it's on another core or on a different preemptive thread
911             // in both cases, it will quickly notice this transition 
912             // in particular, we should not need to force an exit here
913
914             PrintDebug(VM_NONE, VCORE_NONE, " INIT delivery done\n");
915
916             break;                                                      
917         }
918         case IPI_SIPI: { 
919
920             // Sanity check
921             if (dst_apic->ipi_state != SIPI) { 
922                 PrintError(VM_NONE, VCORE_NONE, " core %u is not in SIPI state (mode = %d), ignored!\n",
923                            dst_core->vcpu_id, dst_apic->ipi_state);
924                 break;
925             }
926
927             v3_reset_vm_core(dst_core, ipi->vector);
928
929             PrintDebug(VM_NONE, VCORE_NONE, " SIPI delivery (0x%x -> 0x%x:0x0) to core %u\n",
930                        ipi->vector, dst_core->segments.cs.selector, dst_core->vcpu_id);
931             // Maybe need to adjust the APIC?
932             
933             // We transition the target core to SIPI state
934             dst_core->core_run_state = CORE_RUNNING;  // note: locking should not be needed here
935             dst_apic->ipi_state = STARTED;
936             
937             // As with INIT, we should not need to do anything else
938             
939             PrintDebug(VM_NONE, VCORE_NONE, " SIPI delivery done\n");
940             
941             break;                                                      
942         }
943
944         case IPI_EXTINT: // EXTINT
945             /* Two possible things to do here: 
946              * 1. Ignore the IPI and assume the 8259a (PIC) will handle it
947              * 2. Add 32 to the vector and inject it...
948              * We probably just want to do 1 here, and assume the raise_irq() will hit the 8259a.
949              */
950             return 0;
951
952         case IPI_SMI: 
953         case IPI_RES1: // reserved                                              
954         case IPI_NMI:
955         default:
956             PrintError(VM_NONE, VCORE_NONE, "IPI %d delivery is unsupported\n", ipi->mode); 
957             return -1;
958     }
959     
960     return 0;
961     
962 }
963
964 static struct apic_state * find_physical_apic(struct apic_dev_state * apic_dev, uint32_t dst_idx) {
965     struct apic_state * dst_apic = NULL;
966     addr_t flags;
967     int i;
968
969     flags = v3_lock_irqsave(apic_dev->state_lock);
970
971     if ( (dst_idx > 0) && (dst_idx < apic_dev->num_apics) ) { 
972         // see if it simply is the core id
973         if (apic_dev->apics[dst_idx].lapic_id.apic_id == dst_idx) { 
974              dst_apic = &(apic_dev->apics[dst_idx]);
975         }
976     }
977
978     for (i = 0; i < apic_dev->num_apics; i++) { 
979         if (apic_dev->apics[i].lapic_id.apic_id == dst_idx) { 
980             dst_apic =  &(apic_dev->apics[i]);
981         }
982     }
983
984     v3_unlock_irqrestore(apic_dev->state_lock, flags);
985
986     return dst_apic;
987
988 }
989
990
991 static int route_ipi(struct apic_dev_state * apic_dev,
992                      struct apic_state * src_apic, 
993                      struct v3_gen_ipi * ipi) {
994     struct apic_state * dest_apic = NULL;
995
996
997     PrintDebug(VM_NONE, VCORE_NONE, "apic: IPI %s %u from apic %p to %s %s %u\n",
998                deliverymode_str[ipi->mode], 
999                ipi->vector, 
1000                src_apic,               
1001                (ipi->logical == 0) ? "(physical)" : "(logical)", 
1002                shorthand_str[ipi->dst_shorthand], 
1003                ipi->dst);
1004
1005
1006     switch (ipi->dst_shorthand) {
1007
1008         case APIC_SHORTHAND_NONE:  // no shorthand
1009             if (ipi->logical == APIC_DEST_PHYSICAL) { 
1010
1011                 dest_apic = find_physical_apic(apic_dev, ipi->dst);
1012                 
1013                 if (dest_apic == NULL) { 
1014                     PrintError(VM_NONE, VCORE_NONE, "apic: Attempted send to unregistered apic id=%u\n", ipi->dst);
1015                     return -1;
1016                 }
1017
1018                 if (deliver_ipi(src_apic, dest_apic, ipi) == -1) {
1019                     PrintError(VM_NONE, VCORE_NONE, "apic: Could not deliver IPI\n");
1020                     return -1;
1021                 }
1022
1023
1024                 PrintDebug(VM_NONE, VCORE_NONE, "apic: done\n");
1025
1026             } else if (ipi->logical == APIC_DEST_LOGICAL) {
1027                 
1028                 if (ipi->mode != IPI_LOWEST_PRIO) { 
1029                     int i;
1030                     uint8_t mda = ipi->dst;
1031
1032                     // logical, but not lowest priority
1033                     // we immediately trigger
1034                     // fixed, smi, reserved, nmi, init, sipi, etc
1035
1036                     // HVM is handled here within deliver_ipi 
1037
1038                     for (i = 0; i < apic_dev->num_apics; i++) { 
1039                         int del_flag = 0;
1040                         
1041                         dest_apic = &(apic_dev->apics[i]);
1042                         
1043                         del_flag = should_deliver_ipi(apic_dev, dest_apic->core, dest_apic, mda);
1044                         
1045                         if (del_flag == -1) {
1046
1047                             PrintError(VM_NONE, VCORE_NONE, "apic: Error checking delivery mode\n");
1048                             return -1;
1049                         } else if (del_flag == 1) {
1050
1051                             if (deliver_ipi(src_apic, dest_apic, ipi) == -1) {
1052                                 PrintError(VM_NONE, VCORE_NONE, "apic: Error: Could not deliver IPI\n");
1053                                 return -1;
1054                             }
1055                         }
1056                     }
1057                 } else {  // APIC_LOWEST_DELIVERY
1058                     struct apic_state * cur_best_apic = NULL;
1059                     uint32_t cur_best_apr;
1060                     uint8_t mda = ipi->dst;
1061                     int i;
1062                     uint32_t start_apic = 0;
1063                     uint32_t num_apics = apic_dev->num_apics;
1064
1065 #ifdef V3_CONFIG_HVM
1066                     // Need to limit lowest priority search to ROS apics
1067                     // if this is coming from a ROS apic or ioapic, etc. 
1068                     v3_hvm_find_apics_seen_by_core(src_apic ? src_apic->core : 0, 
1069                                                    apic_dev->apics[0].core->vm_info,
1070                                                    &start_apic,
1071                                                    &num_apics);
1072 #endif
1073
1074                     // logical, lowest priority
1075
1076                     for (i = start_apic; i < num_apics; i++) { 
1077                         int del_flag = 0;
1078
1079                         dest_apic = &(apic_dev->apics[i]);
1080                         
1081                         del_flag = should_deliver_ipi(apic_dev, dest_apic->core, dest_apic, mda);
1082                         
1083                         if (del_flag == -1) {
1084                             PrintError(VM_NONE, VCORE_NONE, "apic: Error checking delivery mode\n");
1085
1086                             return -1;
1087                         } else if (del_flag == 1) {
1088                             // update priority for lowest priority scan
1089                             addr_t flags = 0;
1090
1091                             flags = v3_lock_irqsave(apic_dev->state_lock);
1092
1093                             if (cur_best_apic == 0) {
1094                                 cur_best_apic = dest_apic;  
1095                                 cur_best_apr = get_apic_apr(dest_apic) & 0xf0;
1096                             } else {
1097                                 uint32_t dest_apr = get_apic_apr(dest_apic) & 0xf0;
1098                                 if (dest_apr < cur_best_apr) {
1099                                     cur_best_apic = dest_apic;
1100                                     cur_best_apr = dest_apr;
1101                                 }
1102                             } 
1103
1104                             v3_unlock_irqrestore(apic_dev->state_lock, flags);
1105
1106                         }
1107                     }
1108
1109                     // now we will deliver to the best one if it exists
1110                     if (!cur_best_apic) { 
1111                         PrintDebug(VM_NONE, VCORE_NONE, "apic: lowest priority delivery, but no destinations!\n");
1112                     } else {
1113                         if (deliver_ipi(src_apic, cur_best_apic, ipi) == -1) {
1114                             PrintError(VM_NONE, VCORE_NONE, "apic: Error: Could not deliver IPI\n");
1115                             return -1;
1116                         }
1117                         //V3_Print(VM_NONE, VCORE_NONE, "apic: logical, lowest priority delivery to apic %u\n",cur_best_apic->lapic_id.apic_id);
1118                     }
1119                 }
1120             }
1121
1122             break;
1123             
1124         case APIC_SHORTHAND_SELF:  // self
1125
1126             if (src_apic == NULL) {    /* this is not an apic, but it's trying to send to itself??? */
1127                 PrintError(VM_NONE, VCORE_NONE, "apic: Sending IPI to self from generic IPI sender\n");
1128                 break;
1129             }
1130
1131
1132
1133             if (ipi->logical == APIC_DEST_PHYSICAL)  {  /* physical delivery */
1134                 if (deliver_ipi(src_apic, src_apic, ipi) == -1) {
1135                     PrintError(VM_NONE, VCORE_NONE, "apic: Could not deliver IPI to self (physical)\n");
1136                     return -1;
1137                 }
1138             } else if (ipi->logical == APIC_DEST_LOGICAL) {  /* logical delivery */
1139                 PrintError(VM_NONE, VCORE_NONE, "apic: use of logical delivery in self (untested)\n");
1140
1141                 if (deliver_ipi(src_apic, src_apic, ipi) == -1) {
1142                     PrintError(VM_NONE, VCORE_NONE, "apic: Could not deliver IPI to self (logical)\n");
1143                     return -1;
1144                 }
1145             }
1146
1147             break;
1148             
1149         case APIC_SHORTHAND_ALL: 
1150         case APIC_SHORTHAND_ALL_BUT_ME: { /* all and all-but-me */
1151             /* assuming that logical verus physical doesn't matter
1152                although it is odd that both are used */
1153             int i;
1154             uint32_t start_apic = 0;
1155             uint32_t num_apics = apic_dev->num_apics;
1156
1157 #ifdef V3_CONFIG_HVM
1158             v3_hvm_find_apics_seen_by_core(src_apic ? src_apic->core : 0, 
1159                                            apic_dev->apics[0].core->vm_info,
1160                                            &start_apic,
1161                                            &num_apics);
1162 #endif
1163
1164             for (i = start_apic; i < num_apics; i++) { 
1165                 dest_apic = &(apic_dev->apics[i]);
1166                 
1167                 if ((dest_apic != src_apic) || (ipi->dst_shorthand == APIC_SHORTHAND_ALL)) { 
1168                     if (deliver_ipi(src_apic, dest_apic, ipi) == -1) {
1169                         PrintError(VM_NONE, VCORE_NONE, "apic: Error: Could not deliver IPI\n");
1170                         return -1;
1171                     }
1172                 }
1173             }
1174
1175             break;
1176         }
1177         default:
1178             PrintError(VM_NONE, VCORE_NONE, "apic: Error routing IPI, invalid Mode (%d)\n", ipi->dst_shorthand);
1179             return -1;
1180     }
1181  
1182     return 0;
1183 }
1184
1185
1186 // External function, expected to acquire lock on apic
1187 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
1188     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1189     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]);
1190     addr_t reg_addr  = guest_addr - apic->base_addr;
1191     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
1192     uint32_t val = 0;
1193
1194
1195     PrintDebug(core->vm_info, core, "apic %u: core %u: at %p: Read apic address space (%p)\n",
1196                apic->lapic_id.apic_id, core->vcpu_id, apic, (void *)guest_addr);
1197
1198     if (msr->apic_enable == 0) {
1199         PrintError(core->vm_info, core, "apic %u: core %u: Read from APIC address space with disabled APIC, apic msr=0x%llx\n",
1200                    apic->lapic_id.apic_id, core->vcpu_id, apic->base_addr_msr.value);
1201         return -1;
1202     }
1203
1204
1205     /* Because "May not be supported" doesn't matter to Linux developers... */
1206     /*   if (length != 4) { */
1207     /*     PrintError(core->vm_info, core, "Invalid apic read length (%d)\n", length); */
1208     /*     return -1; */
1209     /*   } */
1210
1211     switch (reg_addr & ~0x3) {
1212         case EOI_OFFSET:
1213             // Well, only an idiot would read from a architectural write only register
1214             // Oh, Hello Linux.
1215             //    PrintError(core->vm_info, core, "Attempting to read from write only register\n");
1216             //    return -1;
1217             break;
1218
1219             // data registers
1220         case APIC_ID_OFFSET:
1221             val = apic->lapic_id.val;
1222             break;
1223         case APIC_VERSION_OFFSET:
1224             val = apic->apic_ver.val;
1225             break;
1226         case TPR_OFFSET:
1227             val = get_apic_tpr(apic);
1228             break;
1229         case APR_OFFSET:
1230             val = get_apic_apr(apic);
1231             break;
1232         case PPR_OFFSET:
1233             val = get_apic_ppr(apic);
1234             break;
1235         case REMOTE_READ_OFFSET:
1236             val = apic->rem_rd_data;
1237             break;
1238         case LDR_OFFSET:
1239             val = apic->log_dst.val;
1240             break;
1241         case DFR_OFFSET:
1242             val = apic->dst_fmt.val;
1243             break;
1244         case SPURIOUS_INT_VEC_OFFSET:
1245             val = apic->spurious_int.val;
1246             break;
1247         case ESR_OFFSET:
1248             val = apic->err_status.val;
1249             break;
1250         case TMR_LOC_VEC_TBL_OFFSET:
1251             val = apic->tmr_vec_tbl.val;
1252             break;
1253         case LINT0_VEC_TBL_OFFSET:
1254             val = apic->lint0_vec_tbl.val;
1255             break;
1256         case LINT1_VEC_TBL_OFFSET:
1257             val = apic->lint1_vec_tbl.val;
1258             break;
1259         case ERR_VEC_TBL_OFFSET:
1260             val = apic->err_vec_tbl.val;
1261             break;
1262         case TMR_INIT_CNT_OFFSET:
1263             val = apic->tmr_init_cnt;
1264             break;
1265         case TMR_DIV_CFG_OFFSET:
1266             val = apic->tmr_div_cfg.val;
1267             break;
1268
1269         case IER_OFFSET0:
1270             val = *(uint32_t *)(apic->int_en_reg);
1271             break;
1272         case IER_OFFSET1:
1273             val = *(uint32_t *)(apic->int_en_reg + 4);
1274             break;
1275         case IER_OFFSET2:
1276             val = *(uint32_t *)(apic->int_en_reg + 8);
1277             break;
1278         case IER_OFFSET3:
1279             val = *(uint32_t *)(apic->int_en_reg + 12);
1280             break;
1281         case IER_OFFSET4:
1282             val = *(uint32_t *)(apic->int_en_reg + 16);
1283             break;
1284         case IER_OFFSET5:
1285             val = *(uint32_t *)(apic->int_en_reg + 20);
1286             break;
1287         case IER_OFFSET6:
1288             val = *(uint32_t *)(apic->int_en_reg + 24);
1289             break;
1290         case IER_OFFSET7:
1291             val = *(uint32_t *)(apic->int_en_reg + 28);
1292             break;
1293
1294         case ISR_OFFSET0:
1295             val = *(uint32_t *)(apic->int_svc_reg);
1296             break;
1297         case ISR_OFFSET1:
1298             val = *(uint32_t *)(apic->int_svc_reg + 4);
1299             break;
1300         case ISR_OFFSET2:
1301             val = *(uint32_t *)(apic->int_svc_reg + 8);
1302             break;
1303         case ISR_OFFSET3:
1304             val = *(uint32_t *)(apic->int_svc_reg + 12);
1305             break;
1306         case ISR_OFFSET4:
1307             val = *(uint32_t *)(apic->int_svc_reg + 16);
1308             break;
1309         case ISR_OFFSET5:
1310             val = *(uint32_t *)(apic->int_svc_reg + 20);
1311             break;
1312         case ISR_OFFSET6:
1313             val = *(uint32_t *)(apic->int_svc_reg + 24);
1314             break;
1315         case ISR_OFFSET7:
1316             val = *(uint32_t *)(apic->int_svc_reg + 28);
1317             break;
1318    
1319         case TRIG_OFFSET0:
1320             val = *(uint32_t *)(apic->trig_mode_reg);
1321             break;
1322         case TRIG_OFFSET1:
1323             val = *(uint32_t *)(apic->trig_mode_reg + 4);
1324             break;
1325         case TRIG_OFFSET2:
1326             val = *(uint32_t *)(apic->trig_mode_reg + 8);
1327             break;
1328         case TRIG_OFFSET3:
1329             val = *(uint32_t *)(apic->trig_mode_reg + 12);
1330             break;
1331         case TRIG_OFFSET4:
1332             val = *(uint32_t *)(apic->trig_mode_reg + 16);
1333             break;
1334         case TRIG_OFFSET5:
1335             val = *(uint32_t *)(apic->trig_mode_reg + 20);
1336             break;
1337         case TRIG_OFFSET6:
1338             val = *(uint32_t *)(apic->trig_mode_reg + 24);
1339             break;
1340         case TRIG_OFFSET7:
1341             val = *(uint32_t *)(apic->trig_mode_reg + 28);
1342             break;
1343
1344         case IRR_OFFSET0:
1345             val = *(uint32_t *)(apic->int_req_reg);
1346             break;
1347         case IRR_OFFSET1:
1348             val = *(uint32_t *)(apic->int_req_reg + 4);
1349             break;
1350         case IRR_OFFSET2:
1351             val = *(uint32_t *)(apic->int_req_reg + 8);
1352             break;
1353         case IRR_OFFSET3:
1354             val = *(uint32_t *)(apic->int_req_reg + 12);
1355             break;
1356         case IRR_OFFSET4:
1357             val = *(uint32_t *)(apic->int_req_reg + 16);
1358             break;
1359         case IRR_OFFSET5:
1360             val = *(uint32_t *)(apic->int_req_reg + 20);
1361             break;
1362         case IRR_OFFSET6:
1363             val = *(uint32_t *)(apic->int_req_reg + 24);
1364             break;
1365         case IRR_OFFSET7:
1366             val = *(uint32_t *)(apic->int_req_reg + 28);
1367             break;
1368         case TMR_CUR_CNT_OFFSET:
1369             val = apic->tmr_cur_cnt;
1370             break;
1371
1372             // We are not going to implement these....
1373         case THERM_LOC_VEC_TBL_OFFSET:
1374             val = apic->therm_loc_vec_tbl.val;
1375             break;
1376         case PERF_CTR_LOC_VEC_TBL_OFFSET:
1377             val = apic->perf_ctr_loc_vec_tbl.val;
1378             break;
1379
1380  
1381
1382             // handled registers
1383         case INT_CMD_LO_OFFSET:    
1384             val = apic->int_cmd.lo;
1385             break;
1386         case INT_CMD_HI_OFFSET:
1387             val = apic->int_cmd.hi;
1388             break;
1389
1390             // handle current timer count
1391
1392             // Unhandled Registers
1393         case EXT_INT_LOC_VEC_TBL_OFFSET0:
1394             val = apic->ext_intr_vec_tbl[0].val;
1395             break;
1396         case EXT_INT_LOC_VEC_TBL_OFFSET1:
1397             val = apic->ext_intr_vec_tbl[1].val;
1398             break;
1399         case EXT_INT_LOC_VEC_TBL_OFFSET2:
1400             val = apic->ext_intr_vec_tbl[2].val;
1401             break;
1402         case EXT_INT_LOC_VEC_TBL_OFFSET3:
1403             val = apic->ext_intr_vec_tbl[3].val;
1404             break;
1405     
1406
1407         case EXT_APIC_FEATURE_OFFSET:
1408         case EXT_APIC_CMD_OFFSET:
1409         case SEOI_OFFSET:
1410
1411         default:
1412             PrintError(core->vm_info, core, "apic %u: core %u: Read from Unhandled APIC Register: %x (getting zero)\n", 
1413                        apic->lapic_id.apic_id, core->vcpu_id, (uint32_t)reg_addr);
1414             memset(dst,0,length);
1415             return length;
1416     }
1417
1418
1419     if (length == 1) {
1420         uint_t byte_addr = reg_addr & 0x3;
1421         uint8_t * val_ptr = (uint8_t *)dst;
1422     
1423         *val_ptr = *(((uint8_t *)&val) + byte_addr);
1424
1425     } else if ((length == 2) && 
1426                ((reg_addr & 0x3) != 0x3)) {
1427         uint_t byte_addr = reg_addr & 0x3;
1428         uint16_t * val_ptr = (uint16_t *)dst;
1429         *val_ptr = *(((uint16_t *)&val) + byte_addr);
1430
1431     } else if (length == 4) {
1432         uint32_t * val_ptr = (uint32_t *)dst;
1433         *val_ptr = val;
1434
1435     } else {
1436         PrintError(core->vm_info, core, "apic %u: core %u: Invalid apic read length (%d)\n", 
1437                    apic->lapic_id.apic_id, core->vcpu_id, length);
1438         return -1;
1439     }
1440
1441     PrintDebug(core->vm_info, core, "apic %u: core %u: Read finished (val=%x)\n", 
1442                apic->lapic_id.apic_id, core->vcpu_id, *(uint32_t *)dst);
1443
1444     return length;
1445 }
1446
1447
1448 /**
1449  *
1450  */
1451 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data) {
1452     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1453     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1454     addr_t reg_addr  = guest_addr - apic->base_addr;
1455     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
1456     uint32_t op_val = *(uint32_t *)src;
1457     addr_t flags = 0;
1458
1459     PrintDebug(core->vm_info, core, "apic %u: core %u: at %p and priv_data is at %p\n",
1460                apic->lapic_id.apic_id, core->vcpu_id, apic, priv_data);
1461
1462     PrintDebug(core->vm_info, core, "apic %u: core %u: write to address space (%p) (val=%x)\n", 
1463                apic->lapic_id.apic_id, core->vcpu_id, (void *)guest_addr, *(uint32_t *)src);
1464
1465     if (msr->apic_enable == 0) {
1466         PrintError(core->vm_info, core, "apic %u: core %u: Write to APIC address space with disabled APIC, apic msr=0x%llx\n",
1467                    apic->lapic_id.apic_id, core->vcpu_id, apic->base_addr_msr.value);
1468         return -1;
1469     }
1470
1471
1472     if (length != 4) {
1473         PrintError(core->vm_info, core, "apic %u: core %u: Invalid apic write length (%d)\n", 
1474                    apic->lapic_id.apic_id, length, core->vcpu_id);
1475         return -1;
1476     }
1477
1478     switch (reg_addr) {
1479         case REMOTE_READ_OFFSET:
1480         case APIC_VERSION_OFFSET:
1481         case APR_OFFSET:
1482         case IRR_OFFSET0:
1483         case IRR_OFFSET1:
1484         case IRR_OFFSET2:
1485         case IRR_OFFSET3:
1486         case IRR_OFFSET4:
1487         case IRR_OFFSET5:
1488         case IRR_OFFSET6:
1489         case IRR_OFFSET7:
1490         case ISR_OFFSET0:
1491         case ISR_OFFSET1:
1492         case ISR_OFFSET2:
1493         case ISR_OFFSET3:
1494         case ISR_OFFSET4:
1495         case ISR_OFFSET5:
1496         case ISR_OFFSET6:
1497         case ISR_OFFSET7:
1498         case TRIG_OFFSET0:
1499         case TRIG_OFFSET1:
1500         case TRIG_OFFSET2:
1501         case TRIG_OFFSET3:
1502         case TRIG_OFFSET4:
1503         case TRIG_OFFSET5:
1504         case TRIG_OFFSET6:
1505         case TRIG_OFFSET7:
1506         case PPR_OFFSET:
1507         case EXT_APIC_FEATURE_OFFSET:
1508
1509             PrintError(core->vm_info, core, "apic %u: core %u: Attempting to write to read only register %p (error)\n", 
1510                        apic->lapic_id.apic_id, core->vcpu_id, (void *)reg_addr);
1511
1512             break;
1513
1514             // Data registers
1515         case APIC_ID_OFFSET:
1516             //V3_Print(core->vm_info, core, "apic %u: core %u: my id is being changed to 0x%x\n", 
1517             //       apic->lapic_id.apic_id, core->vcpu_id, op_val);
1518
1519             apic->lapic_id.val = op_val;
1520             break;
1521         case TPR_OFFSET:
1522             set_apic_tpr(apic,op_val);
1523             break;
1524         case LDR_OFFSET:
1525             PrintDebug(core->vm_info, core, "apic %u: core %u: setting log_dst.val to 0x%x\n",
1526                        apic->lapic_id.apic_id, core->vcpu_id, op_val);
1527             flags = v3_lock_irqsave(apic_dev->state_lock);
1528             apic->log_dst.val = op_val;
1529             v3_unlock_irqrestore(apic_dev->state_lock, flags);
1530             break;
1531         case DFR_OFFSET:
1532             flags = v3_lock_irqsave(apic_dev->state_lock);
1533             apic->dst_fmt.val = op_val;
1534             v3_unlock_irqrestore(apic_dev->state_lock, flags);
1535             break;
1536         case SPURIOUS_INT_VEC_OFFSET:
1537             apic->spurious_int.val = op_val;
1538             break;
1539         case ESR_OFFSET:
1540             apic->err_status.val = op_val;
1541             break;
1542         case TMR_LOC_VEC_TBL_OFFSET:
1543             apic->tmr_vec_tbl.val = op_val;
1544             break;
1545         case THERM_LOC_VEC_TBL_OFFSET:
1546             apic->therm_loc_vec_tbl.val = op_val;
1547             break;
1548         case PERF_CTR_LOC_VEC_TBL_OFFSET:
1549             apic->perf_ctr_loc_vec_tbl.val = op_val;
1550             break;
1551         case LINT0_VEC_TBL_OFFSET:
1552             apic->lint0_vec_tbl.val = op_val;
1553             break;
1554         case LINT1_VEC_TBL_OFFSET:
1555             apic->lint1_vec_tbl.val = op_val;
1556             break;
1557         case ERR_VEC_TBL_OFFSET:
1558             apic->err_vec_tbl.val = op_val;
1559             break;
1560         case TMR_INIT_CNT_OFFSET:
1561             apic->tmr_init_cnt = op_val;
1562             apic->tmr_cur_cnt = op_val;
1563             break;
1564         case TMR_CUR_CNT_OFFSET:
1565             apic->tmr_cur_cnt = op_val;
1566             break;
1567         case TMR_DIV_CFG_OFFSET:
1568             PrintDebug(core->vm_info, core, "apic %u: core %u: setting tmr_div_cfg to 0x%x\n",
1569                        apic->lapic_id.apic_id, core->vcpu_id, op_val);
1570             apic->tmr_div_cfg.val = op_val;
1571             break;
1572
1573
1574             // Enable mask (256 bits)
1575         case IER_OFFSET0:
1576             *(uint32_t *)(apic->int_en_reg) = op_val;
1577             break;
1578         case IER_OFFSET1:
1579             *(uint32_t *)(apic->int_en_reg + 4) = op_val;
1580             break;
1581         case IER_OFFSET2:
1582             *(uint32_t *)(apic->int_en_reg + 8) = op_val;
1583             break;
1584         case IER_OFFSET3:
1585             *(uint32_t *)(apic->int_en_reg + 12) = op_val;
1586             break;
1587         case IER_OFFSET4:
1588             *(uint32_t *)(apic->int_en_reg + 16) = op_val;
1589             break;
1590         case IER_OFFSET5:
1591             *(uint32_t *)(apic->int_en_reg + 20) = op_val;
1592             break;
1593         case IER_OFFSET6:
1594             *(uint32_t *)(apic->int_en_reg + 24) = op_val;
1595             break;
1596         case IER_OFFSET7:
1597             *(uint32_t *)(apic->int_en_reg + 28) = op_val;
1598             break;
1599
1600         case EXT_INT_LOC_VEC_TBL_OFFSET0:
1601             apic->ext_intr_vec_tbl[0].val = op_val;
1602             break;
1603         case EXT_INT_LOC_VEC_TBL_OFFSET1:
1604             apic->ext_intr_vec_tbl[1].val = op_val;
1605             break;
1606         case EXT_INT_LOC_VEC_TBL_OFFSET2:
1607             apic->ext_intr_vec_tbl[2].val = op_val;
1608             break;
1609         case EXT_INT_LOC_VEC_TBL_OFFSET3:
1610             apic->ext_intr_vec_tbl[3].val = op_val;
1611             break;
1612
1613
1614             // Action Registers
1615         case EOI_OFFSET:
1616             // do eoi 
1617             apic_do_eoi(core, apic);
1618             break;
1619
1620         case INT_CMD_LO_OFFSET: {
1621             // execute command 
1622
1623             struct v3_gen_ipi tmp_ipi;
1624
1625             apic->int_cmd.lo = op_val;
1626
1627             tmp_ipi.vector = apic->int_cmd.vec;
1628             tmp_ipi.mode = apic->int_cmd.del_mode;
1629             tmp_ipi.logical = apic->int_cmd.dst_mode;
1630             tmp_ipi.trigger_mode = apic->int_cmd.trig_mode;
1631             tmp_ipi.dst_shorthand = apic->int_cmd.dst_shorthand;
1632             tmp_ipi.dst = apic->int_cmd.dst;
1633                 
1634             tmp_ipi.ack = NULL;
1635             tmp_ipi.private_data = NULL;
1636             
1637
1638             //      V3_Print(core->vm_info, core, "apic %u: core %u: sending cmd 0x%llx to apic %u\n", 
1639             //       apic->lapic_id.apic_id, core->vcpu_id,
1640             //       apic->int_cmd.val, apic->int_cmd.dst);
1641
1642             if (route_ipi(apic_dev, apic, &tmp_ipi) == -1) { 
1643                 PrintError(core->vm_info, core, "IPI Routing failure\n");
1644                 return -1;
1645             }
1646
1647             break;
1648         }
1649         case INT_CMD_HI_OFFSET: {
1650             apic->int_cmd.hi = op_val;
1651             //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);
1652             break;
1653         }
1654         // Unhandled Registers
1655         case EXT_APIC_CMD_OFFSET:
1656         case SEOI_OFFSET:
1657         default:
1658             PrintError(core->vm_info, core, "apic %u: core %u: Write to Unhandled APIC Register: %x (ignored)\n", 
1659                        apic->lapic_id.apic_id, core->vcpu_id, (uint32_t)reg_addr);
1660
1661             return length;
1662     }
1663
1664     PrintDebug(core->vm_info, core, "apic %u: core %u: Write finished\n", apic->lapic_id.apic_id, core->vcpu_id);
1665
1666     return length;
1667
1668 }
1669
1670
1671
1672 /* Interrupt Controller Functions */
1673
1674
1675 static int apic_intr_pending(struct guest_info * core, void * private_data) {
1676     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
1677     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1678     int req_irq = 0;    
1679     int svc_irq = 0;
1680
1681     // Activate all queued IRQ entries
1682     drain_irq_entries(apic);
1683
1684     // Check for newly activated entries
1685     req_irq = get_highest_irr(apic);
1686     svc_irq = get_highest_isr(apic);
1687
1688     //    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);
1689
1690
1691     if ((req_irq >= 0) && 
1692         (req_irq > svc_irq)) {
1693
1694         // We have a new requested vector that is higher priority than
1695         // the vector that is in-service
1696
1697         uint32_t ppr = get_apic_ppr(apic);
1698
1699         if ((req_irq & 0xf0) > (ppr & 0xf0)) {
1700             // it's also higher priority than the current
1701             // processor priority.  Therefore this
1702             // interrupt can go in now.
1703             return 1;
1704         } else {
1705             // processor priority is currently too high
1706             // for this interrupt to go in now.  
1707             // note that if tpr=0xf?, then ppr=0xf?
1708             // and thus all vectors will be masked
1709             // as required (tpr=0xf? => all masked)
1710             return 0;
1711         }
1712     } else {
1713         // the vector that is in service is higher
1714         // priority than any new requested vector
1715         return 0;
1716     }
1717 }
1718
1719
1720
1721 static int apic_get_intr_number(struct guest_info * core, void * private_data) {
1722     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
1723     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1724     int req_irq = get_highest_irr(apic);
1725     int svc_irq = get_highest_isr(apic);
1726
1727
1728     // for the logic here, see the comments for apic_intr_pending
1729     if ((req_irq >=0) &&
1730         (req_irq > svc_irq)) { 
1731         
1732         uint32_t ppr = get_apic_ppr(apic);
1733         
1734         if ((req_irq & 0xf0) > (ppr & 0xf0)) {
1735             return req_irq;
1736         } else {
1737             // hmm, this should not have happened, but, anyway,
1738             // no interrupt is currently ready to go in
1739             return -1;
1740         }
1741     } else {
1742         return -1;
1743     }
1744 }
1745
1746
1747
1748 int v3_apic_send_ipi(struct v3_vm_info * vm, struct v3_gen_ipi * ipi, void * dev_data) {
1749     struct apic_dev_state * apic_dev = (struct apic_dev_state *)
1750         (((struct vm_device *)dev_data)->private_data);
1751
1752     return route_ipi(apic_dev, NULL, ipi);
1753 }
1754
1755
1756
1757 static int apic_begin_irq(struct guest_info * core, void * private_data, int irq) {
1758     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
1759     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1760     int major_offset = (irq & ~0x00000007) >> 3;
1761     int minor_offset = irq & 0x00000007;
1762     uint8_t *req_location = apic->int_req_reg + major_offset;
1763     uint8_t *svc_location = apic->int_svc_reg + major_offset;
1764     uint8_t flag = 0x01 << minor_offset;
1765
1766     if (*req_location & flag) {
1767         // we will only pay attention to a begin irq if we
1768         // know that we initiated it!
1769         *svc_location |= flag;
1770         *req_location &= ~flag;
1771     } else {
1772         // do nothing... 
1773         //PrintDebug(core->vm_info, core, "apic %u: core %u: begin irq for %d ignored since I don't own it\n",
1774         //         apic->lapic_id.apic_id, core->vcpu_id, irq);
1775     }
1776
1777     return 0;
1778 }
1779
1780
1781 /* Timer Functions */
1782
1783 static void apic_inject_timer_intr(struct guest_info *core,
1784                                    void * priv_data) {
1785     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1786     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1787     // raise irq
1788     PrintDebug(core->vm_info, core, "apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d)\n",
1789                apic->lapic_id.apic_id, core->vcpu_id,
1790                apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt);
1791
1792     if (apic_intr_pending(core, priv_data)) {
1793         PrintDebug(core->vm_info, core, "apic %u: core %u: Overriding pending IRQ %d\n", 
1794                    apic->lapic_id.apic_id, core->vcpu_id, 
1795                    apic_get_intr_number(core, priv_data));
1796     }
1797
1798     if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
1799         PrintError(core->vm_info, core, "apic %u: core %u: Could not raise Timer interrupt\n",
1800                    apic->lapic_id.apic_id, core->vcpu_id);
1801     }
1802
1803     return;
1804 }
1805         
1806
1807
1808
1809 static void apic_update_time(struct guest_info * core, 
1810                              uint64_t cpu_cycles, uint64_t cpu_freq, 
1811                              void * priv_data) {
1812     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1813     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1814
1815     // The 32 bit GCC runtime is a pile of shit
1816 #ifdef __V3_64BIT__
1817     uint64_t tmr_ticks = 0;
1818 #else 
1819     uint32_t tmr_ticks = 0;
1820 #endif
1821
1822     uint8_t tmr_div = *(uint8_t *)&(apic->tmr_div_cfg.val);
1823     uint_t shift_num = 0;
1824
1825
1826     // Check whether this is true:
1827     //   -> If the Init count is zero then the timer is disabled
1828     //      and doesn't just blitz interrupts to the CPU
1829     if ((apic->tmr_init_cnt == 0) || 
1830         ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
1831           (apic->tmr_cur_cnt == 0))) {
1832         //PrintDebug(core->vm_info, core, "apic %u: core %u: APIC timer not yet initialized\n",apic->lapic_id.apic_id,info->vcpu_id);
1833         return;
1834     }
1835
1836
1837     switch (tmr_div) {
1838         case APIC_TMR_DIV1:
1839             shift_num = 0;
1840             break;
1841         case APIC_TMR_DIV2:
1842             shift_num = 1;
1843             break;
1844         case APIC_TMR_DIV4:
1845             shift_num = 2;
1846             break;
1847         case APIC_TMR_DIV8:
1848             shift_num = 3;
1849             break;
1850         case APIC_TMR_DIV16:
1851             shift_num = 4;
1852             break;
1853         case APIC_TMR_DIV32:
1854             shift_num = 5;
1855             break;
1856         case APIC_TMR_DIV64:
1857             shift_num = 6;
1858             break;
1859         case APIC_TMR_DIV128:
1860             shift_num = 7;
1861             break;
1862         default:
1863             PrintError(core->vm_info, core, "apic %u: core %u: Invalid Timer Divider configuration\n",
1864                        apic->lapic_id.apic_id, core->vcpu_id);
1865             return;
1866     }
1867
1868     tmr_ticks = cpu_cycles >> shift_num;
1869     //    PrintDebug(core->vm_info, core, "Timer Ticks: %p\n", (void *)tmr_ticks);
1870
1871     if (tmr_ticks < apic->tmr_cur_cnt) {
1872         apic->tmr_cur_cnt -= tmr_ticks;
1873 #ifdef V3_CONFIG_APIC_ENQUEUE_MISSED_TMR_IRQS
1874         if (apic->missed_ints && !apic_intr_pending(core, priv_data)) {
1875             PrintDebug(core->vm_info, core, "apic %u: core %u: Injecting queued APIC timer interrupt.\n",
1876                        apic->lapic_id.apic_id, core->vcpu_id);
1877             apic_inject_timer_intr(core, priv_data);
1878             apic->missed_ints--;
1879         }
1880 #endif /* CONFIG_APIC_ENQUEUE_MISSED_TMR_IRQS */ 
1881     } else {
1882         tmr_ticks -= apic->tmr_cur_cnt;
1883         apic->tmr_cur_cnt = 0;
1884
1885         apic_inject_timer_intr(core, priv_data);
1886
1887         if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
1888             int queued_ints = tmr_ticks / apic->tmr_init_cnt;
1889             tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
1890             apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
1891             apic->missed_ints += queued_ints;
1892         }
1893     }
1894
1895     return;
1896 }
1897
1898 static struct intr_ctrl_ops intr_ops = {
1899     .intr_pending = apic_intr_pending,
1900     .get_intr_number = apic_get_intr_number,
1901     .begin_irq = apic_begin_irq,
1902 };
1903
1904
1905 static struct v3_timer_ops timer_ops = {
1906     .update_timer = apic_update_time,
1907 };
1908
1909
1910
1911
1912 static int apic_free(struct apic_dev_state * apic_dev) {
1913     int i = 0;
1914     struct v3_vm_info * vm = NULL;
1915
1916     for (i = 0; i < apic_dev->num_apics; i++) {
1917         struct apic_state * apic = &(apic_dev->apics[i]);
1918         struct guest_info * core = apic->core;
1919         
1920         vm = core->vm_info;
1921
1922         v3_remove_intr_controller(core, apic->controller_handle);
1923
1924         if (apic->timer) {
1925             v3_remove_timer(core, apic->timer);
1926         }
1927
1928         v3_lock_deinit(&(apic->irq_queue.lock));
1929
1930         v3_unhook_mem(vm,core->vcpu_id,apic->base_addr);
1931
1932     }
1933
1934     v3_unhook_msr(vm, BASE_ADDR_MSR);
1935
1936     v3_lock_deinit(&(apic_dev->state_lock));
1937
1938     V3_Free(apic_dev);
1939     return 0;
1940 }
1941
1942 #ifdef V3_CONFIG_CHECKPOINT
1943
1944 #define KEY_MAX 128
1945 #define MAKE_KEY(x) snprintf(key,KEY_MAX,"%s%d",x,i);
1946
1947 static int apic_save(struct v3_chkpt_ctx * ctx, void * private_data) {
1948     struct apic_dev_state * apic_state = (struct apic_dev_state *)private_data;
1949     int i = 0;
1950     uint32_t temp;
1951     char key[KEY_MAX];
1952
1953     V3_CHKPT_SAVE(ctx, "NUM_APICS", apic_state->num_apics,savefailout);
1954
1955     for (i = 0; i < apic_state->num_apics; i++) {
1956       drain_irq_entries(&(apic_state->apics[i]));
1957
1958       MAKE_KEY("BASE_ADDR"); 
1959       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].base_addr,savefailout);
1960       MAKE_KEY("BASE_ADDR_MSR"); 
1961       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].base_addr_msr,savefailout);
1962       MAKE_KEY("LAPIC_ID");
1963       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].lapic_id,savefailout);
1964       MAKE_KEY("APIC_VER");
1965       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].apic_ver,savefailout);
1966       MAKE_KEY("EXT_APIC_CTRL");
1967       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ext_apic_ctrl,savefailout);
1968       MAKE_KEY("LOCAL_VEC_TBL");
1969       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].local_vec_tbl,savefailout);
1970       MAKE_KEY("TMR_VEC_TBL");
1971       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_vec_tbl,savefailout);
1972       MAKE_KEY("TMR_DIV_CFG");
1973       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_div_cfg,savefailout);
1974       MAKE_KEY("LINT0_VEC_TBL");
1975       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].lint0_vec_tbl,savefailout);
1976       MAKE_KEY("LINT1_VEC_TBL");
1977       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].lint1_vec_tbl,savefailout);
1978       MAKE_KEY("PERF_CTR_LOC_VEC_TBL");
1979       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].perf_ctr_loc_vec_tbl,savefailout);
1980       MAKE_KEY("THERM_LOC_VEC_TBL");
1981       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].therm_loc_vec_tbl,savefailout);
1982       MAKE_KEY("ERR_VEC_TBL");
1983       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].err_vec_tbl,savefailout);
1984       MAKE_KEY("ERR_STATUS");
1985       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].err_status,savefailout);
1986       MAKE_KEY("SPURIOUS_INT");
1987       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].spurious_int,savefailout);
1988       MAKE_KEY("INT_CMD");
1989       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_cmd,savefailout);
1990       MAKE_KEY("LOG_DST");
1991       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].log_dst,savefailout);
1992       MAKE_KEY("DST_FMT");
1993       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].dst_fmt,savefailout);
1994
1995       // APR and PPR are stored only for compatability
1996       // TPR is in APIC_TPR, APR and PPR are derived
1997         
1998       temp = get_apic_apr(&(apic_state->apics[i]));
1999       MAKE_KEY("ARB_PRIO");
2000       V3_CHKPT_SAVE(ctx, key, temp,savefailout);
2001       temp = get_apic_tpr(&(apic_state->apics[i]));
2002       MAKE_KEY("TASK_PRIO");
2003       V3_CHKPT_SAVE(ctx,key,temp,savefailout);
2004       temp = get_apic_ppr(&(apic_state->apics[i]));
2005       MAKE_KEY("PROC_PRIO");
2006       V3_CHKPT_SAVE(ctx, key,temp,savefailout);
2007
2008       MAKE_KEY("EXT_APIC_FEATURE");
2009       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ext_apic_feature,savefailout);
2010       MAKE_KEY("SPEC_EOI");
2011       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].spec_eoi,savefailout);
2012       MAKE_KEY("TMR_CUR_CNT");
2013       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_cur_cnt,savefailout);
2014       
2015       MAKE_KEY("TMR_INIT_CNT");
2016       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_init_cnt,savefailout);
2017       MAKE_KEY("EXT_INTR_VEC_TBL");
2018       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ext_intr_vec_tbl,savefailout);
2019
2020       MAKE_KEY("REM_RD_DATA");
2021       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].rem_rd_data,savefailout);
2022       MAKE_KEY("IPI_STATE");
2023       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ipi_state,savefailout);
2024       MAKE_KEY("INT_REQ_REG");
2025       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_req_reg,savefailout);
2026       MAKE_KEY("INT_SVC_REG");
2027       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_svc_reg,savefailout);
2028       MAKE_KEY("INT_EN_REG");
2029       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_en_reg,savefailout);
2030       MAKE_KEY("TRIG_MODE_REG");
2031       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].trig_mode_reg,savefailout);
2032       MAKE_KEY("EOI");
2033       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].eoi,savefailout);
2034
2035     }
2036
2037     return 0;
2038
2039  savefailout:
2040     PrintError(VM_NONE, VCORE_NONE, "Failed to save apic\n");
2041     return -1;
2042 }
2043
2044 static int apic_load(struct v3_chkpt_ctx * ctx, void * private_data) {
2045     struct apic_dev_state *apic_state = (struct apic_dev_state *)private_data;
2046     int i = 0;
2047     uint32_t temp;
2048     char key[KEY_MAX];
2049
2050     V3_CHKPT_LOAD(ctx,"NUM_APICS", apic_state->num_apics, loadfailout);
2051
2052     for (i = 0; i < apic_state->num_apics; i++) {
2053       drain_irq_entries(&(apic_state->apics[i]));
2054
2055       MAKE_KEY("BASE_ADDR"); 
2056       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].base_addr,loadfailout);
2057       MAKE_KEY("BASE_ADDR_MSR"); 
2058       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].base_addr_msr,loadfailout);
2059       MAKE_KEY("LAPIC_ID");
2060       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].lapic_id,loadfailout);
2061       MAKE_KEY("APIC_VER");
2062       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].apic_ver,loadfailout);
2063       MAKE_KEY("EXT_APIC_CTRL");
2064       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ext_apic_ctrl,loadfailout);
2065       MAKE_KEY("LOCAL_VEC_TBL");
2066       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].local_vec_tbl,loadfailout);
2067       MAKE_KEY("TMR_VEC_TBL");
2068       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_vec_tbl,loadfailout);
2069       MAKE_KEY("TMR_DIV_CFG");
2070       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_div_cfg,loadfailout);
2071       MAKE_KEY("LINT0_VEC_TBL");
2072       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].lint0_vec_tbl,loadfailout);
2073       MAKE_KEY("LINT1_VEC_TBL");
2074       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].lint1_vec_tbl,loadfailout);
2075       MAKE_KEY("PERF_CTR_LOC_VEC_TBL");
2076       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].perf_ctr_loc_vec_tbl,loadfailout);
2077       MAKE_KEY("THERM_LOC_VEC_TBL");
2078       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].therm_loc_vec_tbl,loadfailout);
2079       MAKE_KEY("ERR_VEC_TBL");
2080       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].err_vec_tbl,loadfailout);
2081       MAKE_KEY("ERR_STATUS");
2082       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].err_status,loadfailout);
2083       MAKE_KEY("SPURIOUS_INT");
2084       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].spurious_int,loadfailout);
2085       MAKE_KEY("INT_CMD");
2086       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_cmd,loadfailout);
2087       MAKE_KEY("LOG_DST");
2088       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].log_dst,loadfailout);
2089       MAKE_KEY("DST_FMT");
2090       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].dst_fmt,loadfailout);
2091
2092       // APR and PPR are stored only for compatability
2093       // TPR is in APIC_TPR, APR and PPR are derived
2094
2095       MAKE_KEY("ARB_PRIO");
2096       V3_CHKPT_LOAD(ctx, key, temp,loadfailout);
2097       // discarded
2098
2099       MAKE_KEY("TASK_PRIO");
2100       V3_CHKPT_LOAD(ctx,key,temp,loadfailout);
2101       set_apic_tpr(&(apic_state->apics[i]),temp);
2102       
2103       MAKE_KEY("PROC_PRIO");
2104       V3_CHKPT_LOAD(ctx, key,temp,loadfailout);
2105       // discarded
2106
2107
2108       MAKE_KEY("EXT_APIC_FEATURE");
2109       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ext_apic_feature,loadfailout);
2110       MAKE_KEY("SPEC_EOI");
2111       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].spec_eoi,loadfailout);
2112       MAKE_KEY("TMR_CUR_CNT");
2113       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_cur_cnt,loadfailout);
2114       
2115       MAKE_KEY("TMR_INIT_CNT");
2116       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_init_cnt,loadfailout);
2117       MAKE_KEY("EXT_INTR_VEC_TBL");
2118       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ext_intr_vec_tbl,loadfailout);
2119
2120       MAKE_KEY("REM_RD_DATA");
2121       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].rem_rd_data,loadfailout);
2122       MAKE_KEY("IPI_STATE");
2123       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ipi_state,loadfailout);
2124       MAKE_KEY("INT_REQ_REG");
2125       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_req_reg,loadfailout);
2126       MAKE_KEY("INT_SVC_REG");
2127       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_svc_reg,loadfailout);
2128       MAKE_KEY("INT_EN_REG");
2129       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_en_reg,loadfailout);
2130       MAKE_KEY("TRIG_MODE_REG");
2131       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].trig_mode_reg,loadfailout);
2132       MAKE_KEY("EOI");
2133       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].eoi,loadfailout);
2134     }
2135     
2136     
2137     return 0;
2138     
2139  loadfailout:
2140     PrintError(VM_NONE,VCORE_NONE, "Failed to load apic\n");
2141     return -1;
2142     
2143 }
2144
2145 #endif
2146
2147 static struct v3_device_ops dev_ops = {
2148     .free = (int (*)(void *))apic_free,
2149 #ifdef V3_CONFIG_CHECKPOINT
2150     .save = apic_save,
2151     .load = apic_load
2152 #endif
2153 };
2154
2155
2156
2157 static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2158     char * dev_id = v3_cfg_val(cfg, "ID");
2159     struct apic_dev_state * apic_dev = NULL;
2160     int i = 0;
2161
2162     PrintDebug(vm, VCORE_NONE, "apic: creating an APIC for each core\n");
2163
2164     apic_dev = (struct apic_dev_state *)V3_Malloc(sizeof(struct apic_dev_state) + 
2165                                                   sizeof(struct apic_state) * vm->num_cores);
2166
2167
2168     if (!apic_dev) {
2169         PrintError(vm, VCORE_NONE, "Failed to allocate space for APIC\n");
2170         return -1;
2171     }
2172
2173     memset(apic_dev,0,
2174            sizeof(struct apic_dev_state) + 
2175            sizeof(struct apic_state) * vm->num_cores);
2176
2177     apic_dev->num_apics = vm->num_cores;
2178     v3_lock_init(&(apic_dev->state_lock));
2179
2180     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, apic_dev);
2181
2182     if (dev == NULL) {
2183         PrintError(vm, VCORE_NONE, "apic: Could not attach device %s\n", dev_id);
2184         V3_Free(apic_dev);
2185         return -1;
2186     }
2187
2188     
2189     for (i = 0; i < vm->num_cores; i++) {
2190         struct apic_state * apic = &(apic_dev->apics[i]);
2191         struct guest_info * core = &(vm->cores[i]);
2192
2193         apic->core = core;
2194
2195         init_apic_state(apic, i);
2196
2197         apic->controller_handle = v3_register_intr_controller(core, &intr_ops, apic_dev);
2198
2199         apic->timer = v3_add_timer(core, &timer_ops, apic_dev);
2200
2201         if (apic->timer == NULL) {
2202             PrintError(vm, VCORE_NONE,"APIC: Failed to attach timer to core %d\n", i);
2203             v3_remove_device(dev);
2204             return -1;
2205         }
2206
2207         // hook to initial location
2208         v3_hook_full_mem(vm, core->vcpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, apic_dev);
2209
2210         PrintDebug(vm, VCORE_NONE, "apic %u: (setup device): done, my id is %u\n", i, apic->lapic_id.apic_id);
2211     }
2212
2213 #ifdef V3_CONFIG_DEBUG_APIC
2214     for (i = 0; i < vm->num_cores; i++) {
2215         struct apic_state * apic = &(apic_dev->apics[i]);
2216         PrintDebug(vm, VCORE_NONE, "apic: sanity check: apic %u (at %p) has id %u and msr value %llx and core at %p\n",
2217                    i, apic, apic->lapic_id.apic_id, apic->base_addr_msr.value,apic->core);
2218     }
2219 #endif
2220
2221
2222     PrintDebug(vm, VCORE_NONE, "apic: priv_data is at %p\n", apic_dev);
2223
2224     v3_hook_msr(vm, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, apic_dev);
2225
2226     return 0;
2227 }
2228
2229 static char hexify_nybble(char c)
2230 {
2231     if (c>=0 && c<=9) { 
2232         return '0'+c;
2233     } else if (c>=0xa && c<=0xf) { 
2234         return 'a'+(c-0xa);
2235     } else {
2236         return -1;
2237     }
2238 }
2239
2240
2241 static int hexify_byte(char *c, char b)
2242 {
2243     char n;
2244     n = hexify_nybble( (b >> 4) & 0xf);
2245     if (n==-1) { 
2246         return -1;
2247     }
2248     c[0] = n;
2249     n = hexify_nybble( b & 0xf);
2250     if (n==-1) { 
2251         return -1;
2252     }
2253     c[1] = n;
2254     return 0;
2255 }
2256
2257 // dest must be of length at least 2*n+1
2258 static int hexify_byte_string(char *dest, char *src, int n)
2259 {
2260     int i;
2261     for (i=0;i<n;i++) { 
2262         if (hexify_byte(dest,src[i])) { 
2263             return -1;
2264         }
2265         dest+=2;
2266     }
2267     *dest=0;
2268     return 0;
2269 }
2270
2271
2272 static __attribute__((unused)) void dump_all_apic_state(struct v3_vm_info *vm, struct apic_dev_state *a)
2273 {
2274     int i;
2275     for (i=0;i<a->num_apics;i++) { 
2276         dump_apic_state(&(vm->cores[i]),&(a->apics[i]));
2277     }
2278 }
2279         
2280 static void dump_apic_state(struct guest_info *core, struct apic_state * a) 
2281 {
2282     char buf[80];
2283     struct irq_queue_entry *ie;
2284
2285     V3_Print(core->vm_info, core, "APIC (vcore %d) {\n", core->vcpu_id);
2286     V3_Print(core->vm_info, core, "\tbase_addr: %llx\n", (uint64_t)(a->base_addr));
2287     V3_Print(core->vm_info, core, "\tlapic_id_reg {\n");
2288     V3_Print(core->vm_info, core, "\t\trsvd: 0x%x\n", a->lapic_id.rsvd);
2289     V3_Print(core->vm_info, core, "\t\tapic_id: 0x%x\n", a->lapic_id.apic_id);
2290     V3_Print(core->vm_info, core, "\t}\n");
2291     V3_Print(core->vm_info, core, "\tapic_ver_reg {\n");
2292     V3_Print(core->vm_info, core, "\t\tver: 0x%x\n", a->apic_ver.ver);
2293     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->apic_ver.rsvd1);
2294     V3_Print(core->vm_info, core, "\t\tmax_lvts: 0x%x\n", a->apic_ver.max_lvts);
2295     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->apic_ver.rsvd2);
2296     V3_Print(core->vm_info, core, "\t\text_reg_present: 0x%x\n", a->apic_ver.ext_reg_present);
2297     V3_Print(core->vm_info, core, "\t}\n");
2298     V3_Print(core->vm_info, core, "\text_apic_ctrl_reg {\n");
2299     V3_Print(core->vm_info, core, "\t\tver: 0x%x\n", a->ext_apic_ctrl.ver);
2300     V3_Print(core->vm_info, core, "\t\tseoi_enable: 0x%x\n", a->ext_apic_ctrl.seoi_enable);
2301     V3_Print(core->vm_info, core, "\t\text_id_enable: 0x%x\n", a->ext_apic_ctrl.ext_id_enable);
2302     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_apic_ctrl.rsvd2);
2303     V3_Print(core->vm_info, core, "\t}\n");
2304     V3_Print(core->vm_info, core, "\tlocal_vec_tbl_reg {\n");
2305     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->local_vec_tbl.vec);
2306     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->local_vec_tbl.msg_type);
2307     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->local_vec_tbl.rsvd1);
2308     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->local_vec_tbl.del_status);
2309     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->local_vec_tbl.rsvd2);
2310     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->local_vec_tbl.rem_irr);
2311     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->local_vec_tbl.trig_mode);
2312     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->local_vec_tbl.mask);
2313     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->local_vec_tbl.tmr_mode);
2314     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->local_vec_tbl.rsvd3);
2315     V3_Print(core->vm_info, core, "\t}\n");
2316     V3_Print(core->vm_info, core, "\ttmr_vec_tbl_reg {\n");
2317     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->tmr_vec_tbl.vec);
2318     V3_Print(core->vm_info, core, "\t\trsvd: 0x%x\n", a->tmr_vec_tbl.rsvd);
2319     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->tmr_vec_tbl.del_status);
2320     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->tmr_vec_tbl.rsvd2);
2321     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->tmr_vec_tbl.mask);
2322     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->tmr_vec_tbl.tmr_mode);
2323     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->tmr_vec_tbl.rsvd3);
2324     V3_Print(core->vm_info, core, "\t}\n");
2325     V3_Print(core->vm_info, core, "\ttmr_div_cfg_reg {\n");
2326     V3_Print(core->vm_info, core, "\t\tdiv_val: 0x%x\n", a->tmr_div_cfg.div_val);
2327     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->tmr_div_cfg.rsvd1);
2328     V3_Print(core->vm_info, core, "\t\tdiv_val2: 0x%x\n", a->tmr_div_cfg.div_val2);
2329     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->tmr_div_cfg.rsvd2);
2330     V3_Print(core->vm_info, core, "\t}\n");
2331     V3_Print(core->vm_info, core, "\tlint_vec_tbl_reg 0 {\n");
2332     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->lint0_vec_tbl.vec);
2333     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->lint0_vec_tbl.msg_type);
2334     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->lint0_vec_tbl.rsvd1);
2335     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->lint0_vec_tbl.del_status);
2336     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->lint0_vec_tbl.rsvd2);
2337     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->lint0_vec_tbl.rem_irr);
2338     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->lint0_vec_tbl.trig_mode);
2339     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->lint0_vec_tbl.mask);
2340     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->lint0_vec_tbl.rsvd3);
2341     V3_Print(core->vm_info, core, "\t}\n");
2342     V3_Print(core->vm_info, core, "\tlint_vec_tbl_reg 1 {\n");
2343     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->lint1_vec_tbl.vec);
2344     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->lint1_vec_tbl.msg_type);
2345     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->lint1_vec_tbl.rsvd1);
2346     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->lint1_vec_tbl.del_status);
2347     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->lint1_vec_tbl.rsvd2);
2348     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->lint1_vec_tbl.rem_irr);
2349     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->lint1_vec_tbl.trig_mode);
2350     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->lint1_vec_tbl.mask);
2351     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->lint1_vec_tbl.rsvd3);
2352     V3_Print(core->vm_info, core, "\t}\n");
2353     V3_Print(core->vm_info, core, "\tperf_ctr_loc_vec_tbl_reg {\n");
2354     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->perf_ctr_loc_vec_tbl.vec);
2355     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->perf_ctr_loc_vec_tbl.msg_type);
2356     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->perf_ctr_loc_vec_tbl.rsvd1);
2357     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->perf_ctr_loc_vec_tbl.del_status);
2358     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->perf_ctr_loc_vec_tbl.rsvd2);
2359     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->perf_ctr_loc_vec_tbl.mask);
2360     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->perf_ctr_loc_vec_tbl.rsvd3);
2361     V3_Print(core->vm_info, core, "\t}\n");
2362     V3_Print(core->vm_info, core, "\ttherm_loc_vec_tbl_reg {\n");
2363     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->therm_loc_vec_tbl.vec);
2364     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->therm_loc_vec_tbl.msg_type);
2365     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->therm_loc_vec_tbl.rsvd1);
2366     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->therm_loc_vec_tbl.del_status);
2367     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->therm_loc_vec_tbl.rsvd2);
2368     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->therm_loc_vec_tbl.mask);
2369     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->therm_loc_vec_tbl.rsvd3);
2370     V3_Print(core->vm_info, core, "\t}\n");
2371     V3_Print(core->vm_info, core, "\terr_vec_tbl_reg {\n");
2372     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->err_vec_tbl.vec);
2373     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->err_vec_tbl.msg_type);
2374     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->err_vec_tbl.rsvd1);
2375     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->err_vec_tbl.del_status);
2376     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->err_vec_tbl.rsvd2);
2377     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->err_vec_tbl.mask);
2378     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->err_vec_tbl.rsvd3);
2379     V3_Print(core->vm_info, core, "\t}\n");
2380     V3_Print(core->vm_info, core, "\terr_status_reg {\n");
2381     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->err_status.rsvd1);
2382     V3_Print(core->vm_info, core, "\t\tsent_acc_err: 0x%x\n", a->err_status.sent_acc_err);
2383     V3_Print(core->vm_info, core, "\t\trecv_acc_err: 0x%x\n", a->err_status.recv_acc_err);
2384     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->err_status.rsvd2);
2385     V3_Print(core->vm_info, core, "\t\tsent_ill_err: 0x%x\n", a->err_status.sent_ill_err);
2386     V3_Print(core->vm_info, core, "\t\trecv_ill_err: 0x%x\n", a->err_status.recv_ill_err);
2387     V3_Print(core->vm_info, core, "\t\till_reg_addr: 0x%x\n", a->err_status.ill_reg_addr);
2388     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->err_status.rsvd3);
2389     V3_Print(core->vm_info, core, "\t}\n");
2390     V3_Print(core->vm_info, core, "\tspurious_int_reg {\n");
2391     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->spurious_int.vec);
2392     V3_Print(core->vm_info, core, "\t\tapic_soft_en: 0x%x\n", a->spurious_int.apic_soft_en);
2393     V3_Print(core->vm_info, core, "\t\tfoc_cpu_chk: 0x%x\n", a->spurious_int.foc_cpu_chk);
2394     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->spurious_int.rsvd1);
2395     V3_Print(core->vm_info, core, "\t}\n");
2396     V3_Print(core->vm_info, core, "\tint_cmd_reg {\n");
2397     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->int_cmd.vec);
2398     V3_Print(core->vm_info, core, "\t\tdel_mode: 0x%x\n", a->int_cmd.del_mode);
2399     V3_Print(core->vm_info, core, "\t\tdst_mode: 0x%x\n", a->int_cmd.dst_mode);
2400     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->int_cmd.del_status);
2401     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->int_cmd.rsvd1);
2402     V3_Print(core->vm_info, core, "\t\tlvl: 0x%x\n", a->int_cmd.lvl);
2403     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->int_cmd.trig_mode);
2404     V3_Print(core->vm_info, core, "\t\trm_rd_status: 0x%x\n", a->int_cmd.rem_rd_status);
2405     V3_Print(core->vm_info, core, "\t\tdst_shorthand: 0x%x\n", a->int_cmd.dst_shorthand);
2406     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%llx\n", (uint64_t)(a->int_cmd.rsvd2));
2407     V3_Print(core->vm_info, core, "\t\tdst: 0x%x\n", a->int_cmd.dst);
2408     V3_Print(core->vm_info, core, "\t}\n");
2409     V3_Print(core->vm_info, core, "\tlog_dst_reg {\n");
2410     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->log_dst.rsvd1);
2411     V3_Print(core->vm_info, core, "\t\tdst_log_id: 0x%x\n", a->log_dst.dst_log_id);
2412     V3_Print(core->vm_info, core, "\t}\n");
2413     V3_Print(core->vm_info, core, "\tdst_fmt_reg {\n");
2414     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->dst_fmt.rsvd1);
2415     V3_Print(core->vm_info, core, "\t\tmodel: 0x%x\n", a->dst_fmt.model);
2416     V3_Print(core->vm_info, core, "\t}\n");
2417     V3_Print(core->vm_info, core, "\tarb_prio_reg: 0x%x\n",get_apic_apr(a));
2418     V3_Print(core->vm_info, core, "\ttask_prio_reg: 0x%x\n", get_apic_tpr(a));
2419     V3_Print(core->vm_info, core, "\tproc_prio_reg: 0x%x\n",get_apic_ppr(a));
2420     V3_Print(core->vm_info, core, "\text_apic_feature_reg {\n");
2421     V3_Print(core->vm_info, core, "\t\tint_en_reg_cap: 0x%x\n", a->ext_apic_feature.int_en_reg_cap);
2422     V3_Print(core->vm_info, core, "\t\tspec_eoi_cap: 0x%x\n", a->ext_apic_feature.spec_eoi_cap);
2423     V3_Print(core->vm_info, core, "\t\text_apic_id_cap: 0x%x\n", a->ext_apic_feature.ext_apic_id_cap);
2424     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->ext_apic_feature.rsvd1);
2425     V3_Print(core->vm_info, core, "\t\text_lvt_cnt: 0x%x\n", a->ext_apic_feature.ext_lvt_cnt);
2426     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_apic_feature.rsvd2);
2427     V3_Print(core->vm_info, core, "\t}\n");
2428     V3_Print(core->vm_info, core, "\tspec_eoi_reg {\n");
2429     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->spec_eoi.vec);
2430     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->spec_eoi.rsvd1);
2431     V3_Print(core->vm_info, core, "\t}\n");
2432     V3_Print(core->vm_info, core, "\ttmr_cur_cnt: 0x%x\n", a->tmr_cur_cnt);
2433     V3_Print(core->vm_info, core, "\ttmr_init_cnt: 0x%x\n", a->tmr_init_cnt);
2434     V3_Print(core->vm_info, core, "\tmissed_ints: 0x%x\n", a->missed_ints);
2435     V3_Print(core->vm_info, core, "\text_vec_tbl_reg 0 {\n");
2436     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->ext_intr_vec_tbl[0].vec);
2437     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->ext_intr_vec_tbl[0].msg_type);
2438     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->ext_intr_vec_tbl[0].rsvd1);
2439     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->ext_intr_vec_tbl[0].del_status);
2440     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_intr_vec_tbl[0].rsvd2);
2441     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->ext_intr_vec_tbl[0].rem_irr);
2442     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->ext_intr_vec_tbl[0].trig_mode);
2443     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->ext_intr_vec_tbl[0].mask);
2444     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->ext_intr_vec_tbl[0].tmr_mode);
2445     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->ext_intr_vec_tbl[0].rsvd3);
2446     V3_Print(core->vm_info, core, "\t}\n");
2447     V3_Print(core->vm_info, core, "\text_vec_tbl_reg 1 {\n");
2448     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->ext_intr_vec_tbl[1].vec);
2449     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->ext_intr_vec_tbl[1].msg_type);
2450     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->ext_intr_vec_tbl[1].rsvd1);
2451     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->ext_intr_vec_tbl[1].del_status);
2452     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_intr_vec_tbl[1].rsvd2);
2453     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->ext_intr_vec_tbl[1].rem_irr);
2454     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->ext_intr_vec_tbl[1].trig_mode);
2455     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->ext_intr_vec_tbl[1].mask);
2456     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->ext_intr_vec_tbl[1].tmr_mode);
2457     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->ext_intr_vec_tbl[1].rsvd3);
2458     V3_Print(core->vm_info, core, "\t}\n");
2459     V3_Print(core->vm_info, core, "\text_vec_tbl_reg 2 {\n");
2460     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->ext_intr_vec_tbl[2].vec);
2461     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->ext_intr_vec_tbl[2].msg_type);
2462     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->ext_intr_vec_tbl[2].rsvd1);
2463     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->ext_intr_vec_tbl[2].del_status);
2464     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_intr_vec_tbl[2].rsvd2);
2465     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->ext_intr_vec_tbl[2].rem_irr);
2466     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->ext_intr_vec_tbl[2].trig_mode);
2467     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->ext_intr_vec_tbl[2].mask);
2468     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->ext_intr_vec_tbl[2].tmr_mode);
2469     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->ext_intr_vec_tbl[2].rsvd3);
2470     V3_Print(core->vm_info, core, "\t}\n");
2471     V3_Print(core->vm_info, core, "\text_vec_tbl_reg 3 {\n");
2472     V3_Print(core->vm_info, core, "\t\tvec: 0x%x\n", a->ext_intr_vec_tbl[3].vec);
2473     V3_Print(core->vm_info, core, "\t\tmsg_type: 0x%x\n", a->ext_intr_vec_tbl[3].msg_type);
2474     V3_Print(core->vm_info, core, "\t\trsvd1: 0x%x\n", a->ext_intr_vec_tbl[3].rsvd1);
2475     V3_Print(core->vm_info, core, "\t\tdel_status: 0x%x\n", a->ext_intr_vec_tbl[3].del_status);
2476     V3_Print(core->vm_info, core, "\t\trsvd2: 0x%x\n", a->ext_intr_vec_tbl[3].rsvd2);
2477     V3_Print(core->vm_info, core, "\t\trem_irr: 0x%x\n", a->ext_intr_vec_tbl[3].rem_irr);
2478     V3_Print(core->vm_info, core, "\t\ttrig_mode: 0x%x\n", a->ext_intr_vec_tbl[3].trig_mode);
2479     V3_Print(core->vm_info, core, "\t\tmask: 0x%x\n", a->ext_intr_vec_tbl[3].mask);
2480     V3_Print(core->vm_info, core, "\t\ttmr_mode: 0x%x\n", a->ext_intr_vec_tbl[3].tmr_mode);
2481     V3_Print(core->vm_info, core, "\t\trsvd3: 0x%x\n", a->ext_intr_vec_tbl[3].rsvd3);
2482     V3_Print(core->vm_info, core, "\t}\n");
2483     V3_Print(core->vm_info, core, "\trem_rd_data: 0x%x\n", a->rem_rd_data);
2484     hexify_byte_string(buf,a->int_req_reg,32);
2485     V3_Print(core->vm_info, core, "\tint_req_reg: 0x%s\n",buf);
2486     hexify_byte_string(buf,a->int_svc_reg,32);
2487     V3_Print(core->vm_info, core, "\tint_svc_reg: 0x%s\n",buf);
2488     hexify_byte_string(buf,a->int_en_reg,32);
2489     V3_Print(core->vm_info, core, "\tint_en_reg: 0x%s\n",buf);
2490     hexify_byte_string(buf,a->trig_mode_reg,32);
2491     V3_Print(core->vm_info, core, "\ttrig_mode_reg: 0x%s\n",buf);
2492     V3_Print(core->vm_info, core, "\tirq_ack_cbs: SKIPPED\n");
2493     V3_Print(core->vm_info, core, "\tirq_queue: (follows)\n");
2494     // note we do not hold the lock for purposes of printing this list... 
2495     list_for_each_entry(ie,&(a->irq_queue.entries), list_node) {
2496         V3_Print(core->vm_info,core,"\t\tvector 0x%x ack %p priv %p\n", ie->vector, ie->ack, ie->private_data);
2497     }
2498     V3_Print(core->vm_info, core, "\t}\n");
2499     V3_Print(core->vm_info, core, "\teoi: 0x%x\n", a->eoi);
2500     V3_Print(core->vm_info, core,"}\n");
2501 }
2502
2503
2504
2505
2506
2507
2508 device_register("LAPIC", apic_init)