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