Restart with just vmm rebased on master.
[akaros.git] / kern / arch / x86 / vmm / intel / vmx.h
1 /*-
2  * Copyright (c) 2011 NetApp, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #ifndef _VMX_H_
30 #define _VMX_H_
31
32 struct vmxctx {
33         uint64_t guest_rdi;             /* Guest state */
34         uint64_t guest_rsi;
35         uint64_t guest_rdx;
36         uint64_t guest_rcx;
37         uint64_t guest_r8;
38         uint64_t guest_r9;
39         uint64_t guest_rax;
40         uint64_t guest_rbx;
41         uint64_t guest_rbp;
42         uint64_t guest_r10;
43         uint64_t guest_r11;
44         uint64_t guest_r12;
45         uint64_t guest_r13;
46         uint64_t guest_r14;
47         uint64_t guest_r15;
48         uint64_t guest_cr2;
49
50         uint64_t host_r15;              /* Host state */
51         uint64_t host_r14;
52         uint64_t host_r13;
53         uint64_t host_r12;
54         uint64_t host_rbp;
55         uint64_t host_rsp;
56         uint64_t host_rbx;
57         /*
58          * XXX todo debug registers and fpu state
59          */
60
61         int inst_fail_status;
62
63         /*
64          * The pmap needs to be deactivated in vmx_enter_guest()
65          * so keep a copy of the 'pmap' in each vmxctx.
66         struct pmap *pmap;
67          */
68         // For Akaros. The pmap did not apply directly, but struct proc * is right.
69         struct proc *p;
70 };
71
72 struct vmxcap {
73         int set;
74         uint32_t proc_ctls;
75         uint32_t proc_ctls2;
76 };
77
78 struct vmxstate {
79         uint64_t nextrip;                       /* next instruction to be executed by guest */
80         int lastcpu;                            /* host cpu that this 'vcpu' last ran on */
81         uint16_t vpid;
82 };
83
84 // TODO: akaros: merge all our various apic structs. 
85 struct apic_page {
86         uint32_t reg[PAGE_SIZE / 4];
87 };
88
89 /* Posted Interrupt Descriptor (described in section 29.6 of the Intel SDM) */
90 struct pir_desc {
91         atomic_t pir[4];
92         atomic_t pending;
93         uint64_t unused[3];
94 } __attribute__((aligned(64)));
95
96 /* Index into the 'guest_msrs[]' array */
97 enum {
98         IDX_MSR_LSTAR,
99         IDX_MSR_CSTAR,
100         IDX_MSR_STAR,
101         IDX_MSR_SYSCALL_MASK,
102         IDX_MSR_KERNEL_GS_BASE,
103         GUEST_MSR_NUM                           /* must be the last enumeration */
104 };
105
106 struct msr_bitmap {
107         char bitmap[PAGE_SIZE]; 
108 } __attribute__ ((aligned(PAGE_SIZE)));
109 /* virtual machine softc */
110 // TODO: this has to go somewhere is we make VMs a flavor of an MCP, as we hope to do.
111 struct vmx {
112         struct vmcs vmcs[MAX_NUM_CPUS]; /* one vmcs per virtual cpu */
113         struct apic_page apic_page[MAX_NUM_CPUS];       /* one apic page per vcpu */
114         struct msr_bitmap msr_bitmap;
115         struct pir_desc pir_desc[MAX_NUM_CPUS];
116         uint64_t guest_msrs[MAX_NUM_CPUS][GUEST_MSR_NUM];
117         struct vmxctx ctx[MAX_NUM_CPUS];
118         struct vmxcap cap[MAX_NUM_CPUS];
119         struct vmxstate state[MAX_NUM_CPUS];
120         uint64_t eptp;
121         struct vm *vm;
122         long eptgen[MAX_NUM_CPUS];      /* cached pmap->pm_eptgen */
123 };
124
125 #define VMX_GUEST_VMEXIT        0
126 #define VMX_VMRESUME_ERROR      1
127 #define VMX_VMLAUNCH_ERROR      2
128 #define VMX_INVEPT_ERROR        3
129
130 // This is here solely to make all the static asserts work. Hack. But those
131 // are very useful functions. 
132 // TODO: there HAS to be a better way ...
133 static void __1(void) {
134         static_assert((offsetof(struct vmx, pir_desc[0]) & 63) == 0);
135         // should not fail  but does ... TODO Akaros
136         //static_assert((offsetof(struct vmx, msr_bitmap) & PAGE_MASK) == 0);
137         static_assert((offsetof(struct vmx, vmcs) & PAGE_MASK) == 0);
138         static_assert(sizeof(struct pir_desc) == 64);
139         static_assert(sizeof(struct apic_page) == PAGE_SIZE);
140 }
141
142 int vmx_enter_guest(struct vmxctx *ctx, struct vmx *vmx, int launched);
143 void vmx_call_isr(uintptr_t entry);
144
145 unsigned long vmx_fix_cr0(unsigned long cr0);
146 unsigned long vmx_fix_cr4(unsigned long cr4);
147
148 extern char vmx_exit_guest[];
149
150 #endif