Restart with just vmm rebased on master.
[akaros.git] / kern / arch / x86 / vmm / intel / vmx_cpufunc.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_CPUFUNC_H_
30 #define _VMX_CPUFUNC_H_
31
32 struct vmcs;
33
34 /*
35  * Section 5.2 "Conventions" from Intel Architecture Manual 2B.
36  *
37  *                      error
38  * VMsucceed              0
39  * VMFailInvalid          1
40  * VMFailValid            2     see also VMCS VM-Instruction Error Field
41  */
42 #define VM_SUCCESS              0
43 #define VM_FAIL_INVALID         1
44 #define VM_FAIL_VALID           2
45 #define VMX_SET_ERROR_CODE \
46         "       jnc 1f;"                                                \
47         "       mov $1, %[error];"      /* CF: error = 1 */             \
48         "       jmp 3f;"                                                \
49         "1:     jnz 2f;"                                                \
50         "       mov $2, %[error];"      /* ZF: error = 2 */             \
51         "       jmp 3f;"                                                \
52         "2:     mov $0, %[error];"                                      \
53         "3:"
54
55 /* returns 0 on success and non-zero on failure */
56 static __inline int vmxon(char *region)
57 {
58         int error;
59         uint64_t addr;
60
61         addr = PADDR(region);
62         __asm __volatile("vmxon %[addr];" VMX_SET_ERROR_CODE:[error] "=r"(error)
63                                          :[addr] "m"(*(uint64_t *) & addr)
64                                          :"memory");
65
66         return (error);
67 }
68
69 /* returns 0 on success and non-zero on failure */
70 static __inline int vmclear(struct vmcs *vmcs)
71 {
72         int error;
73         uint64_t addr;
74
75         addr = PADDR(vmcs);
76         __asm __volatile("vmclear %[addr];" VMX_SET_ERROR_CODE:[error] "=r"(error)
77                                          :[addr] "m"(*(uint64_t *) & addr)
78                                          :"memory");
79         return (error);
80 }
81
82 static __inline void vmxoff(void)
83 {
84
85         __asm __volatile("vmxoff");
86 }
87
88 static __inline void vmptrst(uint64_t * addr)
89 {
90
91         __asm __volatile("vmptrst %[addr]"::[addr] "m"(*addr):"memory");
92 }
93
94 static __inline int vmptrld(struct vmcs *vmcs)
95 {
96         int error;
97         uint64_t addr;
98
99         addr = PADDR(vmcs);
100         __asm __volatile("vmptrld %[addr];" VMX_SET_ERROR_CODE:[error] "=r"(error)
101                                          :[addr] "m"(*(uint64_t *) & addr)
102                                          :"memory");
103         return (error);
104 }
105
106 static __inline int vmwrite(uint64_t reg, uint64_t val)
107 {
108         int error;
109
110         __asm __volatile("vmwrite %[val], %[reg];"
111                                          VMX_SET_ERROR_CODE:[error] "=r"(error)
112                                          :[val] "r"(val),[reg] "r"(reg)
113                                          :"memory");
114
115         return (error);
116 }
117
118 static __inline int vmread(uint64_t r, uint64_t * addr)
119 {
120         int error;
121
122         __asm __volatile("vmread %[r], %[addr];"
123                                          VMX_SET_ERROR_CODE:[error] "=r"(error)
124                                          :[r] "r"(r),[addr] "m"(*addr)
125                                          :"memory");
126
127         return (error);
128 }
129
130 static void __inline VMCLEAR(int8_t *irq, struct vmcs *vmcs)
131 {
132         int err;
133
134         err = vmclear(vmcs);
135         if (err != 0)
136                 panic("%s: vmclear(%p) error %d", __func__, vmcs, err);
137
138         enable_irqsave(irq);
139 }
140
141 static void __inline VMPTRLD(int8_t *irq, struct vmcs *vmcs)
142 {
143         int err;
144
145         disable_irqsave(irq);
146
147         err = vmptrld(vmcs);
148         if (err != 0)
149                 panic("%s: vmptrld(%p) error %d", __func__, vmcs, err);
150 }
151
152 #define INVVPID_TYPE_ADDRESS            0UL
153 #define INVVPID_TYPE_SINGLE_CONTEXT     1UL
154 #define INVVPID_TYPE_ALL_CONTEXTS       2UL
155
156 struct invvpid_desc {
157         uint16_t vpid;
158         uint16_t _res1;
159         uint32_t _res2;
160         uint64_t linear_addr;
161 };
162
163 static void __inline invvpid(uint64_t type, struct invvpid_desc desc)
164 {
165         int error;
166         static_assert(sizeof(struct invvpid_desc) == 16);
167
168         __asm __volatile("invvpid %[desc], %[type];"
169                                          VMX_SET_ERROR_CODE:[error] "=r"(error)
170                                          :[desc] "m"(desc),[type] "r"(type)
171                                          :"memory");
172
173         if (error)
174                 panic("invvpid error %d", error);
175 }
176
177 #define INVEPT_TYPE_SINGLE_CONTEXT      1UL
178 #define INVEPT_TYPE_ALL_CONTEXTS        2UL
179 struct invept_desc {
180         uint64_t eptp;
181         uint64_t _res;
182 };
183 static void __inline invept(uint64_t type, struct invept_desc desc)
184 {
185         int error;
186         static_assert(sizeof(struct invept_desc) == 16);
187
188         __asm __volatile("invept %[desc], %[type];"
189                                          VMX_SET_ERROR_CODE:[error] "=r"(error)
190                                          :[desc] "m"(desc),[type] "r"(type)
191                                          :"memory");
192
193         if (error)
194                 panic("invept error %d", error);
195 }
196 #endif