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.


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