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.


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