1 /* 2 * nestedsvm.h: Nested Virtualization 3 * Copyright (c) 2011, Advanced Micro Devices, Inc 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program; If not, see <http://www.gnu.org/licenses/>. 16 * 17 */ 18 #ifndef __ASM_X86_HVM_SVM_NESTEDSVM_H__ 19 #define __ASM_X86_HVM_SVM_NESTEDSVM_H__ 20 21 #include <asm/hvm/hvm.h> 22 #include <asm/hvm/svm/vmcb.h> 23 24 /* SVM specific intblk types, cannot be an enum because gcc 4.5 complains */ 25 /* GIF cleared */ 26 #define hvm_intblk_svm_gif hvm_intblk_arch 27 28 struct nestedsvm { 29 bool_t ns_gif; 30 uint64_t ns_msr_hsavepa; /* MSR HSAVE_PA value */ 31 32 /* l1 guest physical address of virtual vmcb used by prior VMRUN. 33 * Needed for VMCB Cleanbit emulation. 34 */ 35 uint64_t ns_ovvmcb_pa; 36 37 /* virtual tscratio holding the value l1 guest writes to the 38 * MSR_AMD64_TSC_RATIO MSR. 39 */ 40 uint64_t ns_tscratio; 41 42 /* Cached real intercepts of the l2 guest */ 43 uint32_t ns_cr_intercepts; 44 uint32_t ns_dr_intercepts; 45 uint32_t ns_exception_intercepts; 46 uint32_t ns_general1_intercepts; 47 uint32_t ns_general2_intercepts; 48 49 /* Cached real lbr and other virtual extentions of the l2 guest */ 50 virt_ext_t ns_virt_ext; 51 52 /* Cached real MSR permission bitmaps of the l2 guest */ 53 unsigned long *ns_cached_msrpm; 54 /* Merged MSR permission bitmap */ 55 unsigned long *ns_merged_msrpm; 56 57 /* guest physical address of virtual io permission map */ 58 paddr_t ns_iomap_pa, ns_oiomap_pa; 59 /* Shadow io permission map */ 60 unsigned long *ns_iomap; 61 62 uint64_t ns_cr0; /* Cached guest_cr[0] of l1 guest while l2 guest runs. 63 * Needed to handle FPU context switching */ 64 65 /* Cache guest cr3/host cr3 the guest sets up for the l2 guest. 66 * Used by Shadow-on-Shadow and Nested-on-Nested. 67 * ns_vmcb_guestcr3: in l2 guest physical address space and points to 68 * the l2 guest page table 69 * ns_vmcb_hostcr3: in l1 guest physical address space and points to 70 * the l1 guest nested page table 71 */ 72 uint64_t ns_vmcb_guestcr3, ns_vmcb_hostcr3; 73 uint32_t ns_guest_asid; 74 75 bool_t ns_hap_enabled; 76 77 /* Only meaningful when vmexit_pending flag is set */ 78 struct { 79 uint64_t exitcode; /* native exitcode to inject into l1 guest */ 80 uint64_t exitinfo1; /* additional information to the exitcode */ 81 uint64_t exitinfo2; /* additional information to the exitcode */ 82 } ns_vmexit; 83 union { 84 uint32_t bytes; 85 struct { 86 uint32_t rflagsif: 1; 87 uint32_t vintrmask: 1; 88 uint32_t reserved: 30; 89 } fields; 90 } ns_hostflags; 91 }; 92 93 #define vcpu_nestedsvm(v) (vcpu_nestedhvm(v).u.nsvm) 94 95 /* True when l1 guest enabled SVM in EFER */ 96 #define nsvm_efer_svm_enabled(v) \ 97 (!!((v)->arch.hvm.guest_efer & EFER_SVME)) 98 99 int nestedsvm_vmcb_map(struct vcpu *v, uint64_t vmcbaddr); 100 void nestedsvm_vmexit_defer(struct vcpu *v, 101 uint64_t exitcode, uint64_t exitinfo1, uint64_t exitinfo2); 102 enum nestedhvm_vmexits 103 nestedsvm_vmexit_n2n1(struct vcpu *v, struct cpu_user_regs *regs); 104 enum nestedhvm_vmexits 105 nestedsvm_check_intercepts(struct vcpu *v, struct cpu_user_regs *regs, 106 uint64_t exitcode); 107 void svm_nested_features_on_efer_update(struct vcpu *v); 108 109 /* Interface methods */ 110 void nsvm_vcpu_destroy(struct vcpu *v); 111 int nsvm_vcpu_initialise(struct vcpu *v); 112 int nsvm_vcpu_reset(struct vcpu *v); 113 int nsvm_vcpu_vmrun(struct vcpu *v, struct cpu_user_regs *regs); 114 int nsvm_vcpu_vmexit_event(struct vcpu *v, const struct x86_event *event); 115 uint64_t nsvm_vcpu_hostcr3(struct vcpu *v); 116 bool_t nsvm_vmcb_guest_intercepts_event( 117 struct vcpu *v, unsigned int vector, int errcode); 118 bool_t nsvm_vmcb_hap_enabled(struct vcpu *v); 119 enum hvm_intblk nsvm_intr_blocked(struct vcpu *v); 120 121 /* MSRs */ 122 int nsvm_rdmsr(struct vcpu *v, unsigned int msr, uint64_t *msr_content); 123 int nsvm_wrmsr(struct vcpu *v, unsigned int msr, uint64_t msr_content); 124 125 /* Interrupts, vGIF */ 126 void svm_vmexit_do_clgi(struct cpu_user_regs *regs, struct vcpu *v); 127 void svm_vmexit_do_stgi(struct cpu_user_regs *regs, struct vcpu *v); 128 bool_t nestedsvm_gif_isset(struct vcpu *v); 129 int nsvm_hap_walk_L1_p2m(struct vcpu *v, paddr_t L2_gpa, paddr_t *L1_gpa, 130 unsigned int *page_order, uint8_t *p2m_acc, 131 bool_t access_r, bool_t access_w, bool_t access_x); 132 133 #define NSVM_INTR_NOTHANDLED 3 134 #define NSVM_INTR_NOTINTERCEPTED 2 135 #define NSVM_INTR_FORCEVMEXIT 1 136 #define NSVM_INTR_MASKED 0 137 int nestedsvm_vcpu_interrupt(struct vcpu *v, const struct hvm_intack intack); 138 139 #endif /* ASM_X86_HVM_SVM_NESTEDSVM_H__ */ 140 141 /* 142 * Local variables: 143 * mode: C 144 * c-file-style: "BSD" 145 * c-basic-offset: 4 146 * tab-width: 4 147 * indent-tabs-mode: nil 148 * End: 149 */ 150