1883b0a91SJoerg Roedel // SPDX-License-Identifier: GPL-2.0-only 2883b0a91SJoerg Roedel /* 3883b0a91SJoerg Roedel * Kernel-based Virtual Machine driver for Linux 4883b0a91SJoerg Roedel * 5883b0a91SJoerg Roedel * AMD SVM support 6883b0a91SJoerg Roedel * 7883b0a91SJoerg Roedel * Copyright (C) 2006 Qumranet, Inc. 8883b0a91SJoerg Roedel * Copyright 2010 Red Hat, Inc. and/or its affiliates. 9883b0a91SJoerg Roedel * 10883b0a91SJoerg Roedel * Authors: 11883b0a91SJoerg Roedel * Yaniv Kamay <yaniv@qumranet.com> 12883b0a91SJoerg Roedel * Avi Kivity <avi@qumranet.com> 13883b0a91SJoerg Roedel */ 14883b0a91SJoerg Roedel 15883b0a91SJoerg Roedel #define pr_fmt(fmt) "SVM: " fmt 16883b0a91SJoerg Roedel 17883b0a91SJoerg Roedel #include <linux/kvm_types.h> 18883b0a91SJoerg Roedel #include <linux/kvm_host.h> 19883b0a91SJoerg Roedel #include <linux/kernel.h> 20883b0a91SJoerg Roedel 21883b0a91SJoerg Roedel #include <asm/msr-index.h> 225679b803SPaolo Bonzini #include <asm/debugreg.h> 23883b0a91SJoerg Roedel 24883b0a91SJoerg Roedel #include "kvm_emulate.h" 25883b0a91SJoerg Roedel #include "trace.h" 26883b0a91SJoerg Roedel #include "mmu.h" 27883b0a91SJoerg Roedel #include "x86.h" 28cc440cdaSPaolo Bonzini #include "cpuid.h" 295b672408SPaolo Bonzini #include "lapic.h" 30883b0a91SJoerg Roedel #include "svm.h" 31883b0a91SJoerg Roedel 32883b0a91SJoerg Roedel static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu, 33883b0a91SJoerg Roedel struct x86_exception *fault) 34883b0a91SJoerg Roedel { 35883b0a91SJoerg Roedel struct vcpu_svm *svm = to_svm(vcpu); 36883b0a91SJoerg Roedel 37883b0a91SJoerg Roedel if (svm->vmcb->control.exit_code != SVM_EXIT_NPF) { 38883b0a91SJoerg Roedel /* 39883b0a91SJoerg Roedel * TODO: track the cause of the nested page fault, and 40883b0a91SJoerg Roedel * correctly fill in the high bits of exit_info_1. 41883b0a91SJoerg Roedel */ 42883b0a91SJoerg Roedel svm->vmcb->control.exit_code = SVM_EXIT_NPF; 43883b0a91SJoerg Roedel svm->vmcb->control.exit_code_hi = 0; 44883b0a91SJoerg Roedel svm->vmcb->control.exit_info_1 = (1ULL << 32); 45883b0a91SJoerg Roedel svm->vmcb->control.exit_info_2 = fault->address; 46883b0a91SJoerg Roedel } 47883b0a91SJoerg Roedel 48883b0a91SJoerg Roedel svm->vmcb->control.exit_info_1 &= ~0xffffffffULL; 49883b0a91SJoerg Roedel svm->vmcb->control.exit_info_1 |= fault->error_code; 50883b0a91SJoerg Roedel 51883b0a91SJoerg Roedel nested_svm_vmexit(svm); 52883b0a91SJoerg Roedel } 53883b0a91SJoerg Roedel 54883b0a91SJoerg Roedel static u64 nested_svm_get_tdp_pdptr(struct kvm_vcpu *vcpu, int index) 55883b0a91SJoerg Roedel { 56883b0a91SJoerg Roedel struct vcpu_svm *svm = to_svm(vcpu); 57e670bf68SPaolo Bonzini u64 cr3 = svm->nested.ctl.nested_cr3; 58883b0a91SJoerg Roedel u64 pdpte; 59883b0a91SJoerg Roedel int ret; 60883b0a91SJoerg Roedel 61883b0a91SJoerg Roedel ret = kvm_vcpu_read_guest_page(vcpu, gpa_to_gfn(__sme_clr(cr3)), &pdpte, 62883b0a91SJoerg Roedel offset_in_page(cr3) + index * 8, 8); 63883b0a91SJoerg Roedel if (ret) 64883b0a91SJoerg Roedel return 0; 65883b0a91SJoerg Roedel return pdpte; 66883b0a91SJoerg Roedel } 67883b0a91SJoerg Roedel 68883b0a91SJoerg Roedel static unsigned long nested_svm_get_tdp_cr3(struct kvm_vcpu *vcpu) 69883b0a91SJoerg Roedel { 70883b0a91SJoerg Roedel struct vcpu_svm *svm = to_svm(vcpu); 71883b0a91SJoerg Roedel 72e670bf68SPaolo Bonzini return svm->nested.ctl.nested_cr3; 73883b0a91SJoerg Roedel } 74883b0a91SJoerg Roedel 75883b0a91SJoerg Roedel static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu) 76883b0a91SJoerg Roedel { 77929d1cfaSPaolo Bonzini struct vcpu_svm *svm = to_svm(vcpu); 78929d1cfaSPaolo Bonzini struct vmcb *hsave = svm->nested.hsave; 79929d1cfaSPaolo Bonzini 80883b0a91SJoerg Roedel WARN_ON(mmu_is_nested(vcpu)); 81883b0a91SJoerg Roedel 82883b0a91SJoerg Roedel vcpu->arch.mmu = &vcpu->arch.guest_mmu; 830f04a2acSVitaly Kuznetsov kvm_init_shadow_npt_mmu(vcpu, X86_CR0_PG, hsave->save.cr4, hsave->save.efer, 840f04a2acSVitaly Kuznetsov svm->nested.ctl.nested_cr3); 85883b0a91SJoerg Roedel vcpu->arch.mmu->get_guest_pgd = nested_svm_get_tdp_cr3; 86883b0a91SJoerg Roedel vcpu->arch.mmu->get_pdptr = nested_svm_get_tdp_pdptr; 87883b0a91SJoerg Roedel vcpu->arch.mmu->inject_page_fault = nested_svm_inject_npf_exit; 88883b0a91SJoerg Roedel reset_shadow_zero_bits_mask(vcpu, vcpu->arch.mmu); 89883b0a91SJoerg Roedel vcpu->arch.walk_mmu = &vcpu->arch.nested_mmu; 90883b0a91SJoerg Roedel } 91883b0a91SJoerg Roedel 92883b0a91SJoerg Roedel static void nested_svm_uninit_mmu_context(struct kvm_vcpu *vcpu) 93883b0a91SJoerg Roedel { 94883b0a91SJoerg Roedel vcpu->arch.mmu = &vcpu->arch.root_mmu; 95883b0a91SJoerg Roedel vcpu->arch.walk_mmu = &vcpu->arch.root_mmu; 96883b0a91SJoerg Roedel } 97883b0a91SJoerg Roedel 98883b0a91SJoerg Roedel void recalc_intercepts(struct vcpu_svm *svm) 99883b0a91SJoerg Roedel { 100e670bf68SPaolo Bonzini struct vmcb_control_area *c, *h, *g; 101c45ad722SBabu Moger unsigned int i; 102883b0a91SJoerg Roedel 10306e7852cSJoerg Roedel vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS); 104883b0a91SJoerg Roedel 105883b0a91SJoerg Roedel if (!is_guest_mode(&svm->vcpu)) 106883b0a91SJoerg Roedel return; 107883b0a91SJoerg Roedel 108883b0a91SJoerg Roedel c = &svm->vmcb->control; 109883b0a91SJoerg Roedel h = &svm->nested.hsave->control; 110e670bf68SPaolo Bonzini g = &svm->nested.ctl; 111883b0a91SJoerg Roedel 112c45ad722SBabu Moger for (i = 0; i < MAX_INTERCEPT; i++) 113c45ad722SBabu Moger c->intercepts[i] = h->intercepts[i]; 114c45ad722SBabu Moger 115e9fd761aSPaolo Bonzini if (g->int_ctl & V_INTR_MASKING_MASK) { 116883b0a91SJoerg Roedel /* We only want the cr8 intercept bits of L1 */ 11703bfeeb9SBabu Moger vmcb_clr_intercept(c, INTERCEPT_CR8_READ); 11803bfeeb9SBabu Moger vmcb_clr_intercept(c, INTERCEPT_CR8_WRITE); 119883b0a91SJoerg Roedel 120883b0a91SJoerg Roedel /* 121883b0a91SJoerg Roedel * Once running L2 with HF_VINTR_MASK, EFLAGS.IF does not 122883b0a91SJoerg Roedel * affect any interrupt we may want to inject; therefore, 123883b0a91SJoerg Roedel * interrupt window vmexits are irrelevant to L0. 124883b0a91SJoerg Roedel */ 125c62e2e94SBabu Moger vmcb_clr_intercept(c, INTERCEPT_VINTR); 126883b0a91SJoerg Roedel } 127883b0a91SJoerg Roedel 128883b0a91SJoerg Roedel /* We don't want to see VMMCALLs from a nested guest */ 129c62e2e94SBabu Moger vmcb_clr_intercept(c, INTERCEPT_VMMCALL); 130883b0a91SJoerg Roedel 131c45ad722SBabu Moger for (i = 0; i < MAX_INTERCEPT; i++) 132c45ad722SBabu Moger c->intercepts[i] |= g->intercepts[i]; 133883b0a91SJoerg Roedel } 134883b0a91SJoerg Roedel 1352f675917SPaolo Bonzini static void copy_vmcb_control_area(struct vmcb_control_area *dst, 1362f675917SPaolo Bonzini struct vmcb_control_area *from) 137883b0a91SJoerg Roedel { 138c45ad722SBabu Moger unsigned int i; 139c45ad722SBabu Moger 140c45ad722SBabu Moger for (i = 0; i < MAX_INTERCEPT; i++) 141c45ad722SBabu Moger dst->intercepts[i] = from->intercepts[i]; 142c45ad722SBabu Moger 143883b0a91SJoerg Roedel dst->iopm_base_pa = from->iopm_base_pa; 144883b0a91SJoerg Roedel dst->msrpm_base_pa = from->msrpm_base_pa; 145883b0a91SJoerg Roedel dst->tsc_offset = from->tsc_offset; 1466c0238c4SPaolo Bonzini /* asid not copied, it is handled manually for svm->vmcb. */ 147883b0a91SJoerg Roedel dst->tlb_ctl = from->tlb_ctl; 148883b0a91SJoerg Roedel dst->int_ctl = from->int_ctl; 149883b0a91SJoerg Roedel dst->int_vector = from->int_vector; 150883b0a91SJoerg Roedel dst->int_state = from->int_state; 151883b0a91SJoerg Roedel dst->exit_code = from->exit_code; 152883b0a91SJoerg Roedel dst->exit_code_hi = from->exit_code_hi; 153883b0a91SJoerg Roedel dst->exit_info_1 = from->exit_info_1; 154883b0a91SJoerg Roedel dst->exit_info_2 = from->exit_info_2; 155883b0a91SJoerg Roedel dst->exit_int_info = from->exit_int_info; 156883b0a91SJoerg Roedel dst->exit_int_info_err = from->exit_int_info_err; 157883b0a91SJoerg Roedel dst->nested_ctl = from->nested_ctl; 158883b0a91SJoerg Roedel dst->event_inj = from->event_inj; 159883b0a91SJoerg Roedel dst->event_inj_err = from->event_inj_err; 160883b0a91SJoerg Roedel dst->nested_cr3 = from->nested_cr3; 161883b0a91SJoerg Roedel dst->virt_ext = from->virt_ext; 162883b0a91SJoerg Roedel dst->pause_filter_count = from->pause_filter_count; 163883b0a91SJoerg Roedel dst->pause_filter_thresh = from->pause_filter_thresh; 164883b0a91SJoerg Roedel } 165883b0a91SJoerg Roedel 166883b0a91SJoerg Roedel static bool nested_svm_vmrun_msrpm(struct vcpu_svm *svm) 167883b0a91SJoerg Roedel { 168883b0a91SJoerg Roedel /* 169883b0a91SJoerg Roedel * This function merges the msr permission bitmaps of kvm and the 170883b0a91SJoerg Roedel * nested vmcb. It is optimized in that it only merges the parts where 171883b0a91SJoerg Roedel * the kvm msr permission bitmap may contain zero bits 172883b0a91SJoerg Roedel */ 173883b0a91SJoerg Roedel int i; 174883b0a91SJoerg Roedel 175c62e2e94SBabu Moger if (!(vmcb_is_intercept(&svm->nested.ctl, INTERCEPT_MSR_PROT))) 176883b0a91SJoerg Roedel return true; 177883b0a91SJoerg Roedel 178883b0a91SJoerg Roedel for (i = 0; i < MSRPM_OFFSETS; i++) { 179883b0a91SJoerg Roedel u32 value, p; 180883b0a91SJoerg Roedel u64 offset; 181883b0a91SJoerg Roedel 182883b0a91SJoerg Roedel if (msrpm_offsets[i] == 0xffffffff) 183883b0a91SJoerg Roedel break; 184883b0a91SJoerg Roedel 185883b0a91SJoerg Roedel p = msrpm_offsets[i]; 186e670bf68SPaolo Bonzini offset = svm->nested.ctl.msrpm_base_pa + (p * 4); 187883b0a91SJoerg Roedel 188883b0a91SJoerg Roedel if (kvm_vcpu_read_guest(&svm->vcpu, offset, &value, 4)) 189883b0a91SJoerg Roedel return false; 190883b0a91SJoerg Roedel 191883b0a91SJoerg Roedel svm->nested.msrpm[p] = svm->msrpm[p] | value; 192883b0a91SJoerg Roedel } 193883b0a91SJoerg Roedel 194883b0a91SJoerg Roedel svm->vmcb->control.msrpm_base_pa = __sme_set(__pa(svm->nested.msrpm)); 195883b0a91SJoerg Roedel 196883b0a91SJoerg Roedel return true; 197883b0a91SJoerg Roedel } 198883b0a91SJoerg Roedel 199a7d5c7ceSPaolo Bonzini static bool svm_get_nested_state_pages(struct kvm_vcpu *vcpu) 200a7d5c7ceSPaolo Bonzini { 201a7d5c7ceSPaolo Bonzini struct vcpu_svm *svm = to_svm(vcpu); 202a7d5c7ceSPaolo Bonzini if (!nested_svm_vmrun_msrpm(svm)) { 203a7d5c7ceSPaolo Bonzini vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; 204a7d5c7ceSPaolo Bonzini vcpu->run->internal.suberror = 205a7d5c7ceSPaolo Bonzini KVM_INTERNAL_ERROR_EMULATION; 206a7d5c7ceSPaolo Bonzini vcpu->run->internal.ndata = 0; 207a7d5c7ceSPaolo Bonzini return false; 208a7d5c7ceSPaolo Bonzini } 209a7d5c7ceSPaolo Bonzini 210a7d5c7ceSPaolo Bonzini return true; 211a7d5c7ceSPaolo Bonzini } 212a7d5c7ceSPaolo Bonzini 213ca46d739SPaolo Bonzini static bool nested_vmcb_check_controls(struct vmcb_control_area *control) 214ca46d739SPaolo Bonzini { 215c62e2e94SBabu Moger if ((vmcb_is_intercept(control, INTERCEPT_VMRUN)) == 0) 216ca46d739SPaolo Bonzini return false; 217ca46d739SPaolo Bonzini 218ca46d739SPaolo Bonzini if (control->asid == 0) 219ca46d739SPaolo Bonzini return false; 220ca46d739SPaolo Bonzini 221ca46d739SPaolo Bonzini if ((control->nested_ctl & SVM_NESTED_CTL_NP_ENABLE) && 222ca46d739SPaolo Bonzini !npt_enabled) 223ca46d739SPaolo Bonzini return false; 224ca46d739SPaolo Bonzini 225ca46d739SPaolo Bonzini return true; 226ca46d739SPaolo Bonzini } 227ca46d739SPaolo Bonzini 2280dd16b5bSMaxim Levitsky static bool nested_vmcb_checks(struct vcpu_svm *svm, struct vmcb *vmcb12) 229883b0a91SJoerg Roedel { 2300dd16b5bSMaxim Levitsky bool vmcb12_lma; 2310dd16b5bSMaxim Levitsky 2320dd16b5bSMaxim Levitsky if ((vmcb12->save.efer & EFER_SVME) == 0) 233883b0a91SJoerg Roedel return false; 234883b0a91SJoerg Roedel 2350dd16b5bSMaxim Levitsky if (((vmcb12->save.cr0 & X86_CR0_CD) == 0) && (vmcb12->save.cr0 & X86_CR0_NW)) 2364f233371SKrish Sadhukhan return false; 2374f233371SKrish Sadhukhan 2380dd16b5bSMaxim Levitsky if (!kvm_dr6_valid(vmcb12->save.dr6) || !kvm_dr7_valid(vmcb12->save.dr7)) 2391aef8161SKrish Sadhukhan return false; 2401aef8161SKrish Sadhukhan 2410dd16b5bSMaxim Levitsky vmcb12_lma = (vmcb12->save.efer & EFER_LME) && (vmcb12->save.cr0 & X86_CR0_PG); 242761e4169SKrish Sadhukhan 2430dd16b5bSMaxim Levitsky if (!vmcb12_lma) { 2440dd16b5bSMaxim Levitsky if (vmcb12->save.cr4 & X86_CR4_PAE) { 2450dd16b5bSMaxim Levitsky if (vmcb12->save.cr3 & MSR_CR3_LEGACY_PAE_RESERVED_MASK) 246761e4169SKrish Sadhukhan return false; 247761e4169SKrish Sadhukhan } else { 2480dd16b5bSMaxim Levitsky if (vmcb12->save.cr3 & MSR_CR3_LEGACY_RESERVED_MASK) 249761e4169SKrish Sadhukhan return false; 250761e4169SKrish Sadhukhan } 251761e4169SKrish Sadhukhan } else { 2520dd16b5bSMaxim Levitsky if (!(vmcb12->save.cr4 & X86_CR4_PAE) || 2530dd16b5bSMaxim Levitsky !(vmcb12->save.cr0 & X86_CR0_PE) || 254fb0f33fdSKrish Sadhukhan (vmcb12->save.cr3 & MSR_CR3_LONG_MBZ_MASK)) 255761e4169SKrish Sadhukhan return false; 256761e4169SKrish Sadhukhan } 257ee69c92bSSean Christopherson if (!kvm_is_valid_cr4(&svm->vcpu, vmcb12->save.cr4)) 258761e4169SKrish Sadhukhan return false; 259761e4169SKrish Sadhukhan 2600dd16b5bSMaxim Levitsky return nested_vmcb_check_controls(&vmcb12->control); 261883b0a91SJoerg Roedel } 262883b0a91SJoerg Roedel 2633e06f016SPaolo Bonzini static void load_nested_vmcb_control(struct vcpu_svm *svm, 2643e06f016SPaolo Bonzini struct vmcb_control_area *control) 2653e06f016SPaolo Bonzini { 266e670bf68SPaolo Bonzini copy_vmcb_control_area(&svm->nested.ctl, control); 2673e06f016SPaolo Bonzini 268cc440cdaSPaolo Bonzini /* Copy it here because nested_svm_check_controls will check it. */ 269cc440cdaSPaolo Bonzini svm->nested.ctl.asid = control->asid; 270e670bf68SPaolo Bonzini svm->nested.ctl.msrpm_base_pa &= ~0x0fffULL; 271e670bf68SPaolo Bonzini svm->nested.ctl.iopm_base_pa &= ~0x0fffULL; 2723e06f016SPaolo Bonzini } 2733e06f016SPaolo Bonzini 2742d8a42beSPaolo Bonzini /* 2752d8a42beSPaolo Bonzini * Synchronize fields that are written by the processor, so that 2762d8a42beSPaolo Bonzini * they can be copied back into the nested_vmcb. 2772d8a42beSPaolo Bonzini */ 2782d8a42beSPaolo Bonzini void sync_nested_vmcb_control(struct vcpu_svm *svm) 2792d8a42beSPaolo Bonzini { 2802d8a42beSPaolo Bonzini u32 mask; 2812d8a42beSPaolo Bonzini svm->nested.ctl.event_inj = svm->vmcb->control.event_inj; 2822d8a42beSPaolo Bonzini svm->nested.ctl.event_inj_err = svm->vmcb->control.event_inj_err; 2832d8a42beSPaolo Bonzini 2842d8a42beSPaolo Bonzini /* Only a few fields of int_ctl are written by the processor. */ 2852d8a42beSPaolo Bonzini mask = V_IRQ_MASK | V_TPR_MASK; 2862d8a42beSPaolo Bonzini if (!(svm->nested.ctl.int_ctl & V_INTR_MASKING_MASK) && 287a284ba56SJoerg Roedel svm_is_intercept(svm, INTERCEPT_VINTR)) { 2882d8a42beSPaolo Bonzini /* 2892d8a42beSPaolo Bonzini * In order to request an interrupt window, L0 is usurping 2902d8a42beSPaolo Bonzini * svm->vmcb->control.int_ctl and possibly setting V_IRQ 2912d8a42beSPaolo Bonzini * even if it was clear in L1's VMCB. Restoring it would be 2922d8a42beSPaolo Bonzini * wrong. However, in this case V_IRQ will remain true until 2932d8a42beSPaolo Bonzini * interrupt_window_interception calls svm_clear_vintr and 2942d8a42beSPaolo Bonzini * restores int_ctl. We can just leave it aside. 2952d8a42beSPaolo Bonzini */ 2962d8a42beSPaolo Bonzini mask &= ~V_IRQ_MASK; 2972d8a42beSPaolo Bonzini } 2982d8a42beSPaolo Bonzini svm->nested.ctl.int_ctl &= ~mask; 2992d8a42beSPaolo Bonzini svm->nested.ctl.int_ctl |= svm->vmcb->control.int_ctl & mask; 3002d8a42beSPaolo Bonzini } 3012d8a42beSPaolo Bonzini 30236e2e983SPaolo Bonzini /* 30336e2e983SPaolo Bonzini * Transfer any event that L0 or L1 wanted to inject into L2 to 30436e2e983SPaolo Bonzini * EXIT_INT_INFO. 30536e2e983SPaolo Bonzini */ 30636e2e983SPaolo Bonzini static void nested_vmcb_save_pending_event(struct vcpu_svm *svm, 3070dd16b5bSMaxim Levitsky struct vmcb *vmcb12) 30836e2e983SPaolo Bonzini { 30936e2e983SPaolo Bonzini struct kvm_vcpu *vcpu = &svm->vcpu; 31036e2e983SPaolo Bonzini u32 exit_int_info = 0; 31136e2e983SPaolo Bonzini unsigned int nr; 31236e2e983SPaolo Bonzini 31336e2e983SPaolo Bonzini if (vcpu->arch.exception.injected) { 31436e2e983SPaolo Bonzini nr = vcpu->arch.exception.nr; 31536e2e983SPaolo Bonzini exit_int_info = nr | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT; 31636e2e983SPaolo Bonzini 31736e2e983SPaolo Bonzini if (vcpu->arch.exception.has_error_code) { 31836e2e983SPaolo Bonzini exit_int_info |= SVM_EVTINJ_VALID_ERR; 3190dd16b5bSMaxim Levitsky vmcb12->control.exit_int_info_err = 32036e2e983SPaolo Bonzini vcpu->arch.exception.error_code; 32136e2e983SPaolo Bonzini } 32236e2e983SPaolo Bonzini 32336e2e983SPaolo Bonzini } else if (vcpu->arch.nmi_injected) { 32436e2e983SPaolo Bonzini exit_int_info = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI; 32536e2e983SPaolo Bonzini 32636e2e983SPaolo Bonzini } else if (vcpu->arch.interrupt.injected) { 32736e2e983SPaolo Bonzini nr = vcpu->arch.interrupt.nr; 32836e2e983SPaolo Bonzini exit_int_info = nr | SVM_EVTINJ_VALID; 32936e2e983SPaolo Bonzini 33036e2e983SPaolo Bonzini if (vcpu->arch.interrupt.soft) 33136e2e983SPaolo Bonzini exit_int_info |= SVM_EVTINJ_TYPE_SOFT; 33236e2e983SPaolo Bonzini else 33336e2e983SPaolo Bonzini exit_int_info |= SVM_EVTINJ_TYPE_INTR; 33436e2e983SPaolo Bonzini } 33536e2e983SPaolo Bonzini 3360dd16b5bSMaxim Levitsky vmcb12->control.exit_int_info = exit_int_info; 33736e2e983SPaolo Bonzini } 33836e2e983SPaolo Bonzini 33962156f6cSVitaly Kuznetsov static inline bool nested_npt_enabled(struct vcpu_svm *svm) 34062156f6cSVitaly Kuznetsov { 34162156f6cSVitaly Kuznetsov return svm->nested.ctl.nested_ctl & SVM_NESTED_CTL_NP_ENABLE; 34262156f6cSVitaly Kuznetsov } 34362156f6cSVitaly Kuznetsov 34462156f6cSVitaly Kuznetsov /* 345d82aaef9SVitaly Kuznetsov * Load guest's/host's cr3 on nested vmentry or vmexit. @nested_npt is true 346d82aaef9SVitaly Kuznetsov * if we are emulating VM-Entry into a guest with NPT enabled. 34762156f6cSVitaly Kuznetsov */ 34862156f6cSVitaly Kuznetsov static int nested_svm_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, 34962156f6cSVitaly Kuznetsov bool nested_npt) 35062156f6cSVitaly Kuznetsov { 351a506fdd2SVitaly Kuznetsov if (cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 63)) 352a506fdd2SVitaly Kuznetsov return -EINVAL; 353a506fdd2SVitaly Kuznetsov 354a506fdd2SVitaly Kuznetsov if (!nested_npt && is_pae_paging(vcpu) && 355a506fdd2SVitaly Kuznetsov (cr3 != kvm_read_cr3(vcpu) || pdptrs_changed(vcpu))) { 356a506fdd2SVitaly Kuznetsov if (!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3)) 357a506fdd2SVitaly Kuznetsov return -EINVAL; 358a506fdd2SVitaly Kuznetsov } 359a506fdd2SVitaly Kuznetsov 360a506fdd2SVitaly Kuznetsov /* 361a506fdd2SVitaly Kuznetsov * TODO: optimize unconditional TLB flush/MMU sync here and in 362a506fdd2SVitaly Kuznetsov * kvm_init_shadow_npt_mmu(). 363a506fdd2SVitaly Kuznetsov */ 364a506fdd2SVitaly Kuznetsov if (!nested_npt) 365a506fdd2SVitaly Kuznetsov kvm_mmu_new_pgd(vcpu, cr3, false, false); 366a506fdd2SVitaly Kuznetsov 367a506fdd2SVitaly Kuznetsov vcpu->arch.cr3 = cr3; 368a506fdd2SVitaly Kuznetsov kvm_register_mark_available(vcpu, VCPU_EXREG_CR3); 369a506fdd2SVitaly Kuznetsov 370a506fdd2SVitaly Kuznetsov kvm_init_mmu(vcpu, false); 371a506fdd2SVitaly Kuznetsov 372a506fdd2SVitaly Kuznetsov return 0; 37362156f6cSVitaly Kuznetsov } 37462156f6cSVitaly Kuznetsov 3750dd16b5bSMaxim Levitsky static void nested_prepare_vmcb_save(struct vcpu_svm *svm, struct vmcb *vmcb12) 376883b0a91SJoerg Roedel { 377883b0a91SJoerg Roedel /* Load the nested guest state */ 3780dd16b5bSMaxim Levitsky svm->vmcb->save.es = vmcb12->save.es; 3790dd16b5bSMaxim Levitsky svm->vmcb->save.cs = vmcb12->save.cs; 3800dd16b5bSMaxim Levitsky svm->vmcb->save.ss = vmcb12->save.ss; 3810dd16b5bSMaxim Levitsky svm->vmcb->save.ds = vmcb12->save.ds; 3820dd16b5bSMaxim Levitsky svm->vmcb->save.gdtr = vmcb12->save.gdtr; 3830dd16b5bSMaxim Levitsky svm->vmcb->save.idtr = vmcb12->save.idtr; 3848cce12b3SPaolo Bonzini kvm_set_rflags(&svm->vcpu, vmcb12->save.rflags | X86_EFLAGS_FIXED); 3850dd16b5bSMaxim Levitsky svm_set_efer(&svm->vcpu, vmcb12->save.efer); 3860dd16b5bSMaxim Levitsky svm_set_cr0(&svm->vcpu, vmcb12->save.cr0); 3870dd16b5bSMaxim Levitsky svm_set_cr4(&svm->vcpu, vmcb12->save.cr4); 3880dd16b5bSMaxim Levitsky svm->vmcb->save.cr2 = svm->vcpu.arch.cr2 = vmcb12->save.cr2; 3890dd16b5bSMaxim Levitsky kvm_rax_write(&svm->vcpu, vmcb12->save.rax); 3900dd16b5bSMaxim Levitsky kvm_rsp_write(&svm->vcpu, vmcb12->save.rsp); 3910dd16b5bSMaxim Levitsky kvm_rip_write(&svm->vcpu, vmcb12->save.rip); 392883b0a91SJoerg Roedel 393883b0a91SJoerg Roedel /* In case we don't even reach vcpu_run, the fields are not updated */ 3940dd16b5bSMaxim Levitsky svm->vmcb->save.rax = vmcb12->save.rax; 3950dd16b5bSMaxim Levitsky svm->vmcb->save.rsp = vmcb12->save.rsp; 3960dd16b5bSMaxim Levitsky svm->vmcb->save.rip = vmcb12->save.rip; 3978cce12b3SPaolo Bonzini svm->vmcb->save.dr7 = vmcb12->save.dr7 | DR7_FIXED_1; 3988cce12b3SPaolo Bonzini svm->vcpu.arch.dr6 = vmcb12->save.dr6 | DR6_FIXED_1 | DR6_RTM; 3990dd16b5bSMaxim Levitsky svm->vmcb->save.cpl = vmcb12->save.cpl; 400f241d711SPaolo Bonzini } 401883b0a91SJoerg Roedel 402e670bf68SPaolo Bonzini static void nested_prepare_vmcb_control(struct vcpu_svm *svm) 403f241d711SPaolo Bonzini { 40491b7130cSPaolo Bonzini const u32 mask = V_INTR_MASKING_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK; 40562156f6cSVitaly Kuznetsov 40662156f6cSVitaly Kuznetsov if (nested_npt_enabled(svm)) 40769cb8774SPaolo Bonzini nested_svm_init_mmu_context(&svm->vcpu); 40869cb8774SPaolo Bonzini 40918fc6c55SPaolo Bonzini svm->vmcb->control.tsc_offset = svm->vcpu.arch.tsc_offset = 410e670bf68SPaolo Bonzini svm->vcpu.arch.l1_tsc_offset + svm->nested.ctl.tsc_offset; 411883b0a91SJoerg Roedel 41291b7130cSPaolo Bonzini svm->vmcb->control.int_ctl = 41391b7130cSPaolo Bonzini (svm->nested.ctl.int_ctl & ~mask) | 41491b7130cSPaolo Bonzini (svm->nested.hsave->control.int_ctl & mask); 41591b7130cSPaolo Bonzini 416e670bf68SPaolo Bonzini svm->vmcb->control.virt_ext = svm->nested.ctl.virt_ext; 417e670bf68SPaolo Bonzini svm->vmcb->control.int_vector = svm->nested.ctl.int_vector; 418e670bf68SPaolo Bonzini svm->vmcb->control.int_state = svm->nested.ctl.int_state; 419e670bf68SPaolo Bonzini svm->vmcb->control.event_inj = svm->nested.ctl.event_inj; 420e670bf68SPaolo Bonzini svm->vmcb->control.event_inj_err = svm->nested.ctl.event_inj_err; 421883b0a91SJoerg Roedel 422e670bf68SPaolo Bonzini svm->vmcb->control.pause_filter_count = svm->nested.ctl.pause_filter_count; 423e670bf68SPaolo Bonzini svm->vmcb->control.pause_filter_thresh = svm->nested.ctl.pause_filter_thresh; 424883b0a91SJoerg Roedel 425883b0a91SJoerg Roedel /* Enter Guest-Mode */ 426883b0a91SJoerg Roedel enter_guest_mode(&svm->vcpu); 427883b0a91SJoerg Roedel 428883b0a91SJoerg Roedel /* 429883b0a91SJoerg Roedel * Merge guest and host intercepts - must be called with vcpu in 430883b0a91SJoerg Roedel * guest-mode to take affect here 431883b0a91SJoerg Roedel */ 432883b0a91SJoerg Roedel recalc_intercepts(svm); 433883b0a91SJoerg Roedel 43406e7852cSJoerg Roedel vmcb_mark_all_dirty(svm->vmcb); 435f241d711SPaolo Bonzini } 436f241d711SPaolo Bonzini 4370dd16b5bSMaxim Levitsky int enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb12_gpa, 4380dd16b5bSMaxim Levitsky struct vmcb *vmcb12) 439f241d711SPaolo Bonzini { 440a506fdd2SVitaly Kuznetsov int ret; 441a506fdd2SVitaly Kuznetsov 4420dd16b5bSMaxim Levitsky svm->nested.vmcb12_gpa = vmcb12_gpa; 4430dd16b5bSMaxim Levitsky load_nested_vmcb_control(svm, &vmcb12->control); 4440dd16b5bSMaxim Levitsky nested_prepare_vmcb_save(svm, vmcb12); 445e670bf68SPaolo Bonzini nested_prepare_vmcb_control(svm); 446f241d711SPaolo Bonzini 4470dd16b5bSMaxim Levitsky ret = nested_svm_load_cr3(&svm->vcpu, vmcb12->save.cr3, 448a506fdd2SVitaly Kuznetsov nested_npt_enabled(svm)); 449a506fdd2SVitaly Kuznetsov if (ret) 450a506fdd2SVitaly Kuznetsov return ret; 451a506fdd2SVitaly Kuznetsov 452ffdf7f9eSPaolo Bonzini svm_set_gif(svm, true); 45359cd9bc5SVitaly Kuznetsov 45459cd9bc5SVitaly Kuznetsov return 0; 455883b0a91SJoerg Roedel } 456883b0a91SJoerg Roedel 457883b0a91SJoerg Roedel int nested_svm_vmrun(struct vcpu_svm *svm) 458883b0a91SJoerg Roedel { 459883b0a91SJoerg Roedel int ret; 4600dd16b5bSMaxim Levitsky struct vmcb *vmcb12; 461883b0a91SJoerg Roedel struct vmcb *hsave = svm->nested.hsave; 462883b0a91SJoerg Roedel struct vmcb *vmcb = svm->vmcb; 463883b0a91SJoerg Roedel struct kvm_host_map map; 4640dd16b5bSMaxim Levitsky u64 vmcb12_gpa; 465883b0a91SJoerg Roedel 4667c67f546SPaolo Bonzini if (is_smm(&svm->vcpu)) { 4677c67f546SPaolo Bonzini kvm_queue_exception(&svm->vcpu, UD_VECTOR); 4687c67f546SPaolo Bonzini return 1; 4697c67f546SPaolo Bonzini } 470883b0a91SJoerg Roedel 4710dd16b5bSMaxim Levitsky vmcb12_gpa = svm->vmcb->save.rax; 4720dd16b5bSMaxim Levitsky ret = kvm_vcpu_map(&svm->vcpu, gpa_to_gfn(vmcb12_gpa), &map); 473883b0a91SJoerg Roedel if (ret == -EINVAL) { 474883b0a91SJoerg Roedel kvm_inject_gp(&svm->vcpu, 0); 475883b0a91SJoerg Roedel return 1; 476883b0a91SJoerg Roedel } else if (ret) { 477883b0a91SJoerg Roedel return kvm_skip_emulated_instruction(&svm->vcpu); 478883b0a91SJoerg Roedel } 479883b0a91SJoerg Roedel 480883b0a91SJoerg Roedel ret = kvm_skip_emulated_instruction(&svm->vcpu); 481883b0a91SJoerg Roedel 4820dd16b5bSMaxim Levitsky vmcb12 = map.hva; 483883b0a91SJoerg Roedel 4842fcf4876SMaxim Levitsky if (WARN_ON_ONCE(!svm->nested.initialized)) 4852fcf4876SMaxim Levitsky return -EINVAL; 4862fcf4876SMaxim Levitsky 4870dd16b5bSMaxim Levitsky if (!nested_vmcb_checks(svm, vmcb12)) { 4880dd16b5bSMaxim Levitsky vmcb12->control.exit_code = SVM_EXIT_ERR; 4890dd16b5bSMaxim Levitsky vmcb12->control.exit_code_hi = 0; 4900dd16b5bSMaxim Levitsky vmcb12->control.exit_info_1 = 0; 4910dd16b5bSMaxim Levitsky vmcb12->control.exit_info_2 = 0; 49269c9dfa2SPaolo Bonzini goto out; 493883b0a91SJoerg Roedel } 494883b0a91SJoerg Roedel 4950dd16b5bSMaxim Levitsky trace_kvm_nested_vmrun(svm->vmcb->save.rip, vmcb12_gpa, 4960dd16b5bSMaxim Levitsky vmcb12->save.rip, 4970dd16b5bSMaxim Levitsky vmcb12->control.int_ctl, 4980dd16b5bSMaxim Levitsky vmcb12->control.event_inj, 4990dd16b5bSMaxim Levitsky vmcb12->control.nested_ctl); 500883b0a91SJoerg Roedel 50103bfeeb9SBabu Moger trace_kvm_nested_intercepts(vmcb12->control.intercepts[INTERCEPT_CR] & 0xffff, 50203bfeeb9SBabu Moger vmcb12->control.intercepts[INTERCEPT_CR] >> 16, 5039780d51dSBabu Moger vmcb12->control.intercepts[INTERCEPT_EXCEPTION], 504c62e2e94SBabu Moger vmcb12->control.intercepts[INTERCEPT_WORD3], 5054c44e8d6SBabu Moger vmcb12->control.intercepts[INTERCEPT_WORD4], 5064c44e8d6SBabu Moger vmcb12->control.intercepts[INTERCEPT_WORD5]); 507883b0a91SJoerg Roedel 508883b0a91SJoerg Roedel /* Clear internal status */ 509883b0a91SJoerg Roedel kvm_clear_exception_queue(&svm->vcpu); 510883b0a91SJoerg Roedel kvm_clear_interrupt_queue(&svm->vcpu); 511883b0a91SJoerg Roedel 512883b0a91SJoerg Roedel /* 513883b0a91SJoerg Roedel * Save the old vmcb, so we don't need to pick what we save, but can 514883b0a91SJoerg Roedel * restore everything when a VMEXIT occurs 515883b0a91SJoerg Roedel */ 516883b0a91SJoerg Roedel hsave->save.es = vmcb->save.es; 517883b0a91SJoerg Roedel hsave->save.cs = vmcb->save.cs; 518883b0a91SJoerg Roedel hsave->save.ss = vmcb->save.ss; 519883b0a91SJoerg Roedel hsave->save.ds = vmcb->save.ds; 520883b0a91SJoerg Roedel hsave->save.gdtr = vmcb->save.gdtr; 521883b0a91SJoerg Roedel hsave->save.idtr = vmcb->save.idtr; 522883b0a91SJoerg Roedel hsave->save.efer = svm->vcpu.arch.efer; 523883b0a91SJoerg Roedel hsave->save.cr0 = kvm_read_cr0(&svm->vcpu); 524883b0a91SJoerg Roedel hsave->save.cr4 = svm->vcpu.arch.cr4; 525883b0a91SJoerg Roedel hsave->save.rflags = kvm_get_rflags(&svm->vcpu); 526883b0a91SJoerg Roedel hsave->save.rip = kvm_rip_read(&svm->vcpu); 527883b0a91SJoerg Roedel hsave->save.rsp = vmcb->save.rsp; 528883b0a91SJoerg Roedel hsave->save.rax = vmcb->save.rax; 529883b0a91SJoerg Roedel if (npt_enabled) 530883b0a91SJoerg Roedel hsave->save.cr3 = vmcb->save.cr3; 531883b0a91SJoerg Roedel else 532883b0a91SJoerg Roedel hsave->save.cr3 = kvm_read_cr3(&svm->vcpu); 533883b0a91SJoerg Roedel 5342f675917SPaolo Bonzini copy_vmcb_control_area(&hsave->control, &vmcb->control); 535883b0a91SJoerg Roedel 536f74f9414SPaolo Bonzini svm->nested.nested_run_pending = 1; 537883b0a91SJoerg Roedel 5380dd16b5bSMaxim Levitsky if (enter_svm_guest_mode(svm, vmcb12_gpa, vmcb12)) 53959cd9bc5SVitaly Kuznetsov goto out_exit_err; 54059cd9bc5SVitaly Kuznetsov 54159cd9bc5SVitaly Kuznetsov if (nested_svm_vmrun_msrpm(svm)) 54259cd9bc5SVitaly Kuznetsov goto out; 54359cd9bc5SVitaly Kuznetsov 54459cd9bc5SVitaly Kuznetsov out_exit_err: 545ebdb3dbaSVitaly Kuznetsov svm->nested.nested_run_pending = 0; 546ebdb3dbaSVitaly Kuznetsov 547883b0a91SJoerg Roedel svm->vmcb->control.exit_code = SVM_EXIT_ERR; 548883b0a91SJoerg Roedel svm->vmcb->control.exit_code_hi = 0; 549883b0a91SJoerg Roedel svm->vmcb->control.exit_info_1 = 0; 550883b0a91SJoerg Roedel svm->vmcb->control.exit_info_2 = 0; 551883b0a91SJoerg Roedel 552883b0a91SJoerg Roedel nested_svm_vmexit(svm); 553883b0a91SJoerg Roedel 55469c9dfa2SPaolo Bonzini out: 55569c9dfa2SPaolo Bonzini kvm_vcpu_unmap(&svm->vcpu, &map, true); 55669c9dfa2SPaolo Bonzini 557883b0a91SJoerg Roedel return ret; 558883b0a91SJoerg Roedel } 559883b0a91SJoerg Roedel 560883b0a91SJoerg Roedel void nested_svm_vmloadsave(struct vmcb *from_vmcb, struct vmcb *to_vmcb) 561883b0a91SJoerg Roedel { 562883b0a91SJoerg Roedel to_vmcb->save.fs = from_vmcb->save.fs; 563883b0a91SJoerg Roedel to_vmcb->save.gs = from_vmcb->save.gs; 564883b0a91SJoerg Roedel to_vmcb->save.tr = from_vmcb->save.tr; 565883b0a91SJoerg Roedel to_vmcb->save.ldtr = from_vmcb->save.ldtr; 566883b0a91SJoerg Roedel to_vmcb->save.kernel_gs_base = from_vmcb->save.kernel_gs_base; 567883b0a91SJoerg Roedel to_vmcb->save.star = from_vmcb->save.star; 568883b0a91SJoerg Roedel to_vmcb->save.lstar = from_vmcb->save.lstar; 569883b0a91SJoerg Roedel to_vmcb->save.cstar = from_vmcb->save.cstar; 570883b0a91SJoerg Roedel to_vmcb->save.sfmask = from_vmcb->save.sfmask; 571883b0a91SJoerg Roedel to_vmcb->save.sysenter_cs = from_vmcb->save.sysenter_cs; 572883b0a91SJoerg Roedel to_vmcb->save.sysenter_esp = from_vmcb->save.sysenter_esp; 573883b0a91SJoerg Roedel to_vmcb->save.sysenter_eip = from_vmcb->save.sysenter_eip; 574883b0a91SJoerg Roedel } 575883b0a91SJoerg Roedel 576883b0a91SJoerg Roedel int nested_svm_vmexit(struct vcpu_svm *svm) 577883b0a91SJoerg Roedel { 578883b0a91SJoerg Roedel int rc; 5790dd16b5bSMaxim Levitsky struct vmcb *vmcb12; 580883b0a91SJoerg Roedel struct vmcb *hsave = svm->nested.hsave; 581883b0a91SJoerg Roedel struct vmcb *vmcb = svm->vmcb; 582883b0a91SJoerg Roedel struct kvm_host_map map; 583883b0a91SJoerg Roedel 5840dd16b5bSMaxim Levitsky rc = kvm_vcpu_map(&svm->vcpu, gpa_to_gfn(svm->nested.vmcb12_gpa), &map); 585883b0a91SJoerg Roedel if (rc) { 586883b0a91SJoerg Roedel if (rc == -EINVAL) 587883b0a91SJoerg Roedel kvm_inject_gp(&svm->vcpu, 0); 588883b0a91SJoerg Roedel return 1; 589883b0a91SJoerg Roedel } 590883b0a91SJoerg Roedel 5910dd16b5bSMaxim Levitsky vmcb12 = map.hva; 592883b0a91SJoerg Roedel 593883b0a91SJoerg Roedel /* Exit Guest-Mode */ 594883b0a91SJoerg Roedel leave_guest_mode(&svm->vcpu); 5950dd16b5bSMaxim Levitsky svm->nested.vmcb12_gpa = 0; 5962d8a42beSPaolo Bonzini WARN_ON_ONCE(svm->nested.nested_run_pending); 597883b0a91SJoerg Roedel 59838c0b192SPaolo Bonzini /* in case we halted in L2 */ 59938c0b192SPaolo Bonzini svm->vcpu.arch.mp_state = KVM_MP_STATE_RUNNABLE; 60038c0b192SPaolo Bonzini 601883b0a91SJoerg Roedel /* Give the current vmcb to the guest */ 602883b0a91SJoerg Roedel 6030dd16b5bSMaxim Levitsky vmcb12->save.es = vmcb->save.es; 6040dd16b5bSMaxim Levitsky vmcb12->save.cs = vmcb->save.cs; 6050dd16b5bSMaxim Levitsky vmcb12->save.ss = vmcb->save.ss; 6060dd16b5bSMaxim Levitsky vmcb12->save.ds = vmcb->save.ds; 6070dd16b5bSMaxim Levitsky vmcb12->save.gdtr = vmcb->save.gdtr; 6080dd16b5bSMaxim Levitsky vmcb12->save.idtr = vmcb->save.idtr; 6090dd16b5bSMaxim Levitsky vmcb12->save.efer = svm->vcpu.arch.efer; 6100dd16b5bSMaxim Levitsky vmcb12->save.cr0 = kvm_read_cr0(&svm->vcpu); 6110dd16b5bSMaxim Levitsky vmcb12->save.cr3 = kvm_read_cr3(&svm->vcpu); 6120dd16b5bSMaxim Levitsky vmcb12->save.cr2 = vmcb->save.cr2; 6130dd16b5bSMaxim Levitsky vmcb12->save.cr4 = svm->vcpu.arch.cr4; 6140dd16b5bSMaxim Levitsky vmcb12->save.rflags = kvm_get_rflags(&svm->vcpu); 6150dd16b5bSMaxim Levitsky vmcb12->save.rip = kvm_rip_read(&svm->vcpu); 6160dd16b5bSMaxim Levitsky vmcb12->save.rsp = kvm_rsp_read(&svm->vcpu); 6170dd16b5bSMaxim Levitsky vmcb12->save.rax = kvm_rax_read(&svm->vcpu); 6180dd16b5bSMaxim Levitsky vmcb12->save.dr7 = vmcb->save.dr7; 6190dd16b5bSMaxim Levitsky vmcb12->save.dr6 = svm->vcpu.arch.dr6; 6200dd16b5bSMaxim Levitsky vmcb12->save.cpl = vmcb->save.cpl; 621883b0a91SJoerg Roedel 6220dd16b5bSMaxim Levitsky vmcb12->control.int_state = vmcb->control.int_state; 6230dd16b5bSMaxim Levitsky vmcb12->control.exit_code = vmcb->control.exit_code; 6240dd16b5bSMaxim Levitsky vmcb12->control.exit_code_hi = vmcb->control.exit_code_hi; 6250dd16b5bSMaxim Levitsky vmcb12->control.exit_info_1 = vmcb->control.exit_info_1; 6260dd16b5bSMaxim Levitsky vmcb12->control.exit_info_2 = vmcb->control.exit_info_2; 62736e2e983SPaolo Bonzini 6280dd16b5bSMaxim Levitsky if (vmcb12->control.exit_code != SVM_EXIT_ERR) 6290dd16b5bSMaxim Levitsky nested_vmcb_save_pending_event(svm, vmcb12); 630883b0a91SJoerg Roedel 631883b0a91SJoerg Roedel if (svm->nrips_enabled) 6320dd16b5bSMaxim Levitsky vmcb12->control.next_rip = vmcb->control.next_rip; 633883b0a91SJoerg Roedel 6340dd16b5bSMaxim Levitsky vmcb12->control.int_ctl = svm->nested.ctl.int_ctl; 6350dd16b5bSMaxim Levitsky vmcb12->control.tlb_ctl = svm->nested.ctl.tlb_ctl; 6360dd16b5bSMaxim Levitsky vmcb12->control.event_inj = svm->nested.ctl.event_inj; 6370dd16b5bSMaxim Levitsky vmcb12->control.event_inj_err = svm->nested.ctl.event_inj_err; 638883b0a91SJoerg Roedel 6390dd16b5bSMaxim Levitsky vmcb12->control.pause_filter_count = 640883b0a91SJoerg Roedel svm->vmcb->control.pause_filter_count; 6410dd16b5bSMaxim Levitsky vmcb12->control.pause_filter_thresh = 642883b0a91SJoerg Roedel svm->vmcb->control.pause_filter_thresh; 643883b0a91SJoerg Roedel 644883b0a91SJoerg Roedel /* Restore the original control entries */ 6452f675917SPaolo Bonzini copy_vmcb_control_area(&vmcb->control, &hsave->control); 646883b0a91SJoerg Roedel 6479883764aSMaxim Levitsky /* On vmexit the GIF is set to false */ 6489883764aSMaxim Levitsky svm_set_gif(svm, false); 6499883764aSMaxim Levitsky 65018fc6c55SPaolo Bonzini svm->vmcb->control.tsc_offset = svm->vcpu.arch.tsc_offset = 65118fc6c55SPaolo Bonzini svm->vcpu.arch.l1_tsc_offset; 65218fc6c55SPaolo Bonzini 653e670bf68SPaolo Bonzini svm->nested.ctl.nested_cr3 = 0; 654883b0a91SJoerg Roedel 655883b0a91SJoerg Roedel /* Restore selected save entries */ 656883b0a91SJoerg Roedel svm->vmcb->save.es = hsave->save.es; 657883b0a91SJoerg Roedel svm->vmcb->save.cs = hsave->save.cs; 658883b0a91SJoerg Roedel svm->vmcb->save.ss = hsave->save.ss; 659883b0a91SJoerg Roedel svm->vmcb->save.ds = hsave->save.ds; 660883b0a91SJoerg Roedel svm->vmcb->save.gdtr = hsave->save.gdtr; 661883b0a91SJoerg Roedel svm->vmcb->save.idtr = hsave->save.idtr; 662883b0a91SJoerg Roedel kvm_set_rflags(&svm->vcpu, hsave->save.rflags); 6638cce12b3SPaolo Bonzini kvm_set_rflags(&svm->vcpu, hsave->save.rflags | X86_EFLAGS_FIXED); 664883b0a91SJoerg Roedel svm_set_efer(&svm->vcpu, hsave->save.efer); 665883b0a91SJoerg Roedel svm_set_cr0(&svm->vcpu, hsave->save.cr0 | X86_CR0_PE); 666883b0a91SJoerg Roedel svm_set_cr4(&svm->vcpu, hsave->save.cr4); 667883b0a91SJoerg Roedel kvm_rax_write(&svm->vcpu, hsave->save.rax); 668883b0a91SJoerg Roedel kvm_rsp_write(&svm->vcpu, hsave->save.rsp); 669883b0a91SJoerg Roedel kvm_rip_write(&svm->vcpu, hsave->save.rip); 6708cce12b3SPaolo Bonzini svm->vmcb->save.dr7 = DR7_FIXED_1; 671883b0a91SJoerg Roedel svm->vmcb->save.cpl = 0; 672883b0a91SJoerg Roedel svm->vmcb->control.exit_int_info = 0; 673883b0a91SJoerg Roedel 67406e7852cSJoerg Roedel vmcb_mark_all_dirty(svm->vmcb); 675883b0a91SJoerg Roedel 6760dd16b5bSMaxim Levitsky trace_kvm_nested_vmexit_inject(vmcb12->control.exit_code, 6770dd16b5bSMaxim Levitsky vmcb12->control.exit_info_1, 6780dd16b5bSMaxim Levitsky vmcb12->control.exit_info_2, 6790dd16b5bSMaxim Levitsky vmcb12->control.exit_int_info, 6800dd16b5bSMaxim Levitsky vmcb12->control.exit_int_info_err, 68136e2e983SPaolo Bonzini KVM_ISA_SVM); 68236e2e983SPaolo Bonzini 683883b0a91SJoerg Roedel kvm_vcpu_unmap(&svm->vcpu, &map, true); 684883b0a91SJoerg Roedel 685883b0a91SJoerg Roedel nested_svm_uninit_mmu_context(&svm->vcpu); 686bf7dea42SVitaly Kuznetsov 687d82aaef9SVitaly Kuznetsov rc = nested_svm_load_cr3(&svm->vcpu, hsave->save.cr3, false); 688d82aaef9SVitaly Kuznetsov if (rc) 689d82aaef9SVitaly Kuznetsov return 1; 690bf7dea42SVitaly Kuznetsov 691d82aaef9SVitaly Kuznetsov if (npt_enabled) 692d82aaef9SVitaly Kuznetsov svm->vmcb->save.cr3 = hsave->save.cr3; 693883b0a91SJoerg Roedel 694883b0a91SJoerg Roedel /* 695883b0a91SJoerg Roedel * Drop what we picked up for L2 via svm_complete_interrupts() so it 696883b0a91SJoerg Roedel * doesn't end up in L1. 697883b0a91SJoerg Roedel */ 698883b0a91SJoerg Roedel svm->vcpu.arch.nmi_injected = false; 699883b0a91SJoerg Roedel kvm_clear_exception_queue(&svm->vcpu); 700883b0a91SJoerg Roedel kvm_clear_interrupt_queue(&svm->vcpu); 701883b0a91SJoerg Roedel 702883b0a91SJoerg Roedel return 0; 703883b0a91SJoerg Roedel } 704883b0a91SJoerg Roedel 7052fcf4876SMaxim Levitsky int svm_allocate_nested(struct vcpu_svm *svm) 7062fcf4876SMaxim Levitsky { 7072fcf4876SMaxim Levitsky struct page *hsave_page; 7082fcf4876SMaxim Levitsky 7092fcf4876SMaxim Levitsky if (svm->nested.initialized) 7102fcf4876SMaxim Levitsky return 0; 7112fcf4876SMaxim Levitsky 7122fcf4876SMaxim Levitsky hsave_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO); 7132fcf4876SMaxim Levitsky if (!hsave_page) 7142fcf4876SMaxim Levitsky return -ENOMEM; 7152fcf4876SMaxim Levitsky svm->nested.hsave = page_address(hsave_page); 7162fcf4876SMaxim Levitsky 7172fcf4876SMaxim Levitsky svm->nested.msrpm = svm_vcpu_alloc_msrpm(); 7182fcf4876SMaxim Levitsky if (!svm->nested.msrpm) 7192fcf4876SMaxim Levitsky goto err_free_hsave; 7202fcf4876SMaxim Levitsky svm_vcpu_init_msrpm(&svm->vcpu, svm->nested.msrpm); 7212fcf4876SMaxim Levitsky 7222fcf4876SMaxim Levitsky svm->nested.initialized = true; 7232fcf4876SMaxim Levitsky return 0; 7242fcf4876SMaxim Levitsky 7252fcf4876SMaxim Levitsky err_free_hsave: 7262fcf4876SMaxim Levitsky __free_page(hsave_page); 7272fcf4876SMaxim Levitsky return -ENOMEM; 7282fcf4876SMaxim Levitsky } 7292fcf4876SMaxim Levitsky 7302fcf4876SMaxim Levitsky void svm_free_nested(struct vcpu_svm *svm) 7312fcf4876SMaxim Levitsky { 7322fcf4876SMaxim Levitsky if (!svm->nested.initialized) 7332fcf4876SMaxim Levitsky return; 7342fcf4876SMaxim Levitsky 7352fcf4876SMaxim Levitsky svm_vcpu_free_msrpm(svm->nested.msrpm); 7362fcf4876SMaxim Levitsky svm->nested.msrpm = NULL; 7372fcf4876SMaxim Levitsky 7382fcf4876SMaxim Levitsky __free_page(virt_to_page(svm->nested.hsave)); 7392fcf4876SMaxim Levitsky svm->nested.hsave = NULL; 7402fcf4876SMaxim Levitsky 7412fcf4876SMaxim Levitsky svm->nested.initialized = false; 7422fcf4876SMaxim Levitsky } 7432fcf4876SMaxim Levitsky 744c513f484SPaolo Bonzini /* 745c513f484SPaolo Bonzini * Forcibly leave nested mode in order to be able to reset the VCPU later on. 746c513f484SPaolo Bonzini */ 747c513f484SPaolo Bonzini void svm_leave_nested(struct vcpu_svm *svm) 748c513f484SPaolo Bonzini { 749c513f484SPaolo Bonzini if (is_guest_mode(&svm->vcpu)) { 750c513f484SPaolo Bonzini struct vmcb *hsave = svm->nested.hsave; 751c513f484SPaolo Bonzini struct vmcb *vmcb = svm->vmcb; 752c513f484SPaolo Bonzini 753c513f484SPaolo Bonzini svm->nested.nested_run_pending = 0; 754c513f484SPaolo Bonzini leave_guest_mode(&svm->vcpu); 755c513f484SPaolo Bonzini copy_vmcb_control_area(&vmcb->control, &hsave->control); 756c513f484SPaolo Bonzini nested_svm_uninit_mmu_context(&svm->vcpu); 757*56fe28deSMaxim Levitsky vmcb_mark_all_dirty(svm->vmcb); 758c513f484SPaolo Bonzini } 759a7d5c7ceSPaolo Bonzini 760a7d5c7ceSPaolo Bonzini kvm_clear_request(KVM_REQ_GET_NESTED_STATE_PAGES, &svm->vcpu); 761c513f484SPaolo Bonzini } 762c513f484SPaolo Bonzini 763883b0a91SJoerg Roedel static int nested_svm_exit_handled_msr(struct vcpu_svm *svm) 764883b0a91SJoerg Roedel { 765883b0a91SJoerg Roedel u32 offset, msr, value; 766883b0a91SJoerg Roedel int write, mask; 767883b0a91SJoerg Roedel 768c62e2e94SBabu Moger if (!(vmcb_is_intercept(&svm->nested.ctl, INTERCEPT_MSR_PROT))) 769883b0a91SJoerg Roedel return NESTED_EXIT_HOST; 770883b0a91SJoerg Roedel 771883b0a91SJoerg Roedel msr = svm->vcpu.arch.regs[VCPU_REGS_RCX]; 772883b0a91SJoerg Roedel offset = svm_msrpm_offset(msr); 773883b0a91SJoerg Roedel write = svm->vmcb->control.exit_info_1 & 1; 774883b0a91SJoerg Roedel mask = 1 << ((2 * (msr & 0xf)) + write); 775883b0a91SJoerg Roedel 776883b0a91SJoerg Roedel if (offset == MSR_INVALID) 777883b0a91SJoerg Roedel return NESTED_EXIT_DONE; 778883b0a91SJoerg Roedel 779883b0a91SJoerg Roedel /* Offset is in 32 bit units but need in 8 bit units */ 780883b0a91SJoerg Roedel offset *= 4; 781883b0a91SJoerg Roedel 782e670bf68SPaolo Bonzini if (kvm_vcpu_read_guest(&svm->vcpu, svm->nested.ctl.msrpm_base_pa + offset, &value, 4)) 783883b0a91SJoerg Roedel return NESTED_EXIT_DONE; 784883b0a91SJoerg Roedel 785883b0a91SJoerg Roedel return (value & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST; 786883b0a91SJoerg Roedel } 787883b0a91SJoerg Roedel 788883b0a91SJoerg Roedel static int nested_svm_intercept_ioio(struct vcpu_svm *svm) 789883b0a91SJoerg Roedel { 790883b0a91SJoerg Roedel unsigned port, size, iopm_len; 791883b0a91SJoerg Roedel u16 val, mask; 792883b0a91SJoerg Roedel u8 start_bit; 793883b0a91SJoerg Roedel u64 gpa; 794883b0a91SJoerg Roedel 795c62e2e94SBabu Moger if (!(vmcb_is_intercept(&svm->nested.ctl, INTERCEPT_IOIO_PROT))) 796883b0a91SJoerg Roedel return NESTED_EXIT_HOST; 797883b0a91SJoerg Roedel 798883b0a91SJoerg Roedel port = svm->vmcb->control.exit_info_1 >> 16; 799883b0a91SJoerg Roedel size = (svm->vmcb->control.exit_info_1 & SVM_IOIO_SIZE_MASK) >> 800883b0a91SJoerg Roedel SVM_IOIO_SIZE_SHIFT; 801e670bf68SPaolo Bonzini gpa = svm->nested.ctl.iopm_base_pa + (port / 8); 802883b0a91SJoerg Roedel start_bit = port % 8; 803883b0a91SJoerg Roedel iopm_len = (start_bit + size > 8) ? 2 : 1; 804883b0a91SJoerg Roedel mask = (0xf >> (4 - size)) << start_bit; 805883b0a91SJoerg Roedel val = 0; 806883b0a91SJoerg Roedel 807883b0a91SJoerg Roedel if (kvm_vcpu_read_guest(&svm->vcpu, gpa, &val, iopm_len)) 808883b0a91SJoerg Roedel return NESTED_EXIT_DONE; 809883b0a91SJoerg Roedel 810883b0a91SJoerg Roedel return (val & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST; 811883b0a91SJoerg Roedel } 812883b0a91SJoerg Roedel 813883b0a91SJoerg Roedel static int nested_svm_intercept(struct vcpu_svm *svm) 814883b0a91SJoerg Roedel { 815883b0a91SJoerg Roedel u32 exit_code = svm->vmcb->control.exit_code; 816883b0a91SJoerg Roedel int vmexit = NESTED_EXIT_HOST; 817883b0a91SJoerg Roedel 818883b0a91SJoerg Roedel switch (exit_code) { 819883b0a91SJoerg Roedel case SVM_EXIT_MSR: 820883b0a91SJoerg Roedel vmexit = nested_svm_exit_handled_msr(svm); 821883b0a91SJoerg Roedel break; 822883b0a91SJoerg Roedel case SVM_EXIT_IOIO: 823883b0a91SJoerg Roedel vmexit = nested_svm_intercept_ioio(svm); 824883b0a91SJoerg Roedel break; 825883b0a91SJoerg Roedel case SVM_EXIT_READ_CR0 ... SVM_EXIT_WRITE_CR8: { 82603bfeeb9SBabu Moger if (vmcb_is_intercept(&svm->nested.ctl, exit_code)) 827883b0a91SJoerg Roedel vmexit = NESTED_EXIT_DONE; 828883b0a91SJoerg Roedel break; 829883b0a91SJoerg Roedel } 830883b0a91SJoerg Roedel case SVM_EXIT_READ_DR0 ... SVM_EXIT_WRITE_DR7: { 83130abaa88SBabu Moger if (vmcb_is_intercept(&svm->nested.ctl, exit_code)) 832883b0a91SJoerg Roedel vmexit = NESTED_EXIT_DONE; 833883b0a91SJoerg Roedel break; 834883b0a91SJoerg Roedel } 835883b0a91SJoerg Roedel case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: { 8367c86663bSPaolo Bonzini /* 8377c86663bSPaolo Bonzini * Host-intercepted exceptions have been checked already in 8387c86663bSPaolo Bonzini * nested_svm_exit_special. There is nothing to do here, 8397c86663bSPaolo Bonzini * the vmexit is injected by svm_check_nested_events. 8407c86663bSPaolo Bonzini */ 841883b0a91SJoerg Roedel vmexit = NESTED_EXIT_DONE; 842883b0a91SJoerg Roedel break; 843883b0a91SJoerg Roedel } 844883b0a91SJoerg Roedel case SVM_EXIT_ERR: { 845883b0a91SJoerg Roedel vmexit = NESTED_EXIT_DONE; 846883b0a91SJoerg Roedel break; 847883b0a91SJoerg Roedel } 848883b0a91SJoerg Roedel default: { 849c62e2e94SBabu Moger if (vmcb_is_intercept(&svm->nested.ctl, exit_code)) 850883b0a91SJoerg Roedel vmexit = NESTED_EXIT_DONE; 851883b0a91SJoerg Roedel } 852883b0a91SJoerg Roedel } 853883b0a91SJoerg Roedel 854883b0a91SJoerg Roedel return vmexit; 855883b0a91SJoerg Roedel } 856883b0a91SJoerg Roedel 857883b0a91SJoerg Roedel int nested_svm_exit_handled(struct vcpu_svm *svm) 858883b0a91SJoerg Roedel { 859883b0a91SJoerg Roedel int vmexit; 860883b0a91SJoerg Roedel 861883b0a91SJoerg Roedel vmexit = nested_svm_intercept(svm); 862883b0a91SJoerg Roedel 863883b0a91SJoerg Roedel if (vmexit == NESTED_EXIT_DONE) 864883b0a91SJoerg Roedel nested_svm_vmexit(svm); 865883b0a91SJoerg Roedel 866883b0a91SJoerg Roedel return vmexit; 867883b0a91SJoerg Roedel } 868883b0a91SJoerg Roedel 869883b0a91SJoerg Roedel int nested_svm_check_permissions(struct vcpu_svm *svm) 870883b0a91SJoerg Roedel { 871883b0a91SJoerg Roedel if (!(svm->vcpu.arch.efer & EFER_SVME) || 872883b0a91SJoerg Roedel !is_paging(&svm->vcpu)) { 873883b0a91SJoerg Roedel kvm_queue_exception(&svm->vcpu, UD_VECTOR); 874883b0a91SJoerg Roedel return 1; 875883b0a91SJoerg Roedel } 876883b0a91SJoerg Roedel 877883b0a91SJoerg Roedel if (svm->vmcb->save.cpl) { 878883b0a91SJoerg Roedel kvm_inject_gp(&svm->vcpu, 0); 879883b0a91SJoerg Roedel return 1; 880883b0a91SJoerg Roedel } 881883b0a91SJoerg Roedel 882883b0a91SJoerg Roedel return 0; 883883b0a91SJoerg Roedel } 884883b0a91SJoerg Roedel 8857c86663bSPaolo Bonzini static bool nested_exit_on_exception(struct vcpu_svm *svm) 886883b0a91SJoerg Roedel { 8877c86663bSPaolo Bonzini unsigned int nr = svm->vcpu.arch.exception.nr; 888883b0a91SJoerg Roedel 8899780d51dSBabu Moger return (svm->nested.ctl.intercepts[INTERCEPT_EXCEPTION] & BIT(nr)); 8907c86663bSPaolo Bonzini } 891883b0a91SJoerg Roedel 8927c86663bSPaolo Bonzini static void nested_svm_inject_exception_vmexit(struct vcpu_svm *svm) 8937c86663bSPaolo Bonzini { 8947c86663bSPaolo Bonzini unsigned int nr = svm->vcpu.arch.exception.nr; 895883b0a91SJoerg Roedel 896883b0a91SJoerg Roedel svm->vmcb->control.exit_code = SVM_EXIT_EXCP_BASE + nr; 897883b0a91SJoerg Roedel svm->vmcb->control.exit_code_hi = 0; 8987c86663bSPaolo Bonzini 8997c86663bSPaolo Bonzini if (svm->vcpu.arch.exception.has_error_code) 9007c86663bSPaolo Bonzini svm->vmcb->control.exit_info_1 = svm->vcpu.arch.exception.error_code; 901883b0a91SJoerg Roedel 902883b0a91SJoerg Roedel /* 903883b0a91SJoerg Roedel * EXITINFO2 is undefined for all exception intercepts other 904883b0a91SJoerg Roedel * than #PF. 905883b0a91SJoerg Roedel */ 9067c86663bSPaolo Bonzini if (nr == PF_VECTOR) { 907883b0a91SJoerg Roedel if (svm->vcpu.arch.exception.nested_apf) 908883b0a91SJoerg Roedel svm->vmcb->control.exit_info_2 = svm->vcpu.arch.apf.nested_apf_token; 909883b0a91SJoerg Roedel else if (svm->vcpu.arch.exception.has_payload) 910883b0a91SJoerg Roedel svm->vmcb->control.exit_info_2 = svm->vcpu.arch.exception.payload; 911883b0a91SJoerg Roedel else 912883b0a91SJoerg Roedel svm->vmcb->control.exit_info_2 = svm->vcpu.arch.cr2; 9137c86663bSPaolo Bonzini } else if (nr == DB_VECTOR) { 9147c86663bSPaolo Bonzini /* See inject_pending_event. */ 9157c86663bSPaolo Bonzini kvm_deliver_exception_payload(&svm->vcpu); 9167c86663bSPaolo Bonzini if (svm->vcpu.arch.dr7 & DR7_GD) { 9177c86663bSPaolo Bonzini svm->vcpu.arch.dr7 &= ~DR7_GD; 9187c86663bSPaolo Bonzini kvm_update_dr7(&svm->vcpu); 9197c86663bSPaolo Bonzini } 9207c86663bSPaolo Bonzini } else 9217c86663bSPaolo Bonzini WARN_ON(svm->vcpu.arch.exception.has_payload); 922883b0a91SJoerg Roedel 9237c86663bSPaolo Bonzini nested_svm_vmexit(svm); 924883b0a91SJoerg Roedel } 925883b0a91SJoerg Roedel 92655714cddSPaolo Bonzini static void nested_svm_smi(struct vcpu_svm *svm) 92755714cddSPaolo Bonzini { 92855714cddSPaolo Bonzini svm->vmcb->control.exit_code = SVM_EXIT_SMI; 92955714cddSPaolo Bonzini svm->vmcb->control.exit_info_1 = 0; 93055714cddSPaolo Bonzini svm->vmcb->control.exit_info_2 = 0; 93155714cddSPaolo Bonzini 93255714cddSPaolo Bonzini nested_svm_vmexit(svm); 93355714cddSPaolo Bonzini } 93455714cddSPaolo Bonzini 9359c3d370aSCathy Avery static void nested_svm_nmi(struct vcpu_svm *svm) 9369c3d370aSCathy Avery { 9379c3d370aSCathy Avery svm->vmcb->control.exit_code = SVM_EXIT_NMI; 9389c3d370aSCathy Avery svm->vmcb->control.exit_info_1 = 0; 9399c3d370aSCathy Avery svm->vmcb->control.exit_info_2 = 0; 9409c3d370aSCathy Avery 9419c3d370aSCathy Avery nested_svm_vmexit(svm); 9429c3d370aSCathy Avery } 9439c3d370aSCathy Avery 944883b0a91SJoerg Roedel static void nested_svm_intr(struct vcpu_svm *svm) 945883b0a91SJoerg Roedel { 9466e085cbfSPaolo Bonzini trace_kvm_nested_intr_vmexit(svm->vmcb->save.rip); 9476e085cbfSPaolo Bonzini 948883b0a91SJoerg Roedel svm->vmcb->control.exit_code = SVM_EXIT_INTR; 949883b0a91SJoerg Roedel svm->vmcb->control.exit_info_1 = 0; 950883b0a91SJoerg Roedel svm->vmcb->control.exit_info_2 = 0; 951883b0a91SJoerg Roedel 9526e085cbfSPaolo Bonzini nested_svm_vmexit(svm); 953883b0a91SJoerg Roedel } 954883b0a91SJoerg Roedel 9555b672408SPaolo Bonzini static inline bool nested_exit_on_init(struct vcpu_svm *svm) 9565b672408SPaolo Bonzini { 957c62e2e94SBabu Moger return vmcb_is_intercept(&svm->nested.ctl, INTERCEPT_INIT); 9585b672408SPaolo Bonzini } 9595b672408SPaolo Bonzini 9605b672408SPaolo Bonzini static void nested_svm_init(struct vcpu_svm *svm) 9615b672408SPaolo Bonzini { 9625b672408SPaolo Bonzini svm->vmcb->control.exit_code = SVM_EXIT_INIT; 9635b672408SPaolo Bonzini svm->vmcb->control.exit_info_1 = 0; 9645b672408SPaolo Bonzini svm->vmcb->control.exit_info_2 = 0; 9655b672408SPaolo Bonzini 9665b672408SPaolo Bonzini nested_svm_vmexit(svm); 9675b672408SPaolo Bonzini } 9685b672408SPaolo Bonzini 9695b672408SPaolo Bonzini 97033b22172SPaolo Bonzini static int svm_check_nested_events(struct kvm_vcpu *vcpu) 971883b0a91SJoerg Roedel { 972883b0a91SJoerg Roedel struct vcpu_svm *svm = to_svm(vcpu); 973883b0a91SJoerg Roedel bool block_nested_events = 974bd279629SPaolo Bonzini kvm_event_needs_reinjection(vcpu) || svm->nested.nested_run_pending; 9755b672408SPaolo Bonzini struct kvm_lapic *apic = vcpu->arch.apic; 9765b672408SPaolo Bonzini 9775b672408SPaolo Bonzini if (lapic_in_kernel(vcpu) && 9785b672408SPaolo Bonzini test_bit(KVM_APIC_INIT, &apic->pending_events)) { 9795b672408SPaolo Bonzini if (block_nested_events) 9805b672408SPaolo Bonzini return -EBUSY; 9815b672408SPaolo Bonzini if (!nested_exit_on_init(svm)) 9825b672408SPaolo Bonzini return 0; 9835b672408SPaolo Bonzini nested_svm_init(svm); 9845b672408SPaolo Bonzini return 0; 9855b672408SPaolo Bonzini } 986883b0a91SJoerg Roedel 9877c86663bSPaolo Bonzini if (vcpu->arch.exception.pending) { 9887c86663bSPaolo Bonzini if (block_nested_events) 9897c86663bSPaolo Bonzini return -EBUSY; 9907c86663bSPaolo Bonzini if (!nested_exit_on_exception(svm)) 9917c86663bSPaolo Bonzini return 0; 9927c86663bSPaolo Bonzini nested_svm_inject_exception_vmexit(svm); 9937c86663bSPaolo Bonzini return 0; 9947c86663bSPaolo Bonzini } 9957c86663bSPaolo Bonzini 996221e7610SPaolo Bonzini if (vcpu->arch.smi_pending && !svm_smi_blocked(vcpu)) { 99755714cddSPaolo Bonzini if (block_nested_events) 99855714cddSPaolo Bonzini return -EBUSY; 999221e7610SPaolo Bonzini if (!nested_exit_on_smi(svm)) 1000221e7610SPaolo Bonzini return 0; 100155714cddSPaolo Bonzini nested_svm_smi(svm); 100255714cddSPaolo Bonzini return 0; 100355714cddSPaolo Bonzini } 100455714cddSPaolo Bonzini 1005221e7610SPaolo Bonzini if (vcpu->arch.nmi_pending && !svm_nmi_blocked(vcpu)) { 10069c3d370aSCathy Avery if (block_nested_events) 10079c3d370aSCathy Avery return -EBUSY; 1008221e7610SPaolo Bonzini if (!nested_exit_on_nmi(svm)) 1009221e7610SPaolo Bonzini return 0; 10109c3d370aSCathy Avery nested_svm_nmi(svm); 10119c3d370aSCathy Avery return 0; 10129c3d370aSCathy Avery } 10139c3d370aSCathy Avery 1014221e7610SPaolo Bonzini if (kvm_cpu_has_interrupt(vcpu) && !svm_interrupt_blocked(vcpu)) { 1015883b0a91SJoerg Roedel if (block_nested_events) 1016883b0a91SJoerg Roedel return -EBUSY; 1017221e7610SPaolo Bonzini if (!nested_exit_on_intr(svm)) 1018221e7610SPaolo Bonzini return 0; 1019883b0a91SJoerg Roedel nested_svm_intr(svm); 1020883b0a91SJoerg Roedel return 0; 1021883b0a91SJoerg Roedel } 1022883b0a91SJoerg Roedel 1023883b0a91SJoerg Roedel return 0; 1024883b0a91SJoerg Roedel } 1025883b0a91SJoerg Roedel 1026883b0a91SJoerg Roedel int nested_svm_exit_special(struct vcpu_svm *svm) 1027883b0a91SJoerg Roedel { 1028883b0a91SJoerg Roedel u32 exit_code = svm->vmcb->control.exit_code; 1029883b0a91SJoerg Roedel 1030883b0a91SJoerg Roedel switch (exit_code) { 1031883b0a91SJoerg Roedel case SVM_EXIT_INTR: 1032883b0a91SJoerg Roedel case SVM_EXIT_NMI: 1033883b0a91SJoerg Roedel case SVM_EXIT_NPF: 1034883b0a91SJoerg Roedel return NESTED_EXIT_HOST; 10357c86663bSPaolo Bonzini case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: { 10367c86663bSPaolo Bonzini u32 excp_bits = 1 << (exit_code - SVM_EXIT_EXCP_BASE); 10377c86663bSPaolo Bonzini 10389780d51dSBabu Moger if (get_host_vmcb(svm)->control.intercepts[INTERCEPT_EXCEPTION] & 10399780d51dSBabu Moger excp_bits) 10407c86663bSPaolo Bonzini return NESTED_EXIT_HOST; 10417c86663bSPaolo Bonzini else if (exit_code == SVM_EXIT_EXCP_BASE + PF_VECTOR && 104268fd66f1SVitaly Kuznetsov svm->vcpu.arch.apf.host_apf_flags) 1043a3535be7SPaolo Bonzini /* Trap async PF even if not shadowing */ 1044883b0a91SJoerg Roedel return NESTED_EXIT_HOST; 1045883b0a91SJoerg Roedel break; 10467c86663bSPaolo Bonzini } 1047883b0a91SJoerg Roedel default: 1048883b0a91SJoerg Roedel break; 1049883b0a91SJoerg Roedel } 1050883b0a91SJoerg Roedel 1051883b0a91SJoerg Roedel return NESTED_EXIT_CONTINUE; 1052883b0a91SJoerg Roedel } 105333b22172SPaolo Bonzini 1054cc440cdaSPaolo Bonzini static int svm_get_nested_state(struct kvm_vcpu *vcpu, 1055cc440cdaSPaolo Bonzini struct kvm_nested_state __user *user_kvm_nested_state, 1056cc440cdaSPaolo Bonzini u32 user_data_size) 1057cc440cdaSPaolo Bonzini { 1058cc440cdaSPaolo Bonzini struct vcpu_svm *svm; 1059cc440cdaSPaolo Bonzini struct kvm_nested_state kvm_state = { 1060cc440cdaSPaolo Bonzini .flags = 0, 1061cc440cdaSPaolo Bonzini .format = KVM_STATE_NESTED_FORMAT_SVM, 1062cc440cdaSPaolo Bonzini .size = sizeof(kvm_state), 1063cc440cdaSPaolo Bonzini }; 1064cc440cdaSPaolo Bonzini struct vmcb __user *user_vmcb = (struct vmcb __user *) 1065cc440cdaSPaolo Bonzini &user_kvm_nested_state->data.svm[0]; 1066cc440cdaSPaolo Bonzini 1067cc440cdaSPaolo Bonzini if (!vcpu) 1068cc440cdaSPaolo Bonzini return kvm_state.size + KVM_STATE_NESTED_SVM_VMCB_SIZE; 1069cc440cdaSPaolo Bonzini 1070cc440cdaSPaolo Bonzini svm = to_svm(vcpu); 1071cc440cdaSPaolo Bonzini 1072cc440cdaSPaolo Bonzini if (user_data_size < kvm_state.size) 1073cc440cdaSPaolo Bonzini goto out; 1074cc440cdaSPaolo Bonzini 1075cc440cdaSPaolo Bonzini /* First fill in the header and copy it out. */ 1076cc440cdaSPaolo Bonzini if (is_guest_mode(vcpu)) { 10770dd16b5bSMaxim Levitsky kvm_state.hdr.svm.vmcb_pa = svm->nested.vmcb12_gpa; 1078cc440cdaSPaolo Bonzini kvm_state.size += KVM_STATE_NESTED_SVM_VMCB_SIZE; 1079cc440cdaSPaolo Bonzini kvm_state.flags |= KVM_STATE_NESTED_GUEST_MODE; 1080cc440cdaSPaolo Bonzini 1081cc440cdaSPaolo Bonzini if (svm->nested.nested_run_pending) 1082cc440cdaSPaolo Bonzini kvm_state.flags |= KVM_STATE_NESTED_RUN_PENDING; 1083cc440cdaSPaolo Bonzini } 1084cc440cdaSPaolo Bonzini 1085cc440cdaSPaolo Bonzini if (gif_set(svm)) 1086cc440cdaSPaolo Bonzini kvm_state.flags |= KVM_STATE_NESTED_GIF_SET; 1087cc440cdaSPaolo Bonzini 1088cc440cdaSPaolo Bonzini if (copy_to_user(user_kvm_nested_state, &kvm_state, sizeof(kvm_state))) 1089cc440cdaSPaolo Bonzini return -EFAULT; 1090cc440cdaSPaolo Bonzini 1091cc440cdaSPaolo Bonzini if (!is_guest_mode(vcpu)) 1092cc440cdaSPaolo Bonzini goto out; 1093cc440cdaSPaolo Bonzini 1094cc440cdaSPaolo Bonzini /* 1095cc440cdaSPaolo Bonzini * Copy over the full size of the VMCB rather than just the size 1096cc440cdaSPaolo Bonzini * of the structs. 1097cc440cdaSPaolo Bonzini */ 1098cc440cdaSPaolo Bonzini if (clear_user(user_vmcb, KVM_STATE_NESTED_SVM_VMCB_SIZE)) 1099cc440cdaSPaolo Bonzini return -EFAULT; 1100cc440cdaSPaolo Bonzini if (copy_to_user(&user_vmcb->control, &svm->nested.ctl, 1101cc440cdaSPaolo Bonzini sizeof(user_vmcb->control))) 1102cc440cdaSPaolo Bonzini return -EFAULT; 1103cc440cdaSPaolo Bonzini if (copy_to_user(&user_vmcb->save, &svm->nested.hsave->save, 1104cc440cdaSPaolo Bonzini sizeof(user_vmcb->save))) 1105cc440cdaSPaolo Bonzini return -EFAULT; 1106cc440cdaSPaolo Bonzini 1107cc440cdaSPaolo Bonzini out: 1108cc440cdaSPaolo Bonzini return kvm_state.size; 1109cc440cdaSPaolo Bonzini } 1110cc440cdaSPaolo Bonzini 1111cc440cdaSPaolo Bonzini static int svm_set_nested_state(struct kvm_vcpu *vcpu, 1112cc440cdaSPaolo Bonzini struct kvm_nested_state __user *user_kvm_nested_state, 1113cc440cdaSPaolo Bonzini struct kvm_nested_state *kvm_state) 1114cc440cdaSPaolo Bonzini { 1115cc440cdaSPaolo Bonzini struct vcpu_svm *svm = to_svm(vcpu); 1116cc440cdaSPaolo Bonzini struct vmcb *hsave = svm->nested.hsave; 1117cc440cdaSPaolo Bonzini struct vmcb __user *user_vmcb = (struct vmcb __user *) 1118cc440cdaSPaolo Bonzini &user_kvm_nested_state->data.svm[0]; 11196ccbd29aSJoerg Roedel struct vmcb_control_area *ctl; 11206ccbd29aSJoerg Roedel struct vmcb_save_area *save; 11216ccbd29aSJoerg Roedel int ret; 1122cc440cdaSPaolo Bonzini u32 cr0; 1123cc440cdaSPaolo Bonzini 11246ccbd29aSJoerg Roedel BUILD_BUG_ON(sizeof(struct vmcb_control_area) + sizeof(struct vmcb_save_area) > 11256ccbd29aSJoerg Roedel KVM_STATE_NESTED_SVM_VMCB_SIZE); 11266ccbd29aSJoerg Roedel 1127cc440cdaSPaolo Bonzini if (kvm_state->format != KVM_STATE_NESTED_FORMAT_SVM) 1128cc440cdaSPaolo Bonzini return -EINVAL; 1129cc440cdaSPaolo Bonzini 1130cc440cdaSPaolo Bonzini if (kvm_state->flags & ~(KVM_STATE_NESTED_GUEST_MODE | 1131cc440cdaSPaolo Bonzini KVM_STATE_NESTED_RUN_PENDING | 1132cc440cdaSPaolo Bonzini KVM_STATE_NESTED_GIF_SET)) 1133cc440cdaSPaolo Bonzini return -EINVAL; 1134cc440cdaSPaolo Bonzini 1135cc440cdaSPaolo Bonzini /* 1136cc440cdaSPaolo Bonzini * If in guest mode, vcpu->arch.efer actually refers to the L2 guest's 1137cc440cdaSPaolo Bonzini * EFER.SVME, but EFER.SVME still has to be 1 for VMRUN to succeed. 1138cc440cdaSPaolo Bonzini */ 1139cc440cdaSPaolo Bonzini if (!(vcpu->arch.efer & EFER_SVME)) { 1140cc440cdaSPaolo Bonzini /* GIF=1 and no guest mode are required if SVME=0. */ 1141cc440cdaSPaolo Bonzini if (kvm_state->flags != KVM_STATE_NESTED_GIF_SET) 1142cc440cdaSPaolo Bonzini return -EINVAL; 1143cc440cdaSPaolo Bonzini } 1144cc440cdaSPaolo Bonzini 1145cc440cdaSPaolo Bonzini /* SMM temporarily disables SVM, so we cannot be in guest mode. */ 1146cc440cdaSPaolo Bonzini if (is_smm(vcpu) && (kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE)) 1147cc440cdaSPaolo Bonzini return -EINVAL; 1148cc440cdaSPaolo Bonzini 1149cc440cdaSPaolo Bonzini if (!(kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE)) { 1150cc440cdaSPaolo Bonzini svm_leave_nested(svm); 1151d5cd6f34SVitaly Kuznetsov svm_set_gif(svm, !!(kvm_state->flags & KVM_STATE_NESTED_GIF_SET)); 1152d5cd6f34SVitaly Kuznetsov return 0; 1153cc440cdaSPaolo Bonzini } 1154cc440cdaSPaolo Bonzini 1155cc440cdaSPaolo Bonzini if (!page_address_valid(vcpu, kvm_state->hdr.svm.vmcb_pa)) 1156cc440cdaSPaolo Bonzini return -EINVAL; 1157cc440cdaSPaolo Bonzini if (kvm_state->size < sizeof(*kvm_state) + KVM_STATE_NESTED_SVM_VMCB_SIZE) 1158cc440cdaSPaolo Bonzini return -EINVAL; 1159cc440cdaSPaolo Bonzini 11606ccbd29aSJoerg Roedel ret = -ENOMEM; 11616ccbd29aSJoerg Roedel ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); 11626ccbd29aSJoerg Roedel save = kzalloc(sizeof(*save), GFP_KERNEL); 11636ccbd29aSJoerg Roedel if (!ctl || !save) 11646ccbd29aSJoerg Roedel goto out_free; 11656ccbd29aSJoerg Roedel 11666ccbd29aSJoerg Roedel ret = -EFAULT; 11676ccbd29aSJoerg Roedel if (copy_from_user(ctl, &user_vmcb->control, sizeof(*ctl))) 11686ccbd29aSJoerg Roedel goto out_free; 11696ccbd29aSJoerg Roedel if (copy_from_user(save, &user_vmcb->save, sizeof(*save))) 11706ccbd29aSJoerg Roedel goto out_free; 11716ccbd29aSJoerg Roedel 11726ccbd29aSJoerg Roedel ret = -EINVAL; 11736ccbd29aSJoerg Roedel if (!nested_vmcb_check_controls(ctl)) 11746ccbd29aSJoerg Roedel goto out_free; 1175cc440cdaSPaolo Bonzini 1176cc440cdaSPaolo Bonzini /* 1177cc440cdaSPaolo Bonzini * Processor state contains L2 state. Check that it is 1178cc440cdaSPaolo Bonzini * valid for guest mode (see nested_vmcb_checks). 1179cc440cdaSPaolo Bonzini */ 1180cc440cdaSPaolo Bonzini cr0 = kvm_read_cr0(vcpu); 1181cc440cdaSPaolo Bonzini if (((cr0 & X86_CR0_CD) == 0) && (cr0 & X86_CR0_NW)) 11826ccbd29aSJoerg Roedel goto out_free; 1183cc440cdaSPaolo Bonzini 1184cc440cdaSPaolo Bonzini /* 1185cc440cdaSPaolo Bonzini * Validate host state saved from before VMRUN (see 1186cc440cdaSPaolo Bonzini * nested_svm_check_permissions). 1187cc440cdaSPaolo Bonzini * TODO: validate reserved bits for all saved state. 1188cc440cdaSPaolo Bonzini */ 11896ccbd29aSJoerg Roedel if (!(save->cr0 & X86_CR0_PG)) 11906ccbd29aSJoerg Roedel goto out_free; 1191cc440cdaSPaolo Bonzini 1192cc440cdaSPaolo Bonzini /* 1193cc440cdaSPaolo Bonzini * All checks done, we can enter guest mode. L1 control fields 1194cc440cdaSPaolo Bonzini * come from the nested save state. Guest state is already 1195cc440cdaSPaolo Bonzini * in the registers, the save area of the nested state instead 1196cc440cdaSPaolo Bonzini * contains saved L1 state. 1197cc440cdaSPaolo Bonzini */ 119881f76adaSMaxim Levitsky 119981f76adaSMaxim Levitsky svm->nested.nested_run_pending = 120081f76adaSMaxim Levitsky !!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING); 120181f76adaSMaxim Levitsky 1202cc440cdaSPaolo Bonzini copy_vmcb_control_area(&hsave->control, &svm->vmcb->control); 12036ccbd29aSJoerg Roedel hsave->save = *save; 1204cc440cdaSPaolo Bonzini 12050dd16b5bSMaxim Levitsky svm->nested.vmcb12_gpa = kvm_state->hdr.svm.vmcb_pa; 12066ccbd29aSJoerg Roedel load_nested_vmcb_control(svm, ctl); 1207cc440cdaSPaolo Bonzini nested_prepare_vmcb_control(svm); 1208cc440cdaSPaolo Bonzini 1209a7d5c7ceSPaolo Bonzini kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu); 12106ccbd29aSJoerg Roedel ret = 0; 12116ccbd29aSJoerg Roedel out_free: 12126ccbd29aSJoerg Roedel kfree(save); 12136ccbd29aSJoerg Roedel kfree(ctl); 12146ccbd29aSJoerg Roedel 12156ccbd29aSJoerg Roedel return ret; 1216cc440cdaSPaolo Bonzini } 1217cc440cdaSPaolo Bonzini 121833b22172SPaolo Bonzini struct kvm_x86_nested_ops svm_nested_ops = { 121933b22172SPaolo Bonzini .check_events = svm_check_nested_events, 1220a7d5c7ceSPaolo Bonzini .get_nested_state_pages = svm_get_nested_state_pages, 1221cc440cdaSPaolo Bonzini .get_state = svm_get_nested_state, 1222cc440cdaSPaolo Bonzini .set_state = svm_set_nested_state, 122333b22172SPaolo Bonzini }; 1224