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, Universitaetstrasse 6, 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#ifdef CONFIG_SVM
22#include <dev/amd_vmcb_dev.h>
23#else
24#include "vmx.h"
25#endif
26
27#include <if/hyper_defs.h>
28
29#define G_NAME_LEN 64
30struct guest {
31    char name[G_NAME_LEN];
32    uint64_t dispframe; // unique identifier for this guest
33    // indicates whether the guest is runnable atm or waiting
34    bool                    runnable;
35    // Monitor endpoint for this guest
36    struct lmp_endpoint     *monitor_ep;
37    // The allocator for the slot this guests uses
38    struct multi_slot_allocator slot_alloc;
39    // VMCB data
40    struct capref           vmcb_cap;
41    lpaddr_t                 vmcb_pa;
42    lvaddr_t                 vmcb_va;
43    // guest control data
44    struct capref           ctrl_cap;
45    struct guest_control    *ctrl;
46    // IOPM data (IO port access)
47#ifdef CONFIG_SVM
48    struct capref           iopm_cap;
49    lpaddr_t                 iopm_pa;
50    lvaddr_t                 iopm_va;
51#else
52    // I/O bitmap A
53    struct capref iobmp_a_cap;
54    lpaddr_t iobmp_a_pa;
55    lvaddr_t iobmp_a_va;
56
57    // I/O bitmap B
58    struct capref iobmp_b_cap;
59    lpaddr_t iobmp_b_pa;
60    lvaddr_t iobmp_b_va;
61
62    // Guest MSR store/load area
63    struct capref msr_area_cap;
64    lpaddr_t msr_area_pa;
65    lvaddr_t msr_area_va;
66#endif
67    // MSRPM data (MSR access)
68    struct capref           msrpm_cap;
69    lpaddr_t                 msrpm_pa;
70    lvaddr_t                 msrpm_va;
71#ifdef CONFIG_SVM
72    // Mackerel data structure to VMCV
73    amd_vmcb_t              vmcb;
74#endif
75    // Guest dispatcher
76    struct capref           dcb_cap;
77    // Guests physical address space (virtual to the domain)
78    struct vspace           *vspace;
79    genvaddr_t              pml4; // if we're doing unmanaged ept mgmt
80    lpaddr_t		    pml4_pa;
81    // Guest physical memory
82    lvaddr_t                 mem_low_va;
83    lvaddr_t                 mem_high_va;
84    // indicates whether the guest was in emulation before the exit
85    bool                    emulated_before_exit;
86    // virtual hardware
87    struct hdd              *hdds[8];
88    size_t                  hdd_count;
89    struct console          *console;
90    struct pc16550d         *serial_ports[4];
91    size_t                  serial_port_count;
92    struct apic             *apic;
93    struct lpc              *lpc;
94    struct pci              *pci;
95    // some settings which belong to an upcomming CPU abstraction
96    bool                    a20_gate_enabled;
97
98    // list of guests
99    struct guest *next;
100};
101
102/**
103 * \brief This enum is used to indicate the size of operands to some operations.
104 */
105enum opsize {
106    OPSIZE_8,
107    OPSIZE_16,
108    OPSIZE_32,
109    OPSIZE_64
110};
111
112extern lvaddr_t guest_offset;
113static inline lvaddr_t
114        host_to_guest (lvaddr_t addr)
115{
116    return addr - guest_offset;
117}
118
119static inline lvaddr_t
120        guest_to_host (lvaddr_t addr)
121{
122    return addr + guest_offset;
123}
124
125// REGISTER ACCESS HELPERS
126
127// RAX
128
129static inline uint64_t
130guest_get_rax (struct guest *g)
131{
132#ifdef CONFIG_SVM
133    return amd_vmcb_rax_rd(&g->vmcb);
134#else
135    return g->ctrl->regs.rax;
136#endif
137}
138
139static inline void
140guest_set_rax (struct guest *g, uint64_t val)
141{
142#ifdef CONFIG_SVM
143    amd_vmcb_rax_wr(&g->vmcb, val);
144#else
145    g->ctrl->regs.rax = val;
146#endif
147}
148
149static inline uint32_t
150guest_get_eax (struct guest *g)
151{
152#ifdef CONFIG_SVM
153    return amd_vmcb_rax_rd(&g->vmcb) & 0xffffffff;
154#else
155    return (g->ctrl->regs.rax) & 0xffffffff;
156#endif
157}
158
159static inline void
160guest_set_eax (struct guest *g, uint32_t val)
161{
162#ifdef CONFIG_SVM
163    uint64_t buf = amd_vmcb_rax_rd(&g->vmcb);
164    buf = (buf & ~0xffffffff) | val;
165    amd_vmcb_rax_wr(&g->vmcb, buf);
166#else
167    uint64_t buf = g->ctrl->regs.rax;
168    buf = (buf & ~0xffffffff) | val;
169    g->ctrl->regs.rax = buf;
170#endif
171}
172
173static inline uint16_t
174guest_get_ax (struct guest *g)
175{
176#ifdef CONFIG_SVM
177    return amd_vmcb_rax_rd(&g->vmcb) & 0xffff;
178#else
179    return (g->ctrl->regs.rax) & 0xffff;
180#endif
181}
182
183static inline void
184guest_set_ax (struct guest *g, uint16_t val)
185{
186#ifdef CONFIG_SVM
187    uint64_t buf = amd_vmcb_rax_rd(&g->vmcb);
188    buf = (buf & ~0xffff) | val;
189    amd_vmcb_rax_wr(&g->vmcb, buf);
190#else
191    uint64_t buf = g->ctrl->regs.rax;
192    buf = (buf & ~0xffff) | val;
193    g->ctrl->regs.rax = buf;
194#endif
195}
196
197static inline uint8_t
198guest_get_ah (struct guest *g)
199{
200#ifdef CONFIG_SVM
201    return amd_vmcb_rax_rd(&g->vmcb) >> 8;
202#else
203    return (g->ctrl->regs.rax) >> 8;
204#endif
205}
206
207static inline void
208guest_set_ah (struct guest *g, uint8_t val)
209{
210#ifdef CONFIG_SVM
211    uint64_t buf = amd_vmcb_rax_rd(&g->vmcb);
212    buf = (buf & ~0xff00) | ((uint64_t)val) << 8;
213    amd_vmcb_rax_wr(&g->vmcb, buf);
214#else
215    uint64_t buf = g->ctrl->regs.rax;
216    buf = (buf & ~0xff00) | ((uint64_t)val) << 8;
217    g->ctrl->regs.rax = buf;
218#endif
219}
220
221static inline uint8_t
222guest_get_al (struct guest *g)
223{
224#ifdef CONFIG_SVM
225    return amd_vmcb_rax_rd(&g->vmcb);
226#else
227    return g->ctrl->regs.rax;
228#endif
229}
230
231static inline void
232guest_set_al (struct guest *g, uint8_t val)
233{
234#ifdef CONFIG_SVM
235    uint64_t buf = amd_vmcb_rax_rd(&g->vmcb);
236    buf = (buf & ~0xff) | val;
237    amd_vmcb_rax_wr(&g->vmcb, buf);
238#else
239    uint64_t buf = g->ctrl->regs.rax;
240    buf = (buf & ~0xff) | val;
241    g->ctrl->regs.rax = buf;
242#endif
243}
244
245
246// RBX
247
248static inline uint64_t
249guest_get_rbx (struct guest *g)
250{
251    return g->ctrl->regs.rbx;
252}
253
254static inline void
255guest_set_rbx (struct guest *g, uint64_t val)
256{
257    g->ctrl->regs.rbx = val;
258}
259
260static inline uint32_t
261guest_get_ebx (struct guest *g) {
262    return g->ctrl->regs.rbx;
263}
264
265static inline void
266guest_set_ebx (struct guest *g, uint32_t val) {
267    uint64_t buf = g->ctrl->regs.rbx;
268    g->ctrl->regs.rbx = (buf & ~0xffffffff) | val;
269}
270
271static inline uint16_t
272guest_get_bx (struct guest *g)
273{
274    return g->ctrl->regs.rbx & 0xffff;
275}
276
277static inline void
278guest_set_bx (struct guest *g, uint16_t val)
279{
280    uint64_t buf = g->ctrl->regs.rbx;
281    g->ctrl->regs.rbx = (buf & ~0xffff) | val;
282}
283
284static inline uint8_t
285guest_get_bl (struct guest *g)
286{
287    return g->ctrl->regs.rbx & 0xff;
288}
289
290static inline void
291guest_set_bl (struct guest *g, uint8_t val)
292{
293    uint64_t buf = g->ctrl->regs.rbx;
294    g->ctrl->regs.rbx = (buf & ~0xff) | val;
295}
296
297static inline uint8_t
298guest_get_bh (struct guest *g)
299{
300    return g->ctrl->regs.rbx >> 8;
301}
302
303static inline void
304guest_set_bh (struct guest *g, uint8_t val)
305{
306    uint64_t buf = g->ctrl->regs.rbx;
307    g->ctrl->regs.rbx = (buf & ~0xff00) | ((uint64_t)val) << 8;
308}
309
310
311// RCX
312
313static inline uint64_t
314guest_get_rcx (struct guest *g)
315{
316    return g->ctrl->regs.rcx;
317}
318
319static inline void
320guest_set_rcx (struct guest *g, uint64_t val)
321{
322    g->ctrl->regs.rcx = val;
323}
324
325static inline uint32_t
326guest_get_ecx (struct guest *g) {
327    return g->ctrl->regs.rcx;
328}
329
330static inline void
331guest_set_ecx (struct guest *g, uint32_t val) {
332    uint64_t buf = g->ctrl->regs.rcx;
333    g->ctrl->regs.rcx = (buf & ~0xffffffff) | val;
334}
335
336static inline uint16_t
337guest_get_cx (struct guest *g)
338{
339    return g->ctrl->regs.rcx & 0xffff;
340}
341
342static inline void
343guest_set_cx (struct guest *g, uint16_t val)
344{
345    uint64_t buf = g->ctrl->regs.rcx;
346    g->ctrl->regs.rcx = (buf & ~0xffff) | val;
347}
348
349static inline uint8_t
350guest_get_ch (struct guest *g)
351{
352    return g->ctrl->regs.rcx >> 8;
353}
354
355static inline void
356guest_set_ch (struct guest *g, uint8_t val)
357{
358    uint64_t buf = g->ctrl->regs.rcx;
359    g->ctrl->regs.rcx = (buf & ~0xff00) | ((uint64_t)val) << 8;
360}
361
362static inline uint8_t
363guest_get_cl (struct guest *g)
364{
365    return g->ctrl->regs.rcx;
366}
367
368static inline void
369guest_set_cl (struct guest *g, uint8_t val)
370{
371    uint64_t buf = g->ctrl->regs.rcx;
372    buf = (buf & ~0xff) | val;
373    g->ctrl->regs.rcx = val;
374}
375
376
377// RDX
378
379static inline uint64_t
380guest_get_rdx (struct guest *g)
381{
382    return g->ctrl->regs.rdx;
383}
384
385static inline void
386guest_set_rdx (struct guest *g, uint64_t val)
387{
388    g->ctrl->regs.rdx = val;
389}
390
391static inline uint32_t
392guest_get_edx (struct guest *g) {
393    return g->ctrl->regs.rdx;
394}
395
396static inline void
397guest_set_edx (struct guest *g, uint32_t val) {
398    uint64_t buf = g->ctrl->regs.rdx;
399    g->ctrl->regs.rdx = (buf & ~0xffffffff) | val;
400}
401
402static inline uint8_t
403guest_get_dh (struct guest *g)
404{
405    return g->ctrl->regs.rdx >> 8;
406}
407
408static inline void
409guest_set_dh (struct guest *g, uint8_t val)
410{
411    uint64_t buf = g->ctrl->regs.rdx;
412    g->ctrl->regs.rdx = (buf & ~0xff00) | ((uint64_t)val) << 8;
413}
414
415static inline uint8_t
416guest_get_dl (struct guest *g)
417{
418    return g->ctrl->regs.rdx & 0xff;
419}
420
421static inline void
422guest_set_dl (struct guest *g, uint8_t val)
423{
424    uint64_t buf = g->ctrl->regs.rdx;
425    g->ctrl->regs.rdx = (buf & ~0xff) | val;
426}
427
428
429// RDI
430
431static inline uint64_t
432guest_get_rdi (struct guest *g)
433{
434    return g->ctrl->regs.rdi;
435}
436
437static inline void
438guest_set_rdi (struct guest *g, uint64_t val)
439{
440    g->ctrl->regs.rdi = val;
441}
442
443static inline uint16_t
444guest_get_di (struct guest *g)
445{
446    return g->ctrl->regs.rdi & 0xffff;
447}
448
449static inline void
450guest_set_di (struct guest *g, uint16_t val)
451{
452    uint64_t buf = g->ctrl->regs.rdi;
453    g->ctrl->regs.rdi = (buf & ~0xffff) | val;
454}
455
456
457// RSI
458
459static inline uint64_t
460guest_get_rsi (struct guest *g)
461{
462    return g->ctrl->regs.rsi;
463}
464
465static inline void
466guest_set_rsi (struct guest *g, uint64_t val)
467{
468    g->ctrl->regs.rsi = val;
469}
470
471static inline uint16_t
472guest_get_si (struct guest *g)
473{
474    return g->ctrl->regs.rsi & 0xffff;
475}
476
477static inline void
478guest_set_si (struct guest *g, uint16_t val)
479{
480    uint64_t buf = g->ctrl->regs.rsi;
481    g->ctrl->regs.rsi = (buf & ~0xffff) | val;
482}
483
484
485// RSP
486
487static inline uint64_t
488guest_get_rsp (struct guest *g)
489{
490#ifdef CONFIG_SVM
491    return amd_vmcb_rsp_rd(&g->vmcb);
492#else
493    uint64_t guest_rsp;
494    errval_t err = invoke_dispatcher_vmread(g->dcb_cap, VMX_GUEST_RSP, &guest_rsp);
495    assert(err_is_ok(err));
496    return guest_rsp;
497#endif
498}
499
500static inline void
501guest_set_rsp (struct guest *g, uint64_t val)
502{
503#ifdef CONFIG_SVM
504    amd_vmcb_rsp_wr(&g->vmcb, val);
505#else
506    errval_t err = invoke_dispatcher_vmwrite(g->dcb_cap, VMX_GUEST_RSP, val);
507    assert(err_is_ok(err));
508#endif
509}
510
511
512// RBP
513
514static inline uint64_t
515guest_get_rbp (struct guest *g)
516{
517    return g->ctrl->regs.rbp;
518}
519
520static inline void
521guest_set_rbp (struct guest *g, uint64_t val)
522{
523    g->ctrl->regs.rbp = val;
524}
525
526
527struct guest *guest_create (void);
528errval_t guest_make_runnable (struct guest *g, bool run);
529void guest_handle_vmexit (struct guest *g);
530void spawn_guest_domain (struct guest *self, struct spawninfo *si);
531errval_t guest_vspace_map_wrapper(struct vspace *vspace, lvaddr_t vaddr,
532                                  struct capref frame,  size_t size);
533
534errval_t
535alloc_guest_mem(struct guest *g, lvaddr_t guest_paddr, size_t bytes);
536
537void npt_map_handler(struct hyper_binding *b, struct capref mem);
538
539#endif // GUEST_H
540