xref: /linux/arch/x86/kvm/svm/nested.c (revision d20c796ca3709801f8a7fa36e8770a3dd8ebd34e)
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"
3166c03a92SVitaly Kuznetsov #include "hyperv.h"
32883b0a91SJoerg Roedel 
3311f0cbf0SSean Christopherson #define CC KVM_NESTED_VMENTER_CONSISTENCY_CHECK
3411f0cbf0SSean Christopherson 
35883b0a91SJoerg Roedel static void nested_svm_inject_npf_exit(struct kvm_vcpu *vcpu,
36883b0a91SJoerg Roedel 				       struct x86_exception *fault)
37883b0a91SJoerg Roedel {
38883b0a91SJoerg Roedel 	struct vcpu_svm *svm = to_svm(vcpu);
39db663af4SMaxim Levitsky 	struct vmcb *vmcb = svm->vmcb;
40883b0a91SJoerg Roedel 
41db663af4SMaxim Levitsky 	if (vmcb->control.exit_code != SVM_EXIT_NPF) {
42883b0a91SJoerg Roedel 		/*
43883b0a91SJoerg Roedel 		 * TODO: track the cause of the nested page fault, and
44883b0a91SJoerg Roedel 		 * correctly fill in the high bits of exit_info_1.
45883b0a91SJoerg Roedel 		 */
46db663af4SMaxim Levitsky 		vmcb->control.exit_code = SVM_EXIT_NPF;
47db663af4SMaxim Levitsky 		vmcb->control.exit_code_hi = 0;
48db663af4SMaxim Levitsky 		vmcb->control.exit_info_1 = (1ULL << 32);
49db663af4SMaxim Levitsky 		vmcb->control.exit_info_2 = fault->address;
50883b0a91SJoerg Roedel 	}
51883b0a91SJoerg Roedel 
52db663af4SMaxim Levitsky 	vmcb->control.exit_info_1 &= ~0xffffffffULL;
53db663af4SMaxim Levitsky 	vmcb->control.exit_info_1 |= fault->error_code;
54883b0a91SJoerg Roedel 
55883b0a91SJoerg Roedel 	nested_svm_vmexit(svm);
56883b0a91SJoerg Roedel }
57883b0a91SJoerg Roedel 
58a04aead1SPaolo Bonzini static void svm_inject_page_fault_nested(struct kvm_vcpu *vcpu, struct x86_exception *fault)
59a04aead1SPaolo Bonzini {
60a04aead1SPaolo Bonzini 	struct vcpu_svm *svm = to_svm(vcpu);
61db663af4SMaxim Levitsky 	struct vmcb *vmcb = svm->vmcb;
62db663af4SMaxim Levitsky 
63a04aead1SPaolo Bonzini 	WARN_ON(!is_guest_mode(vcpu));
64a04aead1SPaolo Bonzini 
658fc78909SEmanuele Giuseppe Esposito 	if (vmcb12_is_intercept(&svm->nested.ctl,
668fc78909SEmanuele Giuseppe Esposito 				INTERCEPT_EXCEPTION_OFFSET + PF_VECTOR) &&
67a04aead1SPaolo Bonzini 				!svm->nested.nested_run_pending) {
68db663af4SMaxim Levitsky 		vmcb->control.exit_code = SVM_EXIT_EXCP_BASE + PF_VECTOR;
69db663af4SMaxim Levitsky 		vmcb->control.exit_code_hi = 0;
70db663af4SMaxim Levitsky 		vmcb->control.exit_info_1 = fault->error_code;
71db663af4SMaxim Levitsky 		vmcb->control.exit_info_2 = fault->address;
72a04aead1SPaolo Bonzini 		nested_svm_vmexit(svm);
73a04aead1SPaolo Bonzini 	} else {
74a04aead1SPaolo Bonzini 		kvm_inject_page_fault(vcpu, fault);
75a04aead1SPaolo Bonzini 	}
76a04aead1SPaolo Bonzini }
77a04aead1SPaolo Bonzini 
78883b0a91SJoerg Roedel static u64 nested_svm_get_tdp_pdptr(struct kvm_vcpu *vcpu, int index)
79883b0a91SJoerg Roedel {
80883b0a91SJoerg Roedel 	struct vcpu_svm *svm = to_svm(vcpu);
81e670bf68SPaolo Bonzini 	u64 cr3 = svm->nested.ctl.nested_cr3;
82883b0a91SJoerg Roedel 	u64 pdpte;
83883b0a91SJoerg Roedel 	int ret;
84883b0a91SJoerg Roedel 
852732be90SSean Christopherson 	ret = kvm_vcpu_read_guest_page(vcpu, gpa_to_gfn(cr3), &pdpte,
86883b0a91SJoerg Roedel 				       offset_in_page(cr3) + index * 8, 8);
87883b0a91SJoerg Roedel 	if (ret)
88883b0a91SJoerg Roedel 		return 0;
89883b0a91SJoerg Roedel 	return pdpte;
90883b0a91SJoerg Roedel }
91883b0a91SJoerg Roedel 
92883b0a91SJoerg Roedel static unsigned long nested_svm_get_tdp_cr3(struct kvm_vcpu *vcpu)
93883b0a91SJoerg Roedel {
94883b0a91SJoerg Roedel 	struct vcpu_svm *svm = to_svm(vcpu);
95883b0a91SJoerg Roedel 
96e670bf68SPaolo Bonzini 	return svm->nested.ctl.nested_cr3;
97883b0a91SJoerg Roedel }
98883b0a91SJoerg Roedel 
99883b0a91SJoerg Roedel static void nested_svm_init_mmu_context(struct kvm_vcpu *vcpu)
100883b0a91SJoerg Roedel {
101929d1cfaSPaolo Bonzini 	struct vcpu_svm *svm = to_svm(vcpu);
102929d1cfaSPaolo Bonzini 
103883b0a91SJoerg Roedel 	WARN_ON(mmu_is_nested(vcpu));
104883b0a91SJoerg Roedel 
105883b0a91SJoerg Roedel 	vcpu->arch.mmu = &vcpu->arch.guest_mmu;
10631e96bc6SSean Christopherson 
10731e96bc6SSean Christopherson 	/*
10831e96bc6SSean Christopherson 	 * The NPT format depends on L1's CR4 and EFER, which is in vmcb01.  Note,
10931e96bc6SSean Christopherson 	 * when called via KVM_SET_NESTED_STATE, that state may _not_ match current
11031e96bc6SSean Christopherson 	 * vCPU state.  CR0.WP is explicitly ignored, while CR0.PG is required.
11131e96bc6SSean Christopherson 	 */
1124995a368SCathy Avery 	kvm_init_shadow_npt_mmu(vcpu, X86_CR0_PG, svm->vmcb01.ptr->save.cr4,
1134995a368SCathy Avery 				svm->vmcb01.ptr->save.efer,
1140f04a2acSVitaly Kuznetsov 				svm->nested.ctl.nested_cr3);
115883b0a91SJoerg Roedel 	vcpu->arch.mmu->get_guest_pgd     = nested_svm_get_tdp_cr3;
116883b0a91SJoerg Roedel 	vcpu->arch.mmu->get_pdptr         = nested_svm_get_tdp_pdptr;
117883b0a91SJoerg Roedel 	vcpu->arch.mmu->inject_page_fault = nested_svm_inject_npf_exit;
118883b0a91SJoerg Roedel 	vcpu->arch.walk_mmu              = &vcpu->arch.nested_mmu;
119883b0a91SJoerg Roedel }
120883b0a91SJoerg Roedel 
121883b0a91SJoerg Roedel static void nested_svm_uninit_mmu_context(struct kvm_vcpu *vcpu)
122883b0a91SJoerg Roedel {
123883b0a91SJoerg Roedel 	vcpu->arch.mmu = &vcpu->arch.root_mmu;
124883b0a91SJoerg Roedel 	vcpu->arch.walk_mmu = &vcpu->arch.root_mmu;
125883b0a91SJoerg Roedel }
126883b0a91SJoerg Roedel 
127b9f3973aSMaxim Levitsky static bool nested_vmcb_needs_vls_intercept(struct vcpu_svm *svm)
128b9f3973aSMaxim Levitsky {
129b9f3973aSMaxim Levitsky 	if (!svm->v_vmload_vmsave_enabled)
130b9f3973aSMaxim Levitsky 		return true;
131b9f3973aSMaxim Levitsky 
132b9f3973aSMaxim Levitsky 	if (!nested_npt_enabled(svm))
133b9f3973aSMaxim Levitsky 		return true;
134b9f3973aSMaxim Levitsky 
135b9f3973aSMaxim Levitsky 	if (!(svm->nested.ctl.virt_ext & VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK))
136b9f3973aSMaxim Levitsky 		return true;
137b9f3973aSMaxim Levitsky 
138b9f3973aSMaxim Levitsky 	return false;
139b9f3973aSMaxim Levitsky }
140b9f3973aSMaxim Levitsky 
141883b0a91SJoerg Roedel void recalc_intercepts(struct vcpu_svm *svm)
142883b0a91SJoerg Roedel {
1438fc78909SEmanuele Giuseppe Esposito 	struct vmcb_control_area *c, *h;
1448fc78909SEmanuele Giuseppe Esposito 	struct vmcb_ctrl_area_cached *g;
145c45ad722SBabu Moger 	unsigned int i;
146883b0a91SJoerg Roedel 
14706e7852cSJoerg Roedel 	vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
148883b0a91SJoerg Roedel 
149883b0a91SJoerg Roedel 	if (!is_guest_mode(&svm->vcpu))
150883b0a91SJoerg Roedel 		return;
151883b0a91SJoerg Roedel 
152883b0a91SJoerg Roedel 	c = &svm->vmcb->control;
1534995a368SCathy Avery 	h = &svm->vmcb01.ptr->control;
154e670bf68SPaolo Bonzini 	g = &svm->nested.ctl;
155883b0a91SJoerg Roedel 
156c45ad722SBabu Moger 	for (i = 0; i < MAX_INTERCEPT; i++)
157c45ad722SBabu Moger 		c->intercepts[i] = h->intercepts[i];
158c45ad722SBabu Moger 
159e9fd761aSPaolo Bonzini 	if (g->int_ctl & V_INTR_MASKING_MASK) {
160883b0a91SJoerg Roedel 		/* We only want the cr8 intercept bits of L1 */
16103bfeeb9SBabu Moger 		vmcb_clr_intercept(c, INTERCEPT_CR8_READ);
16203bfeeb9SBabu Moger 		vmcb_clr_intercept(c, INTERCEPT_CR8_WRITE);
163883b0a91SJoerg Roedel 
164883b0a91SJoerg Roedel 		/*
165883b0a91SJoerg Roedel 		 * Once running L2 with HF_VINTR_MASK, EFLAGS.IF does not
166883b0a91SJoerg Roedel 		 * affect any interrupt we may want to inject; therefore,
167883b0a91SJoerg Roedel 		 * interrupt window vmexits are irrelevant to L0.
168883b0a91SJoerg Roedel 		 */
169c62e2e94SBabu Moger 		vmcb_clr_intercept(c, INTERCEPT_VINTR);
170883b0a91SJoerg Roedel 	}
171883b0a91SJoerg Roedel 
172883b0a91SJoerg Roedel 	/* We don't want to see VMMCALLs from a nested guest */
173c62e2e94SBabu Moger 	vmcb_clr_intercept(c, INTERCEPT_VMMCALL);
174883b0a91SJoerg Roedel 
175c45ad722SBabu Moger 	for (i = 0; i < MAX_INTERCEPT; i++)
176c45ad722SBabu Moger 		c->intercepts[i] |= g->intercepts[i];
1774b639a9fSMaxim Levitsky 
1784b639a9fSMaxim Levitsky 	/* If SMI is not intercepted, ignore guest SMI intercept as well  */
1794b639a9fSMaxim Levitsky 	if (!intercept_smi)
1804b639a9fSMaxim Levitsky 		vmcb_clr_intercept(c, INTERCEPT_SMI);
181c7dfa400SMaxim Levitsky 
182b9f3973aSMaxim Levitsky 	if (nested_vmcb_needs_vls_intercept(svm)) {
183b9f3973aSMaxim Levitsky 		/*
184b9f3973aSMaxim Levitsky 		 * If the virtual VMLOAD/VMSAVE is not enabled for the L2,
185b9f3973aSMaxim Levitsky 		 * we must intercept these instructions to correctly
186b9f3973aSMaxim Levitsky 		 * emulate them in case L1 doesn't intercept them.
187b9f3973aSMaxim Levitsky 		 */
188c7dfa400SMaxim Levitsky 		vmcb_set_intercept(c, INTERCEPT_VMLOAD);
189c7dfa400SMaxim Levitsky 		vmcb_set_intercept(c, INTERCEPT_VMSAVE);
190b9f3973aSMaxim Levitsky 	} else {
191b9f3973aSMaxim Levitsky 		WARN_ON(!(c->virt_ext & VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK));
192b9f3973aSMaxim Levitsky 	}
193883b0a91SJoerg Roedel }
194883b0a91SJoerg Roedel 
19566c03a92SVitaly Kuznetsov /*
19666c03a92SVitaly Kuznetsov  * Merge L0's (KVM) and L1's (Nested VMCB) MSR permission bitmaps. The function
19766c03a92SVitaly Kuznetsov  * is optimized in that it only merges the parts where KVM MSR permission bitmap
19866c03a92SVitaly Kuznetsov  * may contain zero bits.
19966c03a92SVitaly Kuznetsov  */
200883b0a91SJoerg Roedel static bool nested_svm_vmrun_msrpm(struct vcpu_svm *svm)
201883b0a91SJoerg Roedel {
20266c03a92SVitaly Kuznetsov 	struct hv_enlightenments *hve =
20366c03a92SVitaly Kuznetsov 		(struct hv_enlightenments *)svm->nested.ctl.reserved_sw;
204883b0a91SJoerg Roedel 	int i;
205883b0a91SJoerg Roedel 
20666c03a92SVitaly Kuznetsov 	/*
20766c03a92SVitaly Kuznetsov 	 * MSR bitmap update can be skipped when:
20866c03a92SVitaly Kuznetsov 	 * - MSR bitmap for L1 hasn't changed.
20966c03a92SVitaly Kuznetsov 	 * - Nested hypervisor (L1) is attempting to launch the same L2 as
21066c03a92SVitaly Kuznetsov 	 *   before.
21166c03a92SVitaly Kuznetsov 	 * - Nested hypervisor (L1) is using Hyper-V emulation interface and
21266c03a92SVitaly Kuznetsov 	 * tells KVM (L0) there were no changes in MSR bitmap for L2.
21366c03a92SVitaly Kuznetsov 	 */
21466c03a92SVitaly Kuznetsov 	if (!svm->nested.force_msr_bitmap_recalc &&
21566c03a92SVitaly Kuznetsov 	    kvm_hv_hypercall_enabled(&svm->vcpu) &&
21666c03a92SVitaly Kuznetsov 	    hve->hv_enlightenments_control.msr_bitmap &&
21766c03a92SVitaly Kuznetsov 	    (svm->nested.ctl.clean & BIT(VMCB_HV_NESTED_ENLIGHTENMENTS)))
21866c03a92SVitaly Kuznetsov 		goto set_msrpm_base_pa;
21966c03a92SVitaly Kuznetsov 
2208fc78909SEmanuele Giuseppe Esposito 	if (!(vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_MSR_PROT)))
221883b0a91SJoerg Roedel 		return true;
222883b0a91SJoerg Roedel 
223883b0a91SJoerg Roedel 	for (i = 0; i < MSRPM_OFFSETS; i++) {
224883b0a91SJoerg Roedel 		u32 value, p;
225883b0a91SJoerg Roedel 		u64 offset;
226883b0a91SJoerg Roedel 
227883b0a91SJoerg Roedel 		if (msrpm_offsets[i] == 0xffffffff)
228883b0a91SJoerg Roedel 			break;
229883b0a91SJoerg Roedel 
230883b0a91SJoerg Roedel 		p      = msrpm_offsets[i];
231e670bf68SPaolo Bonzini 		offset = svm->nested.ctl.msrpm_base_pa + (p * 4);
232883b0a91SJoerg Roedel 
233883b0a91SJoerg Roedel 		if (kvm_vcpu_read_guest(&svm->vcpu, offset, &value, 4))
234883b0a91SJoerg Roedel 			return false;
235883b0a91SJoerg Roedel 
236883b0a91SJoerg Roedel 		svm->nested.msrpm[p] = svm->msrpm[p] | value;
237883b0a91SJoerg Roedel 	}
238883b0a91SJoerg Roedel 
23973c25546SVitaly Kuznetsov 	svm->nested.force_msr_bitmap_recalc = false;
24073c25546SVitaly Kuznetsov 
24166c03a92SVitaly Kuznetsov set_msrpm_base_pa:
242883b0a91SJoerg Roedel 	svm->vmcb->control.msrpm_base_pa = __sme_set(__pa(svm->nested.msrpm));
243883b0a91SJoerg Roedel 
244883b0a91SJoerg Roedel 	return true;
245883b0a91SJoerg Roedel }
246883b0a91SJoerg Roedel 
247ee695f22SKrish Sadhukhan /*
248ee695f22SKrish Sadhukhan  * Bits 11:0 of bitmap address are ignored by hardware
249ee695f22SKrish Sadhukhan  */
250ee695f22SKrish Sadhukhan static bool nested_svm_check_bitmap_pa(struct kvm_vcpu *vcpu, u64 pa, u32 size)
251ee695f22SKrish Sadhukhan {
252ee695f22SKrish Sadhukhan 	u64 addr = PAGE_ALIGN(pa);
253ee695f22SKrish Sadhukhan 
254ee695f22SKrish Sadhukhan 	return kvm_vcpu_is_legal_gpa(vcpu, addr) &&
255ee695f22SKrish Sadhukhan 	    kvm_vcpu_is_legal_gpa(vcpu, addr + size - 1);
256ee695f22SKrish Sadhukhan }
257ee695f22SKrish Sadhukhan 
258174a921bSKrish Sadhukhan static bool nested_svm_check_tlb_ctl(struct kvm_vcpu *vcpu, u8 tlb_ctl)
259174a921bSKrish Sadhukhan {
260174a921bSKrish Sadhukhan 	/* Nested FLUSHBYASID is not supported yet.  */
261174a921bSKrish Sadhukhan 	switch(tlb_ctl) {
262174a921bSKrish Sadhukhan 		case TLB_CONTROL_DO_NOTHING:
263174a921bSKrish Sadhukhan 		case TLB_CONTROL_FLUSH_ALL_ASID:
264174a921bSKrish Sadhukhan 			return true;
265174a921bSKrish Sadhukhan 		default:
266174a921bSKrish Sadhukhan 			return false;
267174a921bSKrish Sadhukhan 	}
268174a921bSKrish Sadhukhan }
269174a921bSKrish Sadhukhan 
270bd95926cSPaolo Bonzini static bool __nested_vmcb_check_controls(struct kvm_vcpu *vcpu,
2718fc78909SEmanuele Giuseppe Esposito 					 struct vmcb_ctrl_area_cached *control)
272ca46d739SPaolo Bonzini {
2738fc78909SEmanuele Giuseppe Esposito 	if (CC(!vmcb12_is_intercept(control, INTERCEPT_VMRUN)))
274ca46d739SPaolo Bonzini 		return false;
275ca46d739SPaolo Bonzini 
27611f0cbf0SSean Christopherson 	if (CC(control->asid == 0))
277ca46d739SPaolo Bonzini 		return false;
278ca46d739SPaolo Bonzini 
27911f0cbf0SSean Christopherson 	if (CC((control->nested_ctl & SVM_NESTED_CTL_NP_ENABLE) && !npt_enabled))
280ca46d739SPaolo Bonzini 		return false;
281ca46d739SPaolo Bonzini 
282ee695f22SKrish Sadhukhan 	if (CC(!nested_svm_check_bitmap_pa(vcpu, control->msrpm_base_pa,
283ee695f22SKrish Sadhukhan 					   MSRPM_SIZE)))
284ee695f22SKrish Sadhukhan 		return false;
285ee695f22SKrish Sadhukhan 	if (CC(!nested_svm_check_bitmap_pa(vcpu, control->iopm_base_pa,
286ee695f22SKrish Sadhukhan 					   IOPM_SIZE)))
287ee695f22SKrish Sadhukhan 		return false;
288ee695f22SKrish Sadhukhan 
289174a921bSKrish Sadhukhan 	if (CC(!nested_svm_check_tlb_ctl(vcpu, control->tlb_ctl)))
290174a921bSKrish Sadhukhan 		return false;
291174a921bSKrish Sadhukhan 
292ca46d739SPaolo Bonzini 	return true;
293ca46d739SPaolo Bonzini }
294ca46d739SPaolo Bonzini 
2956906e06dSKrish Sadhukhan /* Common checks that apply to both L1 and L2 state.  */
296b7a3d8b6SEmanuele Giuseppe Esposito static bool __nested_vmcb_check_save(struct kvm_vcpu *vcpu,
297b7a3d8b6SEmanuele Giuseppe Esposito 				     struct vmcb_save_area_cached *save)
2986906e06dSKrish Sadhukhan {
29911f0cbf0SSean Christopherson 	if (CC(!(save->efer & EFER_SVME)))
3006906e06dSKrish Sadhukhan 		return false;
3016906e06dSKrish Sadhukhan 
30211f0cbf0SSean Christopherson 	if (CC((save->cr0 & X86_CR0_CD) == 0 && (save->cr0 & X86_CR0_NW)) ||
30311f0cbf0SSean Christopherson 	    CC(save->cr0 & ~0xffffffffULL))
3046906e06dSKrish Sadhukhan 		return false;
3056906e06dSKrish Sadhukhan 
30611f0cbf0SSean Christopherson 	if (CC(!kvm_dr6_valid(save->dr6)) || CC(!kvm_dr7_valid(save->dr7)))
3076906e06dSKrish Sadhukhan 		return false;
3086906e06dSKrish Sadhukhan 
309907afa48SEmanuele Giuseppe Esposito 	/*
310907afa48SEmanuele Giuseppe Esposito 	 * These checks are also performed by KVM_SET_SREGS,
311907afa48SEmanuele Giuseppe Esposito 	 * except that EFER.LMA is not checked by SVM against
312907afa48SEmanuele Giuseppe Esposito 	 * CR0.PG && EFER.LME.
313907afa48SEmanuele Giuseppe Esposito 	 */
314907afa48SEmanuele Giuseppe Esposito 	if ((save->efer & EFER_LME) && (save->cr0 & X86_CR0_PG)) {
315907afa48SEmanuele Giuseppe Esposito 		if (CC(!(save->cr4 & X86_CR4_PAE)) ||
316907afa48SEmanuele Giuseppe Esposito 		    CC(!(save->cr0 & X86_CR0_PE)) ||
317907afa48SEmanuele Giuseppe Esposito 		    CC(kvm_vcpu_is_illegal_gpa(vcpu, save->cr3)))
318907afa48SEmanuele Giuseppe Esposito 			return false;
319907afa48SEmanuele Giuseppe Esposito 	}
320907afa48SEmanuele Giuseppe Esposito 
321907afa48SEmanuele Giuseppe Esposito 	if (CC(!kvm_is_valid_cr4(vcpu, save->cr4)))
3226906e06dSKrish Sadhukhan 		return false;
3236906e06dSKrish Sadhukhan 
32463129754SPaolo Bonzini 	if (CC(!kvm_valid_efer(vcpu, save->efer)))
3256906e06dSKrish Sadhukhan 		return false;
3266906e06dSKrish Sadhukhan 
3276906e06dSKrish Sadhukhan 	return true;
3286906e06dSKrish Sadhukhan }
3296906e06dSKrish Sadhukhan 
330b7a3d8b6SEmanuele Giuseppe Esposito static bool nested_vmcb_check_save(struct kvm_vcpu *vcpu)
331b7a3d8b6SEmanuele Giuseppe Esposito {
332b7a3d8b6SEmanuele Giuseppe Esposito 	struct vcpu_svm *svm = to_svm(vcpu);
333b7a3d8b6SEmanuele Giuseppe Esposito 	struct vmcb_save_area_cached *save = &svm->nested.save;
334b7a3d8b6SEmanuele Giuseppe Esposito 
335b7a3d8b6SEmanuele Giuseppe Esposito 	return __nested_vmcb_check_save(vcpu, save);
336b7a3d8b6SEmanuele Giuseppe Esposito }
337b7a3d8b6SEmanuele Giuseppe Esposito 
338bd95926cSPaolo Bonzini static bool nested_vmcb_check_controls(struct kvm_vcpu *vcpu)
339bd95926cSPaolo Bonzini {
340bd95926cSPaolo Bonzini 	struct vcpu_svm *svm = to_svm(vcpu);
3418fc78909SEmanuele Giuseppe Esposito 	struct vmcb_ctrl_area_cached *ctl = &svm->nested.ctl;
342bd95926cSPaolo Bonzini 
343bd95926cSPaolo Bonzini 	return __nested_vmcb_check_controls(vcpu, ctl);
344bd95926cSPaolo Bonzini }
345bd95926cSPaolo Bonzini 
3467907160dSEmanuele Giuseppe Esposito static
34766c03a92SVitaly Kuznetsov void __nested_copy_vmcb_control_to_cache(struct kvm_vcpu *vcpu,
34866c03a92SVitaly Kuznetsov 					 struct vmcb_ctrl_area_cached *to,
3497907160dSEmanuele Giuseppe Esposito 					 struct vmcb_control_area *from)
3507907160dSEmanuele Giuseppe Esposito {
3517907160dSEmanuele Giuseppe Esposito 	unsigned int i;
3527907160dSEmanuele Giuseppe Esposito 
3537907160dSEmanuele Giuseppe Esposito 	for (i = 0; i < MAX_INTERCEPT; i++)
3547907160dSEmanuele Giuseppe Esposito 		to->intercepts[i] = from->intercepts[i];
3557907160dSEmanuele Giuseppe Esposito 
3567907160dSEmanuele Giuseppe Esposito 	to->iopm_base_pa        = from->iopm_base_pa;
3577907160dSEmanuele Giuseppe Esposito 	to->msrpm_base_pa       = from->msrpm_base_pa;
3587907160dSEmanuele Giuseppe Esposito 	to->tsc_offset          = from->tsc_offset;
3597907160dSEmanuele Giuseppe Esposito 	to->tlb_ctl             = from->tlb_ctl;
3607907160dSEmanuele Giuseppe Esposito 	to->int_ctl             = from->int_ctl;
3617907160dSEmanuele Giuseppe Esposito 	to->int_vector          = from->int_vector;
3627907160dSEmanuele Giuseppe Esposito 	to->int_state           = from->int_state;
3637907160dSEmanuele Giuseppe Esposito 	to->exit_code           = from->exit_code;
3647907160dSEmanuele Giuseppe Esposito 	to->exit_code_hi        = from->exit_code_hi;
3657907160dSEmanuele Giuseppe Esposito 	to->exit_info_1         = from->exit_info_1;
3667907160dSEmanuele Giuseppe Esposito 	to->exit_info_2         = from->exit_info_2;
3677907160dSEmanuele Giuseppe Esposito 	to->exit_int_info       = from->exit_int_info;
3687907160dSEmanuele Giuseppe Esposito 	to->exit_int_info_err   = from->exit_int_info_err;
3697907160dSEmanuele Giuseppe Esposito 	to->nested_ctl          = from->nested_ctl;
3707907160dSEmanuele Giuseppe Esposito 	to->event_inj           = from->event_inj;
3717907160dSEmanuele Giuseppe Esposito 	to->event_inj_err       = from->event_inj_err;
3727907160dSEmanuele Giuseppe Esposito 	to->nested_cr3          = from->nested_cr3;
3737907160dSEmanuele Giuseppe Esposito 	to->virt_ext            = from->virt_ext;
3747907160dSEmanuele Giuseppe Esposito 	to->pause_filter_count  = from->pause_filter_count;
3757907160dSEmanuele Giuseppe Esposito 	to->pause_filter_thresh = from->pause_filter_thresh;
3767907160dSEmanuele Giuseppe Esposito 
3777907160dSEmanuele Giuseppe Esposito 	/* Copy asid here because nested_vmcb_check_controls will check it.  */
3787907160dSEmanuele Giuseppe Esposito 	to->asid           = from->asid;
3797907160dSEmanuele Giuseppe Esposito 	to->msrpm_base_pa &= ~0x0fffULL;
3807907160dSEmanuele Giuseppe Esposito 	to->iopm_base_pa  &= ~0x0fffULL;
38166c03a92SVitaly Kuznetsov 
38266c03a92SVitaly Kuznetsov 	/* Hyper-V extensions (Enlightened VMCB) */
38366c03a92SVitaly Kuznetsov 	if (kvm_hv_hypercall_enabled(vcpu)) {
38466c03a92SVitaly Kuznetsov 		to->clean = from->clean;
38566c03a92SVitaly Kuznetsov 		memcpy(to->reserved_sw, from->reserved_sw,
38666c03a92SVitaly Kuznetsov 		       sizeof(struct hv_enlightenments));
38766c03a92SVitaly Kuznetsov 	}
3887907160dSEmanuele Giuseppe Esposito }
3897907160dSEmanuele Giuseppe Esposito 
3907907160dSEmanuele Giuseppe Esposito void nested_copy_vmcb_control_to_cache(struct vcpu_svm *svm,
3913e06f016SPaolo Bonzini 				       struct vmcb_control_area *control)
3923e06f016SPaolo Bonzini {
39366c03a92SVitaly Kuznetsov 	__nested_copy_vmcb_control_to_cache(&svm->vcpu, &svm->nested.ctl, control);
3943e06f016SPaolo Bonzini }
3953e06f016SPaolo Bonzini 
396f2740a8dSEmanuele Giuseppe Esposito static void __nested_copy_vmcb_save_to_cache(struct vmcb_save_area_cached *to,
397f2740a8dSEmanuele Giuseppe Esposito 					     struct vmcb_save_area *from)
398f2740a8dSEmanuele Giuseppe Esposito {
399f2740a8dSEmanuele Giuseppe Esposito 	/*
400f2740a8dSEmanuele Giuseppe Esposito 	 * Copy only fields that are validated, as we need them
401f2740a8dSEmanuele Giuseppe Esposito 	 * to avoid TOC/TOU races.
402f2740a8dSEmanuele Giuseppe Esposito 	 */
403f2740a8dSEmanuele Giuseppe Esposito 	to->efer = from->efer;
404f2740a8dSEmanuele Giuseppe Esposito 	to->cr0 = from->cr0;
405f2740a8dSEmanuele Giuseppe Esposito 	to->cr3 = from->cr3;
406f2740a8dSEmanuele Giuseppe Esposito 	to->cr4 = from->cr4;
407f2740a8dSEmanuele Giuseppe Esposito 
408f2740a8dSEmanuele Giuseppe Esposito 	to->dr6 = from->dr6;
409f2740a8dSEmanuele Giuseppe Esposito 	to->dr7 = from->dr7;
410f2740a8dSEmanuele Giuseppe Esposito }
411f2740a8dSEmanuele Giuseppe Esposito 
412f2740a8dSEmanuele Giuseppe Esposito void nested_copy_vmcb_save_to_cache(struct vcpu_svm *svm,
413f2740a8dSEmanuele Giuseppe Esposito 				    struct vmcb_save_area *save)
414f2740a8dSEmanuele Giuseppe Esposito {
415f2740a8dSEmanuele Giuseppe Esposito 	__nested_copy_vmcb_save_to_cache(&svm->nested.save, save);
416f2740a8dSEmanuele Giuseppe Esposito }
417f2740a8dSEmanuele Giuseppe Esposito 
4182d8a42beSPaolo Bonzini /*
4192d8a42beSPaolo Bonzini  * Synchronize fields that are written by the processor, so that
4209e8f0fbfSPaolo Bonzini  * they can be copied back into the vmcb12.
4212d8a42beSPaolo Bonzini  */
4229e8f0fbfSPaolo Bonzini void nested_sync_control_from_vmcb02(struct vcpu_svm *svm)
4232d8a42beSPaolo Bonzini {
4242d8a42beSPaolo Bonzini 	u32 mask;
4252d8a42beSPaolo Bonzini 	svm->nested.ctl.event_inj      = svm->vmcb->control.event_inj;
4262d8a42beSPaolo Bonzini 	svm->nested.ctl.event_inj_err  = svm->vmcb->control.event_inj_err;
4272d8a42beSPaolo Bonzini 
4282d8a42beSPaolo Bonzini 	/* Only a few fields of int_ctl are written by the processor.  */
4292d8a42beSPaolo Bonzini 	mask = V_IRQ_MASK | V_TPR_MASK;
4302d8a42beSPaolo Bonzini 	if (!(svm->nested.ctl.int_ctl & V_INTR_MASKING_MASK) &&
431a284ba56SJoerg Roedel 	    svm_is_intercept(svm, INTERCEPT_VINTR)) {
4322d8a42beSPaolo Bonzini 		/*
4332d8a42beSPaolo Bonzini 		 * In order to request an interrupt window, L0 is usurping
4342d8a42beSPaolo Bonzini 		 * svm->vmcb->control.int_ctl and possibly setting V_IRQ
4352d8a42beSPaolo Bonzini 		 * even if it was clear in L1's VMCB.  Restoring it would be
4362d8a42beSPaolo Bonzini 		 * wrong.  However, in this case V_IRQ will remain true until
4372d8a42beSPaolo Bonzini 		 * interrupt_window_interception calls svm_clear_vintr and
4382d8a42beSPaolo Bonzini 		 * restores int_ctl.  We can just leave it aside.
4392d8a42beSPaolo Bonzini 		 */
4402d8a42beSPaolo Bonzini 		mask &= ~V_IRQ_MASK;
4412d8a42beSPaolo Bonzini 	}
4422d8a42beSPaolo Bonzini 	svm->nested.ctl.int_ctl        &= ~mask;
4432d8a42beSPaolo Bonzini 	svm->nested.ctl.int_ctl        |= svm->vmcb->control.int_ctl & mask;
4442d8a42beSPaolo Bonzini }
4452d8a42beSPaolo Bonzini 
44636e2e983SPaolo Bonzini /*
44736e2e983SPaolo Bonzini  * Transfer any event that L0 or L1 wanted to inject into L2 to
44836e2e983SPaolo Bonzini  * EXIT_INT_INFO.
44936e2e983SPaolo Bonzini  */
4509e8f0fbfSPaolo Bonzini static void nested_save_pending_event_to_vmcb12(struct vcpu_svm *svm,
4510dd16b5bSMaxim Levitsky 						struct vmcb *vmcb12)
45236e2e983SPaolo Bonzini {
45336e2e983SPaolo Bonzini 	struct kvm_vcpu *vcpu = &svm->vcpu;
45436e2e983SPaolo Bonzini 	u32 exit_int_info = 0;
45536e2e983SPaolo Bonzini 	unsigned int nr;
45636e2e983SPaolo Bonzini 
45736e2e983SPaolo Bonzini 	if (vcpu->arch.exception.injected) {
45836e2e983SPaolo Bonzini 		nr = vcpu->arch.exception.nr;
45936e2e983SPaolo Bonzini 		exit_int_info = nr | SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_EXEPT;
46036e2e983SPaolo Bonzini 
46136e2e983SPaolo Bonzini 		if (vcpu->arch.exception.has_error_code) {
46236e2e983SPaolo Bonzini 			exit_int_info |= SVM_EVTINJ_VALID_ERR;
4630dd16b5bSMaxim Levitsky 			vmcb12->control.exit_int_info_err =
46436e2e983SPaolo Bonzini 				vcpu->arch.exception.error_code;
46536e2e983SPaolo Bonzini 		}
46636e2e983SPaolo Bonzini 
46736e2e983SPaolo Bonzini 	} else if (vcpu->arch.nmi_injected) {
46836e2e983SPaolo Bonzini 		exit_int_info = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI;
46936e2e983SPaolo Bonzini 
47036e2e983SPaolo Bonzini 	} else if (vcpu->arch.interrupt.injected) {
47136e2e983SPaolo Bonzini 		nr = vcpu->arch.interrupt.nr;
47236e2e983SPaolo Bonzini 		exit_int_info = nr | SVM_EVTINJ_VALID;
47336e2e983SPaolo Bonzini 
47436e2e983SPaolo Bonzini 		if (vcpu->arch.interrupt.soft)
47536e2e983SPaolo Bonzini 			exit_int_info |= SVM_EVTINJ_TYPE_SOFT;
47636e2e983SPaolo Bonzini 		else
47736e2e983SPaolo Bonzini 			exit_int_info |= SVM_EVTINJ_TYPE_INTR;
47836e2e983SPaolo Bonzini 	}
47936e2e983SPaolo Bonzini 
4800dd16b5bSMaxim Levitsky 	vmcb12->control.exit_int_info = exit_int_info;
48136e2e983SPaolo Bonzini }
48236e2e983SPaolo Bonzini 
483d2e56019SSean Christopherson static void nested_svm_transition_tlb_flush(struct kvm_vcpu *vcpu)
484d2e56019SSean Christopherson {
485d2e56019SSean Christopherson 	/*
486d2e56019SSean Christopherson 	 * TODO: optimize unconditional TLB flush/MMU sync.  A partial list of
487d2e56019SSean Christopherson 	 * things to fix before this can be conditional:
488d2e56019SSean Christopherson 	 *
489d2e56019SSean Christopherson 	 *  - Flush TLBs for both L1 and L2 remote TLB flush
490d2e56019SSean Christopherson 	 *  - Honor L1's request to flush an ASID on nested VMRUN
491d2e56019SSean Christopherson 	 *  - Sync nested NPT MMU on VMRUN that flushes L2's ASID[*]
492d2e56019SSean Christopherson 	 *  - Don't crush a pending TLB flush in vmcb02 on nested VMRUN
493d2e56019SSean Christopherson 	 *  - Flush L1's ASID on KVM_REQ_TLB_FLUSH_GUEST
494d2e56019SSean Christopherson 	 *
495d2e56019SSean Christopherson 	 * [*] Unlike nested EPT, SVM's ASID management can invalidate nested
496d2e56019SSean Christopherson 	 *     NPT guest-physical mappings on VMRUN.
497d2e56019SSean Christopherson 	 */
498d2e56019SSean Christopherson 	kvm_make_request(KVM_REQ_MMU_SYNC, vcpu);
499d2e56019SSean Christopherson 	kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu);
500d2e56019SSean Christopherson }
501d2e56019SSean Christopherson 
50262156f6cSVitaly Kuznetsov /*
503d82aaef9SVitaly Kuznetsov  * Load guest's/host's cr3 on nested vmentry or vmexit. @nested_npt is true
504d82aaef9SVitaly Kuznetsov  * if we are emulating VM-Entry into a guest with NPT enabled.
50562156f6cSVitaly Kuznetsov  */
50662156f6cSVitaly Kuznetsov static int nested_svm_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3,
507b222b0b8SMaxim Levitsky 			       bool nested_npt, bool reload_pdptrs)
50862156f6cSVitaly Kuznetsov {
50911f0cbf0SSean Christopherson 	if (CC(kvm_vcpu_is_illegal_gpa(vcpu, cr3)))
510a506fdd2SVitaly Kuznetsov 		return -EINVAL;
511a506fdd2SVitaly Kuznetsov 
512b222b0b8SMaxim Levitsky 	if (reload_pdptrs && !nested_npt && is_pae_paging(vcpu) &&
5132df4a5ebSLai Jiangshan 	    CC(!load_pdptrs(vcpu, cr3)))
514a506fdd2SVitaly Kuznetsov 		return -EINVAL;
515a506fdd2SVitaly Kuznetsov 
516a506fdd2SVitaly Kuznetsov 	vcpu->arch.cr3 = cr3;
517a506fdd2SVitaly Kuznetsov 
518616007c8SSean Christopherson 	/* Re-initialize the MMU, e.g. to pick up CR4 MMU role changes. */
519c9060662SSean Christopherson 	kvm_init_mmu(vcpu);
520a506fdd2SVitaly Kuznetsov 
5213cffc89dSPaolo Bonzini 	if (!nested_npt)
5223cffc89dSPaolo Bonzini 		kvm_mmu_new_pgd(vcpu, cr3);
5233cffc89dSPaolo Bonzini 
524a506fdd2SVitaly Kuznetsov 	return 0;
52562156f6cSVitaly Kuznetsov }
52662156f6cSVitaly Kuznetsov 
5274995a368SCathy Avery void nested_vmcb02_compute_g_pat(struct vcpu_svm *svm)
5284995a368SCathy Avery {
5294995a368SCathy Avery 	if (!svm->nested.vmcb02.ptr)
5304995a368SCathy Avery 		return;
5314995a368SCathy Avery 
5324995a368SCathy Avery 	/* FIXME: merge g_pat from vmcb01 and vmcb12.  */
5334995a368SCathy Avery 	svm->nested.vmcb02.ptr->save.g_pat = svm->vmcb01.ptr->save.g_pat;
5344995a368SCathy Avery }
5354995a368SCathy Avery 
5369e8f0fbfSPaolo Bonzini static void nested_vmcb02_prepare_save(struct vcpu_svm *svm, struct vmcb *vmcb12)
537883b0a91SJoerg Roedel {
5388173396eSCathy Avery 	bool new_vmcb12 = false;
5391d5a1b58SMaxim Levitsky 	struct vmcb *vmcb01 = svm->vmcb01.ptr;
540db663af4SMaxim Levitsky 	struct vmcb *vmcb02 = svm->nested.vmcb02.ptr;
5418173396eSCathy Avery 
5424995a368SCathy Avery 	nested_vmcb02_compute_g_pat(svm);
5434995a368SCathy Avery 
544883b0a91SJoerg Roedel 	/* Load the nested guest state */
5458173396eSCathy Avery 	if (svm->nested.vmcb12_gpa != svm->nested.last_vmcb12_gpa) {
5468173396eSCathy Avery 		new_vmcb12 = true;
5478173396eSCathy Avery 		svm->nested.last_vmcb12_gpa = svm->nested.vmcb12_gpa;
54873c25546SVitaly Kuznetsov 		svm->nested.force_msr_bitmap_recalc = true;
5498173396eSCathy Avery 	}
5508173396eSCathy Avery 
5518173396eSCathy Avery 	if (unlikely(new_vmcb12 || vmcb_is_dirty(vmcb12, VMCB_SEG))) {
552db663af4SMaxim Levitsky 		vmcb02->save.es = vmcb12->save.es;
553db663af4SMaxim Levitsky 		vmcb02->save.cs = vmcb12->save.cs;
554db663af4SMaxim Levitsky 		vmcb02->save.ss = vmcb12->save.ss;
555db663af4SMaxim Levitsky 		vmcb02->save.ds = vmcb12->save.ds;
556db663af4SMaxim Levitsky 		vmcb02->save.cpl = vmcb12->save.cpl;
557db663af4SMaxim Levitsky 		vmcb_mark_dirty(vmcb02, VMCB_SEG);
5588173396eSCathy Avery 	}
5594bb170a5SPaolo Bonzini 
5608173396eSCathy Avery 	if (unlikely(new_vmcb12 || vmcb_is_dirty(vmcb12, VMCB_DT))) {
561db663af4SMaxim Levitsky 		vmcb02->save.gdtr = vmcb12->save.gdtr;
562db663af4SMaxim Levitsky 		vmcb02->save.idtr = vmcb12->save.idtr;
563db663af4SMaxim Levitsky 		vmcb_mark_dirty(vmcb02, VMCB_DT);
5648173396eSCathy Avery 	}
5654bb170a5SPaolo Bonzini 
5668cce12b3SPaolo Bonzini 	kvm_set_rflags(&svm->vcpu, vmcb12->save.rflags | X86_EFLAGS_FIXED);
5673c346c0cSPaolo Bonzini 
568355d0473SEmanuele Giuseppe Esposito 	svm_set_efer(&svm->vcpu, svm->nested.save.efer);
5693c346c0cSPaolo Bonzini 
570355d0473SEmanuele Giuseppe Esposito 	svm_set_cr0(&svm->vcpu, svm->nested.save.cr0);
571355d0473SEmanuele Giuseppe Esposito 	svm_set_cr4(&svm->vcpu, svm->nested.save.cr4);
5724bb170a5SPaolo Bonzini 
5734bb170a5SPaolo Bonzini 	svm->vcpu.arch.cr2 = vmcb12->save.cr2;
5748173396eSCathy Avery 
5750dd16b5bSMaxim Levitsky 	kvm_rax_write(&svm->vcpu, vmcb12->save.rax);
5760dd16b5bSMaxim Levitsky 	kvm_rsp_write(&svm->vcpu, vmcb12->save.rsp);
5770dd16b5bSMaxim Levitsky 	kvm_rip_write(&svm->vcpu, vmcb12->save.rip);
578883b0a91SJoerg Roedel 
579883b0a91SJoerg Roedel 	/* In case we don't even reach vcpu_run, the fields are not updated */
580db663af4SMaxim Levitsky 	vmcb02->save.rax = vmcb12->save.rax;
581db663af4SMaxim Levitsky 	vmcb02->save.rsp = vmcb12->save.rsp;
582db663af4SMaxim Levitsky 	vmcb02->save.rip = vmcb12->save.rip;
5834bb170a5SPaolo Bonzini 
5848173396eSCathy Avery 	/* These bits will be set properly on the first execution when new_vmc12 is true */
5858173396eSCathy Avery 	if (unlikely(new_vmcb12 || vmcb_is_dirty(vmcb12, VMCB_DR))) {
586db663af4SMaxim Levitsky 		vmcb02->save.dr7 = svm->nested.save.dr7 | DR7_FIXED_1;
587355d0473SEmanuele Giuseppe Esposito 		svm->vcpu.arch.dr6  = svm->nested.save.dr6 | DR6_ACTIVE_LOW;
588db663af4SMaxim Levitsky 		vmcb_mark_dirty(vmcb02, VMCB_DR);
589f241d711SPaolo Bonzini 	}
5901d5a1b58SMaxim Levitsky 
591*d20c796cSMaxim Levitsky 	if (unlikely(svm->lbrv_enabled && (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK))) {
592*d20c796cSMaxim Levitsky 		/*
593*d20c796cSMaxim Levitsky 		 * Reserved bits of DEBUGCTL are ignored.  Be consistent with
594*d20c796cSMaxim Levitsky 		 * svm_set_msr's definition of reserved bits.
595*d20c796cSMaxim Levitsky 		 */
596*d20c796cSMaxim Levitsky 		svm_copy_lbrs(vmcb02, vmcb12);
597*d20c796cSMaxim Levitsky 		vmcb02->save.dbgctl &= ~DEBUGCTL_RESERVED_BITS;
598*d20c796cSMaxim Levitsky 		svm_update_lbrv(&svm->vcpu);
599*d20c796cSMaxim Levitsky 
600*d20c796cSMaxim Levitsky 	} else if (unlikely(vmcb01->control.virt_ext & LBR_CTL_ENABLE_MASK)) {
6011d5a1b58SMaxim Levitsky 		svm_copy_lbrs(vmcb02, vmcb01);
6028173396eSCathy Avery 	}
603*d20c796cSMaxim Levitsky }
604883b0a91SJoerg Roedel 
6059e8f0fbfSPaolo Bonzini static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
606f241d711SPaolo Bonzini {
6070f923e07SMaxim Levitsky 	const u32 int_ctl_vmcb01_bits =
6080f923e07SMaxim Levitsky 		V_INTR_MASKING_MASK | V_GIF_MASK | V_GIF_ENABLE_MASK;
6090f923e07SMaxim Levitsky 
6100f923e07SMaxim Levitsky 	const u32 int_ctl_vmcb12_bits = V_TPR_MASK | V_IRQ_INJECTION_BITS_MASK;
6110f923e07SMaxim Levitsky 
612d2e56019SSean Christopherson 	struct kvm_vcpu *vcpu = &svm->vcpu;
613db663af4SMaxim Levitsky 	struct vmcb *vmcb01 = svm->vmcb01.ptr;
614db663af4SMaxim Levitsky 	struct vmcb *vmcb02 = svm->nested.vmcb02.ptr;
61562156f6cSVitaly Kuznetsov 
6167c3ecfcdSPaolo Bonzini 	/*
6177c3ecfcdSPaolo Bonzini 	 * Filled at exit: exit_code, exit_code_hi, exit_info_1, exit_info_2,
6187c3ecfcdSPaolo Bonzini 	 * exit_int_info, exit_int_info_err, next_rip, insn_len, insn_bytes.
6197c3ecfcdSPaolo Bonzini 	 */
6204995a368SCathy Avery 
6217c3ecfcdSPaolo Bonzini 	/*
6227c3ecfcdSPaolo Bonzini 	 * Also covers avic_vapic_bar, avic_backing_page, avic_logical_id,
6237c3ecfcdSPaolo Bonzini 	 * avic_physical_id.
6247c3ecfcdSPaolo Bonzini 	 */
625feea0136SMaxim Levitsky 	WARN_ON(kvm_apicv_activated(svm->vcpu.kvm));
6267c3ecfcdSPaolo Bonzini 
6277c3ecfcdSPaolo Bonzini 	/* Copied from vmcb01.  msrpm_base can be overwritten later.  */
628db663af4SMaxim Levitsky 	vmcb02->control.nested_ctl = vmcb01->control.nested_ctl;
629db663af4SMaxim Levitsky 	vmcb02->control.iopm_base_pa = vmcb01->control.iopm_base_pa;
630db663af4SMaxim Levitsky 	vmcb02->control.msrpm_base_pa = vmcb01->control.msrpm_base_pa;
6317c3ecfcdSPaolo Bonzini 
6327c3ecfcdSPaolo Bonzini 	/* Done at vmrun: asid.  */
6337c3ecfcdSPaolo Bonzini 
6347c3ecfcdSPaolo Bonzini 	/* Also overwritten later if necessary.  */
635db663af4SMaxim Levitsky 	vmcb02->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
6367c3ecfcdSPaolo Bonzini 
6377c3ecfcdSPaolo Bonzini 	/* nested_cr3.  */
63862156f6cSVitaly Kuznetsov 	if (nested_npt_enabled(svm))
639d2e56019SSean Christopherson 		nested_svm_init_mmu_context(vcpu);
64069cb8774SPaolo Bonzini 
6415228eb96SMaxim Levitsky 	vcpu->arch.tsc_offset = kvm_calc_nested_tsc_offset(
6425228eb96SMaxim Levitsky 			vcpu->arch.l1_tsc_offset,
6435228eb96SMaxim Levitsky 			svm->nested.ctl.tsc_offset,
6445228eb96SMaxim Levitsky 			svm->tsc_ratio_msr);
6455228eb96SMaxim Levitsky 
646db663af4SMaxim Levitsky 	vmcb02->control.tsc_offset = vcpu->arch.tsc_offset;
6475228eb96SMaxim Levitsky 
6485228eb96SMaxim Levitsky 	if (svm->tsc_ratio_msr != kvm_default_tsc_scaling_ratio) {
6495228eb96SMaxim Levitsky 		WARN_ON(!svm->tsc_scaling_enabled);
6505228eb96SMaxim Levitsky 		nested_svm_update_tsc_ratio_msr(vcpu);
6515228eb96SMaxim Levitsky 	}
652883b0a91SJoerg Roedel 
653db663af4SMaxim Levitsky 	vmcb02->control.int_ctl             =
6540f923e07SMaxim Levitsky 		(svm->nested.ctl.int_ctl & int_ctl_vmcb12_bits) |
655db663af4SMaxim Levitsky 		(vmcb01->control.int_ctl & int_ctl_vmcb01_bits);
65691b7130cSPaolo Bonzini 
657db663af4SMaxim Levitsky 	vmcb02->control.int_vector          = svm->nested.ctl.int_vector;
658db663af4SMaxim Levitsky 	vmcb02->control.int_state           = svm->nested.ctl.int_state;
659db663af4SMaxim Levitsky 	vmcb02->control.event_inj           = svm->nested.ctl.event_inj;
660db663af4SMaxim Levitsky 	vmcb02->control.event_inj_err       = svm->nested.ctl.event_inj_err;
661883b0a91SJoerg Roedel 
6621d5a1b58SMaxim Levitsky 	vmcb02->control.virt_ext            = vmcb01->control.virt_ext &
6631d5a1b58SMaxim Levitsky 					      LBR_CTL_ENABLE_MASK;
664*d20c796cSMaxim Levitsky 	if (svm->lbrv_enabled)
665*d20c796cSMaxim Levitsky 		vmcb02->control.virt_ext  |=
666*d20c796cSMaxim Levitsky 			(svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK);
6671d5a1b58SMaxim Levitsky 
668b9f3973aSMaxim Levitsky 	if (!nested_vmcb_needs_vls_intercept(svm))
669db663af4SMaxim Levitsky 		vmcb02->control.virt_ext |= VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK;
670b9f3973aSMaxim Levitsky 
671d2e56019SSean Christopherson 	nested_svm_transition_tlb_flush(vcpu);
672d2e56019SSean Christopherson 
673883b0a91SJoerg Roedel 	/* Enter Guest-Mode */
674d2e56019SSean Christopherson 	enter_guest_mode(vcpu);
675883b0a91SJoerg Roedel 
676883b0a91SJoerg Roedel 	/*
677883b0a91SJoerg Roedel 	 * Merge guest and host intercepts - must be called with vcpu in
6784bb170a5SPaolo Bonzini 	 * guest-mode to take effect.
679883b0a91SJoerg Roedel 	 */
680883b0a91SJoerg Roedel 	recalc_intercepts(svm);
681f241d711SPaolo Bonzini }
682f241d711SPaolo Bonzini 
683d00b99c5SBabu Moger static void nested_svm_copy_common_state(struct vmcb *from_vmcb, struct vmcb *to_vmcb)
684d00b99c5SBabu Moger {
685d00b99c5SBabu Moger 	/*
686d00b99c5SBabu Moger 	 * Some VMCB state is shared between L1 and L2 and thus has to be
687d00b99c5SBabu Moger 	 * moved at the time of nested vmrun and vmexit.
688d00b99c5SBabu Moger 	 *
689d00b99c5SBabu Moger 	 * VMLOAD/VMSAVE state would also belong in this category, but KVM
690d00b99c5SBabu Moger 	 * always performs VMLOAD and VMSAVE from the VMCB01.
691d00b99c5SBabu Moger 	 */
692d00b99c5SBabu Moger 	to_vmcb->save.spec_ctrl = from_vmcb->save.spec_ctrl;
693d00b99c5SBabu Moger }
694d00b99c5SBabu Moger 
69563129754SPaolo Bonzini int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64 vmcb12_gpa,
696e85d3e7bSMaxim Levitsky 			 struct vmcb *vmcb12, bool from_vmrun)
697f241d711SPaolo Bonzini {
69863129754SPaolo Bonzini 	struct vcpu_svm *svm = to_svm(vcpu);
699a506fdd2SVitaly Kuznetsov 	int ret;
700a506fdd2SVitaly Kuznetsov 
701954f419bSMaxim Levitsky 	trace_kvm_nested_vmrun(svm->vmcb->save.rip, vmcb12_gpa,
702954f419bSMaxim Levitsky 			       vmcb12->save.rip,
703954f419bSMaxim Levitsky 			       vmcb12->control.int_ctl,
704954f419bSMaxim Levitsky 			       vmcb12->control.event_inj,
705954f419bSMaxim Levitsky 			       vmcb12->control.nested_ctl);
706954f419bSMaxim Levitsky 
707954f419bSMaxim Levitsky 	trace_kvm_nested_intercepts(vmcb12->control.intercepts[INTERCEPT_CR] & 0xffff,
708954f419bSMaxim Levitsky 				    vmcb12->control.intercepts[INTERCEPT_CR] >> 16,
709954f419bSMaxim Levitsky 				    vmcb12->control.intercepts[INTERCEPT_EXCEPTION],
710954f419bSMaxim Levitsky 				    vmcb12->control.intercepts[INTERCEPT_WORD3],
711954f419bSMaxim Levitsky 				    vmcb12->control.intercepts[INTERCEPT_WORD4],
712954f419bSMaxim Levitsky 				    vmcb12->control.intercepts[INTERCEPT_WORD5]);
713954f419bSMaxim Levitsky 
714954f419bSMaxim Levitsky 
7150dd16b5bSMaxim Levitsky 	svm->nested.vmcb12_gpa = vmcb12_gpa;
7164995a368SCathy Avery 
7174995a368SCathy Avery 	WARN_ON(svm->vmcb == svm->nested.vmcb02.ptr);
7184995a368SCathy Avery 
719d00b99c5SBabu Moger 	nested_svm_copy_common_state(svm->vmcb01.ptr, svm->nested.vmcb02.ptr);
7204995a368SCathy Avery 
7214995a368SCathy Avery 	svm_switch_vmcb(svm, &svm->nested.vmcb02);
7229e8f0fbfSPaolo Bonzini 	nested_vmcb02_prepare_control(svm);
7239e8f0fbfSPaolo Bonzini 	nested_vmcb02_prepare_save(svm, vmcb12);
724f241d711SPaolo Bonzini 
725355d0473SEmanuele Giuseppe Esposito 	ret = nested_svm_load_cr3(&svm->vcpu, svm->nested.save.cr3,
726e85d3e7bSMaxim Levitsky 				  nested_npt_enabled(svm), from_vmrun);
727a506fdd2SVitaly Kuznetsov 	if (ret)
728a506fdd2SVitaly Kuznetsov 		return ret;
729a506fdd2SVitaly Kuznetsov 
730a04aead1SPaolo Bonzini 	if (!npt_enabled)
73163129754SPaolo Bonzini 		vcpu->arch.mmu->inject_page_fault = svm_inject_page_fault_nested;
732a04aead1SPaolo Bonzini 
733e85d3e7bSMaxim Levitsky 	if (!from_vmrun)
734e85d3e7bSMaxim Levitsky 		kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu);
735e85d3e7bSMaxim Levitsky 
736ffdf7f9eSPaolo Bonzini 	svm_set_gif(svm, true);
73759cd9bc5SVitaly Kuznetsov 
73859cd9bc5SVitaly Kuznetsov 	return 0;
739883b0a91SJoerg Roedel }
740883b0a91SJoerg Roedel 
74163129754SPaolo Bonzini int nested_svm_vmrun(struct kvm_vcpu *vcpu)
742883b0a91SJoerg Roedel {
74363129754SPaolo Bonzini 	struct vcpu_svm *svm = to_svm(vcpu);
744883b0a91SJoerg Roedel 	int ret;
7450dd16b5bSMaxim Levitsky 	struct vmcb *vmcb12;
746883b0a91SJoerg Roedel 	struct kvm_host_map map;
7470dd16b5bSMaxim Levitsky 	u64 vmcb12_gpa;
748db663af4SMaxim Levitsky 	struct vmcb *vmcb01 = svm->vmcb01.ptr;
749883b0a91SJoerg Roedel 
750fb79f566SVitaly Kuznetsov 	if (!svm->nested.hsave_msr) {
751fb79f566SVitaly Kuznetsov 		kvm_inject_gp(vcpu, 0);
752fb79f566SVitaly Kuznetsov 		return 1;
753fb79f566SVitaly Kuznetsov 	}
754fb79f566SVitaly Kuznetsov 
75563129754SPaolo Bonzini 	if (is_smm(vcpu)) {
75663129754SPaolo Bonzini 		kvm_queue_exception(vcpu, UD_VECTOR);
7577c67f546SPaolo Bonzini 		return 1;
7587c67f546SPaolo Bonzini 	}
759883b0a91SJoerg Roedel 
7600dd16b5bSMaxim Levitsky 	vmcb12_gpa = svm->vmcb->save.rax;
76163129754SPaolo Bonzini 	ret = kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map);
762883b0a91SJoerg Roedel 	if (ret == -EINVAL) {
76363129754SPaolo Bonzini 		kvm_inject_gp(vcpu, 0);
764883b0a91SJoerg Roedel 		return 1;
765883b0a91SJoerg Roedel 	} else if (ret) {
76663129754SPaolo Bonzini 		return kvm_skip_emulated_instruction(vcpu);
767883b0a91SJoerg Roedel 	}
768883b0a91SJoerg Roedel 
76963129754SPaolo Bonzini 	ret = kvm_skip_emulated_instruction(vcpu);
770883b0a91SJoerg Roedel 
7710dd16b5bSMaxim Levitsky 	vmcb12 = map.hva;
772883b0a91SJoerg Roedel 
7732fcf4876SMaxim Levitsky 	if (WARN_ON_ONCE(!svm->nested.initialized))
7742fcf4876SMaxim Levitsky 		return -EINVAL;
7752fcf4876SMaxim Levitsky 
7767907160dSEmanuele Giuseppe Esposito 	nested_copy_vmcb_control_to_cache(svm, &vmcb12->control);
777f2740a8dSEmanuele Giuseppe Esposito 	nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);
778cb9b6a1bSPaolo Bonzini 
779b7a3d8b6SEmanuele Giuseppe Esposito 	if (!nested_vmcb_check_save(vcpu) ||
780bd95926cSPaolo Bonzini 	    !nested_vmcb_check_controls(vcpu)) {
7810dd16b5bSMaxim Levitsky 		vmcb12->control.exit_code    = SVM_EXIT_ERR;
7820dd16b5bSMaxim Levitsky 		vmcb12->control.exit_code_hi = 0;
7830dd16b5bSMaxim Levitsky 		vmcb12->control.exit_info_1  = 0;
7840dd16b5bSMaxim Levitsky 		vmcb12->control.exit_info_2  = 0;
78569c9dfa2SPaolo Bonzini 		goto out;
786883b0a91SJoerg Roedel 	}
787883b0a91SJoerg Roedel 
788883b0a91SJoerg Roedel 	/*
7894995a368SCathy Avery 	 * Since vmcb01 is not in use, we can use it to store some of the L1
7904995a368SCathy Avery 	 * state.
791883b0a91SJoerg Roedel 	 */
792db663af4SMaxim Levitsky 	vmcb01->save.efer   = vcpu->arch.efer;
793db663af4SMaxim Levitsky 	vmcb01->save.cr0    = kvm_read_cr0(vcpu);
794db663af4SMaxim Levitsky 	vmcb01->save.cr4    = vcpu->arch.cr4;
795db663af4SMaxim Levitsky 	vmcb01->save.rflags = kvm_get_rflags(vcpu);
796db663af4SMaxim Levitsky 	vmcb01->save.rip    = kvm_rip_read(vcpu);
797883b0a91SJoerg Roedel 
7984995a368SCathy Avery 	if (!npt_enabled)
799db663af4SMaxim Levitsky 		vmcb01->save.cr3 = kvm_read_cr3(vcpu);
800883b0a91SJoerg Roedel 
801f74f9414SPaolo Bonzini 	svm->nested.nested_run_pending = 1;
802883b0a91SJoerg Roedel 
803e85d3e7bSMaxim Levitsky 	if (enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, true))
80459cd9bc5SVitaly Kuznetsov 		goto out_exit_err;
80559cd9bc5SVitaly Kuznetsov 
80659cd9bc5SVitaly Kuznetsov 	if (nested_svm_vmrun_msrpm(svm))
80759cd9bc5SVitaly Kuznetsov 		goto out;
80859cd9bc5SVitaly Kuznetsov 
80959cd9bc5SVitaly Kuznetsov out_exit_err:
810ebdb3dbaSVitaly Kuznetsov 	svm->nested.nested_run_pending = 0;
811ebdb3dbaSVitaly Kuznetsov 
812883b0a91SJoerg Roedel 	svm->vmcb->control.exit_code    = SVM_EXIT_ERR;
813883b0a91SJoerg Roedel 	svm->vmcb->control.exit_code_hi = 0;
814883b0a91SJoerg Roedel 	svm->vmcb->control.exit_info_1  = 0;
815883b0a91SJoerg Roedel 	svm->vmcb->control.exit_info_2  = 0;
816883b0a91SJoerg Roedel 
817883b0a91SJoerg Roedel 	nested_svm_vmexit(svm);
818883b0a91SJoerg Roedel 
81969c9dfa2SPaolo Bonzini out:
82063129754SPaolo Bonzini 	kvm_vcpu_unmap(vcpu, &map, true);
82169c9dfa2SPaolo Bonzini 
822883b0a91SJoerg Roedel 	return ret;
823883b0a91SJoerg Roedel }
824883b0a91SJoerg Roedel 
8250a758290SVitaly Kuznetsov /* Copy state save area fields which are handled by VMRUN */
8262bb16beaSVitaly Kuznetsov void svm_copy_vmrun_state(struct vmcb_save_area *to_save,
8272bb16beaSVitaly Kuznetsov 			  struct vmcb_save_area *from_save)
8280a758290SVitaly Kuznetsov {
8290a758290SVitaly Kuznetsov 	to_save->es = from_save->es;
8300a758290SVitaly Kuznetsov 	to_save->cs = from_save->cs;
8310a758290SVitaly Kuznetsov 	to_save->ss = from_save->ss;
8320a758290SVitaly Kuznetsov 	to_save->ds = from_save->ds;
8330a758290SVitaly Kuznetsov 	to_save->gdtr = from_save->gdtr;
8340a758290SVitaly Kuznetsov 	to_save->idtr = from_save->idtr;
8350a758290SVitaly Kuznetsov 	to_save->rflags = from_save->rflags | X86_EFLAGS_FIXED;
8360a758290SVitaly Kuznetsov 	to_save->efer = from_save->efer;
8370a758290SVitaly Kuznetsov 	to_save->cr0 = from_save->cr0;
8380a758290SVitaly Kuznetsov 	to_save->cr3 = from_save->cr3;
8390a758290SVitaly Kuznetsov 	to_save->cr4 = from_save->cr4;
8400a758290SVitaly Kuznetsov 	to_save->rax = from_save->rax;
8410a758290SVitaly Kuznetsov 	to_save->rsp = from_save->rsp;
8420a758290SVitaly Kuznetsov 	to_save->rip = from_save->rip;
8430a758290SVitaly Kuznetsov 	to_save->cpl = 0;
8440a758290SVitaly Kuznetsov }
8450a758290SVitaly Kuznetsov 
8462bb16beaSVitaly Kuznetsov void svm_copy_vmloadsave_state(struct vmcb *to_vmcb, struct vmcb *from_vmcb)
847883b0a91SJoerg Roedel {
848883b0a91SJoerg Roedel 	to_vmcb->save.fs = from_vmcb->save.fs;
849883b0a91SJoerg Roedel 	to_vmcb->save.gs = from_vmcb->save.gs;
850883b0a91SJoerg Roedel 	to_vmcb->save.tr = from_vmcb->save.tr;
851883b0a91SJoerg Roedel 	to_vmcb->save.ldtr = from_vmcb->save.ldtr;
852883b0a91SJoerg Roedel 	to_vmcb->save.kernel_gs_base = from_vmcb->save.kernel_gs_base;
853883b0a91SJoerg Roedel 	to_vmcb->save.star = from_vmcb->save.star;
854883b0a91SJoerg Roedel 	to_vmcb->save.lstar = from_vmcb->save.lstar;
855883b0a91SJoerg Roedel 	to_vmcb->save.cstar = from_vmcb->save.cstar;
856883b0a91SJoerg Roedel 	to_vmcb->save.sfmask = from_vmcb->save.sfmask;
857883b0a91SJoerg Roedel 	to_vmcb->save.sysenter_cs = from_vmcb->save.sysenter_cs;
858883b0a91SJoerg Roedel 	to_vmcb->save.sysenter_esp = from_vmcb->save.sysenter_esp;
859883b0a91SJoerg Roedel 	to_vmcb->save.sysenter_eip = from_vmcb->save.sysenter_eip;
860883b0a91SJoerg Roedel }
861883b0a91SJoerg Roedel 
862883b0a91SJoerg Roedel int nested_svm_vmexit(struct vcpu_svm *svm)
863883b0a91SJoerg Roedel {
86463129754SPaolo Bonzini 	struct kvm_vcpu *vcpu = &svm->vcpu;
865db663af4SMaxim Levitsky 	struct vmcb *vmcb01 = svm->vmcb01.ptr;
866db663af4SMaxim Levitsky 	struct vmcb *vmcb02 = svm->nested.vmcb02.ptr;
8670dd16b5bSMaxim Levitsky 	struct vmcb *vmcb12;
868883b0a91SJoerg Roedel 	struct kvm_host_map map;
86963129754SPaolo Bonzini 	int rc;
870883b0a91SJoerg Roedel 
871cb6a32c2SSean Christopherson 	/* Triple faults in L2 should never escape. */
872cb6a32c2SSean Christopherson 	WARN_ON_ONCE(kvm_check_request(KVM_REQ_TRIPLE_FAULT, vcpu));
873cb6a32c2SSean Christopherson 
87463129754SPaolo Bonzini 	rc = kvm_vcpu_map(vcpu, gpa_to_gfn(svm->nested.vmcb12_gpa), &map);
875883b0a91SJoerg Roedel 	if (rc) {
876883b0a91SJoerg Roedel 		if (rc == -EINVAL)
87763129754SPaolo Bonzini 			kvm_inject_gp(vcpu, 0);
878883b0a91SJoerg Roedel 		return 1;
879883b0a91SJoerg Roedel 	}
880883b0a91SJoerg Roedel 
8810dd16b5bSMaxim Levitsky 	vmcb12 = map.hva;
882883b0a91SJoerg Roedel 
883883b0a91SJoerg Roedel 	/* Exit Guest-Mode */
88463129754SPaolo Bonzini 	leave_guest_mode(vcpu);
8850dd16b5bSMaxim Levitsky 	svm->nested.vmcb12_gpa = 0;
8862d8a42beSPaolo Bonzini 	WARN_ON_ONCE(svm->nested.nested_run_pending);
887883b0a91SJoerg Roedel 
88863129754SPaolo Bonzini 	kvm_clear_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu);
889f2c7ef3bSMaxim Levitsky 
89038c0b192SPaolo Bonzini 	/* in case we halted in L2 */
89138c0b192SPaolo Bonzini 	svm->vcpu.arch.mp_state = KVM_MP_STATE_RUNNABLE;
89238c0b192SPaolo Bonzini 
893883b0a91SJoerg Roedel 	/* Give the current vmcb to the guest */
894883b0a91SJoerg Roedel 
895db663af4SMaxim Levitsky 	vmcb12->save.es     = vmcb02->save.es;
896db663af4SMaxim Levitsky 	vmcb12->save.cs     = vmcb02->save.cs;
897db663af4SMaxim Levitsky 	vmcb12->save.ss     = vmcb02->save.ss;
898db663af4SMaxim Levitsky 	vmcb12->save.ds     = vmcb02->save.ds;
899db663af4SMaxim Levitsky 	vmcb12->save.gdtr   = vmcb02->save.gdtr;
900db663af4SMaxim Levitsky 	vmcb12->save.idtr   = vmcb02->save.idtr;
9010dd16b5bSMaxim Levitsky 	vmcb12->save.efer   = svm->vcpu.arch.efer;
90263129754SPaolo Bonzini 	vmcb12->save.cr0    = kvm_read_cr0(vcpu);
90363129754SPaolo Bonzini 	vmcb12->save.cr3    = kvm_read_cr3(vcpu);
904db663af4SMaxim Levitsky 	vmcb12->save.cr2    = vmcb02->save.cr2;
9050dd16b5bSMaxim Levitsky 	vmcb12->save.cr4    = svm->vcpu.arch.cr4;
90663129754SPaolo Bonzini 	vmcb12->save.rflags = kvm_get_rflags(vcpu);
90763129754SPaolo Bonzini 	vmcb12->save.rip    = kvm_rip_read(vcpu);
90863129754SPaolo Bonzini 	vmcb12->save.rsp    = kvm_rsp_read(vcpu);
90963129754SPaolo Bonzini 	vmcb12->save.rax    = kvm_rax_read(vcpu);
910db663af4SMaxim Levitsky 	vmcb12->save.dr7    = vmcb02->save.dr7;
9110dd16b5bSMaxim Levitsky 	vmcb12->save.dr6    = svm->vcpu.arch.dr6;
912db663af4SMaxim Levitsky 	vmcb12->save.cpl    = vmcb02->save.cpl;
913883b0a91SJoerg Roedel 
914db663af4SMaxim Levitsky 	vmcb12->control.int_state         = vmcb02->control.int_state;
915db663af4SMaxim Levitsky 	vmcb12->control.exit_code         = vmcb02->control.exit_code;
916db663af4SMaxim Levitsky 	vmcb12->control.exit_code_hi      = vmcb02->control.exit_code_hi;
917db663af4SMaxim Levitsky 	vmcb12->control.exit_info_1       = vmcb02->control.exit_info_1;
918db663af4SMaxim Levitsky 	vmcb12->control.exit_info_2       = vmcb02->control.exit_info_2;
91936e2e983SPaolo Bonzini 
9200dd16b5bSMaxim Levitsky 	if (vmcb12->control.exit_code != SVM_EXIT_ERR)
9219e8f0fbfSPaolo Bonzini 		nested_save_pending_event_to_vmcb12(svm, vmcb12);
922883b0a91SJoerg Roedel 
923883b0a91SJoerg Roedel 	if (svm->nrips_enabled)
924db663af4SMaxim Levitsky 		vmcb12->control.next_rip  = vmcb02->control.next_rip;
925883b0a91SJoerg Roedel 
9260dd16b5bSMaxim Levitsky 	vmcb12->control.int_ctl           = svm->nested.ctl.int_ctl;
9270dd16b5bSMaxim Levitsky 	vmcb12->control.tlb_ctl           = svm->nested.ctl.tlb_ctl;
9280dd16b5bSMaxim Levitsky 	vmcb12->control.event_inj         = svm->nested.ctl.event_inj;
9290dd16b5bSMaxim Levitsky 	vmcb12->control.event_inj_err     = svm->nested.ctl.event_inj_err;
930883b0a91SJoerg Roedel 
931d00b99c5SBabu Moger 	nested_svm_copy_common_state(svm->nested.vmcb02.ptr, svm->vmcb01.ptr);
932d00b99c5SBabu Moger 
9334995a368SCathy Avery 	svm_switch_vmcb(svm, &svm->vmcb01);
9344995a368SCathy Avery 
935*d20c796cSMaxim Levitsky 	if (unlikely(svm->lbrv_enabled && (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK))) {
936*d20c796cSMaxim Levitsky 		svm_copy_lbrs(vmcb12, vmcb02);
937*d20c796cSMaxim Levitsky 		svm_update_lbrv(vcpu);
938*d20c796cSMaxim Levitsky 	} else if (unlikely(vmcb01->control.virt_ext & LBR_CTL_ENABLE_MASK)) {
9391d5a1b58SMaxim Levitsky 		svm_copy_lbrs(vmcb01, vmcb02);
9401d5a1b58SMaxim Levitsky 		svm_update_lbrv(vcpu);
9411d5a1b58SMaxim Levitsky 	}
9421d5a1b58SMaxim Levitsky 
9434995a368SCathy Avery 	/*
9444995a368SCathy Avery 	 * On vmexit the  GIF is set to false and
9454995a368SCathy Avery 	 * no event can be injected in L1.
9464995a368SCathy Avery 	 */
9479883764aSMaxim Levitsky 	svm_set_gif(svm, false);
948db663af4SMaxim Levitsky 	vmcb01->control.exit_int_info = 0;
9499883764aSMaxim Levitsky 
9507ca62d13SPaolo Bonzini 	svm->vcpu.arch.tsc_offset = svm->vcpu.arch.l1_tsc_offset;
951db663af4SMaxim Levitsky 	if (vmcb01->control.tsc_offset != svm->vcpu.arch.tsc_offset) {
952db663af4SMaxim Levitsky 		vmcb01->control.tsc_offset = svm->vcpu.arch.tsc_offset;
953db663af4SMaxim Levitsky 		vmcb_mark_dirty(vmcb01, VMCB_INTERCEPTS);
9547ca62d13SPaolo Bonzini 	}
95518fc6c55SPaolo Bonzini 
9565228eb96SMaxim Levitsky 	if (svm->tsc_ratio_msr != kvm_default_tsc_scaling_ratio) {
9575228eb96SMaxim Levitsky 		WARN_ON(!svm->tsc_scaling_enabled);
9585228eb96SMaxim Levitsky 		vcpu->arch.tsc_scaling_ratio = vcpu->arch.l1_tsc_scaling_ratio;
9595228eb96SMaxim Levitsky 		svm_write_tsc_multiplier(vcpu, vcpu->arch.tsc_scaling_ratio);
9605228eb96SMaxim Levitsky 	}
9615228eb96SMaxim Levitsky 
962e670bf68SPaolo Bonzini 	svm->nested.ctl.nested_cr3 = 0;
963883b0a91SJoerg Roedel 
9644995a368SCathy Avery 	/*
9654995a368SCathy Avery 	 * Restore processor state that had been saved in vmcb01
9664995a368SCathy Avery 	 */
967db663af4SMaxim Levitsky 	kvm_set_rflags(vcpu, vmcb01->save.rflags);
968db663af4SMaxim Levitsky 	svm_set_efer(vcpu, vmcb01->save.efer);
969db663af4SMaxim Levitsky 	svm_set_cr0(vcpu, vmcb01->save.cr0 | X86_CR0_PE);
970db663af4SMaxim Levitsky 	svm_set_cr4(vcpu, vmcb01->save.cr4);
971db663af4SMaxim Levitsky 	kvm_rax_write(vcpu, vmcb01->save.rax);
972db663af4SMaxim Levitsky 	kvm_rsp_write(vcpu, vmcb01->save.rsp);
973db663af4SMaxim Levitsky 	kvm_rip_write(vcpu, vmcb01->save.rip);
9744995a368SCathy Avery 
9754995a368SCathy Avery 	svm->vcpu.arch.dr7 = DR7_FIXED_1;
9764995a368SCathy Avery 	kvm_update_dr7(&svm->vcpu);
977883b0a91SJoerg Roedel 
9780dd16b5bSMaxim Levitsky 	trace_kvm_nested_vmexit_inject(vmcb12->control.exit_code,
9790dd16b5bSMaxim Levitsky 				       vmcb12->control.exit_info_1,
9800dd16b5bSMaxim Levitsky 				       vmcb12->control.exit_info_2,
9810dd16b5bSMaxim Levitsky 				       vmcb12->control.exit_int_info,
9820dd16b5bSMaxim Levitsky 				       vmcb12->control.exit_int_info_err,
98336e2e983SPaolo Bonzini 				       KVM_ISA_SVM);
98436e2e983SPaolo Bonzini 
98563129754SPaolo Bonzini 	kvm_vcpu_unmap(vcpu, &map, true);
986883b0a91SJoerg Roedel 
987d2e56019SSean Christopherson 	nested_svm_transition_tlb_flush(vcpu);
988d2e56019SSean Christopherson 
98963129754SPaolo Bonzini 	nested_svm_uninit_mmu_context(vcpu);
990bf7dea42SVitaly Kuznetsov 
991db663af4SMaxim Levitsky 	rc = nested_svm_load_cr3(vcpu, vmcb01->save.cr3, false, true);
992d82aaef9SVitaly Kuznetsov 	if (rc)
993d82aaef9SVitaly Kuznetsov 		return 1;
994bf7dea42SVitaly Kuznetsov 
995883b0a91SJoerg Roedel 	/*
996883b0a91SJoerg Roedel 	 * Drop what we picked up for L2 via svm_complete_interrupts() so it
997883b0a91SJoerg Roedel 	 * doesn't end up in L1.
998883b0a91SJoerg Roedel 	 */
999883b0a91SJoerg Roedel 	svm->vcpu.arch.nmi_injected = false;
100063129754SPaolo Bonzini 	kvm_clear_exception_queue(vcpu);
100163129754SPaolo Bonzini 	kvm_clear_interrupt_queue(vcpu);
1002883b0a91SJoerg Roedel 
10039a7de6ecSKrish Sadhukhan 	/*
10049a7de6ecSKrish Sadhukhan 	 * If we are here following the completion of a VMRUN that
10059a7de6ecSKrish Sadhukhan 	 * is being single-stepped, queue the pending #DB intercept
10069a7de6ecSKrish Sadhukhan 	 * right now so that it an be accounted for before we execute
10079a7de6ecSKrish Sadhukhan 	 * L1's next instruction.
10089a7de6ecSKrish Sadhukhan 	 */
1009db663af4SMaxim Levitsky 	if (unlikely(vmcb01->save.rflags & X86_EFLAGS_TF))
10109a7de6ecSKrish Sadhukhan 		kvm_queue_exception(&(svm->vcpu), DB_VECTOR);
10119a7de6ecSKrish Sadhukhan 
1012883b0a91SJoerg Roedel 	return 0;
1013883b0a91SJoerg Roedel }
1014883b0a91SJoerg Roedel 
1015cb6a32c2SSean Christopherson static void nested_svm_triple_fault(struct kvm_vcpu *vcpu)
1016cb6a32c2SSean Christopherson {
10173a87c7e0SSean Christopherson 	nested_svm_simple_vmexit(to_svm(vcpu), SVM_EXIT_SHUTDOWN);
1018cb6a32c2SSean Christopherson }
1019cb6a32c2SSean Christopherson 
10202fcf4876SMaxim Levitsky int svm_allocate_nested(struct vcpu_svm *svm)
10212fcf4876SMaxim Levitsky {
10224995a368SCathy Avery 	struct page *vmcb02_page;
10232fcf4876SMaxim Levitsky 
10242fcf4876SMaxim Levitsky 	if (svm->nested.initialized)
10252fcf4876SMaxim Levitsky 		return 0;
10262fcf4876SMaxim Levitsky 
10274995a368SCathy Avery 	vmcb02_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
10284995a368SCathy Avery 	if (!vmcb02_page)
10292fcf4876SMaxim Levitsky 		return -ENOMEM;
10304995a368SCathy Avery 	svm->nested.vmcb02.ptr = page_address(vmcb02_page);
10314995a368SCathy Avery 	svm->nested.vmcb02.pa = __sme_set(page_to_pfn(vmcb02_page) << PAGE_SHIFT);
10322fcf4876SMaxim Levitsky 
10332fcf4876SMaxim Levitsky 	svm->nested.msrpm = svm_vcpu_alloc_msrpm();
10342fcf4876SMaxim Levitsky 	if (!svm->nested.msrpm)
10354995a368SCathy Avery 		goto err_free_vmcb02;
10362fcf4876SMaxim Levitsky 	svm_vcpu_init_msrpm(&svm->vcpu, svm->nested.msrpm);
10372fcf4876SMaxim Levitsky 
10382fcf4876SMaxim Levitsky 	svm->nested.initialized = true;
10392fcf4876SMaxim Levitsky 	return 0;
10402fcf4876SMaxim Levitsky 
10414995a368SCathy Avery err_free_vmcb02:
10424995a368SCathy Avery 	__free_page(vmcb02_page);
10432fcf4876SMaxim Levitsky 	return -ENOMEM;
10442fcf4876SMaxim Levitsky }
10452fcf4876SMaxim Levitsky 
10462fcf4876SMaxim Levitsky void svm_free_nested(struct vcpu_svm *svm)
10472fcf4876SMaxim Levitsky {
10482fcf4876SMaxim Levitsky 	if (!svm->nested.initialized)
10492fcf4876SMaxim Levitsky 		return;
10502fcf4876SMaxim Levitsky 
10512fcf4876SMaxim Levitsky 	svm_vcpu_free_msrpm(svm->nested.msrpm);
10522fcf4876SMaxim Levitsky 	svm->nested.msrpm = NULL;
10532fcf4876SMaxim Levitsky 
10544995a368SCathy Avery 	__free_page(virt_to_page(svm->nested.vmcb02.ptr));
10554995a368SCathy Avery 	svm->nested.vmcb02.ptr = NULL;
10562fcf4876SMaxim Levitsky 
1057c74ad08fSMaxim Levitsky 	/*
1058c74ad08fSMaxim Levitsky 	 * When last_vmcb12_gpa matches the current vmcb12 gpa,
1059c74ad08fSMaxim Levitsky 	 * some vmcb12 fields are not loaded if they are marked clean
1060c74ad08fSMaxim Levitsky 	 * in the vmcb12, since in this case they are up to date already.
1061c74ad08fSMaxim Levitsky 	 *
1062c74ad08fSMaxim Levitsky 	 * When the vmcb02 is freed, this optimization becomes invalid.
1063c74ad08fSMaxim Levitsky 	 */
1064c74ad08fSMaxim Levitsky 	svm->nested.last_vmcb12_gpa = INVALID_GPA;
1065c74ad08fSMaxim Levitsky 
10662fcf4876SMaxim Levitsky 	svm->nested.initialized = false;
10672fcf4876SMaxim Levitsky }
10682fcf4876SMaxim Levitsky 
1069c513f484SPaolo Bonzini /*
1070c513f484SPaolo Bonzini  * Forcibly leave nested mode in order to be able to reset the VCPU later on.
1071c513f484SPaolo Bonzini  */
1072f7e57078SSean Christopherson void svm_leave_nested(struct kvm_vcpu *vcpu)
1073c513f484SPaolo Bonzini {
1074f7e57078SSean Christopherson 	struct vcpu_svm *svm = to_svm(vcpu);
107563129754SPaolo Bonzini 
107663129754SPaolo Bonzini 	if (is_guest_mode(vcpu)) {
1077c513f484SPaolo Bonzini 		svm->nested.nested_run_pending = 0;
1078c74ad08fSMaxim Levitsky 		svm->nested.vmcb12_gpa = INVALID_GPA;
1079c74ad08fSMaxim Levitsky 
108063129754SPaolo Bonzini 		leave_guest_mode(vcpu);
10814995a368SCathy Avery 
1082deee59baSMaxim Levitsky 		svm_switch_vmcb(svm, &svm->vmcb01);
10834995a368SCathy Avery 
108463129754SPaolo Bonzini 		nested_svm_uninit_mmu_context(vcpu);
108556fe28deSMaxim Levitsky 		vmcb_mark_all_dirty(svm->vmcb);
1086c513f484SPaolo Bonzini 	}
1087a7d5c7ceSPaolo Bonzini 
108863129754SPaolo Bonzini 	kvm_clear_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu);
1089c513f484SPaolo Bonzini }
1090c513f484SPaolo Bonzini 
1091883b0a91SJoerg Roedel static int nested_svm_exit_handled_msr(struct vcpu_svm *svm)
1092883b0a91SJoerg Roedel {
1093883b0a91SJoerg Roedel 	u32 offset, msr, value;
1094883b0a91SJoerg Roedel 	int write, mask;
1095883b0a91SJoerg Roedel 
10968fc78909SEmanuele Giuseppe Esposito 	if (!(vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_MSR_PROT)))
1097883b0a91SJoerg Roedel 		return NESTED_EXIT_HOST;
1098883b0a91SJoerg Roedel 
1099883b0a91SJoerg Roedel 	msr    = svm->vcpu.arch.regs[VCPU_REGS_RCX];
1100883b0a91SJoerg Roedel 	offset = svm_msrpm_offset(msr);
1101883b0a91SJoerg Roedel 	write  = svm->vmcb->control.exit_info_1 & 1;
1102883b0a91SJoerg Roedel 	mask   = 1 << ((2 * (msr & 0xf)) + write);
1103883b0a91SJoerg Roedel 
1104883b0a91SJoerg Roedel 	if (offset == MSR_INVALID)
1105883b0a91SJoerg Roedel 		return NESTED_EXIT_DONE;
1106883b0a91SJoerg Roedel 
1107883b0a91SJoerg Roedel 	/* Offset is in 32 bit units but need in 8 bit units */
1108883b0a91SJoerg Roedel 	offset *= 4;
1109883b0a91SJoerg Roedel 
1110e670bf68SPaolo Bonzini 	if (kvm_vcpu_read_guest(&svm->vcpu, svm->nested.ctl.msrpm_base_pa + offset, &value, 4))
1111883b0a91SJoerg Roedel 		return NESTED_EXIT_DONE;
1112883b0a91SJoerg Roedel 
1113883b0a91SJoerg Roedel 	return (value & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
1114883b0a91SJoerg Roedel }
1115883b0a91SJoerg Roedel 
1116883b0a91SJoerg Roedel static int nested_svm_intercept_ioio(struct vcpu_svm *svm)
1117883b0a91SJoerg Roedel {
1118883b0a91SJoerg Roedel 	unsigned port, size, iopm_len;
1119883b0a91SJoerg Roedel 	u16 val, mask;
1120883b0a91SJoerg Roedel 	u8 start_bit;
1121883b0a91SJoerg Roedel 	u64 gpa;
1122883b0a91SJoerg Roedel 
11238fc78909SEmanuele Giuseppe Esposito 	if (!(vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_IOIO_PROT)))
1124883b0a91SJoerg Roedel 		return NESTED_EXIT_HOST;
1125883b0a91SJoerg Roedel 
1126883b0a91SJoerg Roedel 	port = svm->vmcb->control.exit_info_1 >> 16;
1127883b0a91SJoerg Roedel 	size = (svm->vmcb->control.exit_info_1 & SVM_IOIO_SIZE_MASK) >>
1128883b0a91SJoerg Roedel 		SVM_IOIO_SIZE_SHIFT;
1129e670bf68SPaolo Bonzini 	gpa  = svm->nested.ctl.iopm_base_pa + (port / 8);
1130883b0a91SJoerg Roedel 	start_bit = port % 8;
1131883b0a91SJoerg Roedel 	iopm_len = (start_bit + size > 8) ? 2 : 1;
1132883b0a91SJoerg Roedel 	mask = (0xf >> (4 - size)) << start_bit;
1133883b0a91SJoerg Roedel 	val = 0;
1134883b0a91SJoerg Roedel 
1135883b0a91SJoerg Roedel 	if (kvm_vcpu_read_guest(&svm->vcpu, gpa, &val, iopm_len))
1136883b0a91SJoerg Roedel 		return NESTED_EXIT_DONE;
1137883b0a91SJoerg Roedel 
1138883b0a91SJoerg Roedel 	return (val & mask) ? NESTED_EXIT_DONE : NESTED_EXIT_HOST;
1139883b0a91SJoerg Roedel }
1140883b0a91SJoerg Roedel 
1141883b0a91SJoerg Roedel static int nested_svm_intercept(struct vcpu_svm *svm)
1142883b0a91SJoerg Roedel {
1143883b0a91SJoerg Roedel 	u32 exit_code = svm->vmcb->control.exit_code;
1144883b0a91SJoerg Roedel 	int vmexit = NESTED_EXIT_HOST;
1145883b0a91SJoerg Roedel 
1146883b0a91SJoerg Roedel 	switch (exit_code) {
1147883b0a91SJoerg Roedel 	case SVM_EXIT_MSR:
1148883b0a91SJoerg Roedel 		vmexit = nested_svm_exit_handled_msr(svm);
1149883b0a91SJoerg Roedel 		break;
1150883b0a91SJoerg Roedel 	case SVM_EXIT_IOIO:
1151883b0a91SJoerg Roedel 		vmexit = nested_svm_intercept_ioio(svm);
1152883b0a91SJoerg Roedel 		break;
1153883b0a91SJoerg Roedel 	case SVM_EXIT_READ_CR0 ... SVM_EXIT_WRITE_CR8: {
11548fc78909SEmanuele Giuseppe Esposito 		if (vmcb12_is_intercept(&svm->nested.ctl, exit_code))
1155883b0a91SJoerg Roedel 			vmexit = NESTED_EXIT_DONE;
1156883b0a91SJoerg Roedel 		break;
1157883b0a91SJoerg Roedel 	}
1158883b0a91SJoerg Roedel 	case SVM_EXIT_READ_DR0 ... SVM_EXIT_WRITE_DR7: {
11598fc78909SEmanuele Giuseppe Esposito 		if (vmcb12_is_intercept(&svm->nested.ctl, exit_code))
1160883b0a91SJoerg Roedel 			vmexit = NESTED_EXIT_DONE;
1161883b0a91SJoerg Roedel 		break;
1162883b0a91SJoerg Roedel 	}
1163883b0a91SJoerg Roedel 	case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: {
11647c86663bSPaolo Bonzini 		/*
11657c86663bSPaolo Bonzini 		 * Host-intercepted exceptions have been checked already in
11667c86663bSPaolo Bonzini 		 * nested_svm_exit_special.  There is nothing to do here,
11677c86663bSPaolo Bonzini 		 * the vmexit is injected by svm_check_nested_events.
11687c86663bSPaolo Bonzini 		 */
1169883b0a91SJoerg Roedel 		vmexit = NESTED_EXIT_DONE;
1170883b0a91SJoerg Roedel 		break;
1171883b0a91SJoerg Roedel 	}
1172883b0a91SJoerg Roedel 	case SVM_EXIT_ERR: {
1173883b0a91SJoerg Roedel 		vmexit = NESTED_EXIT_DONE;
1174883b0a91SJoerg Roedel 		break;
1175883b0a91SJoerg Roedel 	}
1176883b0a91SJoerg Roedel 	default: {
11778fc78909SEmanuele Giuseppe Esposito 		if (vmcb12_is_intercept(&svm->nested.ctl, exit_code))
1178883b0a91SJoerg Roedel 			vmexit = NESTED_EXIT_DONE;
1179883b0a91SJoerg Roedel 	}
1180883b0a91SJoerg Roedel 	}
1181883b0a91SJoerg Roedel 
1182883b0a91SJoerg Roedel 	return vmexit;
1183883b0a91SJoerg Roedel }
1184883b0a91SJoerg Roedel 
1185883b0a91SJoerg Roedel int nested_svm_exit_handled(struct vcpu_svm *svm)
1186883b0a91SJoerg Roedel {
1187883b0a91SJoerg Roedel 	int vmexit;
1188883b0a91SJoerg Roedel 
1189883b0a91SJoerg Roedel 	vmexit = nested_svm_intercept(svm);
1190883b0a91SJoerg Roedel 
1191883b0a91SJoerg Roedel 	if (vmexit == NESTED_EXIT_DONE)
1192883b0a91SJoerg Roedel 		nested_svm_vmexit(svm);
1193883b0a91SJoerg Roedel 
1194883b0a91SJoerg Roedel 	return vmexit;
1195883b0a91SJoerg Roedel }
1196883b0a91SJoerg Roedel 
119763129754SPaolo Bonzini int nested_svm_check_permissions(struct kvm_vcpu *vcpu)
1198883b0a91SJoerg Roedel {
119963129754SPaolo Bonzini 	if (!(vcpu->arch.efer & EFER_SVME) || !is_paging(vcpu)) {
120063129754SPaolo Bonzini 		kvm_queue_exception(vcpu, UD_VECTOR);
1201883b0a91SJoerg Roedel 		return 1;
1202883b0a91SJoerg Roedel 	}
1203883b0a91SJoerg Roedel 
120463129754SPaolo Bonzini 	if (to_svm(vcpu)->vmcb->save.cpl) {
120563129754SPaolo Bonzini 		kvm_inject_gp(vcpu, 0);
1206883b0a91SJoerg Roedel 		return 1;
1207883b0a91SJoerg Roedel 	}
1208883b0a91SJoerg Roedel 
1209883b0a91SJoerg Roedel 	return 0;
1210883b0a91SJoerg Roedel }
1211883b0a91SJoerg Roedel 
12127c86663bSPaolo Bonzini static bool nested_exit_on_exception(struct vcpu_svm *svm)
1213883b0a91SJoerg Roedel {
12147c86663bSPaolo Bonzini 	unsigned int nr = svm->vcpu.arch.exception.nr;
1215883b0a91SJoerg Roedel 
12169780d51dSBabu Moger 	return (svm->nested.ctl.intercepts[INTERCEPT_EXCEPTION] & BIT(nr));
12177c86663bSPaolo Bonzini }
1218883b0a91SJoerg Roedel 
12197c86663bSPaolo Bonzini static void nested_svm_inject_exception_vmexit(struct vcpu_svm *svm)
12207c86663bSPaolo Bonzini {
12217c86663bSPaolo Bonzini 	unsigned int nr = svm->vcpu.arch.exception.nr;
1222db663af4SMaxim Levitsky 	struct vmcb *vmcb = svm->vmcb;
1223883b0a91SJoerg Roedel 
1224db663af4SMaxim Levitsky 	vmcb->control.exit_code = SVM_EXIT_EXCP_BASE + nr;
1225db663af4SMaxim Levitsky 	vmcb->control.exit_code_hi = 0;
12267c86663bSPaolo Bonzini 
12277c86663bSPaolo Bonzini 	if (svm->vcpu.arch.exception.has_error_code)
1228db663af4SMaxim Levitsky 		vmcb->control.exit_info_1 = svm->vcpu.arch.exception.error_code;
1229883b0a91SJoerg Roedel 
1230883b0a91SJoerg Roedel 	/*
1231883b0a91SJoerg Roedel 	 * EXITINFO2 is undefined for all exception intercepts other
1232883b0a91SJoerg Roedel 	 * than #PF.
1233883b0a91SJoerg Roedel 	 */
12347c86663bSPaolo Bonzini 	if (nr == PF_VECTOR) {
1235883b0a91SJoerg Roedel 		if (svm->vcpu.arch.exception.nested_apf)
1236db663af4SMaxim Levitsky 			vmcb->control.exit_info_2 = svm->vcpu.arch.apf.nested_apf_token;
1237883b0a91SJoerg Roedel 		else if (svm->vcpu.arch.exception.has_payload)
1238db663af4SMaxim Levitsky 			vmcb->control.exit_info_2 = svm->vcpu.arch.exception.payload;
1239883b0a91SJoerg Roedel 		else
1240db663af4SMaxim Levitsky 			vmcb->control.exit_info_2 = svm->vcpu.arch.cr2;
12417c86663bSPaolo Bonzini 	} else if (nr == DB_VECTOR) {
12427c86663bSPaolo Bonzini 		/* See inject_pending_event.  */
12437c86663bSPaolo Bonzini 		kvm_deliver_exception_payload(&svm->vcpu);
12447c86663bSPaolo Bonzini 		if (svm->vcpu.arch.dr7 & DR7_GD) {
12457c86663bSPaolo Bonzini 			svm->vcpu.arch.dr7 &= ~DR7_GD;
12467c86663bSPaolo Bonzini 			kvm_update_dr7(&svm->vcpu);
12477c86663bSPaolo Bonzini 		}
12487c86663bSPaolo Bonzini 	} else
12497c86663bSPaolo Bonzini 		WARN_ON(svm->vcpu.arch.exception.has_payload);
1250883b0a91SJoerg Roedel 
12517c86663bSPaolo Bonzini 	nested_svm_vmexit(svm);
1252883b0a91SJoerg Roedel }
1253883b0a91SJoerg Roedel 
12545b672408SPaolo Bonzini static inline bool nested_exit_on_init(struct vcpu_svm *svm)
12555b672408SPaolo Bonzini {
12568fc78909SEmanuele Giuseppe Esposito 	return vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_INIT);
12575b672408SPaolo Bonzini }
12585b672408SPaolo Bonzini 
125933b22172SPaolo Bonzini static int svm_check_nested_events(struct kvm_vcpu *vcpu)
1260883b0a91SJoerg Roedel {
1261883b0a91SJoerg Roedel 	struct vcpu_svm *svm = to_svm(vcpu);
1262883b0a91SJoerg Roedel 	bool block_nested_events =
1263bd279629SPaolo Bonzini 		kvm_event_needs_reinjection(vcpu) || svm->nested.nested_run_pending;
12645b672408SPaolo Bonzini 	struct kvm_lapic *apic = vcpu->arch.apic;
12655b672408SPaolo Bonzini 
12665b672408SPaolo Bonzini 	if (lapic_in_kernel(vcpu) &&
12675b672408SPaolo Bonzini 	    test_bit(KVM_APIC_INIT, &apic->pending_events)) {
12685b672408SPaolo Bonzini 		if (block_nested_events)
12695b672408SPaolo Bonzini 			return -EBUSY;
12705b672408SPaolo Bonzini 		if (!nested_exit_on_init(svm))
12715b672408SPaolo Bonzini 			return 0;
12723a87c7e0SSean Christopherson 		nested_svm_simple_vmexit(svm, SVM_EXIT_INIT);
12735b672408SPaolo Bonzini 		return 0;
12745b672408SPaolo Bonzini 	}
1275883b0a91SJoerg Roedel 
12767c86663bSPaolo Bonzini 	if (vcpu->arch.exception.pending) {
12774020da3bSMaxim Levitsky 		/*
12784020da3bSMaxim Levitsky 		 * Only a pending nested run can block a pending exception.
12794020da3bSMaxim Levitsky 		 * Otherwise an injected NMI/interrupt should either be
12804020da3bSMaxim Levitsky 		 * lost or delivered to the nested hypervisor in the EXITINTINFO
12814020da3bSMaxim Levitsky 		 * vmcb field, while delivering the pending exception.
12824020da3bSMaxim Levitsky 		 */
12834020da3bSMaxim Levitsky 		if (svm->nested.nested_run_pending)
12847c86663bSPaolo Bonzini                         return -EBUSY;
12857c86663bSPaolo Bonzini 		if (!nested_exit_on_exception(svm))
12867c86663bSPaolo Bonzini 			return 0;
12877c86663bSPaolo Bonzini 		nested_svm_inject_exception_vmexit(svm);
12887c86663bSPaolo Bonzini 		return 0;
12897c86663bSPaolo Bonzini 	}
12907c86663bSPaolo Bonzini 
1291221e7610SPaolo Bonzini 	if (vcpu->arch.smi_pending && !svm_smi_blocked(vcpu)) {
129255714cddSPaolo Bonzini 		if (block_nested_events)
129355714cddSPaolo Bonzini 			return -EBUSY;
1294221e7610SPaolo Bonzini 		if (!nested_exit_on_smi(svm))
1295221e7610SPaolo Bonzini 			return 0;
12963a87c7e0SSean Christopherson 		nested_svm_simple_vmexit(svm, SVM_EXIT_SMI);
129755714cddSPaolo Bonzini 		return 0;
129855714cddSPaolo Bonzini 	}
129955714cddSPaolo Bonzini 
1300221e7610SPaolo Bonzini 	if (vcpu->arch.nmi_pending && !svm_nmi_blocked(vcpu)) {
13019c3d370aSCathy Avery 		if (block_nested_events)
13029c3d370aSCathy Avery 			return -EBUSY;
1303221e7610SPaolo Bonzini 		if (!nested_exit_on_nmi(svm))
1304221e7610SPaolo Bonzini 			return 0;
13053a87c7e0SSean Christopherson 		nested_svm_simple_vmexit(svm, SVM_EXIT_NMI);
13069c3d370aSCathy Avery 		return 0;
13079c3d370aSCathy Avery 	}
13089c3d370aSCathy Avery 
1309221e7610SPaolo Bonzini 	if (kvm_cpu_has_interrupt(vcpu) && !svm_interrupt_blocked(vcpu)) {
1310883b0a91SJoerg Roedel 		if (block_nested_events)
1311883b0a91SJoerg Roedel 			return -EBUSY;
1312221e7610SPaolo Bonzini 		if (!nested_exit_on_intr(svm))
1313221e7610SPaolo Bonzini 			return 0;
13143a87c7e0SSean Christopherson 		trace_kvm_nested_intr_vmexit(svm->vmcb->save.rip);
13153a87c7e0SSean Christopherson 		nested_svm_simple_vmexit(svm, SVM_EXIT_INTR);
1316883b0a91SJoerg Roedel 		return 0;
1317883b0a91SJoerg Roedel 	}
1318883b0a91SJoerg Roedel 
1319883b0a91SJoerg Roedel 	return 0;
1320883b0a91SJoerg Roedel }
1321883b0a91SJoerg Roedel 
1322883b0a91SJoerg Roedel int nested_svm_exit_special(struct vcpu_svm *svm)
1323883b0a91SJoerg Roedel {
1324883b0a91SJoerg Roedel 	u32 exit_code = svm->vmcb->control.exit_code;
1325883b0a91SJoerg Roedel 
1326883b0a91SJoerg Roedel 	switch (exit_code) {
1327883b0a91SJoerg Roedel 	case SVM_EXIT_INTR:
1328883b0a91SJoerg Roedel 	case SVM_EXIT_NMI:
1329883b0a91SJoerg Roedel 	case SVM_EXIT_NPF:
1330883b0a91SJoerg Roedel 		return NESTED_EXIT_HOST;
13317c86663bSPaolo Bonzini 	case SVM_EXIT_EXCP_BASE ... SVM_EXIT_EXCP_BASE + 0x1f: {
13327c86663bSPaolo Bonzini 		u32 excp_bits = 1 << (exit_code - SVM_EXIT_EXCP_BASE);
13337c86663bSPaolo Bonzini 
13344995a368SCathy Avery 		if (svm->vmcb01.ptr->control.intercepts[INTERCEPT_EXCEPTION] &
13359780d51dSBabu Moger 		    excp_bits)
13367c86663bSPaolo Bonzini 			return NESTED_EXIT_HOST;
13377c86663bSPaolo Bonzini 		else if (exit_code == SVM_EXIT_EXCP_BASE + PF_VECTOR &&
133868fd66f1SVitaly Kuznetsov 			 svm->vcpu.arch.apf.host_apf_flags)
1339a3535be7SPaolo Bonzini 			/* Trap async PF even if not shadowing */
1340883b0a91SJoerg Roedel 			return NESTED_EXIT_HOST;
1341883b0a91SJoerg Roedel 		break;
13427c86663bSPaolo Bonzini 	}
1343883b0a91SJoerg Roedel 	default:
1344883b0a91SJoerg Roedel 		break;
1345883b0a91SJoerg Roedel 	}
1346883b0a91SJoerg Roedel 
1347883b0a91SJoerg Roedel 	return NESTED_EXIT_CONTINUE;
1348883b0a91SJoerg Roedel }
134933b22172SPaolo Bonzini 
13505228eb96SMaxim Levitsky void nested_svm_update_tsc_ratio_msr(struct kvm_vcpu *vcpu)
13515228eb96SMaxim Levitsky {
13525228eb96SMaxim Levitsky 	struct vcpu_svm *svm = to_svm(vcpu);
13535228eb96SMaxim Levitsky 
13545228eb96SMaxim Levitsky 	vcpu->arch.tsc_scaling_ratio =
13555228eb96SMaxim Levitsky 		kvm_calc_nested_tsc_multiplier(vcpu->arch.l1_tsc_scaling_ratio,
13565228eb96SMaxim Levitsky 					       svm->tsc_ratio_msr);
13575228eb96SMaxim Levitsky 	svm_write_tsc_multiplier(vcpu, vcpu->arch.tsc_scaling_ratio);
13585228eb96SMaxim Levitsky }
13595228eb96SMaxim Levitsky 
13608fc78909SEmanuele Giuseppe Esposito /* Inverse operation of nested_copy_vmcb_control_to_cache(). asid is copied too. */
13618fc78909SEmanuele Giuseppe Esposito static void nested_copy_vmcb_cache_to_control(struct vmcb_control_area *dst,
13628fc78909SEmanuele Giuseppe Esposito 					      struct vmcb_ctrl_area_cached *from)
13638fc78909SEmanuele Giuseppe Esposito {
13648fc78909SEmanuele Giuseppe Esposito 	unsigned int i;
13658fc78909SEmanuele Giuseppe Esposito 
13668fc78909SEmanuele Giuseppe Esposito 	memset(dst, 0, sizeof(struct vmcb_control_area));
13678fc78909SEmanuele Giuseppe Esposito 
13688fc78909SEmanuele Giuseppe Esposito 	for (i = 0; i < MAX_INTERCEPT; i++)
13698fc78909SEmanuele Giuseppe Esposito 		dst->intercepts[i] = from->intercepts[i];
13708fc78909SEmanuele Giuseppe Esposito 
13718fc78909SEmanuele Giuseppe Esposito 	dst->iopm_base_pa         = from->iopm_base_pa;
13728fc78909SEmanuele Giuseppe Esposito 	dst->msrpm_base_pa        = from->msrpm_base_pa;
13738fc78909SEmanuele Giuseppe Esposito 	dst->tsc_offset           = from->tsc_offset;
13748fc78909SEmanuele Giuseppe Esposito 	dst->asid                 = from->asid;
13758fc78909SEmanuele Giuseppe Esposito 	dst->tlb_ctl              = from->tlb_ctl;
13768fc78909SEmanuele Giuseppe Esposito 	dst->int_ctl              = from->int_ctl;
13778fc78909SEmanuele Giuseppe Esposito 	dst->int_vector           = from->int_vector;
13788fc78909SEmanuele Giuseppe Esposito 	dst->int_state            = from->int_state;
13798fc78909SEmanuele Giuseppe Esposito 	dst->exit_code            = from->exit_code;
13808fc78909SEmanuele Giuseppe Esposito 	dst->exit_code_hi         = from->exit_code_hi;
13818fc78909SEmanuele Giuseppe Esposito 	dst->exit_info_1          = from->exit_info_1;
13828fc78909SEmanuele Giuseppe Esposito 	dst->exit_info_2          = from->exit_info_2;
13838fc78909SEmanuele Giuseppe Esposito 	dst->exit_int_info        = from->exit_int_info;
13848fc78909SEmanuele Giuseppe Esposito 	dst->exit_int_info_err    = from->exit_int_info_err;
13858fc78909SEmanuele Giuseppe Esposito 	dst->nested_ctl           = from->nested_ctl;
13868fc78909SEmanuele Giuseppe Esposito 	dst->event_inj            = from->event_inj;
13878fc78909SEmanuele Giuseppe Esposito 	dst->event_inj_err        = from->event_inj_err;
13888fc78909SEmanuele Giuseppe Esposito 	dst->nested_cr3           = from->nested_cr3;
13898fc78909SEmanuele Giuseppe Esposito 	dst->virt_ext              = from->virt_ext;
13908fc78909SEmanuele Giuseppe Esposito 	dst->pause_filter_count   = from->pause_filter_count;
13918fc78909SEmanuele Giuseppe Esposito 	dst->pause_filter_thresh  = from->pause_filter_thresh;
139266c03a92SVitaly Kuznetsov 	/* 'clean' and 'reserved_sw' are not changed by KVM */
13938fc78909SEmanuele Giuseppe Esposito }
13948fc78909SEmanuele Giuseppe Esposito 
1395cc440cdaSPaolo Bonzini static int svm_get_nested_state(struct kvm_vcpu *vcpu,
1396cc440cdaSPaolo Bonzini 				struct kvm_nested_state __user *user_kvm_nested_state,
1397cc440cdaSPaolo Bonzini 				u32 user_data_size)
1398cc440cdaSPaolo Bonzini {
1399cc440cdaSPaolo Bonzini 	struct vcpu_svm *svm;
14008fc78909SEmanuele Giuseppe Esposito 	struct vmcb_control_area *ctl;
14018fc78909SEmanuele Giuseppe Esposito 	unsigned long r;
1402cc440cdaSPaolo Bonzini 	struct kvm_nested_state kvm_state = {
1403cc440cdaSPaolo Bonzini 		.flags = 0,
1404cc440cdaSPaolo Bonzini 		.format = KVM_STATE_NESTED_FORMAT_SVM,
1405cc440cdaSPaolo Bonzini 		.size = sizeof(kvm_state),
1406cc440cdaSPaolo Bonzini 	};
1407cc440cdaSPaolo Bonzini 	struct vmcb __user *user_vmcb = (struct vmcb __user *)
1408cc440cdaSPaolo Bonzini 		&user_kvm_nested_state->data.svm[0];
1409cc440cdaSPaolo Bonzini 
1410cc440cdaSPaolo Bonzini 	if (!vcpu)
1411cc440cdaSPaolo Bonzini 		return kvm_state.size + KVM_STATE_NESTED_SVM_VMCB_SIZE;
1412cc440cdaSPaolo Bonzini 
1413cc440cdaSPaolo Bonzini 	svm = to_svm(vcpu);
1414cc440cdaSPaolo Bonzini 
1415cc440cdaSPaolo Bonzini 	if (user_data_size < kvm_state.size)
1416cc440cdaSPaolo Bonzini 		goto out;
1417cc440cdaSPaolo Bonzini 
1418cc440cdaSPaolo Bonzini 	/* First fill in the header and copy it out.  */
1419cc440cdaSPaolo Bonzini 	if (is_guest_mode(vcpu)) {
14200dd16b5bSMaxim Levitsky 		kvm_state.hdr.svm.vmcb_pa = svm->nested.vmcb12_gpa;
1421cc440cdaSPaolo Bonzini 		kvm_state.size += KVM_STATE_NESTED_SVM_VMCB_SIZE;
1422cc440cdaSPaolo Bonzini 		kvm_state.flags |= KVM_STATE_NESTED_GUEST_MODE;
1423cc440cdaSPaolo Bonzini 
1424cc440cdaSPaolo Bonzini 		if (svm->nested.nested_run_pending)
1425cc440cdaSPaolo Bonzini 			kvm_state.flags |= KVM_STATE_NESTED_RUN_PENDING;
1426cc440cdaSPaolo Bonzini 	}
1427cc440cdaSPaolo Bonzini 
1428cc440cdaSPaolo Bonzini 	if (gif_set(svm))
1429cc440cdaSPaolo Bonzini 		kvm_state.flags |= KVM_STATE_NESTED_GIF_SET;
1430cc440cdaSPaolo Bonzini 
1431cc440cdaSPaolo Bonzini 	if (copy_to_user(user_kvm_nested_state, &kvm_state, sizeof(kvm_state)))
1432cc440cdaSPaolo Bonzini 		return -EFAULT;
1433cc440cdaSPaolo Bonzini 
1434cc440cdaSPaolo Bonzini 	if (!is_guest_mode(vcpu))
1435cc440cdaSPaolo Bonzini 		goto out;
1436cc440cdaSPaolo Bonzini 
1437cc440cdaSPaolo Bonzini 	/*
1438cc440cdaSPaolo Bonzini 	 * Copy over the full size of the VMCB rather than just the size
1439cc440cdaSPaolo Bonzini 	 * of the structs.
1440cc440cdaSPaolo Bonzini 	 */
1441cc440cdaSPaolo Bonzini 	if (clear_user(user_vmcb, KVM_STATE_NESTED_SVM_VMCB_SIZE))
1442cc440cdaSPaolo Bonzini 		return -EFAULT;
14438fc78909SEmanuele Giuseppe Esposito 
14448fc78909SEmanuele Giuseppe Esposito 	ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
14458fc78909SEmanuele Giuseppe Esposito 	if (!ctl)
14468fc78909SEmanuele Giuseppe Esposito 		return -ENOMEM;
14478fc78909SEmanuele Giuseppe Esposito 
14488fc78909SEmanuele Giuseppe Esposito 	nested_copy_vmcb_cache_to_control(ctl, &svm->nested.ctl);
14498fc78909SEmanuele Giuseppe Esposito 	r = copy_to_user(&user_vmcb->control, ctl,
14508fc78909SEmanuele Giuseppe Esposito 			 sizeof(user_vmcb->control));
14518fc78909SEmanuele Giuseppe Esposito 	kfree(ctl);
14528fc78909SEmanuele Giuseppe Esposito 	if (r)
1453cc440cdaSPaolo Bonzini 		return -EFAULT;
14548fc78909SEmanuele Giuseppe Esposito 
14554995a368SCathy Avery 	if (copy_to_user(&user_vmcb->save, &svm->vmcb01.ptr->save,
1456cc440cdaSPaolo Bonzini 			 sizeof(user_vmcb->save)))
1457cc440cdaSPaolo Bonzini 		return -EFAULT;
1458cc440cdaSPaolo Bonzini out:
1459cc440cdaSPaolo Bonzini 	return kvm_state.size;
1460cc440cdaSPaolo Bonzini }
1461cc440cdaSPaolo Bonzini 
1462cc440cdaSPaolo Bonzini static int svm_set_nested_state(struct kvm_vcpu *vcpu,
1463cc440cdaSPaolo Bonzini 				struct kvm_nested_state __user *user_kvm_nested_state,
1464cc440cdaSPaolo Bonzini 				struct kvm_nested_state *kvm_state)
1465cc440cdaSPaolo Bonzini {
1466cc440cdaSPaolo Bonzini 	struct vcpu_svm *svm = to_svm(vcpu);
1467cc440cdaSPaolo Bonzini 	struct vmcb __user *user_vmcb = (struct vmcb __user *)
1468cc440cdaSPaolo Bonzini 		&user_kvm_nested_state->data.svm[0];
14696ccbd29aSJoerg Roedel 	struct vmcb_control_area *ctl;
14706ccbd29aSJoerg Roedel 	struct vmcb_save_area *save;
1471b7a3d8b6SEmanuele Giuseppe Esposito 	struct vmcb_save_area_cached save_cached;
14728fc78909SEmanuele Giuseppe Esposito 	struct vmcb_ctrl_area_cached ctl_cached;
1473dbc4739bSSean Christopherson 	unsigned long cr0;
14746ccbd29aSJoerg Roedel 	int ret;
1475cc440cdaSPaolo Bonzini 
14766ccbd29aSJoerg Roedel 	BUILD_BUG_ON(sizeof(struct vmcb_control_area) + sizeof(struct vmcb_save_area) >
14776ccbd29aSJoerg Roedel 		     KVM_STATE_NESTED_SVM_VMCB_SIZE);
14786ccbd29aSJoerg Roedel 
1479cc440cdaSPaolo Bonzini 	if (kvm_state->format != KVM_STATE_NESTED_FORMAT_SVM)
1480cc440cdaSPaolo Bonzini 		return -EINVAL;
1481cc440cdaSPaolo Bonzini 
1482cc440cdaSPaolo Bonzini 	if (kvm_state->flags & ~(KVM_STATE_NESTED_GUEST_MODE |
1483cc440cdaSPaolo Bonzini 				 KVM_STATE_NESTED_RUN_PENDING |
1484cc440cdaSPaolo Bonzini 				 KVM_STATE_NESTED_GIF_SET))
1485cc440cdaSPaolo Bonzini 		return -EINVAL;
1486cc440cdaSPaolo Bonzini 
1487cc440cdaSPaolo Bonzini 	/*
1488cc440cdaSPaolo Bonzini 	 * If in guest mode, vcpu->arch.efer actually refers to the L2 guest's
1489cc440cdaSPaolo Bonzini 	 * EFER.SVME, but EFER.SVME still has to be 1 for VMRUN to succeed.
1490cc440cdaSPaolo Bonzini 	 */
1491cc440cdaSPaolo Bonzini 	if (!(vcpu->arch.efer & EFER_SVME)) {
1492cc440cdaSPaolo Bonzini 		/* GIF=1 and no guest mode are required if SVME=0.  */
1493cc440cdaSPaolo Bonzini 		if (kvm_state->flags != KVM_STATE_NESTED_GIF_SET)
1494cc440cdaSPaolo Bonzini 			return -EINVAL;
1495cc440cdaSPaolo Bonzini 	}
1496cc440cdaSPaolo Bonzini 
1497cc440cdaSPaolo Bonzini 	/* SMM temporarily disables SVM, so we cannot be in guest mode.  */
1498cc440cdaSPaolo Bonzini 	if (is_smm(vcpu) && (kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE))
1499cc440cdaSPaolo Bonzini 		return -EINVAL;
1500cc440cdaSPaolo Bonzini 
1501cc440cdaSPaolo Bonzini 	if (!(kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE)) {
1502f7e57078SSean Christopherson 		svm_leave_nested(vcpu);
1503d5cd6f34SVitaly Kuznetsov 		svm_set_gif(svm, !!(kvm_state->flags & KVM_STATE_NESTED_GIF_SET));
1504d5cd6f34SVitaly Kuznetsov 		return 0;
1505cc440cdaSPaolo Bonzini 	}
1506cc440cdaSPaolo Bonzini 
1507cc440cdaSPaolo Bonzini 	if (!page_address_valid(vcpu, kvm_state->hdr.svm.vmcb_pa))
1508cc440cdaSPaolo Bonzini 		return -EINVAL;
1509cc440cdaSPaolo Bonzini 	if (kvm_state->size < sizeof(*kvm_state) + KVM_STATE_NESTED_SVM_VMCB_SIZE)
1510cc440cdaSPaolo Bonzini 		return -EINVAL;
1511cc440cdaSPaolo Bonzini 
15126ccbd29aSJoerg Roedel 	ret  = -ENOMEM;
1513eba04b20SSean Christopherson 	ctl  = kzalloc(sizeof(*ctl),  GFP_KERNEL_ACCOUNT);
1514eba04b20SSean Christopherson 	save = kzalloc(sizeof(*save), GFP_KERNEL_ACCOUNT);
15156ccbd29aSJoerg Roedel 	if (!ctl || !save)
15166ccbd29aSJoerg Roedel 		goto out_free;
15176ccbd29aSJoerg Roedel 
15186ccbd29aSJoerg Roedel 	ret = -EFAULT;
15196ccbd29aSJoerg Roedel 	if (copy_from_user(ctl, &user_vmcb->control, sizeof(*ctl)))
15206ccbd29aSJoerg Roedel 		goto out_free;
15216ccbd29aSJoerg Roedel 	if (copy_from_user(save, &user_vmcb->save, sizeof(*save)))
15226ccbd29aSJoerg Roedel 		goto out_free;
15236ccbd29aSJoerg Roedel 
15246ccbd29aSJoerg Roedel 	ret = -EINVAL;
152566c03a92SVitaly Kuznetsov 	__nested_copy_vmcb_control_to_cache(vcpu, &ctl_cached, ctl);
15268fc78909SEmanuele Giuseppe Esposito 	if (!__nested_vmcb_check_controls(vcpu, &ctl_cached))
15276ccbd29aSJoerg Roedel 		goto out_free;
1528cc440cdaSPaolo Bonzini 
1529cc440cdaSPaolo Bonzini 	/*
1530cc440cdaSPaolo Bonzini 	 * Processor state contains L2 state.  Check that it is
1531cb9b6a1bSPaolo Bonzini 	 * valid for guest mode (see nested_vmcb_check_save).
1532cc440cdaSPaolo Bonzini 	 */
1533cc440cdaSPaolo Bonzini 	cr0 = kvm_read_cr0(vcpu);
1534cc440cdaSPaolo Bonzini         if (((cr0 & X86_CR0_CD) == 0) && (cr0 & X86_CR0_NW))
15356ccbd29aSJoerg Roedel 		goto out_free;
1536cc440cdaSPaolo Bonzini 
1537cc440cdaSPaolo Bonzini 	/*
1538cc440cdaSPaolo Bonzini 	 * Validate host state saved from before VMRUN (see
1539cc440cdaSPaolo Bonzini 	 * nested_svm_check_permissions).
1540cc440cdaSPaolo Bonzini 	 */
1541b7a3d8b6SEmanuele Giuseppe Esposito 	__nested_copy_vmcb_save_to_cache(&save_cached, save);
15426906e06dSKrish Sadhukhan 	if (!(save->cr0 & X86_CR0_PG) ||
15436906e06dSKrish Sadhukhan 	    !(save->cr0 & X86_CR0_PE) ||
15446906e06dSKrish Sadhukhan 	    (save->rflags & X86_EFLAGS_VM) ||
1545b7a3d8b6SEmanuele Giuseppe Esposito 	    !__nested_vmcb_check_save(vcpu, &save_cached))
15466ccbd29aSJoerg Roedel 		goto out_free;
1547cc440cdaSPaolo Bonzini 
1548b222b0b8SMaxim Levitsky 
1549b222b0b8SMaxim Levitsky 	/*
15504995a368SCathy Avery 	 * All checks done, we can enter guest mode. Userspace provides
15514995a368SCathy Avery 	 * vmcb12.control, which will be combined with L1 and stored into
15524995a368SCathy Avery 	 * vmcb02, and the L1 save state which we store in vmcb01.
15534995a368SCathy Avery 	 * L2 registers if needed are moved from the current VMCB to VMCB02.
1554cc440cdaSPaolo Bonzini 	 */
155581f76adaSMaxim Levitsky 
15569d290e16SMaxim Levitsky 	if (is_guest_mode(vcpu))
1557f7e57078SSean Christopherson 		svm_leave_nested(vcpu);
15589d290e16SMaxim Levitsky 	else
15599d290e16SMaxim Levitsky 		svm->nested.vmcb02.ptr->save = svm->vmcb01.ptr->save;
15609d290e16SMaxim Levitsky 
1561063ab16cSMaxim Levitsky 	svm_set_gif(svm, !!(kvm_state->flags & KVM_STATE_NESTED_GIF_SET));
1562063ab16cSMaxim Levitsky 
156381f76adaSMaxim Levitsky 	svm->nested.nested_run_pending =
156481f76adaSMaxim Levitsky 		!!(kvm_state->flags & KVM_STATE_NESTED_RUN_PENDING);
156581f76adaSMaxim Levitsky 
15660dd16b5bSMaxim Levitsky 	svm->nested.vmcb12_gpa = kvm_state->hdr.svm.vmcb_pa;
1567c08f390aSPaolo Bonzini 
15682bb16beaSVitaly Kuznetsov 	svm_copy_vmrun_state(&svm->vmcb01.ptr->save, save);
15697907160dSEmanuele Giuseppe Esposito 	nested_copy_vmcb_control_to_cache(svm, ctl);
15704995a368SCathy Avery 
15714995a368SCathy Avery 	svm_switch_vmcb(svm, &svm->nested.vmcb02);
15729e8f0fbfSPaolo Bonzini 	nested_vmcb02_prepare_control(svm);
1573e1779c27SMaxim Levitsky 
1574e1779c27SMaxim Levitsky 	/*
1575e1779c27SMaxim Levitsky 	 * While the nested guest CR3 is already checked and set by
1576e1779c27SMaxim Levitsky 	 * KVM_SET_SREGS, it was set when nested state was yet loaded,
1577e1779c27SMaxim Levitsky 	 * thus MMU might not be initialized correctly.
1578e1779c27SMaxim Levitsky 	 * Set it again to fix this.
1579e1779c27SMaxim Levitsky 	 */
1580e1779c27SMaxim Levitsky 
1581e1779c27SMaxim Levitsky 	ret = nested_svm_load_cr3(&svm->vcpu, vcpu->arch.cr3,
1582e1779c27SMaxim Levitsky 				  nested_npt_enabled(svm), false);
1583e1779c27SMaxim Levitsky 	if (WARN_ON_ONCE(ret))
1584e1779c27SMaxim Levitsky 		goto out_free;
1585e1779c27SMaxim Levitsky 
158673c25546SVitaly Kuznetsov 	svm->nested.force_msr_bitmap_recalc = true;
1587e1779c27SMaxim Levitsky 
1588a7d5c7ceSPaolo Bonzini 	kvm_make_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu);
15896ccbd29aSJoerg Roedel 	ret = 0;
15906ccbd29aSJoerg Roedel out_free:
15916ccbd29aSJoerg Roedel 	kfree(save);
15926ccbd29aSJoerg Roedel 	kfree(ctl);
15936ccbd29aSJoerg Roedel 
15946ccbd29aSJoerg Roedel 	return ret;
1595cc440cdaSPaolo Bonzini }
1596cc440cdaSPaolo Bonzini 
1597232f75d3SMaxim Levitsky static bool svm_get_nested_state_pages(struct kvm_vcpu *vcpu)
1598232f75d3SMaxim Levitsky {
1599232f75d3SMaxim Levitsky 	struct vcpu_svm *svm = to_svm(vcpu);
1600232f75d3SMaxim Levitsky 
1601232f75d3SMaxim Levitsky 	if (WARN_ON(!is_guest_mode(vcpu)))
1602232f75d3SMaxim Levitsky 		return true;
1603232f75d3SMaxim Levitsky 
1604158a48ecSMaxim Levitsky 	if (!vcpu->arch.pdptrs_from_userspace &&
1605158a48ecSMaxim Levitsky 	    !nested_npt_enabled(svm) && is_pae_paging(vcpu))
1606b222b0b8SMaxim Levitsky 		/*
1607b222b0b8SMaxim Levitsky 		 * Reload the guest's PDPTRs since after a migration
1608b222b0b8SMaxim Levitsky 		 * the guest CR3 might be restored prior to setting the nested
1609b222b0b8SMaxim Levitsky 		 * state which can lead to a load of wrong PDPTRs.
1610b222b0b8SMaxim Levitsky 		 */
16112df4a5ebSLai Jiangshan 		if (CC(!load_pdptrs(vcpu, vcpu->arch.cr3)))
1612232f75d3SMaxim Levitsky 			return false;
1613232f75d3SMaxim Levitsky 
1614232f75d3SMaxim Levitsky 	if (!nested_svm_vmrun_msrpm(svm)) {
1615232f75d3SMaxim Levitsky 		vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
1616232f75d3SMaxim Levitsky 		vcpu->run->internal.suberror =
1617232f75d3SMaxim Levitsky 			KVM_INTERNAL_ERROR_EMULATION;
1618232f75d3SMaxim Levitsky 		vcpu->run->internal.ndata = 0;
1619232f75d3SMaxim Levitsky 		return false;
1620232f75d3SMaxim Levitsky 	}
1621232f75d3SMaxim Levitsky 
1622232f75d3SMaxim Levitsky 	return true;
1623232f75d3SMaxim Levitsky }
1624232f75d3SMaxim Levitsky 
162533b22172SPaolo Bonzini struct kvm_x86_nested_ops svm_nested_ops = {
1626f7e57078SSean Christopherson 	.leave_nested = svm_leave_nested,
162733b22172SPaolo Bonzini 	.check_events = svm_check_nested_events,
1628cb6a32c2SSean Christopherson 	.triple_fault = nested_svm_triple_fault,
1629a7d5c7ceSPaolo Bonzini 	.get_nested_state_pages = svm_get_nested_state_pages,
1630cc440cdaSPaolo Bonzini 	.get_state = svm_get_nested_state,
1631cc440cdaSPaolo Bonzini 	.set_state = svm_set_nested_state,
163233b22172SPaolo Bonzini };
1633