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.


Enable cores to be reset via INIT IPI
[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
279
280 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data);
281 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data);
282
283 static void set_apic_tpr(struct apic_state *apic, uint32_t val);
284
285 static int is_apic_bsp(struct apic_state * apic) {
286     return ((apic->base_addr_msr.value & 0x0000000000000100LL) != 0);
287 }
288
289
290
291
292 // No locking done
293 static void init_apic_state(struct apic_state * apic, uint32_t id) {
294     apic->base_addr = DEFAULT_BASE_ADDR;
295
296     if (id == 0) { 
297         // boot processor, enabled
298         apic->base_addr_msr.value = 0x0000000000000900LL;
299     } else {
300         // ap processor, enabled
301         apic->base_addr_msr.value = 0x0000000000000800LL;
302     }
303
304     // same base address regardless of ap or main
305     apic->base_addr_msr.value |= ((uint64_t)DEFAULT_BASE_ADDR); 
306
307     PrintDebug(VM_NONE, VCORE_NONE, "apic %u: (init_apic_state): msr=0x%llx\n",id, apic->base_addr_msr.value);
308
309     PrintDebug(VM_NONE, VCORE_NONE, "apic %u: (init_apic_state): Sizeof Interrupt Request Register %d, should be 32\n",
310                id, (uint_t)sizeof(apic->int_req_reg));
311
312     memset(apic->int_req_reg, 0, sizeof(apic->int_req_reg));
313     memset(apic->int_svc_reg, 0, sizeof(apic->int_svc_reg));
314     memset(apic->int_en_reg, 0xff, sizeof(apic->int_en_reg));
315     memset(apic->trig_mode_reg, 0, sizeof(apic->trig_mode_reg));
316
317     apic->eoi = 0x00000000;
318     apic->rem_rd_data = 0x00000000;
319     apic->tmr_init_cnt = 0x00000000;
320     apic->tmr_cur_cnt = 0x00000000;
321     apic->missed_ints = 0;
322
323     // note that it's the *lower* 24 bits that are
324     // reserved, not the upper 24.  
325     apic->lapic_id.val = 0;
326     apic->lapic_id.apic_id = id;
327     
328     apic->ipi_state = INIT_ST;
329
330     // The P6 has 6 LVT entries, so we set the value to (6-1)...
331     apic->apic_ver.val = 0x80050010;
332
333     set_apic_tpr(apic,0x00000000);
334     // note that arbitration priority and processor priority are derived values
335     // and are computed on the fly
336
337     apic->log_dst.val = 0x00000000;
338     apic->dst_fmt.val = 0xffffffff;
339     apic->spurious_int.val = 0x000000ff;
340     apic->err_status.val = 0x00000000;
341     apic->int_cmd.val = 0x0000000000000000LL;
342     apic->tmr_vec_tbl.val = 0x00010000;
343     apic->therm_loc_vec_tbl.val = 0x00010000;
344     apic->perf_ctr_loc_vec_tbl.val = 0x00010000;
345     apic->lint0_vec_tbl.val = 0x00010000;
346     apic->lint1_vec_tbl.val = 0x00010000;
347     apic->err_vec_tbl.val = 0x00010000;
348     apic->tmr_div_cfg.val = 0x00000000;
349     //apic->ext_apic_feature.val = 0x00000007;
350     apic->ext_apic_feature.val = 0x00040007;
351     apic->ext_apic_ctrl.val = 0x00000000;
352     apic->spec_eoi.val = 0x00000000;
353
354
355     INIT_LIST_HEAD(&(apic->irq_queue.entries));
356     v3_lock_init(&(apic->irq_queue.lock));
357     apic->irq_queue.num_entries = 0;
358
359 }
360
361
362
363
364
365 static int read_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t * dst, void * priv_data) {
366     struct apic_dev_state * apic_dev = (struct apic_dev_state *)priv_data;
367     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]);
368
369     PrintDebug(core->vm_info, core, "apic %u: core %u: MSR read\n", apic->lapic_id.val, core->vcpu_id);
370
371     dst->value = apic->base_addr;
372
373     return 0;
374 }
375
376
377 static int write_apic_msr(struct guest_info * core, uint_t msr, v3_msr_t src, void * priv_data) {
378     struct apic_dev_state * apic_dev = (struct apic_dev_state *)priv_data;
379     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]);
380     struct v3_mem_region * old_reg = v3_get_mem_region(core->vm_info, core->vcpu_id, apic->base_addr);
381
382
383     PrintDebug(core->vm_info, core, "apic %u: core %u: MSR write\n", apic->lapic_id.val, core->vcpu_id);
384
385     if (old_reg == NULL) {
386         // uh oh...
387         PrintError(core->vm_info, core, "apic %u: core %u: APIC Base address region does not exit...\n",
388                    apic->lapic_id.val, core->vcpu_id);
389         return -1;
390     }
391     
392
393
394     v3_delete_mem_region(core->vm_info, old_reg);
395
396     apic->base_addr = src.value;
397
398     if (v3_hook_full_mem(core->vm_info, core->vcpu_id, apic->base_addr, 
399                          apic->base_addr + PAGE_SIZE_4KB, 
400                          apic_read, apic_write, apic_dev) == -1) {
401         PrintError(core->vm_info, core, "apic %u: core %u: Could not hook new APIC Base address\n",
402                    apic->lapic_id.val, core->vcpu_id);
403
404         return -1;
405     }
406
407
408     return 0;
409 }
410
411
412
413
414
415 // irq_num is the bit offset into a 256 bit buffer...
416 static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num, 
417                              int (*ack)(struct guest_info * core, uint32_t irq, void * private_data), 
418                              void * private_data) {
419     int major_offset = (irq_num & ~0x00000007) >> 3;
420     int minor_offset = irq_num & 0x00000007;
421     uint8_t * req_location = apic->int_req_reg + major_offset;
422     uint8_t * en_location = apic->int_en_reg + major_offset;
423     uint8_t flag = 0x1 << minor_offset;
424
425
426     PrintDebug(VM_NONE, VCORE_NONE, "apic %u: core %d: Raising APIC IRQ %d\n", apic->lapic_id.val, apic->core->vcpu_id, irq_num);
427
428     if (*req_location & flag) {
429         PrintDebug(VM_NONE, VCORE_NONE, "Interrupt %d  coallescing\n", irq_num);
430         return 0;
431     }
432
433     if (*en_location & flag) {
434         *req_location |= flag;
435         apic->irq_ack_cbs[irq_num].ack = ack;
436         apic->irq_ack_cbs[irq_num].private_data = private_data;
437
438         return 1;
439     } else {
440         PrintDebug(VM_NONE, VCORE_NONE, "apic %u: core %d: Interrupt  not enabled... %.2x\n", 
441                    apic->lapic_id.val, apic->core->vcpu_id, *en_location);
442     }
443
444     return 0;
445 }
446
447
448
449 static int add_apic_irq_entry(struct apic_state * apic, uint32_t irq_num, 
450                               int (*ack)(struct guest_info * core, uint32_t irq, void * private_data),
451                               void * private_data) {
452     unsigned int flags = 0;
453     struct irq_queue_entry * entry = NULL;
454
455     if (irq_num <= 15) {
456         PrintError(VM_NONE, VCORE_NONE, "core %d: Attempting to raise an invalid interrupt: %d\n", 
457                     apic->core->vcpu_id, irq_num);
458         return -1;
459     }
460
461     entry = V3_Malloc(sizeof(struct irq_queue_entry));
462
463     if (entry == NULL) {
464         PrintError(VM_NONE, VCORE_NONE, "Could not allocate irq queue entry\n");
465         return -1;
466     }
467
468     entry->vector = irq_num;
469     entry->ack = ack;
470     entry->private_data = private_data;
471
472     flags = v3_lock_irqsave(apic->irq_queue.lock);
473     
474     list_add_tail(&(entry->list_node), &(apic->irq_queue.entries));
475     apic->irq_queue.num_entries++;
476
477     v3_unlock_irqrestore(apic->irq_queue.lock, flags);
478   
479
480     return 0;
481 }
482
483 static void drain_irq_entries(struct apic_state * apic) {
484
485     while (1) {
486         unsigned int flags = 0;
487         struct irq_queue_entry * entry = NULL;
488     
489         flags = v3_lock_irqsave(apic->irq_queue.lock);
490         
491         if (!list_empty(&(apic->irq_queue.entries))) {
492             struct list_head * q_entry = apic->irq_queue.entries.next;
493             entry = list_entry(q_entry, struct irq_queue_entry, list_node);
494
495             apic->irq_queue.num_entries--;
496             list_del(q_entry);
497         }
498         
499         v3_unlock_irqrestore(apic->irq_queue.lock, flags);
500
501         if (entry == NULL) {
502             break;
503         }
504
505         activate_apic_irq(apic, entry->vector, entry->ack, entry->private_data);
506
507         V3_Free(entry);
508     }
509
510 }
511
512
513
514 static int get_highest_isr(struct apic_state * apic) {
515     int i = 0, j = 0;
516
517     // We iterate backwards to find the highest priority in-service request
518     for (i = 31; i >= 0; i--) {
519         uint8_t  * svc_major = apic->int_svc_reg + i;
520     
521         if ((*svc_major) & 0xff) {
522             for (j = 7; j >= 0; j--) {
523                 uint8_t flag = 0x1 << j;
524                 if ((*svc_major) & flag) {
525                     return ((i * 8) + j);
526                 }
527             }
528         }
529     }
530
531     return -1;
532 }
533  
534
535
536 static int get_highest_irr(struct apic_state * apic) {
537     int i = 0, j = 0;
538
539     // We iterate backwards to find the highest priority enabled requested interrupt
540     for (i = 31; i >= 0; i--) {
541         uint8_t  * req_major = apic->int_req_reg + i;
542         uint8_t  * en_major = apic->int_en_reg + i;
543         
544         if ((*req_major) & 0xff) {
545             for (j = 7; j >= 0; j--) {
546                 uint8_t flag = 0x1 << j;
547                 if ((*req_major & *en_major) & flag) {
548                     return ((i * 8) + j);
549                 }
550             }
551         }
552     }
553
554     return -1;
555 }
556  
557
558 static uint32_t get_isrv(struct apic_state *apic)
559 {
560     int isr = get_highest_isr(apic);
561     
562     if (isr>=0) { 
563         return (uint32_t) isr;
564     } else {
565         return 0;
566     }
567 }
568
569 static uint32_t get_irrv(struct apic_state *apic)
570 {
571     int irr = get_highest_irr(apic);
572     
573     if (irr>=0) { 
574         return (uint32_t) irr;
575     } else {
576         return 0;
577     }
578 }
579
580
581 static uint32_t get_apic_tpr(struct apic_state *apic)
582 {
583     return (uint32_t) (apic->core->ctrl_regs.apic_tpr); // see comment in vmm_ctrl_regs.c for how this works
584
585 }
586
587 static void set_apic_tpr(struct apic_state *apic, uint32_t val)
588 {
589     PrintDebug(VM_NONE, VCORE_NONE, "Set apic_tpr to 0x%x from apic reg path\n",val);
590     apic->core->ctrl_regs.apic_tpr = (uint64_t) val; // see comment in vmm_ctrl_regs.c for how this works
591 }
592
593 static uint32_t get_apic_ppr(struct apic_state *apic)
594 {
595     uint32_t tpr = get_apic_tpr(apic);
596     uint32_t isrv = get_isrv(apic);
597     uint32_t tprlevel, isrlevel;
598     uint32_t ppr;
599
600     tprlevel = (tpr >> 4) & 0xf;
601     isrlevel = (isrv >> 4) & 0xf;
602
603     if (tprlevel>=isrlevel) { 
604         ppr = tpr;  // get class and subclass
605     } else { 
606         ppr = (isrlevel << 4); // get class only
607     }
608     
609     return ppr;
610 }
611
612
613
614 static uint32_t get_apic_apr(struct apic_state *apic)
615 {
616     uint32_t tpr = get_apic_tpr(apic);
617     uint32_t isrv = get_isrv(apic);
618     uint32_t irrv = get_irrv(apic);
619     uint32_t tprlevel, isrlevel, irrlevel;
620
621     tprlevel = (tpr >> 4) & 0xf;
622     isrlevel = (isrv >> 4) & 0xf;
623     irrlevel = (irrv >> 4) & 0xf;
624
625     if (tprlevel >= isrlevel) { 
626         if (tprlevel >= irrlevel) { 
627             return tpr;  // get both class and subclass
628         } else {
629             return irrlevel << 4; // get class only
630         }
631     } else {
632         if (isrlevel >= irrlevel) {
633             return isrlevel << 4; // get class only
634         } else {
635             return irrlevel << 4; // get class only
636         }
637     }
638     
639 }
640
641
642 static int apic_do_eoi(struct guest_info * core, struct apic_state * apic) {
643     int isr_irq = get_highest_isr(apic);
644
645     if (isr_irq != -1) {
646         int major_offset = (isr_irq & ~0x00000007) >> 3;
647         int minor_offset = isr_irq & 0x00000007;
648         uint8_t flag = 0x1 << minor_offset;
649         uint8_t * svc_location = apic->int_svc_reg + major_offset;
650         
651         PrintDebug(core->vm_info, core, "apic %u: core ?: Received APIC EOI for IRQ %d\n", apic->lapic_id.val,isr_irq);
652         
653         *svc_location &= ~flag;
654
655         if (apic->irq_ack_cbs[isr_irq].ack) {
656             apic->irq_ack_cbs[isr_irq].ack(core, isr_irq, apic->irq_ack_cbs[isr_irq].private_data);
657         }
658
659 #ifdef V3_CONFIG_CRAY_XT
660         
661         if ((isr_irq == 238) || 
662             (isr_irq == 239)) {
663             PrintDebug(core->vm_info, core, "apic %u: core ?: Acking IRQ %d\n", apic->lapic_id.val,isr_irq);
664         }
665         
666         if (isr_irq == 238) {
667             V3_ACK_IRQ(238);
668         }
669 #endif
670     } else {
671         //PrintError(core->vm_info, core, "apic %u: core ?: Spurious EOI...\n",apic->lapic_id.val);
672     }
673         
674     return 0;
675 }
676  
677
678 static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_type) {
679     uint32_t vec_num = 0;
680     uint32_t del_mode = 0;
681     int masked = 0;
682
683
684     switch (int_type) {
685         case APIC_TMR_INT:
686             vec_num = apic->tmr_vec_tbl.vec;
687             del_mode = IPI_FIXED;
688             masked = apic->tmr_vec_tbl.mask;
689             break;
690         case APIC_THERM_INT:
691             vec_num = apic->therm_loc_vec_tbl.vec;
692             del_mode = apic->therm_loc_vec_tbl.msg_type;
693             masked = apic->therm_loc_vec_tbl.mask;
694             break;
695         case APIC_PERF_INT:
696             vec_num = apic->perf_ctr_loc_vec_tbl.vec;
697             del_mode = apic->perf_ctr_loc_vec_tbl.msg_type;
698             masked = apic->perf_ctr_loc_vec_tbl.mask;
699             break;
700         case APIC_LINT0_INT:
701             vec_num = apic->lint0_vec_tbl.vec;
702             del_mode = apic->lint0_vec_tbl.msg_type;
703             masked = apic->lint0_vec_tbl.mask;
704             break;
705         case APIC_LINT1_INT:
706             vec_num = apic->lint1_vec_tbl.vec;
707             del_mode = apic->lint1_vec_tbl.msg_type;
708             masked = apic->lint1_vec_tbl.mask;
709             break;
710         case APIC_ERR_INT:
711             vec_num = apic->err_vec_tbl.vec;
712             del_mode = IPI_FIXED;
713             masked = apic->err_vec_tbl.mask;
714             break;
715         default:
716             PrintError(VM_NONE, VCORE_NONE, "apic %u: core ?: Invalid APIC interrupt type\n", apic->lapic_id.val);
717             return -1;
718     }
719
720     // interrupt is masked, don't send
721     if (masked == 1) {
722         PrintDebug(VM_NONE, VCORE_NONE, "apic %u: core ?: Inerrupt is masked\n", apic->lapic_id.val);
723         return 0;
724     }
725
726     if (del_mode == IPI_FIXED) {
727         //PrintDebug(VM_NONE, VCORE_NONE, "Activating internal APIC IRQ %d\n", vec_num);
728         return add_apic_irq_entry(apic, vec_num, NULL, NULL);
729     } else {
730         PrintError(VM_NONE, VCORE_NONE, "apic %u: core ?: Unhandled Delivery Mode\n", apic->lapic_id.val);
731         return -1;
732     }
733 }
734
735
736
737 static inline int should_deliver_cluster_ipi(struct apic_dev_state * apic_dev,
738                                              struct guest_info * dst_core, 
739                                              struct apic_state * dst_apic, uint8_t mda) {
740
741     int ret = 0;
742
743
744     if  ( ((mda & 0xf0) == (dst_apic->log_dst.dst_log_id & 0xf0)) &&  /* (I am in the cluster and */
745           ((mda & 0x0f) & (dst_apic->log_dst.dst_log_id & 0x0f)) ) {  /*  I am in the set)        */
746         ret = 1;
747     } else {
748         ret = 0;
749     }
750
751
752     if (ret == 1) {
753         PrintDebug(VM_NONE, VCORE_NONE, "apic %u core %u: accepting clustered IRQ (mda 0x%x == log_dst 0x%x)\n",
754                    dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
755                    dst_apic->log_dst.dst_log_id);
756     } else {
757         PrintDebug(VM_NONE, VCORE_NONE, "apic %u core %u: rejecting clustered IRQ (mda 0x%x != log_dst 0x%x)\n",
758                    dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
759                    dst_apic->log_dst.dst_log_id);
760     }
761
762     return ret;
763
764 }
765
766 static inline int should_deliver_flat_ipi(struct apic_dev_state * apic_dev,
767                                           struct guest_info * dst_core,
768                                           struct apic_state * dst_apic, uint8_t mda) {
769
770     int ret = 0;
771
772
773     if ((dst_apic->log_dst.dst_log_id & mda) != 0) {  // I am in the set 
774         ret = 1;
775     } else {
776         ret = 0;
777     }
778
779
780     if (ret == 1) {
781         PrintDebug(VM_NONE, VCORE_NONE, "apic %u core %u: accepting flat IRQ (mda 0x%x == log_dst 0x%x)\n",
782                    dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
783                    dst_apic->log_dst.dst_log_id);
784     } else {
785         PrintDebug(VM_NONE, VCORE_NONE, "apic %u core %u: rejecting flat IRQ (mda 0x%x != log_dst 0x%x)\n",
786                    dst_apic->lapic_id.val, dst_core->vcpu_id, mda, 
787                    dst_apic->log_dst.dst_log_id);
788     }
789
790
791     return ret;
792 }
793
794
795
796 static int should_deliver_ipi(struct apic_dev_state * apic_dev, 
797                               struct guest_info * dst_core, 
798                               struct apic_state * dst_apic, uint8_t mda) {
799     addr_t flags = 0;
800     int ret = 0;
801
802     flags = v3_lock_irqsave(apic_dev->state_lock);
803
804     if (dst_apic->dst_fmt.model == 0xf) {
805
806         if (mda == 0xff) {
807             /* always deliver broadcast */
808             ret = 1;
809         } else {
810             ret = should_deliver_flat_ipi(apic_dev, dst_core, dst_apic, mda);
811         }
812     } else if (dst_apic->dst_fmt.model == 0x0) {
813
814         if (mda == 0xff) {
815             /*  always deliver broadcast */
816             ret = 1;
817         } else {
818             ret = should_deliver_cluster_ipi(apic_dev, dst_core, dst_apic, mda);
819         }
820
821     } else {
822         ret = -1;
823     }
824     
825     v3_unlock_irqrestore(apic_dev->state_lock, flags);
826
827
828     if (ret == -1) {
829         PrintError(VM_NONE, VCORE_NONE, "apic %u core %u: invalid destination format register value 0x%x for logical mode delivery.\n", 
830                    dst_apic->lapic_id.val, dst_core->vcpu_id, dst_apic->dst_fmt.model);
831     }
832
833     return ret;
834 }
835
836
837
838
839 // Only the src_apic pointer is used
840 static int deliver_ipi(struct apic_state * src_apic, 
841                        struct apic_state * dst_apic, 
842                        struct v3_gen_ipi * ipi) {
843
844
845     struct guest_info * dst_core = dst_apic->core;
846
847
848     switch (ipi->mode) {
849
850         case IPI_FIXED:  
851         case IPI_LOWEST_PRIO: {
852             // lowest priority - 
853             // caller needs to have decided which apic to deliver to!
854
855             PrintDebug(VM_NONE, VCORE_NONE, "delivering IRQ %d to core %u\n", ipi->vector, dst_core->vcpu_id); 
856
857             add_apic_irq_entry(dst_apic, ipi->vector, ipi->ack, ipi->private_data);
858             
859             if (dst_apic != src_apic) { 
860                 PrintDebug(VM_NONE, VCORE_NONE, " non-local core with new interrupt, forcing it to exit now\n"); 
861                 v3_interrupt_cpu(dst_core->vm_info, dst_core->pcpu_id, 0);
862             }
863
864             break;
865         }
866         case IPI_INIT: { 
867
868             PrintDebug(VM_NONE, VCORE_NONE, " INIT delivery to core %u\n", dst_core->vcpu_id);
869
870             if (is_apic_bsp(dst_apic)) {
871                 PrintError(VM_NONE, VCORE_NONE, "Attempted to INIT BSP CPU. Ignoring since I have no idea what the hell to do...\n");
872                 break;
873             }
874
875
876             if (dst_apic->ipi_state != INIT_ST) { 
877                 v3_raise_barrier(dst_core->vm_info, src_apic->core);
878                 dst_core->core_run_state = CORE_STOPPED;
879                 dst_apic->ipi_state = INIT_ST;
880                 v3_lower_barrier(dst_core->vm_info);
881
882             }
883
884             // We transition the target core to SIPI state
885             dst_apic->ipi_state = SIPI;  // note: locking should not be needed here
886
887             // That should be it since the target core should be
888             // waiting in host on this transition
889             // either it's on another core or on a different preemptive thread
890             // in both cases, it will quickly notice this transition 
891             // in particular, we should not need to force an exit here
892
893             PrintDebug(VM_NONE, VCORE_NONE, " INIT delivery done\n");
894
895             break;                                                      
896         }
897         case IPI_SIPI: { 
898
899             // Sanity check
900             if (dst_apic->ipi_state != SIPI) { 
901                 PrintError(VM_NONE, VCORE_NONE, " core %u is not in SIPI state (mode = %d), ignored!\n",
902                            dst_core->vcpu_id, dst_apic->ipi_state);
903                 break;
904             }
905
906             v3_reset_vm_core(dst_core, ipi->vector);
907
908             PrintDebug(VM_NONE, VCORE_NONE, " SIPI delivery (0x%x -> 0x%x:0x0) to core %u\n",
909                        ipi->vector, dst_core->segments.cs.selector, dst_core->vcpu_id);
910             // Maybe need to adjust the APIC?
911             
912             // We transition the target core to SIPI state
913             dst_core->core_run_state = CORE_RUNNING;  // note: locking should not be needed here
914             dst_apic->ipi_state = STARTED;
915             
916             // As with INIT, we should not need to do anything else
917             
918             PrintDebug(VM_NONE, VCORE_NONE, " SIPI delivery done\n");
919             
920             break;                                                      
921         }
922
923         case IPI_EXTINT: // EXTINT
924             /* Two possible things to do here: 
925              * 1. Ignore the IPI and assume the 8259a (PIC) will handle it
926              * 2. Add 32 to the vector and inject it...
927              * We probably just want to do 1 here, and assume the raise_irq() will hit the 8259a.
928              */
929             return 0;
930
931         case IPI_SMI: 
932         case IPI_RES1: // reserved                                              
933         case IPI_NMI:
934         default:
935             PrintError(VM_NONE, VCORE_NONE, "IPI %d delivery is unsupported\n", ipi->mode); 
936             return -1;
937     }
938     
939     return 0;
940     
941 }
942
943 static struct apic_state * find_physical_apic(struct apic_dev_state * apic_dev, uint32_t dst_idx) {
944     struct apic_state * dst_apic = NULL;
945     addr_t flags;
946     int i;
947
948     flags = v3_lock_irqsave(apic_dev->state_lock);
949
950     if ( (dst_idx > 0) && (dst_idx < apic_dev->num_apics) ) { 
951         // see if it simply is the core id
952         if (apic_dev->apics[dst_idx].lapic_id.apic_id == dst_idx) { 
953              dst_apic = &(apic_dev->apics[dst_idx]);
954         }
955     }
956
957     for (i = 0; i < apic_dev->num_apics; i++) { 
958         if (apic_dev->apics[i].lapic_id.apic_id == dst_idx) { 
959             dst_apic =  &(apic_dev->apics[i]);
960         }
961     }
962
963     v3_unlock_irqrestore(apic_dev->state_lock, flags);
964
965     return dst_apic;
966
967 }
968
969
970 static int route_ipi(struct apic_dev_state * apic_dev,
971                      struct apic_state * src_apic, 
972                      struct v3_gen_ipi * ipi) {
973     struct apic_state * dest_apic = NULL;
974
975
976     PrintDebug(VM_NONE, VCORE_NONE, "apic: IPI %s %u from apic %p to %s %s %u\n",
977                deliverymode_str[ipi->mode], 
978                ipi->vector, 
979                src_apic,               
980                (ipi->logical == 0) ? "(physical)" : "(logical)", 
981                shorthand_str[ipi->dst_shorthand], 
982                ipi->dst);
983
984
985     switch (ipi->dst_shorthand) {
986
987         case APIC_SHORTHAND_NONE:  // no shorthand
988             if (ipi->logical == APIC_DEST_PHYSICAL) { 
989
990                 dest_apic = find_physical_apic(apic_dev, ipi->dst);
991                 
992                 if (dest_apic == NULL) { 
993                     PrintError(VM_NONE, VCORE_NONE, "apic: Attempted send to unregistered apic id=%u\n", ipi->dst);
994                     return -1;
995                 }
996
997                 if (deliver_ipi(src_apic, dest_apic, ipi) == -1) {
998                     PrintError(VM_NONE, VCORE_NONE, "apic: Could not deliver IPI\n");
999                     return -1;
1000                 }
1001
1002
1003                 PrintDebug(VM_NONE, VCORE_NONE, "apic: done\n");
1004
1005             } else if (ipi->logical == APIC_DEST_LOGICAL) {
1006                 
1007                 if (ipi->mode != IPI_LOWEST_PRIO) { 
1008                     int i;
1009                     uint8_t mda = ipi->dst;
1010
1011                     // logical, but not lowest priority
1012                     // we immediately trigger
1013                     // fixed, smi, reserved, nmi, init, sipi, etc
1014
1015                     
1016                     for (i = 0; i < apic_dev->num_apics; i++) { 
1017                         int del_flag = 0;
1018                         
1019                         dest_apic = &(apic_dev->apics[i]);
1020                         
1021                         del_flag = should_deliver_ipi(apic_dev, dest_apic->core, dest_apic, mda);
1022                         
1023                         if (del_flag == -1) {
1024
1025                             PrintError(VM_NONE, VCORE_NONE, "apic: Error checking delivery mode\n");
1026                             return -1;
1027                         } else if (del_flag == 1) {
1028
1029                             if (deliver_ipi(src_apic, dest_apic, ipi) == -1) {
1030                                 PrintError(VM_NONE, VCORE_NONE, "apic: Error: Could not deliver IPI\n");
1031                                 return -1;
1032                             }
1033                         }
1034                     }
1035                 } else {  // APIC_LOWEST_DELIVERY
1036                     struct apic_state * cur_best_apic = NULL;
1037                     uint32_t cur_best_apr;
1038                     uint8_t mda = ipi->dst;
1039                     int i;
1040
1041                     // logical, lowest priority
1042
1043                     for (i = 0; i < apic_dev->num_apics; i++) { 
1044                         int del_flag = 0;
1045
1046                         dest_apic = &(apic_dev->apics[i]);
1047                         
1048                         del_flag = should_deliver_ipi(apic_dev, dest_apic->core, dest_apic, mda);
1049                         
1050                         if (del_flag == -1) {
1051                             PrintError(VM_NONE, VCORE_NONE, "apic: Error checking delivery mode\n");
1052
1053                             return -1;
1054                         } else if (del_flag == 1) {
1055                             // update priority for lowest priority scan
1056                             addr_t flags = 0;
1057
1058                             flags = v3_lock_irqsave(apic_dev->state_lock);
1059
1060                             if (cur_best_apic == 0) {
1061                                 cur_best_apic = dest_apic;  
1062                                 cur_best_apr = get_apic_apr(dest_apic) & 0xf0;
1063                             } else {
1064                                 uint32_t dest_apr = get_apic_apr(dest_apic) & 0xf0;
1065                                 if (dest_apr < cur_best_apr) {
1066                                     cur_best_apic = dest_apic;
1067                                     cur_best_apr = dest_apr;
1068                                 }
1069                             } 
1070
1071                             v3_unlock_irqrestore(apic_dev->state_lock, flags);
1072
1073                         }
1074                     }
1075
1076                     // now we will deliver to the best one if it exists
1077                     if (!cur_best_apic) { 
1078                         PrintDebug(VM_NONE, VCORE_NONE, "apic: lowest priority deliver, but no destinations!\n");
1079                     } else {
1080                         if (deliver_ipi(src_apic, cur_best_apic, ipi) == -1) {
1081                             PrintError(VM_NONE, VCORE_NONE, "apic: Error: Could not deliver IPI\n");
1082                             return -1;
1083                         }
1084                         //V3_Print(VM_NONE, VCORE_NONE, "apic: logical, lowest priority delivery to apic %u\n",cur_best_apic->lapic_id.val);
1085                     }
1086                 }
1087             }
1088
1089             break;
1090             
1091         case APIC_SHORTHAND_SELF:  // self
1092
1093             if (src_apic == NULL) {    /* this is not an apic, but it's trying to send to itself??? */
1094                 PrintError(VM_NONE, VCORE_NONE, "apic: Sending IPI to self from generic IPI sender\n");
1095                 break;
1096             }
1097
1098
1099
1100             if (ipi->logical == APIC_DEST_PHYSICAL)  {  /* physical delivery */
1101                 if (deliver_ipi(src_apic, src_apic, ipi) == -1) {
1102                     PrintError(VM_NONE, VCORE_NONE, "apic: Could not deliver IPI to self (physical)\n");
1103                     return -1;
1104                 }
1105             } else if (ipi->logical == APIC_DEST_LOGICAL) {  /* logical delivery */
1106                 PrintError(VM_NONE, VCORE_NONE, "apic: use of logical delivery in self (untested)\n");
1107
1108                 if (deliver_ipi(src_apic, src_apic, ipi) == -1) {
1109                     PrintError(VM_NONE, VCORE_NONE, "apic: Could not deliver IPI to self (logical)\n");
1110                     return -1;
1111                 }
1112             }
1113
1114             break;
1115             
1116         case APIC_SHORTHAND_ALL: 
1117         case APIC_SHORTHAND_ALL_BUT_ME: { /* all and all-but-me */
1118             /* assuming that logical verus physical doesn't matter
1119                although it is odd that both are used */
1120             int i;
1121
1122             for (i = 0; i < apic_dev->num_apics; i++) { 
1123                 dest_apic = &(apic_dev->apics[i]);
1124                 
1125                 if ((dest_apic != src_apic) || (ipi->dst_shorthand == APIC_SHORTHAND_ALL)) { 
1126                     if (deliver_ipi(src_apic, dest_apic, ipi) == -1) {
1127                         PrintError(VM_NONE, VCORE_NONE, "apic: Error: Could not deliver IPI\n");
1128                         return -1;
1129                     }
1130                 }
1131             }
1132
1133             break;
1134         }
1135         default:
1136             PrintError(VM_NONE, VCORE_NONE, "apic: Error routing IPI, invalid Mode (%d)\n", ipi->dst_shorthand);
1137             return -1;
1138     }
1139  
1140     return 0;
1141 }
1142
1143
1144 // External function, expected to acquire lock on apic
1145 static int apic_read(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
1146     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1147     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]);
1148     addr_t reg_addr  = guest_addr - apic->base_addr;
1149     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
1150     uint32_t val = 0;
1151
1152
1153     PrintDebug(core->vm_info, core, "apic %u: core %u: at %p: Read apic address space (%p)\n",
1154                apic->lapic_id.val, core->vcpu_id, apic, (void *)guest_addr);
1155
1156     if (msr->apic_enable == 0) {
1157         PrintError(core->vm_info, core, "apic %u: core %u: Read from APIC address space with disabled APIC, apic msr=0x%llx\n",
1158                    apic->lapic_id.val, core->vcpu_id, apic->base_addr_msr.value);
1159         return -1;
1160     }
1161
1162
1163     /* Because "May not be supported" doesn't matter to Linux developers... */
1164     /*   if (length != 4) { */
1165     /*     PrintError(core->vm_info, core, "Invalid apic read length (%d)\n", length); */
1166     /*     return -1; */
1167     /*   } */
1168
1169     switch (reg_addr & ~0x3) {
1170         case EOI_OFFSET:
1171             // Well, only an idiot would read from a architectural write only register
1172             // Oh, Hello Linux.
1173             //    PrintError(core->vm_info, core, "Attempting to read from write only register\n");
1174             //    return -1;
1175             break;
1176
1177             // data registers
1178         case APIC_ID_OFFSET:
1179             val = apic->lapic_id.val;
1180             break;
1181         case APIC_VERSION_OFFSET:
1182             val = apic->apic_ver.val;
1183             break;
1184         case TPR_OFFSET:
1185             val = get_apic_tpr(apic);
1186             break;
1187         case APR_OFFSET:
1188             val = get_apic_apr(apic);
1189             break;
1190         case PPR_OFFSET:
1191             val = get_apic_ppr(apic);
1192             break;
1193         case REMOTE_READ_OFFSET:
1194             val = apic->rem_rd_data;
1195             break;
1196         case LDR_OFFSET:
1197             val = apic->log_dst.val;
1198             break;
1199         case DFR_OFFSET:
1200             val = apic->dst_fmt.val;
1201             break;
1202         case SPURIOUS_INT_VEC_OFFSET:
1203             val = apic->spurious_int.val;
1204             break;
1205         case ESR_OFFSET:
1206             val = apic->err_status.val;
1207             break;
1208         case TMR_LOC_VEC_TBL_OFFSET:
1209             val = apic->tmr_vec_tbl.val;
1210             break;
1211         case LINT0_VEC_TBL_OFFSET:
1212             val = apic->lint0_vec_tbl.val;
1213             break;
1214         case LINT1_VEC_TBL_OFFSET:
1215             val = apic->lint1_vec_tbl.val;
1216             break;
1217         case ERR_VEC_TBL_OFFSET:
1218             val = apic->err_vec_tbl.val;
1219             break;
1220         case TMR_INIT_CNT_OFFSET:
1221             val = apic->tmr_init_cnt;
1222             break;
1223         case TMR_DIV_CFG_OFFSET:
1224             val = apic->tmr_div_cfg.val;
1225             break;
1226
1227         case IER_OFFSET0:
1228             val = *(uint32_t *)(apic->int_en_reg);
1229             break;
1230         case IER_OFFSET1:
1231             val = *(uint32_t *)(apic->int_en_reg + 4);
1232             break;
1233         case IER_OFFSET2:
1234             val = *(uint32_t *)(apic->int_en_reg + 8);
1235             break;
1236         case IER_OFFSET3:
1237             val = *(uint32_t *)(apic->int_en_reg + 12);
1238             break;
1239         case IER_OFFSET4:
1240             val = *(uint32_t *)(apic->int_en_reg + 16);
1241             break;
1242         case IER_OFFSET5:
1243             val = *(uint32_t *)(apic->int_en_reg + 20);
1244             break;
1245         case IER_OFFSET6:
1246             val = *(uint32_t *)(apic->int_en_reg + 24);
1247             break;
1248         case IER_OFFSET7:
1249             val = *(uint32_t *)(apic->int_en_reg + 28);
1250             break;
1251
1252         case ISR_OFFSET0:
1253             val = *(uint32_t *)(apic->int_svc_reg);
1254             break;
1255         case ISR_OFFSET1:
1256             val = *(uint32_t *)(apic->int_svc_reg + 4);
1257             break;
1258         case ISR_OFFSET2:
1259             val = *(uint32_t *)(apic->int_svc_reg + 8);
1260             break;
1261         case ISR_OFFSET3:
1262             val = *(uint32_t *)(apic->int_svc_reg + 12);
1263             break;
1264         case ISR_OFFSET4:
1265             val = *(uint32_t *)(apic->int_svc_reg + 16);
1266             break;
1267         case ISR_OFFSET5:
1268             val = *(uint32_t *)(apic->int_svc_reg + 20);
1269             break;
1270         case ISR_OFFSET6:
1271             val = *(uint32_t *)(apic->int_svc_reg + 24);
1272             break;
1273         case ISR_OFFSET7:
1274             val = *(uint32_t *)(apic->int_svc_reg + 28);
1275             break;
1276    
1277         case TRIG_OFFSET0:
1278             val = *(uint32_t *)(apic->trig_mode_reg);
1279             break;
1280         case TRIG_OFFSET1:
1281             val = *(uint32_t *)(apic->trig_mode_reg + 4);
1282             break;
1283         case TRIG_OFFSET2:
1284             val = *(uint32_t *)(apic->trig_mode_reg + 8);
1285             break;
1286         case TRIG_OFFSET3:
1287             val = *(uint32_t *)(apic->trig_mode_reg + 12);
1288             break;
1289         case TRIG_OFFSET4:
1290             val = *(uint32_t *)(apic->trig_mode_reg + 16);
1291             break;
1292         case TRIG_OFFSET5:
1293             val = *(uint32_t *)(apic->trig_mode_reg + 20);
1294             break;
1295         case TRIG_OFFSET6:
1296             val = *(uint32_t *)(apic->trig_mode_reg + 24);
1297             break;
1298         case TRIG_OFFSET7:
1299             val = *(uint32_t *)(apic->trig_mode_reg + 28);
1300             break;
1301
1302         case IRR_OFFSET0:
1303             val = *(uint32_t *)(apic->int_req_reg);
1304             break;
1305         case IRR_OFFSET1:
1306             val = *(uint32_t *)(apic->int_req_reg + 4);
1307             break;
1308         case IRR_OFFSET2:
1309             val = *(uint32_t *)(apic->int_req_reg + 8);
1310             break;
1311         case IRR_OFFSET3:
1312             val = *(uint32_t *)(apic->int_req_reg + 12);
1313             break;
1314         case IRR_OFFSET4:
1315             val = *(uint32_t *)(apic->int_req_reg + 16);
1316             break;
1317         case IRR_OFFSET5:
1318             val = *(uint32_t *)(apic->int_req_reg + 20);
1319             break;
1320         case IRR_OFFSET6:
1321             val = *(uint32_t *)(apic->int_req_reg + 24);
1322             break;
1323         case IRR_OFFSET7:
1324             val = *(uint32_t *)(apic->int_req_reg + 28);
1325             break;
1326         case TMR_CUR_CNT_OFFSET:
1327             val = apic->tmr_cur_cnt;
1328             break;
1329
1330             // We are not going to implement these....
1331         case THERM_LOC_VEC_TBL_OFFSET:
1332             val = apic->therm_loc_vec_tbl.val;
1333             break;
1334         case PERF_CTR_LOC_VEC_TBL_OFFSET:
1335             val = apic->perf_ctr_loc_vec_tbl.val;
1336             break;
1337
1338  
1339
1340             // handled registers
1341         case INT_CMD_LO_OFFSET:    
1342             val = apic->int_cmd.lo;
1343             break;
1344         case INT_CMD_HI_OFFSET:
1345             val = apic->int_cmd.hi;
1346             break;
1347
1348             // handle current timer count
1349
1350             // Unhandled Registers
1351         case EXT_INT_LOC_VEC_TBL_OFFSET0:
1352             val = apic->ext_intr_vec_tbl[0].val;
1353             break;
1354         case EXT_INT_LOC_VEC_TBL_OFFSET1:
1355             val = apic->ext_intr_vec_tbl[1].val;
1356             break;
1357         case EXT_INT_LOC_VEC_TBL_OFFSET2:
1358             val = apic->ext_intr_vec_tbl[2].val;
1359             break;
1360         case EXT_INT_LOC_VEC_TBL_OFFSET3:
1361             val = apic->ext_intr_vec_tbl[3].val;
1362             break;
1363     
1364
1365         case EXT_APIC_FEATURE_OFFSET:
1366         case EXT_APIC_CMD_OFFSET:
1367         case SEOI_OFFSET:
1368
1369         default:
1370             PrintError(core->vm_info, core, "apic %u: core %u: Read from Unhandled APIC Register: %x (getting zero)\n", 
1371                        apic->lapic_id.val, core->vcpu_id, (uint32_t)reg_addr);
1372             return -1;
1373     }
1374
1375
1376     if (length == 1) {
1377         uint_t byte_addr = reg_addr & 0x3;
1378         uint8_t * val_ptr = (uint8_t *)dst;
1379     
1380         *val_ptr = *(((uint8_t *)&val) + byte_addr);
1381
1382     } else if ((length == 2) && 
1383                ((reg_addr & 0x3) != 0x3)) {
1384         uint_t byte_addr = reg_addr & 0x3;
1385         uint16_t * val_ptr = (uint16_t *)dst;
1386         *val_ptr = *(((uint16_t *)&val) + byte_addr);
1387
1388     } else if (length == 4) {
1389         uint32_t * val_ptr = (uint32_t *)dst;
1390         *val_ptr = val;
1391
1392     } else {
1393         PrintError(core->vm_info, core, "apic %u: core %u: Invalid apic read length (%d)\n", 
1394                    apic->lapic_id.val, core->vcpu_id, length);
1395         return -1;
1396     }
1397
1398     PrintDebug(core->vm_info, core, "apic %u: core %u: Read finished (val=%x)\n", 
1399                apic->lapic_id.val, core->vcpu_id, *(uint32_t *)dst);
1400
1401     return length;
1402 }
1403
1404
1405 /**
1406  *
1407  */
1408 static int apic_write(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data) {
1409     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1410     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1411     addr_t reg_addr  = guest_addr - apic->base_addr;
1412     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
1413     uint32_t op_val = *(uint32_t *)src;
1414     addr_t flags = 0;
1415
1416     PrintDebug(core->vm_info, core, "apic %u: core %u: at %p and priv_data is at %p\n",
1417                apic->lapic_id.val, core->vcpu_id, apic, priv_data);
1418
1419     PrintDebug(core->vm_info, core, "apic %u: core %u: write to address space (%p) (val=%x)\n", 
1420                apic->lapic_id.val, core->vcpu_id, (void *)guest_addr, *(uint32_t *)src);
1421
1422     if (msr->apic_enable == 0) {
1423         PrintError(core->vm_info, core, "apic %u: core %u: Write to APIC address space with disabled APIC, apic msr=0x%llx\n",
1424                    apic->lapic_id.val, core->vcpu_id, apic->base_addr_msr.value);
1425         return -1;
1426     }
1427
1428
1429     if (length != 4) {
1430         PrintError(core->vm_info, core, "apic %u: core %u: Invalid apic write length (%d)\n", 
1431                    apic->lapic_id.val, length, core->vcpu_id);
1432         return -1;
1433     }
1434
1435     switch (reg_addr) {
1436         case REMOTE_READ_OFFSET:
1437         case APIC_VERSION_OFFSET:
1438         case APR_OFFSET:
1439         case IRR_OFFSET0:
1440         case IRR_OFFSET1:
1441         case IRR_OFFSET2:
1442         case IRR_OFFSET3:
1443         case IRR_OFFSET4:
1444         case IRR_OFFSET5:
1445         case IRR_OFFSET6:
1446         case IRR_OFFSET7:
1447         case ISR_OFFSET0:
1448         case ISR_OFFSET1:
1449         case ISR_OFFSET2:
1450         case ISR_OFFSET3:
1451         case ISR_OFFSET4:
1452         case ISR_OFFSET5:
1453         case ISR_OFFSET6:
1454         case ISR_OFFSET7:
1455         case TRIG_OFFSET0:
1456         case TRIG_OFFSET1:
1457         case TRIG_OFFSET2:
1458         case TRIG_OFFSET3:
1459         case TRIG_OFFSET4:
1460         case TRIG_OFFSET5:
1461         case TRIG_OFFSET6:
1462         case TRIG_OFFSET7:
1463         case PPR_OFFSET:
1464         case EXT_APIC_FEATURE_OFFSET:
1465
1466             PrintError(core->vm_info, core, "apic %u: core %u: Attempting to write to read only register %p (error)\n", 
1467                        apic->lapic_id.val, core->vcpu_id, (void *)reg_addr);
1468
1469             break;
1470
1471             // Data registers
1472         case APIC_ID_OFFSET:
1473             //V3_Print(core->vm_info, core, "apic %u: core %u: my id is being changed to %u\n", 
1474             //       apic->lapic_id.val, core->vcpu_id, op_val);
1475
1476             apic->lapic_id.val = op_val;
1477             break;
1478         case TPR_OFFSET:
1479             set_apic_tpr(apic,op_val);
1480             break;
1481         case LDR_OFFSET:
1482             PrintDebug(core->vm_info, core, "apic %u: core %u: setting log_dst.val to 0x%x\n",
1483                        apic->lapic_id.val, core->vcpu_id, op_val);
1484             flags = v3_lock_irqsave(apic_dev->state_lock);
1485             apic->log_dst.val = op_val;
1486             v3_unlock_irqrestore(apic_dev->state_lock, flags);
1487             break;
1488         case DFR_OFFSET:
1489             flags = v3_lock_irqsave(apic_dev->state_lock);
1490             apic->dst_fmt.val = op_val;
1491             v3_unlock_irqrestore(apic_dev->state_lock, flags);
1492             break;
1493         case SPURIOUS_INT_VEC_OFFSET:
1494             apic->spurious_int.val = op_val;
1495             break;
1496         case ESR_OFFSET:
1497             apic->err_status.val = op_val;
1498             break;
1499         case TMR_LOC_VEC_TBL_OFFSET:
1500             apic->tmr_vec_tbl.val = op_val;
1501             break;
1502         case THERM_LOC_VEC_TBL_OFFSET:
1503             apic->therm_loc_vec_tbl.val = op_val;
1504             break;
1505         case PERF_CTR_LOC_VEC_TBL_OFFSET:
1506             apic->perf_ctr_loc_vec_tbl.val = op_val;
1507             break;
1508         case LINT0_VEC_TBL_OFFSET:
1509             apic->lint0_vec_tbl.val = op_val;
1510             break;
1511         case LINT1_VEC_TBL_OFFSET:
1512             apic->lint1_vec_tbl.val = op_val;
1513             break;
1514         case ERR_VEC_TBL_OFFSET:
1515             apic->err_vec_tbl.val = op_val;
1516             break;
1517         case TMR_INIT_CNT_OFFSET:
1518             apic->tmr_init_cnt = op_val;
1519             apic->tmr_cur_cnt = op_val;
1520             break;
1521         case TMR_CUR_CNT_OFFSET:
1522             apic->tmr_cur_cnt = op_val;
1523             break;
1524         case TMR_DIV_CFG_OFFSET:
1525             PrintDebug(core->vm_info, core, "apic %u: core %u: setting tmr_div_cfg to 0x%x\n",
1526                        apic->lapic_id.val, core->vcpu_id, op_val);
1527             apic->tmr_div_cfg.val = op_val;
1528             break;
1529
1530
1531             // Enable mask (256 bits)
1532         case IER_OFFSET0:
1533             *(uint32_t *)(apic->int_en_reg) = op_val;
1534             break;
1535         case IER_OFFSET1:
1536             *(uint32_t *)(apic->int_en_reg + 4) = op_val;
1537             break;
1538         case IER_OFFSET2:
1539             *(uint32_t *)(apic->int_en_reg + 8) = op_val;
1540             break;
1541         case IER_OFFSET3:
1542             *(uint32_t *)(apic->int_en_reg + 12) = op_val;
1543             break;
1544         case IER_OFFSET4:
1545             *(uint32_t *)(apic->int_en_reg + 16) = op_val;
1546             break;
1547         case IER_OFFSET5:
1548             *(uint32_t *)(apic->int_en_reg + 20) = op_val;
1549             break;
1550         case IER_OFFSET6:
1551             *(uint32_t *)(apic->int_en_reg + 24) = op_val;
1552             break;
1553         case IER_OFFSET7:
1554             *(uint32_t *)(apic->int_en_reg + 28) = op_val;
1555             break;
1556
1557         case EXT_INT_LOC_VEC_TBL_OFFSET0:
1558             apic->ext_intr_vec_tbl[0].val = op_val;
1559             break;
1560         case EXT_INT_LOC_VEC_TBL_OFFSET1:
1561             apic->ext_intr_vec_tbl[1].val = op_val;
1562             break;
1563         case EXT_INT_LOC_VEC_TBL_OFFSET2:
1564             apic->ext_intr_vec_tbl[2].val = op_val;
1565             break;
1566         case EXT_INT_LOC_VEC_TBL_OFFSET3:
1567             apic->ext_intr_vec_tbl[3].val = op_val;
1568             break;
1569
1570
1571             // Action Registers
1572         case EOI_OFFSET:
1573             // do eoi 
1574             apic_do_eoi(core, apic);
1575             break;
1576
1577         case INT_CMD_LO_OFFSET: {
1578             // execute command 
1579
1580             struct v3_gen_ipi tmp_ipi;
1581
1582             apic->int_cmd.lo = op_val;
1583
1584             tmp_ipi.vector = apic->int_cmd.vec;
1585             tmp_ipi.mode = apic->int_cmd.del_mode;
1586             tmp_ipi.logical = apic->int_cmd.dst_mode;
1587             tmp_ipi.trigger_mode = apic->int_cmd.trig_mode;
1588             tmp_ipi.dst_shorthand = apic->int_cmd.dst_shorthand;
1589             tmp_ipi.dst = apic->int_cmd.dst;
1590                 
1591             tmp_ipi.ack = NULL;
1592             tmp_ipi.private_data = NULL;
1593             
1594
1595             //      V3_Print(core->vm_info, core, "apic %u: core %u: sending cmd 0x%llx to apic %u\n", 
1596             //       apic->lapic_id.val, core->vcpu_id,
1597             //       apic->int_cmd.val, apic->int_cmd.dst);
1598
1599             if (route_ipi(apic_dev, apic, &tmp_ipi) == -1) { 
1600                 PrintError(core->vm_info, core, "IPI Routing failure\n");
1601                 return -1;
1602             }
1603
1604             break;
1605         }
1606         case INT_CMD_HI_OFFSET: {
1607             apic->int_cmd.hi = op_val;
1608             //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);
1609             break;
1610         }
1611         // Unhandled Registers
1612         case EXT_APIC_CMD_OFFSET:
1613         case SEOI_OFFSET:
1614         default:
1615             PrintError(core->vm_info, core, "apic %u: core %u: Write to Unhandled APIC Register: %x (ignored)\n", 
1616                        apic->lapic_id.val, core->vcpu_id, (uint32_t)reg_addr);
1617
1618             return -1;
1619     }
1620
1621     PrintDebug(core->vm_info, core, "apic %u: core %u: Write finished\n", apic->lapic_id.val, core->vcpu_id);
1622
1623     return length;
1624
1625 }
1626
1627
1628
1629 /* Interrupt Controller Functions */
1630
1631
1632 static int apic_intr_pending(struct guest_info * core, void * private_data) {
1633     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
1634     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1635     int req_irq = 0;    
1636     int svc_irq = 0;
1637
1638     // Activate all queued IRQ entries
1639     drain_irq_entries(apic);
1640
1641     // Check for newly activated entries
1642     req_irq = get_highest_irr(apic);
1643     svc_irq = get_highest_isr(apic);
1644
1645     //    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);
1646
1647
1648     if ((req_irq >= 0) && 
1649         (req_irq > svc_irq)) {
1650
1651         // We have a new requested vector that is higher priority than
1652         // the vector that is in-service
1653
1654         uint32_t ppr = get_apic_ppr(apic);
1655
1656         if ((req_irq & 0xf0) > (ppr & 0xf0)) {
1657             // it's also higher priority than the current
1658             // processor priority.  Therefore this
1659             // interrupt can go in now.
1660             return 1;
1661         } else {
1662             // processor priority is currently too high
1663             // for this interrupt to go in now.  
1664             // note that if tpr=0xf?, then ppr=0xf?
1665             // and thus all vectors will be masked
1666             // as required (tpr=0xf? => all masked)
1667             return 0;
1668         }
1669     } else {
1670         // the vector that is in service is higher
1671         // priority than any new requested vector
1672         return 0;
1673     }
1674 }
1675
1676
1677
1678 static int apic_get_intr_number(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 = get_highest_irr(apic);
1682     int svc_irq = get_highest_isr(apic);
1683
1684
1685     // for the logic here, see the comments for apic_intr_pending
1686     if ((req_irq >=0) &&
1687         (req_irq > svc_irq)) { 
1688         
1689         uint32_t ppr = get_apic_ppr(apic);
1690         
1691         if ((req_irq & 0xf0) > (ppr & 0xf0)) {
1692             return req_irq;
1693         } else {
1694             // hmm, this should not have happened, but, anyway,
1695             // no interrupt is currently ready to go in
1696             return -1;
1697         }
1698     } else {
1699         return -1;
1700     }
1701 }
1702
1703
1704
1705 int v3_apic_send_ipi(struct v3_vm_info * vm, struct v3_gen_ipi * ipi, void * dev_data) {
1706     struct apic_dev_state * apic_dev = (struct apic_dev_state *)
1707         (((struct vm_device *)dev_data)->private_data);
1708
1709     return route_ipi(apic_dev, NULL, ipi);
1710 }
1711
1712
1713
1714 static int apic_begin_irq(struct guest_info * core, void * private_data, int irq) {
1715     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(private_data);
1716     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1717     int major_offset = (irq & ~0x00000007) >> 3;
1718     int minor_offset = irq & 0x00000007;
1719     uint8_t *req_location = apic->int_req_reg + major_offset;
1720     uint8_t *svc_location = apic->int_svc_reg + major_offset;
1721     uint8_t flag = 0x01 << minor_offset;
1722
1723     if (*req_location & flag) {
1724         // we will only pay attention to a begin irq if we
1725         // know that we initiated it!
1726         *svc_location |= flag;
1727         *req_location &= ~flag;
1728     } else {
1729         // do nothing... 
1730         //PrintDebug(core->vm_info, core, "apic %u: core %u: begin irq for %d ignored since I don't own it\n",
1731         //         apic->lapic_id.val, core->vcpu_id, irq);
1732     }
1733
1734     return 0;
1735 }
1736
1737
1738 /* Timer Functions */
1739
1740 static void apic_inject_timer_intr(struct guest_info *core,
1741                                    void * priv_data) {
1742     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1743     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1744     // raise irq
1745     PrintDebug(core->vm_info, core, "apic %u: core %u: Raising APIC Timer interrupt (periodic=%d) (icnt=%d)\n",
1746                apic->lapic_id.val, core->vcpu_id,
1747                apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt);
1748
1749     if (apic_intr_pending(core, priv_data)) {
1750         PrintDebug(core->vm_info, core, "apic %u: core %u: Overriding pending IRQ %d\n", 
1751                    apic->lapic_id.val, core->vcpu_id, 
1752                    apic_get_intr_number(core, priv_data));
1753     }
1754
1755     if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
1756         PrintError(core->vm_info, core, "apic %u: core %u: Could not raise Timer interrupt\n",
1757                    apic->lapic_id.val, core->vcpu_id);
1758     }
1759
1760     return;
1761 }
1762         
1763
1764
1765
1766 static void apic_update_time(struct guest_info * core, 
1767                              uint64_t cpu_cycles, uint64_t cpu_freq, 
1768                              void * priv_data) {
1769     struct apic_dev_state * apic_dev = (struct apic_dev_state *)(priv_data);
1770     struct apic_state * apic = &(apic_dev->apics[core->vcpu_id]); 
1771
1772     // The 32 bit GCC runtime is a pile of shit
1773 #ifdef __V3_64BIT__
1774     uint64_t tmr_ticks = 0;
1775 #else 
1776     uint32_t tmr_ticks = 0;
1777 #endif
1778
1779     uint8_t tmr_div = *(uint8_t *)&(apic->tmr_div_cfg.val);
1780     uint_t shift_num = 0;
1781
1782
1783     // Check whether this is true:
1784     //   -> If the Init count is zero then the timer is disabled
1785     //      and doesn't just blitz interrupts to the CPU
1786     if ((apic->tmr_init_cnt == 0) || 
1787         ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
1788           (apic->tmr_cur_cnt == 0))) {
1789         //PrintDebug(core->vm_info, core, "apic %u: core %u: APIC timer not yet initialized\n",apic->lapic_id.val,info->vcpu_id);
1790         return;
1791     }
1792
1793
1794     switch (tmr_div) {
1795         case APIC_TMR_DIV1:
1796             shift_num = 0;
1797             break;
1798         case APIC_TMR_DIV2:
1799             shift_num = 1;
1800             break;
1801         case APIC_TMR_DIV4:
1802             shift_num = 2;
1803             break;
1804         case APIC_TMR_DIV8:
1805             shift_num = 3;
1806             break;
1807         case APIC_TMR_DIV16:
1808             shift_num = 4;
1809             break;
1810         case APIC_TMR_DIV32:
1811             shift_num = 5;
1812             break;
1813         case APIC_TMR_DIV64:
1814             shift_num = 6;
1815             break;
1816         case APIC_TMR_DIV128:
1817             shift_num = 7;
1818             break;
1819         default:
1820             PrintError(core->vm_info, core, "apic %u: core %u: Invalid Timer Divider configuration\n",
1821                        apic->lapic_id.val, core->vcpu_id);
1822             return;
1823     }
1824
1825     tmr_ticks = cpu_cycles >> shift_num;
1826     //    PrintDebug(core->vm_info, core, "Timer Ticks: %p\n", (void *)tmr_ticks);
1827
1828     if (tmr_ticks < apic->tmr_cur_cnt) {
1829         apic->tmr_cur_cnt -= tmr_ticks;
1830 #ifdef V3_CONFIG_APIC_ENQUEUE_MISSED_TMR_IRQS
1831         if (apic->missed_ints && !apic_intr_pending(core, priv_data)) {
1832             PrintDebug(core->vm_info, core, "apic %u: core %u: Injecting queued APIC timer interrupt.\n",
1833                        apic->lapic_id.val, core->vcpu_id);
1834             apic_inject_timer_intr(core, priv_data);
1835             apic->missed_ints--;
1836         }
1837 #endif /* CONFIG_APIC_ENQUEUE_MISSED_TMR_IRQS */ 
1838     } else {
1839         tmr_ticks -= apic->tmr_cur_cnt;
1840         apic->tmr_cur_cnt = 0;
1841
1842         apic_inject_timer_intr(core, priv_data);
1843
1844         if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
1845             int queued_ints = tmr_ticks / apic->tmr_init_cnt;
1846             tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
1847             apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
1848             apic->missed_ints += queued_ints;
1849         }
1850     }
1851
1852     return;
1853 }
1854
1855 static struct intr_ctrl_ops intr_ops = {
1856     .intr_pending = apic_intr_pending,
1857     .get_intr_number = apic_get_intr_number,
1858     .begin_irq = apic_begin_irq,
1859 };
1860
1861
1862 static struct v3_timer_ops timer_ops = {
1863     .update_timer = apic_update_time,
1864 };
1865
1866
1867
1868
1869 static int apic_free(struct apic_dev_state * apic_dev) {
1870     int i = 0;
1871     struct v3_vm_info * vm = NULL;
1872
1873     for (i = 0; i < apic_dev->num_apics; i++) {
1874         struct apic_state * apic = &(apic_dev->apics[i]);
1875         struct guest_info * core = apic->core;
1876         
1877         vm = core->vm_info;
1878
1879         v3_remove_intr_controller(core, apic->controller_handle);
1880
1881         if (apic->timer) {
1882             v3_remove_timer(core, apic->timer);
1883         }
1884
1885         v3_lock_deinit(&(apic->irq_queue.lock));
1886
1887         // unhook memory
1888
1889     }
1890
1891     v3_unhook_msr(vm, BASE_ADDR_MSR);
1892
1893     v3_lock_deinit(&(apic_dev->state_lock));
1894
1895     V3_Free(apic_dev);
1896     return 0;
1897 }
1898
1899 #ifdef V3_CONFIG_CHECKPOINT
1900
1901 #define KEY_MAX 128
1902 #define MAKE_KEY(x) snprintf(key,KEY_MAX,"%s%d",x,i);
1903
1904 static int apic_save(struct v3_chkpt_ctx * ctx, void * private_data) {
1905     struct apic_dev_state * apic_state = (struct apic_dev_state *)private_data;
1906     int i = 0;
1907     uint32_t temp;
1908     char key[KEY_MAX];
1909
1910     V3_CHKPT_SAVE(ctx, "NUM_APICS", apic_state->num_apics,savefailout);
1911
1912     for (i = 0; i < apic_state->num_apics; i++) {
1913       drain_irq_entries(&(apic_state->apics[i]));
1914
1915       MAKE_KEY("BASE_ADDR"); 
1916       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].base_addr,savefailout);
1917       MAKE_KEY("BASE_ADDR_MSR"); 
1918       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].base_addr_msr,savefailout);
1919       MAKE_KEY("LAPIC_ID");
1920       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].lapic_id,savefailout);
1921       MAKE_KEY("APIC_VER");
1922       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].apic_ver,savefailout);
1923       MAKE_KEY("EXT_APIC_CTRL");
1924       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ext_apic_ctrl,savefailout);
1925       MAKE_KEY("LOCAL_VEC_TBL");
1926       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].local_vec_tbl,savefailout);
1927       MAKE_KEY("TMR_VEC_TBL");
1928       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_vec_tbl,savefailout);
1929       MAKE_KEY("TMR_DIV_CFG");
1930       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_div_cfg,savefailout);
1931       MAKE_KEY("LINT0_VEC_TBL");
1932       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].lint0_vec_tbl,savefailout);
1933       MAKE_KEY("LINT1_VEC_TBL");
1934       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].lint1_vec_tbl,savefailout);
1935       MAKE_KEY("PERF_CTR_LOC_VEC_TBL");
1936       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].perf_ctr_loc_vec_tbl,savefailout);
1937       MAKE_KEY("THERM_LOC_VEC_TBL");
1938       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].therm_loc_vec_tbl,savefailout);
1939       MAKE_KEY("ERR_VEC_TBL");
1940       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].err_vec_tbl,savefailout);
1941       MAKE_KEY("ERR_STATUS");
1942       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].err_status,savefailout);
1943       MAKE_KEY("SPURIOUS_INT");
1944       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].spurious_int,savefailout);
1945       MAKE_KEY("INT_CMD");
1946       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_cmd,savefailout);
1947       MAKE_KEY("LOG_DST");
1948       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].log_dst,savefailout);
1949       MAKE_KEY("DST_FMT");
1950       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].dst_fmt,savefailout);
1951
1952       // APR and PPR are stored only for compatability
1953       // TPR is in APIC_TPR, APR and PPR are derived
1954         
1955       temp = get_apic_apr(&(apic_state->apics[i]));
1956       MAKE_KEY("ARB_PRIO");
1957       V3_CHKPT_SAVE(ctx, key, temp,savefailout);
1958       temp = get_apic_tpr(&(apic_state->apics[i]));
1959       MAKE_KEY("TASK_PRIO");
1960       V3_CHKPT_SAVE(ctx,key,temp,savefailout);
1961       temp = get_apic_ppr(&(apic_state->apics[i]));
1962       MAKE_KEY("PROC_PRIO");
1963       V3_CHKPT_SAVE(ctx, key,temp,savefailout);
1964
1965       MAKE_KEY("EXT_APIC_FEATURE");
1966       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ext_apic_feature,savefailout);
1967       MAKE_KEY("SPEC_EOI");
1968       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].spec_eoi,savefailout);
1969       MAKE_KEY("TMR_CUR_CNT");
1970       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_cur_cnt,savefailout);
1971       
1972       MAKE_KEY("TMR_INIT_CNT");
1973       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].tmr_init_cnt,savefailout);
1974       MAKE_KEY("EXT_INTR_VEC_TBL");
1975       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ext_intr_vec_tbl,savefailout);
1976
1977       MAKE_KEY("REM_RD_DATA");
1978       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].rem_rd_data,savefailout);
1979       MAKE_KEY("IPI_STATE");
1980       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].ipi_state,savefailout);
1981       MAKE_KEY("INT_REQ_REG");
1982       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_req_reg,savefailout);
1983       MAKE_KEY("INT_SVC_REG");
1984       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_svc_reg,savefailout);
1985       MAKE_KEY("INT_EN_REG");
1986       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].int_en_reg,savefailout);
1987       MAKE_KEY("TRIG_MODE_REG");
1988       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].trig_mode_reg,savefailout);
1989       MAKE_KEY("EOI");
1990       V3_CHKPT_SAVE(ctx, key, apic_state->apics[i].eoi,savefailout);
1991
1992     }
1993
1994     return 0;
1995
1996  savefailout:
1997     PrintError(VM_NONE, VCORE_NONE, "Failed to save apic\n");
1998     return -1;
1999 }
2000
2001 static int apic_load(struct v3_chkpt_ctx * ctx, void * private_data) {
2002     struct apic_dev_state *apic_state = (struct apic_dev_state *)private_data;
2003     int i = 0;
2004     uint32_t temp;
2005     char key[KEY_MAX];
2006
2007     V3_CHKPT_LOAD(ctx,"NUM_APICS", apic_state->num_apics, loadfailout);
2008
2009     for (i = 0; i < apic_state->num_apics; i++) {
2010       drain_irq_entries(&(apic_state->apics[i]));
2011
2012       MAKE_KEY("BASE_ADDR"); 
2013       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].base_addr,loadfailout);
2014       MAKE_KEY("BASE_ADDR_MSR"); 
2015       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].base_addr_msr,loadfailout);
2016       MAKE_KEY("LAPIC_ID");
2017       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].lapic_id,loadfailout);
2018       MAKE_KEY("APIC_VER");
2019       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].apic_ver,loadfailout);
2020       MAKE_KEY("EXT_APIC_CTRL");
2021       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ext_apic_ctrl,loadfailout);
2022       MAKE_KEY("LOCAL_VEC_TBL");
2023       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].local_vec_tbl,loadfailout);
2024       MAKE_KEY("TMR_VEC_TBL");
2025       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_vec_tbl,loadfailout);
2026       MAKE_KEY("TMR_DIV_CFG");
2027       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_div_cfg,loadfailout);
2028       MAKE_KEY("LINT0_VEC_TBL");
2029       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].lint0_vec_tbl,loadfailout);
2030       MAKE_KEY("LINT1_VEC_TBL");
2031       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].lint1_vec_tbl,loadfailout);
2032       MAKE_KEY("PERF_CTR_LOC_VEC_TBL");
2033       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].perf_ctr_loc_vec_tbl,loadfailout);
2034       MAKE_KEY("THERM_LOC_VEC_TBL");
2035       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].therm_loc_vec_tbl,loadfailout);
2036       MAKE_KEY("ERR_VEC_TBL");
2037       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].err_vec_tbl,loadfailout);
2038       MAKE_KEY("ERR_STATUS");
2039       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].err_status,loadfailout);
2040       MAKE_KEY("SPURIOUS_INT");
2041       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].spurious_int,loadfailout);
2042       MAKE_KEY("INT_CMD");
2043       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_cmd,loadfailout);
2044       MAKE_KEY("LOG_DST");
2045       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].log_dst,loadfailout);
2046       MAKE_KEY("DST_FMT");
2047       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].dst_fmt,loadfailout);
2048
2049       // APR and PPR are stored only for compatability
2050       // TPR is in APIC_TPR, APR and PPR are derived
2051
2052       MAKE_KEY("ARB_PRIO");
2053       V3_CHKPT_LOAD(ctx, key, temp,loadfailout);
2054       // discarded
2055
2056       MAKE_KEY("TASK_PRIO");
2057       V3_CHKPT_LOAD(ctx,key,temp,loadfailout);
2058       set_apic_tpr(&(apic_state->apics[i]),temp);
2059       
2060       MAKE_KEY("PROC_PRIO");
2061       V3_CHKPT_LOAD(ctx, key,temp,loadfailout);
2062       // discarded
2063
2064
2065       MAKE_KEY("EXT_APIC_FEATURE");
2066       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ext_apic_feature,loadfailout);
2067       MAKE_KEY("SPEC_EOI");
2068       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].spec_eoi,loadfailout);
2069       MAKE_KEY("TMR_CUR_CNT");
2070       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_cur_cnt,loadfailout);
2071       
2072       MAKE_KEY("TMR_INIT_CNT");
2073       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].tmr_init_cnt,loadfailout);
2074       MAKE_KEY("EXT_INTR_VEC_TBL");
2075       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ext_intr_vec_tbl,loadfailout);
2076
2077       MAKE_KEY("REM_RD_DATA");
2078       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].rem_rd_data,loadfailout);
2079       MAKE_KEY("IPI_STATE");
2080       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].ipi_state,loadfailout);
2081       MAKE_KEY("INT_REQ_REG");
2082       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_req_reg,loadfailout);
2083       MAKE_KEY("INT_SVC_REG");
2084       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_svc_reg,loadfailout);
2085       MAKE_KEY("INT_EN_REG");
2086       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].int_en_reg,loadfailout);
2087       MAKE_KEY("TRIG_MODE_REG");
2088       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].trig_mode_reg,loadfailout);
2089       MAKE_KEY("EOI");
2090       V3_CHKPT_LOAD(ctx, key, apic_state->apics[i].eoi,loadfailout);
2091     }
2092     
2093     
2094     return 0;
2095     
2096  loadfailout:
2097     PrintError(VM_NONE,VCORE_NONE, "Failed to load apic\n");
2098     return -1;
2099     
2100 }
2101
2102 #endif
2103
2104 static struct v3_device_ops dev_ops = {
2105     .free = (int (*)(void *))apic_free,
2106 #ifdef V3_CONFIG_CHECKPOINT
2107     .save = apic_save,
2108     .load = apic_load
2109 #endif
2110 };
2111
2112
2113
2114 static int apic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
2115     char * dev_id = v3_cfg_val(cfg, "ID");
2116     struct apic_dev_state * apic_dev = NULL;
2117     int i = 0;
2118
2119     PrintDebug(vm, VCORE_NONE, "apic: creating an APIC for each core\n");
2120
2121     apic_dev = (struct apic_dev_state *)V3_Malloc(sizeof(struct apic_dev_state) + 
2122                                                   sizeof(struct apic_state) * vm->num_cores);
2123
2124
2125     if (!apic_dev) {
2126         PrintError(vm, VCORE_NONE, "Failed to allocate space for APIC\n");
2127         return -1;
2128     }
2129
2130     apic_dev->num_apics = vm->num_cores;
2131     v3_lock_init(&(apic_dev->state_lock));
2132
2133     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, apic_dev);
2134
2135     if (dev == NULL) {
2136         PrintError(vm, VCORE_NONE, "apic: Could not attach device %s\n", dev_id);
2137         V3_Free(apic_dev);
2138         return -1;
2139     }
2140
2141     
2142     for (i = 0; i < vm->num_cores; i++) {
2143         struct apic_state * apic = &(apic_dev->apics[i]);
2144         struct guest_info * core = &(vm->cores[i]);
2145
2146         apic->core = core;
2147
2148         init_apic_state(apic, i);
2149
2150         apic->controller_handle = v3_register_intr_controller(core, &intr_ops, apic_dev);
2151
2152         apic->timer = v3_add_timer(core, &timer_ops, apic_dev);
2153
2154         if (apic->timer == NULL) {
2155             PrintError(vm, VCORE_NONE,"APIC: Failed to attach timer to core %d\n", i);
2156             v3_remove_device(dev);
2157             return -1;
2158         }
2159
2160         v3_hook_full_mem(vm, core->vcpu_id, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, apic_dev);
2161
2162         PrintDebug(vm, VCORE_NONE, "apic %u: (setup device): done, my id is %u\n", i, apic->lapic_id.val);
2163     }
2164
2165 #ifdef V3_CONFIG_DEBUG_APIC
2166     for (i = 0; i < vm->num_cores; i++) {
2167         struct apic_state * apic = &(apic_dev->apics[i]);
2168         PrintDebug(vm, VCORE_NONE, "apic: sanity check: apic %u (at %p) has id %u and msr value %llx and core at %p\n",
2169                    i, apic, apic->lapic_id.val, apic->base_addr_msr.value,apic->core);
2170     }
2171 #endif
2172
2173
2174     PrintDebug(vm, VCORE_NONE, "apic: priv_data is at %p\n", apic_dev);
2175
2176     v3_hook_msr(vm, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, apic_dev);
2177
2178     return 0;
2179 }
2180
2181
2182
2183 device_register("LAPIC", apic_init)