vmcb.h revision 249967
1249130Sneel/*- 2249130Sneel * Copyright (c) 2013 Anish Gupta (akgupt3@gmail.com) 3249130Sneel * All rights reserved. 4249130Sneel * 5249130Sneel * Redistribution and use in source and binary forms, with or without 6249130Sneel * modification, are permitted provided that the following conditions 7249130Sneel * are met: 8249130Sneel * 1. Redistributions of source code must retain the above copyright 9249967Sneel * notice unmodified, this list of conditions, and the following 10249967Sneel * disclaimer. 11249130Sneel * 2. Redistributions in binary form must reproduce the above copyright 12249130Sneel * notice, this list of conditions and the following disclaimer in the 13249130Sneel * documentation and/or other materials provided with the distribution. 14249130Sneel * 15249967Sneel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16249967Sneel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17249967Sneel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18249967Sneel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19249967Sneel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20249967Sneel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21249967Sneel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22249967Sneel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23249967Sneel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24249967Sneel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25249130Sneel * 26249130Sneel * $FreeBSD: projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.h 249967 2013-04-27 04:49:51Z neel $ 27249130Sneel */ 28249130Sneel 29249130Sneel#ifndef _VMCB_H_ 30249130Sneel#define _VMCB_H_ 31249130Sneel 32249130Sneel/* 33249130Sneel * Secure Virtual Machine: AMD64 Programmer's Manual Vol2, Chapter 15 34249130Sneel * Layout of VMCB: AMD64 Programmer's Manual Vol2, Appendix B 35249130Sneel */ 36249130Sneel 37249130Sneel/* VMCB Control offset 0xC */ 38249130Sneel#define VMCB_INTCPT_INTR BIT(0) 39249130Sneel#define VMCB_INTCPT_NMI BIT(1) 40249130Sneel#define VMCB_INTCPT_SMI BIT(2) 41249130Sneel#define VMCB_INTCPT_INIT BIT(3) 42249130Sneel#define VMCB_INTCPT_VINTR BIT(4) 43249130Sneel#define VMCB_INTCPT_CR0_WRITE BIT(5) 44249130Sneel#define VMCB_INTCPT_IDTR_READ BIT(6) 45249130Sneel#define VMCB_INTCPT_GDTR_READ BIT(7) 46249130Sneel#define VMCB_INTCPT_LDTR_READ BIT(8) 47249130Sneel#define VMCB_INTCPT_TR_READ BIT(9) 48249130Sneel#define VMCB_INTCPT_IDTR_WRITE BIT(10) 49249130Sneel#define VMCB_INTCPT_GDTR_WRITE BIT(11) 50249130Sneel#define VMCB_INTCPT_LDTR_WRITE BIT(12) 51249130Sneel#define VMCB_INTCPT_TR_WRITE BIT(13) 52249130Sneel#define VMCB_INTCPT_RDTSC BIT(14) 53249130Sneel#define VMCB_INTCPT_RDPMC BIT(15) 54249130Sneel#define VMCB_INTCPT_PUSHF BIT(16) 55249130Sneel#define VMCB_INTCPT_POPF BIT(17) 56249130Sneel#define VMCB_INTCPT_CPUID BIT(18) 57249130Sneel#define VMCB_INTCPT_RSM BIT(19) 58249130Sneel#define VMCB_INTCPT_IRET BIT(20) 59249130Sneel#define VMCB_INTCPT_INTn BIT(21) 60249130Sneel#define VMCB_INTCPT_INVD BIT(22) 61249130Sneel#define VMCB_INTCPT_PAUSE BIT(23) 62249130Sneel#define VMCB_INTCPT_HLT BIT(24) 63249130Sneel#define VMCB_INTCPT_INVPG BIT(25) 64249130Sneel#define VMCB_INTCPT_INVPGA BIT(26) 65249130Sneel#define VMCB_INTCPT_IO BIT(27) 66249130Sneel#define VMCB_INTCPT_MSR BIT(28) 67249130Sneel#define VMCB_INTCPT_TASK_SWITCH BIT(29) 68249130Sneel#define VMCB_INTCPT_FERR_FREEZE BIT(30) 69249130Sneel#define VMCB_INTCPT_SHUTDOWN BIT(31) 70249130Sneel 71249130Sneel/* VMCB Control offset 0x10 */ 72249130Sneel#define VMCB_INTCPT_VMRUN BIT(0) 73249130Sneel#define VMCB_INTCPT_VMMCALL BIT(1) 74249130Sneel#define VMCB_INTCPT_VMLOAD BIT(2) 75249130Sneel#define VMCB_INTCPT_VMSAVE BIT(3) 76249130Sneel#define VMCB_INTCPT_STGI BIT(4) 77249130Sneel#define VMCB_INTCPT_CLGI BIT(5) 78249130Sneel#define VMCB_INTCPT_SKINIT BIT(6) 79249130Sneel#define VMCB_INTCPT_RDTSCP BIT(7) 80249130Sneel#define VMCB_INTCPT_ICEBP BIT(8) 81249130Sneel#define VMCB_INTCPT_WBINVD BIT(9) 82249130Sneel#define VMCB_INTCPT_MONITOR BIT(10) 83249130Sneel#define VMCB_INTCPT_MWAIT BIT(11) 84249130Sneel#define VMCB_INTCPT_MWAIT_ARMED BIT(12) 85249130Sneel#define VMCB_INTCPT_XSETBV BIT(13) 86249130Sneel 87249130Sneel/* VMCB TLB control */ 88249130Sneel#define VMCB_TLB_FLUSH_NOTHING 0 /* Flush nothing */ 89249130Sneel#define VMCB_TLB_FLUSH_EVERYTHING 1 /* Flush entire TLB */ 90249130Sneel#define VMCB_TLB_FLUSH_GUEST 3 /* Flush all guest entries */ 91249130Sneel#define VMCB_TLB_FLUSH_GUEST_NONGLOBAL 7 /* Flush guest non-PG entries */ 92249130Sneel 93249130Sneel/* VMCB state caching */ 94249130Sneel#define VMCB_CACHE_NONE 0 /* No caching */ 95249130Sneel#define VMCB_CACHE_I BIT(0) /* Cache vectors, TSC offset */ 96249130Sneel#define VMCB_CACHE_IOPM BIT(1) /* I/O and MSR permission */ 97249130Sneel#define VMCB_CACHE_ASID BIT(2) /* ASID */ 98249130Sneel#define VMCB_CACHE_TPR BIT(3) /* V_TPR to V_INTR_VECTOR */ 99249130Sneel#define VMCB_CACHE_NP BIT(4) /* Nested Paging */ 100249130Sneel#define VMCB_CACHE_CR BIT(5) /* CR0, CR3, CR4 & EFER */ 101249130Sneel#define VMCB_CACHE_DR BIT(6) /* Debug registers */ 102249130Sneel#define VMCB_CACHE_DT BIT(7) /* GDT/IDT */ 103249130Sneel#define VMCB_CACHE_SEG BIT(8) /* User segments, CPL */ 104249130Sneel#define VMCB_CACHE_CR2 BIT(9) /* page fault address */ 105249130Sneel#define VMCB_CACHE_LBR BIT(10) /* Last branch */ 106249130Sneel 107249130Sneel 108249130Sneel/* VMCB control event injection */ 109249130Sneel#define VMCB_EVENTINJ_EC_VALID BIT(11) /* Error Code valid */ 110249130Sneel#define VMCB_EVENTINJ_VALID BIT(31) /* Event valid */ 111249130Sneel 112249130Sneel#define VMCB_EVENTINJ_VECTOR_MASK 0xFF 113249130Sneel#define VMCB_EVENTINJ_INTR_TYPE_SHIFT 8 114249130Sneel#define VMCB_EVENTINJ_ERRCODE_SHIFT 32 115249130Sneel 116249130Sneel/* Event types that can be injected */ 117249130Sneel#define VMCB_EVENTINJ_TYPE_INTR 0 118249130Sneel#define VMCB_EVENTINJ_TYPE_NMI 2 119249130Sneel#define VMCB_EVENTINJ_TYPE_EXCEPTION 3 120249130Sneel#define VMCB_EVENTINJ_TYPE_INTn 4 121249130Sneel 122249130Sneel/* VMCB exit code, APM vol2 Appendix C */ 123249130Sneel#define VMCB_EXIT_MC 0x52 124249130Sneel#define VMCB_EXIT_INTR 0x60 125249130Sneel#define VMCB_EXIT_PUSHF 0x70 126249130Sneel#define VMCB_EXIT_POPF 0x71 127249130Sneel#define VMCB_EXIT_CPUID 0x72 128249130Sneel#define VMCB_EXIT_IRET 0x74 129249130Sneel#define VMCB_EXIT_PAUSE 0x77 130249130Sneel#define VMCB_EXIT_HLT 0x78 131249130Sneel#define VMCB_EXIT_IO 0x7B 132249130Sneel#define VMCB_EXIT_MSR 0x7C 133249130Sneel#define VMCB_EXIT_SHUTDOWN 0x7F 134249130Sneel#define VMCB_EXIT_VMSAVE 0x83 135249130Sneel#define VMCB_EXIT_NPF 0x400 136249130Sneel#define VMCB_EXIT_INVALID -1 137249130Sneel 138249130Sneel/* 139249130Sneel * Nested page fault. 140249130Sneel * Bit definitions to decode EXITINFO1. 141249130Sneel */ 142249130Sneel#define VMCB_NPF_INFO1_P BIT(0) /* Nested page present. */ 143249130Sneel#define VMCB_NPF_INFO1_W BIT(1) /* Access was write. */ 144249130Sneel#define VMCB_NPF_INFO1_U BIT(2) /* Access was user access. */ 145249130Sneel#define VMCB_NPF_INFO1_RSV BIT(3) /* Reserved bits present. */ 146249130Sneel#define VMCB_NPF_INFO1_ID BIT(4) /* Code read. */ 147249130Sneel 148249130Sneel#define VMCB_NPF_INFO1_GPA BIT(32) /* Guest physical address. */ 149249130Sneel#define VMCB_NPF_INFO1_GPT BIT(33) /* Guest page table. */ 150249130Sneel 151249130Sneel/* VMCB save state area segment format */ 152249130Sneelstruct vmcb_segment { 153249130Sneel uint16_t selector; 154249130Sneel uint16_t attrib; 155249130Sneel uint32_t limit; 156249130Sneel uint64_t base; 157249130Sneel} __attribute__ ((__packed__)); 158249130SneelCTASSERT(sizeof(struct vmcb_segment) == 16); 159249130Sneel 160249130Sneel/* 161249130Sneel * The VMCB is divided into two areas - the first one contains various 162249130Sneel * control bits including the intercept vector and the second one contains 163249130Sneel * the guest state. 164249130Sneel */ 165249130Sneel 166249130Sneel/* VMCB control area - padded up to 1024 bytes */ 167249130Sneelstruct vmcb_ctrl { 168249130Sneel uint16_t cr_read; /* Offset 0, CR0-15 read/write */ 169249130Sneel uint16_t cr_write; 170249130Sneel uint16_t dr_read; /* Offset 4, DR0-DR15 */ 171249130Sneel uint16_t dr_write; 172249130Sneel uint32_t exception; /* Offset 8, bit mask for exceptions. */ 173249130Sneel uint32_t ctrl1; /* Offset 0xC, intercept events1 */ 174249130Sneel uint32_t ctrl2; /* Offset 0x10, intercept event2 */ 175249130Sneel uint8_t pad1[0x28]; /* Offsets 0x14-0x3B are reserved. */ 176249130Sneel uint16_t pause_filthresh; /* Offset 0x3C, PAUSE filter threshold */ 177249130Sneel uint16_t pause_filcnt; /* Offset 0x3E, PAUSE filter count */ 178249130Sneel uint64_t iopm_base_pa; /* 0x40: IOPM_BASE_PA */ 179249130Sneel uint64_t msrpm_base_pa; /* 0x48: MSRPM_BASE_PA */ 180249130Sneel uint64_t tsc_offset; /* 0x50: TSC_OFFSET */ 181249130Sneel uint32_t asid; /* 0x58: Guest ASID */ 182249130Sneel uint8_t tlb_ctrl; /* 0x5C: TLB_CONTROL */ 183249130Sneel uint8_t pad2[3]; /* 0x5D-0x5F: Reserved. */ 184249130Sneel uint8_t v_tpr; /* 0x60: V_TPR, guest CR8 */ 185249130Sneel uint8_t v_irq:1; /* Is virtual interrupt pending? */ 186249130Sneel uint8_t :7; /* Padding */ 187249130Sneel uint8_t v_intr_prio:4; /* 0x62: Priority for virtual interrupt. */ 188249130Sneel uint8_t v_ign_tpr:1; 189249130Sneel uint8_t :3; 190249130Sneel uint8_t v_intr_masking:1; /* Guest and host sharing of RFLAGS. */ 191249130Sneel uint8_t :7; 192249130Sneel uint8_t v_intr_vector; /* 0x65: Vector for virtual interrupt. */ 193249130Sneel uint8_t pad3[3]; /* Bit64-40 Reserved. */ 194249130Sneel uint64_t intr_shadow:1; /* 0x68: Interrupt shadow, section15.2.1 APM2 */ 195249130Sneel uint64_t :63; 196249130Sneel uint64_t exitcode; /* 0x70, Exitcode */ 197249130Sneel uint64_t exitinfo1; /* 0x78, EXITINFO1 */ 198249130Sneel uint64_t exitinfo2; /* 0x80, EXITINFO2 */ 199249130Sneel uint64_t exitintinfo; /* 0x88, Interrupt exit value. */ 200249130Sneel uint64_t np_enable:1; /* 0x90, Nested paging enable. */ 201249130Sneel uint64_t :63; 202249130Sneel uint8_t pad4[0x10]; /* 0x98-0xA7 reserved. */ 203249130Sneel uint64_t eventinj; /* 0xA8, Event injection. */ 204249130Sneel uint64_t n_cr3; /* B0, Nested page table. */ 205249130Sneel uint64_t lbr_virt_en:1; /* Enable LBR virtualization. */ 206249130Sneel uint64_t :63; 207249130Sneel uint32_t vmcb_clean; /* 0xC0: VMCB clean bits for caching */ 208249130Sneel uint32_t :32; /* 0xC4: Reserved */ 209249130Sneel uint64_t nrip; /* 0xC8: Guest next nRIP. */ 210249130Sneel uint8_t inst_decode_size; /* 0xD0: Instruction decode */ 211249130Sneel uint8_t inst_decode_bytes[15]; 212249130Sneel uint8_t padd6[0x320]; 213249130Sneel} __attribute__ ((__packed__)); 214249130SneelCTASSERT(sizeof(struct vmcb_ctrl) == 1024); 215249130Sneel 216249130Sneelstruct vmcb_state { 217249130Sneel struct vmcb_segment es; 218249130Sneel struct vmcb_segment cs; 219249130Sneel struct vmcb_segment ss; 220249130Sneel struct vmcb_segment ds; 221249130Sneel struct vmcb_segment fs; 222249130Sneel struct vmcb_segment gs; 223249130Sneel struct vmcb_segment gdt; 224249130Sneel struct vmcb_segment ldt; 225249130Sneel struct vmcb_segment idt; 226249130Sneel struct vmcb_segment tr; 227249130Sneel uint8_t pad1[0x2b]; /* Reserved: 0xA0-0xCA */ 228249130Sneel uint8_t cpl; 229249130Sneel uint8_t pad2[4]; 230249130Sneel uint64_t efer; 231249130Sneel uint8_t pad3[0x70]; /* Reserved: 0xd8-0x147 */ 232249130Sneel uint64_t cr4; 233249130Sneel uint64_t cr3; /* Guest CR3 */ 234249130Sneel uint64_t cr0; 235249130Sneel uint64_t dr7; 236249130Sneel uint64_t dr6; 237249130Sneel uint64_t rflags; 238249130Sneel uint64_t rip; 239249130Sneel uint8_t pad4[0x58]; /* Reserved: 0x180-0x1D7 */ 240249130Sneel uint64_t rsp; 241249130Sneel uint8_t pad5[0x18]; /* Reserved 0x1E0-0x1F7 */ 242249130Sneel uint64_t rax; 243249130Sneel uint64_t star; 244249130Sneel uint64_t lstar; 245249130Sneel uint64_t cstar; 246249130Sneel uint64_t sfmask; 247249130Sneel uint64_t kernelgsbase; 248249130Sneel uint64_t sysenter_cs; 249249130Sneel uint64_t sysenter_esp; 250249130Sneel uint64_t sysenter_eip; 251249130Sneel uint64_t cr2; 252249130Sneel uint8_t pad6[0x20]; 253249130Sneel uint64_t g_pat; 254249130Sneel uint64_t dbgctl; 255249130Sneel uint64_t br_from; 256249130Sneel uint64_t br_to; 257249130Sneel uint64_t lastexcpfrom; 258249130Sneel uint64_t lastexcpto; 259249130Sneel uint8_t pad7[0x968]; /* Reserved upto end of VMCB */ 260249130Sneel} __attribute__ ((__packed__)); 261249130SneelCTASSERT(sizeof(struct vmcb_state) == 0xC00); 262249130Sneel 263249130Sneelstruct vmcb { 264249130Sneel struct vmcb_ctrl ctrl; 265249130Sneel struct vmcb_state state; 266249130Sneel} __attribute__ ((__packed__)); 267249130SneelCTASSERT(sizeof(struct vmcb) == PAGE_SIZE); 268249130SneelCTASSERT(offsetof(struct vmcb, state) == 0x400); 269249130Sneel 270249353Sneelint svm_init_vmcb(struct vmcb *vmcb, uint64_t iopm_base_pa, 271249353Sneel uint64_t msrpm_base_pa, uint64_t np_pml4); 272249353Sneelint svm_set_vmcb(struct vmcb *vmcb, uint8_t asid); 273249353Sneelint vmcb_read(struct vmcb *vmcb, int ident, uint64_t *retval); 274249353Sneelint vmcb_write(struct vmcb *vmcb, int ident, uint64_t val); 275249353Sneelstruct vmcb_segment *vmcb_seg(struct vmcb *vmcb, int type); 276249353Sneelint vmcb_eventinject(struct vmcb_ctrl *ctrl, int type, int vector, 277249353Sneel uint32_t error, boolean_t ec_valid); 278249353Sneel 279249130Sneel#endif /* _VMCB_H_ */ 280