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