1/**
2 * \file
3 */
4
5/*
6 * Copyright (c) 2009, ETH Zurich.
7 * All rights reserved.
8 *
9 * This file is distributed under the terms in the attached LICENSE file.
10 * If you do not find this file, copies can be found by writing to:
11 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
12 */
13
14#ifndef GUEST_H
15#define GUEST_H
16
17#include <barrelfish/barrelfish.h>
18#include <barrelfish_kpi/vmx_encodings.h>
19#include <spawndomain/spawndomain.h>
20#include <barrelfish_kpi/vmkit.h>
21#include <dev/amd_vmcb_dev.h>
22
23struct guest {
24    // indicates whether the guest is runnable atm or waiting
25    bool                    runnable;
26    // Monitor endpoint for this guest
27    struct lmp_endpoint     *monitor_ep;
28    // The allocator for the slot this guests uses
29    struct multi_slot_allocator slot_alloc;
30    // VMCB data
31    struct capref           vmcb_cap;
32    lpaddr_t                 vmcb_pa;
33    lvaddr_t                 vmcb_va;
34    // guest control data
35    struct capref           ctrl_cap;
36    struct guest_control    *ctrl;
37    // IOPM data (IO port access)
38#ifdef CONFIG_SVM
39    struct capref           iopm_cap;
40    lpaddr_t                 iopm_pa;
41    lvaddr_t                 iopm_va;
42#else
43     struct capref iobmp_a_cap;
44     lpaddr_t iobmp_a_pa;
45     lvaddr_t iobmp_a_va;
46
47     struct capref iobmp_b_cap;
48     lpaddr_t iobmp_b_pa;
49     lvaddr_t iobmp_b_va;
50#endif
51    // MSRPM data (MSR access)
52    struct capref           msrpm_cap;
53    lpaddr_t                 msrpm_pa;
54    lvaddr_t                 msrpm_va;
55    // Mackerel data structure to VMCV
56    amd_vmcb_t              vmcb;
57    // Guest dispatcher
58    struct capref           dcb_cap;
59    // Guests physical address space (virtual to the domain)
60    struct vspace           *vspace;
61    lpaddr_t		    pml4_pa;
62    // Guest physical memory
63    lvaddr_t                 mem_low_va;
64    lvaddr_t                 mem_high_va;
65    // indicates whether the guest was in emulation before the exit
66    bool                    emulated_before_exit;
67    // virtual hardware
68    struct hdd              *hdds[8];
69    size_t                  hdd_count;
70    struct console          *console;
71    struct pc16550d         *serial_ports[4];
72    size_t                  serial_port_count;
73    struct apic             *apic;
74    struct lpc              *lpc;
75    struct pci              *pci;
76    // some settings which belong to an upcomming CPU abstraction
77    bool                    a20_gate_enabled;
78};
79
80/**
81 * \brief This enum is used to indicate the size of operands to some operations.
82 */
83enum opsize {
84    OPSIZE_8,
85    OPSIZE_16,
86    OPSIZE_32,
87    OPSIZE_64
88};
89
90extern lvaddr_t guest_offset;
91static inline lvaddr_t
92        host_to_guest (lvaddr_t addr)
93{
94    return addr - guest_offset;
95}
96
97static inline lvaddr_t
98        guest_to_host (lvaddr_t addr)
99{
100    return addr + guest_offset;
101}
102
103// REGISTER ACCESS HELPERS
104
105// RAX
106
107static inline uint64_t
108guest_get_rax (struct guest *g)
109{
110    return amd_vmcb_rax_rd(&g->vmcb);
111}
112
113static inline void
114guest_set_rax (struct guest *g, uint64_t val)
115{
116    amd_vmcb_rax_wr(&g->vmcb, val);
117}
118
119static inline uint32_t
120guest_get_eax (struct guest *g)
121{
122    return amd_vmcb_rax_rd(&g->vmcb) & 0xffffffff;
123}
124
125static inline void
126guest_set_eax (struct guest *g, uint32_t val)
127{
128    uint64_t buf = amd_vmcb_rax_rd(&g->vmcb);
129    buf = (buf & ~0xffffffff) | val;
130    amd_vmcb_rax_wr(&g->vmcb, buf);
131}
132
133static inline uint16_t
134guest_get_ax (struct guest *g)
135{
136    return amd_vmcb_rax_rd(&g->vmcb) & 0xffff;
137}
138
139static inline void
140guest_set_ax (struct guest *g, uint16_t val)
141{
142    uint64_t buf = amd_vmcb_rax_rd(&g->vmcb);
143    buf = (buf & ~0xffff) | val;
144    amd_vmcb_rax_wr(&g->vmcb, buf);
145}
146
147static inline uint8_t
148guest_get_ah (struct guest *g)
149{
150    return amd_vmcb_rax_rd(&g->vmcb) >> 8;
151}
152
153static inline void
154guest_set_ah (struct guest *g, uint8_t val)
155{
156    uint64_t buf = amd_vmcb_rax_rd(&g->vmcb);
157    buf = (buf & ~0xff00) | ((uint64_t)val) << 8;
158    amd_vmcb_rax_wr(&g->vmcb, buf);
159}
160
161static inline uint8_t
162guest_get_al (struct guest *g)
163{
164    return amd_vmcb_rax_rd(&g->vmcb);
165}
166
167static inline void
168guest_set_al (struct guest *g, uint8_t val)
169{
170    uint64_t buf = amd_vmcb_rax_rd(&g->vmcb);
171    buf = (buf & ~0xff) | val;
172    amd_vmcb_rax_wr(&g->vmcb, buf);
173}
174
175
176// RBX
177
178static inline uint64_t
179guest_get_rbx (struct guest *g)
180{
181    return g->ctrl->regs.rbx;
182}
183
184static inline void
185guest_set_rbx (struct guest *g, uint64_t val)
186{
187    g->ctrl->regs.rbx = val;
188}
189
190static inline uint32_t
191guest_get_ebx (struct guest *g) {
192    return g->ctrl->regs.rbx;
193}
194
195static inline void
196guest_set_ebx (struct guest *g, uint32_t val) {
197    uint64_t buf = g->ctrl->regs.rbx;
198    g->ctrl->regs.rbx = (buf & ~0xffffffff) | val;
199}
200
201static inline uint16_t
202guest_get_bx (struct guest *g)
203{
204    return g->ctrl->regs.rbx & 0xffff;
205}
206
207static inline void
208guest_set_bx (struct guest *g, uint16_t val)
209{
210    uint64_t buf = g->ctrl->regs.rbx;
211    g->ctrl->regs.rbx = (buf & ~0xffff) | val;
212}
213
214static inline uint8_t
215guest_get_bl (struct guest *g)
216{
217    return g->ctrl->regs.rbx & 0xff;
218}
219
220static inline void
221guest_set_bl (struct guest *g, uint8_t val)
222{
223    uint64_t buf = g->ctrl->regs.rbx;
224    g->ctrl->regs.rbx = (buf & ~0xff) | val;
225}
226
227static inline uint8_t
228guest_get_bh (struct guest *g)
229{
230    return g->ctrl->regs.rbx >> 8;
231}
232
233static inline void
234guest_set_bh (struct guest *g, uint8_t val)
235{
236    uint64_t buf = g->ctrl->regs.rbx;
237    g->ctrl->regs.rbx = (buf & ~0xff00) | ((uint64_t)val) << 8;
238}
239
240
241// RCX
242
243static inline uint64_t
244guest_get_rcx (struct guest *g)
245{
246    return g->ctrl->regs.rcx;
247}
248
249static inline void
250guest_set_rcx (struct guest *g, uint64_t val)
251{
252    g->ctrl->regs.rcx = val;
253}
254
255static inline uint32_t
256guest_get_ecx (struct guest *g) {
257    return g->ctrl->regs.rcx;
258}
259
260static inline void
261guest_set_ecx (struct guest *g, uint32_t val) {
262    uint64_t buf = g->ctrl->regs.rcx;
263    g->ctrl->regs.rcx = (buf & ~0xffffffff) | val;
264}
265
266static inline uint16_t
267guest_get_cx (struct guest *g)
268{
269    return g->ctrl->regs.rcx & 0xffff;
270}
271
272static inline void
273guest_set_cx (struct guest *g, uint16_t val)
274{
275    uint64_t buf = g->ctrl->regs.rcx;
276    g->ctrl->regs.rcx = (buf & ~0xffff) | val;
277}
278
279static inline uint8_t
280guest_get_ch (struct guest *g)
281{
282    return g->ctrl->regs.rcx >> 8;
283}
284
285static inline void
286guest_set_ch (struct guest *g, uint8_t val)
287{
288    uint64_t buf = g->ctrl->regs.rcx;
289    g->ctrl->regs.rcx = (buf & ~0xff00) | ((uint64_t)val) << 8;
290}
291
292static inline uint8_t
293guest_get_cl (struct guest *g)
294{
295    return g->ctrl->regs.rcx;
296}
297
298static inline void
299guest_set_cl (struct guest *g, uint8_t val)
300{
301    uint64_t buf = g->ctrl->regs.rcx;
302    buf = (buf & ~0xff) | val;
303    g->ctrl->regs.rcx = val;
304}
305
306
307// RDX
308
309static inline uint64_t
310guest_get_rdx (struct guest *g)
311{
312    return g->ctrl->regs.rdx;
313}
314
315static inline void
316guest_set_rdx (struct guest *g, uint64_t val)
317{
318    g->ctrl->regs.rdx = val;
319}
320
321static inline uint32_t
322guest_get_edx (struct guest *g) {
323    return g->ctrl->regs.rdx;
324}
325
326static inline void
327guest_set_edx (struct guest *g, uint32_t val) {
328    uint64_t buf = g->ctrl->regs.rdx;
329    g->ctrl->regs.rdx = (buf & ~0xffffffff) | val;
330}
331
332static inline uint8_t
333guest_get_dh (struct guest *g)
334{
335    return g->ctrl->regs.rdx >> 8;
336}
337
338static inline void
339guest_set_dh (struct guest *g, uint8_t val)
340{
341    uint64_t buf = g->ctrl->regs.rdx;
342    g->ctrl->regs.rdx = (buf & ~0xff00) | ((uint64_t)val) << 8;
343}
344
345static inline uint8_t
346guest_get_dl (struct guest *g)
347{
348    return g->ctrl->regs.rdx & 0xff;
349}
350
351static inline void
352guest_set_dl (struct guest *g, uint8_t val)
353{
354    uint64_t buf = g->ctrl->regs.rdx;
355    g->ctrl->regs.rdx = (buf & ~0xff) | val;
356}
357
358
359// RDI
360
361static inline uint64_t
362guest_get_rdi (struct guest *g)
363{
364    return g->ctrl->regs.rdi;
365}
366
367static inline void
368guest_set_rdi (struct guest *g, uint64_t val)
369{
370    g->ctrl->regs.rdi = val;
371}
372
373static inline uint16_t
374guest_get_di (struct guest *g)
375{
376    return g->ctrl->regs.rdi & 0xffff;
377}
378
379static inline void
380guest_set_di (struct guest *g, uint16_t val)
381{
382    uint64_t buf = g->ctrl->regs.rdi;
383    g->ctrl->regs.rdi = (buf & ~0xffff) | val;
384}
385
386
387// RSI
388
389static inline uint64_t
390guest_get_rsi (struct guest *g)
391{
392    return g->ctrl->regs.rsi;
393}
394
395static inline void
396guest_set_rsi (struct guest *g, uint64_t val)
397{
398    g->ctrl->regs.rsi = val;
399}
400
401static inline uint16_t
402guest_get_si (struct guest *g)
403{
404    return g->ctrl->regs.rsi & 0xffff;
405}
406
407static inline void
408guest_set_si (struct guest *g, uint16_t val)
409{
410    uint64_t buf = g->ctrl->regs.rsi;
411    g->ctrl->regs.rsi = (buf & ~0xffff) | val;
412}
413
414
415// RSP
416
417static inline uint64_t
418guest_get_rsp (struct guest *g)
419{
420    return amd_vmcb_rsp_rd(&g->vmcb);
421}
422
423static inline void
424guest_set_rsp (struct guest *g, uint64_t val)
425{
426    amd_vmcb_rsp_wr(&g->vmcb, val);
427}
428
429
430// RBP
431
432static inline uint64_t
433guest_get_rbp (struct guest *g)
434{
435    return g->ctrl->regs.rbp;
436}
437
438static inline void
439guest_set_rbp (struct guest *g, uint64_t val)
440{
441    g->ctrl->regs.rbp = val;
442}
443
444
445struct guest *guest_create (void);
446errval_t guest_make_runnable (struct guest *g, bool run);
447void guest_handle_vmexit (struct guest *g);
448void spawn_guest_domain (struct guest *self, struct spawninfo *si);
449
450#endif // GUEST_H
451