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