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.


SVM Bug Fixes and Enhancements
[palacios.git] / palacios / include / palacios / vmcb.h
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 #ifndef __VMCB_H
21 #define __VMCB_H
22
23 #ifdef __V3VEE__
24
25 #include <palacios/vmm_types.h>
26 #include <palacios/vm_guest.h>
27
28 #define VMCB_CTRL_AREA_OFFSET                   0x0
29 #define VMCB_CTRL_AREA_SIZE                     0x400
30 #define VMCB_STATE_SAVE_AREA_OFFSET             0x400
31 #define VMCB_STATE_SAVE_AREA_SIZE               0x298
32 #define VMCB_END_OFFSET                         (VMCB_CTRL_AREA_SIZE+VMCB_STATE_SAVE_AREA_SIZE)
33 #define VMCB_TOTAL_SIZE                         0x1000
34
35 #define GET_VMCB_CTRL_AREA(page)         (page + VMCB_CTRL_AREA_OFFSET)
36 #define GET_VMCB_SAVE_STATE_AREA(page)   (page + VMCB_STATE_SAVE_AREA_OFFSET)
37
38
39
40 typedef void vmcb_t;
41
42
43 struct Ctrl_Registers {
44     uint_t cr0        : 1;
45     uint_t cr1        : 1;
46     uint_t cr2        : 1;
47     uint_t cr3        : 1;
48     uint_t cr4        : 1;
49     uint_t cr5        : 1;
50     uint_t cr6        : 1;
51     uint_t cr7        : 1;
52     uint_t cr8        : 1;
53     uint_t cr9        : 1;
54     uint_t cr10       : 1;
55     uint_t cr11       : 1;
56     uint_t cr12       : 1;
57     uint_t cr13       : 1;
58     uint_t cr14       : 1;
59     uint_t cr15       : 1;
60 } __attribute__((packed));
61
62
63 struct Debug_Registers {
64     uint_t dr0        : 1;
65     uint_t dr1        : 1;
66     uint_t dr2        : 1;
67     uint_t dr3        : 1;
68     uint_t dr4        : 1;
69     uint_t dr5        : 1;
70     uint_t dr6        : 1;
71     uint_t dr7        : 1;
72     uint_t dr8        : 1;
73     uint_t dr9        : 1;
74     uint_t dr10       : 1;
75     uint_t dr11       : 1;
76     uint_t dr12       : 1;
77     uint_t dr13       : 1;
78     uint_t dr14       : 1;
79     uint_t dr15       : 1;
80 } __attribute__((packed));
81
82
83 struct Exception_Vectors {
84     uint_t de          : 1; // (0) divide by zero
85     uint_t db          : 1; // (1) Debug
86     uint_t nmi         : 1; // (2) Non-maskable interrupt
87     uint_t bp          : 1; // (3) Breakpoint
88     uint_t of          : 1; // (4) Overflow
89     uint_t br          : 1; // (5) Bound-Range
90     uint_t ud          : 1; // (6) Invalid-Opcode
91     uint_t nm          : 1; // (7) Device-not-available
92     uint_t df          : 1; // (8) Double Fault
93     uint_t ex9         : 1; 
94     uint_t ts          : 1; // (10) Invalid TSS
95     uint_t np          : 1; // (11) Segment-not-present
96     uint_t ss          : 1; // (12) Stack
97     uint_t gp          : 1; // (13) General Protection Fault
98     uint_t pf          : 1; // (14) Page fault
99     uint_t ex15        : 1;
100     uint_t mf          : 1; // (15) Floating point exception
101     uint_t ac          : 1; // (16) Alignment-check
102     uint_t mc          : 1; // (17) Machine Check
103     uint_t xf          : 1; // (18) SIMD floating-point
104     uint_t ex20        : 1;
105     uint_t ex21        : 1;
106     uint_t ex22        : 1;
107     uint_t ex23        : 1;
108     uint_t ex24        : 1;
109     uint_t ex25        : 1;
110     uint_t ex26        : 1;
111     uint_t ex27        : 1;
112     uint_t ex28        : 1;
113     uint_t ex29        : 1;
114     uint_t sx          : 1; // (30) Security Exception
115     uint_t ex31        : 1;
116 } __attribute__((packed));
117
118
119 struct Instr_Intercepts {
120     uint_t INTR        : 1;
121     uint_t NMI         : 1;
122     uint_t SMI         : 1;
123     uint_t INIT        : 1;
124     uint_t VINTR       : 1;
125     uint_t CR0         : 1;
126     uint_t RD_IDTR     : 1;
127     uint_t RD_GDTR     : 1;
128     uint_t RD_LDTR     : 1;
129     uint_t RD_TR       : 1;
130     uint_t WR_IDTR     : 1;
131     uint_t WR_GDTR     : 1;
132     uint_t WR_LDTR     : 1;
133     uint_t WR_TR       : 1;
134     uint_t RDTSC       : 1;
135     uint_t RDPMC       : 1;
136     uint_t PUSHF       : 1;
137     uint_t POPF        : 1;
138     uint_t CPUID       : 1;
139     uint_t RSM         : 1;
140     uint_t IRET        : 1;
141     uint_t INTn        : 1;
142     uint_t INVD        : 1;
143     uint_t PAUSE       : 1;
144     uint_t HLT         : 1;
145     uint_t INVLPG      : 1;
146     uint_t INVLPGA     : 1;
147     uint_t IOIO_PROT   : 1;
148     uint_t MSR_PROT    : 1;
149     uint_t task_switch : 1;
150     uint_t FERR_FREEZE : 1;
151     uint_t shutdown_evts: 1;
152 } __attribute__((packed));
153
154 struct SVM_Instr_Intercepts { 
155     uint_t VMRUN      : 1;
156     uint_t VMMCALL    : 1;
157     uint_t VMLOAD     : 1;
158     uint_t VMSAVE     : 1;
159     uint_t STGI       : 1;
160     uint_t CLGI       : 1;
161     uint_t SKINIT     : 1;
162     uint_t RDTSCP     : 1;
163     uint_t ICEBP      : 1;
164     uint_t WBINVD     : 1;
165     uint_t MONITOR    : 1;
166     uint_t MWAIT_always : 1;
167     uint_t MWAIT_if_armed : 1;
168     uint_t XSETBV  : 1;
169     uint_t reserved  : 18;  // Should be 0
170 } __attribute__((packed));
171
172
173 struct Guest_Control {
174     uchar_t V_TPR;
175     uint_t V_IRQ      : 1;
176     uint_t rsvd1      : 7;  // Should be 0
177     uint_t V_INTR_PRIO : 4;
178     uint_t V_IGN_TPR  : 1;
179     uint_t rsvd2      : 3;  // Should be 0
180     uint_t V_INTR_MASKING : 1;
181     uint_t rsvd3      : 6;  // Should be 0
182     uint_t AVIC_enable : 1;
183     uchar_t V_INTR_VECTOR;
184     uint_t rsvd4      : 24;  // Should be 0
185 } __attribute__((packed));
186
187 #define SVM_INJECTION_IRQ  0
188 #define SVM_INJECTION_NMI           2
189 #define SVM_INJECTION_EXCEPTION     3
190 #define SVM_INJECTION_SOFT_INTR     4
191
192 struct Interrupt_Info {
193     uint_t vector       : 8;
194     uint_t type         : 3;
195     uint_t ev           : 1;
196     uint_t rsvd         : 19;
197     uint_t valid        : 1;
198     uint_t error_code   : 32;
199 } __attribute__((packed));
200
201
202
203 struct VMCB_Control_Area {
204     // offset 0x000
205     struct Ctrl_Registers cr_reads;
206     struct Ctrl_Registers cr_writes;
207     // offset 0x004
208     struct Debug_Registers dr_reads;
209     struct Debug_Registers dr_writes;
210     // offset 0x008
211     struct Exception_Vectors exceptions;
212     // offset 0x00c
213     struct Instr_Intercepts instrs;
214     // offset 0x010
215     struct SVM_Instr_Intercepts svm_instrs;
216
217     // offset 0x014
218     uchar_t rsvd1[40];  // Should be 0
219
220     // offset 0x03c
221     uint16_t pause_filter_threshold;
222     uint16_t pause_filter_count;
223
224     // offset 0x040
225     ullong_t IOPM_BASE_PA;
226     ullong_t MSRPM_BASE_PA;
227     ullong_t TSC_OFFSET;
228     
229     // offset 0x058
230     uint_t guest_ASID;
231     uchar_t TLB_CONTROL;
232
233     uchar_t rsvd2[3];  // Should be 0
234
235     // offset 0x060
236     struct Guest_Control guest_ctrl;
237   
238     // offset 0x068
239     uint_t   interrupt_shadow  : 1;
240     uint64_t rsvd3             : 63;  // Should be 0
241
242     // offset 0x070
243     ullong_t exit_code;
244     ullong_t exit_info1;
245     ullong_t exit_info2;
246
247     // offset 0x088
248     struct Interrupt_Info exit_int_info;
249
250     // offset 0x090
251     uint_t NP_ENABLE : 1;
252     uint64_t rsvd4 : 63;
253
254     // offet 0x098
255     uint64_t AVIC_APIC_BAR: 52;
256     uint64_t rsvd5 : 12;
257
258     // offset 0x0a0
259     uchar_t rsvd6[8];  // Should be 0
260
261     // offset 0x0a8
262     struct Interrupt_Info EVENTINJ;
263
264     // offset 0x0b0
265     ullong_t N_CR3;
266
267     // offset 0x0b8
268     uint_t LBR_VIRTUALIZATION_ENABLE : 1;
269     ullong_t rsvd7            : 63;   // Should be 0
270
271     // offset 0x0c0
272     uint32_t clean_bits;         // used for VMCB caching  
273     uint32_t rsvd8;
274     
275     // offset 0x0c8
276     uint64_t nrip;         
277
278     // offset 0x0d0
279     // fetch of instruction
280     uint8_t  num_ifetch_bytes; 
281     uint8_t  ifetch_bytes[15];
282     
283     // offset 0x0e0
284     uint64_t AVIC_APIC_backing_page : 52; // page-aligned
285     uint64_t rsvd9 : 12;
286     
287     // offset 0x0e8
288     uint64_t rsvd10;
289
290     // offset 0x0f0
291     uint64_t AVIC_logical_table : 52; // page-aligned
292     uint64_t rsvd11 : 12;
293     
294     // offset 0xf8
295     uint8_t AVIC_PHYSICAL_MAX_INDEX;
296     uint8_t rsvd12: 4;
297     uint64_t AVIC_PHYSICAL_TABLE_PTR: 40; // page-aligned
298     uint64_t rsvd13: 12; 
299
300     // offset 0x100 space from here to 0x3ff should be zero
301     uint8_t  rsvd_tail[VMCB_CTRL_AREA_SIZE-0x100];
302
303 } __attribute__((packed));
304
305
306 typedef struct VMCB_Control_Area vmcb_ctrl_t;
307
308
309
310
311
312
313 struct vmcb_selector {
314     uint16_t selector;
315
316     /* These attributes are basically a direct map of the attribute fields of a segment desc.
317      * The segment limit in the middle is removed and the fields are fused together
318      * There IS empty space at the end... See AMD Arch vol3, sect. 4.7.1,  pg 78
319      */
320     union {
321         ushort_t raw;
322         struct {
323             uint_t type              : 4; // segment type, [see Intel vol. 3b, sect. 3.4.5.1 (because I have the books)]
324             uint_t S                 : 1; // System=0, code/data=1
325             uint_t dpl               : 2; // priviledge level, corresonds to protection ring
326             uint_t P                 : 1; // present flag
327             uint_t avl               : 1; // available for use by system software
328             uint_t L                 : 1; // long mode (64 bit?)
329             uint_t db                : 1; // default op size (0=16 bit seg, 1=32 bit seg)
330             uint_t G                 : 1; // Granularity, (0=bytes, 1=4k)
331             uint_t rsvd              : 4;
332         }  __attribute__((packed)) fields;
333     }  __attribute__((packed)) attrib;
334
335     uint32_t  limit;
336     uint64_t base;
337 }  __attribute__((packed));
338
339
340 struct VMCB_State_Save_Area {
341     struct vmcb_selector es; // only lower 32 bits of base are implemented
342     struct vmcb_selector cs; // only lower 32 bits of base are implemented
343     struct vmcb_selector ss; // only lower 32 bits of base are implemented
344     struct vmcb_selector ds; // only lower 32 bits of base are implemented
345     struct vmcb_selector fs; 
346     struct vmcb_selector gs; 
347
348     struct vmcb_selector gdtr; // selector+attrib are reserved, only lower 16 bits of limit are implemented
349     struct vmcb_selector ldtr; 
350     struct vmcb_selector idtr; // selector+attrib are reserved, only lower 16 bits of limit are implemented
351     struct vmcb_selector tr; 
352
353     uchar_t rsvd1[43];
354
355     //offset 0x0cb
356     uchar_t cpl; // if the guest is real-mode then the CPL is forced to 0
357     // if the guest is virtual-mode then the CPL is forced to 3
358
359     uint_t rsvd2;
360
361     // offset 0x0d0
362     ullong_t efer;
363
364     uchar_t rsvd3[112];
365   
366     //offset 0x148
367     ullong_t cr4;
368     ullong_t cr3;
369     ullong_t cr0;
370     ullong_t dr7;
371     ullong_t dr6;
372     ullong_t rflags;
373     ullong_t rip;
374
375     uchar_t rsvd4[88];
376   
377     //offset 0x1d8
378     ullong_t rsp;
379
380     uchar_t rsvd5[24];
381
382     //offset 0x1f8
383     ullong_t rax;
384     ullong_t star;
385     ullong_t lstar;
386     ullong_t cstar;
387     ullong_t sfmask;
388     ullong_t KernelGsBase;
389     ullong_t sysenter_cs;
390     ullong_t sysenter_esp;
391     ullong_t sysenter_eip;
392     ullong_t cr2;
393
394
395     uchar_t rsvd6[32];
396
397     //offset 0x268
398     ullong_t g_pat; // Guest PAT                     
399     //   -- only used if nested paging is enabled
400     ullong_t dbgctl; // Guest DBGCTL MSR               
401     //   -- only used if the LBR registers are virtualized
402     ullong_t br_from; // Guest LastBranchFromIP MSR
403     //   -- only used if the LBR registers are virtualized
404     ullong_t br_to; // Guest LastBranchToIP MSR   
405     //   -- only used if the LBR registers are virtualized
406     ullong_t lastexcpfrom; // Guest LastExceptionFromIP MSR
407     //   -- only used if the LBR registers are virtualized
408     ullong_t lastexcpto; // Guest LastExceptionToIP MSR 
409     //   -- only used if the LBR registers are virtualized
410
411     // offset 0x298
412     // Remainder to end of page is reserved and zero
413 } __attribute__((packed));
414
415
416 typedef struct VMCB_State_Save_Area vmcb_saved_state_t;
417
418 void PrintDebugVMCB(vmcb_t * vmcb);
419
420
421 void v3_set_vmcb_segments(vmcb_t * vmcb, struct v3_segments * segs);
422 void v3_get_vmcb_segments(vmcb_t * vmcb, struct v3_segments * segs);
423
424 #endif // ! __V3VEE__
425
426 #endif