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.


added special handler for seastar interrupt
[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  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21 #include <devices/apic.h>
22 #include <devices/apic_regs.h>
23 #include <palacios/vmm.h>
24 #include <palacios/vmm_msr.h>
25
26
27 #ifndef DEBUG_APIC
28 #undef PrintDebug
29 #define PrintDebug(fmt, args...)
30 #endif
31
32
33 typedef enum { APIC_TMR_INT, APIC_THERM_INT, APIC_PERF_INT, 
34                APIC_LINT0_INT, APIC_LINT1_INT, APIC_ERR_INT } apic_irq_type_t;
35
36 #define APIC_FIXED_DELIVERY  0x0
37 #define APIC_SMI_DELIVERY    0x2
38 #define APIC_NMI_DELIVERY    0x4
39 #define APIC_INIT_DELIVERY   0x5
40 #define APIC_EXTINT_DELIVERY 0x7
41
42
43 #define BASE_ADDR_MSR 0x0000001B
44 #define DEFAULT_BASE_ADDR 0xfee00000
45
46 #define APIC_ID_OFFSET                    0x020
47 #define APIC_VERSION_OFFSET               0x030
48 #define TPR_OFFSET                        0x080
49 #define APR_OFFSET                        0x090
50 #define PPR_OFFSET                        0x0a0
51 #define EOI_OFFSET                        0x0b0
52 #define REMOTE_READ_OFFSET                0x0c0
53 #define LDR_OFFSET                        0x0d0
54 #define DFR_OFFSET                        0x0e0
55 #define SPURIOUS_INT_VEC_OFFSET           0x0f0
56
57 #define ISR_OFFSET0                       0x100   // 0x100 - 0x170
58 #define ISR_OFFSET1                       0x110   // 0x100 - 0x170
59 #define ISR_OFFSET2                       0x120   // 0x100 - 0x170
60 #define ISR_OFFSET3                       0x130   // 0x100 - 0x170
61 #define ISR_OFFSET4                       0x140   // 0x100 - 0x170
62 #define ISR_OFFSET5                       0x150   // 0x100 - 0x170
63 #define ISR_OFFSET6                       0x160   // 0x100 - 0x170
64 #define ISR_OFFSET7                       0x170   // 0x100 - 0x170
65
66 #define TRIG_OFFSET0                      0x180   // 0x180 - 0x1f0
67 #define TRIG_OFFSET1                      0x190   // 0x180 - 0x1f0
68 #define TRIG_OFFSET2                      0x1a0   // 0x180 - 0x1f0
69 #define TRIG_OFFSET3                      0x1b0   // 0x180 - 0x1f0
70 #define TRIG_OFFSET4                      0x1c0   // 0x180 - 0x1f0
71 #define TRIG_OFFSET5                      0x1d0   // 0x180 - 0x1f0
72 #define TRIG_OFFSET6                      0x1e0   // 0x180 - 0x1f0
73 #define TRIG_OFFSET7                      0x1f0   // 0x180 - 0x1f0
74
75
76 #define IRR_OFFSET0                       0x200   // 0x200 - 0x270
77 #define IRR_OFFSET1                       0x210   // 0x200 - 0x270
78 #define IRR_OFFSET2                       0x220   // 0x200 - 0x270
79 #define IRR_OFFSET3                       0x230   // 0x200 - 0x270
80 #define IRR_OFFSET4                       0x240   // 0x200 - 0x270
81 #define IRR_OFFSET5                       0x250   // 0x200 - 0x270
82 #define IRR_OFFSET6                       0x260   // 0x200 - 0x270
83 #define IRR_OFFSET7                       0x270   // 0x200 - 0x270
84
85
86 #define ESR_OFFSET                        0x280
87 #define INT_CMD_LO_OFFSET                 0x300
88 #define INT_CMD_HI_OFFSET                 0x310
89 #define TMR_LOC_VEC_TBL_OFFSET            0x320
90 #define THERM_LOC_VEC_TBL_OFFSET          0x330
91 #define PERF_CTR_LOC_VEC_TBL_OFFSET       0x340
92 #define LINT0_VEC_TBL_OFFSET              0x350
93 #define LINT1_VEC_TBL_OFFSET              0x360
94 #define ERR_VEC_TBL_OFFSET                0x370
95 #define TMR_INIT_CNT_OFFSET               0x380
96 #define TMR_CUR_CNT_OFFSET                0x390
97 #define TMR_DIV_CFG_OFFSET                0x3e0
98 #define EXT_APIC_FEATURE_OFFSET           0x400
99 #define EXT_APIC_CMD_OFFSET               0x410
100 #define SEOI_OFFSET                       0x420
101
102 #define IER_OFFSET0                       0x480   // 0x480 - 0x4f0
103 #define IER_OFFSET1                       0x490   // 0x480 - 0x4f0
104 #define IER_OFFSET2                       0x4a0   // 0x480 - 0x4f0
105 #define IER_OFFSET3                       0x4b0   // 0x480 - 0x4f0
106 #define IER_OFFSET4                       0x4c0   // 0x480 - 0x4f0
107 #define IER_OFFSET5                       0x4d0   // 0x480 - 0x4f0
108 #define IER_OFFSET6                       0x4e0   // 0x480 - 0x4f0
109 #define IER_OFFSET7                       0x4f0   // 0x480 - 0x4f0
110
111 #define EXT_INT_LOC_VEC_TBL_OFFSET0       0x500   // 0x500 - 0x530
112 #define EXT_INT_LOC_VEC_TBL_OFFSET1       0x510   // 0x500 - 0x530
113 #define EXT_INT_LOC_VEC_TBL_OFFSET2       0x520   // 0x500 - 0x530
114 #define EXT_INT_LOC_VEC_TBL_OFFSET3       0x530   // 0x500 - 0x530
115
116
117
118 struct apic_msr {
119     union {
120         uint64_t val;
121         struct {
122             uchar_t rsvd;
123             uint_t bootstrap_cpu : 1;
124             uint_t rsvd2         : 2;
125             uint_t apic_enable   : 1;
126             ullong_t base_addr   : 40;
127             uint_t rsvd3         : 12;
128         } __attribute__((packed));
129     } __attribute__((packed));
130 } __attribute__((packed));
131
132
133
134
135 struct apic_state {
136     addr_t base_addr;
137
138     /* MSRs */
139     v3_msr_t base_addr_msr;
140
141
142     /* memory map registers */
143
144     struct lapic_id_reg lapic_id;
145     struct apic_ver_reg apic_ver;
146     struct ext_apic_ctrl_reg ext_apic_ctrl;
147     struct local_vec_tbl_reg local_vec_tbl;
148     struct tmr_vec_tbl_reg tmr_vec_tbl;
149     struct tmr_div_cfg_reg tmr_div_cfg;
150     struct lint_vec_tbl_reg lint0_vec_tbl;
151     struct lint_vec_tbl_reg lint1_vec_tbl;
152     struct perf_ctr_loc_vec_tbl_reg perf_ctr_loc_vec_tbl;
153     struct therm_loc_vec_tbl_reg therm_loc_vec_tbl;
154     struct err_vec_tbl_reg err_vec_tbl;
155     struct err_status_reg err_status;
156     struct spurious_int_reg spurious_int;
157     struct int_cmd_reg int_cmd;
158     struct log_dst_reg log_dst;
159     struct dst_fmt_reg dst_fmt;
160     struct arb_prio_reg arb_prio;
161     struct task_prio_reg task_prio;
162     struct proc_prio_reg proc_prio;
163     struct ext_apic_feature_reg ext_apic_feature;
164     struct spec_eoi_reg spec_eoi;
165   
166
167     uint32_t tmr_cur_cnt;
168     uint32_t tmr_init_cnt;
169
170
171
172     uint32_t rem_rd_data;
173
174
175     uchar_t int_req_reg[32];
176     uchar_t int_svc_reg[32];
177     uchar_t int_en_reg[32];
178     uchar_t trig_mode_reg[32];
179   
180     uint32_t eoi;
181
182
183 };
184
185
186 static void init_apic_state(struct apic_state * apic) {
187     apic->base_addr = DEFAULT_BASE_ADDR;
188     apic->base_addr_msr.value = 0x0000000000000900LL;
189     apic->base_addr_msr.value |= ((uint64_t)DEFAULT_BASE_ADDR); 
190
191     PrintDebug("Sizeof Interrupt Request Register %d, should be 32\n", 
192                (uint_t)sizeof(apic->int_req_reg));
193
194     memset(apic->int_req_reg, 0, sizeof(apic->int_req_reg));
195     memset(apic->int_svc_reg, 0, sizeof(apic->int_svc_reg));
196     memset(apic->int_en_reg, 0xff, sizeof(apic->int_en_reg));
197     memset(apic->trig_mode_reg, 0, sizeof(apic->trig_mode_reg));
198
199     apic->eoi = 0x00000000;
200     apic->rem_rd_data = 0x00000000;
201     apic->tmr_init_cnt = 0x00000000;
202     apic->tmr_cur_cnt = 0x00000000;
203
204     // TODO:
205     // We need to figure out what the APIC ID is....
206     apic->lapic_id.val = 0x00000000;
207
208     // The P6 has 6 LVT entries, so we set the value to (6-1)...
209     apic->apic_ver.val = 0x80050010;
210
211     apic->task_prio.val = 0x00000000;
212     apic->arb_prio.val = 0x00000000;
213     apic->proc_prio.val = 0x00000000;
214     apic->log_dst.val = 0x00000000;
215     apic->dst_fmt.val = 0xffffffff;
216     apic->spurious_int.val = 0x000000ff;
217     apic->err_status.val = 0x00000000;
218     apic->int_cmd.val = 0x0000000000000000LL;
219     apic->tmr_vec_tbl.val = 0x00010000;
220     apic->therm_loc_vec_tbl.val = 0x00010000;
221     apic->perf_ctr_loc_vec_tbl.val = 0x00010000;
222     apic->lint0_vec_tbl.val = 0x00010000;
223     apic->lint1_vec_tbl.val = 0x00010000;
224     apic->err_vec_tbl.val = 0x00010000;
225     apic->tmr_div_cfg.val = 0x00000000;
226     apic->ext_apic_feature.val = 0x00040007;
227     apic->ext_apic_ctrl.val = 0x00000000;
228     apic->spec_eoi.val = 0x00000000;
229 }
230
231
232
233
234 static int read_apic_msr(uint_t msr, v3_msr_t * dst, void * priv_data) {
235     struct vm_device * dev = (struct vm_device *)priv_data;
236     struct apic_state * apic = (struct apic_state *)dev->private_data;
237     PrintError("READING APIC BASE ADDR: HI=%x LO=%x\n", apic->base_addr_msr.hi, apic->base_addr_msr.lo);
238
239     return -1;
240 }
241
242
243 static int write_apic_msr(uint_t msr, v3_msr_t src, void * priv_data) {
244     //  struct vm_device * dev = (struct vm_device *)priv_data;
245     //  struct apic_state * apic = (struct apic_state *)dev->private_data;
246
247     PrintError("WRITING APIC BASE ADDR: HI=%x LO=%x\n", src.hi, src.lo);
248
249     return -1;
250 }
251
252
253 // irq_num is the bit offset into a 256 bit buffer...
254 static int activate_apic_irq(struct apic_state * apic, uint32_t irq_num) {
255     int major_offset = (irq_num & ~0x00000007) >> 3;
256     int minor_offset = irq_num & 0x00000007;
257     uchar_t * req_location = apic->int_req_reg + major_offset;
258     uchar_t * en_location = apic->int_en_reg + major_offset;
259     uchar_t flag = 0x1 << minor_offset;
260
261     if (irq_num <= 15) {
262         PrintError("Attempting to raise an invalid interrupt: %d\n", irq_num);
263         return -1;
264     }
265
266     PrintDebug("Raising APIC IRQ %d\n", irq_num);
267
268     if (*en_location & flag) {
269         *req_location |= flag;
270     } else {
271         PrintDebug("Interrupt  not enabled... %.2x\n", *en_location);
272         return 0;
273     }
274
275     return 0;
276 }
277
278
279
280 static int apic_do_eoi(struct apic_state * apic) {
281     int i = 0, j = 0;
282
283     // We iterate backwards to find the highest priority
284     for (i = 31; i >= 0; i--) {
285         uchar_t  * svc_major = apic->int_svc_reg + i;
286     
287         if ((*svc_major) & 0xff) {
288             for (j = 7; j >= 0; j--) {
289                 uchar_t flag = 0x1 << j;
290                 if ((*svc_major) & flag) {
291                     *svc_major &= ~flag;
292                     return 0;
293                 }
294             }
295         }
296     }
297
298     return 0;
299 }
300  
301
302 static int activate_internal_irq(struct apic_state * apic, apic_irq_type_t int_type) {
303     uint32_t vec_num = 0;
304     uint32_t del_mode = 0;
305     int masked = 0;
306
307
308     switch (int_type) {
309         case APIC_TMR_INT:
310             vec_num = apic->tmr_vec_tbl.vec;
311             del_mode = APIC_FIXED_DELIVERY;
312             masked = apic->tmr_vec_tbl.mask;
313             break;
314         case APIC_THERM_INT:
315             vec_num = apic->therm_loc_vec_tbl.vec;
316             del_mode = apic->therm_loc_vec_tbl.msg_type;
317             masked = apic->therm_loc_vec_tbl.mask;
318             break;
319         case APIC_PERF_INT:
320             vec_num = apic->perf_ctr_loc_vec_tbl.vec;
321             del_mode = apic->perf_ctr_loc_vec_tbl.msg_type;
322             masked = apic->perf_ctr_loc_vec_tbl.mask;
323             break;
324         case APIC_LINT0_INT:
325             vec_num = apic->lint0_vec_tbl.vec;
326             del_mode = apic->lint0_vec_tbl.msg_type;
327             masked = apic->lint0_vec_tbl.mask;
328             break;
329         case APIC_LINT1_INT:
330             vec_num = apic->lint1_vec_tbl.vec;
331             del_mode = apic->lint1_vec_tbl.msg_type;
332             masked = apic->lint1_vec_tbl.mask;
333             break;
334         case APIC_ERR_INT:
335             vec_num = apic->err_vec_tbl.vec;
336             del_mode = APIC_FIXED_DELIVERY;
337             masked = apic->err_vec_tbl.mask;
338             break;
339         default:
340             PrintError("Invalid APIC interrupt type\n");
341             return -1;
342     }
343
344     // interrupt is masked, don't send
345     if (masked == 1) {
346         PrintDebug("Inerrupt is masked\n");
347         return 0;
348     }
349
350     if (del_mode == APIC_FIXED_DELIVERY) {
351         //PrintDebug("Activating internal APIC IRQ %d\n", vec_num);
352         return activate_apic_irq(apic, vec_num);
353     } else {
354         PrintError("Unhandled Delivery Mode\n");
355         return -1;
356     }
357 }
358
359
360 static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
361     struct vm_device * dev = (struct vm_device *)priv_data;
362     struct apic_state * apic = (struct apic_state *)dev->private_data;
363     addr_t reg_addr  = guest_addr - apic->base_addr;
364     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
365     uint32_t val = 0;
366
367
368     PrintDebug("Read apic address space (%p)\n", 
369                (void *)guest_addr);
370
371     if (msr->apic_enable == 0) {
372         PrintError("Write to APIC address space with disabled APIC\n");
373         return -1;
374     }
375
376
377     /* Because "May not be supported" doesn't matter to Linux developers... */
378     /*   if (length != 4) { */
379     /*     PrintError("Invalid apic read length (%d)\n", length); */
380     /*     return -1; */
381     /*   } */
382
383     switch (reg_addr & ~0x3) {
384         case EOI_OFFSET:
385             // Well, only an idiot would read from a architectural write only register
386             // Oh, Hello Linux.
387             //    PrintError("Attempting to read from write only register\n");
388             //    return -1;
389             break;
390
391             // data registers
392         case APIC_ID_OFFSET:
393             val = apic->lapic_id.val;
394             break;
395         case APIC_VERSION_OFFSET:
396             val = apic->apic_ver.val;
397             break;
398         case TPR_OFFSET:
399             val = apic->task_prio.val;
400             break;
401         case APR_OFFSET:
402             val = apic->arb_prio.val;
403             break;
404         case PPR_OFFSET:
405             val = apic->proc_prio.val;
406             break;
407         case REMOTE_READ_OFFSET:
408             val = apic->rem_rd_data;
409             break;
410         case LDR_OFFSET:
411             val = apic->log_dst.val;
412             break;
413         case DFR_OFFSET:
414             val = apic->dst_fmt.val;
415             break;
416         case SPURIOUS_INT_VEC_OFFSET:
417             val = apic->spurious_int.val;
418             break;
419         case ESR_OFFSET:
420             val = apic->err_status.val;
421             break;
422         case TMR_LOC_VEC_TBL_OFFSET:
423             val = apic->tmr_vec_tbl.val;
424             break;
425         case LINT0_VEC_TBL_OFFSET:
426             val = apic->lint0_vec_tbl.val;
427             break;
428         case LINT1_VEC_TBL_OFFSET:
429             val = apic->lint1_vec_tbl.val;
430             break;
431         case ERR_VEC_TBL_OFFSET:
432             val = apic->err_vec_tbl.val;
433             break;
434         case TMR_INIT_CNT_OFFSET:
435             val = apic->tmr_init_cnt;
436             break;
437         case TMR_DIV_CFG_OFFSET:
438             val = apic->tmr_div_cfg.val;
439             break;
440
441         case IER_OFFSET0:
442             val = *(uint32_t *)(apic->int_en_reg);
443             break;
444         case IER_OFFSET1:
445             val = *(uint32_t *)(apic->int_en_reg + 4);
446             break;
447         case IER_OFFSET2:
448             val = *(uint32_t *)(apic->int_en_reg + 8);
449             break;
450         case IER_OFFSET3:
451             val = *(uint32_t *)(apic->int_en_reg + 12);
452             break;
453         case IER_OFFSET4:
454             val = *(uint32_t *)(apic->int_en_reg + 16);
455             break;
456         case IER_OFFSET5:
457             val = *(uint32_t *)(apic->int_en_reg + 20);
458             break;
459         case IER_OFFSET6:
460             val = *(uint32_t *)(apic->int_en_reg + 24);
461             break;
462         case IER_OFFSET7:
463             val = *(uint32_t *)(apic->int_en_reg + 28);
464             break;
465
466         case ISR_OFFSET0:
467             val = *(uint32_t *)(apic->int_svc_reg);
468             break;
469         case ISR_OFFSET1:
470             val = *(uint32_t *)(apic->int_svc_reg + 4);
471             break;
472         case ISR_OFFSET2:
473             val = *(uint32_t *)(apic->int_svc_reg + 8);
474             break;
475         case ISR_OFFSET3:
476             val = *(uint32_t *)(apic->int_svc_reg + 12);
477             break;
478         case ISR_OFFSET4:
479             val = *(uint32_t *)(apic->int_svc_reg + 16);
480             break;
481         case ISR_OFFSET5:
482             val = *(uint32_t *)(apic->int_svc_reg + 20);
483             break;
484         case ISR_OFFSET6:
485             val = *(uint32_t *)(apic->int_svc_reg + 24);
486             break;
487         case ISR_OFFSET7:
488             val = *(uint32_t *)(apic->int_svc_reg + 28);
489             break;
490    
491         case TRIG_OFFSET0:
492             val = *(uint32_t *)(apic->trig_mode_reg);
493             break;
494         case TRIG_OFFSET1:
495             val = *(uint32_t *)(apic->trig_mode_reg + 4);
496             break;
497         case TRIG_OFFSET2:
498             val = *(uint32_t *)(apic->trig_mode_reg + 8);
499             break;
500         case TRIG_OFFSET3:
501             val = *(uint32_t *)(apic->trig_mode_reg + 12);
502             break;
503         case TRIG_OFFSET4:
504             val = *(uint32_t *)(apic->trig_mode_reg + 16);
505             break;
506         case TRIG_OFFSET5:
507             val = *(uint32_t *)(apic->trig_mode_reg + 20);
508             break;
509         case TRIG_OFFSET6:
510             val = *(uint32_t *)(apic->trig_mode_reg + 24);
511             break;
512         case TRIG_OFFSET7:
513             val = *(uint32_t *)(apic->trig_mode_reg + 28);
514             break;
515
516         case IRR_OFFSET0:
517             val = *(uint32_t *)(apic->int_req_reg);
518             break;
519         case IRR_OFFSET1:
520             val = *(uint32_t *)(apic->int_req_reg + 4);
521             break;
522         case IRR_OFFSET2:
523             val = *(uint32_t *)(apic->int_req_reg + 8);
524             break;
525         case IRR_OFFSET3:
526             val = *(uint32_t *)(apic->int_req_reg + 12);
527             break;
528         case IRR_OFFSET4:
529             val = *(uint32_t *)(apic->int_req_reg + 16);
530             break;
531         case IRR_OFFSET5:
532             val = *(uint32_t *)(apic->int_req_reg + 20);
533             break;
534         case IRR_OFFSET6:
535             val = *(uint32_t *)(apic->int_req_reg + 24);
536             break;
537         case IRR_OFFSET7:
538             val = *(uint32_t *)(apic->int_req_reg + 28);
539             break;
540         case TMR_CUR_CNT_OFFSET:
541             val = apic->tmr_cur_cnt;
542             break;
543
544             // We are not going to implement these....
545         case THERM_LOC_VEC_TBL_OFFSET:
546             val = apic->therm_loc_vec_tbl.val;
547             break;
548         case PERF_CTR_LOC_VEC_TBL_OFFSET:
549             val = apic->perf_ctr_loc_vec_tbl.val;
550             break;
551
552  
553
554             // handled registers
555         case INT_CMD_LO_OFFSET:    
556             val = apic->int_cmd.lo;
557             break;
558         case INT_CMD_HI_OFFSET:
559             val = apic->int_cmd.hi;
560             break;
561
562             // handle current timer count
563
564             // Unhandled Registers
565         case EXT_INT_LOC_VEC_TBL_OFFSET0:
566         case EXT_INT_LOC_VEC_TBL_OFFSET1:
567         case EXT_INT_LOC_VEC_TBL_OFFSET2:
568         case EXT_INT_LOC_VEC_TBL_OFFSET3:
569         case EXT_APIC_FEATURE_OFFSET:
570         case EXT_APIC_CMD_OFFSET:
571         case SEOI_OFFSET:
572
573         default:
574             PrintError("Read from Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
575             return -1;
576     }
577
578
579     if (length == 1) {
580         uint_t byte_addr = reg_addr & 0x3;
581         uint8_t * val_ptr = (uint8_t *)dst;
582     
583         *val_ptr = *(((uint8_t *)&val) + byte_addr);
584
585     } else if ((length == 2) && 
586                ((reg_addr & 0x3) == 0x3)) {
587         uint_t byte_addr = reg_addr & 0x3;
588         uint16_t * val_ptr = (uint16_t *)dst;
589         *val_ptr = *(((uint16_t *)&val) + byte_addr);
590
591     } else if (length == 4) {
592         uint32_t * val_ptr = (uint32_t *)dst;
593         *val_ptr = val;
594
595     } else {
596         PrintError("Invalid apic read length (%d)\n", length);
597         return -1;
598     }
599
600     PrintDebug("Read finished (val=%x)\n", *(uint32_t *)dst);
601
602     return length;
603 }
604
605
606 static int apic_write(addr_t guest_addr, void * src, uint_t length, void * priv_data) {
607     struct vm_device * dev = (struct vm_device *)priv_data;
608     struct apic_state * apic = (struct apic_state *)dev->private_data;
609     addr_t reg_addr  = guest_addr - apic->base_addr;
610     struct apic_msr * msr = (struct apic_msr *)&(apic->base_addr_msr.value);
611     uint32_t op_val = *(uint32_t *)src;
612
613     PrintDebug("Write to apic address space (%p) (val=%x)\n", 
614                (void *)guest_addr, *(uint32_t *)src);
615
616     if (msr->apic_enable == 0) {
617         PrintError("Write to APIC address space with disabled APIC\n");
618         return -1;
619     }
620
621
622     if (length != 4) {
623         PrintError("Invalid apic write length (%d)\n", length);
624         return -1;
625     }
626
627     switch (reg_addr) {
628         case REMOTE_READ_OFFSET:
629         case APIC_VERSION_OFFSET:
630         case APR_OFFSET:
631         case IRR_OFFSET0:
632         case IRR_OFFSET1:
633         case IRR_OFFSET2:
634         case IRR_OFFSET3:
635         case IRR_OFFSET4:
636         case IRR_OFFSET5:
637         case IRR_OFFSET6:
638         case IRR_OFFSET7:
639         case ISR_OFFSET0:
640         case ISR_OFFSET1:
641         case ISR_OFFSET2:
642         case ISR_OFFSET3:
643         case ISR_OFFSET4:
644         case ISR_OFFSET5:
645         case ISR_OFFSET6:
646         case ISR_OFFSET7:
647         case TRIG_OFFSET0:
648         case TRIG_OFFSET1:
649         case TRIG_OFFSET2:
650         case TRIG_OFFSET3:
651         case TRIG_OFFSET4:
652         case TRIG_OFFSET5:
653         case TRIG_OFFSET6:
654         case TRIG_OFFSET7:
655         case PPR_OFFSET:
656         case EXT_APIC_FEATURE_OFFSET:
657 #if 1
658             PrintError("Attempting to write to read only register %p (ignored)\n", (void *)reg_addr);
659 #else   
660             PrintError("Attempting to write to read only register %p (error)\n", (void *)reg_addr);
661             return -1;
662 #endif
663             break;
664
665             // Data registers
666         case APIC_ID_OFFSET:
667             apic->lapic_id.val = op_val;
668             break;
669         case TPR_OFFSET:
670             apic->task_prio.val = op_val;
671             break;
672         case LDR_OFFSET:
673             apic->log_dst.val = op_val;
674             break;
675         case DFR_OFFSET:
676             apic->dst_fmt.val = op_val;
677             break;
678         case SPURIOUS_INT_VEC_OFFSET:
679             apic->spurious_int.val = op_val;
680             break;
681         case ESR_OFFSET:
682             apic->err_status.val = op_val;
683             break;
684         case TMR_LOC_VEC_TBL_OFFSET:
685             apic->tmr_vec_tbl.val = op_val;
686             break;
687         case THERM_LOC_VEC_TBL_OFFSET:
688             apic->therm_loc_vec_tbl.val = op_val;
689             break;
690         case PERF_CTR_LOC_VEC_TBL_OFFSET:
691             apic->perf_ctr_loc_vec_tbl.val = op_val;
692             break;
693         case LINT0_VEC_TBL_OFFSET:
694             apic->lint0_vec_tbl.val = op_val;
695             break;
696         case LINT1_VEC_TBL_OFFSET:
697             apic->lint1_vec_tbl.val = op_val;
698             break;
699         case ERR_VEC_TBL_OFFSET:
700             apic->err_vec_tbl.val = op_val;
701             break;
702         case TMR_INIT_CNT_OFFSET:
703             apic->tmr_init_cnt = op_val;
704             apic->tmr_cur_cnt = op_val;
705             break;
706         case TMR_CUR_CNT_OFFSET:
707             apic->tmr_cur_cnt = op_val;
708             break;
709         case TMR_DIV_CFG_OFFSET:
710             apic->tmr_div_cfg.val = op_val;
711             break;
712
713
714             // Enable mask (256 bits)
715         case IER_OFFSET0:
716             *(uint32_t *)(apic->int_en_reg) = op_val;
717             break;
718         case IER_OFFSET1:
719             *(uint32_t *)(apic->int_en_reg + 4) = op_val;
720             break;
721         case IER_OFFSET2:
722             *(uint32_t *)(apic->int_en_reg + 8) = op_val;
723             break;
724         case IER_OFFSET3:
725             *(uint32_t *)(apic->int_en_reg + 12) = op_val;
726             break;
727         case IER_OFFSET4:
728             *(uint32_t *)(apic->int_en_reg + 16) = op_val;
729             break;
730         case IER_OFFSET5:
731             *(uint32_t *)(apic->int_en_reg + 20) = op_val;
732             break;
733         case IER_OFFSET6:
734             *(uint32_t *)(apic->int_en_reg + 24) = op_val;
735             break;
736         case IER_OFFSET7:
737             *(uint32_t *)(apic->int_en_reg + 28) = op_val;
738             break;
739    
740
741             // Action Registers
742         case INT_CMD_LO_OFFSET:
743         case INT_CMD_HI_OFFSET:
744         case EOI_OFFSET:
745             {
746                 // do eoi
747                 apic_do_eoi(apic);
748                 break;
749             }
750             // Unhandled Registers
751         case EXT_INT_LOC_VEC_TBL_OFFSET0:
752         case EXT_INT_LOC_VEC_TBL_OFFSET1:
753         case EXT_INT_LOC_VEC_TBL_OFFSET2:
754         case EXT_INT_LOC_VEC_TBL_OFFSET3:
755         case EXT_APIC_CMD_OFFSET:
756         case SEOI_OFFSET:
757         default:
758             PrintError("Write to Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
759             return -1;
760     }
761
762     PrintDebug("Write finished\n");
763
764     return length;
765 }
766
767
768
769 /* Interrupt Controller Functions */
770
771 static int apic_intr_pending(void * private_data) {
772     struct vm_device * dev = (struct vm_device *)private_data;
773     struct apic_state * apic = (struct apic_state *)dev->private_data;
774     int i = 0;
775
776
777     // just scan the request register looking for any set bit
778     // we should probably just do this with uint64 casts 
779     for (i = 0; i < 32; i++) {
780         if (apic->int_req_reg[i] & 0xff) {
781             return 1;
782         }
783     }
784     return 0;
785 }
786
787 static int apic_get_intr_number(void * private_data) {
788     struct vm_device * dev = (struct vm_device *)private_data;
789     struct apic_state * apic = (struct apic_state *)dev->private_data;
790     int i = 0, j = 0;
791
792
793     // We iterate backwards to find the highest priority
794     for (i = 31; i >= 0; i--) {
795         uchar_t req_major = apic->int_req_reg[i];
796     
797         if (req_major & 0xff) {
798             for (j = 7; j >= 0; j--) {
799                 if ((req_major >> j) == 0x1) {
800                     return (i * 8) + j;
801                 }
802             }
803         }
804     }
805
806     return -1;
807 }
808
809 static int apic_raise_intr(void * private_data, int irq) {
810 #ifdef CRAY_XT
811     if (irq == 238) {
812         struct vm_device * dev = (struct vm_device *)private_data;
813         struct apic_state * apic = (struct apic_state *)dev->private_data;
814
815         return activate_apic_irq(apic, irq);
816     }
817 #endif
818     return 0;
819 }
820
821 static int apic_lower_intr(void * private_data, int irq) {
822     return 0;
823 }
824
825 static int apic_begin_irq(void * private_data, int irq) {
826     struct vm_device * dev = (struct vm_device *)private_data;
827     struct apic_state * apic = (struct apic_state *)dev->private_data;
828     int major_offset = (irq & ~0x00000007) >> 3;
829     int minor_offset = irq & 0x00000007;
830     uchar_t * req_location = apic->int_req_reg + major_offset;
831     uchar_t * svc_location = apic->int_svc_reg + major_offset;
832     uchar_t flag = 0x01 << minor_offset;
833
834     *svc_location |= flag;
835     *req_location &= ~flag;
836
837     return 0;
838 }
839
840
841
842 int v3_apic_raise_intr(struct vm_device * apic_dev, int intr_num) {
843     struct apic_state * apic = (struct apic_state *)apic_dev->private_data;
844     return activate_apic_irq(apic, intr_num);
845 }
846
847
848
849 /* Timer Functions */
850 static void apic_update_time(ullong_t cpu_cycles, ullong_t cpu_freq, void * priv_data) {
851     struct vm_device * dev = (struct vm_device *)priv_data;
852     struct apic_state * apic = (struct apic_state *)dev->private_data;
853     // The 32 bit GCC runtime is a pile of shit
854 #ifdef __V3_64BIT__
855     uint64_t tmr_ticks = 0;
856 #else 
857     uint32_t tmr_ticks = 0;
858 #endif
859
860     uchar_t tmr_div = *(uchar_t *)&(apic->tmr_div_cfg.val);
861     uint_t shift_num = 0;
862
863
864     // Check whether this is true:
865     //   -> If the Init count is zero then the timer is disabled
866     //      and doesn't just blitz interrupts to the CPU
867     if ((apic->tmr_init_cnt == 0) || 
868         ( (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_ONESHOT) &&
869           (apic->tmr_cur_cnt == 0))) {
870         //PrintDebug("APIC timer not yet initialized\n");
871         return;
872     }
873
874
875     switch (tmr_div) {
876         case APIC_TMR_DIV1:
877             shift_num = 0;
878             break;
879         case APIC_TMR_DIV2:
880             shift_num = 1;
881             break;
882         case APIC_TMR_DIV4:
883             shift_num = 2;
884             break;
885         case APIC_TMR_DIV8:
886             shift_num = 3;
887             break;
888         case APIC_TMR_DIV16:
889             shift_num = 4;
890             break;
891         case APIC_TMR_DIV32:
892             shift_num = 5;
893             break;
894         case APIC_TMR_DIV64:
895             shift_num = 6;
896             break;
897         case APIC_TMR_DIV128:
898             shift_num = 7;
899             break;
900         default:
901             PrintError("Invalid Timer Divider configuration\n");
902             return;
903     }
904
905     tmr_ticks = cpu_cycles >> shift_num;
906     //  PrintDebug("Timer Ticks: %p\n", (void *)tmr_ticks);
907
908     if (tmr_ticks < apic->tmr_cur_cnt) {
909         apic->tmr_cur_cnt -= tmr_ticks;
910     } else {
911         tmr_ticks -= apic->tmr_cur_cnt;
912         apic->tmr_cur_cnt = 0;
913
914         // raise irq
915         PrintDebug("Raising APIC Timer interrupt (periodic=%d) (icnt=%d) (div=%d)\n", 
916                    apic->tmr_vec_tbl.tmr_mode, apic->tmr_init_cnt, shift_num);
917         if (activate_internal_irq(apic, APIC_TMR_INT) == -1) {
918             PrintError("Could not raise Timer interrupt\n");
919         }
920     
921         if (apic->tmr_vec_tbl.tmr_mode == APIC_TMR_PERIODIC) {
922             tmr_ticks = tmr_ticks % apic->tmr_init_cnt;
923             apic->tmr_cur_cnt = apic->tmr_init_cnt - tmr_ticks;
924         }
925     }
926
927
928 }
929
930
931
932 static struct intr_ctrl_ops intr_ops = {
933     .intr_pending = apic_intr_pending,
934     .get_intr_number = apic_get_intr_number,
935     .raise_intr = apic_raise_intr,
936     .begin_irq = apic_begin_irq,
937     .lower_intr = apic_lower_intr, 
938 };
939
940
941 static struct vm_timer_ops timer_ops = {
942     .update_time = apic_update_time,
943 };
944
945
946 static int apic_init(struct vm_device * dev) {
947     struct guest_info * info = dev->vm;
948     struct apic_state * apic = (struct apic_state *)(dev->private_data);
949
950     v3_register_intr_controller(dev->vm, &intr_ops, dev);
951     v3_add_timer(dev->vm, &timer_ops, dev);
952
953     init_apic_state(apic);
954
955     v3_hook_msr(info, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev);
956
957     v3_hook_full_mem(info, apic->base_addr, apic->base_addr + PAGE_SIZE_4KB, apic_read, apic_write, dev);
958
959     return 0;
960 }
961
962 static int apic_deinit(struct vm_device * dev) {
963     struct guest_info * info = dev->vm;
964
965     v3_unhook_msr(info, BASE_ADDR_MSR);
966
967     return 0;
968 }
969
970
971 static struct vm_device_ops dev_ops = {
972     .init = apic_init,
973     .deinit = apic_deinit,
974     .reset = NULL,
975     .start = NULL,
976     .stop = NULL,
977 };
978
979
980 struct vm_device * v3_create_apic() {
981     PrintDebug("Creating APIC\n");
982
983     struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state));
984
985     struct vm_device * device = v3_create_device("APIC", &dev_ops, apic);
986   
987     return device;
988 }