vmcall_interface.h
Go to the documentation of this file.
1 /*
2  * Bareflank Hypervisor
3  *
4  * Copyright (C) 2015 Assured Information Security, Inc.
5  * Author: Rian Quinn <quinnr@ainfosec.com>
6  * Author: Brendan Kerrigan <kerriganb@ainfosec.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #ifndef VMCALL_INTERFACE_H
24 #define VMCALL_INTERFACE_H
25 
26 #pragma pack(push, 1)
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 /*
33  * VMCall Magic Number
34  *
35  * Defines a magic number that can be defined by the user to uniquely identify
36  * both the version of the user as well as the VMM. Note that this value will
37  * change with each release of Bareflank, but should probably be manually set
38  * when creating production code.
39  */
40 #ifndef VMCALL_MAGIC_NUMBER
41 #define VMCALL_MAGIC_NUMBER 0xB045EACDACD52E22
42 #endif
43 
44 /*
45  * VMCall Version
46  *
47  * Define the version of this VMCall ABI. Note that unlike the magic number,
48  * this number only changes when this file changes.
49  */
50 #define VMCALL_VERSION 1
51 
52 /*
53  * VMCall Opcode
54  *
55  * Defines the vmcall being made. Note that these are generic vmcall opcodes,
56  * and they made be used to create actual commands to the hypervisor. For
57  * example, the registers vmcall could contain user defined instructions
58  * while the data vmcall could also contain JSON formatted instructions.
59  *
60  * Each opcode is defined below. Note that these might change as part of
61  * an updated. It's up to the user to ensure that versions match correctly.
62  */
64 {
65  /*
66  * Versions
67  *
68  * Returns version information from the hypervisor which can be used by
69  * users of the vmcall interface to ensure that their code is compatible
70  * with the VMM.
71  *
72  * @note: indexes 0x0000000000000000 -> 0x7FFFFFFFFFFFFFFF are reserved
73  * for Bareflank. The remaining indexes may be used by custom
74  * extensions for version information
75  *
76  * In:
77  * r0 = VMCALL_VERSIONS
78  * r1 = VMCALL_MAGIC_NUMBER
79  * r2 = index
80  *
81  * Out (index == VMCALL_VERSION_PROTOCOL):
82  * r1 = 0 == success, error code otherwise
83  * r2 = index
84  * r3 = VMCALL_VERSION
85  *
86  * Out (index == VMCALL_VERSION_BAREFLANK):
87  * r1 = 0 == success, error code otherwise
88  * r2 = index
89  * r3 = BAREFLANK_VERSION_MAJOR
90  * r4 = BAREFLANK_VERSION_MINOR
91  * r5 = BAREFLANK_VERSION_PATCH
92  *
93  * Out (index == VMCALL_VERSION_USER):
94  * r1 = 0 == success, error code otherwise
95  * r2 = index
96  * r3 = USER_VERSION_MAJOR
97  * r4 = USER_VERSION_MINOR
98  * r5 = USER_VERSION_PATCH
99  *
100  * Out (index > 0x8000000000000000): User-defined
101  */
103 
104  /*
105  * Raw Registers
106  *
107  * Provides a means to send to the VMM, raw register values, and
108  * return raw register values. This is a wrapper around your basic vmcall,
109  * consuming the reserved registers in the process for ABI compatibility
110  *
111  * In:
112  * r0 = VMCALL_REGISTERS
113  * r1 = VMCALL_MAGIC_NUMBER
114  * r2 = xxx
115  * ...
116  * r31 = xxx
117  *
118  * Out:
119  * r1 = 0 == success, error code otherwise
120  * r2 = xxx
121  * ...
122  * r31 = xxx
123  */
125 
126  /*
127  * Data
128  *
129  * Provides a means to send and receive binary data (page sharing). With
130  * this vmcall, an in and out buffer are provided. The VMM will map in
131  * both buffers, perform whatever operation it should, and then unmap the
132  * buffers. The type field must be provided for the input buffer, and it
133  * defines what type of data is being provided. The VMM will return data
134  * in the output buffer, and set the output type based on whatever
135  * operation it performed. The size is in bytes, but the VMM will map
136  * complete pages. If the size of the buffer is not a multiple of a page,
137  * the VMM will have access to data outside the bounds of the buffer
138  * (which may be fine depending on the use case). The uuid field is provided
139  * as a means to identify the data being sent / received. Specifically,
140  * this field can be paired with the registers vmcall to ensure that
141  * consecutive vmcalls have the proper data. For example, if an operation
142  * takes more than one vmcall to perform, and software on the CPU is
143  * threaded, the uuid field provides the VMM with a means to handle when
144  * more than one vmcall becomes interlaced. Note that the uuid field is
145  * optional. out_size contains the max size of the output buffer that
146  * is provided, but the VMM must set out_size to the actual number of
147  * bytes that it is sending back, which likely will not be the same as
148  * the output buffer going in is likely the "max" sized buffer, while the
149  * actual contents being written back are likely smaller.
150  *
151  * In:
152  * r0 = VMCALL_DATA
153  * r1 = VMCALL_MAGIC_NUMBER
154  * r2 = uuid1 (bits 0 -> 63)
155  * r3 = uuid2 (bits 64 -> 127)
156  * r4 = in_type (vmcall_data_type)
157  * r5 = in_addr (addr of virtually contiguous buffer)
158  * r6 = in_size (size of virtually contiguous buffer)
159  * r7 = out_type (vmcall_data_type)
160  * r8 = out_addr (addr of virtually contiguous buffer)
161  * r9 = out_size (size of virtually contiguous buffer)
162  *
163  * Out:
164  * r1 = 0 == success, error code otherwise
165  */
167 
168  /*
169  * Event
170  *
171  * This vmcall is used to signal and event (basically a virtual interrupt)
172  * Note that this takes a different path so it's faster than using
173  * VMCALL_REGISTERS as that call does more register copying. Also note
174  * that we provide for a success / failure on the event and it's up to the
175  * VMM extensions to decide if an event can actually fail.
176  *
177  * In:
178  * r0 = VMCALL_EVENT
179  * r1 = VMCALL_MAGIC_NUMBER
180  * r2 = index
181  *
182  * Out:
183  * r1 = 0 == success, error code otherwise
184  */
186 
187  /*
188  * Start
189  *
190  * This vmcall is used to run "start" code while the hypervisor is running.
191  * This vmcall should not be used by software and can only be used one
192  * by the bfdriver common.c
193  *
194  * In:
195  * r0 = VMCALL_START
196  * r1 = VMCALL_MAGIC_NUMBER
197  *
198  * Out:
199  * r1 = 0 == success, error code otherwise
200  */
202 
203  /*
204  * Stop
205  *
206  * This vmcall is used to run "stop" code while the hypervisor is running.
207  * This vmcall should not be used by software and can only be used one
208  * by the bfdriver common.c
209  *
210  * In:
211  * r0 = VMCALL_STOP
212  * r1 = VMCALL_MAGIC_NUMBER
213  *
214  * Out:
215  * r1 = 0 == success, error code otherwise
216  */
218 
219  /*
220  * Unit Test
221  *
222  * This vmcall is used to unit test software inside the VMM. For example,
223  * for Bareflank to ensure that supported portions of libc++ actually work
224  * inside the VMM, unit testing must be performed in the VMM itself. This
225  * vmcall does that.
226  *
227  * @note: indexes 0x0000000000000000 -> 0x7FFFFFFFFFFFFFFF are reserved
228  * for Bareflank. The remaining indexes may be used by custom
229  * extensions for their own unit tests
230  *
231  * In:
232  * r0 = VMCALL_UNITTEST
233  * r1 = VMCALL_MAGIC_NUMBER
234  * r2 = index
235  *
236  * Out:
237  * r1 = 0 == success, error code otherwise
238  */
240 };
241 
242 /*
243  * VMCall Versions
244  *
245  * Defines the different version indexes that are officially supported
246  * by Bareflank. Others may be used by the user as defined by the protocol
247  *
248  * @note: indexes 0x0000000000000000 -> 0x7FFFFFFFFFFFFFFF are reserved
249  * for Bareflank. The remaining indexes may be used by custom
250  * extensions to define their own version info
251 */
253 {
257 };
258 
259 /*
260  * VMCall Data Type
261  *
262  * Defines the different data types for data vmcall.
263  *
264  * @note: types 0x0000000000000000 -> 0x7FFFFFFFFFFFFFFF are reserved
265  * for Bareflank. The remaining types may be used by custom
266  * extensions to define their own data types
267  */
269 {
274 };
275 
276 /*
277  * VMCall Registers
278  *
279  * Defines a structure that stores each register. The register names are
280  * generic so that they can be used by different CPU architectures.
281  *
282  * Intel: (unused: rsp, rbp, rdi)
283  * r0 = rax
284  * r1 = rdx
285  * r2 = rcx
286  * r3 = rdx
287  * r4 = rsi
288  * r5 = r8
289  * r6 = r9
290  * r7 = r10
291  * r8 = r11
292  * r9 = r12
293  * r10 = r13
294  * r11 = r14
295  * r12 = r15
296  * r13 = undefined
297  * ...
298  * r31 = undefined
299  *
300  * ARM:
301  * <TBD>
302  */
304 {
305  uintptr_t r00;
306  uintptr_t r01;
307  uintptr_t r02;
308  uintptr_t r03;
309  uintptr_t r04;
310  uintptr_t r05;
311  uintptr_t r06;
312  uintptr_t r07;
313  uintptr_t r08;
314  uintptr_t r09;
315  uintptr_t r10;
316  uintptr_t r11;
317  uintptr_t r12;
318  uintptr_t r13;
319  uintptr_t r14;
320  uintptr_t r15;
321 };
322 
323 #ifdef __cplusplus
324 }
325 #endif
326 
327 #pragma pack(pop)
328 
329 #endif
vmcall_data_type
vmcall_opcode
vmcall_versions