Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


apic register definitions added
[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 #define BASE_ADDR_MSR 0x0000001B
27 #define DEFAULT_BASE_ADDR 0xfee00000
28
29 #define APIC_ID_OFFSET                    0x020
30 #define APIC_VERSION_OFFSET               0x030
31 #define TPR_OFFSET                        0x080
32 #define APR_OFFSET                        0x090
33 #define PPR_OFFSET                        0x0a0
34 #define EOI_OFFSET                        0x0b0
35 #define REMOTE_READ_OFFSET                0x0c0
36 #define LDR_OFFSET                        0x0d0
37 #define DFR_OFFSET                        0x0e0
38 #define SPURIOUS_INT_VEC_OFFSET           0x0f0
39 #define ISR_OFFSET                        0x100   // 0x100 - 0x170
40 #define TMR_OFFSET                        0x180   // 0x180 - 0x1f0
41 #define IRR_OFFSET                        0x200   // 0x200 - 0x270
42 #define ESR_OFFSET                        0x280
43 #define INT_CMD_LO_OFFSET                 0x300
44 #define INT_CMD_HI_OFFSET                 0x310
45 #define TMR_LOC_VEC_TBL_OFFSET            0x320
46 #define THERM_LOC_VEC_TBL_OFFSET          0x330
47 #define PERF_CTR_LOC_VEC_TBL_OFFSET       0x340
48 #define LINT0_VEC_TBL_OFFSET              0x350
49 #define LINT1_VEC_TBL_OFFSET              0x360
50 #define ERR_VEC_TBL_OFFSET                0x370
51 #define TMR_INIT_CNT_OFFSET               0x380
52 #define TMR_CUR_CNT_OFFSET                0x390
53 #define TMR_DIV_CFG_OFFSET                0x3e0
54 #define EXT_APIC_FEATURE_OFFSET           0x400
55 #define EXT_APIC_CMD_OFFSET               0x410
56 #define SEOI_OFFSET                       0x420
57 #define IER_OFFSET                        0x480   // 0x480 - 0x4f0
58 #define EXT_INT_LOC_VEC_TBL_OFFSET        0x500   // 0x500 - 0x530
59
60
61 struct apic_base_addr_msr {
62   union {
63     uint64_t val;
64     struct {
65       uchar_t rsvd;
66       uint_t cpu_core      : 1;
67       uint_t rsvd2         : 2;
68       uint_t apic_enable   : 1;
69       ullong_t base_addr   : 40;
70       uint_t rsvd3         : 12;
71     } __attribute__((packed));
72   } __attribute__((packed));
73 } __attribute__((packed));
74
75
76
77
78 struct apic_state {
79   addr_t base_addr;
80
81   /* MSRs */
82   v3_msr_t base_addr_msr;
83
84
85   /* memory map registers */
86
87   struct lapic_id_reg lapic_id;
88   struct apic_ver_reg apic_ver;
89   struct ext_apic_ctrl_reg ext_apic_ctrl;
90   struct local_vec_tbl_reg local_vec_tbl;
91   struct tmr_vec_tbl_reg tmr_vec_tbl;
92   struct div_cfg_reg div_cfg;
93   struct lint_vec_tbl_reg lint_vec_tbl;
94   struct perf_ctr_loc_vec_tbl_reg perf_ctr_loc_vec_tbl;
95   struct therm_loc_vec_tbl_reg therm_loc_vec_tbl;
96   struct err_vec_tbl_reg err_vec_tbl;
97   struct err_status_reg err_status;
98   struct spurious_int_reg spurious_int;
99   struct int_cmd_reg int_cmd;
100   struct loc_dst_reg loc_dst;
101   struct dst_fmt_reg dst_fmt;
102   struct arb_prio_reg arb_prio;
103   struct task_prio_reg task_prio;
104   struct proc_prio_reg proc_prio;
105   struct ext_apic_feature_reg ext_apic_feature;
106   struct spec_eoi_reg spec_eoi;
107   
108
109   uint32_t tmr_cur_cnt_reg;
110   uint32_t tmr_init_cnt_reg;
111
112
113
114   uint32_t rem_rd_data;
115
116
117   uchar_t int_req_reg[32];
118   uchar_t int_svc_reg[32];
119   uchar_t int_en_reg[32];
120   uchar_t trig_mode_reg[32];
121   
122   uint32_t eoi;
123
124
125 };
126
127
128 static int read_apic_msr(uint_t msr, v3_msr_t * dst, void * priv_data) {
129   struct vm_device * dev = (struct vm_device *)priv_data;
130   struct apic_state * apic = (struct apic_state *)dev->private_data;
131   PrintDebug("READING APIC BASE ADDR: HI=%x LO=%x\n", apic->base_addr_msr.hi, apic->base_addr_msr.lo);
132
133   return -1;
134 }
135
136
137 static int write_apic_msr(uint_t msr, v3_msr_t src, void * priv_data) {
138   //  struct vm_device * dev = (struct vm_device *)priv_data;
139   //  struct apic_state * apic = (struct apic_state *)dev->private_data;
140
141   PrintDebug("WRITING APIC BASE ADDR: HI=%x LO=%x\n", src.hi, src.lo);
142
143   return -1;
144 }
145
146
147 static int apic_read(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
148   struct vm_device * dev = (struct vm_device *)priv_data;
149   struct apic_state * apic = (struct apic_state *)dev->private_data;
150   addr_t reg_addr  = guest_addr - apic->base_addr;
151
152   if (length != 4) {
153     PrintError("Invalid apic readlength\n");
154     return -1;
155   }
156
157   switch (reg_addr) {
158   case APIC_ID_OFFSET:
159   case APIC_VERSION_OFFSET:
160   case TPR_OFFSET:
161   case APR_OFFSET:
162   case PPR_OFFSET:
163   case EOI_OFFSET:
164   case REMOTE_READ_OFFSET:
165   case LDR_OFFSET:
166   case DFR_OFFSET:
167   case SPURIOUS_INT_VEC_OFFSET:
168   case ISR_OFFSET:
169   case TMR_OFFSET:
170   case IRR_OFFSET:
171   case ESR_OFFSET:
172   case INT_CMD_LO_OFFSET:
173   case INT_CMD_HI_OFFSET:
174   case TMR_LOC_VEC_TBL_OFFSET:
175   case THERM_LOC_VEC_TBL_OFFSET:
176   case PERF_CTR_LOC_VEC_TBL_OFFSET:
177   case LINT0_VEC_TBL_OFFSET:
178   case LINT1_VEC_TBL_OFFSET:
179   case ERR_VEC_TBL_OFFSET:
180   case TMR_INIT_CNT_OFFSET:
181   case TMR_CUR_CNT_OFFSET:
182   case TMR_DIV_CFG_OFFSET:
183   case EXT_APIC_FEATURE_OFFSET:
184   case EXT_APIC_CMD_OFFSET:
185   case SEOI_OFFSET:
186   case IER_OFFSET:
187   case EXT_INT_LOC_VEC_TBL_OFFSET:
188   default:
189     PrintError("Read from Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
190     return -1;
191   }
192   return length;
193 }
194
195
196 static int apic_write(addr_t guest_addr, void * dst, uint_t length, void * priv_data) {
197   PrintDebug("Write to apic address space\n");
198   struct vm_device * dev = (struct vm_device *)priv_data;
199   struct apic_state * apic = (struct apic_state *)dev->private_data;
200   addr_t reg_addr  = guest_addr - apic->base_addr;
201
202   if (length != 4) {
203     PrintError("Invalid apic write length\n");
204     return -1;
205   }
206
207   switch (reg_addr) {
208   case APIC_ID_OFFSET:
209   case APIC_VERSION_OFFSET:
210   case TPR_OFFSET:
211   case APR_OFFSET:
212   case PPR_OFFSET:
213   case EOI_OFFSET:
214   case REMOTE_READ_OFFSET:
215   case LDR_OFFSET:
216   case DFR_OFFSET:
217   case SPURIOUS_INT_VEC_OFFSET:
218   case ISR_OFFSET:
219   case TMR_OFFSET:
220   case IRR_OFFSET:
221   case ESR_OFFSET:
222   case INT_CMD_LO_OFFSET:
223   case INT_CMD_HI_OFFSET:
224   case TMR_LOC_VEC_TBL_OFFSET:
225   case THERM_LOC_VEC_TBL_OFFSET:
226   case PERF_CTR_LOC_VEC_TBL_OFFSET:
227   case LINT0_VEC_TBL_OFFSET:
228   case LINT1_VEC_TBL_OFFSET:
229   case ERR_VEC_TBL_OFFSET:
230   case TMR_INIT_CNT_OFFSET:
231   case TMR_CUR_CNT_OFFSET:
232   case TMR_DIV_CFG_OFFSET:
233   case EXT_APIC_FEATURE_OFFSET:
234   case EXT_APIC_CMD_OFFSET:
235   case SEOI_OFFSET:
236   case IER_OFFSET:
237   case EXT_INT_LOC_VEC_TBL_OFFSET:
238   default:
239     PrintError("Write to Unhandled APIC Register: %x\n", (uint32_t)reg_addr);
240     return -1;
241   }
242
243   return length;
244 }
245
246
247 static int apic_deinit(struct vm_device * dev) {
248   struct guest_info * info = dev->vm;
249
250   v3_unhook_msr(info, BASE_ADDR_MSR);
251
252   return 0;
253 }
254
255
256 static int apic_init(struct vm_device * dev) {
257   struct guest_info * info = dev->vm;
258   struct apic_state * apic = (struct apic_state *)(dev->private_data);
259
260   apic->base_addr = DEFAULT_BASE_ADDR;
261
262   v3_hook_msr(info, BASE_ADDR_MSR, read_apic_msr, write_apic_msr, dev);
263
264   v3_hook_full_mem(info, DEFAULT_BASE_ADDR, DEFAULT_BASE_ADDR + PAGE_SIZE_4KB, apic_read, apic_write, dev);
265
266   return 0;
267 }
268
269
270
271 static struct vm_device_ops dev_ops = {
272   .init = apic_init,
273   .deinit = apic_deinit,
274   .reset = NULL,
275   .start = NULL,
276   .stop = NULL,
277 };
278
279
280 struct vm_device * v3_create_apic() {
281   PrintDebug("Creating APIC\n");
282
283   struct apic_state * apic = (struct apic_state *)V3_Malloc(sizeof(struct apic_state));
284
285   struct vm_device * device = v3_create_device("APIC", &dev_ops, apic);
286   
287   return device;
288 }