162306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include <linux/kvm_host.h>
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include "irq.h"
662306a36Sopenharmony_ci#include "mmu.h"
762306a36Sopenharmony_ci#include "kvm_cache_regs.h"
862306a36Sopenharmony_ci#include "x86.h"
962306a36Sopenharmony_ci#include "smm.h"
1062306a36Sopenharmony_ci#include "cpuid.h"
1162306a36Sopenharmony_ci#include "pmu.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
1562306a36Sopenharmony_ci#include <linux/kernel.h>
1662306a36Sopenharmony_ci#include <linux/vmalloc.h>
1762306a36Sopenharmony_ci#include <linux/highmem.h>
1862306a36Sopenharmony_ci#include <linux/amd-iommu.h>
1962306a36Sopenharmony_ci#include <linux/sched.h>
2062306a36Sopenharmony_ci#include <linux/trace_events.h>
2162306a36Sopenharmony_ci#include <linux/slab.h>
2262306a36Sopenharmony_ci#include <linux/hashtable.h>
2362306a36Sopenharmony_ci#include <linux/objtool.h>
2462306a36Sopenharmony_ci#include <linux/psp-sev.h>
2562306a36Sopenharmony_ci#include <linux/file.h>
2662306a36Sopenharmony_ci#include <linux/pagemap.h>
2762306a36Sopenharmony_ci#include <linux/swap.h>
2862306a36Sopenharmony_ci#include <linux/rwsem.h>
2962306a36Sopenharmony_ci#include <linux/cc_platform.h>
3062306a36Sopenharmony_ci#include <linux/smp.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#include <asm/apic.h>
3362306a36Sopenharmony_ci#include <asm/perf_event.h>
3462306a36Sopenharmony_ci#include <asm/tlbflush.h>
3562306a36Sopenharmony_ci#include <asm/desc.h>
3662306a36Sopenharmony_ci#include <asm/debugreg.h>
3762306a36Sopenharmony_ci#include <asm/kvm_para.h>
3862306a36Sopenharmony_ci#include <asm/irq_remapping.h>
3962306a36Sopenharmony_ci#include <asm/spec-ctrl.h>
4062306a36Sopenharmony_ci#include <asm/cpu_device_id.h>
4162306a36Sopenharmony_ci#include <asm/traps.h>
4262306a36Sopenharmony_ci#include <asm/reboot.h>
4362306a36Sopenharmony_ci#include <asm/fpu/api.h>
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#include <trace/events/ipi.h>
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#include "trace.h"
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci#include "svm.h"
5062306a36Sopenharmony_ci#include "svm_ops.h"
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#include "kvm_onhyperv.h"
5362306a36Sopenharmony_ci#include "svm_onhyperv.h"
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ciMODULE_AUTHOR("Qumranet");
5662306a36Sopenharmony_ciMODULE_LICENSE("GPL");
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#ifdef MODULE
5962306a36Sopenharmony_cistatic const struct x86_cpu_id svm_cpu_id[] = {
6062306a36Sopenharmony_ci	X86_MATCH_FEATURE(X86_FEATURE_SVM, NULL),
6162306a36Sopenharmony_ci	{}
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(x86cpu, svm_cpu_id);
6462306a36Sopenharmony_ci#endif
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#define SEG_TYPE_LDT 2
6762306a36Sopenharmony_ci#define SEG_TYPE_BUSY_TSS16 3
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic bool erratum_383_found __read_mostly;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ciu32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/*
7462306a36Sopenharmony_ci * Set osvw_len to higher value when updated Revision Guides
7562306a36Sopenharmony_ci * are published and we know what the new status bits are
7662306a36Sopenharmony_ci */
7762306a36Sopenharmony_cistatic uint64_t osvw_len = 4, osvw_status;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic DEFINE_PER_CPU(u64, current_tsc_ratio);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci#define X2APIC_MSR(x)	(APIC_BASE_MSR + (x >> 4))
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistatic const struct svm_direct_access_msrs {
8462306a36Sopenharmony_ci	u32 index;   /* Index of the MSR */
8562306a36Sopenharmony_ci	bool always; /* True if intercept is initially cleared */
8662306a36Sopenharmony_ci} direct_access_msrs[MAX_DIRECT_ACCESS_MSRS] = {
8762306a36Sopenharmony_ci	{ .index = MSR_STAR,				.always = true  },
8862306a36Sopenharmony_ci	{ .index = MSR_IA32_SYSENTER_CS,		.always = true  },
8962306a36Sopenharmony_ci	{ .index = MSR_IA32_SYSENTER_EIP,		.always = false },
9062306a36Sopenharmony_ci	{ .index = MSR_IA32_SYSENTER_ESP,		.always = false },
9162306a36Sopenharmony_ci#ifdef CONFIG_X86_64
9262306a36Sopenharmony_ci	{ .index = MSR_GS_BASE,				.always = true  },
9362306a36Sopenharmony_ci	{ .index = MSR_FS_BASE,				.always = true  },
9462306a36Sopenharmony_ci	{ .index = MSR_KERNEL_GS_BASE,			.always = true  },
9562306a36Sopenharmony_ci	{ .index = MSR_LSTAR,				.always = true  },
9662306a36Sopenharmony_ci	{ .index = MSR_CSTAR,				.always = true  },
9762306a36Sopenharmony_ci	{ .index = MSR_SYSCALL_MASK,			.always = true  },
9862306a36Sopenharmony_ci#endif
9962306a36Sopenharmony_ci	{ .index = MSR_IA32_SPEC_CTRL,			.always = false },
10062306a36Sopenharmony_ci	{ .index = MSR_IA32_PRED_CMD,			.always = false },
10162306a36Sopenharmony_ci	{ .index = MSR_IA32_FLUSH_CMD,			.always = false },
10262306a36Sopenharmony_ci	{ .index = MSR_IA32_LASTBRANCHFROMIP,		.always = false },
10362306a36Sopenharmony_ci	{ .index = MSR_IA32_LASTBRANCHTOIP,		.always = false },
10462306a36Sopenharmony_ci	{ .index = MSR_IA32_LASTINTFROMIP,		.always = false },
10562306a36Sopenharmony_ci	{ .index = MSR_IA32_LASTINTTOIP,		.always = false },
10662306a36Sopenharmony_ci	{ .index = MSR_EFER,				.always = false },
10762306a36Sopenharmony_ci	{ .index = MSR_IA32_CR_PAT,			.always = false },
10862306a36Sopenharmony_ci	{ .index = MSR_AMD64_SEV_ES_GHCB,		.always = true  },
10962306a36Sopenharmony_ci	{ .index = MSR_TSC_AUX,				.always = false },
11062306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_ID),			.always = false },
11162306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_LVR),		.always = false },
11262306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_TASKPRI),		.always = false },
11362306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_ARBPRI),		.always = false },
11462306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_PROCPRI),		.always = false },
11562306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_EOI),		.always = false },
11662306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_RRR),		.always = false },
11762306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_LDR),		.always = false },
11862306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_DFR),		.always = false },
11962306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_SPIV),		.always = false },
12062306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_ISR),		.always = false },
12162306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_TMR),		.always = false },
12262306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_IRR),		.always = false },
12362306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_ESR),		.always = false },
12462306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_ICR),		.always = false },
12562306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_ICR2),		.always = false },
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	/*
12862306a36Sopenharmony_ci	 * Note:
12962306a36Sopenharmony_ci	 * AMD does not virtualize APIC TSC-deadline timer mode, but it is
13062306a36Sopenharmony_ci	 * emulated by KVM. When setting APIC LVTT (0x832) register bit 18,
13162306a36Sopenharmony_ci	 * the AVIC hardware would generate GP fault. Therefore, always
13262306a36Sopenharmony_ci	 * intercept the MSR 0x832, and do not setup direct_access_msr.
13362306a36Sopenharmony_ci	 */
13462306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_LVTTHMR),		.always = false },
13562306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_LVTPC),		.always = false },
13662306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_LVT0),		.always = false },
13762306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_LVT1),		.always = false },
13862306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_LVTERR),		.always = false },
13962306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_TMICT),		.always = false },
14062306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_TMCCT),		.always = false },
14162306a36Sopenharmony_ci	{ .index = X2APIC_MSR(APIC_TDCR),		.always = false },
14262306a36Sopenharmony_ci	{ .index = MSR_INVALID,				.always = false },
14362306a36Sopenharmony_ci};
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/*
14662306a36Sopenharmony_ci * These 2 parameters are used to config the controls for Pause-Loop Exiting:
14762306a36Sopenharmony_ci * pause_filter_count: On processors that support Pause filtering(indicated
14862306a36Sopenharmony_ci *	by CPUID Fn8000_000A_EDX), the VMCB provides a 16 bit pause filter
14962306a36Sopenharmony_ci *	count value. On VMRUN this value is loaded into an internal counter.
15062306a36Sopenharmony_ci *	Each time a pause instruction is executed, this counter is decremented
15162306a36Sopenharmony_ci *	until it reaches zero at which time a #VMEXIT is generated if pause
15262306a36Sopenharmony_ci *	intercept is enabled. Refer to  AMD APM Vol 2 Section 15.14.4 Pause
15362306a36Sopenharmony_ci *	Intercept Filtering for more details.
15462306a36Sopenharmony_ci *	This also indicate if ple logic enabled.
15562306a36Sopenharmony_ci *
15662306a36Sopenharmony_ci * pause_filter_thresh: In addition, some processor families support advanced
15762306a36Sopenharmony_ci *	pause filtering (indicated by CPUID Fn8000_000A_EDX) upper bound on
15862306a36Sopenharmony_ci *	the amount of time a guest is allowed to execute in a pause loop.
15962306a36Sopenharmony_ci *	In this mode, a 16-bit pause filter threshold field is added in the
16062306a36Sopenharmony_ci *	VMCB. The threshold value is a cycle count that is used to reset the
16162306a36Sopenharmony_ci *	pause counter. As with simple pause filtering, VMRUN loads the pause
16262306a36Sopenharmony_ci *	count value from VMCB into an internal counter. Then, on each pause
16362306a36Sopenharmony_ci *	instruction the hardware checks the elapsed number of cycles since
16462306a36Sopenharmony_ci *	the most recent pause instruction against the pause filter threshold.
16562306a36Sopenharmony_ci *	If the elapsed cycle count is greater than the pause filter threshold,
16662306a36Sopenharmony_ci *	then the internal pause count is reloaded from the VMCB and execution
16762306a36Sopenharmony_ci *	continues. If the elapsed cycle count is less than the pause filter
16862306a36Sopenharmony_ci *	threshold, then the internal pause count is decremented. If the count
16962306a36Sopenharmony_ci *	value is less than zero and PAUSE intercept is enabled, a #VMEXIT is
17062306a36Sopenharmony_ci *	triggered. If advanced pause filtering is supported and pause filter
17162306a36Sopenharmony_ci *	threshold field is set to zero, the filter will operate in the simpler,
17262306a36Sopenharmony_ci *	count only mode.
17362306a36Sopenharmony_ci */
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_cistatic unsigned short pause_filter_thresh = KVM_DEFAULT_PLE_GAP;
17662306a36Sopenharmony_cimodule_param(pause_filter_thresh, ushort, 0444);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic unsigned short pause_filter_count = KVM_SVM_DEFAULT_PLE_WINDOW;
17962306a36Sopenharmony_cimodule_param(pause_filter_count, ushort, 0444);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci/* Default doubles per-vcpu window every exit. */
18262306a36Sopenharmony_cistatic unsigned short pause_filter_count_grow = KVM_DEFAULT_PLE_WINDOW_GROW;
18362306a36Sopenharmony_cimodule_param(pause_filter_count_grow, ushort, 0444);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/* Default resets per-vcpu window every exit to pause_filter_count. */
18662306a36Sopenharmony_cistatic unsigned short pause_filter_count_shrink = KVM_DEFAULT_PLE_WINDOW_SHRINK;
18762306a36Sopenharmony_cimodule_param(pause_filter_count_shrink, ushort, 0444);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci/* Default is to compute the maximum so we can never overflow. */
19062306a36Sopenharmony_cistatic unsigned short pause_filter_count_max = KVM_SVM_DEFAULT_PLE_WINDOW_MAX;
19162306a36Sopenharmony_cimodule_param(pause_filter_count_max, ushort, 0444);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci/*
19462306a36Sopenharmony_ci * Use nested page tables by default.  Note, NPT may get forced off by
19562306a36Sopenharmony_ci * svm_hardware_setup() if it's unsupported by hardware or the host kernel.
19662306a36Sopenharmony_ci */
19762306a36Sopenharmony_cibool npt_enabled = true;
19862306a36Sopenharmony_cimodule_param_named(npt, npt_enabled, bool, 0444);
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci/* allow nested virtualization in KVM/SVM */
20162306a36Sopenharmony_cistatic int nested = true;
20262306a36Sopenharmony_cimodule_param(nested, int, S_IRUGO);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci/* enable/disable Next RIP Save */
20562306a36Sopenharmony_ciint nrips = true;
20662306a36Sopenharmony_cimodule_param(nrips, int, 0444);
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci/* enable/disable Virtual VMLOAD VMSAVE */
20962306a36Sopenharmony_cistatic int vls = true;
21062306a36Sopenharmony_cimodule_param(vls, int, 0444);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci/* enable/disable Virtual GIF */
21362306a36Sopenharmony_ciint vgif = true;
21462306a36Sopenharmony_cimodule_param(vgif, int, 0444);
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci/* enable/disable LBR virtualization */
21762306a36Sopenharmony_cistatic int lbrv = true;
21862306a36Sopenharmony_cimodule_param(lbrv, int, 0444);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cistatic int tsc_scaling = true;
22162306a36Sopenharmony_cimodule_param(tsc_scaling, int, 0444);
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci/*
22462306a36Sopenharmony_ci * enable / disable AVIC.  Because the defaults differ for APICv
22562306a36Sopenharmony_ci * support between VMX and SVM we cannot use module_param_named.
22662306a36Sopenharmony_ci */
22762306a36Sopenharmony_cistatic bool avic;
22862306a36Sopenharmony_cimodule_param(avic, bool, 0444);
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cibool __read_mostly dump_invalid_vmcb;
23162306a36Sopenharmony_cimodule_param(dump_invalid_vmcb, bool, 0644);
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cibool intercept_smi = true;
23562306a36Sopenharmony_cimodule_param(intercept_smi, bool, 0444);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cibool vnmi = true;
23862306a36Sopenharmony_cimodule_param(vnmi, bool, 0444);
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic bool svm_gp_erratum_intercept = true;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_cistatic u8 rsm_ins_bytes[] = "\x0f\xaa";
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_cistatic unsigned long iopm_base;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ciDEFINE_PER_CPU(struct svm_cpu_data, svm_data);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci/*
24962306a36Sopenharmony_ci * Only MSR_TSC_AUX is switched via the user return hook.  EFER is switched via
25062306a36Sopenharmony_ci * the VMCB, and the SYSCALL/SYSENTER MSRs are handled by VMLOAD/VMSAVE.
25162306a36Sopenharmony_ci *
25262306a36Sopenharmony_ci * RDTSCP and RDPID are not used in the kernel, specifically to allow KVM to
25362306a36Sopenharmony_ci * defer the restoration of TSC_AUX until the CPU returns to userspace.
25462306a36Sopenharmony_ci */
25562306a36Sopenharmony_cistatic int tsc_aux_uret_slot __read_mostly = -1;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cistatic const u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci#define NUM_MSR_MAPS ARRAY_SIZE(msrpm_ranges)
26062306a36Sopenharmony_ci#define MSRS_RANGE_SIZE 2048
26162306a36Sopenharmony_ci#define MSRS_IN_RANGE (MSRS_RANGE_SIZE * 8 / 2)
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ciu32 svm_msrpm_offset(u32 msr)
26462306a36Sopenharmony_ci{
26562306a36Sopenharmony_ci	u32 offset;
26662306a36Sopenharmony_ci	int i;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	for (i = 0; i < NUM_MSR_MAPS; i++) {
26962306a36Sopenharmony_ci		if (msr < msrpm_ranges[i] ||
27062306a36Sopenharmony_ci		    msr >= msrpm_ranges[i] + MSRS_IN_RANGE)
27162306a36Sopenharmony_ci			continue;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci		offset  = (msr - msrpm_ranges[i]) / 4; /* 4 msrs per u8 */
27462306a36Sopenharmony_ci		offset += (i * MSRS_RANGE_SIZE);       /* add range offset */
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci		/* Now we have the u8 offset - but need the u32 offset */
27762306a36Sopenharmony_ci		return offset / 4;
27862306a36Sopenharmony_ci	}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	/* MSR not in any range */
28162306a36Sopenharmony_ci	return MSR_INVALID;
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic void svm_flush_tlb_current(struct kvm_vcpu *vcpu);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_cistatic int get_npt_level(void)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci#ifdef CONFIG_X86_64
28962306a36Sopenharmony_ci	return pgtable_l5_enabled() ? PT64_ROOT_5LEVEL : PT64_ROOT_4LEVEL;
29062306a36Sopenharmony_ci#else
29162306a36Sopenharmony_ci	return PT32E_ROOT_LEVEL;
29262306a36Sopenharmony_ci#endif
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ciint svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
29662306a36Sopenharmony_ci{
29762306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
29862306a36Sopenharmony_ci	u64 old_efer = vcpu->arch.efer;
29962306a36Sopenharmony_ci	vcpu->arch.efer = efer;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	if (!npt_enabled) {
30262306a36Sopenharmony_ci		/* Shadow paging assumes NX to be available.  */
30362306a36Sopenharmony_ci		efer |= EFER_NX;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci		if (!(efer & EFER_LMA))
30662306a36Sopenharmony_ci			efer &= ~EFER_LME;
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	if ((old_efer & EFER_SVME) != (efer & EFER_SVME)) {
31062306a36Sopenharmony_ci		if (!(efer & EFER_SVME)) {
31162306a36Sopenharmony_ci			svm_leave_nested(vcpu);
31262306a36Sopenharmony_ci			svm_set_gif(svm, true);
31362306a36Sopenharmony_ci			/* #GP intercept is still needed for vmware backdoor */
31462306a36Sopenharmony_ci			if (!enable_vmware_backdoor)
31562306a36Sopenharmony_ci				clr_exception_intercept(svm, GP_VECTOR);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci			/*
31862306a36Sopenharmony_ci			 * Free the nested guest state, unless we are in SMM.
31962306a36Sopenharmony_ci			 * In this case we will return to the nested guest
32062306a36Sopenharmony_ci			 * as soon as we leave SMM.
32162306a36Sopenharmony_ci			 */
32262306a36Sopenharmony_ci			if (!is_smm(vcpu))
32362306a36Sopenharmony_ci				svm_free_nested(svm);
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci		} else {
32662306a36Sopenharmony_ci			int ret = svm_allocate_nested(svm);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci			if (ret) {
32962306a36Sopenharmony_ci				vcpu->arch.efer = old_efer;
33062306a36Sopenharmony_ci				return ret;
33162306a36Sopenharmony_ci			}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci			/*
33462306a36Sopenharmony_ci			 * Never intercept #GP for SEV guests, KVM can't
33562306a36Sopenharmony_ci			 * decrypt guest memory to workaround the erratum.
33662306a36Sopenharmony_ci			 */
33762306a36Sopenharmony_ci			if (svm_gp_erratum_intercept && !sev_guest(vcpu->kvm))
33862306a36Sopenharmony_ci				set_exception_intercept(svm, GP_VECTOR);
33962306a36Sopenharmony_ci		}
34062306a36Sopenharmony_ci	}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	svm->vmcb->save.efer = efer | EFER_SVME;
34362306a36Sopenharmony_ci	vmcb_mark_dirty(svm->vmcb, VMCB_CR);
34462306a36Sopenharmony_ci	return 0;
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_cistatic u32 svm_get_interrupt_shadow(struct kvm_vcpu *vcpu)
34862306a36Sopenharmony_ci{
34962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
35062306a36Sopenharmony_ci	u32 ret = 0;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	if (svm->vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK)
35362306a36Sopenharmony_ci		ret = KVM_X86_SHADOW_INT_STI | KVM_X86_SHADOW_INT_MOV_SS;
35462306a36Sopenharmony_ci	return ret;
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic void svm_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	if (mask == 0)
36262306a36Sopenharmony_ci		svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
36362306a36Sopenharmony_ci	else
36462306a36Sopenharmony_ci		svm->vmcb->control.int_state |= SVM_INTERRUPT_SHADOW_MASK;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci}
36762306a36Sopenharmony_cistatic bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
36862306a36Sopenharmony_ci					void *insn, int insn_len);
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_cistatic int __svm_skip_emulated_instruction(struct kvm_vcpu *vcpu,
37162306a36Sopenharmony_ci					   bool commit_side_effects)
37262306a36Sopenharmony_ci{
37362306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
37462306a36Sopenharmony_ci	unsigned long old_rflags;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	/*
37762306a36Sopenharmony_ci	 * SEV-ES does not expose the next RIP. The RIP update is controlled by
37862306a36Sopenharmony_ci	 * the type of exit and the #VC handler in the guest.
37962306a36Sopenharmony_ci	 */
38062306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm))
38162306a36Sopenharmony_ci		goto done;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	if (nrips && svm->vmcb->control.next_rip != 0) {
38462306a36Sopenharmony_ci		WARN_ON_ONCE(!static_cpu_has(X86_FEATURE_NRIPS));
38562306a36Sopenharmony_ci		svm->next_rip = svm->vmcb->control.next_rip;
38662306a36Sopenharmony_ci	}
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	if (!svm->next_rip) {
38962306a36Sopenharmony_ci		/*
39062306a36Sopenharmony_ci		 * FIXME: Drop this when kvm_emulate_instruction() does the
39162306a36Sopenharmony_ci		 * right thing and treats "can't emulate" as outright failure
39262306a36Sopenharmony_ci		 * for EMULTYPE_SKIP.
39362306a36Sopenharmony_ci		 */
39462306a36Sopenharmony_ci		if (!svm_can_emulate_instruction(vcpu, EMULTYPE_SKIP, NULL, 0))
39562306a36Sopenharmony_ci			return 0;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci		if (unlikely(!commit_side_effects))
39862306a36Sopenharmony_ci			old_rflags = svm->vmcb->save.rflags;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci		if (!kvm_emulate_instruction(vcpu, EMULTYPE_SKIP))
40162306a36Sopenharmony_ci			return 0;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci		if (unlikely(!commit_side_effects))
40462306a36Sopenharmony_ci			svm->vmcb->save.rflags = old_rflags;
40562306a36Sopenharmony_ci	} else {
40662306a36Sopenharmony_ci		kvm_rip_write(vcpu, svm->next_rip);
40762306a36Sopenharmony_ci	}
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_cidone:
41062306a36Sopenharmony_ci	if (likely(commit_side_effects))
41162306a36Sopenharmony_ci		svm_set_interrupt_shadow(vcpu, 0);
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	return 1;
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic int svm_skip_emulated_instruction(struct kvm_vcpu *vcpu)
41762306a36Sopenharmony_ci{
41862306a36Sopenharmony_ci	return __svm_skip_emulated_instruction(vcpu, true);
41962306a36Sopenharmony_ci}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_cistatic int svm_update_soft_interrupt_rip(struct kvm_vcpu *vcpu)
42262306a36Sopenharmony_ci{
42362306a36Sopenharmony_ci	unsigned long rip, old_rip = kvm_rip_read(vcpu);
42462306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	/*
42762306a36Sopenharmony_ci	 * Due to architectural shortcomings, the CPU doesn't always provide
42862306a36Sopenharmony_ci	 * NextRIP, e.g. if KVM intercepted an exception that occurred while
42962306a36Sopenharmony_ci	 * the CPU was vectoring an INTO/INT3 in the guest.  Temporarily skip
43062306a36Sopenharmony_ci	 * the instruction even if NextRIP is supported to acquire the next
43162306a36Sopenharmony_ci	 * RIP so that it can be shoved into the NextRIP field, otherwise
43262306a36Sopenharmony_ci	 * hardware will fail to advance guest RIP during event injection.
43362306a36Sopenharmony_ci	 * Drop the exception/interrupt if emulation fails and effectively
43462306a36Sopenharmony_ci	 * retry the instruction, it's the least awful option.  If NRIPS is
43562306a36Sopenharmony_ci	 * in use, the skip must not commit any side effects such as clearing
43662306a36Sopenharmony_ci	 * the interrupt shadow or RFLAGS.RF.
43762306a36Sopenharmony_ci	 */
43862306a36Sopenharmony_ci	if (!__svm_skip_emulated_instruction(vcpu, !nrips))
43962306a36Sopenharmony_ci		return -EIO;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	rip = kvm_rip_read(vcpu);
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	/*
44462306a36Sopenharmony_ci	 * Save the injection information, even when using next_rip, as the
44562306a36Sopenharmony_ci	 * VMCB's next_rip will be lost (cleared on VM-Exit) if the injection
44662306a36Sopenharmony_ci	 * doesn't complete due to a VM-Exit occurring while the CPU is
44762306a36Sopenharmony_ci	 * vectoring the event.   Decoding the instruction isn't guaranteed to
44862306a36Sopenharmony_ci	 * work as there may be no backing instruction, e.g. if the event is
44962306a36Sopenharmony_ci	 * being injected by L1 for L2, or if the guest is patching INT3 into
45062306a36Sopenharmony_ci	 * a different instruction.
45162306a36Sopenharmony_ci	 */
45262306a36Sopenharmony_ci	svm->soft_int_injected = true;
45362306a36Sopenharmony_ci	svm->soft_int_csbase = svm->vmcb->save.cs.base;
45462306a36Sopenharmony_ci	svm->soft_int_old_rip = old_rip;
45562306a36Sopenharmony_ci	svm->soft_int_next_rip = rip;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	if (nrips)
45862306a36Sopenharmony_ci		kvm_rip_write(vcpu, old_rip);
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_NRIPS))
46162306a36Sopenharmony_ci		svm->vmcb->control.next_rip = rip;
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	return 0;
46462306a36Sopenharmony_ci}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_cistatic void svm_inject_exception(struct kvm_vcpu *vcpu)
46762306a36Sopenharmony_ci{
46862306a36Sopenharmony_ci	struct kvm_queued_exception *ex = &vcpu->arch.exception;
46962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	kvm_deliver_exception_payload(vcpu, ex);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	if (kvm_exception_is_soft(ex->vector) &&
47462306a36Sopenharmony_ci	    svm_update_soft_interrupt_rip(vcpu))
47562306a36Sopenharmony_ci		return;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	svm->vmcb->control.event_inj = ex->vector
47862306a36Sopenharmony_ci		| SVM_EVTINJ_VALID
47962306a36Sopenharmony_ci		| (ex->has_error_code ? SVM_EVTINJ_VALID_ERR : 0)
48062306a36Sopenharmony_ci		| SVM_EVTINJ_TYPE_EXEPT;
48162306a36Sopenharmony_ci	svm->vmcb->control.event_inj_err = ex->error_code;
48262306a36Sopenharmony_ci}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_cistatic void svm_init_erratum_383(void)
48562306a36Sopenharmony_ci{
48662306a36Sopenharmony_ci	u32 low, high;
48762306a36Sopenharmony_ci	int err;
48862306a36Sopenharmony_ci	u64 val;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	if (!static_cpu_has_bug(X86_BUG_AMD_TLB_MMATCH))
49162306a36Sopenharmony_ci		return;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	/* Use _safe variants to not break nested virtualization */
49462306a36Sopenharmony_ci	val = native_read_msr_safe(MSR_AMD64_DC_CFG, &err);
49562306a36Sopenharmony_ci	if (err)
49662306a36Sopenharmony_ci		return;
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	val |= (1ULL << 47);
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	low  = lower_32_bits(val);
50162306a36Sopenharmony_ci	high = upper_32_bits(val);
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	native_write_msr_safe(MSR_AMD64_DC_CFG, low, high);
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	erratum_383_found = true;
50662306a36Sopenharmony_ci}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_cistatic void svm_init_osvw(struct kvm_vcpu *vcpu)
50962306a36Sopenharmony_ci{
51062306a36Sopenharmony_ci	/*
51162306a36Sopenharmony_ci	 * Guests should see errata 400 and 415 as fixed (assuming that
51262306a36Sopenharmony_ci	 * HLT and IO instructions are intercepted).
51362306a36Sopenharmony_ci	 */
51462306a36Sopenharmony_ci	vcpu->arch.osvw.length = (osvw_len >= 3) ? (osvw_len) : 3;
51562306a36Sopenharmony_ci	vcpu->arch.osvw.status = osvw_status & ~(6ULL);
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	/*
51862306a36Sopenharmony_ci	 * By increasing VCPU's osvw.length to 3 we are telling the guest that
51962306a36Sopenharmony_ci	 * all osvw.status bits inside that length, including bit 0 (which is
52062306a36Sopenharmony_ci	 * reserved for erratum 298), are valid. However, if host processor's
52162306a36Sopenharmony_ci	 * osvw_len is 0 then osvw_status[0] carries no information. We need to
52262306a36Sopenharmony_ci	 * be conservative here and therefore we tell the guest that erratum 298
52362306a36Sopenharmony_ci	 * is present (because we really don't know).
52462306a36Sopenharmony_ci	 */
52562306a36Sopenharmony_ci	if (osvw_len == 0 && boot_cpu_data.x86 == 0x10)
52662306a36Sopenharmony_ci		vcpu->arch.osvw.status |= 1;
52762306a36Sopenharmony_ci}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_cistatic bool __kvm_is_svm_supported(void)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	int cpu = smp_processor_id();
53262306a36Sopenharmony_ci	struct cpuinfo_x86 *c = &cpu_data(cpu);
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	u64 vm_cr;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	if (c->x86_vendor != X86_VENDOR_AMD &&
53762306a36Sopenharmony_ci	    c->x86_vendor != X86_VENDOR_HYGON) {
53862306a36Sopenharmony_ci		pr_err("CPU %d isn't AMD or Hygon\n", cpu);
53962306a36Sopenharmony_ci		return false;
54062306a36Sopenharmony_ci	}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	if (!cpu_has(c, X86_FEATURE_SVM)) {
54362306a36Sopenharmony_ci		pr_err("SVM not supported by CPU %d\n", cpu);
54462306a36Sopenharmony_ci		return false;
54562306a36Sopenharmony_ci	}
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
54862306a36Sopenharmony_ci		pr_info("KVM is unsupported when running as an SEV guest\n");
54962306a36Sopenharmony_ci		return false;
55062306a36Sopenharmony_ci	}
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	rdmsrl(MSR_VM_CR, vm_cr);
55362306a36Sopenharmony_ci	if (vm_cr & (1 << SVM_VM_CR_SVM_DISABLE)) {
55462306a36Sopenharmony_ci		pr_err("SVM disabled (by BIOS) in MSR_VM_CR on CPU %d\n", cpu);
55562306a36Sopenharmony_ci		return false;
55662306a36Sopenharmony_ci	}
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	return true;
55962306a36Sopenharmony_ci}
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_cistatic bool kvm_is_svm_supported(void)
56262306a36Sopenharmony_ci{
56362306a36Sopenharmony_ci	bool supported;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	migrate_disable();
56662306a36Sopenharmony_ci	supported = __kvm_is_svm_supported();
56762306a36Sopenharmony_ci	migrate_enable();
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	return supported;
57062306a36Sopenharmony_ci}
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_cistatic int svm_check_processor_compat(void)
57362306a36Sopenharmony_ci{
57462306a36Sopenharmony_ci	if (!__kvm_is_svm_supported())
57562306a36Sopenharmony_ci		return -EIO;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	return 0;
57862306a36Sopenharmony_ci}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_cistatic void __svm_write_tsc_multiplier(u64 multiplier)
58162306a36Sopenharmony_ci{
58262306a36Sopenharmony_ci	if (multiplier == __this_cpu_read(current_tsc_ratio))
58362306a36Sopenharmony_ci		return;
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	wrmsrl(MSR_AMD64_TSC_RATIO, multiplier);
58662306a36Sopenharmony_ci	__this_cpu_write(current_tsc_ratio, multiplier);
58762306a36Sopenharmony_ci}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_cistatic inline void kvm_cpu_svm_disable(void)
59062306a36Sopenharmony_ci{
59162306a36Sopenharmony_ci	uint64_t efer;
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	wrmsrl(MSR_VM_HSAVE_PA, 0);
59462306a36Sopenharmony_ci	rdmsrl(MSR_EFER, efer);
59562306a36Sopenharmony_ci	if (efer & EFER_SVME) {
59662306a36Sopenharmony_ci		/*
59762306a36Sopenharmony_ci		 * Force GIF=1 prior to disabling SVM, e.g. to ensure INIT and
59862306a36Sopenharmony_ci		 * NMI aren't blocked.
59962306a36Sopenharmony_ci		 */
60062306a36Sopenharmony_ci		stgi();
60162306a36Sopenharmony_ci		wrmsrl(MSR_EFER, efer & ~EFER_SVME);
60262306a36Sopenharmony_ci	}
60362306a36Sopenharmony_ci}
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_cistatic void svm_emergency_disable(void)
60662306a36Sopenharmony_ci{
60762306a36Sopenharmony_ci	kvm_rebooting = true;
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	kvm_cpu_svm_disable();
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_cistatic void svm_hardware_disable(void)
61362306a36Sopenharmony_ci{
61462306a36Sopenharmony_ci	/* Make sure we clean up behind us */
61562306a36Sopenharmony_ci	if (tsc_scaling)
61662306a36Sopenharmony_ci		__svm_write_tsc_multiplier(SVM_TSC_RATIO_DEFAULT);
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	kvm_cpu_svm_disable();
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	amd_pmu_disable_virt();
62162306a36Sopenharmony_ci}
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_cistatic int svm_hardware_enable(void)
62462306a36Sopenharmony_ci{
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	struct svm_cpu_data *sd;
62762306a36Sopenharmony_ci	uint64_t efer;
62862306a36Sopenharmony_ci	int me = raw_smp_processor_id();
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	rdmsrl(MSR_EFER, efer);
63162306a36Sopenharmony_ci	if (efer & EFER_SVME)
63262306a36Sopenharmony_ci		return -EBUSY;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	sd = per_cpu_ptr(&svm_data, me);
63562306a36Sopenharmony_ci	sd->asid_generation = 1;
63662306a36Sopenharmony_ci	sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
63762306a36Sopenharmony_ci	sd->next_asid = sd->max_asid + 1;
63862306a36Sopenharmony_ci	sd->min_asid = max_sev_asid + 1;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	wrmsrl(MSR_EFER, efer | EFER_SVME);
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	wrmsrl(MSR_VM_HSAVE_PA, sd->save_area_pa);
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_TSCRATEMSR)) {
64562306a36Sopenharmony_ci		/*
64662306a36Sopenharmony_ci		 * Set the default value, even if we don't use TSC scaling
64762306a36Sopenharmony_ci		 * to avoid having stale value in the msr
64862306a36Sopenharmony_ci		 */
64962306a36Sopenharmony_ci		__svm_write_tsc_multiplier(SVM_TSC_RATIO_DEFAULT);
65062306a36Sopenharmony_ci	}
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	/*
65462306a36Sopenharmony_ci	 * Get OSVW bits.
65562306a36Sopenharmony_ci	 *
65662306a36Sopenharmony_ci	 * Note that it is possible to have a system with mixed processor
65762306a36Sopenharmony_ci	 * revisions and therefore different OSVW bits. If bits are not the same
65862306a36Sopenharmony_ci	 * on different processors then choose the worst case (i.e. if erratum
65962306a36Sopenharmony_ci	 * is present on one processor and not on another then assume that the
66062306a36Sopenharmony_ci	 * erratum is present everywhere).
66162306a36Sopenharmony_ci	 */
66262306a36Sopenharmony_ci	if (cpu_has(&boot_cpu_data, X86_FEATURE_OSVW)) {
66362306a36Sopenharmony_ci		uint64_t len, status = 0;
66462306a36Sopenharmony_ci		int err;
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci		len = native_read_msr_safe(MSR_AMD64_OSVW_ID_LENGTH, &err);
66762306a36Sopenharmony_ci		if (!err)
66862306a36Sopenharmony_ci			status = native_read_msr_safe(MSR_AMD64_OSVW_STATUS,
66962306a36Sopenharmony_ci						      &err);
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci		if (err)
67262306a36Sopenharmony_ci			osvw_status = osvw_len = 0;
67362306a36Sopenharmony_ci		else {
67462306a36Sopenharmony_ci			if (len < osvw_len)
67562306a36Sopenharmony_ci				osvw_len = len;
67662306a36Sopenharmony_ci			osvw_status |= status;
67762306a36Sopenharmony_ci			osvw_status &= (1ULL << osvw_len) - 1;
67862306a36Sopenharmony_ci		}
67962306a36Sopenharmony_ci	} else
68062306a36Sopenharmony_ci		osvw_status = osvw_len = 0;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	svm_init_erratum_383();
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	amd_pmu_enable_virt();
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	/*
68762306a36Sopenharmony_ci	 * If TSC_AUX virtualization is supported, TSC_AUX becomes a swap type
68862306a36Sopenharmony_ci	 * "B" field (see sev_es_prepare_switch_to_guest()) for SEV-ES guests.
68962306a36Sopenharmony_ci	 * Since Linux does not change the value of TSC_AUX once set, prime the
69062306a36Sopenharmony_ci	 * TSC_AUX field now to avoid a RDMSR on every vCPU run.
69162306a36Sopenharmony_ci	 */
69262306a36Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_V_TSC_AUX)) {
69362306a36Sopenharmony_ci		struct sev_es_save_area *hostsa;
69462306a36Sopenharmony_ci		u32 __maybe_unused msr_hi;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci		hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400);
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci		rdmsr(MSR_TSC_AUX, hostsa->tsc_aux, msr_hi);
69962306a36Sopenharmony_ci	}
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	return 0;
70262306a36Sopenharmony_ci}
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_cistatic void svm_cpu_uninit(int cpu)
70562306a36Sopenharmony_ci{
70662306a36Sopenharmony_ci	struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	if (!sd->save_area)
70962306a36Sopenharmony_ci		return;
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	kfree(sd->sev_vmcbs);
71262306a36Sopenharmony_ci	__free_page(sd->save_area);
71362306a36Sopenharmony_ci	sd->save_area_pa = 0;
71462306a36Sopenharmony_ci	sd->save_area = NULL;
71562306a36Sopenharmony_ci}
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_cistatic int svm_cpu_init(int cpu)
71862306a36Sopenharmony_ci{
71962306a36Sopenharmony_ci	struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
72062306a36Sopenharmony_ci	int ret = -ENOMEM;
72162306a36Sopenharmony_ci
72262306a36Sopenharmony_ci	memset(sd, 0, sizeof(struct svm_cpu_data));
72362306a36Sopenharmony_ci	sd->save_area = alloc_page(GFP_KERNEL | __GFP_ZERO);
72462306a36Sopenharmony_ci	if (!sd->save_area)
72562306a36Sopenharmony_ci		return ret;
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	ret = sev_cpu_init(sd);
72862306a36Sopenharmony_ci	if (ret)
72962306a36Sopenharmony_ci		goto free_save_area;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	sd->save_area_pa = __sme_page_pa(sd->save_area);
73262306a36Sopenharmony_ci	return 0;
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_cifree_save_area:
73562306a36Sopenharmony_ci	__free_page(sd->save_area);
73662306a36Sopenharmony_ci	sd->save_area = NULL;
73762306a36Sopenharmony_ci	return ret;
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci}
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_cistatic void set_dr_intercepts(struct vcpu_svm *svm)
74262306a36Sopenharmony_ci{
74362306a36Sopenharmony_ci	struct vmcb *vmcb = svm->vmcb01.ptr;
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR0_READ);
74662306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR1_READ);
74762306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR2_READ);
74862306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR3_READ);
74962306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR4_READ);
75062306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR5_READ);
75162306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR6_READ);
75262306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR0_WRITE);
75362306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR1_WRITE);
75462306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR2_WRITE);
75562306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR3_WRITE);
75662306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR4_WRITE);
75762306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR5_WRITE);
75862306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR6_WRITE);
75962306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_READ);
76062306a36Sopenharmony_ci	vmcb_set_intercept(&vmcb->control, INTERCEPT_DR7_WRITE);
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	recalc_intercepts(svm);
76362306a36Sopenharmony_ci}
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_cistatic void clr_dr_intercepts(struct vcpu_svm *svm)
76662306a36Sopenharmony_ci{
76762306a36Sopenharmony_ci	struct vmcb *vmcb = svm->vmcb01.ptr;
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	vmcb->control.intercepts[INTERCEPT_DR] = 0;
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	recalc_intercepts(svm);
77262306a36Sopenharmony_ci}
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_cistatic int direct_access_msr_slot(u32 msr)
77562306a36Sopenharmony_ci{
77662306a36Sopenharmony_ci	u32 i;
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci	for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++)
77962306a36Sopenharmony_ci		if (direct_access_msrs[i].index == msr)
78062306a36Sopenharmony_ci			return i;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	return -ENOENT;
78362306a36Sopenharmony_ci}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_cistatic void set_shadow_msr_intercept(struct kvm_vcpu *vcpu, u32 msr, int read,
78662306a36Sopenharmony_ci				     int write)
78762306a36Sopenharmony_ci{
78862306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
78962306a36Sopenharmony_ci	int slot = direct_access_msr_slot(msr);
79062306a36Sopenharmony_ci
79162306a36Sopenharmony_ci	if (slot == -ENOENT)
79262306a36Sopenharmony_ci		return;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	/* Set the shadow bitmaps to the desired intercept states */
79562306a36Sopenharmony_ci	if (read)
79662306a36Sopenharmony_ci		set_bit(slot, svm->shadow_msr_intercept.read);
79762306a36Sopenharmony_ci	else
79862306a36Sopenharmony_ci		clear_bit(slot, svm->shadow_msr_intercept.read);
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	if (write)
80162306a36Sopenharmony_ci		set_bit(slot, svm->shadow_msr_intercept.write);
80262306a36Sopenharmony_ci	else
80362306a36Sopenharmony_ci		clear_bit(slot, svm->shadow_msr_intercept.write);
80462306a36Sopenharmony_ci}
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_cistatic bool valid_msr_intercept(u32 index)
80762306a36Sopenharmony_ci{
80862306a36Sopenharmony_ci	return direct_access_msr_slot(index) != -ENOENT;
80962306a36Sopenharmony_ci}
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_cistatic bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr)
81262306a36Sopenharmony_ci{
81362306a36Sopenharmony_ci	u8 bit_write;
81462306a36Sopenharmony_ci	unsigned long tmp;
81562306a36Sopenharmony_ci	u32 offset;
81662306a36Sopenharmony_ci	u32 *msrpm;
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	/*
81962306a36Sopenharmony_ci	 * For non-nested case:
82062306a36Sopenharmony_ci	 * If the L01 MSR bitmap does not intercept the MSR, then we need to
82162306a36Sopenharmony_ci	 * save it.
82262306a36Sopenharmony_ci	 *
82362306a36Sopenharmony_ci	 * For nested case:
82462306a36Sopenharmony_ci	 * If the L02 MSR bitmap does not intercept the MSR, then we need to
82562306a36Sopenharmony_ci	 * save it.
82662306a36Sopenharmony_ci	 */
82762306a36Sopenharmony_ci	msrpm = is_guest_mode(vcpu) ? to_svm(vcpu)->nested.msrpm:
82862306a36Sopenharmony_ci				      to_svm(vcpu)->msrpm;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	offset    = svm_msrpm_offset(msr);
83162306a36Sopenharmony_ci	bit_write = 2 * (msr & 0x0f) + 1;
83262306a36Sopenharmony_ci	tmp       = msrpm[offset];
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	BUG_ON(offset == MSR_INVALID);
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	return test_bit(bit_write, &tmp);
83762306a36Sopenharmony_ci}
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_cistatic void set_msr_interception_bitmap(struct kvm_vcpu *vcpu, u32 *msrpm,
84062306a36Sopenharmony_ci					u32 msr, int read, int write)
84162306a36Sopenharmony_ci{
84262306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
84362306a36Sopenharmony_ci	u8 bit_read, bit_write;
84462306a36Sopenharmony_ci	unsigned long tmp;
84562306a36Sopenharmony_ci	u32 offset;
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	/*
84862306a36Sopenharmony_ci	 * If this warning triggers extend the direct_access_msrs list at the
84962306a36Sopenharmony_ci	 * beginning of the file
85062306a36Sopenharmony_ci	 */
85162306a36Sopenharmony_ci	WARN_ON(!valid_msr_intercept(msr));
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	/* Enforce non allowed MSRs to trap */
85462306a36Sopenharmony_ci	if (read && !kvm_msr_allowed(vcpu, msr, KVM_MSR_FILTER_READ))
85562306a36Sopenharmony_ci		read = 0;
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	if (write && !kvm_msr_allowed(vcpu, msr, KVM_MSR_FILTER_WRITE))
85862306a36Sopenharmony_ci		write = 0;
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	offset    = svm_msrpm_offset(msr);
86162306a36Sopenharmony_ci	bit_read  = 2 * (msr & 0x0f);
86262306a36Sopenharmony_ci	bit_write = 2 * (msr & 0x0f) + 1;
86362306a36Sopenharmony_ci	tmp       = msrpm[offset];
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	BUG_ON(offset == MSR_INVALID);
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	read  ? clear_bit(bit_read,  &tmp) : set_bit(bit_read,  &tmp);
86862306a36Sopenharmony_ci	write ? clear_bit(bit_write, &tmp) : set_bit(bit_write, &tmp);
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	msrpm[offset] = tmp;
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	svm_hv_vmcb_dirty_nested_enlightenments(vcpu);
87362306a36Sopenharmony_ci	svm->nested.force_msr_bitmap_recalc = true;
87462306a36Sopenharmony_ci}
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_civoid set_msr_interception(struct kvm_vcpu *vcpu, u32 *msrpm, u32 msr,
87762306a36Sopenharmony_ci			  int read, int write)
87862306a36Sopenharmony_ci{
87962306a36Sopenharmony_ci	set_shadow_msr_intercept(vcpu, msr, read, write);
88062306a36Sopenharmony_ci	set_msr_interception_bitmap(vcpu, msrpm, msr, read, write);
88162306a36Sopenharmony_ci}
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ciu32 *svm_vcpu_alloc_msrpm(void)
88462306a36Sopenharmony_ci{
88562306a36Sopenharmony_ci	unsigned int order = get_order(MSRPM_SIZE);
88662306a36Sopenharmony_ci	struct page *pages = alloc_pages(GFP_KERNEL_ACCOUNT, order);
88762306a36Sopenharmony_ci	u32 *msrpm;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	if (!pages)
89062306a36Sopenharmony_ci		return NULL;
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	msrpm = page_address(pages);
89362306a36Sopenharmony_ci	memset(msrpm, 0xff, PAGE_SIZE * (1 << order));
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	return msrpm;
89662306a36Sopenharmony_ci}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_civoid svm_vcpu_init_msrpm(struct kvm_vcpu *vcpu, u32 *msrpm)
89962306a36Sopenharmony_ci{
90062306a36Sopenharmony_ci	int i;
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++) {
90362306a36Sopenharmony_ci		if (!direct_access_msrs[i].always)
90462306a36Sopenharmony_ci			continue;
90562306a36Sopenharmony_ci		set_msr_interception(vcpu, msrpm, direct_access_msrs[i].index, 1, 1);
90662306a36Sopenharmony_ci	}
90762306a36Sopenharmony_ci}
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_civoid svm_set_x2apic_msr_interception(struct vcpu_svm *svm, bool intercept)
91062306a36Sopenharmony_ci{
91162306a36Sopenharmony_ci	int i;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	if (intercept == svm->x2avic_msrs_intercepted)
91462306a36Sopenharmony_ci		return;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	if (!x2avic_enabled)
91762306a36Sopenharmony_ci		return;
91862306a36Sopenharmony_ci
91962306a36Sopenharmony_ci	for (i = 0; i < MAX_DIRECT_ACCESS_MSRS; i++) {
92062306a36Sopenharmony_ci		int index = direct_access_msrs[i].index;
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci		if ((index < APIC_BASE_MSR) ||
92362306a36Sopenharmony_ci		    (index > APIC_BASE_MSR + 0xff))
92462306a36Sopenharmony_ci			continue;
92562306a36Sopenharmony_ci		set_msr_interception(&svm->vcpu, svm->msrpm, index,
92662306a36Sopenharmony_ci				     !intercept, !intercept);
92762306a36Sopenharmony_ci	}
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci	svm->x2avic_msrs_intercepted = intercept;
93062306a36Sopenharmony_ci}
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_civoid svm_vcpu_free_msrpm(u32 *msrpm)
93362306a36Sopenharmony_ci{
93462306a36Sopenharmony_ci	__free_pages(virt_to_page(msrpm), get_order(MSRPM_SIZE));
93562306a36Sopenharmony_ci}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_cistatic void svm_msr_filter_changed(struct kvm_vcpu *vcpu)
93862306a36Sopenharmony_ci{
93962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
94062306a36Sopenharmony_ci	u32 i;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	/*
94362306a36Sopenharmony_ci	 * Set intercept permissions for all direct access MSRs again. They
94462306a36Sopenharmony_ci	 * will automatically get filtered through the MSR filter, so we are
94562306a36Sopenharmony_ci	 * back in sync after this.
94662306a36Sopenharmony_ci	 */
94762306a36Sopenharmony_ci	for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++) {
94862306a36Sopenharmony_ci		u32 msr = direct_access_msrs[i].index;
94962306a36Sopenharmony_ci		u32 read = test_bit(i, svm->shadow_msr_intercept.read);
95062306a36Sopenharmony_ci		u32 write = test_bit(i, svm->shadow_msr_intercept.write);
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci		set_msr_interception_bitmap(vcpu, svm->msrpm, msr, read, write);
95362306a36Sopenharmony_ci	}
95462306a36Sopenharmony_ci}
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_cistatic void add_msr_offset(u32 offset)
95762306a36Sopenharmony_ci{
95862306a36Sopenharmony_ci	int i;
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	for (i = 0; i < MSRPM_OFFSETS; ++i) {
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci		/* Offset already in list? */
96362306a36Sopenharmony_ci		if (msrpm_offsets[i] == offset)
96462306a36Sopenharmony_ci			return;
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci		/* Slot used by another offset? */
96762306a36Sopenharmony_ci		if (msrpm_offsets[i] != MSR_INVALID)
96862306a36Sopenharmony_ci			continue;
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci		/* Add offset to list */
97162306a36Sopenharmony_ci		msrpm_offsets[i] = offset;
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci		return;
97462306a36Sopenharmony_ci	}
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	/*
97762306a36Sopenharmony_ci	 * If this BUG triggers the msrpm_offsets table has an overflow. Just
97862306a36Sopenharmony_ci	 * increase MSRPM_OFFSETS in this case.
97962306a36Sopenharmony_ci	 */
98062306a36Sopenharmony_ci	BUG();
98162306a36Sopenharmony_ci}
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_cistatic void init_msrpm_offsets(void)
98462306a36Sopenharmony_ci{
98562306a36Sopenharmony_ci	int i;
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	memset(msrpm_offsets, 0xff, sizeof(msrpm_offsets));
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++) {
99062306a36Sopenharmony_ci		u32 offset;
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci		offset = svm_msrpm_offset(direct_access_msrs[i].index);
99362306a36Sopenharmony_ci		BUG_ON(offset == MSR_INVALID);
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci		add_msr_offset(offset);
99662306a36Sopenharmony_ci	}
99762306a36Sopenharmony_ci}
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_civoid svm_copy_lbrs(struct vmcb *to_vmcb, struct vmcb *from_vmcb)
100062306a36Sopenharmony_ci{
100162306a36Sopenharmony_ci	to_vmcb->save.dbgctl		= from_vmcb->save.dbgctl;
100262306a36Sopenharmony_ci	to_vmcb->save.br_from		= from_vmcb->save.br_from;
100362306a36Sopenharmony_ci	to_vmcb->save.br_to		= from_vmcb->save.br_to;
100462306a36Sopenharmony_ci	to_vmcb->save.last_excp_from	= from_vmcb->save.last_excp_from;
100562306a36Sopenharmony_ci	to_vmcb->save.last_excp_to	= from_vmcb->save.last_excp_to;
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	vmcb_mark_dirty(to_vmcb, VMCB_LBR);
100862306a36Sopenharmony_ci}
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_cistatic void svm_enable_lbrv(struct kvm_vcpu *vcpu)
101162306a36Sopenharmony_ci{
101262306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci	svm->vmcb->control.virt_ext |= LBR_CTL_ENABLE_MASK;
101562306a36Sopenharmony_ci	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHFROMIP, 1, 1);
101662306a36Sopenharmony_ci	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHTOIP, 1, 1);
101762306a36Sopenharmony_ci	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTFROMIP, 1, 1);
101862306a36Sopenharmony_ci	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTTOIP, 1, 1);
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	/* Move the LBR msrs to the vmcb02 so that the guest can see them. */
102162306a36Sopenharmony_ci	if (is_guest_mode(vcpu))
102262306a36Sopenharmony_ci		svm_copy_lbrs(svm->vmcb, svm->vmcb01.ptr);
102362306a36Sopenharmony_ci}
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_cistatic void svm_disable_lbrv(struct kvm_vcpu *vcpu)
102662306a36Sopenharmony_ci{
102762306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	svm->vmcb->control.virt_ext &= ~LBR_CTL_ENABLE_MASK;
103062306a36Sopenharmony_ci	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHFROMIP, 0, 0);
103162306a36Sopenharmony_ci	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTBRANCHTOIP, 0, 0);
103262306a36Sopenharmony_ci	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTFROMIP, 0, 0);
103362306a36Sopenharmony_ci	set_msr_interception(vcpu, svm->msrpm, MSR_IA32_LASTINTTOIP, 0, 0);
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	/*
103662306a36Sopenharmony_ci	 * Move the LBR msrs back to the vmcb01 to avoid copying them
103762306a36Sopenharmony_ci	 * on nested guest entries.
103862306a36Sopenharmony_ci	 */
103962306a36Sopenharmony_ci	if (is_guest_mode(vcpu))
104062306a36Sopenharmony_ci		svm_copy_lbrs(svm->vmcb01.ptr, svm->vmcb);
104162306a36Sopenharmony_ci}
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_cistatic struct vmcb *svm_get_lbr_vmcb(struct vcpu_svm *svm)
104462306a36Sopenharmony_ci{
104562306a36Sopenharmony_ci	/*
104662306a36Sopenharmony_ci	 * If LBR virtualization is disabled, the LBR MSRs are always kept in
104762306a36Sopenharmony_ci	 * vmcb01.  If LBR virtualization is enabled and L1 is running VMs of
104862306a36Sopenharmony_ci	 * its own, the MSRs are moved between vmcb01 and vmcb02 as needed.
104962306a36Sopenharmony_ci	 */
105062306a36Sopenharmony_ci	return svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK ? svm->vmcb :
105162306a36Sopenharmony_ci								   svm->vmcb01.ptr;
105262306a36Sopenharmony_ci}
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_civoid svm_update_lbrv(struct kvm_vcpu *vcpu)
105562306a36Sopenharmony_ci{
105662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
105762306a36Sopenharmony_ci	bool current_enable_lbrv = svm->vmcb->control.virt_ext & LBR_CTL_ENABLE_MASK;
105862306a36Sopenharmony_ci	bool enable_lbrv = (svm_get_lbr_vmcb(svm)->save.dbgctl & DEBUGCTLMSR_LBR) ||
105962306a36Sopenharmony_ci			    (is_guest_mode(vcpu) && guest_can_use(vcpu, X86_FEATURE_LBRV) &&
106062306a36Sopenharmony_ci			    (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK));
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	if (enable_lbrv == current_enable_lbrv)
106362306a36Sopenharmony_ci		return;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	if (enable_lbrv)
106662306a36Sopenharmony_ci		svm_enable_lbrv(vcpu);
106762306a36Sopenharmony_ci	else
106862306a36Sopenharmony_ci		svm_disable_lbrv(vcpu);
106962306a36Sopenharmony_ci}
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_civoid disable_nmi_singlestep(struct vcpu_svm *svm)
107262306a36Sopenharmony_ci{
107362306a36Sopenharmony_ci	svm->nmi_singlestep = false;
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	if (!(svm->vcpu.guest_debug & KVM_GUESTDBG_SINGLESTEP)) {
107662306a36Sopenharmony_ci		/* Clear our flags if they were not set by the guest */
107762306a36Sopenharmony_ci		if (!(svm->nmi_singlestep_guest_rflags & X86_EFLAGS_TF))
107862306a36Sopenharmony_ci			svm->vmcb->save.rflags &= ~X86_EFLAGS_TF;
107962306a36Sopenharmony_ci		if (!(svm->nmi_singlestep_guest_rflags & X86_EFLAGS_RF))
108062306a36Sopenharmony_ci			svm->vmcb->save.rflags &= ~X86_EFLAGS_RF;
108162306a36Sopenharmony_ci	}
108262306a36Sopenharmony_ci}
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_cistatic void grow_ple_window(struct kvm_vcpu *vcpu)
108562306a36Sopenharmony_ci{
108662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
108762306a36Sopenharmony_ci	struct vmcb_control_area *control = &svm->vmcb->control;
108862306a36Sopenharmony_ci	int old = control->pause_filter_count;
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	if (kvm_pause_in_guest(vcpu->kvm))
109162306a36Sopenharmony_ci		return;
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	control->pause_filter_count = __grow_ple_window(old,
109462306a36Sopenharmony_ci							pause_filter_count,
109562306a36Sopenharmony_ci							pause_filter_count_grow,
109662306a36Sopenharmony_ci							pause_filter_count_max);
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci	if (control->pause_filter_count != old) {
109962306a36Sopenharmony_ci		vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
110062306a36Sopenharmony_ci		trace_kvm_ple_window_update(vcpu->vcpu_id,
110162306a36Sopenharmony_ci					    control->pause_filter_count, old);
110262306a36Sopenharmony_ci	}
110362306a36Sopenharmony_ci}
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_cistatic void shrink_ple_window(struct kvm_vcpu *vcpu)
110662306a36Sopenharmony_ci{
110762306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
110862306a36Sopenharmony_ci	struct vmcb_control_area *control = &svm->vmcb->control;
110962306a36Sopenharmony_ci	int old = control->pause_filter_count;
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	if (kvm_pause_in_guest(vcpu->kvm))
111262306a36Sopenharmony_ci		return;
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	control->pause_filter_count =
111562306a36Sopenharmony_ci				__shrink_ple_window(old,
111662306a36Sopenharmony_ci						    pause_filter_count,
111762306a36Sopenharmony_ci						    pause_filter_count_shrink,
111862306a36Sopenharmony_ci						    pause_filter_count);
111962306a36Sopenharmony_ci	if (control->pause_filter_count != old) {
112062306a36Sopenharmony_ci		vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
112162306a36Sopenharmony_ci		trace_kvm_ple_window_update(vcpu->vcpu_id,
112262306a36Sopenharmony_ci					    control->pause_filter_count, old);
112362306a36Sopenharmony_ci	}
112462306a36Sopenharmony_ci}
112562306a36Sopenharmony_ci
112662306a36Sopenharmony_cistatic void svm_hardware_unsetup(void)
112762306a36Sopenharmony_ci{
112862306a36Sopenharmony_ci	int cpu;
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	sev_hardware_unsetup();
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	for_each_possible_cpu(cpu)
113362306a36Sopenharmony_ci		svm_cpu_uninit(cpu);
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	__free_pages(pfn_to_page(iopm_base >> PAGE_SHIFT),
113662306a36Sopenharmony_ci	get_order(IOPM_SIZE));
113762306a36Sopenharmony_ci	iopm_base = 0;
113862306a36Sopenharmony_ci}
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_cistatic void init_seg(struct vmcb_seg *seg)
114162306a36Sopenharmony_ci{
114262306a36Sopenharmony_ci	seg->selector = 0;
114362306a36Sopenharmony_ci	seg->attrib = SVM_SELECTOR_P_MASK | SVM_SELECTOR_S_MASK |
114462306a36Sopenharmony_ci		      SVM_SELECTOR_WRITE_MASK; /* Read/Write Data Segment */
114562306a36Sopenharmony_ci	seg->limit = 0xffff;
114662306a36Sopenharmony_ci	seg->base = 0;
114762306a36Sopenharmony_ci}
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_cistatic void init_sys_seg(struct vmcb_seg *seg, uint32_t type)
115062306a36Sopenharmony_ci{
115162306a36Sopenharmony_ci	seg->selector = 0;
115262306a36Sopenharmony_ci	seg->attrib = SVM_SELECTOR_P_MASK | type;
115362306a36Sopenharmony_ci	seg->limit = 0xffff;
115462306a36Sopenharmony_ci	seg->base = 0;
115562306a36Sopenharmony_ci}
115662306a36Sopenharmony_ci
115762306a36Sopenharmony_cistatic u64 svm_get_l2_tsc_offset(struct kvm_vcpu *vcpu)
115862306a36Sopenharmony_ci{
115962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	return svm->nested.ctl.tsc_offset;
116262306a36Sopenharmony_ci}
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_cistatic u64 svm_get_l2_tsc_multiplier(struct kvm_vcpu *vcpu)
116562306a36Sopenharmony_ci{
116662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	return svm->tsc_ratio_msr;
116962306a36Sopenharmony_ci}
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_cistatic void svm_write_tsc_offset(struct kvm_vcpu *vcpu)
117262306a36Sopenharmony_ci{
117362306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	svm->vmcb01.ptr->control.tsc_offset = vcpu->arch.l1_tsc_offset;
117662306a36Sopenharmony_ci	svm->vmcb->control.tsc_offset = vcpu->arch.tsc_offset;
117762306a36Sopenharmony_ci	vmcb_mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
117862306a36Sopenharmony_ci}
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_civoid svm_write_tsc_multiplier(struct kvm_vcpu *vcpu)
118162306a36Sopenharmony_ci{
118262306a36Sopenharmony_ci	preempt_disable();
118362306a36Sopenharmony_ci	if (to_svm(vcpu)->guest_state_loaded)
118462306a36Sopenharmony_ci		__svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio);
118562306a36Sopenharmony_ci	preempt_enable();
118662306a36Sopenharmony_ci}
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci/* Evaluate instruction intercepts that depend on guest CPUID features. */
118962306a36Sopenharmony_cistatic void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu,
119062306a36Sopenharmony_ci					      struct vcpu_svm *svm)
119162306a36Sopenharmony_ci{
119262306a36Sopenharmony_ci	/*
119362306a36Sopenharmony_ci	 * Intercept INVPCID if shadow paging is enabled to sync/free shadow
119462306a36Sopenharmony_ci	 * roots, or if INVPCID is disabled in the guest to inject #UD.
119562306a36Sopenharmony_ci	 */
119662306a36Sopenharmony_ci	if (kvm_cpu_cap_has(X86_FEATURE_INVPCID)) {
119762306a36Sopenharmony_ci		if (!npt_enabled ||
119862306a36Sopenharmony_ci		    !guest_cpuid_has(&svm->vcpu, X86_FEATURE_INVPCID))
119962306a36Sopenharmony_ci			svm_set_intercept(svm, INTERCEPT_INVPCID);
120062306a36Sopenharmony_ci		else
120162306a36Sopenharmony_ci			svm_clr_intercept(svm, INTERCEPT_INVPCID);
120262306a36Sopenharmony_ci	}
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	if (kvm_cpu_cap_has(X86_FEATURE_RDTSCP)) {
120562306a36Sopenharmony_ci		if (guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
120662306a36Sopenharmony_ci			svm_clr_intercept(svm, INTERCEPT_RDTSCP);
120762306a36Sopenharmony_ci		else
120862306a36Sopenharmony_ci			svm_set_intercept(svm, INTERCEPT_RDTSCP);
120962306a36Sopenharmony_ci	}
121062306a36Sopenharmony_ci}
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_cistatic inline void init_vmcb_after_set_cpuid(struct kvm_vcpu *vcpu)
121362306a36Sopenharmony_ci{
121462306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	if (guest_cpuid_is_intel(vcpu)) {
121762306a36Sopenharmony_ci		/*
121862306a36Sopenharmony_ci		 * We must intercept SYSENTER_EIP and SYSENTER_ESP
121962306a36Sopenharmony_ci		 * accesses because the processor only stores 32 bits.
122062306a36Sopenharmony_ci		 * For the same reason we cannot use virtual VMLOAD/VMSAVE.
122162306a36Sopenharmony_ci		 */
122262306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_VMLOAD);
122362306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_VMSAVE);
122462306a36Sopenharmony_ci		svm->vmcb->control.virt_ext &= ~VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK;
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci		set_msr_interception(vcpu, svm->msrpm, MSR_IA32_SYSENTER_EIP, 0, 0);
122762306a36Sopenharmony_ci		set_msr_interception(vcpu, svm->msrpm, MSR_IA32_SYSENTER_ESP, 0, 0);
122862306a36Sopenharmony_ci	} else {
122962306a36Sopenharmony_ci		/*
123062306a36Sopenharmony_ci		 * If hardware supports Virtual VMLOAD VMSAVE then enable it
123162306a36Sopenharmony_ci		 * in VMCB and clear intercepts to avoid #VMEXIT.
123262306a36Sopenharmony_ci		 */
123362306a36Sopenharmony_ci		if (vls) {
123462306a36Sopenharmony_ci			svm_clr_intercept(svm, INTERCEPT_VMLOAD);
123562306a36Sopenharmony_ci			svm_clr_intercept(svm, INTERCEPT_VMSAVE);
123662306a36Sopenharmony_ci			svm->vmcb->control.virt_ext |= VIRTUAL_VMLOAD_VMSAVE_ENABLE_MASK;
123762306a36Sopenharmony_ci		}
123862306a36Sopenharmony_ci		/* No need to intercept these MSRs */
123962306a36Sopenharmony_ci		set_msr_interception(vcpu, svm->msrpm, MSR_IA32_SYSENTER_EIP, 1, 1);
124062306a36Sopenharmony_ci		set_msr_interception(vcpu, svm->msrpm, MSR_IA32_SYSENTER_ESP, 1, 1);
124162306a36Sopenharmony_ci	}
124262306a36Sopenharmony_ci}
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_cistatic void init_vmcb(struct kvm_vcpu *vcpu)
124562306a36Sopenharmony_ci{
124662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
124762306a36Sopenharmony_ci	struct vmcb *vmcb = svm->vmcb01.ptr;
124862306a36Sopenharmony_ci	struct vmcb_control_area *control = &vmcb->control;
124962306a36Sopenharmony_ci	struct vmcb_save_area *save = &vmcb->save;
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_CR0_READ);
125262306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_CR3_READ);
125362306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_CR4_READ);
125462306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_CR0_WRITE);
125562306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_CR3_WRITE);
125662306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_CR4_WRITE);
125762306a36Sopenharmony_ci	if (!kvm_vcpu_apicv_active(vcpu))
125862306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_CR8_WRITE);
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci	set_dr_intercepts(svm);
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci	set_exception_intercept(svm, PF_VECTOR);
126362306a36Sopenharmony_ci	set_exception_intercept(svm, UD_VECTOR);
126462306a36Sopenharmony_ci	set_exception_intercept(svm, MC_VECTOR);
126562306a36Sopenharmony_ci	set_exception_intercept(svm, AC_VECTOR);
126662306a36Sopenharmony_ci	set_exception_intercept(svm, DB_VECTOR);
126762306a36Sopenharmony_ci	/*
126862306a36Sopenharmony_ci	 * Guest access to VMware backdoor ports could legitimately
126962306a36Sopenharmony_ci	 * trigger #GP because of TSS I/O permission bitmap.
127062306a36Sopenharmony_ci	 * We intercept those #GP and allow access to them anyway
127162306a36Sopenharmony_ci	 * as VMware does.
127262306a36Sopenharmony_ci	 */
127362306a36Sopenharmony_ci	if (enable_vmware_backdoor)
127462306a36Sopenharmony_ci		set_exception_intercept(svm, GP_VECTOR);
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_INTR);
127762306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_NMI);
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	if (intercept_smi)
128062306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_SMI);
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_SELECTIVE_CR0);
128362306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_RDPMC);
128462306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_CPUID);
128562306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_INVD);
128662306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_INVLPG);
128762306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_INVLPGA);
128862306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_IOIO_PROT);
128962306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_MSR_PROT);
129062306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_TASK_SWITCH);
129162306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_SHUTDOWN);
129262306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_VMRUN);
129362306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_VMMCALL);
129462306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_VMLOAD);
129562306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_VMSAVE);
129662306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_STGI);
129762306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_CLGI);
129862306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_SKINIT);
129962306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_WBINVD);
130062306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_XSETBV);
130162306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_RDPRU);
130262306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_RSM);
130362306a36Sopenharmony_ci
130462306a36Sopenharmony_ci	if (!kvm_mwait_in_guest(vcpu->kvm)) {
130562306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_MONITOR);
130662306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_MWAIT);
130762306a36Sopenharmony_ci	}
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci	if (!kvm_hlt_in_guest(vcpu->kvm))
131062306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_HLT);
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_ci	control->iopm_base_pa = __sme_set(iopm_base);
131362306a36Sopenharmony_ci	control->msrpm_base_pa = __sme_set(__pa(svm->msrpm));
131462306a36Sopenharmony_ci	control->int_ctl = V_INTR_MASKING_MASK;
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_ci	init_seg(&save->es);
131762306a36Sopenharmony_ci	init_seg(&save->ss);
131862306a36Sopenharmony_ci	init_seg(&save->ds);
131962306a36Sopenharmony_ci	init_seg(&save->fs);
132062306a36Sopenharmony_ci	init_seg(&save->gs);
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	save->cs.selector = 0xf000;
132362306a36Sopenharmony_ci	save->cs.base = 0xffff0000;
132462306a36Sopenharmony_ci	/* Executable/Readable Code Segment */
132562306a36Sopenharmony_ci	save->cs.attrib = SVM_SELECTOR_READ_MASK | SVM_SELECTOR_P_MASK |
132662306a36Sopenharmony_ci		SVM_SELECTOR_S_MASK | SVM_SELECTOR_CODE_MASK;
132762306a36Sopenharmony_ci	save->cs.limit = 0xffff;
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_ci	save->gdtr.base = 0;
133062306a36Sopenharmony_ci	save->gdtr.limit = 0xffff;
133162306a36Sopenharmony_ci	save->idtr.base = 0;
133262306a36Sopenharmony_ci	save->idtr.limit = 0xffff;
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	init_sys_seg(&save->ldtr, SEG_TYPE_LDT);
133562306a36Sopenharmony_ci	init_sys_seg(&save->tr, SEG_TYPE_BUSY_TSS16);
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci	if (npt_enabled) {
133862306a36Sopenharmony_ci		/* Setup VMCB for Nested Paging */
133962306a36Sopenharmony_ci		control->nested_ctl |= SVM_NESTED_CTL_NP_ENABLE;
134062306a36Sopenharmony_ci		svm_clr_intercept(svm, INTERCEPT_INVLPG);
134162306a36Sopenharmony_ci		clr_exception_intercept(svm, PF_VECTOR);
134262306a36Sopenharmony_ci		svm_clr_intercept(svm, INTERCEPT_CR3_READ);
134362306a36Sopenharmony_ci		svm_clr_intercept(svm, INTERCEPT_CR3_WRITE);
134462306a36Sopenharmony_ci		save->g_pat = vcpu->arch.pat;
134562306a36Sopenharmony_ci		save->cr3 = 0;
134662306a36Sopenharmony_ci	}
134762306a36Sopenharmony_ci	svm->current_vmcb->asid_generation = 0;
134862306a36Sopenharmony_ci	svm->asid = 0;
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_ci	svm->nested.vmcb12_gpa = INVALID_GPA;
135162306a36Sopenharmony_ci	svm->nested.last_vmcb12_gpa = INVALID_GPA;
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci	if (!kvm_pause_in_guest(vcpu->kvm)) {
135462306a36Sopenharmony_ci		control->pause_filter_count = pause_filter_count;
135562306a36Sopenharmony_ci		if (pause_filter_thresh)
135662306a36Sopenharmony_ci			control->pause_filter_thresh = pause_filter_thresh;
135762306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_PAUSE);
135862306a36Sopenharmony_ci	} else {
135962306a36Sopenharmony_ci		svm_clr_intercept(svm, INTERCEPT_PAUSE);
136062306a36Sopenharmony_ci	}
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci	svm_recalc_instruction_intercepts(vcpu, svm);
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci	/*
136562306a36Sopenharmony_ci	 * If the host supports V_SPEC_CTRL then disable the interception
136662306a36Sopenharmony_ci	 * of MSR_IA32_SPEC_CTRL.
136762306a36Sopenharmony_ci	 */
136862306a36Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_V_SPEC_CTRL))
136962306a36Sopenharmony_ci		set_msr_interception(vcpu, svm->msrpm, MSR_IA32_SPEC_CTRL, 1, 1);
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	if (kvm_vcpu_apicv_active(vcpu))
137262306a36Sopenharmony_ci		avic_init_vmcb(svm, vmcb);
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci	if (vnmi)
137562306a36Sopenharmony_ci		svm->vmcb->control.int_ctl |= V_NMI_ENABLE_MASK;
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	if (vgif) {
137862306a36Sopenharmony_ci		svm_clr_intercept(svm, INTERCEPT_STGI);
137962306a36Sopenharmony_ci		svm_clr_intercept(svm, INTERCEPT_CLGI);
138062306a36Sopenharmony_ci		svm->vmcb->control.int_ctl |= V_GIF_ENABLE_MASK;
138162306a36Sopenharmony_ci	}
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	if (sev_guest(vcpu->kvm))
138462306a36Sopenharmony_ci		sev_init_vmcb(svm);
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci	svm_hv_init_vmcb(vmcb);
138762306a36Sopenharmony_ci	init_vmcb_after_set_cpuid(vcpu);
138862306a36Sopenharmony_ci
138962306a36Sopenharmony_ci	vmcb_mark_all_dirty(vmcb);
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci	enable_gif(svm);
139262306a36Sopenharmony_ci}
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_cistatic void __svm_vcpu_reset(struct kvm_vcpu *vcpu)
139562306a36Sopenharmony_ci{
139662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
139762306a36Sopenharmony_ci
139862306a36Sopenharmony_ci	svm_vcpu_init_msrpm(vcpu, svm->msrpm);
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci	svm_init_osvw(vcpu);
140162306a36Sopenharmony_ci	vcpu->arch.microcode_version = 0x01000065;
140262306a36Sopenharmony_ci	svm->tsc_ratio_msr = kvm_caps.default_tsc_scaling_ratio;
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	svm->nmi_masked = false;
140562306a36Sopenharmony_ci	svm->awaiting_iret_completion = false;
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm))
140862306a36Sopenharmony_ci		sev_es_vcpu_reset(svm);
140962306a36Sopenharmony_ci}
141062306a36Sopenharmony_ci
141162306a36Sopenharmony_cistatic void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
141262306a36Sopenharmony_ci{
141362306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	svm->spec_ctrl = 0;
141662306a36Sopenharmony_ci	svm->virt_spec_ctrl = 0;
141762306a36Sopenharmony_ci
141862306a36Sopenharmony_ci	init_vmcb(vcpu);
141962306a36Sopenharmony_ci
142062306a36Sopenharmony_ci	if (!init_event)
142162306a36Sopenharmony_ci		__svm_vcpu_reset(vcpu);
142262306a36Sopenharmony_ci}
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_civoid svm_switch_vmcb(struct vcpu_svm *svm, struct kvm_vmcb_info *target_vmcb)
142562306a36Sopenharmony_ci{
142662306a36Sopenharmony_ci	svm->current_vmcb = target_vmcb;
142762306a36Sopenharmony_ci	svm->vmcb = target_vmcb->ptr;
142862306a36Sopenharmony_ci}
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_cistatic int svm_vcpu_create(struct kvm_vcpu *vcpu)
143162306a36Sopenharmony_ci{
143262306a36Sopenharmony_ci	struct vcpu_svm *svm;
143362306a36Sopenharmony_ci	struct page *vmcb01_page;
143462306a36Sopenharmony_ci	struct page *vmsa_page = NULL;
143562306a36Sopenharmony_ci	int err;
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_ci	BUILD_BUG_ON(offsetof(struct vcpu_svm, vcpu) != 0);
143862306a36Sopenharmony_ci	svm = to_svm(vcpu);
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci	err = -ENOMEM;
144162306a36Sopenharmony_ci	vmcb01_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
144262306a36Sopenharmony_ci	if (!vmcb01_page)
144362306a36Sopenharmony_ci		goto out;
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm)) {
144662306a36Sopenharmony_ci		/*
144762306a36Sopenharmony_ci		 * SEV-ES guests require a separate VMSA page used to contain
144862306a36Sopenharmony_ci		 * the encrypted register state of the guest.
144962306a36Sopenharmony_ci		 */
145062306a36Sopenharmony_ci		vmsa_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
145162306a36Sopenharmony_ci		if (!vmsa_page)
145262306a36Sopenharmony_ci			goto error_free_vmcb_page;
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci		/*
145562306a36Sopenharmony_ci		 * SEV-ES guests maintain an encrypted version of their FPU
145662306a36Sopenharmony_ci		 * state which is restored and saved on VMRUN and VMEXIT.
145762306a36Sopenharmony_ci		 * Mark vcpu->arch.guest_fpu->fpstate as scratch so it won't
145862306a36Sopenharmony_ci		 * do xsave/xrstor on it.
145962306a36Sopenharmony_ci		 */
146062306a36Sopenharmony_ci		fpstate_set_confidential(&vcpu->arch.guest_fpu);
146162306a36Sopenharmony_ci	}
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	err = avic_init_vcpu(svm);
146462306a36Sopenharmony_ci	if (err)
146562306a36Sopenharmony_ci		goto error_free_vmsa_page;
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	svm->msrpm = svm_vcpu_alloc_msrpm();
146862306a36Sopenharmony_ci	if (!svm->msrpm) {
146962306a36Sopenharmony_ci		err = -ENOMEM;
147062306a36Sopenharmony_ci		goto error_free_vmsa_page;
147162306a36Sopenharmony_ci	}
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci	svm->x2avic_msrs_intercepted = true;
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci	svm->vmcb01.ptr = page_address(vmcb01_page);
147662306a36Sopenharmony_ci	svm->vmcb01.pa = __sme_set(page_to_pfn(vmcb01_page) << PAGE_SHIFT);
147762306a36Sopenharmony_ci	svm_switch_vmcb(svm, &svm->vmcb01);
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	if (vmsa_page)
148062306a36Sopenharmony_ci		svm->sev_es.vmsa = page_address(vmsa_page);
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci	svm->guest_state_loaded = false;
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci	return 0;
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_cierror_free_vmsa_page:
148762306a36Sopenharmony_ci	if (vmsa_page)
148862306a36Sopenharmony_ci		__free_page(vmsa_page);
148962306a36Sopenharmony_cierror_free_vmcb_page:
149062306a36Sopenharmony_ci	__free_page(vmcb01_page);
149162306a36Sopenharmony_ciout:
149262306a36Sopenharmony_ci	return err;
149362306a36Sopenharmony_ci}
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_cistatic void svm_clear_current_vmcb(struct vmcb *vmcb)
149662306a36Sopenharmony_ci{
149762306a36Sopenharmony_ci	int i;
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci	for_each_online_cpu(i)
150062306a36Sopenharmony_ci		cmpxchg(per_cpu_ptr(&svm_data.current_vmcb, i), vmcb, NULL);
150162306a36Sopenharmony_ci}
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_cistatic void svm_vcpu_free(struct kvm_vcpu *vcpu)
150462306a36Sopenharmony_ci{
150562306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
150662306a36Sopenharmony_ci
150762306a36Sopenharmony_ci	/*
150862306a36Sopenharmony_ci	 * The vmcb page can be recycled, causing a false negative in
150962306a36Sopenharmony_ci	 * svm_vcpu_load(). So, ensure that no logical CPU has this
151062306a36Sopenharmony_ci	 * vmcb page recorded as its current vmcb.
151162306a36Sopenharmony_ci	 */
151262306a36Sopenharmony_ci	svm_clear_current_vmcb(svm->vmcb);
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_ci	svm_leave_nested(vcpu);
151562306a36Sopenharmony_ci	svm_free_nested(svm);
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci	sev_free_vcpu(vcpu);
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci	__free_page(pfn_to_page(__sme_clr(svm->vmcb01.pa) >> PAGE_SHIFT));
152062306a36Sopenharmony_ci	__free_pages(virt_to_page(svm->msrpm), get_order(MSRPM_SIZE));
152162306a36Sopenharmony_ci}
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_cistatic void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
152462306a36Sopenharmony_ci{
152562306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
152662306a36Sopenharmony_ci	struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm))
152962306a36Sopenharmony_ci		sev_es_unmap_ghcb(svm);
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci	if (svm->guest_state_loaded)
153262306a36Sopenharmony_ci		return;
153362306a36Sopenharmony_ci
153462306a36Sopenharmony_ci	/*
153562306a36Sopenharmony_ci	 * Save additional host state that will be restored on VMEXIT (sev-es)
153662306a36Sopenharmony_ci	 * or subsequent vmload of host save area.
153762306a36Sopenharmony_ci	 */
153862306a36Sopenharmony_ci	vmsave(sd->save_area_pa);
153962306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm)) {
154062306a36Sopenharmony_ci		struct sev_es_save_area *hostsa;
154162306a36Sopenharmony_ci		hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400);
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci		sev_es_prepare_switch_to_guest(hostsa);
154462306a36Sopenharmony_ci	}
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	if (tsc_scaling)
154762306a36Sopenharmony_ci		__svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio);
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	/*
155062306a36Sopenharmony_ci	 * TSC_AUX is always virtualized for SEV-ES guests when the feature is
155162306a36Sopenharmony_ci	 * available. The user return MSR support is not required in this case
155262306a36Sopenharmony_ci	 * because TSC_AUX is restored on #VMEXIT from the host save area
155362306a36Sopenharmony_ci	 * (which has been initialized in svm_hardware_enable()).
155462306a36Sopenharmony_ci	 */
155562306a36Sopenharmony_ci	if (likely(tsc_aux_uret_slot >= 0) &&
155662306a36Sopenharmony_ci	    (!boot_cpu_has(X86_FEATURE_V_TSC_AUX) || !sev_es_guest(vcpu->kvm)))
155762306a36Sopenharmony_ci		kvm_set_user_return_msr(tsc_aux_uret_slot, svm->tsc_aux, -1ull);
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	svm->guest_state_loaded = true;
156062306a36Sopenharmony_ci}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_cistatic void svm_prepare_host_switch(struct kvm_vcpu *vcpu)
156362306a36Sopenharmony_ci{
156462306a36Sopenharmony_ci	to_svm(vcpu)->guest_state_loaded = false;
156562306a36Sopenharmony_ci}
156662306a36Sopenharmony_ci
156762306a36Sopenharmony_cistatic void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
156862306a36Sopenharmony_ci{
156962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
157062306a36Sopenharmony_ci	struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_ci	if (sd->current_vmcb != svm->vmcb) {
157362306a36Sopenharmony_ci		sd->current_vmcb = svm->vmcb;
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ci		if (!cpu_feature_enabled(X86_FEATURE_IBPB_ON_VMEXIT))
157662306a36Sopenharmony_ci			indirect_branch_prediction_barrier();
157762306a36Sopenharmony_ci	}
157862306a36Sopenharmony_ci	if (kvm_vcpu_apicv_active(vcpu))
157962306a36Sopenharmony_ci		avic_vcpu_load(vcpu, cpu);
158062306a36Sopenharmony_ci}
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_cistatic void svm_vcpu_put(struct kvm_vcpu *vcpu)
158362306a36Sopenharmony_ci{
158462306a36Sopenharmony_ci	if (kvm_vcpu_apicv_active(vcpu))
158562306a36Sopenharmony_ci		avic_vcpu_put(vcpu);
158662306a36Sopenharmony_ci
158762306a36Sopenharmony_ci	svm_prepare_host_switch(vcpu);
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_ci	++vcpu->stat.host_state_reload;
159062306a36Sopenharmony_ci}
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_cistatic unsigned long svm_get_rflags(struct kvm_vcpu *vcpu)
159362306a36Sopenharmony_ci{
159462306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
159562306a36Sopenharmony_ci	unsigned long rflags = svm->vmcb->save.rflags;
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	if (svm->nmi_singlestep) {
159862306a36Sopenharmony_ci		/* Hide our flags if they were not set by the guest */
159962306a36Sopenharmony_ci		if (!(svm->nmi_singlestep_guest_rflags & X86_EFLAGS_TF))
160062306a36Sopenharmony_ci			rflags &= ~X86_EFLAGS_TF;
160162306a36Sopenharmony_ci		if (!(svm->nmi_singlestep_guest_rflags & X86_EFLAGS_RF))
160262306a36Sopenharmony_ci			rflags &= ~X86_EFLAGS_RF;
160362306a36Sopenharmony_ci	}
160462306a36Sopenharmony_ci	return rflags;
160562306a36Sopenharmony_ci}
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_cistatic void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
160862306a36Sopenharmony_ci{
160962306a36Sopenharmony_ci	if (to_svm(vcpu)->nmi_singlestep)
161062306a36Sopenharmony_ci		rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
161162306a36Sopenharmony_ci
161262306a36Sopenharmony_ci       /*
161362306a36Sopenharmony_ci        * Any change of EFLAGS.VM is accompanied by a reload of SS
161462306a36Sopenharmony_ci        * (caused by either a task switch or an inter-privilege IRET),
161562306a36Sopenharmony_ci        * so we do not need to update the CPL here.
161662306a36Sopenharmony_ci        */
161762306a36Sopenharmony_ci	to_svm(vcpu)->vmcb->save.rflags = rflags;
161862306a36Sopenharmony_ci}
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_cistatic bool svm_get_if_flag(struct kvm_vcpu *vcpu)
162162306a36Sopenharmony_ci{
162262306a36Sopenharmony_ci	struct vmcb *vmcb = to_svm(vcpu)->vmcb;
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	return sev_es_guest(vcpu->kvm)
162562306a36Sopenharmony_ci		? vmcb->control.int_state & SVM_GUEST_INTERRUPT_MASK
162662306a36Sopenharmony_ci		: kvm_get_rflags(vcpu) & X86_EFLAGS_IF;
162762306a36Sopenharmony_ci}
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_cistatic void svm_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
163062306a36Sopenharmony_ci{
163162306a36Sopenharmony_ci	kvm_register_mark_available(vcpu, reg);
163262306a36Sopenharmony_ci
163362306a36Sopenharmony_ci	switch (reg) {
163462306a36Sopenharmony_ci	case VCPU_EXREG_PDPTR:
163562306a36Sopenharmony_ci		/*
163662306a36Sopenharmony_ci		 * When !npt_enabled, mmu->pdptrs[] is already available since
163762306a36Sopenharmony_ci		 * it is always updated per SDM when moving to CRs.
163862306a36Sopenharmony_ci		 */
163962306a36Sopenharmony_ci		if (npt_enabled)
164062306a36Sopenharmony_ci			load_pdptrs(vcpu, kvm_read_cr3(vcpu));
164162306a36Sopenharmony_ci		break;
164262306a36Sopenharmony_ci	default:
164362306a36Sopenharmony_ci		KVM_BUG_ON(1, vcpu->kvm);
164462306a36Sopenharmony_ci	}
164562306a36Sopenharmony_ci}
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_cistatic void svm_set_vintr(struct vcpu_svm *svm)
164862306a36Sopenharmony_ci{
164962306a36Sopenharmony_ci	struct vmcb_control_area *control;
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	/*
165262306a36Sopenharmony_ci	 * The following fields are ignored when AVIC is enabled
165362306a36Sopenharmony_ci	 */
165462306a36Sopenharmony_ci	WARN_ON(kvm_vcpu_apicv_activated(&svm->vcpu));
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci	svm_set_intercept(svm, INTERCEPT_VINTR);
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci	/*
165962306a36Sopenharmony_ci	 * Recalculating intercepts may have cleared the VINTR intercept.  If
166062306a36Sopenharmony_ci	 * V_INTR_MASKING is enabled in vmcb12, then the effective RFLAGS.IF
166162306a36Sopenharmony_ci	 * for L1 physical interrupts is L1's RFLAGS.IF at the time of VMRUN.
166262306a36Sopenharmony_ci	 * Requesting an interrupt window if save.RFLAGS.IF=0 is pointless as
166362306a36Sopenharmony_ci	 * interrupts will never be unblocked while L2 is running.
166462306a36Sopenharmony_ci	 */
166562306a36Sopenharmony_ci	if (!svm_is_intercept(svm, INTERCEPT_VINTR))
166662306a36Sopenharmony_ci		return;
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci	/*
166962306a36Sopenharmony_ci	 * This is just a dummy VINTR to actually cause a vmexit to happen.
167062306a36Sopenharmony_ci	 * Actual injection of virtual interrupts happens through EVENTINJ.
167162306a36Sopenharmony_ci	 */
167262306a36Sopenharmony_ci	control = &svm->vmcb->control;
167362306a36Sopenharmony_ci	control->int_vector = 0x0;
167462306a36Sopenharmony_ci	control->int_ctl &= ~V_INTR_PRIO_MASK;
167562306a36Sopenharmony_ci	control->int_ctl |= V_IRQ_MASK |
167662306a36Sopenharmony_ci		((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT);
167762306a36Sopenharmony_ci	vmcb_mark_dirty(svm->vmcb, VMCB_INTR);
167862306a36Sopenharmony_ci}
167962306a36Sopenharmony_ci
168062306a36Sopenharmony_cistatic void svm_clear_vintr(struct vcpu_svm *svm)
168162306a36Sopenharmony_ci{
168262306a36Sopenharmony_ci	svm_clr_intercept(svm, INTERCEPT_VINTR);
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci	/* Drop int_ctl fields related to VINTR injection.  */
168562306a36Sopenharmony_ci	svm->vmcb->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK;
168662306a36Sopenharmony_ci	if (is_guest_mode(&svm->vcpu)) {
168762306a36Sopenharmony_ci		svm->vmcb01.ptr->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK;
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci		WARN_ON((svm->vmcb->control.int_ctl & V_TPR_MASK) !=
169062306a36Sopenharmony_ci			(svm->nested.ctl.int_ctl & V_TPR_MASK));
169162306a36Sopenharmony_ci
169262306a36Sopenharmony_ci		svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl &
169362306a36Sopenharmony_ci			V_IRQ_INJECTION_BITS_MASK;
169462306a36Sopenharmony_ci
169562306a36Sopenharmony_ci		svm->vmcb->control.int_vector = svm->nested.ctl.int_vector;
169662306a36Sopenharmony_ci	}
169762306a36Sopenharmony_ci
169862306a36Sopenharmony_ci	vmcb_mark_dirty(svm->vmcb, VMCB_INTR);
169962306a36Sopenharmony_ci}
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_cistatic struct vmcb_seg *svm_seg(struct kvm_vcpu *vcpu, int seg)
170262306a36Sopenharmony_ci{
170362306a36Sopenharmony_ci	struct vmcb_save_area *save = &to_svm(vcpu)->vmcb->save;
170462306a36Sopenharmony_ci	struct vmcb_save_area *save01 = &to_svm(vcpu)->vmcb01.ptr->save;
170562306a36Sopenharmony_ci
170662306a36Sopenharmony_ci	switch (seg) {
170762306a36Sopenharmony_ci	case VCPU_SREG_CS: return &save->cs;
170862306a36Sopenharmony_ci	case VCPU_SREG_DS: return &save->ds;
170962306a36Sopenharmony_ci	case VCPU_SREG_ES: return &save->es;
171062306a36Sopenharmony_ci	case VCPU_SREG_FS: return &save01->fs;
171162306a36Sopenharmony_ci	case VCPU_SREG_GS: return &save01->gs;
171262306a36Sopenharmony_ci	case VCPU_SREG_SS: return &save->ss;
171362306a36Sopenharmony_ci	case VCPU_SREG_TR: return &save01->tr;
171462306a36Sopenharmony_ci	case VCPU_SREG_LDTR: return &save01->ldtr;
171562306a36Sopenharmony_ci	}
171662306a36Sopenharmony_ci	BUG();
171762306a36Sopenharmony_ci	return NULL;
171862306a36Sopenharmony_ci}
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_cistatic u64 svm_get_segment_base(struct kvm_vcpu *vcpu, int seg)
172162306a36Sopenharmony_ci{
172262306a36Sopenharmony_ci	struct vmcb_seg *s = svm_seg(vcpu, seg);
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	return s->base;
172562306a36Sopenharmony_ci}
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_cistatic void svm_get_segment(struct kvm_vcpu *vcpu,
172862306a36Sopenharmony_ci			    struct kvm_segment *var, int seg)
172962306a36Sopenharmony_ci{
173062306a36Sopenharmony_ci	struct vmcb_seg *s = svm_seg(vcpu, seg);
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_ci	var->base = s->base;
173362306a36Sopenharmony_ci	var->limit = s->limit;
173462306a36Sopenharmony_ci	var->selector = s->selector;
173562306a36Sopenharmony_ci	var->type = s->attrib & SVM_SELECTOR_TYPE_MASK;
173662306a36Sopenharmony_ci	var->s = (s->attrib >> SVM_SELECTOR_S_SHIFT) & 1;
173762306a36Sopenharmony_ci	var->dpl = (s->attrib >> SVM_SELECTOR_DPL_SHIFT) & 3;
173862306a36Sopenharmony_ci	var->present = (s->attrib >> SVM_SELECTOR_P_SHIFT) & 1;
173962306a36Sopenharmony_ci	var->avl = (s->attrib >> SVM_SELECTOR_AVL_SHIFT) & 1;
174062306a36Sopenharmony_ci	var->l = (s->attrib >> SVM_SELECTOR_L_SHIFT) & 1;
174162306a36Sopenharmony_ci	var->db = (s->attrib >> SVM_SELECTOR_DB_SHIFT) & 1;
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci	/*
174462306a36Sopenharmony_ci	 * AMD CPUs circa 2014 track the G bit for all segments except CS.
174562306a36Sopenharmony_ci	 * However, the SVM spec states that the G bit is not observed by the
174662306a36Sopenharmony_ci	 * CPU, and some VMware virtual CPUs drop the G bit for all segments.
174762306a36Sopenharmony_ci	 * So let's synthesize a legal G bit for all segments, this helps
174862306a36Sopenharmony_ci	 * running KVM nested. It also helps cross-vendor migration, because
174962306a36Sopenharmony_ci	 * Intel's vmentry has a check on the 'G' bit.
175062306a36Sopenharmony_ci	 */
175162306a36Sopenharmony_ci	var->g = s->limit > 0xfffff;
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	/*
175462306a36Sopenharmony_ci	 * AMD's VMCB does not have an explicit unusable field, so emulate it
175562306a36Sopenharmony_ci	 * for cross vendor migration purposes by "not present"
175662306a36Sopenharmony_ci	 */
175762306a36Sopenharmony_ci	var->unusable = !var->present;
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_ci	switch (seg) {
176062306a36Sopenharmony_ci	case VCPU_SREG_TR:
176162306a36Sopenharmony_ci		/*
176262306a36Sopenharmony_ci		 * Work around a bug where the busy flag in the tr selector
176362306a36Sopenharmony_ci		 * isn't exposed
176462306a36Sopenharmony_ci		 */
176562306a36Sopenharmony_ci		var->type |= 0x2;
176662306a36Sopenharmony_ci		break;
176762306a36Sopenharmony_ci	case VCPU_SREG_DS:
176862306a36Sopenharmony_ci	case VCPU_SREG_ES:
176962306a36Sopenharmony_ci	case VCPU_SREG_FS:
177062306a36Sopenharmony_ci	case VCPU_SREG_GS:
177162306a36Sopenharmony_ci		/*
177262306a36Sopenharmony_ci		 * The accessed bit must always be set in the segment
177362306a36Sopenharmony_ci		 * descriptor cache, although it can be cleared in the
177462306a36Sopenharmony_ci		 * descriptor, the cached bit always remains at 1. Since
177562306a36Sopenharmony_ci		 * Intel has a check on this, set it here to support
177662306a36Sopenharmony_ci		 * cross-vendor migration.
177762306a36Sopenharmony_ci		 */
177862306a36Sopenharmony_ci		if (!var->unusable)
177962306a36Sopenharmony_ci			var->type |= 0x1;
178062306a36Sopenharmony_ci		break;
178162306a36Sopenharmony_ci	case VCPU_SREG_SS:
178262306a36Sopenharmony_ci		/*
178362306a36Sopenharmony_ci		 * On AMD CPUs sometimes the DB bit in the segment
178462306a36Sopenharmony_ci		 * descriptor is left as 1, although the whole segment has
178562306a36Sopenharmony_ci		 * been made unusable. Clear it here to pass an Intel VMX
178662306a36Sopenharmony_ci		 * entry check when cross vendor migrating.
178762306a36Sopenharmony_ci		 */
178862306a36Sopenharmony_ci		if (var->unusable)
178962306a36Sopenharmony_ci			var->db = 0;
179062306a36Sopenharmony_ci		/* This is symmetric with svm_set_segment() */
179162306a36Sopenharmony_ci		var->dpl = to_svm(vcpu)->vmcb->save.cpl;
179262306a36Sopenharmony_ci		break;
179362306a36Sopenharmony_ci	}
179462306a36Sopenharmony_ci}
179562306a36Sopenharmony_ci
179662306a36Sopenharmony_cistatic int svm_get_cpl(struct kvm_vcpu *vcpu)
179762306a36Sopenharmony_ci{
179862306a36Sopenharmony_ci	struct vmcb_save_area *save = &to_svm(vcpu)->vmcb->save;
179962306a36Sopenharmony_ci
180062306a36Sopenharmony_ci	return save->cpl;
180162306a36Sopenharmony_ci}
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_cistatic void svm_get_cs_db_l_bits(struct kvm_vcpu *vcpu, int *db, int *l)
180462306a36Sopenharmony_ci{
180562306a36Sopenharmony_ci	struct kvm_segment cs;
180662306a36Sopenharmony_ci
180762306a36Sopenharmony_ci	svm_get_segment(vcpu, &cs, VCPU_SREG_CS);
180862306a36Sopenharmony_ci	*db = cs.db;
180962306a36Sopenharmony_ci	*l = cs.l;
181062306a36Sopenharmony_ci}
181162306a36Sopenharmony_ci
181262306a36Sopenharmony_cistatic void svm_get_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
181362306a36Sopenharmony_ci{
181462306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	dt->size = svm->vmcb->save.idtr.limit;
181762306a36Sopenharmony_ci	dt->address = svm->vmcb->save.idtr.base;
181862306a36Sopenharmony_ci}
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_cistatic void svm_set_idt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
182162306a36Sopenharmony_ci{
182262306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci	svm->vmcb->save.idtr.limit = dt->size;
182562306a36Sopenharmony_ci	svm->vmcb->save.idtr.base = dt->address ;
182662306a36Sopenharmony_ci	vmcb_mark_dirty(svm->vmcb, VMCB_DT);
182762306a36Sopenharmony_ci}
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_cistatic void svm_get_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
183062306a36Sopenharmony_ci{
183162306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ci	dt->size = svm->vmcb->save.gdtr.limit;
183462306a36Sopenharmony_ci	dt->address = svm->vmcb->save.gdtr.base;
183562306a36Sopenharmony_ci}
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_cistatic void svm_set_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
183862306a36Sopenharmony_ci{
183962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci	svm->vmcb->save.gdtr.limit = dt->size;
184262306a36Sopenharmony_ci	svm->vmcb->save.gdtr.base = dt->address ;
184362306a36Sopenharmony_ci	vmcb_mark_dirty(svm->vmcb, VMCB_DT);
184462306a36Sopenharmony_ci}
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_cistatic void sev_post_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
184762306a36Sopenharmony_ci{
184862306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
184962306a36Sopenharmony_ci
185062306a36Sopenharmony_ci	/*
185162306a36Sopenharmony_ci	 * For guests that don't set guest_state_protected, the cr3 update is
185262306a36Sopenharmony_ci	 * handled via kvm_mmu_load() while entering the guest. For guests
185362306a36Sopenharmony_ci	 * that do (SEV-ES/SEV-SNP), the cr3 update needs to be written to
185462306a36Sopenharmony_ci	 * VMCB save area now, since the save area will become the initial
185562306a36Sopenharmony_ci	 * contents of the VMSA, and future VMCB save area updates won't be
185662306a36Sopenharmony_ci	 * seen.
185762306a36Sopenharmony_ci	 */
185862306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm)) {
185962306a36Sopenharmony_ci		svm->vmcb->save.cr3 = cr3;
186062306a36Sopenharmony_ci		vmcb_mark_dirty(svm->vmcb, VMCB_CR);
186162306a36Sopenharmony_ci	}
186262306a36Sopenharmony_ci}
186362306a36Sopenharmony_ci
186462306a36Sopenharmony_cistatic bool svm_is_valid_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
186562306a36Sopenharmony_ci{
186662306a36Sopenharmony_ci	return true;
186762306a36Sopenharmony_ci}
186862306a36Sopenharmony_ci
186962306a36Sopenharmony_civoid svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
187062306a36Sopenharmony_ci{
187162306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
187262306a36Sopenharmony_ci	u64 hcr0 = cr0;
187362306a36Sopenharmony_ci	bool old_paging = is_paging(vcpu);
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_ci#ifdef CONFIG_X86_64
187662306a36Sopenharmony_ci	if (vcpu->arch.efer & EFER_LME) {
187762306a36Sopenharmony_ci		if (!is_paging(vcpu) && (cr0 & X86_CR0_PG)) {
187862306a36Sopenharmony_ci			vcpu->arch.efer |= EFER_LMA;
187962306a36Sopenharmony_ci			if (!vcpu->arch.guest_state_protected)
188062306a36Sopenharmony_ci				svm->vmcb->save.efer |= EFER_LMA | EFER_LME;
188162306a36Sopenharmony_ci		}
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci		if (is_paging(vcpu) && !(cr0 & X86_CR0_PG)) {
188462306a36Sopenharmony_ci			vcpu->arch.efer &= ~EFER_LMA;
188562306a36Sopenharmony_ci			if (!vcpu->arch.guest_state_protected)
188662306a36Sopenharmony_ci				svm->vmcb->save.efer &= ~(EFER_LMA | EFER_LME);
188762306a36Sopenharmony_ci		}
188862306a36Sopenharmony_ci	}
188962306a36Sopenharmony_ci#endif
189062306a36Sopenharmony_ci	vcpu->arch.cr0 = cr0;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	if (!npt_enabled) {
189362306a36Sopenharmony_ci		hcr0 |= X86_CR0_PG | X86_CR0_WP;
189462306a36Sopenharmony_ci		if (old_paging != is_paging(vcpu))
189562306a36Sopenharmony_ci			svm_set_cr4(vcpu, kvm_read_cr4(vcpu));
189662306a36Sopenharmony_ci	}
189762306a36Sopenharmony_ci
189862306a36Sopenharmony_ci	/*
189962306a36Sopenharmony_ci	 * re-enable caching here because the QEMU bios
190062306a36Sopenharmony_ci	 * does not do it - this results in some delay at
190162306a36Sopenharmony_ci	 * reboot
190262306a36Sopenharmony_ci	 */
190362306a36Sopenharmony_ci	if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED))
190462306a36Sopenharmony_ci		hcr0 &= ~(X86_CR0_CD | X86_CR0_NW);
190562306a36Sopenharmony_ci
190662306a36Sopenharmony_ci	svm->vmcb->save.cr0 = hcr0;
190762306a36Sopenharmony_ci	vmcb_mark_dirty(svm->vmcb, VMCB_CR);
190862306a36Sopenharmony_ci
190962306a36Sopenharmony_ci	/*
191062306a36Sopenharmony_ci	 * SEV-ES guests must always keep the CR intercepts cleared. CR
191162306a36Sopenharmony_ci	 * tracking is done using the CR write traps.
191262306a36Sopenharmony_ci	 */
191362306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm))
191462306a36Sopenharmony_ci		return;
191562306a36Sopenharmony_ci
191662306a36Sopenharmony_ci	if (hcr0 == cr0) {
191762306a36Sopenharmony_ci		/* Selective CR0 write remains on.  */
191862306a36Sopenharmony_ci		svm_clr_intercept(svm, INTERCEPT_CR0_READ);
191962306a36Sopenharmony_ci		svm_clr_intercept(svm, INTERCEPT_CR0_WRITE);
192062306a36Sopenharmony_ci	} else {
192162306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_CR0_READ);
192262306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_CR0_WRITE);
192362306a36Sopenharmony_ci	}
192462306a36Sopenharmony_ci}
192562306a36Sopenharmony_ci
192662306a36Sopenharmony_cistatic bool svm_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
192762306a36Sopenharmony_ci{
192862306a36Sopenharmony_ci	return true;
192962306a36Sopenharmony_ci}
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_civoid svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
193262306a36Sopenharmony_ci{
193362306a36Sopenharmony_ci	unsigned long host_cr4_mce = cr4_read_shadow() & X86_CR4_MCE;
193462306a36Sopenharmony_ci	unsigned long old_cr4 = vcpu->arch.cr4;
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci	if (npt_enabled && ((old_cr4 ^ cr4) & X86_CR4_PGE))
193762306a36Sopenharmony_ci		svm_flush_tlb_current(vcpu);
193862306a36Sopenharmony_ci
193962306a36Sopenharmony_ci	vcpu->arch.cr4 = cr4;
194062306a36Sopenharmony_ci	if (!npt_enabled) {
194162306a36Sopenharmony_ci		cr4 |= X86_CR4_PAE;
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci		if (!is_paging(vcpu))
194462306a36Sopenharmony_ci			cr4 &= ~(X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_PKE);
194562306a36Sopenharmony_ci	}
194662306a36Sopenharmony_ci	cr4 |= host_cr4_mce;
194762306a36Sopenharmony_ci	to_svm(vcpu)->vmcb->save.cr4 = cr4;
194862306a36Sopenharmony_ci	vmcb_mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci	if ((cr4 ^ old_cr4) & (X86_CR4_OSXSAVE | X86_CR4_PKE))
195162306a36Sopenharmony_ci		kvm_update_cpuid_runtime(vcpu);
195262306a36Sopenharmony_ci}
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_cistatic void svm_set_segment(struct kvm_vcpu *vcpu,
195562306a36Sopenharmony_ci			    struct kvm_segment *var, int seg)
195662306a36Sopenharmony_ci{
195762306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
195862306a36Sopenharmony_ci	struct vmcb_seg *s = svm_seg(vcpu, seg);
195962306a36Sopenharmony_ci
196062306a36Sopenharmony_ci	s->base = var->base;
196162306a36Sopenharmony_ci	s->limit = var->limit;
196262306a36Sopenharmony_ci	s->selector = var->selector;
196362306a36Sopenharmony_ci	s->attrib = (var->type & SVM_SELECTOR_TYPE_MASK);
196462306a36Sopenharmony_ci	s->attrib |= (var->s & 1) << SVM_SELECTOR_S_SHIFT;
196562306a36Sopenharmony_ci	s->attrib |= (var->dpl & 3) << SVM_SELECTOR_DPL_SHIFT;
196662306a36Sopenharmony_ci	s->attrib |= ((var->present & 1) && !var->unusable) << SVM_SELECTOR_P_SHIFT;
196762306a36Sopenharmony_ci	s->attrib |= (var->avl & 1) << SVM_SELECTOR_AVL_SHIFT;
196862306a36Sopenharmony_ci	s->attrib |= (var->l & 1) << SVM_SELECTOR_L_SHIFT;
196962306a36Sopenharmony_ci	s->attrib |= (var->db & 1) << SVM_SELECTOR_DB_SHIFT;
197062306a36Sopenharmony_ci	s->attrib |= (var->g & 1) << SVM_SELECTOR_G_SHIFT;
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	/*
197362306a36Sopenharmony_ci	 * This is always accurate, except if SYSRET returned to a segment
197462306a36Sopenharmony_ci	 * with SS.DPL != 3.  Intel does not have this quirk, and always
197562306a36Sopenharmony_ci	 * forces SS.DPL to 3 on sysret, so we ignore that case; fixing it
197662306a36Sopenharmony_ci	 * would entail passing the CPL to userspace and back.
197762306a36Sopenharmony_ci	 */
197862306a36Sopenharmony_ci	if (seg == VCPU_SREG_SS)
197962306a36Sopenharmony_ci		/* This is symmetric with svm_get_segment() */
198062306a36Sopenharmony_ci		svm->vmcb->save.cpl = (var->dpl & 3);
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci	vmcb_mark_dirty(svm->vmcb, VMCB_SEG);
198362306a36Sopenharmony_ci}
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_cistatic void svm_update_exception_bitmap(struct kvm_vcpu *vcpu)
198662306a36Sopenharmony_ci{
198762306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci	clr_exception_intercept(svm, BP_VECTOR);
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_ci	if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
199262306a36Sopenharmony_ci		if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
199362306a36Sopenharmony_ci			set_exception_intercept(svm, BP_VECTOR);
199462306a36Sopenharmony_ci	}
199562306a36Sopenharmony_ci}
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_cistatic void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd)
199862306a36Sopenharmony_ci{
199962306a36Sopenharmony_ci	if (sd->next_asid > sd->max_asid) {
200062306a36Sopenharmony_ci		++sd->asid_generation;
200162306a36Sopenharmony_ci		sd->next_asid = sd->min_asid;
200262306a36Sopenharmony_ci		svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
200362306a36Sopenharmony_ci		vmcb_mark_dirty(svm->vmcb, VMCB_ASID);
200462306a36Sopenharmony_ci	}
200562306a36Sopenharmony_ci
200662306a36Sopenharmony_ci	svm->current_vmcb->asid_generation = sd->asid_generation;
200762306a36Sopenharmony_ci	svm->asid = sd->next_asid++;
200862306a36Sopenharmony_ci}
200962306a36Sopenharmony_ci
201062306a36Sopenharmony_cistatic void svm_set_dr6(struct vcpu_svm *svm, unsigned long value)
201162306a36Sopenharmony_ci{
201262306a36Sopenharmony_ci	struct vmcb *vmcb = svm->vmcb;
201362306a36Sopenharmony_ci
201462306a36Sopenharmony_ci	if (svm->vcpu.arch.guest_state_protected)
201562306a36Sopenharmony_ci		return;
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ci	if (unlikely(value != vmcb->save.dr6)) {
201862306a36Sopenharmony_ci		vmcb->save.dr6 = value;
201962306a36Sopenharmony_ci		vmcb_mark_dirty(vmcb, VMCB_DR);
202062306a36Sopenharmony_ci	}
202162306a36Sopenharmony_ci}
202262306a36Sopenharmony_ci
202362306a36Sopenharmony_cistatic void svm_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
202462306a36Sopenharmony_ci{
202562306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci	if (WARN_ON_ONCE(sev_es_guest(vcpu->kvm)))
202862306a36Sopenharmony_ci		return;
202962306a36Sopenharmony_ci
203062306a36Sopenharmony_ci	get_debugreg(vcpu->arch.db[0], 0);
203162306a36Sopenharmony_ci	get_debugreg(vcpu->arch.db[1], 1);
203262306a36Sopenharmony_ci	get_debugreg(vcpu->arch.db[2], 2);
203362306a36Sopenharmony_ci	get_debugreg(vcpu->arch.db[3], 3);
203462306a36Sopenharmony_ci	/*
203562306a36Sopenharmony_ci	 * We cannot reset svm->vmcb->save.dr6 to DR6_ACTIVE_LOW here,
203662306a36Sopenharmony_ci	 * because db_interception might need it.  We can do it before vmentry.
203762306a36Sopenharmony_ci	 */
203862306a36Sopenharmony_ci	vcpu->arch.dr6 = svm->vmcb->save.dr6;
203962306a36Sopenharmony_ci	vcpu->arch.dr7 = svm->vmcb->save.dr7;
204062306a36Sopenharmony_ci	vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_WONT_EXIT;
204162306a36Sopenharmony_ci	set_dr_intercepts(svm);
204262306a36Sopenharmony_ci}
204362306a36Sopenharmony_ci
204462306a36Sopenharmony_cistatic void svm_set_dr7(struct kvm_vcpu *vcpu, unsigned long value)
204562306a36Sopenharmony_ci{
204662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
204762306a36Sopenharmony_ci
204862306a36Sopenharmony_ci	if (vcpu->arch.guest_state_protected)
204962306a36Sopenharmony_ci		return;
205062306a36Sopenharmony_ci
205162306a36Sopenharmony_ci	svm->vmcb->save.dr7 = value;
205262306a36Sopenharmony_ci	vmcb_mark_dirty(svm->vmcb, VMCB_DR);
205362306a36Sopenharmony_ci}
205462306a36Sopenharmony_ci
205562306a36Sopenharmony_cistatic int pf_interception(struct kvm_vcpu *vcpu)
205662306a36Sopenharmony_ci{
205762306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
205862306a36Sopenharmony_ci
205962306a36Sopenharmony_ci	u64 fault_address = svm->vmcb->control.exit_info_2;
206062306a36Sopenharmony_ci	u64 error_code = svm->vmcb->control.exit_info_1;
206162306a36Sopenharmony_ci
206262306a36Sopenharmony_ci	return kvm_handle_page_fault(vcpu, error_code, fault_address,
206362306a36Sopenharmony_ci			static_cpu_has(X86_FEATURE_DECODEASSISTS) ?
206462306a36Sopenharmony_ci			svm->vmcb->control.insn_bytes : NULL,
206562306a36Sopenharmony_ci			svm->vmcb->control.insn_len);
206662306a36Sopenharmony_ci}
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_cistatic int npf_interception(struct kvm_vcpu *vcpu)
206962306a36Sopenharmony_ci{
207062306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
207162306a36Sopenharmony_ci
207262306a36Sopenharmony_ci	u64 fault_address = svm->vmcb->control.exit_info_2;
207362306a36Sopenharmony_ci	u64 error_code = svm->vmcb->control.exit_info_1;
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci	trace_kvm_page_fault(vcpu, fault_address, error_code);
207662306a36Sopenharmony_ci	return kvm_mmu_page_fault(vcpu, fault_address, error_code,
207762306a36Sopenharmony_ci			static_cpu_has(X86_FEATURE_DECODEASSISTS) ?
207862306a36Sopenharmony_ci			svm->vmcb->control.insn_bytes : NULL,
207962306a36Sopenharmony_ci			svm->vmcb->control.insn_len);
208062306a36Sopenharmony_ci}
208162306a36Sopenharmony_ci
208262306a36Sopenharmony_cistatic int db_interception(struct kvm_vcpu *vcpu)
208362306a36Sopenharmony_ci{
208462306a36Sopenharmony_ci	struct kvm_run *kvm_run = vcpu->run;
208562306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci	if (!(vcpu->guest_debug &
208862306a36Sopenharmony_ci	      (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) &&
208962306a36Sopenharmony_ci		!svm->nmi_singlestep) {
209062306a36Sopenharmony_ci		u32 payload = svm->vmcb->save.dr6 ^ DR6_ACTIVE_LOW;
209162306a36Sopenharmony_ci		kvm_queue_exception_p(vcpu, DB_VECTOR, payload);
209262306a36Sopenharmony_ci		return 1;
209362306a36Sopenharmony_ci	}
209462306a36Sopenharmony_ci
209562306a36Sopenharmony_ci	if (svm->nmi_singlestep) {
209662306a36Sopenharmony_ci		disable_nmi_singlestep(svm);
209762306a36Sopenharmony_ci		/* Make sure we check for pending NMIs upon entry */
209862306a36Sopenharmony_ci		kvm_make_request(KVM_REQ_EVENT, vcpu);
209962306a36Sopenharmony_ci	}
210062306a36Sopenharmony_ci
210162306a36Sopenharmony_ci	if (vcpu->guest_debug &
210262306a36Sopenharmony_ci	    (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)) {
210362306a36Sopenharmony_ci		kvm_run->exit_reason = KVM_EXIT_DEBUG;
210462306a36Sopenharmony_ci		kvm_run->debug.arch.dr6 = svm->vmcb->save.dr6;
210562306a36Sopenharmony_ci		kvm_run->debug.arch.dr7 = svm->vmcb->save.dr7;
210662306a36Sopenharmony_ci		kvm_run->debug.arch.pc =
210762306a36Sopenharmony_ci			svm->vmcb->save.cs.base + svm->vmcb->save.rip;
210862306a36Sopenharmony_ci		kvm_run->debug.arch.exception = DB_VECTOR;
210962306a36Sopenharmony_ci		return 0;
211062306a36Sopenharmony_ci	}
211162306a36Sopenharmony_ci
211262306a36Sopenharmony_ci	return 1;
211362306a36Sopenharmony_ci}
211462306a36Sopenharmony_ci
211562306a36Sopenharmony_cistatic int bp_interception(struct kvm_vcpu *vcpu)
211662306a36Sopenharmony_ci{
211762306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
211862306a36Sopenharmony_ci	struct kvm_run *kvm_run = vcpu->run;
211962306a36Sopenharmony_ci
212062306a36Sopenharmony_ci	kvm_run->exit_reason = KVM_EXIT_DEBUG;
212162306a36Sopenharmony_ci	kvm_run->debug.arch.pc = svm->vmcb->save.cs.base + svm->vmcb->save.rip;
212262306a36Sopenharmony_ci	kvm_run->debug.arch.exception = BP_VECTOR;
212362306a36Sopenharmony_ci	return 0;
212462306a36Sopenharmony_ci}
212562306a36Sopenharmony_ci
212662306a36Sopenharmony_cistatic int ud_interception(struct kvm_vcpu *vcpu)
212762306a36Sopenharmony_ci{
212862306a36Sopenharmony_ci	return handle_ud(vcpu);
212962306a36Sopenharmony_ci}
213062306a36Sopenharmony_ci
213162306a36Sopenharmony_cistatic int ac_interception(struct kvm_vcpu *vcpu)
213262306a36Sopenharmony_ci{
213362306a36Sopenharmony_ci	kvm_queue_exception_e(vcpu, AC_VECTOR, 0);
213462306a36Sopenharmony_ci	return 1;
213562306a36Sopenharmony_ci}
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_cistatic bool is_erratum_383(void)
213862306a36Sopenharmony_ci{
213962306a36Sopenharmony_ci	int err, i;
214062306a36Sopenharmony_ci	u64 value;
214162306a36Sopenharmony_ci
214262306a36Sopenharmony_ci	if (!erratum_383_found)
214362306a36Sopenharmony_ci		return false;
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_ci	value = native_read_msr_safe(MSR_IA32_MC0_STATUS, &err);
214662306a36Sopenharmony_ci	if (err)
214762306a36Sopenharmony_ci		return false;
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_ci	/* Bit 62 may or may not be set for this mce */
215062306a36Sopenharmony_ci	value &= ~(1ULL << 62);
215162306a36Sopenharmony_ci
215262306a36Sopenharmony_ci	if (value != 0xb600000000010015ULL)
215362306a36Sopenharmony_ci		return false;
215462306a36Sopenharmony_ci
215562306a36Sopenharmony_ci	/* Clear MCi_STATUS registers */
215662306a36Sopenharmony_ci	for (i = 0; i < 6; ++i)
215762306a36Sopenharmony_ci		native_write_msr_safe(MSR_IA32_MCx_STATUS(i), 0, 0);
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ci	value = native_read_msr_safe(MSR_IA32_MCG_STATUS, &err);
216062306a36Sopenharmony_ci	if (!err) {
216162306a36Sopenharmony_ci		u32 low, high;
216262306a36Sopenharmony_ci
216362306a36Sopenharmony_ci		value &= ~(1ULL << 2);
216462306a36Sopenharmony_ci		low    = lower_32_bits(value);
216562306a36Sopenharmony_ci		high   = upper_32_bits(value);
216662306a36Sopenharmony_ci
216762306a36Sopenharmony_ci		native_write_msr_safe(MSR_IA32_MCG_STATUS, low, high);
216862306a36Sopenharmony_ci	}
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ci	/* Flush tlb to evict multi-match entries */
217162306a36Sopenharmony_ci	__flush_tlb_all();
217262306a36Sopenharmony_ci
217362306a36Sopenharmony_ci	return true;
217462306a36Sopenharmony_ci}
217562306a36Sopenharmony_ci
217662306a36Sopenharmony_cistatic void svm_handle_mce(struct kvm_vcpu *vcpu)
217762306a36Sopenharmony_ci{
217862306a36Sopenharmony_ci	if (is_erratum_383()) {
217962306a36Sopenharmony_ci		/*
218062306a36Sopenharmony_ci		 * Erratum 383 triggered. Guest state is corrupt so kill the
218162306a36Sopenharmony_ci		 * guest.
218262306a36Sopenharmony_ci		 */
218362306a36Sopenharmony_ci		pr_err("Guest triggered AMD Erratum 383\n");
218462306a36Sopenharmony_ci
218562306a36Sopenharmony_ci		kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
218662306a36Sopenharmony_ci
218762306a36Sopenharmony_ci		return;
218862306a36Sopenharmony_ci	}
218962306a36Sopenharmony_ci
219062306a36Sopenharmony_ci	/*
219162306a36Sopenharmony_ci	 * On an #MC intercept the MCE handler is not called automatically in
219262306a36Sopenharmony_ci	 * the host. So do it by hand here.
219362306a36Sopenharmony_ci	 */
219462306a36Sopenharmony_ci	kvm_machine_check();
219562306a36Sopenharmony_ci}
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_cistatic int mc_interception(struct kvm_vcpu *vcpu)
219862306a36Sopenharmony_ci{
219962306a36Sopenharmony_ci	return 1;
220062306a36Sopenharmony_ci}
220162306a36Sopenharmony_ci
220262306a36Sopenharmony_cistatic int shutdown_interception(struct kvm_vcpu *vcpu)
220362306a36Sopenharmony_ci{
220462306a36Sopenharmony_ci	struct kvm_run *kvm_run = vcpu->run;
220562306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci	/*
220862306a36Sopenharmony_ci	 * The VM save area has already been encrypted so it
220962306a36Sopenharmony_ci	 * cannot be reinitialized - just terminate.
221062306a36Sopenharmony_ci	 */
221162306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm))
221262306a36Sopenharmony_ci		return -EINVAL;
221362306a36Sopenharmony_ci
221462306a36Sopenharmony_ci	/*
221562306a36Sopenharmony_ci	 * VMCB is undefined after a SHUTDOWN intercept.  INIT the vCPU to put
221662306a36Sopenharmony_ci	 * the VMCB in a known good state.  Unfortuately, KVM doesn't have
221762306a36Sopenharmony_ci	 * KVM_MP_STATE_SHUTDOWN and can't add it without potentially breaking
221862306a36Sopenharmony_ci	 * userspace.  At a platform view, INIT is acceptable behavior as
221962306a36Sopenharmony_ci	 * there exist bare metal platforms that automatically INIT the CPU
222062306a36Sopenharmony_ci	 * in response to shutdown.
222162306a36Sopenharmony_ci	 */
222262306a36Sopenharmony_ci	clear_page(svm->vmcb);
222362306a36Sopenharmony_ci	kvm_vcpu_reset(vcpu, true);
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci	kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
222662306a36Sopenharmony_ci	return 0;
222762306a36Sopenharmony_ci}
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_cistatic int io_interception(struct kvm_vcpu *vcpu)
223062306a36Sopenharmony_ci{
223162306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
223262306a36Sopenharmony_ci	u32 io_info = svm->vmcb->control.exit_info_1; /* address size bug? */
223362306a36Sopenharmony_ci	int size, in, string;
223462306a36Sopenharmony_ci	unsigned port;
223562306a36Sopenharmony_ci
223662306a36Sopenharmony_ci	++vcpu->stat.io_exits;
223762306a36Sopenharmony_ci	string = (io_info & SVM_IOIO_STR_MASK) != 0;
223862306a36Sopenharmony_ci	in = (io_info & SVM_IOIO_TYPE_MASK) != 0;
223962306a36Sopenharmony_ci	port = io_info >> 16;
224062306a36Sopenharmony_ci	size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT;
224162306a36Sopenharmony_ci
224262306a36Sopenharmony_ci	if (string) {
224362306a36Sopenharmony_ci		if (sev_es_guest(vcpu->kvm))
224462306a36Sopenharmony_ci			return sev_es_string_io(svm, size, port, in);
224562306a36Sopenharmony_ci		else
224662306a36Sopenharmony_ci			return kvm_emulate_instruction(vcpu, 0);
224762306a36Sopenharmony_ci	}
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci	svm->next_rip = svm->vmcb->control.exit_info_2;
225062306a36Sopenharmony_ci
225162306a36Sopenharmony_ci	return kvm_fast_pio(vcpu, size, port, in);
225262306a36Sopenharmony_ci}
225362306a36Sopenharmony_ci
225462306a36Sopenharmony_cistatic int nmi_interception(struct kvm_vcpu *vcpu)
225562306a36Sopenharmony_ci{
225662306a36Sopenharmony_ci	return 1;
225762306a36Sopenharmony_ci}
225862306a36Sopenharmony_ci
225962306a36Sopenharmony_cistatic int smi_interception(struct kvm_vcpu *vcpu)
226062306a36Sopenharmony_ci{
226162306a36Sopenharmony_ci	return 1;
226262306a36Sopenharmony_ci}
226362306a36Sopenharmony_ci
226462306a36Sopenharmony_cistatic int intr_interception(struct kvm_vcpu *vcpu)
226562306a36Sopenharmony_ci{
226662306a36Sopenharmony_ci	++vcpu->stat.irq_exits;
226762306a36Sopenharmony_ci	return 1;
226862306a36Sopenharmony_ci}
226962306a36Sopenharmony_ci
227062306a36Sopenharmony_cistatic int vmload_vmsave_interception(struct kvm_vcpu *vcpu, bool vmload)
227162306a36Sopenharmony_ci{
227262306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
227362306a36Sopenharmony_ci	struct vmcb *vmcb12;
227462306a36Sopenharmony_ci	struct kvm_host_map map;
227562306a36Sopenharmony_ci	int ret;
227662306a36Sopenharmony_ci
227762306a36Sopenharmony_ci	if (nested_svm_check_permissions(vcpu))
227862306a36Sopenharmony_ci		return 1;
227962306a36Sopenharmony_ci
228062306a36Sopenharmony_ci	ret = kvm_vcpu_map(vcpu, gpa_to_gfn(svm->vmcb->save.rax), &map);
228162306a36Sopenharmony_ci	if (ret) {
228262306a36Sopenharmony_ci		if (ret == -EINVAL)
228362306a36Sopenharmony_ci			kvm_inject_gp(vcpu, 0);
228462306a36Sopenharmony_ci		return 1;
228562306a36Sopenharmony_ci	}
228662306a36Sopenharmony_ci
228762306a36Sopenharmony_ci	vmcb12 = map.hva;
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci	ret = kvm_skip_emulated_instruction(vcpu);
229062306a36Sopenharmony_ci
229162306a36Sopenharmony_ci	if (vmload) {
229262306a36Sopenharmony_ci		svm_copy_vmloadsave_state(svm->vmcb, vmcb12);
229362306a36Sopenharmony_ci		svm->sysenter_eip_hi = 0;
229462306a36Sopenharmony_ci		svm->sysenter_esp_hi = 0;
229562306a36Sopenharmony_ci	} else {
229662306a36Sopenharmony_ci		svm_copy_vmloadsave_state(vmcb12, svm->vmcb);
229762306a36Sopenharmony_ci	}
229862306a36Sopenharmony_ci
229962306a36Sopenharmony_ci	kvm_vcpu_unmap(vcpu, &map, true);
230062306a36Sopenharmony_ci
230162306a36Sopenharmony_ci	return ret;
230262306a36Sopenharmony_ci}
230362306a36Sopenharmony_ci
230462306a36Sopenharmony_cistatic int vmload_interception(struct kvm_vcpu *vcpu)
230562306a36Sopenharmony_ci{
230662306a36Sopenharmony_ci	return vmload_vmsave_interception(vcpu, true);
230762306a36Sopenharmony_ci}
230862306a36Sopenharmony_ci
230962306a36Sopenharmony_cistatic int vmsave_interception(struct kvm_vcpu *vcpu)
231062306a36Sopenharmony_ci{
231162306a36Sopenharmony_ci	return vmload_vmsave_interception(vcpu, false);
231262306a36Sopenharmony_ci}
231362306a36Sopenharmony_ci
231462306a36Sopenharmony_cistatic int vmrun_interception(struct kvm_vcpu *vcpu)
231562306a36Sopenharmony_ci{
231662306a36Sopenharmony_ci	if (nested_svm_check_permissions(vcpu))
231762306a36Sopenharmony_ci		return 1;
231862306a36Sopenharmony_ci
231962306a36Sopenharmony_ci	return nested_svm_vmrun(vcpu);
232062306a36Sopenharmony_ci}
232162306a36Sopenharmony_ci
232262306a36Sopenharmony_cienum {
232362306a36Sopenharmony_ci	NONE_SVM_INSTR,
232462306a36Sopenharmony_ci	SVM_INSTR_VMRUN,
232562306a36Sopenharmony_ci	SVM_INSTR_VMLOAD,
232662306a36Sopenharmony_ci	SVM_INSTR_VMSAVE,
232762306a36Sopenharmony_ci};
232862306a36Sopenharmony_ci
232962306a36Sopenharmony_ci/* Return NONE_SVM_INSTR if not SVM instrs, otherwise return decode result */
233062306a36Sopenharmony_cistatic int svm_instr_opcode(struct kvm_vcpu *vcpu)
233162306a36Sopenharmony_ci{
233262306a36Sopenharmony_ci	struct x86_emulate_ctxt *ctxt = vcpu->arch.emulate_ctxt;
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci	if (ctxt->b != 0x1 || ctxt->opcode_len != 2)
233562306a36Sopenharmony_ci		return NONE_SVM_INSTR;
233662306a36Sopenharmony_ci
233762306a36Sopenharmony_ci	switch (ctxt->modrm) {
233862306a36Sopenharmony_ci	case 0xd8: /* VMRUN */
233962306a36Sopenharmony_ci		return SVM_INSTR_VMRUN;
234062306a36Sopenharmony_ci	case 0xda: /* VMLOAD */
234162306a36Sopenharmony_ci		return SVM_INSTR_VMLOAD;
234262306a36Sopenharmony_ci	case 0xdb: /* VMSAVE */
234362306a36Sopenharmony_ci		return SVM_INSTR_VMSAVE;
234462306a36Sopenharmony_ci	default:
234562306a36Sopenharmony_ci		break;
234662306a36Sopenharmony_ci	}
234762306a36Sopenharmony_ci
234862306a36Sopenharmony_ci	return NONE_SVM_INSTR;
234962306a36Sopenharmony_ci}
235062306a36Sopenharmony_ci
235162306a36Sopenharmony_cistatic int emulate_svm_instr(struct kvm_vcpu *vcpu, int opcode)
235262306a36Sopenharmony_ci{
235362306a36Sopenharmony_ci	const int guest_mode_exit_codes[] = {
235462306a36Sopenharmony_ci		[SVM_INSTR_VMRUN] = SVM_EXIT_VMRUN,
235562306a36Sopenharmony_ci		[SVM_INSTR_VMLOAD] = SVM_EXIT_VMLOAD,
235662306a36Sopenharmony_ci		[SVM_INSTR_VMSAVE] = SVM_EXIT_VMSAVE,
235762306a36Sopenharmony_ci	};
235862306a36Sopenharmony_ci	int (*const svm_instr_handlers[])(struct kvm_vcpu *vcpu) = {
235962306a36Sopenharmony_ci		[SVM_INSTR_VMRUN] = vmrun_interception,
236062306a36Sopenharmony_ci		[SVM_INSTR_VMLOAD] = vmload_interception,
236162306a36Sopenharmony_ci		[SVM_INSTR_VMSAVE] = vmsave_interception,
236262306a36Sopenharmony_ci	};
236362306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
236462306a36Sopenharmony_ci	int ret;
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci	if (is_guest_mode(vcpu)) {
236762306a36Sopenharmony_ci		/* Returns '1' or -errno on failure, '0' on success. */
236862306a36Sopenharmony_ci		ret = nested_svm_simple_vmexit(svm, guest_mode_exit_codes[opcode]);
236962306a36Sopenharmony_ci		if (ret)
237062306a36Sopenharmony_ci			return ret;
237162306a36Sopenharmony_ci		return 1;
237262306a36Sopenharmony_ci	}
237362306a36Sopenharmony_ci	return svm_instr_handlers[opcode](vcpu);
237462306a36Sopenharmony_ci}
237562306a36Sopenharmony_ci
237662306a36Sopenharmony_ci/*
237762306a36Sopenharmony_ci * #GP handling code. Note that #GP can be triggered under the following two
237862306a36Sopenharmony_ci * cases:
237962306a36Sopenharmony_ci *   1) SVM VM-related instructions (VMRUN/VMSAVE/VMLOAD) that trigger #GP on
238062306a36Sopenharmony_ci *      some AMD CPUs when EAX of these instructions are in the reserved memory
238162306a36Sopenharmony_ci *      regions (e.g. SMM memory on host).
238262306a36Sopenharmony_ci *   2) VMware backdoor
238362306a36Sopenharmony_ci */
238462306a36Sopenharmony_cistatic int gp_interception(struct kvm_vcpu *vcpu)
238562306a36Sopenharmony_ci{
238662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
238762306a36Sopenharmony_ci	u32 error_code = svm->vmcb->control.exit_info_1;
238862306a36Sopenharmony_ci	int opcode;
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci	/* Both #GP cases have zero error_code */
239162306a36Sopenharmony_ci	if (error_code)
239262306a36Sopenharmony_ci		goto reinject;
239362306a36Sopenharmony_ci
239462306a36Sopenharmony_ci	/* Decode the instruction for usage later */
239562306a36Sopenharmony_ci	if (x86_decode_emulated_instruction(vcpu, 0, NULL, 0) != EMULATION_OK)
239662306a36Sopenharmony_ci		goto reinject;
239762306a36Sopenharmony_ci
239862306a36Sopenharmony_ci	opcode = svm_instr_opcode(vcpu);
239962306a36Sopenharmony_ci
240062306a36Sopenharmony_ci	if (opcode == NONE_SVM_INSTR) {
240162306a36Sopenharmony_ci		if (!enable_vmware_backdoor)
240262306a36Sopenharmony_ci			goto reinject;
240362306a36Sopenharmony_ci
240462306a36Sopenharmony_ci		/*
240562306a36Sopenharmony_ci		 * VMware backdoor emulation on #GP interception only handles
240662306a36Sopenharmony_ci		 * IN{S}, OUT{S}, and RDPMC.
240762306a36Sopenharmony_ci		 */
240862306a36Sopenharmony_ci		if (!is_guest_mode(vcpu))
240962306a36Sopenharmony_ci			return kvm_emulate_instruction(vcpu,
241062306a36Sopenharmony_ci				EMULTYPE_VMWARE_GP | EMULTYPE_NO_DECODE);
241162306a36Sopenharmony_ci	} else {
241262306a36Sopenharmony_ci		/* All SVM instructions expect page aligned RAX */
241362306a36Sopenharmony_ci		if (svm->vmcb->save.rax & ~PAGE_MASK)
241462306a36Sopenharmony_ci			goto reinject;
241562306a36Sopenharmony_ci
241662306a36Sopenharmony_ci		return emulate_svm_instr(vcpu, opcode);
241762306a36Sopenharmony_ci	}
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_cireinject:
242062306a36Sopenharmony_ci	kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
242162306a36Sopenharmony_ci	return 1;
242262306a36Sopenharmony_ci}
242362306a36Sopenharmony_ci
242462306a36Sopenharmony_civoid svm_set_gif(struct vcpu_svm *svm, bool value)
242562306a36Sopenharmony_ci{
242662306a36Sopenharmony_ci	if (value) {
242762306a36Sopenharmony_ci		/*
242862306a36Sopenharmony_ci		 * If VGIF is enabled, the STGI intercept is only added to
242962306a36Sopenharmony_ci		 * detect the opening of the SMI/NMI window; remove it now.
243062306a36Sopenharmony_ci		 * Likewise, clear the VINTR intercept, we will set it
243162306a36Sopenharmony_ci		 * again while processing KVM_REQ_EVENT if needed.
243262306a36Sopenharmony_ci		 */
243362306a36Sopenharmony_ci		if (vgif)
243462306a36Sopenharmony_ci			svm_clr_intercept(svm, INTERCEPT_STGI);
243562306a36Sopenharmony_ci		if (svm_is_intercept(svm, INTERCEPT_VINTR))
243662306a36Sopenharmony_ci			svm_clear_vintr(svm);
243762306a36Sopenharmony_ci
243862306a36Sopenharmony_ci		enable_gif(svm);
243962306a36Sopenharmony_ci		if (svm->vcpu.arch.smi_pending ||
244062306a36Sopenharmony_ci		    svm->vcpu.arch.nmi_pending ||
244162306a36Sopenharmony_ci		    kvm_cpu_has_injectable_intr(&svm->vcpu) ||
244262306a36Sopenharmony_ci		    kvm_apic_has_pending_init_or_sipi(&svm->vcpu))
244362306a36Sopenharmony_ci			kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
244462306a36Sopenharmony_ci	} else {
244562306a36Sopenharmony_ci		disable_gif(svm);
244662306a36Sopenharmony_ci
244762306a36Sopenharmony_ci		/*
244862306a36Sopenharmony_ci		 * After a CLGI no interrupts should come.  But if vGIF is
244962306a36Sopenharmony_ci		 * in use, we still rely on the VINTR intercept (rather than
245062306a36Sopenharmony_ci		 * STGI) to detect an open interrupt window.
245162306a36Sopenharmony_ci		*/
245262306a36Sopenharmony_ci		if (!vgif)
245362306a36Sopenharmony_ci			svm_clear_vintr(svm);
245462306a36Sopenharmony_ci	}
245562306a36Sopenharmony_ci}
245662306a36Sopenharmony_ci
245762306a36Sopenharmony_cistatic int stgi_interception(struct kvm_vcpu *vcpu)
245862306a36Sopenharmony_ci{
245962306a36Sopenharmony_ci	int ret;
246062306a36Sopenharmony_ci
246162306a36Sopenharmony_ci	if (nested_svm_check_permissions(vcpu))
246262306a36Sopenharmony_ci		return 1;
246362306a36Sopenharmony_ci
246462306a36Sopenharmony_ci	ret = kvm_skip_emulated_instruction(vcpu);
246562306a36Sopenharmony_ci	svm_set_gif(to_svm(vcpu), true);
246662306a36Sopenharmony_ci	return ret;
246762306a36Sopenharmony_ci}
246862306a36Sopenharmony_ci
246962306a36Sopenharmony_cistatic int clgi_interception(struct kvm_vcpu *vcpu)
247062306a36Sopenharmony_ci{
247162306a36Sopenharmony_ci	int ret;
247262306a36Sopenharmony_ci
247362306a36Sopenharmony_ci	if (nested_svm_check_permissions(vcpu))
247462306a36Sopenharmony_ci		return 1;
247562306a36Sopenharmony_ci
247662306a36Sopenharmony_ci	ret = kvm_skip_emulated_instruction(vcpu);
247762306a36Sopenharmony_ci	svm_set_gif(to_svm(vcpu), false);
247862306a36Sopenharmony_ci	return ret;
247962306a36Sopenharmony_ci}
248062306a36Sopenharmony_ci
248162306a36Sopenharmony_cistatic int invlpga_interception(struct kvm_vcpu *vcpu)
248262306a36Sopenharmony_ci{
248362306a36Sopenharmony_ci	gva_t gva = kvm_rax_read(vcpu);
248462306a36Sopenharmony_ci	u32 asid = kvm_rcx_read(vcpu);
248562306a36Sopenharmony_ci
248662306a36Sopenharmony_ci	/* FIXME: Handle an address size prefix. */
248762306a36Sopenharmony_ci	if (!is_long_mode(vcpu))
248862306a36Sopenharmony_ci		gva = (u32)gva;
248962306a36Sopenharmony_ci
249062306a36Sopenharmony_ci	trace_kvm_invlpga(to_svm(vcpu)->vmcb->save.rip, asid, gva);
249162306a36Sopenharmony_ci
249262306a36Sopenharmony_ci	/* Let's treat INVLPGA the same as INVLPG (can be optimized!) */
249362306a36Sopenharmony_ci	kvm_mmu_invlpg(vcpu, gva);
249462306a36Sopenharmony_ci
249562306a36Sopenharmony_ci	return kvm_skip_emulated_instruction(vcpu);
249662306a36Sopenharmony_ci}
249762306a36Sopenharmony_ci
249862306a36Sopenharmony_cistatic int skinit_interception(struct kvm_vcpu *vcpu)
249962306a36Sopenharmony_ci{
250062306a36Sopenharmony_ci	trace_kvm_skinit(to_svm(vcpu)->vmcb->save.rip, kvm_rax_read(vcpu));
250162306a36Sopenharmony_ci
250262306a36Sopenharmony_ci	kvm_queue_exception(vcpu, UD_VECTOR);
250362306a36Sopenharmony_ci	return 1;
250462306a36Sopenharmony_ci}
250562306a36Sopenharmony_ci
250662306a36Sopenharmony_cistatic int task_switch_interception(struct kvm_vcpu *vcpu)
250762306a36Sopenharmony_ci{
250862306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
250962306a36Sopenharmony_ci	u16 tss_selector;
251062306a36Sopenharmony_ci	int reason;
251162306a36Sopenharmony_ci	int int_type = svm->vmcb->control.exit_int_info &
251262306a36Sopenharmony_ci		SVM_EXITINTINFO_TYPE_MASK;
251362306a36Sopenharmony_ci	int int_vec = svm->vmcb->control.exit_int_info & SVM_EVTINJ_VEC_MASK;
251462306a36Sopenharmony_ci	uint32_t type =
251562306a36Sopenharmony_ci		svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_TYPE_MASK;
251662306a36Sopenharmony_ci	uint32_t idt_v =
251762306a36Sopenharmony_ci		svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID;
251862306a36Sopenharmony_ci	bool has_error_code = false;
251962306a36Sopenharmony_ci	u32 error_code = 0;
252062306a36Sopenharmony_ci
252162306a36Sopenharmony_ci	tss_selector = (u16)svm->vmcb->control.exit_info_1;
252262306a36Sopenharmony_ci
252362306a36Sopenharmony_ci	if (svm->vmcb->control.exit_info_2 &
252462306a36Sopenharmony_ci	    (1ULL << SVM_EXITINFOSHIFT_TS_REASON_IRET))
252562306a36Sopenharmony_ci		reason = TASK_SWITCH_IRET;
252662306a36Sopenharmony_ci	else if (svm->vmcb->control.exit_info_2 &
252762306a36Sopenharmony_ci		 (1ULL << SVM_EXITINFOSHIFT_TS_REASON_JMP))
252862306a36Sopenharmony_ci		reason = TASK_SWITCH_JMP;
252962306a36Sopenharmony_ci	else if (idt_v)
253062306a36Sopenharmony_ci		reason = TASK_SWITCH_GATE;
253162306a36Sopenharmony_ci	else
253262306a36Sopenharmony_ci		reason = TASK_SWITCH_CALL;
253362306a36Sopenharmony_ci
253462306a36Sopenharmony_ci	if (reason == TASK_SWITCH_GATE) {
253562306a36Sopenharmony_ci		switch (type) {
253662306a36Sopenharmony_ci		case SVM_EXITINTINFO_TYPE_NMI:
253762306a36Sopenharmony_ci			vcpu->arch.nmi_injected = false;
253862306a36Sopenharmony_ci			break;
253962306a36Sopenharmony_ci		case SVM_EXITINTINFO_TYPE_EXEPT:
254062306a36Sopenharmony_ci			if (svm->vmcb->control.exit_info_2 &
254162306a36Sopenharmony_ci			    (1ULL << SVM_EXITINFOSHIFT_TS_HAS_ERROR_CODE)) {
254262306a36Sopenharmony_ci				has_error_code = true;
254362306a36Sopenharmony_ci				error_code =
254462306a36Sopenharmony_ci					(u32)svm->vmcb->control.exit_info_2;
254562306a36Sopenharmony_ci			}
254662306a36Sopenharmony_ci			kvm_clear_exception_queue(vcpu);
254762306a36Sopenharmony_ci			break;
254862306a36Sopenharmony_ci		case SVM_EXITINTINFO_TYPE_INTR:
254962306a36Sopenharmony_ci		case SVM_EXITINTINFO_TYPE_SOFT:
255062306a36Sopenharmony_ci			kvm_clear_interrupt_queue(vcpu);
255162306a36Sopenharmony_ci			break;
255262306a36Sopenharmony_ci		default:
255362306a36Sopenharmony_ci			break;
255462306a36Sopenharmony_ci		}
255562306a36Sopenharmony_ci	}
255662306a36Sopenharmony_ci
255762306a36Sopenharmony_ci	if (reason != TASK_SWITCH_GATE ||
255862306a36Sopenharmony_ci	    int_type == SVM_EXITINTINFO_TYPE_SOFT ||
255962306a36Sopenharmony_ci	    (int_type == SVM_EXITINTINFO_TYPE_EXEPT &&
256062306a36Sopenharmony_ci	     (int_vec == OF_VECTOR || int_vec == BP_VECTOR))) {
256162306a36Sopenharmony_ci		if (!svm_skip_emulated_instruction(vcpu))
256262306a36Sopenharmony_ci			return 0;
256362306a36Sopenharmony_ci	}
256462306a36Sopenharmony_ci
256562306a36Sopenharmony_ci	if (int_type != SVM_EXITINTINFO_TYPE_SOFT)
256662306a36Sopenharmony_ci		int_vec = -1;
256762306a36Sopenharmony_ci
256862306a36Sopenharmony_ci	return kvm_task_switch(vcpu, tss_selector, int_vec, reason,
256962306a36Sopenharmony_ci			       has_error_code, error_code);
257062306a36Sopenharmony_ci}
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_cistatic void svm_clr_iret_intercept(struct vcpu_svm *svm)
257362306a36Sopenharmony_ci{
257462306a36Sopenharmony_ci	if (!sev_es_guest(svm->vcpu.kvm))
257562306a36Sopenharmony_ci		svm_clr_intercept(svm, INTERCEPT_IRET);
257662306a36Sopenharmony_ci}
257762306a36Sopenharmony_ci
257862306a36Sopenharmony_cistatic void svm_set_iret_intercept(struct vcpu_svm *svm)
257962306a36Sopenharmony_ci{
258062306a36Sopenharmony_ci	if (!sev_es_guest(svm->vcpu.kvm))
258162306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_IRET);
258262306a36Sopenharmony_ci}
258362306a36Sopenharmony_ci
258462306a36Sopenharmony_cistatic int iret_interception(struct kvm_vcpu *vcpu)
258562306a36Sopenharmony_ci{
258662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
258762306a36Sopenharmony_ci
258862306a36Sopenharmony_ci	WARN_ON_ONCE(sev_es_guest(vcpu->kvm));
258962306a36Sopenharmony_ci
259062306a36Sopenharmony_ci	++vcpu->stat.nmi_window_exits;
259162306a36Sopenharmony_ci	svm->awaiting_iret_completion = true;
259262306a36Sopenharmony_ci
259362306a36Sopenharmony_ci	svm_clr_iret_intercept(svm);
259462306a36Sopenharmony_ci	svm->nmi_iret_rip = kvm_rip_read(vcpu);
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci	kvm_make_request(KVM_REQ_EVENT, vcpu);
259762306a36Sopenharmony_ci	return 1;
259862306a36Sopenharmony_ci}
259962306a36Sopenharmony_ci
260062306a36Sopenharmony_cistatic int invlpg_interception(struct kvm_vcpu *vcpu)
260162306a36Sopenharmony_ci{
260262306a36Sopenharmony_ci	if (!static_cpu_has(X86_FEATURE_DECODEASSISTS))
260362306a36Sopenharmony_ci		return kvm_emulate_instruction(vcpu, 0);
260462306a36Sopenharmony_ci
260562306a36Sopenharmony_ci	kvm_mmu_invlpg(vcpu, to_svm(vcpu)->vmcb->control.exit_info_1);
260662306a36Sopenharmony_ci	return kvm_skip_emulated_instruction(vcpu);
260762306a36Sopenharmony_ci}
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_cistatic int emulate_on_interception(struct kvm_vcpu *vcpu)
261062306a36Sopenharmony_ci{
261162306a36Sopenharmony_ci	return kvm_emulate_instruction(vcpu, 0);
261262306a36Sopenharmony_ci}
261362306a36Sopenharmony_ci
261462306a36Sopenharmony_cistatic int rsm_interception(struct kvm_vcpu *vcpu)
261562306a36Sopenharmony_ci{
261662306a36Sopenharmony_ci	return kvm_emulate_instruction_from_buffer(vcpu, rsm_ins_bytes, 2);
261762306a36Sopenharmony_ci}
261862306a36Sopenharmony_ci
261962306a36Sopenharmony_cistatic bool check_selective_cr0_intercepted(struct kvm_vcpu *vcpu,
262062306a36Sopenharmony_ci					    unsigned long val)
262162306a36Sopenharmony_ci{
262262306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
262362306a36Sopenharmony_ci	unsigned long cr0 = vcpu->arch.cr0;
262462306a36Sopenharmony_ci	bool ret = false;
262562306a36Sopenharmony_ci
262662306a36Sopenharmony_ci	if (!is_guest_mode(vcpu) ||
262762306a36Sopenharmony_ci	    (!(vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_SELECTIVE_CR0))))
262862306a36Sopenharmony_ci		return false;
262962306a36Sopenharmony_ci
263062306a36Sopenharmony_ci	cr0 &= ~SVM_CR0_SELECTIVE_MASK;
263162306a36Sopenharmony_ci	val &= ~SVM_CR0_SELECTIVE_MASK;
263262306a36Sopenharmony_ci
263362306a36Sopenharmony_ci	if (cr0 ^ val) {
263462306a36Sopenharmony_ci		svm->vmcb->control.exit_code = SVM_EXIT_CR0_SEL_WRITE;
263562306a36Sopenharmony_ci		ret = (nested_svm_exit_handled(svm) == NESTED_EXIT_DONE);
263662306a36Sopenharmony_ci	}
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_ci	return ret;
263962306a36Sopenharmony_ci}
264062306a36Sopenharmony_ci
264162306a36Sopenharmony_ci#define CR_VALID (1ULL << 63)
264262306a36Sopenharmony_ci
264362306a36Sopenharmony_cistatic int cr_interception(struct kvm_vcpu *vcpu)
264462306a36Sopenharmony_ci{
264562306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
264662306a36Sopenharmony_ci	int reg, cr;
264762306a36Sopenharmony_ci	unsigned long val;
264862306a36Sopenharmony_ci	int err;
264962306a36Sopenharmony_ci
265062306a36Sopenharmony_ci	if (!static_cpu_has(X86_FEATURE_DECODEASSISTS))
265162306a36Sopenharmony_ci		return emulate_on_interception(vcpu);
265262306a36Sopenharmony_ci
265362306a36Sopenharmony_ci	if (unlikely((svm->vmcb->control.exit_info_1 & CR_VALID) == 0))
265462306a36Sopenharmony_ci		return emulate_on_interception(vcpu);
265562306a36Sopenharmony_ci
265662306a36Sopenharmony_ci	reg = svm->vmcb->control.exit_info_1 & SVM_EXITINFO_REG_MASK;
265762306a36Sopenharmony_ci	if (svm->vmcb->control.exit_code == SVM_EXIT_CR0_SEL_WRITE)
265862306a36Sopenharmony_ci		cr = SVM_EXIT_WRITE_CR0 - SVM_EXIT_READ_CR0;
265962306a36Sopenharmony_ci	else
266062306a36Sopenharmony_ci		cr = svm->vmcb->control.exit_code - SVM_EXIT_READ_CR0;
266162306a36Sopenharmony_ci
266262306a36Sopenharmony_ci	err = 0;
266362306a36Sopenharmony_ci	if (cr >= 16) { /* mov to cr */
266462306a36Sopenharmony_ci		cr -= 16;
266562306a36Sopenharmony_ci		val = kvm_register_read(vcpu, reg);
266662306a36Sopenharmony_ci		trace_kvm_cr_write(cr, val);
266762306a36Sopenharmony_ci		switch (cr) {
266862306a36Sopenharmony_ci		case 0:
266962306a36Sopenharmony_ci			if (!check_selective_cr0_intercepted(vcpu, val))
267062306a36Sopenharmony_ci				err = kvm_set_cr0(vcpu, val);
267162306a36Sopenharmony_ci			else
267262306a36Sopenharmony_ci				return 1;
267362306a36Sopenharmony_ci
267462306a36Sopenharmony_ci			break;
267562306a36Sopenharmony_ci		case 3:
267662306a36Sopenharmony_ci			err = kvm_set_cr3(vcpu, val);
267762306a36Sopenharmony_ci			break;
267862306a36Sopenharmony_ci		case 4:
267962306a36Sopenharmony_ci			err = kvm_set_cr4(vcpu, val);
268062306a36Sopenharmony_ci			break;
268162306a36Sopenharmony_ci		case 8:
268262306a36Sopenharmony_ci			err = kvm_set_cr8(vcpu, val);
268362306a36Sopenharmony_ci			break;
268462306a36Sopenharmony_ci		default:
268562306a36Sopenharmony_ci			WARN(1, "unhandled write to CR%d", cr);
268662306a36Sopenharmony_ci			kvm_queue_exception(vcpu, UD_VECTOR);
268762306a36Sopenharmony_ci			return 1;
268862306a36Sopenharmony_ci		}
268962306a36Sopenharmony_ci	} else { /* mov from cr */
269062306a36Sopenharmony_ci		switch (cr) {
269162306a36Sopenharmony_ci		case 0:
269262306a36Sopenharmony_ci			val = kvm_read_cr0(vcpu);
269362306a36Sopenharmony_ci			break;
269462306a36Sopenharmony_ci		case 2:
269562306a36Sopenharmony_ci			val = vcpu->arch.cr2;
269662306a36Sopenharmony_ci			break;
269762306a36Sopenharmony_ci		case 3:
269862306a36Sopenharmony_ci			val = kvm_read_cr3(vcpu);
269962306a36Sopenharmony_ci			break;
270062306a36Sopenharmony_ci		case 4:
270162306a36Sopenharmony_ci			val = kvm_read_cr4(vcpu);
270262306a36Sopenharmony_ci			break;
270362306a36Sopenharmony_ci		case 8:
270462306a36Sopenharmony_ci			val = kvm_get_cr8(vcpu);
270562306a36Sopenharmony_ci			break;
270662306a36Sopenharmony_ci		default:
270762306a36Sopenharmony_ci			WARN(1, "unhandled read from CR%d", cr);
270862306a36Sopenharmony_ci			kvm_queue_exception(vcpu, UD_VECTOR);
270962306a36Sopenharmony_ci			return 1;
271062306a36Sopenharmony_ci		}
271162306a36Sopenharmony_ci		kvm_register_write(vcpu, reg, val);
271262306a36Sopenharmony_ci		trace_kvm_cr_read(cr, val);
271362306a36Sopenharmony_ci	}
271462306a36Sopenharmony_ci	return kvm_complete_insn_gp(vcpu, err);
271562306a36Sopenharmony_ci}
271662306a36Sopenharmony_ci
271762306a36Sopenharmony_cistatic int cr_trap(struct kvm_vcpu *vcpu)
271862306a36Sopenharmony_ci{
271962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
272062306a36Sopenharmony_ci	unsigned long old_value, new_value;
272162306a36Sopenharmony_ci	unsigned int cr;
272262306a36Sopenharmony_ci	int ret = 0;
272362306a36Sopenharmony_ci
272462306a36Sopenharmony_ci	new_value = (unsigned long)svm->vmcb->control.exit_info_1;
272562306a36Sopenharmony_ci
272662306a36Sopenharmony_ci	cr = svm->vmcb->control.exit_code - SVM_EXIT_CR0_WRITE_TRAP;
272762306a36Sopenharmony_ci	switch (cr) {
272862306a36Sopenharmony_ci	case 0:
272962306a36Sopenharmony_ci		old_value = kvm_read_cr0(vcpu);
273062306a36Sopenharmony_ci		svm_set_cr0(vcpu, new_value);
273162306a36Sopenharmony_ci
273262306a36Sopenharmony_ci		kvm_post_set_cr0(vcpu, old_value, new_value);
273362306a36Sopenharmony_ci		break;
273462306a36Sopenharmony_ci	case 4:
273562306a36Sopenharmony_ci		old_value = kvm_read_cr4(vcpu);
273662306a36Sopenharmony_ci		svm_set_cr4(vcpu, new_value);
273762306a36Sopenharmony_ci
273862306a36Sopenharmony_ci		kvm_post_set_cr4(vcpu, old_value, new_value);
273962306a36Sopenharmony_ci		break;
274062306a36Sopenharmony_ci	case 8:
274162306a36Sopenharmony_ci		ret = kvm_set_cr8(vcpu, new_value);
274262306a36Sopenharmony_ci		break;
274362306a36Sopenharmony_ci	default:
274462306a36Sopenharmony_ci		WARN(1, "unhandled CR%d write trap", cr);
274562306a36Sopenharmony_ci		kvm_queue_exception(vcpu, UD_VECTOR);
274662306a36Sopenharmony_ci		return 1;
274762306a36Sopenharmony_ci	}
274862306a36Sopenharmony_ci
274962306a36Sopenharmony_ci	return kvm_complete_insn_gp(vcpu, ret);
275062306a36Sopenharmony_ci}
275162306a36Sopenharmony_ci
275262306a36Sopenharmony_cistatic int dr_interception(struct kvm_vcpu *vcpu)
275362306a36Sopenharmony_ci{
275462306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
275562306a36Sopenharmony_ci	int reg, dr;
275662306a36Sopenharmony_ci	unsigned long val;
275762306a36Sopenharmony_ci	int err = 0;
275862306a36Sopenharmony_ci
275962306a36Sopenharmony_ci	/*
276062306a36Sopenharmony_ci	 * SEV-ES intercepts DR7 only to disable guest debugging and the guest issues a VMGEXIT
276162306a36Sopenharmony_ci	 * for DR7 write only. KVM cannot change DR7 (always swapped as type 'A') so return early.
276262306a36Sopenharmony_ci	 */
276362306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm))
276462306a36Sopenharmony_ci		return 1;
276562306a36Sopenharmony_ci
276662306a36Sopenharmony_ci	if (vcpu->guest_debug == 0) {
276762306a36Sopenharmony_ci		/*
276862306a36Sopenharmony_ci		 * No more DR vmexits; force a reload of the debug registers
276962306a36Sopenharmony_ci		 * and reenter on this instruction.  The next vmexit will
277062306a36Sopenharmony_ci		 * retrieve the full state of the debug registers.
277162306a36Sopenharmony_ci		 */
277262306a36Sopenharmony_ci		clr_dr_intercepts(svm);
277362306a36Sopenharmony_ci		vcpu->arch.switch_db_regs |= KVM_DEBUGREG_WONT_EXIT;
277462306a36Sopenharmony_ci		return 1;
277562306a36Sopenharmony_ci	}
277662306a36Sopenharmony_ci
277762306a36Sopenharmony_ci	if (!boot_cpu_has(X86_FEATURE_DECODEASSISTS))
277862306a36Sopenharmony_ci		return emulate_on_interception(vcpu);
277962306a36Sopenharmony_ci
278062306a36Sopenharmony_ci	reg = svm->vmcb->control.exit_info_1 & SVM_EXITINFO_REG_MASK;
278162306a36Sopenharmony_ci	dr = svm->vmcb->control.exit_code - SVM_EXIT_READ_DR0;
278262306a36Sopenharmony_ci	if (dr >= 16) { /* mov to DRn  */
278362306a36Sopenharmony_ci		dr -= 16;
278462306a36Sopenharmony_ci		val = kvm_register_read(vcpu, reg);
278562306a36Sopenharmony_ci		err = kvm_set_dr(vcpu, dr, val);
278662306a36Sopenharmony_ci	} else {
278762306a36Sopenharmony_ci		kvm_get_dr(vcpu, dr, &val);
278862306a36Sopenharmony_ci		kvm_register_write(vcpu, reg, val);
278962306a36Sopenharmony_ci	}
279062306a36Sopenharmony_ci
279162306a36Sopenharmony_ci	return kvm_complete_insn_gp(vcpu, err);
279262306a36Sopenharmony_ci}
279362306a36Sopenharmony_ci
279462306a36Sopenharmony_cistatic int cr8_write_interception(struct kvm_vcpu *vcpu)
279562306a36Sopenharmony_ci{
279662306a36Sopenharmony_ci	int r;
279762306a36Sopenharmony_ci
279862306a36Sopenharmony_ci	u8 cr8_prev = kvm_get_cr8(vcpu);
279962306a36Sopenharmony_ci	/* instruction emulation calls kvm_set_cr8() */
280062306a36Sopenharmony_ci	r = cr_interception(vcpu);
280162306a36Sopenharmony_ci	if (lapic_in_kernel(vcpu))
280262306a36Sopenharmony_ci		return r;
280362306a36Sopenharmony_ci	if (cr8_prev <= kvm_get_cr8(vcpu))
280462306a36Sopenharmony_ci		return r;
280562306a36Sopenharmony_ci	vcpu->run->exit_reason = KVM_EXIT_SET_TPR;
280662306a36Sopenharmony_ci	return 0;
280762306a36Sopenharmony_ci}
280862306a36Sopenharmony_ci
280962306a36Sopenharmony_cistatic int efer_trap(struct kvm_vcpu *vcpu)
281062306a36Sopenharmony_ci{
281162306a36Sopenharmony_ci	struct msr_data msr_info;
281262306a36Sopenharmony_ci	int ret;
281362306a36Sopenharmony_ci
281462306a36Sopenharmony_ci	/*
281562306a36Sopenharmony_ci	 * Clear the EFER_SVME bit from EFER. The SVM code always sets this
281662306a36Sopenharmony_ci	 * bit in svm_set_efer(), but __kvm_valid_efer() checks it against
281762306a36Sopenharmony_ci	 * whether the guest has X86_FEATURE_SVM - this avoids a failure if
281862306a36Sopenharmony_ci	 * the guest doesn't have X86_FEATURE_SVM.
281962306a36Sopenharmony_ci	 */
282062306a36Sopenharmony_ci	msr_info.host_initiated = false;
282162306a36Sopenharmony_ci	msr_info.index = MSR_EFER;
282262306a36Sopenharmony_ci	msr_info.data = to_svm(vcpu)->vmcb->control.exit_info_1 & ~EFER_SVME;
282362306a36Sopenharmony_ci	ret = kvm_set_msr_common(vcpu, &msr_info);
282462306a36Sopenharmony_ci
282562306a36Sopenharmony_ci	return kvm_complete_insn_gp(vcpu, ret);
282662306a36Sopenharmony_ci}
282762306a36Sopenharmony_ci
282862306a36Sopenharmony_cistatic int svm_get_msr_feature(struct kvm_msr_entry *msr)
282962306a36Sopenharmony_ci{
283062306a36Sopenharmony_ci	msr->data = 0;
283162306a36Sopenharmony_ci
283262306a36Sopenharmony_ci	switch (msr->index) {
283362306a36Sopenharmony_ci	case MSR_AMD64_DE_CFG:
283462306a36Sopenharmony_ci		if (cpu_feature_enabled(X86_FEATURE_LFENCE_RDTSC))
283562306a36Sopenharmony_ci			msr->data |= MSR_AMD64_DE_CFG_LFENCE_SERIALIZE;
283662306a36Sopenharmony_ci		break;
283762306a36Sopenharmony_ci	default:
283862306a36Sopenharmony_ci		return KVM_MSR_RET_INVALID;
283962306a36Sopenharmony_ci	}
284062306a36Sopenharmony_ci
284162306a36Sopenharmony_ci	return 0;
284262306a36Sopenharmony_ci}
284362306a36Sopenharmony_ci
284462306a36Sopenharmony_cistatic int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
284562306a36Sopenharmony_ci{
284662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
284762306a36Sopenharmony_ci
284862306a36Sopenharmony_ci	switch (msr_info->index) {
284962306a36Sopenharmony_ci	case MSR_AMD64_TSC_RATIO:
285062306a36Sopenharmony_ci		if (!msr_info->host_initiated &&
285162306a36Sopenharmony_ci		    !guest_can_use(vcpu, X86_FEATURE_TSCRATEMSR))
285262306a36Sopenharmony_ci			return 1;
285362306a36Sopenharmony_ci		msr_info->data = svm->tsc_ratio_msr;
285462306a36Sopenharmony_ci		break;
285562306a36Sopenharmony_ci	case MSR_STAR:
285662306a36Sopenharmony_ci		msr_info->data = svm->vmcb01.ptr->save.star;
285762306a36Sopenharmony_ci		break;
285862306a36Sopenharmony_ci#ifdef CONFIG_X86_64
285962306a36Sopenharmony_ci	case MSR_LSTAR:
286062306a36Sopenharmony_ci		msr_info->data = svm->vmcb01.ptr->save.lstar;
286162306a36Sopenharmony_ci		break;
286262306a36Sopenharmony_ci	case MSR_CSTAR:
286362306a36Sopenharmony_ci		msr_info->data = svm->vmcb01.ptr->save.cstar;
286462306a36Sopenharmony_ci		break;
286562306a36Sopenharmony_ci	case MSR_KERNEL_GS_BASE:
286662306a36Sopenharmony_ci		msr_info->data = svm->vmcb01.ptr->save.kernel_gs_base;
286762306a36Sopenharmony_ci		break;
286862306a36Sopenharmony_ci	case MSR_SYSCALL_MASK:
286962306a36Sopenharmony_ci		msr_info->data = svm->vmcb01.ptr->save.sfmask;
287062306a36Sopenharmony_ci		break;
287162306a36Sopenharmony_ci#endif
287262306a36Sopenharmony_ci	case MSR_IA32_SYSENTER_CS:
287362306a36Sopenharmony_ci		msr_info->data = svm->vmcb01.ptr->save.sysenter_cs;
287462306a36Sopenharmony_ci		break;
287562306a36Sopenharmony_ci	case MSR_IA32_SYSENTER_EIP:
287662306a36Sopenharmony_ci		msr_info->data = (u32)svm->vmcb01.ptr->save.sysenter_eip;
287762306a36Sopenharmony_ci		if (guest_cpuid_is_intel(vcpu))
287862306a36Sopenharmony_ci			msr_info->data |= (u64)svm->sysenter_eip_hi << 32;
287962306a36Sopenharmony_ci		break;
288062306a36Sopenharmony_ci	case MSR_IA32_SYSENTER_ESP:
288162306a36Sopenharmony_ci		msr_info->data = svm->vmcb01.ptr->save.sysenter_esp;
288262306a36Sopenharmony_ci		if (guest_cpuid_is_intel(vcpu))
288362306a36Sopenharmony_ci			msr_info->data |= (u64)svm->sysenter_esp_hi << 32;
288462306a36Sopenharmony_ci		break;
288562306a36Sopenharmony_ci	case MSR_TSC_AUX:
288662306a36Sopenharmony_ci		msr_info->data = svm->tsc_aux;
288762306a36Sopenharmony_ci		break;
288862306a36Sopenharmony_ci	case MSR_IA32_DEBUGCTLMSR:
288962306a36Sopenharmony_ci		msr_info->data = svm_get_lbr_vmcb(svm)->save.dbgctl;
289062306a36Sopenharmony_ci		break;
289162306a36Sopenharmony_ci	case MSR_IA32_LASTBRANCHFROMIP:
289262306a36Sopenharmony_ci		msr_info->data = svm_get_lbr_vmcb(svm)->save.br_from;
289362306a36Sopenharmony_ci		break;
289462306a36Sopenharmony_ci	case MSR_IA32_LASTBRANCHTOIP:
289562306a36Sopenharmony_ci		msr_info->data = svm_get_lbr_vmcb(svm)->save.br_to;
289662306a36Sopenharmony_ci		break;
289762306a36Sopenharmony_ci	case MSR_IA32_LASTINTFROMIP:
289862306a36Sopenharmony_ci		msr_info->data = svm_get_lbr_vmcb(svm)->save.last_excp_from;
289962306a36Sopenharmony_ci		break;
290062306a36Sopenharmony_ci	case MSR_IA32_LASTINTTOIP:
290162306a36Sopenharmony_ci		msr_info->data = svm_get_lbr_vmcb(svm)->save.last_excp_to;
290262306a36Sopenharmony_ci		break;
290362306a36Sopenharmony_ci	case MSR_VM_HSAVE_PA:
290462306a36Sopenharmony_ci		msr_info->data = svm->nested.hsave_msr;
290562306a36Sopenharmony_ci		break;
290662306a36Sopenharmony_ci	case MSR_VM_CR:
290762306a36Sopenharmony_ci		msr_info->data = svm->nested.vm_cr_msr;
290862306a36Sopenharmony_ci		break;
290962306a36Sopenharmony_ci	case MSR_IA32_SPEC_CTRL:
291062306a36Sopenharmony_ci		if (!msr_info->host_initiated &&
291162306a36Sopenharmony_ci		    !guest_has_spec_ctrl_msr(vcpu))
291262306a36Sopenharmony_ci			return 1;
291362306a36Sopenharmony_ci
291462306a36Sopenharmony_ci		if (boot_cpu_has(X86_FEATURE_V_SPEC_CTRL))
291562306a36Sopenharmony_ci			msr_info->data = svm->vmcb->save.spec_ctrl;
291662306a36Sopenharmony_ci		else
291762306a36Sopenharmony_ci			msr_info->data = svm->spec_ctrl;
291862306a36Sopenharmony_ci		break;
291962306a36Sopenharmony_ci	case MSR_AMD64_VIRT_SPEC_CTRL:
292062306a36Sopenharmony_ci		if (!msr_info->host_initiated &&
292162306a36Sopenharmony_ci		    !guest_cpuid_has(vcpu, X86_FEATURE_VIRT_SSBD))
292262306a36Sopenharmony_ci			return 1;
292362306a36Sopenharmony_ci
292462306a36Sopenharmony_ci		msr_info->data = svm->virt_spec_ctrl;
292562306a36Sopenharmony_ci		break;
292662306a36Sopenharmony_ci	case MSR_F15H_IC_CFG: {
292762306a36Sopenharmony_ci
292862306a36Sopenharmony_ci		int family, model;
292962306a36Sopenharmony_ci
293062306a36Sopenharmony_ci		family = guest_cpuid_family(vcpu);
293162306a36Sopenharmony_ci		model  = guest_cpuid_model(vcpu);
293262306a36Sopenharmony_ci
293362306a36Sopenharmony_ci		if (family < 0 || model < 0)
293462306a36Sopenharmony_ci			return kvm_get_msr_common(vcpu, msr_info);
293562306a36Sopenharmony_ci
293662306a36Sopenharmony_ci		msr_info->data = 0;
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_ci		if (family == 0x15 &&
293962306a36Sopenharmony_ci		    (model >= 0x2 && model < 0x20))
294062306a36Sopenharmony_ci			msr_info->data = 0x1E;
294162306a36Sopenharmony_ci		}
294262306a36Sopenharmony_ci		break;
294362306a36Sopenharmony_ci	case MSR_AMD64_DE_CFG:
294462306a36Sopenharmony_ci		msr_info->data = svm->msr_decfg;
294562306a36Sopenharmony_ci		break;
294662306a36Sopenharmony_ci	default:
294762306a36Sopenharmony_ci		return kvm_get_msr_common(vcpu, msr_info);
294862306a36Sopenharmony_ci	}
294962306a36Sopenharmony_ci	return 0;
295062306a36Sopenharmony_ci}
295162306a36Sopenharmony_ci
295262306a36Sopenharmony_cistatic int svm_complete_emulated_msr(struct kvm_vcpu *vcpu, int err)
295362306a36Sopenharmony_ci{
295462306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
295562306a36Sopenharmony_ci	if (!err || !sev_es_guest(vcpu->kvm) || WARN_ON_ONCE(!svm->sev_es.ghcb))
295662306a36Sopenharmony_ci		return kvm_complete_insn_gp(vcpu, err);
295762306a36Sopenharmony_ci
295862306a36Sopenharmony_ci	ghcb_set_sw_exit_info_1(svm->sev_es.ghcb, 1);
295962306a36Sopenharmony_ci	ghcb_set_sw_exit_info_2(svm->sev_es.ghcb,
296062306a36Sopenharmony_ci				X86_TRAP_GP |
296162306a36Sopenharmony_ci				SVM_EVTINJ_TYPE_EXEPT |
296262306a36Sopenharmony_ci				SVM_EVTINJ_VALID);
296362306a36Sopenharmony_ci	return 1;
296462306a36Sopenharmony_ci}
296562306a36Sopenharmony_ci
296662306a36Sopenharmony_cistatic int svm_set_vm_cr(struct kvm_vcpu *vcpu, u64 data)
296762306a36Sopenharmony_ci{
296862306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
296962306a36Sopenharmony_ci	int svm_dis, chg_mask;
297062306a36Sopenharmony_ci
297162306a36Sopenharmony_ci	if (data & ~SVM_VM_CR_VALID_MASK)
297262306a36Sopenharmony_ci		return 1;
297362306a36Sopenharmony_ci
297462306a36Sopenharmony_ci	chg_mask = SVM_VM_CR_VALID_MASK;
297562306a36Sopenharmony_ci
297662306a36Sopenharmony_ci	if (svm->nested.vm_cr_msr & SVM_VM_CR_SVM_DIS_MASK)
297762306a36Sopenharmony_ci		chg_mask &= ~(SVM_VM_CR_SVM_LOCK_MASK | SVM_VM_CR_SVM_DIS_MASK);
297862306a36Sopenharmony_ci
297962306a36Sopenharmony_ci	svm->nested.vm_cr_msr &= ~chg_mask;
298062306a36Sopenharmony_ci	svm->nested.vm_cr_msr |= (data & chg_mask);
298162306a36Sopenharmony_ci
298262306a36Sopenharmony_ci	svm_dis = svm->nested.vm_cr_msr & SVM_VM_CR_SVM_DIS_MASK;
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci	/* check for svm_disable while efer.svme is set */
298562306a36Sopenharmony_ci	if (svm_dis && (vcpu->arch.efer & EFER_SVME))
298662306a36Sopenharmony_ci		return 1;
298762306a36Sopenharmony_ci
298862306a36Sopenharmony_ci	return 0;
298962306a36Sopenharmony_ci}
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_cistatic int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
299262306a36Sopenharmony_ci{
299362306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
299462306a36Sopenharmony_ci	int ret = 0;
299562306a36Sopenharmony_ci
299662306a36Sopenharmony_ci	u32 ecx = msr->index;
299762306a36Sopenharmony_ci	u64 data = msr->data;
299862306a36Sopenharmony_ci	switch (ecx) {
299962306a36Sopenharmony_ci	case MSR_AMD64_TSC_RATIO:
300062306a36Sopenharmony_ci
300162306a36Sopenharmony_ci		if (!guest_can_use(vcpu, X86_FEATURE_TSCRATEMSR)) {
300262306a36Sopenharmony_ci
300362306a36Sopenharmony_ci			if (!msr->host_initiated)
300462306a36Sopenharmony_ci				return 1;
300562306a36Sopenharmony_ci			/*
300662306a36Sopenharmony_ci			 * In case TSC scaling is not enabled, always
300762306a36Sopenharmony_ci			 * leave this MSR at the default value.
300862306a36Sopenharmony_ci			 *
300962306a36Sopenharmony_ci			 * Due to bug in qemu 6.2.0, it would try to set
301062306a36Sopenharmony_ci			 * this msr to 0 if tsc scaling is not enabled.
301162306a36Sopenharmony_ci			 * Ignore this value as well.
301262306a36Sopenharmony_ci			 */
301362306a36Sopenharmony_ci			if (data != 0 && data != svm->tsc_ratio_msr)
301462306a36Sopenharmony_ci				return 1;
301562306a36Sopenharmony_ci			break;
301662306a36Sopenharmony_ci		}
301762306a36Sopenharmony_ci
301862306a36Sopenharmony_ci		if (data & SVM_TSC_RATIO_RSVD)
301962306a36Sopenharmony_ci			return 1;
302062306a36Sopenharmony_ci
302162306a36Sopenharmony_ci		svm->tsc_ratio_msr = data;
302262306a36Sopenharmony_ci
302362306a36Sopenharmony_ci		if (guest_can_use(vcpu, X86_FEATURE_TSCRATEMSR) &&
302462306a36Sopenharmony_ci		    is_guest_mode(vcpu))
302562306a36Sopenharmony_ci			nested_svm_update_tsc_ratio_msr(vcpu);
302662306a36Sopenharmony_ci
302762306a36Sopenharmony_ci		break;
302862306a36Sopenharmony_ci	case MSR_IA32_CR_PAT:
302962306a36Sopenharmony_ci		ret = kvm_set_msr_common(vcpu, msr);
303062306a36Sopenharmony_ci		if (ret)
303162306a36Sopenharmony_ci			break;
303262306a36Sopenharmony_ci
303362306a36Sopenharmony_ci		svm->vmcb01.ptr->save.g_pat = data;
303462306a36Sopenharmony_ci		if (is_guest_mode(vcpu))
303562306a36Sopenharmony_ci			nested_vmcb02_compute_g_pat(svm);
303662306a36Sopenharmony_ci		vmcb_mark_dirty(svm->vmcb, VMCB_NPT);
303762306a36Sopenharmony_ci		break;
303862306a36Sopenharmony_ci	case MSR_IA32_SPEC_CTRL:
303962306a36Sopenharmony_ci		if (!msr->host_initiated &&
304062306a36Sopenharmony_ci		    !guest_has_spec_ctrl_msr(vcpu))
304162306a36Sopenharmony_ci			return 1;
304262306a36Sopenharmony_ci
304362306a36Sopenharmony_ci		if (kvm_spec_ctrl_test_value(data))
304462306a36Sopenharmony_ci			return 1;
304562306a36Sopenharmony_ci
304662306a36Sopenharmony_ci		if (boot_cpu_has(X86_FEATURE_V_SPEC_CTRL))
304762306a36Sopenharmony_ci			svm->vmcb->save.spec_ctrl = data;
304862306a36Sopenharmony_ci		else
304962306a36Sopenharmony_ci			svm->spec_ctrl = data;
305062306a36Sopenharmony_ci		if (!data)
305162306a36Sopenharmony_ci			break;
305262306a36Sopenharmony_ci
305362306a36Sopenharmony_ci		/*
305462306a36Sopenharmony_ci		 * For non-nested:
305562306a36Sopenharmony_ci		 * When it's written (to non-zero) for the first time, pass
305662306a36Sopenharmony_ci		 * it through.
305762306a36Sopenharmony_ci		 *
305862306a36Sopenharmony_ci		 * For nested:
305962306a36Sopenharmony_ci		 * The handling of the MSR bitmap for L2 guests is done in
306062306a36Sopenharmony_ci		 * nested_svm_vmrun_msrpm.
306162306a36Sopenharmony_ci		 * We update the L1 MSR bit as well since it will end up
306262306a36Sopenharmony_ci		 * touching the MSR anyway now.
306362306a36Sopenharmony_ci		 */
306462306a36Sopenharmony_ci		set_msr_interception(vcpu, svm->msrpm, MSR_IA32_SPEC_CTRL, 1, 1);
306562306a36Sopenharmony_ci		break;
306662306a36Sopenharmony_ci	case MSR_AMD64_VIRT_SPEC_CTRL:
306762306a36Sopenharmony_ci		if (!msr->host_initiated &&
306862306a36Sopenharmony_ci		    !guest_cpuid_has(vcpu, X86_FEATURE_VIRT_SSBD))
306962306a36Sopenharmony_ci			return 1;
307062306a36Sopenharmony_ci
307162306a36Sopenharmony_ci		if (data & ~SPEC_CTRL_SSBD)
307262306a36Sopenharmony_ci			return 1;
307362306a36Sopenharmony_ci
307462306a36Sopenharmony_ci		svm->virt_spec_ctrl = data;
307562306a36Sopenharmony_ci		break;
307662306a36Sopenharmony_ci	case MSR_STAR:
307762306a36Sopenharmony_ci		svm->vmcb01.ptr->save.star = data;
307862306a36Sopenharmony_ci		break;
307962306a36Sopenharmony_ci#ifdef CONFIG_X86_64
308062306a36Sopenharmony_ci	case MSR_LSTAR:
308162306a36Sopenharmony_ci		svm->vmcb01.ptr->save.lstar = data;
308262306a36Sopenharmony_ci		break;
308362306a36Sopenharmony_ci	case MSR_CSTAR:
308462306a36Sopenharmony_ci		svm->vmcb01.ptr->save.cstar = data;
308562306a36Sopenharmony_ci		break;
308662306a36Sopenharmony_ci	case MSR_KERNEL_GS_BASE:
308762306a36Sopenharmony_ci		svm->vmcb01.ptr->save.kernel_gs_base = data;
308862306a36Sopenharmony_ci		break;
308962306a36Sopenharmony_ci	case MSR_SYSCALL_MASK:
309062306a36Sopenharmony_ci		svm->vmcb01.ptr->save.sfmask = data;
309162306a36Sopenharmony_ci		break;
309262306a36Sopenharmony_ci#endif
309362306a36Sopenharmony_ci	case MSR_IA32_SYSENTER_CS:
309462306a36Sopenharmony_ci		svm->vmcb01.ptr->save.sysenter_cs = data;
309562306a36Sopenharmony_ci		break;
309662306a36Sopenharmony_ci	case MSR_IA32_SYSENTER_EIP:
309762306a36Sopenharmony_ci		svm->vmcb01.ptr->save.sysenter_eip = (u32)data;
309862306a36Sopenharmony_ci		/*
309962306a36Sopenharmony_ci		 * We only intercept the MSR_IA32_SYSENTER_{EIP|ESP} msrs
310062306a36Sopenharmony_ci		 * when we spoof an Intel vendor ID (for cross vendor migration).
310162306a36Sopenharmony_ci		 * In this case we use this intercept to track the high
310262306a36Sopenharmony_ci		 * 32 bit part of these msrs to support Intel's
310362306a36Sopenharmony_ci		 * implementation of SYSENTER/SYSEXIT.
310462306a36Sopenharmony_ci		 */
310562306a36Sopenharmony_ci		svm->sysenter_eip_hi = guest_cpuid_is_intel(vcpu) ? (data >> 32) : 0;
310662306a36Sopenharmony_ci		break;
310762306a36Sopenharmony_ci	case MSR_IA32_SYSENTER_ESP:
310862306a36Sopenharmony_ci		svm->vmcb01.ptr->save.sysenter_esp = (u32)data;
310962306a36Sopenharmony_ci		svm->sysenter_esp_hi = guest_cpuid_is_intel(vcpu) ? (data >> 32) : 0;
311062306a36Sopenharmony_ci		break;
311162306a36Sopenharmony_ci	case MSR_TSC_AUX:
311262306a36Sopenharmony_ci		/*
311362306a36Sopenharmony_ci		 * TSC_AUX is always virtualized for SEV-ES guests when the
311462306a36Sopenharmony_ci		 * feature is available. The user return MSR support is not
311562306a36Sopenharmony_ci		 * required in this case because TSC_AUX is restored on #VMEXIT
311662306a36Sopenharmony_ci		 * from the host save area (which has been initialized in
311762306a36Sopenharmony_ci		 * svm_hardware_enable()).
311862306a36Sopenharmony_ci		 */
311962306a36Sopenharmony_ci		if (boot_cpu_has(X86_FEATURE_V_TSC_AUX) && sev_es_guest(vcpu->kvm))
312062306a36Sopenharmony_ci			break;
312162306a36Sopenharmony_ci
312262306a36Sopenharmony_ci		/*
312362306a36Sopenharmony_ci		 * TSC_AUX is usually changed only during boot and never read
312462306a36Sopenharmony_ci		 * directly.  Intercept TSC_AUX instead of exposing it to the
312562306a36Sopenharmony_ci		 * guest via direct_access_msrs, and switch it via user return.
312662306a36Sopenharmony_ci		 */
312762306a36Sopenharmony_ci		preempt_disable();
312862306a36Sopenharmony_ci		ret = kvm_set_user_return_msr(tsc_aux_uret_slot, data, -1ull);
312962306a36Sopenharmony_ci		preempt_enable();
313062306a36Sopenharmony_ci		if (ret)
313162306a36Sopenharmony_ci			break;
313262306a36Sopenharmony_ci
313362306a36Sopenharmony_ci		svm->tsc_aux = data;
313462306a36Sopenharmony_ci		break;
313562306a36Sopenharmony_ci	case MSR_IA32_DEBUGCTLMSR:
313662306a36Sopenharmony_ci		if (!lbrv) {
313762306a36Sopenharmony_ci			kvm_pr_unimpl_wrmsr(vcpu, ecx, data);
313862306a36Sopenharmony_ci			break;
313962306a36Sopenharmony_ci		}
314062306a36Sopenharmony_ci		if (data & DEBUGCTL_RESERVED_BITS)
314162306a36Sopenharmony_ci			return 1;
314262306a36Sopenharmony_ci
314362306a36Sopenharmony_ci		svm_get_lbr_vmcb(svm)->save.dbgctl = data;
314462306a36Sopenharmony_ci		svm_update_lbrv(vcpu);
314562306a36Sopenharmony_ci		break;
314662306a36Sopenharmony_ci	case MSR_VM_HSAVE_PA:
314762306a36Sopenharmony_ci		/*
314862306a36Sopenharmony_ci		 * Old kernels did not validate the value written to
314962306a36Sopenharmony_ci		 * MSR_VM_HSAVE_PA.  Allow KVM_SET_MSR to set an invalid
315062306a36Sopenharmony_ci		 * value to allow live migrating buggy or malicious guests
315162306a36Sopenharmony_ci		 * originating from those kernels.
315262306a36Sopenharmony_ci		 */
315362306a36Sopenharmony_ci		if (!msr->host_initiated && !page_address_valid(vcpu, data))
315462306a36Sopenharmony_ci			return 1;
315562306a36Sopenharmony_ci
315662306a36Sopenharmony_ci		svm->nested.hsave_msr = data & PAGE_MASK;
315762306a36Sopenharmony_ci		break;
315862306a36Sopenharmony_ci	case MSR_VM_CR:
315962306a36Sopenharmony_ci		return svm_set_vm_cr(vcpu, data);
316062306a36Sopenharmony_ci	case MSR_VM_IGNNE:
316162306a36Sopenharmony_ci		kvm_pr_unimpl_wrmsr(vcpu, ecx, data);
316262306a36Sopenharmony_ci		break;
316362306a36Sopenharmony_ci	case MSR_AMD64_DE_CFG: {
316462306a36Sopenharmony_ci		struct kvm_msr_entry msr_entry;
316562306a36Sopenharmony_ci
316662306a36Sopenharmony_ci		msr_entry.index = msr->index;
316762306a36Sopenharmony_ci		if (svm_get_msr_feature(&msr_entry))
316862306a36Sopenharmony_ci			return 1;
316962306a36Sopenharmony_ci
317062306a36Sopenharmony_ci		/* Check the supported bits */
317162306a36Sopenharmony_ci		if (data & ~msr_entry.data)
317262306a36Sopenharmony_ci			return 1;
317362306a36Sopenharmony_ci
317462306a36Sopenharmony_ci		/* Don't allow the guest to change a bit, #GP */
317562306a36Sopenharmony_ci		if (!msr->host_initiated && (data ^ msr_entry.data))
317662306a36Sopenharmony_ci			return 1;
317762306a36Sopenharmony_ci
317862306a36Sopenharmony_ci		svm->msr_decfg = data;
317962306a36Sopenharmony_ci		break;
318062306a36Sopenharmony_ci	}
318162306a36Sopenharmony_ci	default:
318262306a36Sopenharmony_ci		return kvm_set_msr_common(vcpu, msr);
318362306a36Sopenharmony_ci	}
318462306a36Sopenharmony_ci	return ret;
318562306a36Sopenharmony_ci}
318662306a36Sopenharmony_ci
318762306a36Sopenharmony_cistatic int msr_interception(struct kvm_vcpu *vcpu)
318862306a36Sopenharmony_ci{
318962306a36Sopenharmony_ci	if (to_svm(vcpu)->vmcb->control.exit_info_1)
319062306a36Sopenharmony_ci		return kvm_emulate_wrmsr(vcpu);
319162306a36Sopenharmony_ci	else
319262306a36Sopenharmony_ci		return kvm_emulate_rdmsr(vcpu);
319362306a36Sopenharmony_ci}
319462306a36Sopenharmony_ci
319562306a36Sopenharmony_cistatic int interrupt_window_interception(struct kvm_vcpu *vcpu)
319662306a36Sopenharmony_ci{
319762306a36Sopenharmony_ci	kvm_make_request(KVM_REQ_EVENT, vcpu);
319862306a36Sopenharmony_ci	svm_clear_vintr(to_svm(vcpu));
319962306a36Sopenharmony_ci
320062306a36Sopenharmony_ci	/*
320162306a36Sopenharmony_ci	 * If not running nested, for AVIC, the only reason to end up here is ExtINTs.
320262306a36Sopenharmony_ci	 * In this case AVIC was temporarily disabled for
320362306a36Sopenharmony_ci	 * requesting the IRQ window and we have to re-enable it.
320462306a36Sopenharmony_ci	 *
320562306a36Sopenharmony_ci	 * If running nested, still remove the VM wide AVIC inhibit to
320662306a36Sopenharmony_ci	 * support case in which the interrupt window was requested when the
320762306a36Sopenharmony_ci	 * vCPU was not running nested.
320862306a36Sopenharmony_ci
320962306a36Sopenharmony_ci	 * All vCPUs which run still run nested, will remain to have their
321062306a36Sopenharmony_ci	 * AVIC still inhibited due to per-cpu AVIC inhibition.
321162306a36Sopenharmony_ci	 */
321262306a36Sopenharmony_ci	kvm_clear_apicv_inhibit(vcpu->kvm, APICV_INHIBIT_REASON_IRQWIN);
321362306a36Sopenharmony_ci
321462306a36Sopenharmony_ci	++vcpu->stat.irq_window_exits;
321562306a36Sopenharmony_ci	return 1;
321662306a36Sopenharmony_ci}
321762306a36Sopenharmony_ci
321862306a36Sopenharmony_cistatic int pause_interception(struct kvm_vcpu *vcpu)
321962306a36Sopenharmony_ci{
322062306a36Sopenharmony_ci	bool in_kernel;
322162306a36Sopenharmony_ci	/*
322262306a36Sopenharmony_ci	 * CPL is not made available for an SEV-ES guest, therefore
322362306a36Sopenharmony_ci	 * vcpu->arch.preempted_in_kernel can never be true.  Just
322462306a36Sopenharmony_ci	 * set in_kernel to false as well.
322562306a36Sopenharmony_ci	 */
322662306a36Sopenharmony_ci	in_kernel = !sev_es_guest(vcpu->kvm) && svm_get_cpl(vcpu) == 0;
322762306a36Sopenharmony_ci
322862306a36Sopenharmony_ci	grow_ple_window(vcpu);
322962306a36Sopenharmony_ci
323062306a36Sopenharmony_ci	kvm_vcpu_on_spin(vcpu, in_kernel);
323162306a36Sopenharmony_ci	return kvm_skip_emulated_instruction(vcpu);
323262306a36Sopenharmony_ci}
323362306a36Sopenharmony_ci
323462306a36Sopenharmony_cistatic int invpcid_interception(struct kvm_vcpu *vcpu)
323562306a36Sopenharmony_ci{
323662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
323762306a36Sopenharmony_ci	unsigned long type;
323862306a36Sopenharmony_ci	gva_t gva;
323962306a36Sopenharmony_ci
324062306a36Sopenharmony_ci	if (!guest_cpuid_has(vcpu, X86_FEATURE_INVPCID)) {
324162306a36Sopenharmony_ci		kvm_queue_exception(vcpu, UD_VECTOR);
324262306a36Sopenharmony_ci		return 1;
324362306a36Sopenharmony_ci	}
324462306a36Sopenharmony_ci
324562306a36Sopenharmony_ci	/*
324662306a36Sopenharmony_ci	 * For an INVPCID intercept:
324762306a36Sopenharmony_ci	 * EXITINFO1 provides the linear address of the memory operand.
324862306a36Sopenharmony_ci	 * EXITINFO2 provides the contents of the register operand.
324962306a36Sopenharmony_ci	 */
325062306a36Sopenharmony_ci	type = svm->vmcb->control.exit_info_2;
325162306a36Sopenharmony_ci	gva = svm->vmcb->control.exit_info_1;
325262306a36Sopenharmony_ci
325362306a36Sopenharmony_ci	return kvm_handle_invpcid(vcpu, type, gva);
325462306a36Sopenharmony_ci}
325562306a36Sopenharmony_ci
325662306a36Sopenharmony_cistatic int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = {
325762306a36Sopenharmony_ci	[SVM_EXIT_READ_CR0]			= cr_interception,
325862306a36Sopenharmony_ci	[SVM_EXIT_READ_CR3]			= cr_interception,
325962306a36Sopenharmony_ci	[SVM_EXIT_READ_CR4]			= cr_interception,
326062306a36Sopenharmony_ci	[SVM_EXIT_READ_CR8]			= cr_interception,
326162306a36Sopenharmony_ci	[SVM_EXIT_CR0_SEL_WRITE]		= cr_interception,
326262306a36Sopenharmony_ci	[SVM_EXIT_WRITE_CR0]			= cr_interception,
326362306a36Sopenharmony_ci	[SVM_EXIT_WRITE_CR3]			= cr_interception,
326462306a36Sopenharmony_ci	[SVM_EXIT_WRITE_CR4]			= cr_interception,
326562306a36Sopenharmony_ci	[SVM_EXIT_WRITE_CR8]			= cr8_write_interception,
326662306a36Sopenharmony_ci	[SVM_EXIT_READ_DR0]			= dr_interception,
326762306a36Sopenharmony_ci	[SVM_EXIT_READ_DR1]			= dr_interception,
326862306a36Sopenharmony_ci	[SVM_EXIT_READ_DR2]			= dr_interception,
326962306a36Sopenharmony_ci	[SVM_EXIT_READ_DR3]			= dr_interception,
327062306a36Sopenharmony_ci	[SVM_EXIT_READ_DR4]			= dr_interception,
327162306a36Sopenharmony_ci	[SVM_EXIT_READ_DR5]			= dr_interception,
327262306a36Sopenharmony_ci	[SVM_EXIT_READ_DR6]			= dr_interception,
327362306a36Sopenharmony_ci	[SVM_EXIT_READ_DR7]			= dr_interception,
327462306a36Sopenharmony_ci	[SVM_EXIT_WRITE_DR0]			= dr_interception,
327562306a36Sopenharmony_ci	[SVM_EXIT_WRITE_DR1]			= dr_interception,
327662306a36Sopenharmony_ci	[SVM_EXIT_WRITE_DR2]			= dr_interception,
327762306a36Sopenharmony_ci	[SVM_EXIT_WRITE_DR3]			= dr_interception,
327862306a36Sopenharmony_ci	[SVM_EXIT_WRITE_DR4]			= dr_interception,
327962306a36Sopenharmony_ci	[SVM_EXIT_WRITE_DR5]			= dr_interception,
328062306a36Sopenharmony_ci	[SVM_EXIT_WRITE_DR6]			= dr_interception,
328162306a36Sopenharmony_ci	[SVM_EXIT_WRITE_DR7]			= dr_interception,
328262306a36Sopenharmony_ci	[SVM_EXIT_EXCP_BASE + DB_VECTOR]	= db_interception,
328362306a36Sopenharmony_ci	[SVM_EXIT_EXCP_BASE + BP_VECTOR]	= bp_interception,
328462306a36Sopenharmony_ci	[SVM_EXIT_EXCP_BASE + UD_VECTOR]	= ud_interception,
328562306a36Sopenharmony_ci	[SVM_EXIT_EXCP_BASE + PF_VECTOR]	= pf_interception,
328662306a36Sopenharmony_ci	[SVM_EXIT_EXCP_BASE + MC_VECTOR]	= mc_interception,
328762306a36Sopenharmony_ci	[SVM_EXIT_EXCP_BASE + AC_VECTOR]	= ac_interception,
328862306a36Sopenharmony_ci	[SVM_EXIT_EXCP_BASE + GP_VECTOR]	= gp_interception,
328962306a36Sopenharmony_ci	[SVM_EXIT_INTR]				= intr_interception,
329062306a36Sopenharmony_ci	[SVM_EXIT_NMI]				= nmi_interception,
329162306a36Sopenharmony_ci	[SVM_EXIT_SMI]				= smi_interception,
329262306a36Sopenharmony_ci	[SVM_EXIT_VINTR]			= interrupt_window_interception,
329362306a36Sopenharmony_ci	[SVM_EXIT_RDPMC]			= kvm_emulate_rdpmc,
329462306a36Sopenharmony_ci	[SVM_EXIT_CPUID]			= kvm_emulate_cpuid,
329562306a36Sopenharmony_ci	[SVM_EXIT_IRET]                         = iret_interception,
329662306a36Sopenharmony_ci	[SVM_EXIT_INVD]                         = kvm_emulate_invd,
329762306a36Sopenharmony_ci	[SVM_EXIT_PAUSE]			= pause_interception,
329862306a36Sopenharmony_ci	[SVM_EXIT_HLT]				= kvm_emulate_halt,
329962306a36Sopenharmony_ci	[SVM_EXIT_INVLPG]			= invlpg_interception,
330062306a36Sopenharmony_ci	[SVM_EXIT_INVLPGA]			= invlpga_interception,
330162306a36Sopenharmony_ci	[SVM_EXIT_IOIO]				= io_interception,
330262306a36Sopenharmony_ci	[SVM_EXIT_MSR]				= msr_interception,
330362306a36Sopenharmony_ci	[SVM_EXIT_TASK_SWITCH]			= task_switch_interception,
330462306a36Sopenharmony_ci	[SVM_EXIT_SHUTDOWN]			= shutdown_interception,
330562306a36Sopenharmony_ci	[SVM_EXIT_VMRUN]			= vmrun_interception,
330662306a36Sopenharmony_ci	[SVM_EXIT_VMMCALL]			= kvm_emulate_hypercall,
330762306a36Sopenharmony_ci	[SVM_EXIT_VMLOAD]			= vmload_interception,
330862306a36Sopenharmony_ci	[SVM_EXIT_VMSAVE]			= vmsave_interception,
330962306a36Sopenharmony_ci	[SVM_EXIT_STGI]				= stgi_interception,
331062306a36Sopenharmony_ci	[SVM_EXIT_CLGI]				= clgi_interception,
331162306a36Sopenharmony_ci	[SVM_EXIT_SKINIT]			= skinit_interception,
331262306a36Sopenharmony_ci	[SVM_EXIT_RDTSCP]			= kvm_handle_invalid_op,
331362306a36Sopenharmony_ci	[SVM_EXIT_WBINVD]                       = kvm_emulate_wbinvd,
331462306a36Sopenharmony_ci	[SVM_EXIT_MONITOR]			= kvm_emulate_monitor,
331562306a36Sopenharmony_ci	[SVM_EXIT_MWAIT]			= kvm_emulate_mwait,
331662306a36Sopenharmony_ci	[SVM_EXIT_XSETBV]			= kvm_emulate_xsetbv,
331762306a36Sopenharmony_ci	[SVM_EXIT_RDPRU]			= kvm_handle_invalid_op,
331862306a36Sopenharmony_ci	[SVM_EXIT_EFER_WRITE_TRAP]		= efer_trap,
331962306a36Sopenharmony_ci	[SVM_EXIT_CR0_WRITE_TRAP]		= cr_trap,
332062306a36Sopenharmony_ci	[SVM_EXIT_CR4_WRITE_TRAP]		= cr_trap,
332162306a36Sopenharmony_ci	[SVM_EXIT_CR8_WRITE_TRAP]		= cr_trap,
332262306a36Sopenharmony_ci	[SVM_EXIT_INVPCID]                      = invpcid_interception,
332362306a36Sopenharmony_ci	[SVM_EXIT_NPF]				= npf_interception,
332462306a36Sopenharmony_ci	[SVM_EXIT_RSM]                          = rsm_interception,
332562306a36Sopenharmony_ci	[SVM_EXIT_AVIC_INCOMPLETE_IPI]		= avic_incomplete_ipi_interception,
332662306a36Sopenharmony_ci	[SVM_EXIT_AVIC_UNACCELERATED_ACCESS]	= avic_unaccelerated_access_interception,
332762306a36Sopenharmony_ci	[SVM_EXIT_VMGEXIT]			= sev_handle_vmgexit,
332862306a36Sopenharmony_ci};
332962306a36Sopenharmony_ci
333062306a36Sopenharmony_cistatic void dump_vmcb(struct kvm_vcpu *vcpu)
333162306a36Sopenharmony_ci{
333262306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
333362306a36Sopenharmony_ci	struct vmcb_control_area *control = &svm->vmcb->control;
333462306a36Sopenharmony_ci	struct vmcb_save_area *save = &svm->vmcb->save;
333562306a36Sopenharmony_ci	struct vmcb_save_area *save01 = &svm->vmcb01.ptr->save;
333662306a36Sopenharmony_ci
333762306a36Sopenharmony_ci	if (!dump_invalid_vmcb) {
333862306a36Sopenharmony_ci		pr_warn_ratelimited("set kvm_amd.dump_invalid_vmcb=1 to dump internal KVM state.\n");
333962306a36Sopenharmony_ci		return;
334062306a36Sopenharmony_ci	}
334162306a36Sopenharmony_ci
334262306a36Sopenharmony_ci	pr_err("VMCB %p, last attempted VMRUN on CPU %d\n",
334362306a36Sopenharmony_ci	       svm->current_vmcb->ptr, vcpu->arch.last_vmentry_cpu);
334462306a36Sopenharmony_ci	pr_err("VMCB Control Area:\n");
334562306a36Sopenharmony_ci	pr_err("%-20s%04x\n", "cr_read:", control->intercepts[INTERCEPT_CR] & 0xffff);
334662306a36Sopenharmony_ci	pr_err("%-20s%04x\n", "cr_write:", control->intercepts[INTERCEPT_CR] >> 16);
334762306a36Sopenharmony_ci	pr_err("%-20s%04x\n", "dr_read:", control->intercepts[INTERCEPT_DR] & 0xffff);
334862306a36Sopenharmony_ci	pr_err("%-20s%04x\n", "dr_write:", control->intercepts[INTERCEPT_DR] >> 16);
334962306a36Sopenharmony_ci	pr_err("%-20s%08x\n", "exceptions:", control->intercepts[INTERCEPT_EXCEPTION]);
335062306a36Sopenharmony_ci	pr_err("%-20s%08x %08x\n", "intercepts:",
335162306a36Sopenharmony_ci              control->intercepts[INTERCEPT_WORD3],
335262306a36Sopenharmony_ci	       control->intercepts[INTERCEPT_WORD4]);
335362306a36Sopenharmony_ci	pr_err("%-20s%d\n", "pause filter count:", control->pause_filter_count);
335462306a36Sopenharmony_ci	pr_err("%-20s%d\n", "pause filter threshold:",
335562306a36Sopenharmony_ci	       control->pause_filter_thresh);
335662306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "iopm_base_pa:", control->iopm_base_pa);
335762306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "msrpm_base_pa:", control->msrpm_base_pa);
335862306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "tsc_offset:", control->tsc_offset);
335962306a36Sopenharmony_ci	pr_err("%-20s%d\n", "asid:", control->asid);
336062306a36Sopenharmony_ci	pr_err("%-20s%d\n", "tlb_ctl:", control->tlb_ctl);
336162306a36Sopenharmony_ci	pr_err("%-20s%08x\n", "int_ctl:", control->int_ctl);
336262306a36Sopenharmony_ci	pr_err("%-20s%08x\n", "int_vector:", control->int_vector);
336362306a36Sopenharmony_ci	pr_err("%-20s%08x\n", "int_state:", control->int_state);
336462306a36Sopenharmony_ci	pr_err("%-20s%08x\n", "exit_code:", control->exit_code);
336562306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "exit_info1:", control->exit_info_1);
336662306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "exit_info2:", control->exit_info_2);
336762306a36Sopenharmony_ci	pr_err("%-20s%08x\n", "exit_int_info:", control->exit_int_info);
336862306a36Sopenharmony_ci	pr_err("%-20s%08x\n", "exit_int_info_err:", control->exit_int_info_err);
336962306a36Sopenharmony_ci	pr_err("%-20s%lld\n", "nested_ctl:", control->nested_ctl);
337062306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "nested_cr3:", control->nested_cr3);
337162306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "avic_vapic_bar:", control->avic_vapic_bar);
337262306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "ghcb:", control->ghcb_gpa);
337362306a36Sopenharmony_ci	pr_err("%-20s%08x\n", "event_inj:", control->event_inj);
337462306a36Sopenharmony_ci	pr_err("%-20s%08x\n", "event_inj_err:", control->event_inj_err);
337562306a36Sopenharmony_ci	pr_err("%-20s%lld\n", "virt_ext:", control->virt_ext);
337662306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "next_rip:", control->next_rip);
337762306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "avic_backing_page:", control->avic_backing_page);
337862306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "avic_logical_id:", control->avic_logical_id);
337962306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "avic_physical_id:", control->avic_physical_id);
338062306a36Sopenharmony_ci	pr_err("%-20s%016llx\n", "vmsa_pa:", control->vmsa_pa);
338162306a36Sopenharmony_ci	pr_err("VMCB State Save Area:\n");
338262306a36Sopenharmony_ci	pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
338362306a36Sopenharmony_ci	       "es:",
338462306a36Sopenharmony_ci	       save->es.selector, save->es.attrib,
338562306a36Sopenharmony_ci	       save->es.limit, save->es.base);
338662306a36Sopenharmony_ci	pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
338762306a36Sopenharmony_ci	       "cs:",
338862306a36Sopenharmony_ci	       save->cs.selector, save->cs.attrib,
338962306a36Sopenharmony_ci	       save->cs.limit, save->cs.base);
339062306a36Sopenharmony_ci	pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
339162306a36Sopenharmony_ci	       "ss:",
339262306a36Sopenharmony_ci	       save->ss.selector, save->ss.attrib,
339362306a36Sopenharmony_ci	       save->ss.limit, save->ss.base);
339462306a36Sopenharmony_ci	pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
339562306a36Sopenharmony_ci	       "ds:",
339662306a36Sopenharmony_ci	       save->ds.selector, save->ds.attrib,
339762306a36Sopenharmony_ci	       save->ds.limit, save->ds.base);
339862306a36Sopenharmony_ci	pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
339962306a36Sopenharmony_ci	       "fs:",
340062306a36Sopenharmony_ci	       save01->fs.selector, save01->fs.attrib,
340162306a36Sopenharmony_ci	       save01->fs.limit, save01->fs.base);
340262306a36Sopenharmony_ci	pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
340362306a36Sopenharmony_ci	       "gs:",
340462306a36Sopenharmony_ci	       save01->gs.selector, save01->gs.attrib,
340562306a36Sopenharmony_ci	       save01->gs.limit, save01->gs.base);
340662306a36Sopenharmony_ci	pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
340762306a36Sopenharmony_ci	       "gdtr:",
340862306a36Sopenharmony_ci	       save->gdtr.selector, save->gdtr.attrib,
340962306a36Sopenharmony_ci	       save->gdtr.limit, save->gdtr.base);
341062306a36Sopenharmony_ci	pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
341162306a36Sopenharmony_ci	       "ldtr:",
341262306a36Sopenharmony_ci	       save01->ldtr.selector, save01->ldtr.attrib,
341362306a36Sopenharmony_ci	       save01->ldtr.limit, save01->ldtr.base);
341462306a36Sopenharmony_ci	pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
341562306a36Sopenharmony_ci	       "idtr:",
341662306a36Sopenharmony_ci	       save->idtr.selector, save->idtr.attrib,
341762306a36Sopenharmony_ci	       save->idtr.limit, save->idtr.base);
341862306a36Sopenharmony_ci	pr_err("%-5s s: %04x a: %04x l: %08x b: %016llx\n",
341962306a36Sopenharmony_ci	       "tr:",
342062306a36Sopenharmony_ci	       save01->tr.selector, save01->tr.attrib,
342162306a36Sopenharmony_ci	       save01->tr.limit, save01->tr.base);
342262306a36Sopenharmony_ci	pr_err("vmpl: %d   cpl:  %d               efer:          %016llx\n",
342362306a36Sopenharmony_ci	       save->vmpl, save->cpl, save->efer);
342462306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
342562306a36Sopenharmony_ci	       "cr0:", save->cr0, "cr2:", save->cr2);
342662306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
342762306a36Sopenharmony_ci	       "cr3:", save->cr3, "cr4:", save->cr4);
342862306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
342962306a36Sopenharmony_ci	       "dr6:", save->dr6, "dr7:", save->dr7);
343062306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
343162306a36Sopenharmony_ci	       "rip:", save->rip, "rflags:", save->rflags);
343262306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
343362306a36Sopenharmony_ci	       "rsp:", save->rsp, "rax:", save->rax);
343462306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
343562306a36Sopenharmony_ci	       "star:", save01->star, "lstar:", save01->lstar);
343662306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
343762306a36Sopenharmony_ci	       "cstar:", save01->cstar, "sfmask:", save01->sfmask);
343862306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
343962306a36Sopenharmony_ci	       "kernel_gs_base:", save01->kernel_gs_base,
344062306a36Sopenharmony_ci	       "sysenter_cs:", save01->sysenter_cs);
344162306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
344262306a36Sopenharmony_ci	       "sysenter_esp:", save01->sysenter_esp,
344362306a36Sopenharmony_ci	       "sysenter_eip:", save01->sysenter_eip);
344462306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
344562306a36Sopenharmony_ci	       "gpat:", save->g_pat, "dbgctl:", save->dbgctl);
344662306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
344762306a36Sopenharmony_ci	       "br_from:", save->br_from, "br_to:", save->br_to);
344862306a36Sopenharmony_ci	pr_err("%-15s %016llx %-13s %016llx\n",
344962306a36Sopenharmony_ci	       "excp_from:", save->last_excp_from,
345062306a36Sopenharmony_ci	       "excp_to:", save->last_excp_to);
345162306a36Sopenharmony_ci}
345262306a36Sopenharmony_ci
345362306a36Sopenharmony_cistatic bool svm_check_exit_valid(u64 exit_code)
345462306a36Sopenharmony_ci{
345562306a36Sopenharmony_ci	return (exit_code < ARRAY_SIZE(svm_exit_handlers) &&
345662306a36Sopenharmony_ci		svm_exit_handlers[exit_code]);
345762306a36Sopenharmony_ci}
345862306a36Sopenharmony_ci
345962306a36Sopenharmony_cistatic int svm_handle_invalid_exit(struct kvm_vcpu *vcpu, u64 exit_code)
346062306a36Sopenharmony_ci{
346162306a36Sopenharmony_ci	vcpu_unimpl(vcpu, "svm: unexpected exit reason 0x%llx\n", exit_code);
346262306a36Sopenharmony_ci	dump_vmcb(vcpu);
346362306a36Sopenharmony_ci	vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
346462306a36Sopenharmony_ci	vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON;
346562306a36Sopenharmony_ci	vcpu->run->internal.ndata = 2;
346662306a36Sopenharmony_ci	vcpu->run->internal.data[0] = exit_code;
346762306a36Sopenharmony_ci	vcpu->run->internal.data[1] = vcpu->arch.last_vmentry_cpu;
346862306a36Sopenharmony_ci	return 0;
346962306a36Sopenharmony_ci}
347062306a36Sopenharmony_ci
347162306a36Sopenharmony_ciint svm_invoke_exit_handler(struct kvm_vcpu *vcpu, u64 exit_code)
347262306a36Sopenharmony_ci{
347362306a36Sopenharmony_ci	if (!svm_check_exit_valid(exit_code))
347462306a36Sopenharmony_ci		return svm_handle_invalid_exit(vcpu, exit_code);
347562306a36Sopenharmony_ci
347662306a36Sopenharmony_ci#ifdef CONFIG_RETPOLINE
347762306a36Sopenharmony_ci	if (exit_code == SVM_EXIT_MSR)
347862306a36Sopenharmony_ci		return msr_interception(vcpu);
347962306a36Sopenharmony_ci	else if (exit_code == SVM_EXIT_VINTR)
348062306a36Sopenharmony_ci		return interrupt_window_interception(vcpu);
348162306a36Sopenharmony_ci	else if (exit_code == SVM_EXIT_INTR)
348262306a36Sopenharmony_ci		return intr_interception(vcpu);
348362306a36Sopenharmony_ci	else if (exit_code == SVM_EXIT_HLT)
348462306a36Sopenharmony_ci		return kvm_emulate_halt(vcpu);
348562306a36Sopenharmony_ci	else if (exit_code == SVM_EXIT_NPF)
348662306a36Sopenharmony_ci		return npf_interception(vcpu);
348762306a36Sopenharmony_ci#endif
348862306a36Sopenharmony_ci	return svm_exit_handlers[exit_code](vcpu);
348962306a36Sopenharmony_ci}
349062306a36Sopenharmony_ci
349162306a36Sopenharmony_cistatic void svm_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason,
349262306a36Sopenharmony_ci			      u64 *info1, u64 *info2,
349362306a36Sopenharmony_ci			      u32 *intr_info, u32 *error_code)
349462306a36Sopenharmony_ci{
349562306a36Sopenharmony_ci	struct vmcb_control_area *control = &to_svm(vcpu)->vmcb->control;
349662306a36Sopenharmony_ci
349762306a36Sopenharmony_ci	*reason = control->exit_code;
349862306a36Sopenharmony_ci	*info1 = control->exit_info_1;
349962306a36Sopenharmony_ci	*info2 = control->exit_info_2;
350062306a36Sopenharmony_ci	*intr_info = control->exit_int_info;
350162306a36Sopenharmony_ci	if ((*intr_info & SVM_EXITINTINFO_VALID) &&
350262306a36Sopenharmony_ci	    (*intr_info & SVM_EXITINTINFO_VALID_ERR))
350362306a36Sopenharmony_ci		*error_code = control->exit_int_info_err;
350462306a36Sopenharmony_ci	else
350562306a36Sopenharmony_ci		*error_code = 0;
350662306a36Sopenharmony_ci}
350762306a36Sopenharmony_ci
350862306a36Sopenharmony_cistatic int svm_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
350962306a36Sopenharmony_ci{
351062306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
351162306a36Sopenharmony_ci	struct kvm_run *kvm_run = vcpu->run;
351262306a36Sopenharmony_ci	u32 exit_code = svm->vmcb->control.exit_code;
351362306a36Sopenharmony_ci
351462306a36Sopenharmony_ci	/* SEV-ES guests must use the CR write traps to track CR registers. */
351562306a36Sopenharmony_ci	if (!sev_es_guest(vcpu->kvm)) {
351662306a36Sopenharmony_ci		if (!svm_is_intercept(svm, INTERCEPT_CR0_WRITE))
351762306a36Sopenharmony_ci			vcpu->arch.cr0 = svm->vmcb->save.cr0;
351862306a36Sopenharmony_ci		if (npt_enabled)
351962306a36Sopenharmony_ci			vcpu->arch.cr3 = svm->vmcb->save.cr3;
352062306a36Sopenharmony_ci	}
352162306a36Sopenharmony_ci
352262306a36Sopenharmony_ci	if (is_guest_mode(vcpu)) {
352362306a36Sopenharmony_ci		int vmexit;
352462306a36Sopenharmony_ci
352562306a36Sopenharmony_ci		trace_kvm_nested_vmexit(vcpu, KVM_ISA_SVM);
352662306a36Sopenharmony_ci
352762306a36Sopenharmony_ci		vmexit = nested_svm_exit_special(svm);
352862306a36Sopenharmony_ci
352962306a36Sopenharmony_ci		if (vmexit == NESTED_EXIT_CONTINUE)
353062306a36Sopenharmony_ci			vmexit = nested_svm_exit_handled(svm);
353162306a36Sopenharmony_ci
353262306a36Sopenharmony_ci		if (vmexit == NESTED_EXIT_DONE)
353362306a36Sopenharmony_ci			return 1;
353462306a36Sopenharmony_ci	}
353562306a36Sopenharmony_ci
353662306a36Sopenharmony_ci	if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
353762306a36Sopenharmony_ci		kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
353862306a36Sopenharmony_ci		kvm_run->fail_entry.hardware_entry_failure_reason
353962306a36Sopenharmony_ci			= svm->vmcb->control.exit_code;
354062306a36Sopenharmony_ci		kvm_run->fail_entry.cpu = vcpu->arch.last_vmentry_cpu;
354162306a36Sopenharmony_ci		dump_vmcb(vcpu);
354262306a36Sopenharmony_ci		return 0;
354362306a36Sopenharmony_ci	}
354462306a36Sopenharmony_ci
354562306a36Sopenharmony_ci	if (exit_fastpath != EXIT_FASTPATH_NONE)
354662306a36Sopenharmony_ci		return 1;
354762306a36Sopenharmony_ci
354862306a36Sopenharmony_ci	return svm_invoke_exit_handler(vcpu, exit_code);
354962306a36Sopenharmony_ci}
355062306a36Sopenharmony_ci
355162306a36Sopenharmony_cistatic void pre_svm_run(struct kvm_vcpu *vcpu)
355262306a36Sopenharmony_ci{
355362306a36Sopenharmony_ci	struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu);
355462306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
355562306a36Sopenharmony_ci
355662306a36Sopenharmony_ci	/*
355762306a36Sopenharmony_ci	 * If the previous vmrun of the vmcb occurred on a different physical
355862306a36Sopenharmony_ci	 * cpu, then mark the vmcb dirty and assign a new asid.  Hardware's
355962306a36Sopenharmony_ci	 * vmcb clean bits are per logical CPU, as are KVM's asid assignments.
356062306a36Sopenharmony_ci	 */
356162306a36Sopenharmony_ci	if (unlikely(svm->current_vmcb->cpu != vcpu->cpu)) {
356262306a36Sopenharmony_ci		svm->current_vmcb->asid_generation = 0;
356362306a36Sopenharmony_ci		vmcb_mark_all_dirty(svm->vmcb);
356462306a36Sopenharmony_ci		svm->current_vmcb->cpu = vcpu->cpu;
356562306a36Sopenharmony_ci        }
356662306a36Sopenharmony_ci
356762306a36Sopenharmony_ci	if (sev_guest(vcpu->kvm))
356862306a36Sopenharmony_ci		return pre_sev_run(svm, vcpu->cpu);
356962306a36Sopenharmony_ci
357062306a36Sopenharmony_ci	/* FIXME: handle wraparound of asid_generation */
357162306a36Sopenharmony_ci	if (svm->current_vmcb->asid_generation != sd->asid_generation)
357262306a36Sopenharmony_ci		new_asid(svm, sd);
357362306a36Sopenharmony_ci}
357462306a36Sopenharmony_ci
357562306a36Sopenharmony_cistatic void svm_inject_nmi(struct kvm_vcpu *vcpu)
357662306a36Sopenharmony_ci{
357762306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
357862306a36Sopenharmony_ci
357962306a36Sopenharmony_ci	svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI;
358062306a36Sopenharmony_ci
358162306a36Sopenharmony_ci	if (svm->nmi_l1_to_l2)
358262306a36Sopenharmony_ci		return;
358362306a36Sopenharmony_ci
358462306a36Sopenharmony_ci	svm->nmi_masked = true;
358562306a36Sopenharmony_ci	svm_set_iret_intercept(svm);
358662306a36Sopenharmony_ci	++vcpu->stat.nmi_injections;
358762306a36Sopenharmony_ci}
358862306a36Sopenharmony_ci
358962306a36Sopenharmony_cistatic bool svm_is_vnmi_pending(struct kvm_vcpu *vcpu)
359062306a36Sopenharmony_ci{
359162306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
359262306a36Sopenharmony_ci
359362306a36Sopenharmony_ci	if (!is_vnmi_enabled(svm))
359462306a36Sopenharmony_ci		return false;
359562306a36Sopenharmony_ci
359662306a36Sopenharmony_ci	return !!(svm->vmcb->control.int_ctl & V_NMI_PENDING_MASK);
359762306a36Sopenharmony_ci}
359862306a36Sopenharmony_ci
359962306a36Sopenharmony_cistatic bool svm_set_vnmi_pending(struct kvm_vcpu *vcpu)
360062306a36Sopenharmony_ci{
360162306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
360262306a36Sopenharmony_ci
360362306a36Sopenharmony_ci	if (!is_vnmi_enabled(svm))
360462306a36Sopenharmony_ci		return false;
360562306a36Sopenharmony_ci
360662306a36Sopenharmony_ci	if (svm->vmcb->control.int_ctl & V_NMI_PENDING_MASK)
360762306a36Sopenharmony_ci		return false;
360862306a36Sopenharmony_ci
360962306a36Sopenharmony_ci	svm->vmcb->control.int_ctl |= V_NMI_PENDING_MASK;
361062306a36Sopenharmony_ci	vmcb_mark_dirty(svm->vmcb, VMCB_INTR);
361162306a36Sopenharmony_ci
361262306a36Sopenharmony_ci	/*
361362306a36Sopenharmony_ci	 * Because the pending NMI is serviced by hardware, KVM can't know when
361462306a36Sopenharmony_ci	 * the NMI is "injected", but for all intents and purposes, passing the
361562306a36Sopenharmony_ci	 * NMI off to hardware counts as injection.
361662306a36Sopenharmony_ci	 */
361762306a36Sopenharmony_ci	++vcpu->stat.nmi_injections;
361862306a36Sopenharmony_ci
361962306a36Sopenharmony_ci	return true;
362062306a36Sopenharmony_ci}
362162306a36Sopenharmony_ci
362262306a36Sopenharmony_cistatic void svm_inject_irq(struct kvm_vcpu *vcpu, bool reinjected)
362362306a36Sopenharmony_ci{
362462306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
362562306a36Sopenharmony_ci	u32 type;
362662306a36Sopenharmony_ci
362762306a36Sopenharmony_ci	if (vcpu->arch.interrupt.soft) {
362862306a36Sopenharmony_ci		if (svm_update_soft_interrupt_rip(vcpu))
362962306a36Sopenharmony_ci			return;
363062306a36Sopenharmony_ci
363162306a36Sopenharmony_ci		type = SVM_EVTINJ_TYPE_SOFT;
363262306a36Sopenharmony_ci	} else {
363362306a36Sopenharmony_ci		type = SVM_EVTINJ_TYPE_INTR;
363462306a36Sopenharmony_ci	}
363562306a36Sopenharmony_ci
363662306a36Sopenharmony_ci	trace_kvm_inj_virq(vcpu->arch.interrupt.nr,
363762306a36Sopenharmony_ci			   vcpu->arch.interrupt.soft, reinjected);
363862306a36Sopenharmony_ci	++vcpu->stat.irq_injections;
363962306a36Sopenharmony_ci
364062306a36Sopenharmony_ci	svm->vmcb->control.event_inj = vcpu->arch.interrupt.nr |
364162306a36Sopenharmony_ci				       SVM_EVTINJ_VALID | type;
364262306a36Sopenharmony_ci}
364362306a36Sopenharmony_ci
364462306a36Sopenharmony_civoid svm_complete_interrupt_delivery(struct kvm_vcpu *vcpu, int delivery_mode,
364562306a36Sopenharmony_ci				     int trig_mode, int vector)
364662306a36Sopenharmony_ci{
364762306a36Sopenharmony_ci	/*
364862306a36Sopenharmony_ci	 * apic->apicv_active must be read after vcpu->mode.
364962306a36Sopenharmony_ci	 * Pairs with smp_store_release in vcpu_enter_guest.
365062306a36Sopenharmony_ci	 */
365162306a36Sopenharmony_ci	bool in_guest_mode = (smp_load_acquire(&vcpu->mode) == IN_GUEST_MODE);
365262306a36Sopenharmony_ci
365362306a36Sopenharmony_ci	/* Note, this is called iff the local APIC is in-kernel. */
365462306a36Sopenharmony_ci	if (!READ_ONCE(vcpu->arch.apic->apicv_active)) {
365562306a36Sopenharmony_ci		/* Process the interrupt via kvm_check_and_inject_events(). */
365662306a36Sopenharmony_ci		kvm_make_request(KVM_REQ_EVENT, vcpu);
365762306a36Sopenharmony_ci		kvm_vcpu_kick(vcpu);
365862306a36Sopenharmony_ci		return;
365962306a36Sopenharmony_ci	}
366062306a36Sopenharmony_ci
366162306a36Sopenharmony_ci	trace_kvm_apicv_accept_irq(vcpu->vcpu_id, delivery_mode, trig_mode, vector);
366262306a36Sopenharmony_ci	if (in_guest_mode) {
366362306a36Sopenharmony_ci		/*
366462306a36Sopenharmony_ci		 * Signal the doorbell to tell hardware to inject the IRQ.  If
366562306a36Sopenharmony_ci		 * the vCPU exits the guest before the doorbell chimes, hardware
366662306a36Sopenharmony_ci		 * will automatically process AVIC interrupts at the next VMRUN.
366762306a36Sopenharmony_ci		 */
366862306a36Sopenharmony_ci		avic_ring_doorbell(vcpu);
366962306a36Sopenharmony_ci	} else {
367062306a36Sopenharmony_ci		/*
367162306a36Sopenharmony_ci		 * Wake the vCPU if it was blocking.  KVM will then detect the
367262306a36Sopenharmony_ci		 * pending IRQ when checking if the vCPU has a wake event.
367362306a36Sopenharmony_ci		 */
367462306a36Sopenharmony_ci		kvm_vcpu_wake_up(vcpu);
367562306a36Sopenharmony_ci	}
367662306a36Sopenharmony_ci}
367762306a36Sopenharmony_ci
367862306a36Sopenharmony_cistatic void svm_deliver_interrupt(struct kvm_lapic *apic,  int delivery_mode,
367962306a36Sopenharmony_ci				  int trig_mode, int vector)
368062306a36Sopenharmony_ci{
368162306a36Sopenharmony_ci	kvm_lapic_set_irr(vector, apic);
368262306a36Sopenharmony_ci
368362306a36Sopenharmony_ci	/*
368462306a36Sopenharmony_ci	 * Pairs with the smp_mb_*() after setting vcpu->guest_mode in
368562306a36Sopenharmony_ci	 * vcpu_enter_guest() to ensure the write to the vIRR is ordered before
368662306a36Sopenharmony_ci	 * the read of guest_mode.  This guarantees that either VMRUN will see
368762306a36Sopenharmony_ci	 * and process the new vIRR entry, or that svm_complete_interrupt_delivery
368862306a36Sopenharmony_ci	 * will signal the doorbell if the CPU has already entered the guest.
368962306a36Sopenharmony_ci	 */
369062306a36Sopenharmony_ci	smp_mb__after_atomic();
369162306a36Sopenharmony_ci	svm_complete_interrupt_delivery(apic->vcpu, delivery_mode, trig_mode, vector);
369262306a36Sopenharmony_ci}
369362306a36Sopenharmony_ci
369462306a36Sopenharmony_cistatic void svm_update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
369562306a36Sopenharmony_ci{
369662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
369762306a36Sopenharmony_ci
369862306a36Sopenharmony_ci	/*
369962306a36Sopenharmony_ci	 * SEV-ES guests must always keep the CR intercepts cleared. CR
370062306a36Sopenharmony_ci	 * tracking is done using the CR write traps.
370162306a36Sopenharmony_ci	 */
370262306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm))
370362306a36Sopenharmony_ci		return;
370462306a36Sopenharmony_ci
370562306a36Sopenharmony_ci	if (nested_svm_virtualize_tpr(vcpu))
370662306a36Sopenharmony_ci		return;
370762306a36Sopenharmony_ci
370862306a36Sopenharmony_ci	svm_clr_intercept(svm, INTERCEPT_CR8_WRITE);
370962306a36Sopenharmony_ci
371062306a36Sopenharmony_ci	if (irr == -1)
371162306a36Sopenharmony_ci		return;
371262306a36Sopenharmony_ci
371362306a36Sopenharmony_ci	if (tpr >= irr)
371462306a36Sopenharmony_ci		svm_set_intercept(svm, INTERCEPT_CR8_WRITE);
371562306a36Sopenharmony_ci}
371662306a36Sopenharmony_ci
371762306a36Sopenharmony_cistatic bool svm_get_nmi_mask(struct kvm_vcpu *vcpu)
371862306a36Sopenharmony_ci{
371962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
372062306a36Sopenharmony_ci
372162306a36Sopenharmony_ci	if (is_vnmi_enabled(svm))
372262306a36Sopenharmony_ci		return svm->vmcb->control.int_ctl & V_NMI_BLOCKING_MASK;
372362306a36Sopenharmony_ci	else
372462306a36Sopenharmony_ci		return svm->nmi_masked;
372562306a36Sopenharmony_ci}
372662306a36Sopenharmony_ci
372762306a36Sopenharmony_cistatic void svm_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked)
372862306a36Sopenharmony_ci{
372962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
373062306a36Sopenharmony_ci
373162306a36Sopenharmony_ci	if (is_vnmi_enabled(svm)) {
373262306a36Sopenharmony_ci		if (masked)
373362306a36Sopenharmony_ci			svm->vmcb->control.int_ctl |= V_NMI_BLOCKING_MASK;
373462306a36Sopenharmony_ci		else
373562306a36Sopenharmony_ci			svm->vmcb->control.int_ctl &= ~V_NMI_BLOCKING_MASK;
373662306a36Sopenharmony_ci
373762306a36Sopenharmony_ci	} else {
373862306a36Sopenharmony_ci		svm->nmi_masked = masked;
373962306a36Sopenharmony_ci		if (masked)
374062306a36Sopenharmony_ci			svm_set_iret_intercept(svm);
374162306a36Sopenharmony_ci		else
374262306a36Sopenharmony_ci			svm_clr_iret_intercept(svm);
374362306a36Sopenharmony_ci	}
374462306a36Sopenharmony_ci}
374562306a36Sopenharmony_ci
374662306a36Sopenharmony_cibool svm_nmi_blocked(struct kvm_vcpu *vcpu)
374762306a36Sopenharmony_ci{
374862306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
374962306a36Sopenharmony_ci	struct vmcb *vmcb = svm->vmcb;
375062306a36Sopenharmony_ci
375162306a36Sopenharmony_ci	if (!gif_set(svm))
375262306a36Sopenharmony_ci		return true;
375362306a36Sopenharmony_ci
375462306a36Sopenharmony_ci	if (is_guest_mode(vcpu) && nested_exit_on_nmi(svm))
375562306a36Sopenharmony_ci		return false;
375662306a36Sopenharmony_ci
375762306a36Sopenharmony_ci	if (svm_get_nmi_mask(vcpu))
375862306a36Sopenharmony_ci		return true;
375962306a36Sopenharmony_ci
376062306a36Sopenharmony_ci	return vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK;
376162306a36Sopenharmony_ci}
376262306a36Sopenharmony_ci
376362306a36Sopenharmony_cistatic int svm_nmi_allowed(struct kvm_vcpu *vcpu, bool for_injection)
376462306a36Sopenharmony_ci{
376562306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
376662306a36Sopenharmony_ci	if (svm->nested.nested_run_pending)
376762306a36Sopenharmony_ci		return -EBUSY;
376862306a36Sopenharmony_ci
376962306a36Sopenharmony_ci	if (svm_nmi_blocked(vcpu))
377062306a36Sopenharmony_ci		return 0;
377162306a36Sopenharmony_ci
377262306a36Sopenharmony_ci	/* An NMI must not be injected into L2 if it's supposed to VM-Exit.  */
377362306a36Sopenharmony_ci	if (for_injection && is_guest_mode(vcpu) && nested_exit_on_nmi(svm))
377462306a36Sopenharmony_ci		return -EBUSY;
377562306a36Sopenharmony_ci	return 1;
377662306a36Sopenharmony_ci}
377762306a36Sopenharmony_ci
377862306a36Sopenharmony_cibool svm_interrupt_blocked(struct kvm_vcpu *vcpu)
377962306a36Sopenharmony_ci{
378062306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
378162306a36Sopenharmony_ci	struct vmcb *vmcb = svm->vmcb;
378262306a36Sopenharmony_ci
378362306a36Sopenharmony_ci	if (!gif_set(svm))
378462306a36Sopenharmony_ci		return true;
378562306a36Sopenharmony_ci
378662306a36Sopenharmony_ci	if (is_guest_mode(vcpu)) {
378762306a36Sopenharmony_ci		/* As long as interrupts are being delivered...  */
378862306a36Sopenharmony_ci		if ((svm->nested.ctl.int_ctl & V_INTR_MASKING_MASK)
378962306a36Sopenharmony_ci		    ? !(svm->vmcb01.ptr->save.rflags & X86_EFLAGS_IF)
379062306a36Sopenharmony_ci		    : !(kvm_get_rflags(vcpu) & X86_EFLAGS_IF))
379162306a36Sopenharmony_ci			return true;
379262306a36Sopenharmony_ci
379362306a36Sopenharmony_ci		/* ... vmexits aren't blocked by the interrupt shadow  */
379462306a36Sopenharmony_ci		if (nested_exit_on_intr(svm))
379562306a36Sopenharmony_ci			return false;
379662306a36Sopenharmony_ci	} else {
379762306a36Sopenharmony_ci		if (!svm_get_if_flag(vcpu))
379862306a36Sopenharmony_ci			return true;
379962306a36Sopenharmony_ci	}
380062306a36Sopenharmony_ci
380162306a36Sopenharmony_ci	return (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK);
380262306a36Sopenharmony_ci}
380362306a36Sopenharmony_ci
380462306a36Sopenharmony_cistatic int svm_interrupt_allowed(struct kvm_vcpu *vcpu, bool for_injection)
380562306a36Sopenharmony_ci{
380662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
380762306a36Sopenharmony_ci
380862306a36Sopenharmony_ci	if (svm->nested.nested_run_pending)
380962306a36Sopenharmony_ci		return -EBUSY;
381062306a36Sopenharmony_ci
381162306a36Sopenharmony_ci	if (svm_interrupt_blocked(vcpu))
381262306a36Sopenharmony_ci		return 0;
381362306a36Sopenharmony_ci
381462306a36Sopenharmony_ci	/*
381562306a36Sopenharmony_ci	 * An IRQ must not be injected into L2 if it's supposed to VM-Exit,
381662306a36Sopenharmony_ci	 * e.g. if the IRQ arrived asynchronously after checking nested events.
381762306a36Sopenharmony_ci	 */
381862306a36Sopenharmony_ci	if (for_injection && is_guest_mode(vcpu) && nested_exit_on_intr(svm))
381962306a36Sopenharmony_ci		return -EBUSY;
382062306a36Sopenharmony_ci
382162306a36Sopenharmony_ci	return 1;
382262306a36Sopenharmony_ci}
382362306a36Sopenharmony_ci
382462306a36Sopenharmony_cistatic void svm_enable_irq_window(struct kvm_vcpu *vcpu)
382562306a36Sopenharmony_ci{
382662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
382762306a36Sopenharmony_ci
382862306a36Sopenharmony_ci	/*
382962306a36Sopenharmony_ci	 * In case GIF=0 we can't rely on the CPU to tell us when GIF becomes
383062306a36Sopenharmony_ci	 * 1, because that's a separate STGI/VMRUN intercept.  The next time we
383162306a36Sopenharmony_ci	 * get that intercept, this function will be called again though and
383262306a36Sopenharmony_ci	 * we'll get the vintr intercept. However, if the vGIF feature is
383362306a36Sopenharmony_ci	 * enabled, the STGI interception will not occur. Enable the irq
383462306a36Sopenharmony_ci	 * window under the assumption that the hardware will set the GIF.
383562306a36Sopenharmony_ci	 */
383662306a36Sopenharmony_ci	if (vgif || gif_set(svm)) {
383762306a36Sopenharmony_ci		/*
383862306a36Sopenharmony_ci		 * IRQ window is not needed when AVIC is enabled,
383962306a36Sopenharmony_ci		 * unless we have pending ExtINT since it cannot be injected
384062306a36Sopenharmony_ci		 * via AVIC. In such case, KVM needs to temporarily disable AVIC,
384162306a36Sopenharmony_ci		 * and fallback to injecting IRQ via V_IRQ.
384262306a36Sopenharmony_ci		 *
384362306a36Sopenharmony_ci		 * If running nested, AVIC is already locally inhibited
384462306a36Sopenharmony_ci		 * on this vCPU, therefore there is no need to request
384562306a36Sopenharmony_ci		 * the VM wide AVIC inhibition.
384662306a36Sopenharmony_ci		 */
384762306a36Sopenharmony_ci		if (!is_guest_mode(vcpu))
384862306a36Sopenharmony_ci			kvm_set_apicv_inhibit(vcpu->kvm, APICV_INHIBIT_REASON_IRQWIN);
384962306a36Sopenharmony_ci
385062306a36Sopenharmony_ci		svm_set_vintr(svm);
385162306a36Sopenharmony_ci	}
385262306a36Sopenharmony_ci}
385362306a36Sopenharmony_ci
385462306a36Sopenharmony_cistatic void svm_enable_nmi_window(struct kvm_vcpu *vcpu)
385562306a36Sopenharmony_ci{
385662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
385762306a36Sopenharmony_ci
385862306a36Sopenharmony_ci	/*
385962306a36Sopenharmony_ci	 * KVM should never request an NMI window when vNMI is enabled, as KVM
386062306a36Sopenharmony_ci	 * allows at most one to-be-injected NMI and one pending NMI, i.e. if
386162306a36Sopenharmony_ci	 * two NMIs arrive simultaneously, KVM will inject one and set
386262306a36Sopenharmony_ci	 * V_NMI_PENDING for the other.  WARN, but continue with the standard
386362306a36Sopenharmony_ci	 * single-step approach to try and salvage the pending NMI.
386462306a36Sopenharmony_ci	 */
386562306a36Sopenharmony_ci	WARN_ON_ONCE(is_vnmi_enabled(svm));
386662306a36Sopenharmony_ci
386762306a36Sopenharmony_ci	if (svm_get_nmi_mask(vcpu) && !svm->awaiting_iret_completion)
386862306a36Sopenharmony_ci		return; /* IRET will cause a vm exit */
386962306a36Sopenharmony_ci
387062306a36Sopenharmony_ci	/*
387162306a36Sopenharmony_ci	 * SEV-ES guests are responsible for signaling when a vCPU is ready to
387262306a36Sopenharmony_ci	 * receive a new NMI, as SEV-ES guests can't be single-stepped, i.e.
387362306a36Sopenharmony_ci	 * KVM can't intercept and single-step IRET to detect when NMIs are
387462306a36Sopenharmony_ci	 * unblocked (architecturally speaking).  See SVM_VMGEXIT_NMI_COMPLETE.
387562306a36Sopenharmony_ci	 *
387662306a36Sopenharmony_ci	 * Note, GIF is guaranteed to be '1' for SEV-ES guests as hardware
387762306a36Sopenharmony_ci	 * ignores SEV-ES guest writes to EFER.SVME *and* CLGI/STGI are not
387862306a36Sopenharmony_ci	 * supported NAEs in the GHCB protocol.
387962306a36Sopenharmony_ci	 */
388062306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm))
388162306a36Sopenharmony_ci		return;
388262306a36Sopenharmony_ci
388362306a36Sopenharmony_ci	if (!gif_set(svm)) {
388462306a36Sopenharmony_ci		if (vgif)
388562306a36Sopenharmony_ci			svm_set_intercept(svm, INTERCEPT_STGI);
388662306a36Sopenharmony_ci		return; /* STGI will cause a vm exit */
388762306a36Sopenharmony_ci	}
388862306a36Sopenharmony_ci
388962306a36Sopenharmony_ci	/*
389062306a36Sopenharmony_ci	 * Something prevents NMI from been injected. Single step over possible
389162306a36Sopenharmony_ci	 * problem (IRET or exception injection or interrupt shadow)
389262306a36Sopenharmony_ci	 */
389362306a36Sopenharmony_ci	svm->nmi_singlestep_guest_rflags = svm_get_rflags(vcpu);
389462306a36Sopenharmony_ci	svm->nmi_singlestep = true;
389562306a36Sopenharmony_ci	svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
389662306a36Sopenharmony_ci}
389762306a36Sopenharmony_ci
389862306a36Sopenharmony_cistatic void svm_flush_tlb_asid(struct kvm_vcpu *vcpu)
389962306a36Sopenharmony_ci{
390062306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
390162306a36Sopenharmony_ci
390262306a36Sopenharmony_ci	/*
390362306a36Sopenharmony_ci	 * Unlike VMX, SVM doesn't provide a way to flush only NPT TLB entries.
390462306a36Sopenharmony_ci	 * A TLB flush for the current ASID flushes both "host" and "guest" TLB
390562306a36Sopenharmony_ci	 * entries, and thus is a superset of Hyper-V's fine grained flushing.
390662306a36Sopenharmony_ci	 */
390762306a36Sopenharmony_ci	kvm_hv_vcpu_purge_flush_tlb(vcpu);
390862306a36Sopenharmony_ci
390962306a36Sopenharmony_ci	/*
391062306a36Sopenharmony_ci	 * Flush only the current ASID even if the TLB flush was invoked via
391162306a36Sopenharmony_ci	 * kvm_flush_remote_tlbs().  Although flushing remote TLBs requires all
391262306a36Sopenharmony_ci	 * ASIDs to be flushed, KVM uses a single ASID for L1 and L2, and
391362306a36Sopenharmony_ci	 * unconditionally does a TLB flush on both nested VM-Enter and nested
391462306a36Sopenharmony_ci	 * VM-Exit (via kvm_mmu_reset_context()).
391562306a36Sopenharmony_ci	 */
391662306a36Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_FLUSHBYASID))
391762306a36Sopenharmony_ci		svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ASID;
391862306a36Sopenharmony_ci	else
391962306a36Sopenharmony_ci		svm->current_vmcb->asid_generation--;
392062306a36Sopenharmony_ci}
392162306a36Sopenharmony_ci
392262306a36Sopenharmony_cistatic void svm_flush_tlb_current(struct kvm_vcpu *vcpu)
392362306a36Sopenharmony_ci{
392462306a36Sopenharmony_ci	hpa_t root_tdp = vcpu->arch.mmu->root.hpa;
392562306a36Sopenharmony_ci
392662306a36Sopenharmony_ci	/*
392762306a36Sopenharmony_ci	 * When running on Hyper-V with EnlightenedNptTlb enabled, explicitly
392862306a36Sopenharmony_ci	 * flush the NPT mappings via hypercall as flushing the ASID only
392962306a36Sopenharmony_ci	 * affects virtual to physical mappings, it does not invalidate guest
393062306a36Sopenharmony_ci	 * physical to host physical mappings.
393162306a36Sopenharmony_ci	 */
393262306a36Sopenharmony_ci	if (svm_hv_is_enlightened_tlb_enabled(vcpu) && VALID_PAGE(root_tdp))
393362306a36Sopenharmony_ci		hyperv_flush_guest_mapping(root_tdp);
393462306a36Sopenharmony_ci
393562306a36Sopenharmony_ci	svm_flush_tlb_asid(vcpu);
393662306a36Sopenharmony_ci}
393762306a36Sopenharmony_ci
393862306a36Sopenharmony_cistatic void svm_flush_tlb_all(struct kvm_vcpu *vcpu)
393962306a36Sopenharmony_ci{
394062306a36Sopenharmony_ci	/*
394162306a36Sopenharmony_ci	 * When running on Hyper-V with EnlightenedNptTlb enabled, remote TLB
394262306a36Sopenharmony_ci	 * flushes should be routed to hv_flush_remote_tlbs() without requesting
394362306a36Sopenharmony_ci	 * a "regular" remote flush.  Reaching this point means either there's
394462306a36Sopenharmony_ci	 * a KVM bug or a prior hv_flush_remote_tlbs() call failed, both of
394562306a36Sopenharmony_ci	 * which might be fatal to the guest.  Yell, but try to recover.
394662306a36Sopenharmony_ci	 */
394762306a36Sopenharmony_ci	if (WARN_ON_ONCE(svm_hv_is_enlightened_tlb_enabled(vcpu)))
394862306a36Sopenharmony_ci		hv_flush_remote_tlbs(vcpu->kvm);
394962306a36Sopenharmony_ci
395062306a36Sopenharmony_ci	svm_flush_tlb_asid(vcpu);
395162306a36Sopenharmony_ci}
395262306a36Sopenharmony_ci
395362306a36Sopenharmony_cistatic void svm_flush_tlb_gva(struct kvm_vcpu *vcpu, gva_t gva)
395462306a36Sopenharmony_ci{
395562306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
395662306a36Sopenharmony_ci
395762306a36Sopenharmony_ci	invlpga(gva, svm->vmcb->control.asid);
395862306a36Sopenharmony_ci}
395962306a36Sopenharmony_ci
396062306a36Sopenharmony_cistatic inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)
396162306a36Sopenharmony_ci{
396262306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
396362306a36Sopenharmony_ci
396462306a36Sopenharmony_ci	if (nested_svm_virtualize_tpr(vcpu))
396562306a36Sopenharmony_ci		return;
396662306a36Sopenharmony_ci
396762306a36Sopenharmony_ci	if (!svm_is_intercept(svm, INTERCEPT_CR8_WRITE)) {
396862306a36Sopenharmony_ci		int cr8 = svm->vmcb->control.int_ctl & V_TPR_MASK;
396962306a36Sopenharmony_ci		kvm_set_cr8(vcpu, cr8);
397062306a36Sopenharmony_ci	}
397162306a36Sopenharmony_ci}
397262306a36Sopenharmony_ci
397362306a36Sopenharmony_cistatic inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu)
397462306a36Sopenharmony_ci{
397562306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
397662306a36Sopenharmony_ci	u64 cr8;
397762306a36Sopenharmony_ci
397862306a36Sopenharmony_ci	if (nested_svm_virtualize_tpr(vcpu) ||
397962306a36Sopenharmony_ci	    kvm_vcpu_apicv_active(vcpu))
398062306a36Sopenharmony_ci		return;
398162306a36Sopenharmony_ci
398262306a36Sopenharmony_ci	cr8 = kvm_get_cr8(vcpu);
398362306a36Sopenharmony_ci	svm->vmcb->control.int_ctl &= ~V_TPR_MASK;
398462306a36Sopenharmony_ci	svm->vmcb->control.int_ctl |= cr8 & V_TPR_MASK;
398562306a36Sopenharmony_ci}
398662306a36Sopenharmony_ci
398762306a36Sopenharmony_cistatic void svm_complete_soft_interrupt(struct kvm_vcpu *vcpu, u8 vector,
398862306a36Sopenharmony_ci					int type)
398962306a36Sopenharmony_ci{
399062306a36Sopenharmony_ci	bool is_exception = (type == SVM_EXITINTINFO_TYPE_EXEPT);
399162306a36Sopenharmony_ci	bool is_soft = (type == SVM_EXITINTINFO_TYPE_SOFT);
399262306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
399362306a36Sopenharmony_ci
399462306a36Sopenharmony_ci	/*
399562306a36Sopenharmony_ci	 * If NRIPS is enabled, KVM must snapshot the pre-VMRUN next_rip that's
399662306a36Sopenharmony_ci	 * associated with the original soft exception/interrupt.  next_rip is
399762306a36Sopenharmony_ci	 * cleared on all exits that can occur while vectoring an event, so KVM
399862306a36Sopenharmony_ci	 * needs to manually set next_rip for re-injection.  Unlike the !nrips
399962306a36Sopenharmony_ci	 * case below, this needs to be done if and only if KVM is re-injecting
400062306a36Sopenharmony_ci	 * the same event, i.e. if the event is a soft exception/interrupt,
400162306a36Sopenharmony_ci	 * otherwise next_rip is unused on VMRUN.
400262306a36Sopenharmony_ci	 */
400362306a36Sopenharmony_ci	if (nrips && (is_soft || (is_exception && kvm_exception_is_soft(vector))) &&
400462306a36Sopenharmony_ci	    kvm_is_linear_rip(vcpu, svm->soft_int_old_rip + svm->soft_int_csbase))
400562306a36Sopenharmony_ci		svm->vmcb->control.next_rip = svm->soft_int_next_rip;
400662306a36Sopenharmony_ci	/*
400762306a36Sopenharmony_ci	 * If NRIPS isn't enabled, KVM must manually advance RIP prior to
400862306a36Sopenharmony_ci	 * injecting the soft exception/interrupt.  That advancement needs to
400962306a36Sopenharmony_ci	 * be unwound if vectoring didn't complete.  Note, the new event may
401062306a36Sopenharmony_ci	 * not be the injected event, e.g. if KVM injected an INTn, the INTn
401162306a36Sopenharmony_ci	 * hit a #NP in the guest, and the #NP encountered a #PF, the #NP will
401262306a36Sopenharmony_ci	 * be the reported vectored event, but RIP still needs to be unwound.
401362306a36Sopenharmony_ci	 */
401462306a36Sopenharmony_ci	else if (!nrips && (is_soft || is_exception) &&
401562306a36Sopenharmony_ci		 kvm_is_linear_rip(vcpu, svm->soft_int_next_rip + svm->soft_int_csbase))
401662306a36Sopenharmony_ci		kvm_rip_write(vcpu, svm->soft_int_old_rip);
401762306a36Sopenharmony_ci}
401862306a36Sopenharmony_ci
401962306a36Sopenharmony_cistatic void svm_complete_interrupts(struct kvm_vcpu *vcpu)
402062306a36Sopenharmony_ci{
402162306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
402262306a36Sopenharmony_ci	u8 vector;
402362306a36Sopenharmony_ci	int type;
402462306a36Sopenharmony_ci	u32 exitintinfo = svm->vmcb->control.exit_int_info;
402562306a36Sopenharmony_ci	bool nmi_l1_to_l2 = svm->nmi_l1_to_l2;
402662306a36Sopenharmony_ci	bool soft_int_injected = svm->soft_int_injected;
402762306a36Sopenharmony_ci
402862306a36Sopenharmony_ci	svm->nmi_l1_to_l2 = false;
402962306a36Sopenharmony_ci	svm->soft_int_injected = false;
403062306a36Sopenharmony_ci
403162306a36Sopenharmony_ci	/*
403262306a36Sopenharmony_ci	 * If we've made progress since setting awaiting_iret_completion, we've
403362306a36Sopenharmony_ci	 * executed an IRET and can allow NMI injection.
403462306a36Sopenharmony_ci	 */
403562306a36Sopenharmony_ci	if (svm->awaiting_iret_completion &&
403662306a36Sopenharmony_ci	    kvm_rip_read(vcpu) != svm->nmi_iret_rip) {
403762306a36Sopenharmony_ci		svm->awaiting_iret_completion = false;
403862306a36Sopenharmony_ci		svm->nmi_masked = false;
403962306a36Sopenharmony_ci		kvm_make_request(KVM_REQ_EVENT, vcpu);
404062306a36Sopenharmony_ci	}
404162306a36Sopenharmony_ci
404262306a36Sopenharmony_ci	vcpu->arch.nmi_injected = false;
404362306a36Sopenharmony_ci	kvm_clear_exception_queue(vcpu);
404462306a36Sopenharmony_ci	kvm_clear_interrupt_queue(vcpu);
404562306a36Sopenharmony_ci
404662306a36Sopenharmony_ci	if (!(exitintinfo & SVM_EXITINTINFO_VALID))
404762306a36Sopenharmony_ci		return;
404862306a36Sopenharmony_ci
404962306a36Sopenharmony_ci	kvm_make_request(KVM_REQ_EVENT, vcpu);
405062306a36Sopenharmony_ci
405162306a36Sopenharmony_ci	vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK;
405262306a36Sopenharmony_ci	type = exitintinfo & SVM_EXITINTINFO_TYPE_MASK;
405362306a36Sopenharmony_ci
405462306a36Sopenharmony_ci	if (soft_int_injected)
405562306a36Sopenharmony_ci		svm_complete_soft_interrupt(vcpu, vector, type);
405662306a36Sopenharmony_ci
405762306a36Sopenharmony_ci	switch (type) {
405862306a36Sopenharmony_ci	case SVM_EXITINTINFO_TYPE_NMI:
405962306a36Sopenharmony_ci		vcpu->arch.nmi_injected = true;
406062306a36Sopenharmony_ci		svm->nmi_l1_to_l2 = nmi_l1_to_l2;
406162306a36Sopenharmony_ci		break;
406262306a36Sopenharmony_ci	case SVM_EXITINTINFO_TYPE_EXEPT:
406362306a36Sopenharmony_ci		/*
406462306a36Sopenharmony_ci		 * Never re-inject a #VC exception.
406562306a36Sopenharmony_ci		 */
406662306a36Sopenharmony_ci		if (vector == X86_TRAP_VC)
406762306a36Sopenharmony_ci			break;
406862306a36Sopenharmony_ci
406962306a36Sopenharmony_ci		if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) {
407062306a36Sopenharmony_ci			u32 err = svm->vmcb->control.exit_int_info_err;
407162306a36Sopenharmony_ci			kvm_requeue_exception_e(vcpu, vector, err);
407262306a36Sopenharmony_ci
407362306a36Sopenharmony_ci		} else
407462306a36Sopenharmony_ci			kvm_requeue_exception(vcpu, vector);
407562306a36Sopenharmony_ci		break;
407662306a36Sopenharmony_ci	case SVM_EXITINTINFO_TYPE_INTR:
407762306a36Sopenharmony_ci		kvm_queue_interrupt(vcpu, vector, false);
407862306a36Sopenharmony_ci		break;
407962306a36Sopenharmony_ci	case SVM_EXITINTINFO_TYPE_SOFT:
408062306a36Sopenharmony_ci		kvm_queue_interrupt(vcpu, vector, true);
408162306a36Sopenharmony_ci		break;
408262306a36Sopenharmony_ci	default:
408362306a36Sopenharmony_ci		break;
408462306a36Sopenharmony_ci	}
408562306a36Sopenharmony_ci
408662306a36Sopenharmony_ci}
408762306a36Sopenharmony_ci
408862306a36Sopenharmony_cistatic void svm_cancel_injection(struct kvm_vcpu *vcpu)
408962306a36Sopenharmony_ci{
409062306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
409162306a36Sopenharmony_ci	struct vmcb_control_area *control = &svm->vmcb->control;
409262306a36Sopenharmony_ci
409362306a36Sopenharmony_ci	control->exit_int_info = control->event_inj;
409462306a36Sopenharmony_ci	control->exit_int_info_err = control->event_inj_err;
409562306a36Sopenharmony_ci	control->event_inj = 0;
409662306a36Sopenharmony_ci	svm_complete_interrupts(vcpu);
409762306a36Sopenharmony_ci}
409862306a36Sopenharmony_ci
409962306a36Sopenharmony_cistatic int svm_vcpu_pre_run(struct kvm_vcpu *vcpu)
410062306a36Sopenharmony_ci{
410162306a36Sopenharmony_ci	return 1;
410262306a36Sopenharmony_ci}
410362306a36Sopenharmony_ci
410462306a36Sopenharmony_cistatic fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
410562306a36Sopenharmony_ci{
410662306a36Sopenharmony_ci	if (to_svm(vcpu)->vmcb->control.exit_code == SVM_EXIT_MSR &&
410762306a36Sopenharmony_ci	    to_svm(vcpu)->vmcb->control.exit_info_1)
410862306a36Sopenharmony_ci		return handle_fastpath_set_msr_irqoff(vcpu);
410962306a36Sopenharmony_ci
411062306a36Sopenharmony_ci	return EXIT_FASTPATH_NONE;
411162306a36Sopenharmony_ci}
411262306a36Sopenharmony_ci
411362306a36Sopenharmony_cistatic noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_intercepted)
411462306a36Sopenharmony_ci{
411562306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
411662306a36Sopenharmony_ci
411762306a36Sopenharmony_ci	guest_state_enter_irqoff();
411862306a36Sopenharmony_ci
411962306a36Sopenharmony_ci	amd_clear_divider();
412062306a36Sopenharmony_ci
412162306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm))
412262306a36Sopenharmony_ci		__svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted);
412362306a36Sopenharmony_ci	else
412462306a36Sopenharmony_ci		__svm_vcpu_run(svm, spec_ctrl_intercepted);
412562306a36Sopenharmony_ci
412662306a36Sopenharmony_ci	guest_state_exit_irqoff();
412762306a36Sopenharmony_ci}
412862306a36Sopenharmony_ci
412962306a36Sopenharmony_cistatic __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)
413062306a36Sopenharmony_ci{
413162306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
413262306a36Sopenharmony_ci	bool spec_ctrl_intercepted = msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL);
413362306a36Sopenharmony_ci
413462306a36Sopenharmony_ci	trace_kvm_entry(vcpu);
413562306a36Sopenharmony_ci
413662306a36Sopenharmony_ci	svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
413762306a36Sopenharmony_ci	svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
413862306a36Sopenharmony_ci	svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP];
413962306a36Sopenharmony_ci
414062306a36Sopenharmony_ci	/*
414162306a36Sopenharmony_ci	 * Disable singlestep if we're injecting an interrupt/exception.
414262306a36Sopenharmony_ci	 * We don't want our modified rflags to be pushed on the stack where
414362306a36Sopenharmony_ci	 * we might not be able to easily reset them if we disabled NMI
414462306a36Sopenharmony_ci	 * singlestep later.
414562306a36Sopenharmony_ci	 */
414662306a36Sopenharmony_ci	if (svm->nmi_singlestep && svm->vmcb->control.event_inj) {
414762306a36Sopenharmony_ci		/*
414862306a36Sopenharmony_ci		 * Event injection happens before external interrupts cause a
414962306a36Sopenharmony_ci		 * vmexit and interrupts are disabled here, so smp_send_reschedule
415062306a36Sopenharmony_ci		 * is enough to force an immediate vmexit.
415162306a36Sopenharmony_ci		 */
415262306a36Sopenharmony_ci		disable_nmi_singlestep(svm);
415362306a36Sopenharmony_ci		smp_send_reschedule(vcpu->cpu);
415462306a36Sopenharmony_ci	}
415562306a36Sopenharmony_ci
415662306a36Sopenharmony_ci	pre_svm_run(vcpu);
415762306a36Sopenharmony_ci
415862306a36Sopenharmony_ci	sync_lapic_to_cr8(vcpu);
415962306a36Sopenharmony_ci
416062306a36Sopenharmony_ci	if (unlikely(svm->asid != svm->vmcb->control.asid)) {
416162306a36Sopenharmony_ci		svm->vmcb->control.asid = svm->asid;
416262306a36Sopenharmony_ci		vmcb_mark_dirty(svm->vmcb, VMCB_ASID);
416362306a36Sopenharmony_ci	}
416462306a36Sopenharmony_ci	svm->vmcb->save.cr2 = vcpu->arch.cr2;
416562306a36Sopenharmony_ci
416662306a36Sopenharmony_ci	svm_hv_update_vp_id(svm->vmcb, vcpu);
416762306a36Sopenharmony_ci
416862306a36Sopenharmony_ci	/*
416962306a36Sopenharmony_ci	 * Run with all-zero DR6 unless needed, so that we can get the exact cause
417062306a36Sopenharmony_ci	 * of a #DB.
417162306a36Sopenharmony_ci	 */
417262306a36Sopenharmony_ci	if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))
417362306a36Sopenharmony_ci		svm_set_dr6(svm, vcpu->arch.dr6);
417462306a36Sopenharmony_ci	else
417562306a36Sopenharmony_ci		svm_set_dr6(svm, DR6_ACTIVE_LOW);
417662306a36Sopenharmony_ci
417762306a36Sopenharmony_ci	clgi();
417862306a36Sopenharmony_ci	kvm_load_guest_xsave_state(vcpu);
417962306a36Sopenharmony_ci
418062306a36Sopenharmony_ci	kvm_wait_lapic_expire(vcpu);
418162306a36Sopenharmony_ci
418262306a36Sopenharmony_ci	/*
418362306a36Sopenharmony_ci	 * If this vCPU has touched SPEC_CTRL, restore the guest's value if
418462306a36Sopenharmony_ci	 * it's non-zero. Since vmentry is serialising on affected CPUs, there
418562306a36Sopenharmony_ci	 * is no need to worry about the conditional branch over the wrmsr
418662306a36Sopenharmony_ci	 * being speculatively taken.
418762306a36Sopenharmony_ci	 */
418862306a36Sopenharmony_ci	if (!static_cpu_has(X86_FEATURE_V_SPEC_CTRL))
418962306a36Sopenharmony_ci		x86_spec_ctrl_set_guest(svm->virt_spec_ctrl);
419062306a36Sopenharmony_ci
419162306a36Sopenharmony_ci	svm_vcpu_enter_exit(vcpu, spec_ctrl_intercepted);
419262306a36Sopenharmony_ci
419362306a36Sopenharmony_ci	if (!static_cpu_has(X86_FEATURE_V_SPEC_CTRL))
419462306a36Sopenharmony_ci		x86_spec_ctrl_restore_host(svm->virt_spec_ctrl);
419562306a36Sopenharmony_ci
419662306a36Sopenharmony_ci	if (!sev_es_guest(vcpu->kvm)) {
419762306a36Sopenharmony_ci		vcpu->arch.cr2 = svm->vmcb->save.cr2;
419862306a36Sopenharmony_ci		vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax;
419962306a36Sopenharmony_ci		vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
420062306a36Sopenharmony_ci		vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
420162306a36Sopenharmony_ci	}
420262306a36Sopenharmony_ci	vcpu->arch.regs_dirty = 0;
420362306a36Sopenharmony_ci
420462306a36Sopenharmony_ci	if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
420562306a36Sopenharmony_ci		kvm_before_interrupt(vcpu, KVM_HANDLING_NMI);
420662306a36Sopenharmony_ci
420762306a36Sopenharmony_ci	kvm_load_host_xsave_state(vcpu);
420862306a36Sopenharmony_ci	stgi();
420962306a36Sopenharmony_ci
421062306a36Sopenharmony_ci	/* Any pending NMI will happen here */
421162306a36Sopenharmony_ci
421262306a36Sopenharmony_ci	if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
421362306a36Sopenharmony_ci		kvm_after_interrupt(vcpu);
421462306a36Sopenharmony_ci
421562306a36Sopenharmony_ci	sync_cr8_to_lapic(vcpu);
421662306a36Sopenharmony_ci
421762306a36Sopenharmony_ci	svm->next_rip = 0;
421862306a36Sopenharmony_ci	if (is_guest_mode(vcpu)) {
421962306a36Sopenharmony_ci		nested_sync_control_from_vmcb02(svm);
422062306a36Sopenharmony_ci
422162306a36Sopenharmony_ci		/* Track VMRUNs that have made past consistency checking */
422262306a36Sopenharmony_ci		if (svm->nested.nested_run_pending &&
422362306a36Sopenharmony_ci		    svm->vmcb->control.exit_code != SVM_EXIT_ERR)
422462306a36Sopenharmony_ci                        ++vcpu->stat.nested_run;
422562306a36Sopenharmony_ci
422662306a36Sopenharmony_ci		svm->nested.nested_run_pending = 0;
422762306a36Sopenharmony_ci	}
422862306a36Sopenharmony_ci
422962306a36Sopenharmony_ci	svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
423062306a36Sopenharmony_ci	vmcb_mark_all_clean(svm->vmcb);
423162306a36Sopenharmony_ci
423262306a36Sopenharmony_ci	/* if exit due to PF check for async PF */
423362306a36Sopenharmony_ci	if (svm->vmcb->control.exit_code == SVM_EXIT_EXCP_BASE + PF_VECTOR)
423462306a36Sopenharmony_ci		vcpu->arch.apf.host_apf_flags =
423562306a36Sopenharmony_ci			kvm_read_and_reset_apf_flags();
423662306a36Sopenharmony_ci
423762306a36Sopenharmony_ci	vcpu->arch.regs_avail &= ~SVM_REGS_LAZY_LOAD_SET;
423862306a36Sopenharmony_ci
423962306a36Sopenharmony_ci	/*
424062306a36Sopenharmony_ci	 * We need to handle MC intercepts here before the vcpu has a chance to
424162306a36Sopenharmony_ci	 * change the physical cpu
424262306a36Sopenharmony_ci	 */
424362306a36Sopenharmony_ci	if (unlikely(svm->vmcb->control.exit_code ==
424462306a36Sopenharmony_ci		     SVM_EXIT_EXCP_BASE + MC_VECTOR))
424562306a36Sopenharmony_ci		svm_handle_mce(vcpu);
424662306a36Sopenharmony_ci
424762306a36Sopenharmony_ci	trace_kvm_exit(vcpu, KVM_ISA_SVM);
424862306a36Sopenharmony_ci
424962306a36Sopenharmony_ci	svm_complete_interrupts(vcpu);
425062306a36Sopenharmony_ci
425162306a36Sopenharmony_ci	if (is_guest_mode(vcpu))
425262306a36Sopenharmony_ci		return EXIT_FASTPATH_NONE;
425362306a36Sopenharmony_ci
425462306a36Sopenharmony_ci	return svm_exit_handlers_fastpath(vcpu);
425562306a36Sopenharmony_ci}
425662306a36Sopenharmony_ci
425762306a36Sopenharmony_cistatic void svm_load_mmu_pgd(struct kvm_vcpu *vcpu, hpa_t root_hpa,
425862306a36Sopenharmony_ci			     int root_level)
425962306a36Sopenharmony_ci{
426062306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
426162306a36Sopenharmony_ci	unsigned long cr3;
426262306a36Sopenharmony_ci
426362306a36Sopenharmony_ci	if (npt_enabled) {
426462306a36Sopenharmony_ci		svm->vmcb->control.nested_cr3 = __sme_set(root_hpa);
426562306a36Sopenharmony_ci		vmcb_mark_dirty(svm->vmcb, VMCB_NPT);
426662306a36Sopenharmony_ci
426762306a36Sopenharmony_ci		hv_track_root_tdp(vcpu, root_hpa);
426862306a36Sopenharmony_ci
426962306a36Sopenharmony_ci		cr3 = vcpu->arch.cr3;
427062306a36Sopenharmony_ci	} else if (root_level >= PT64_ROOT_4LEVEL) {
427162306a36Sopenharmony_ci		cr3 = __sme_set(root_hpa) | kvm_get_active_pcid(vcpu);
427262306a36Sopenharmony_ci	} else {
427362306a36Sopenharmony_ci		/* PCID in the guest should be impossible with a 32-bit MMU. */
427462306a36Sopenharmony_ci		WARN_ON_ONCE(kvm_get_active_pcid(vcpu));
427562306a36Sopenharmony_ci		cr3 = root_hpa;
427662306a36Sopenharmony_ci	}
427762306a36Sopenharmony_ci
427862306a36Sopenharmony_ci	svm->vmcb->save.cr3 = cr3;
427962306a36Sopenharmony_ci	vmcb_mark_dirty(svm->vmcb, VMCB_CR);
428062306a36Sopenharmony_ci}
428162306a36Sopenharmony_ci
428262306a36Sopenharmony_cistatic void
428362306a36Sopenharmony_cisvm_patch_hypercall(struct kvm_vcpu *vcpu, unsigned char *hypercall)
428462306a36Sopenharmony_ci{
428562306a36Sopenharmony_ci	/*
428662306a36Sopenharmony_ci	 * Patch in the VMMCALL instruction:
428762306a36Sopenharmony_ci	 */
428862306a36Sopenharmony_ci	hypercall[0] = 0x0f;
428962306a36Sopenharmony_ci	hypercall[1] = 0x01;
429062306a36Sopenharmony_ci	hypercall[2] = 0xd9;
429162306a36Sopenharmony_ci}
429262306a36Sopenharmony_ci
429362306a36Sopenharmony_ci/*
429462306a36Sopenharmony_ci * The kvm parameter can be NULL (module initialization, or invocation before
429562306a36Sopenharmony_ci * VM creation). Be sure to check the kvm parameter before using it.
429662306a36Sopenharmony_ci */
429762306a36Sopenharmony_cistatic bool svm_has_emulated_msr(struct kvm *kvm, u32 index)
429862306a36Sopenharmony_ci{
429962306a36Sopenharmony_ci	switch (index) {
430062306a36Sopenharmony_ci	case MSR_IA32_MCG_EXT_CTL:
430162306a36Sopenharmony_ci	case KVM_FIRST_EMULATED_VMX_MSR ... KVM_LAST_EMULATED_VMX_MSR:
430262306a36Sopenharmony_ci		return false;
430362306a36Sopenharmony_ci	case MSR_IA32_SMBASE:
430462306a36Sopenharmony_ci		if (!IS_ENABLED(CONFIG_KVM_SMM))
430562306a36Sopenharmony_ci			return false;
430662306a36Sopenharmony_ci		/* SEV-ES guests do not support SMM, so report false */
430762306a36Sopenharmony_ci		if (kvm && sev_es_guest(kvm))
430862306a36Sopenharmony_ci			return false;
430962306a36Sopenharmony_ci		break;
431062306a36Sopenharmony_ci	default:
431162306a36Sopenharmony_ci		break;
431262306a36Sopenharmony_ci	}
431362306a36Sopenharmony_ci
431462306a36Sopenharmony_ci	return true;
431562306a36Sopenharmony_ci}
431662306a36Sopenharmony_ci
431762306a36Sopenharmony_cistatic void svm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
431862306a36Sopenharmony_ci{
431962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
432062306a36Sopenharmony_ci
432162306a36Sopenharmony_ci	/*
432262306a36Sopenharmony_ci	 * SVM doesn't provide a way to disable just XSAVES in the guest, KVM
432362306a36Sopenharmony_ci	 * can only disable all variants of by disallowing CR4.OSXSAVE from
432462306a36Sopenharmony_ci	 * being set.  As a result, if the host has XSAVE and XSAVES, and the
432562306a36Sopenharmony_ci	 * guest has XSAVE enabled, the guest can execute XSAVES without
432662306a36Sopenharmony_ci	 * faulting.  Treat XSAVES as enabled in this case regardless of
432762306a36Sopenharmony_ci	 * whether it's advertised to the guest so that KVM context switches
432862306a36Sopenharmony_ci	 * XSS on VM-Enter/VM-Exit.  Failure to do so would effectively give
432962306a36Sopenharmony_ci	 * the guest read/write access to the host's XSS.
433062306a36Sopenharmony_ci	 */
433162306a36Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_XSAVE) &&
433262306a36Sopenharmony_ci	    boot_cpu_has(X86_FEATURE_XSAVES) &&
433362306a36Sopenharmony_ci	    guest_cpuid_has(vcpu, X86_FEATURE_XSAVE))
433462306a36Sopenharmony_ci		kvm_governed_feature_set(vcpu, X86_FEATURE_XSAVES);
433562306a36Sopenharmony_ci
433662306a36Sopenharmony_ci	kvm_governed_feature_check_and_set(vcpu, X86_FEATURE_NRIPS);
433762306a36Sopenharmony_ci	kvm_governed_feature_check_and_set(vcpu, X86_FEATURE_TSCRATEMSR);
433862306a36Sopenharmony_ci	kvm_governed_feature_check_and_set(vcpu, X86_FEATURE_LBRV);
433962306a36Sopenharmony_ci
434062306a36Sopenharmony_ci	/*
434162306a36Sopenharmony_ci	 * Intercept VMLOAD if the vCPU mode is Intel in order to emulate that
434262306a36Sopenharmony_ci	 * VMLOAD drops bits 63:32 of SYSENTER (ignoring the fact that exposing
434362306a36Sopenharmony_ci	 * SVM on Intel is bonkers and extremely unlikely to work).
434462306a36Sopenharmony_ci	 */
434562306a36Sopenharmony_ci	if (!guest_cpuid_is_intel(vcpu))
434662306a36Sopenharmony_ci		kvm_governed_feature_check_and_set(vcpu, X86_FEATURE_V_VMSAVE_VMLOAD);
434762306a36Sopenharmony_ci
434862306a36Sopenharmony_ci	kvm_governed_feature_check_and_set(vcpu, X86_FEATURE_PAUSEFILTER);
434962306a36Sopenharmony_ci	kvm_governed_feature_check_and_set(vcpu, X86_FEATURE_PFTHRESHOLD);
435062306a36Sopenharmony_ci	kvm_governed_feature_check_and_set(vcpu, X86_FEATURE_VGIF);
435162306a36Sopenharmony_ci	kvm_governed_feature_check_and_set(vcpu, X86_FEATURE_VNMI);
435262306a36Sopenharmony_ci
435362306a36Sopenharmony_ci	svm_recalc_instruction_intercepts(vcpu, svm);
435462306a36Sopenharmony_ci
435562306a36Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_IBPB))
435662306a36Sopenharmony_ci		set_msr_interception(vcpu, svm->msrpm, MSR_IA32_PRED_CMD, 0,
435762306a36Sopenharmony_ci				     !!guest_has_pred_cmd_msr(vcpu));
435862306a36Sopenharmony_ci
435962306a36Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_FLUSH_L1D))
436062306a36Sopenharmony_ci		set_msr_interception(vcpu, svm->msrpm, MSR_IA32_FLUSH_CMD, 0,
436162306a36Sopenharmony_ci				     !!guest_cpuid_has(vcpu, X86_FEATURE_FLUSH_L1D));
436262306a36Sopenharmony_ci
436362306a36Sopenharmony_ci	if (sev_guest(vcpu->kvm))
436462306a36Sopenharmony_ci		sev_vcpu_after_set_cpuid(svm);
436562306a36Sopenharmony_ci
436662306a36Sopenharmony_ci	init_vmcb_after_set_cpuid(vcpu);
436762306a36Sopenharmony_ci}
436862306a36Sopenharmony_ci
436962306a36Sopenharmony_cistatic bool svm_has_wbinvd_exit(void)
437062306a36Sopenharmony_ci{
437162306a36Sopenharmony_ci	return true;
437262306a36Sopenharmony_ci}
437362306a36Sopenharmony_ci
437462306a36Sopenharmony_ci#define PRE_EX(exit)  { .exit_code = (exit), \
437562306a36Sopenharmony_ci			.stage = X86_ICPT_PRE_EXCEPT, }
437662306a36Sopenharmony_ci#define POST_EX(exit) { .exit_code = (exit), \
437762306a36Sopenharmony_ci			.stage = X86_ICPT_POST_EXCEPT, }
437862306a36Sopenharmony_ci#define POST_MEM(exit) { .exit_code = (exit), \
437962306a36Sopenharmony_ci			.stage = X86_ICPT_POST_MEMACCESS, }
438062306a36Sopenharmony_ci
438162306a36Sopenharmony_cistatic const struct __x86_intercept {
438262306a36Sopenharmony_ci	u32 exit_code;
438362306a36Sopenharmony_ci	enum x86_intercept_stage stage;
438462306a36Sopenharmony_ci} x86_intercept_map[] = {
438562306a36Sopenharmony_ci	[x86_intercept_cr_read]		= POST_EX(SVM_EXIT_READ_CR0),
438662306a36Sopenharmony_ci	[x86_intercept_cr_write]	= POST_EX(SVM_EXIT_WRITE_CR0),
438762306a36Sopenharmony_ci	[x86_intercept_clts]		= POST_EX(SVM_EXIT_WRITE_CR0),
438862306a36Sopenharmony_ci	[x86_intercept_lmsw]		= POST_EX(SVM_EXIT_WRITE_CR0),
438962306a36Sopenharmony_ci	[x86_intercept_smsw]		= POST_EX(SVM_EXIT_READ_CR0),
439062306a36Sopenharmony_ci	[x86_intercept_dr_read]		= POST_EX(SVM_EXIT_READ_DR0),
439162306a36Sopenharmony_ci	[x86_intercept_dr_write]	= POST_EX(SVM_EXIT_WRITE_DR0),
439262306a36Sopenharmony_ci	[x86_intercept_sldt]		= POST_EX(SVM_EXIT_LDTR_READ),
439362306a36Sopenharmony_ci	[x86_intercept_str]		= POST_EX(SVM_EXIT_TR_READ),
439462306a36Sopenharmony_ci	[x86_intercept_lldt]		= POST_EX(SVM_EXIT_LDTR_WRITE),
439562306a36Sopenharmony_ci	[x86_intercept_ltr]		= POST_EX(SVM_EXIT_TR_WRITE),
439662306a36Sopenharmony_ci	[x86_intercept_sgdt]		= POST_EX(SVM_EXIT_GDTR_READ),
439762306a36Sopenharmony_ci	[x86_intercept_sidt]		= POST_EX(SVM_EXIT_IDTR_READ),
439862306a36Sopenharmony_ci	[x86_intercept_lgdt]		= POST_EX(SVM_EXIT_GDTR_WRITE),
439962306a36Sopenharmony_ci	[x86_intercept_lidt]		= POST_EX(SVM_EXIT_IDTR_WRITE),
440062306a36Sopenharmony_ci	[x86_intercept_vmrun]		= POST_EX(SVM_EXIT_VMRUN),
440162306a36Sopenharmony_ci	[x86_intercept_vmmcall]		= POST_EX(SVM_EXIT_VMMCALL),
440262306a36Sopenharmony_ci	[x86_intercept_vmload]		= POST_EX(SVM_EXIT_VMLOAD),
440362306a36Sopenharmony_ci	[x86_intercept_vmsave]		= POST_EX(SVM_EXIT_VMSAVE),
440462306a36Sopenharmony_ci	[x86_intercept_stgi]		= POST_EX(SVM_EXIT_STGI),
440562306a36Sopenharmony_ci	[x86_intercept_clgi]		= POST_EX(SVM_EXIT_CLGI),
440662306a36Sopenharmony_ci	[x86_intercept_skinit]		= POST_EX(SVM_EXIT_SKINIT),
440762306a36Sopenharmony_ci	[x86_intercept_invlpga]		= POST_EX(SVM_EXIT_INVLPGA),
440862306a36Sopenharmony_ci	[x86_intercept_rdtscp]		= POST_EX(SVM_EXIT_RDTSCP),
440962306a36Sopenharmony_ci	[x86_intercept_monitor]		= POST_MEM(SVM_EXIT_MONITOR),
441062306a36Sopenharmony_ci	[x86_intercept_mwait]		= POST_EX(SVM_EXIT_MWAIT),
441162306a36Sopenharmony_ci	[x86_intercept_invlpg]		= POST_EX(SVM_EXIT_INVLPG),
441262306a36Sopenharmony_ci	[x86_intercept_invd]		= POST_EX(SVM_EXIT_INVD),
441362306a36Sopenharmony_ci	[x86_intercept_wbinvd]		= POST_EX(SVM_EXIT_WBINVD),
441462306a36Sopenharmony_ci	[x86_intercept_wrmsr]		= POST_EX(SVM_EXIT_MSR),
441562306a36Sopenharmony_ci	[x86_intercept_rdtsc]		= POST_EX(SVM_EXIT_RDTSC),
441662306a36Sopenharmony_ci	[x86_intercept_rdmsr]		= POST_EX(SVM_EXIT_MSR),
441762306a36Sopenharmony_ci	[x86_intercept_rdpmc]		= POST_EX(SVM_EXIT_RDPMC),
441862306a36Sopenharmony_ci	[x86_intercept_cpuid]		= PRE_EX(SVM_EXIT_CPUID),
441962306a36Sopenharmony_ci	[x86_intercept_rsm]		= PRE_EX(SVM_EXIT_RSM),
442062306a36Sopenharmony_ci	[x86_intercept_pause]		= PRE_EX(SVM_EXIT_PAUSE),
442162306a36Sopenharmony_ci	[x86_intercept_pushf]		= PRE_EX(SVM_EXIT_PUSHF),
442262306a36Sopenharmony_ci	[x86_intercept_popf]		= PRE_EX(SVM_EXIT_POPF),
442362306a36Sopenharmony_ci	[x86_intercept_intn]		= PRE_EX(SVM_EXIT_SWINT),
442462306a36Sopenharmony_ci	[x86_intercept_iret]		= PRE_EX(SVM_EXIT_IRET),
442562306a36Sopenharmony_ci	[x86_intercept_icebp]		= PRE_EX(SVM_EXIT_ICEBP),
442662306a36Sopenharmony_ci	[x86_intercept_hlt]		= POST_EX(SVM_EXIT_HLT),
442762306a36Sopenharmony_ci	[x86_intercept_in]		= POST_EX(SVM_EXIT_IOIO),
442862306a36Sopenharmony_ci	[x86_intercept_ins]		= POST_EX(SVM_EXIT_IOIO),
442962306a36Sopenharmony_ci	[x86_intercept_out]		= POST_EX(SVM_EXIT_IOIO),
443062306a36Sopenharmony_ci	[x86_intercept_outs]		= POST_EX(SVM_EXIT_IOIO),
443162306a36Sopenharmony_ci	[x86_intercept_xsetbv]		= PRE_EX(SVM_EXIT_XSETBV),
443262306a36Sopenharmony_ci};
443362306a36Sopenharmony_ci
443462306a36Sopenharmony_ci#undef PRE_EX
443562306a36Sopenharmony_ci#undef POST_EX
443662306a36Sopenharmony_ci#undef POST_MEM
443762306a36Sopenharmony_ci
443862306a36Sopenharmony_cistatic int svm_check_intercept(struct kvm_vcpu *vcpu,
443962306a36Sopenharmony_ci			       struct x86_instruction_info *info,
444062306a36Sopenharmony_ci			       enum x86_intercept_stage stage,
444162306a36Sopenharmony_ci			       struct x86_exception *exception)
444262306a36Sopenharmony_ci{
444362306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
444462306a36Sopenharmony_ci	int vmexit, ret = X86EMUL_CONTINUE;
444562306a36Sopenharmony_ci	struct __x86_intercept icpt_info;
444662306a36Sopenharmony_ci	struct vmcb *vmcb = svm->vmcb;
444762306a36Sopenharmony_ci
444862306a36Sopenharmony_ci	if (info->intercept >= ARRAY_SIZE(x86_intercept_map))
444962306a36Sopenharmony_ci		goto out;
445062306a36Sopenharmony_ci
445162306a36Sopenharmony_ci	icpt_info = x86_intercept_map[info->intercept];
445262306a36Sopenharmony_ci
445362306a36Sopenharmony_ci	if (stage != icpt_info.stage)
445462306a36Sopenharmony_ci		goto out;
445562306a36Sopenharmony_ci
445662306a36Sopenharmony_ci	switch (icpt_info.exit_code) {
445762306a36Sopenharmony_ci	case SVM_EXIT_READ_CR0:
445862306a36Sopenharmony_ci		if (info->intercept == x86_intercept_cr_read)
445962306a36Sopenharmony_ci			icpt_info.exit_code += info->modrm_reg;
446062306a36Sopenharmony_ci		break;
446162306a36Sopenharmony_ci	case SVM_EXIT_WRITE_CR0: {
446262306a36Sopenharmony_ci		unsigned long cr0, val;
446362306a36Sopenharmony_ci
446462306a36Sopenharmony_ci		if (info->intercept == x86_intercept_cr_write)
446562306a36Sopenharmony_ci			icpt_info.exit_code += info->modrm_reg;
446662306a36Sopenharmony_ci
446762306a36Sopenharmony_ci		if (icpt_info.exit_code != SVM_EXIT_WRITE_CR0 ||
446862306a36Sopenharmony_ci		    info->intercept == x86_intercept_clts)
446962306a36Sopenharmony_ci			break;
447062306a36Sopenharmony_ci
447162306a36Sopenharmony_ci		if (!(vmcb12_is_intercept(&svm->nested.ctl,
447262306a36Sopenharmony_ci					INTERCEPT_SELECTIVE_CR0)))
447362306a36Sopenharmony_ci			break;
447462306a36Sopenharmony_ci
447562306a36Sopenharmony_ci		cr0 = vcpu->arch.cr0 & ~SVM_CR0_SELECTIVE_MASK;
447662306a36Sopenharmony_ci		val = info->src_val  & ~SVM_CR0_SELECTIVE_MASK;
447762306a36Sopenharmony_ci
447862306a36Sopenharmony_ci		if (info->intercept == x86_intercept_lmsw) {
447962306a36Sopenharmony_ci			cr0 &= 0xfUL;
448062306a36Sopenharmony_ci			val &= 0xfUL;
448162306a36Sopenharmony_ci			/* lmsw can't clear PE - catch this here */
448262306a36Sopenharmony_ci			if (cr0 & X86_CR0_PE)
448362306a36Sopenharmony_ci				val |= X86_CR0_PE;
448462306a36Sopenharmony_ci		}
448562306a36Sopenharmony_ci
448662306a36Sopenharmony_ci		if (cr0 ^ val)
448762306a36Sopenharmony_ci			icpt_info.exit_code = SVM_EXIT_CR0_SEL_WRITE;
448862306a36Sopenharmony_ci
448962306a36Sopenharmony_ci		break;
449062306a36Sopenharmony_ci	}
449162306a36Sopenharmony_ci	case SVM_EXIT_READ_DR0:
449262306a36Sopenharmony_ci	case SVM_EXIT_WRITE_DR0:
449362306a36Sopenharmony_ci		icpt_info.exit_code += info->modrm_reg;
449462306a36Sopenharmony_ci		break;
449562306a36Sopenharmony_ci	case SVM_EXIT_MSR:
449662306a36Sopenharmony_ci		if (info->intercept == x86_intercept_wrmsr)
449762306a36Sopenharmony_ci			vmcb->control.exit_info_1 = 1;
449862306a36Sopenharmony_ci		else
449962306a36Sopenharmony_ci			vmcb->control.exit_info_1 = 0;
450062306a36Sopenharmony_ci		break;
450162306a36Sopenharmony_ci	case SVM_EXIT_PAUSE:
450262306a36Sopenharmony_ci		/*
450362306a36Sopenharmony_ci		 * We get this for NOP only, but pause
450462306a36Sopenharmony_ci		 * is rep not, check this here
450562306a36Sopenharmony_ci		 */
450662306a36Sopenharmony_ci		if (info->rep_prefix != REPE_PREFIX)
450762306a36Sopenharmony_ci			goto out;
450862306a36Sopenharmony_ci		break;
450962306a36Sopenharmony_ci	case SVM_EXIT_IOIO: {
451062306a36Sopenharmony_ci		u64 exit_info;
451162306a36Sopenharmony_ci		u32 bytes;
451262306a36Sopenharmony_ci
451362306a36Sopenharmony_ci		if (info->intercept == x86_intercept_in ||
451462306a36Sopenharmony_ci		    info->intercept == x86_intercept_ins) {
451562306a36Sopenharmony_ci			exit_info = ((info->src_val & 0xffff) << 16) |
451662306a36Sopenharmony_ci				SVM_IOIO_TYPE_MASK;
451762306a36Sopenharmony_ci			bytes = info->dst_bytes;
451862306a36Sopenharmony_ci		} else {
451962306a36Sopenharmony_ci			exit_info = (info->dst_val & 0xffff) << 16;
452062306a36Sopenharmony_ci			bytes = info->src_bytes;
452162306a36Sopenharmony_ci		}
452262306a36Sopenharmony_ci
452362306a36Sopenharmony_ci		if (info->intercept == x86_intercept_outs ||
452462306a36Sopenharmony_ci		    info->intercept == x86_intercept_ins)
452562306a36Sopenharmony_ci			exit_info |= SVM_IOIO_STR_MASK;
452662306a36Sopenharmony_ci
452762306a36Sopenharmony_ci		if (info->rep_prefix)
452862306a36Sopenharmony_ci			exit_info |= SVM_IOIO_REP_MASK;
452962306a36Sopenharmony_ci
453062306a36Sopenharmony_ci		bytes = min(bytes, 4u);
453162306a36Sopenharmony_ci
453262306a36Sopenharmony_ci		exit_info |= bytes << SVM_IOIO_SIZE_SHIFT;
453362306a36Sopenharmony_ci
453462306a36Sopenharmony_ci		exit_info |= (u32)info->ad_bytes << (SVM_IOIO_ASIZE_SHIFT - 1);
453562306a36Sopenharmony_ci
453662306a36Sopenharmony_ci		vmcb->control.exit_info_1 = exit_info;
453762306a36Sopenharmony_ci		vmcb->control.exit_info_2 = info->next_rip;
453862306a36Sopenharmony_ci
453962306a36Sopenharmony_ci		break;
454062306a36Sopenharmony_ci	}
454162306a36Sopenharmony_ci	default:
454262306a36Sopenharmony_ci		break;
454362306a36Sopenharmony_ci	}
454462306a36Sopenharmony_ci
454562306a36Sopenharmony_ci	/* TODO: Advertise NRIPS to guest hypervisor unconditionally */
454662306a36Sopenharmony_ci	if (static_cpu_has(X86_FEATURE_NRIPS))
454762306a36Sopenharmony_ci		vmcb->control.next_rip  = info->next_rip;
454862306a36Sopenharmony_ci	vmcb->control.exit_code = icpt_info.exit_code;
454962306a36Sopenharmony_ci	vmexit = nested_svm_exit_handled(svm);
455062306a36Sopenharmony_ci
455162306a36Sopenharmony_ci	ret = (vmexit == NESTED_EXIT_DONE) ? X86EMUL_INTERCEPTED
455262306a36Sopenharmony_ci					   : X86EMUL_CONTINUE;
455362306a36Sopenharmony_ci
455462306a36Sopenharmony_ciout:
455562306a36Sopenharmony_ci	return ret;
455662306a36Sopenharmony_ci}
455762306a36Sopenharmony_ci
455862306a36Sopenharmony_cistatic void svm_handle_exit_irqoff(struct kvm_vcpu *vcpu)
455962306a36Sopenharmony_ci{
456062306a36Sopenharmony_ci	if (to_svm(vcpu)->vmcb->control.exit_code == SVM_EXIT_INTR)
456162306a36Sopenharmony_ci		vcpu->arch.at_instruction_boundary = true;
456262306a36Sopenharmony_ci}
456362306a36Sopenharmony_ci
456462306a36Sopenharmony_cistatic void svm_sched_in(struct kvm_vcpu *vcpu, int cpu)
456562306a36Sopenharmony_ci{
456662306a36Sopenharmony_ci	if (!kvm_pause_in_guest(vcpu->kvm))
456762306a36Sopenharmony_ci		shrink_ple_window(vcpu);
456862306a36Sopenharmony_ci}
456962306a36Sopenharmony_ci
457062306a36Sopenharmony_cistatic void svm_setup_mce(struct kvm_vcpu *vcpu)
457162306a36Sopenharmony_ci{
457262306a36Sopenharmony_ci	/* [63:9] are reserved. */
457362306a36Sopenharmony_ci	vcpu->arch.mcg_cap &= 0x1ff;
457462306a36Sopenharmony_ci}
457562306a36Sopenharmony_ci
457662306a36Sopenharmony_ci#ifdef CONFIG_KVM_SMM
457762306a36Sopenharmony_cibool svm_smi_blocked(struct kvm_vcpu *vcpu)
457862306a36Sopenharmony_ci{
457962306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
458062306a36Sopenharmony_ci
458162306a36Sopenharmony_ci	/* Per APM Vol.2 15.22.2 "Response to SMI" */
458262306a36Sopenharmony_ci	if (!gif_set(svm))
458362306a36Sopenharmony_ci		return true;
458462306a36Sopenharmony_ci
458562306a36Sopenharmony_ci	return is_smm(vcpu);
458662306a36Sopenharmony_ci}
458762306a36Sopenharmony_ci
458862306a36Sopenharmony_cistatic int svm_smi_allowed(struct kvm_vcpu *vcpu, bool for_injection)
458962306a36Sopenharmony_ci{
459062306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
459162306a36Sopenharmony_ci	if (svm->nested.nested_run_pending)
459262306a36Sopenharmony_ci		return -EBUSY;
459362306a36Sopenharmony_ci
459462306a36Sopenharmony_ci	if (svm_smi_blocked(vcpu))
459562306a36Sopenharmony_ci		return 0;
459662306a36Sopenharmony_ci
459762306a36Sopenharmony_ci	/* An SMI must not be injected into L2 if it's supposed to VM-Exit.  */
459862306a36Sopenharmony_ci	if (for_injection && is_guest_mode(vcpu) && nested_exit_on_smi(svm))
459962306a36Sopenharmony_ci		return -EBUSY;
460062306a36Sopenharmony_ci
460162306a36Sopenharmony_ci	return 1;
460262306a36Sopenharmony_ci}
460362306a36Sopenharmony_ci
460462306a36Sopenharmony_cistatic int svm_enter_smm(struct kvm_vcpu *vcpu, union kvm_smram *smram)
460562306a36Sopenharmony_ci{
460662306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
460762306a36Sopenharmony_ci	struct kvm_host_map map_save;
460862306a36Sopenharmony_ci	int ret;
460962306a36Sopenharmony_ci
461062306a36Sopenharmony_ci	if (!is_guest_mode(vcpu))
461162306a36Sopenharmony_ci		return 0;
461262306a36Sopenharmony_ci
461362306a36Sopenharmony_ci	/*
461462306a36Sopenharmony_ci	 * 32-bit SMRAM format doesn't preserve EFER and SVM state.  Userspace is
461562306a36Sopenharmony_ci	 * responsible for ensuring nested SVM and SMIs are mutually exclusive.
461662306a36Sopenharmony_ci	 */
461762306a36Sopenharmony_ci
461862306a36Sopenharmony_ci	if (!guest_cpuid_has(vcpu, X86_FEATURE_LM))
461962306a36Sopenharmony_ci		return 1;
462062306a36Sopenharmony_ci
462162306a36Sopenharmony_ci	smram->smram64.svm_guest_flag = 1;
462262306a36Sopenharmony_ci	smram->smram64.svm_guest_vmcb_gpa = svm->nested.vmcb12_gpa;
462362306a36Sopenharmony_ci
462462306a36Sopenharmony_ci	svm->vmcb->save.rax = vcpu->arch.regs[VCPU_REGS_RAX];
462562306a36Sopenharmony_ci	svm->vmcb->save.rsp = vcpu->arch.regs[VCPU_REGS_RSP];
462662306a36Sopenharmony_ci	svm->vmcb->save.rip = vcpu->arch.regs[VCPU_REGS_RIP];
462762306a36Sopenharmony_ci
462862306a36Sopenharmony_ci	ret = nested_svm_simple_vmexit(svm, SVM_EXIT_SW);
462962306a36Sopenharmony_ci	if (ret)
463062306a36Sopenharmony_ci		return ret;
463162306a36Sopenharmony_ci
463262306a36Sopenharmony_ci	/*
463362306a36Sopenharmony_ci	 * KVM uses VMCB01 to store L1 host state while L2 runs but
463462306a36Sopenharmony_ci	 * VMCB01 is going to be used during SMM and thus the state will
463562306a36Sopenharmony_ci	 * be lost. Temporary save non-VMLOAD/VMSAVE state to the host save
463662306a36Sopenharmony_ci	 * area pointed to by MSR_VM_HSAVE_PA. APM guarantees that the
463762306a36Sopenharmony_ci	 * format of the area is identical to guest save area offsetted
463862306a36Sopenharmony_ci	 * by 0x400 (matches the offset of 'struct vmcb_save_area'
463962306a36Sopenharmony_ci	 * within 'struct vmcb'). Note: HSAVE area may also be used by
464062306a36Sopenharmony_ci	 * L1 hypervisor to save additional host context (e.g. KVM does
464162306a36Sopenharmony_ci	 * that, see svm_prepare_switch_to_guest()) which must be
464262306a36Sopenharmony_ci	 * preserved.
464362306a36Sopenharmony_ci	 */
464462306a36Sopenharmony_ci	if (kvm_vcpu_map(vcpu, gpa_to_gfn(svm->nested.hsave_msr), &map_save))
464562306a36Sopenharmony_ci		return 1;
464662306a36Sopenharmony_ci
464762306a36Sopenharmony_ci	BUILD_BUG_ON(offsetof(struct vmcb, save) != 0x400);
464862306a36Sopenharmony_ci
464962306a36Sopenharmony_ci	svm_copy_vmrun_state(map_save.hva + 0x400,
465062306a36Sopenharmony_ci			     &svm->vmcb01.ptr->save);
465162306a36Sopenharmony_ci
465262306a36Sopenharmony_ci	kvm_vcpu_unmap(vcpu, &map_save, true);
465362306a36Sopenharmony_ci	return 0;
465462306a36Sopenharmony_ci}
465562306a36Sopenharmony_ci
465662306a36Sopenharmony_cistatic int svm_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram)
465762306a36Sopenharmony_ci{
465862306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
465962306a36Sopenharmony_ci	struct kvm_host_map map, map_save;
466062306a36Sopenharmony_ci	struct vmcb *vmcb12;
466162306a36Sopenharmony_ci	int ret;
466262306a36Sopenharmony_ci
466362306a36Sopenharmony_ci	const struct kvm_smram_state_64 *smram64 = &smram->smram64;
466462306a36Sopenharmony_ci
466562306a36Sopenharmony_ci	if (!guest_cpuid_has(vcpu, X86_FEATURE_LM))
466662306a36Sopenharmony_ci		return 0;
466762306a36Sopenharmony_ci
466862306a36Sopenharmony_ci	/* Non-zero if SMI arrived while vCPU was in guest mode. */
466962306a36Sopenharmony_ci	if (!smram64->svm_guest_flag)
467062306a36Sopenharmony_ci		return 0;
467162306a36Sopenharmony_ci
467262306a36Sopenharmony_ci	if (!guest_cpuid_has(vcpu, X86_FEATURE_SVM))
467362306a36Sopenharmony_ci		return 1;
467462306a36Sopenharmony_ci
467562306a36Sopenharmony_ci	if (!(smram64->efer & EFER_SVME))
467662306a36Sopenharmony_ci		return 1;
467762306a36Sopenharmony_ci
467862306a36Sopenharmony_ci	if (kvm_vcpu_map(vcpu, gpa_to_gfn(smram64->svm_guest_vmcb_gpa), &map))
467962306a36Sopenharmony_ci		return 1;
468062306a36Sopenharmony_ci
468162306a36Sopenharmony_ci	ret = 1;
468262306a36Sopenharmony_ci	if (kvm_vcpu_map(vcpu, gpa_to_gfn(svm->nested.hsave_msr), &map_save))
468362306a36Sopenharmony_ci		goto unmap_map;
468462306a36Sopenharmony_ci
468562306a36Sopenharmony_ci	if (svm_allocate_nested(svm))
468662306a36Sopenharmony_ci		goto unmap_save;
468762306a36Sopenharmony_ci
468862306a36Sopenharmony_ci	/*
468962306a36Sopenharmony_ci	 * Restore L1 host state from L1 HSAVE area as VMCB01 was
469062306a36Sopenharmony_ci	 * used during SMM (see svm_enter_smm())
469162306a36Sopenharmony_ci	 */
469262306a36Sopenharmony_ci
469362306a36Sopenharmony_ci	svm_copy_vmrun_state(&svm->vmcb01.ptr->save, map_save.hva + 0x400);
469462306a36Sopenharmony_ci
469562306a36Sopenharmony_ci	/*
469662306a36Sopenharmony_ci	 * Enter the nested guest now
469762306a36Sopenharmony_ci	 */
469862306a36Sopenharmony_ci
469962306a36Sopenharmony_ci	vmcb_mark_all_dirty(svm->vmcb01.ptr);
470062306a36Sopenharmony_ci
470162306a36Sopenharmony_ci	vmcb12 = map.hva;
470262306a36Sopenharmony_ci	nested_copy_vmcb_control_to_cache(svm, &vmcb12->control);
470362306a36Sopenharmony_ci	nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);
470462306a36Sopenharmony_ci	ret = enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa, vmcb12, false);
470562306a36Sopenharmony_ci
470662306a36Sopenharmony_ci	if (ret)
470762306a36Sopenharmony_ci		goto unmap_save;
470862306a36Sopenharmony_ci
470962306a36Sopenharmony_ci	svm->nested.nested_run_pending = 1;
471062306a36Sopenharmony_ci
471162306a36Sopenharmony_ciunmap_save:
471262306a36Sopenharmony_ci	kvm_vcpu_unmap(vcpu, &map_save, true);
471362306a36Sopenharmony_ciunmap_map:
471462306a36Sopenharmony_ci	kvm_vcpu_unmap(vcpu, &map, true);
471562306a36Sopenharmony_ci	return ret;
471662306a36Sopenharmony_ci}
471762306a36Sopenharmony_ci
471862306a36Sopenharmony_cistatic void svm_enable_smi_window(struct kvm_vcpu *vcpu)
471962306a36Sopenharmony_ci{
472062306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
472162306a36Sopenharmony_ci
472262306a36Sopenharmony_ci	if (!gif_set(svm)) {
472362306a36Sopenharmony_ci		if (vgif)
472462306a36Sopenharmony_ci			svm_set_intercept(svm, INTERCEPT_STGI);
472562306a36Sopenharmony_ci		/* STGI will cause a vm exit */
472662306a36Sopenharmony_ci	} else {
472762306a36Sopenharmony_ci		/* We must be in SMM; RSM will cause a vmexit anyway.  */
472862306a36Sopenharmony_ci	}
472962306a36Sopenharmony_ci}
473062306a36Sopenharmony_ci#endif
473162306a36Sopenharmony_ci
473262306a36Sopenharmony_cistatic bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
473362306a36Sopenharmony_ci					void *insn, int insn_len)
473462306a36Sopenharmony_ci{
473562306a36Sopenharmony_ci	bool smep, smap, is_user;
473662306a36Sopenharmony_ci	u64 error_code;
473762306a36Sopenharmony_ci
473862306a36Sopenharmony_ci	/* Emulation is always possible when KVM has access to all guest state. */
473962306a36Sopenharmony_ci	if (!sev_guest(vcpu->kvm))
474062306a36Sopenharmony_ci		return true;
474162306a36Sopenharmony_ci
474262306a36Sopenharmony_ci	/* #UD and #GP should never be intercepted for SEV guests. */
474362306a36Sopenharmony_ci	WARN_ON_ONCE(emul_type & (EMULTYPE_TRAP_UD |
474462306a36Sopenharmony_ci				  EMULTYPE_TRAP_UD_FORCED |
474562306a36Sopenharmony_ci				  EMULTYPE_VMWARE_GP));
474662306a36Sopenharmony_ci
474762306a36Sopenharmony_ci	/*
474862306a36Sopenharmony_ci	 * Emulation is impossible for SEV-ES guests as KVM doesn't have access
474962306a36Sopenharmony_ci	 * to guest register state.
475062306a36Sopenharmony_ci	 */
475162306a36Sopenharmony_ci	if (sev_es_guest(vcpu->kvm))
475262306a36Sopenharmony_ci		return false;
475362306a36Sopenharmony_ci
475462306a36Sopenharmony_ci	/*
475562306a36Sopenharmony_ci	 * Emulation is possible if the instruction is already decoded, e.g.
475662306a36Sopenharmony_ci	 * when completing I/O after returning from userspace.
475762306a36Sopenharmony_ci	 */
475862306a36Sopenharmony_ci	if (emul_type & EMULTYPE_NO_DECODE)
475962306a36Sopenharmony_ci		return true;
476062306a36Sopenharmony_ci
476162306a36Sopenharmony_ci	/*
476262306a36Sopenharmony_ci	 * Emulation is possible for SEV guests if and only if a prefilled
476362306a36Sopenharmony_ci	 * buffer containing the bytes of the intercepted instruction is
476462306a36Sopenharmony_ci	 * available. SEV guest memory is encrypted with a guest specific key
476562306a36Sopenharmony_ci	 * and cannot be decrypted by KVM, i.e. KVM would read cyphertext and
476662306a36Sopenharmony_ci	 * decode garbage.
476762306a36Sopenharmony_ci	 *
476862306a36Sopenharmony_ci	 * If KVM is NOT trying to simply skip an instruction, inject #UD if
476962306a36Sopenharmony_ci	 * KVM reached this point without an instruction buffer.  In practice,
477062306a36Sopenharmony_ci	 * this path should never be hit by a well-behaved guest, e.g. KVM
477162306a36Sopenharmony_ci	 * doesn't intercept #UD or #GP for SEV guests, but this path is still
477262306a36Sopenharmony_ci	 * theoretically reachable, e.g. via unaccelerated fault-like AVIC
477362306a36Sopenharmony_ci	 * access, and needs to be handled by KVM to avoid putting the guest
477462306a36Sopenharmony_ci	 * into an infinite loop.   Injecting #UD is somewhat arbitrary, but
477562306a36Sopenharmony_ci	 * its the least awful option given lack of insight into the guest.
477662306a36Sopenharmony_ci	 *
477762306a36Sopenharmony_ci	 * If KVM is trying to skip an instruction, simply resume the guest.
477862306a36Sopenharmony_ci	 * If a #NPF occurs while the guest is vectoring an INT3/INTO, then KVM
477962306a36Sopenharmony_ci	 * will attempt to re-inject the INT3/INTO and skip the instruction.
478062306a36Sopenharmony_ci	 * In that scenario, retrying the INT3/INTO and hoping the guest will
478162306a36Sopenharmony_ci	 * make forward progress is the only option that has a chance of
478262306a36Sopenharmony_ci	 * success (and in practice it will work the vast majority of the time).
478362306a36Sopenharmony_ci	 */
478462306a36Sopenharmony_ci	if (unlikely(!insn)) {
478562306a36Sopenharmony_ci		if (!(emul_type & EMULTYPE_SKIP))
478662306a36Sopenharmony_ci			kvm_queue_exception(vcpu, UD_VECTOR);
478762306a36Sopenharmony_ci		return false;
478862306a36Sopenharmony_ci	}
478962306a36Sopenharmony_ci
479062306a36Sopenharmony_ci	/*
479162306a36Sopenharmony_ci	 * Emulate for SEV guests if the insn buffer is not empty.  The buffer
479262306a36Sopenharmony_ci	 * will be empty if the DecodeAssist microcode cannot fetch bytes for
479362306a36Sopenharmony_ci	 * the faulting instruction because the code fetch itself faulted, e.g.
479462306a36Sopenharmony_ci	 * the guest attempted to fetch from emulated MMIO or a guest page
479562306a36Sopenharmony_ci	 * table used to translate CS:RIP resides in emulated MMIO.
479662306a36Sopenharmony_ci	 */
479762306a36Sopenharmony_ci	if (likely(insn_len))
479862306a36Sopenharmony_ci		return true;
479962306a36Sopenharmony_ci
480062306a36Sopenharmony_ci	/*
480162306a36Sopenharmony_ci	 * Detect and workaround Errata 1096 Fam_17h_00_0Fh.
480262306a36Sopenharmony_ci	 *
480362306a36Sopenharmony_ci	 * Errata:
480462306a36Sopenharmony_ci	 * When CPU raises #NPF on guest data access and vCPU CR4.SMAP=1, it is
480562306a36Sopenharmony_ci	 * possible that CPU microcode implementing DecodeAssist will fail to
480662306a36Sopenharmony_ci	 * read guest memory at CS:RIP and vmcb.GuestIntrBytes will incorrectly
480762306a36Sopenharmony_ci	 * be '0'.  This happens because microcode reads CS:RIP using a _data_
480862306a36Sopenharmony_ci	 * loap uop with CPL=0 privileges.  If the load hits a SMAP #PF, ucode
480962306a36Sopenharmony_ci	 * gives up and does not fill the instruction bytes buffer.
481062306a36Sopenharmony_ci	 *
481162306a36Sopenharmony_ci	 * As above, KVM reaches this point iff the VM is an SEV guest, the CPU
481262306a36Sopenharmony_ci	 * supports DecodeAssist, a #NPF was raised, KVM's page fault handler
481362306a36Sopenharmony_ci	 * triggered emulation (e.g. for MMIO), and the CPU returned 0 in the
481462306a36Sopenharmony_ci	 * GuestIntrBytes field of the VMCB.
481562306a36Sopenharmony_ci	 *
481662306a36Sopenharmony_ci	 * This does _not_ mean that the erratum has been encountered, as the
481762306a36Sopenharmony_ci	 * DecodeAssist will also fail if the load for CS:RIP hits a legitimate
481862306a36Sopenharmony_ci	 * #PF, e.g. if the guest attempt to execute from emulated MMIO and
481962306a36Sopenharmony_ci	 * encountered a reserved/not-present #PF.
482062306a36Sopenharmony_ci	 *
482162306a36Sopenharmony_ci	 * To hit the erratum, the following conditions must be true:
482262306a36Sopenharmony_ci	 *    1. CR4.SMAP=1 (obviously).
482362306a36Sopenharmony_ci	 *    2. CR4.SMEP=0 || CPL=3.  If SMEP=1 and CPL<3, the erratum cannot
482462306a36Sopenharmony_ci	 *       have been hit as the guest would have encountered a SMEP
482562306a36Sopenharmony_ci	 *       violation #PF, not a #NPF.
482662306a36Sopenharmony_ci	 *    3. The #NPF is not due to a code fetch, in which case failure to
482762306a36Sopenharmony_ci	 *       retrieve the instruction bytes is legitimate (see abvoe).
482862306a36Sopenharmony_ci	 *
482962306a36Sopenharmony_ci	 * In addition, don't apply the erratum workaround if the #NPF occurred
483062306a36Sopenharmony_ci	 * while translating guest page tables (see below).
483162306a36Sopenharmony_ci	 */
483262306a36Sopenharmony_ci	error_code = to_svm(vcpu)->vmcb->control.exit_info_1;
483362306a36Sopenharmony_ci	if (error_code & (PFERR_GUEST_PAGE_MASK | PFERR_FETCH_MASK))
483462306a36Sopenharmony_ci		goto resume_guest;
483562306a36Sopenharmony_ci
483662306a36Sopenharmony_ci	smep = kvm_is_cr4_bit_set(vcpu, X86_CR4_SMEP);
483762306a36Sopenharmony_ci	smap = kvm_is_cr4_bit_set(vcpu, X86_CR4_SMAP);
483862306a36Sopenharmony_ci	is_user = svm_get_cpl(vcpu) == 3;
483962306a36Sopenharmony_ci	if (smap && (!smep || is_user)) {
484062306a36Sopenharmony_ci		pr_err_ratelimited("SEV Guest triggered AMD Erratum 1096\n");
484162306a36Sopenharmony_ci
484262306a36Sopenharmony_ci		/*
484362306a36Sopenharmony_ci		 * If the fault occurred in userspace, arbitrarily inject #GP
484462306a36Sopenharmony_ci		 * to avoid killing the guest and to hopefully avoid confusing
484562306a36Sopenharmony_ci		 * the guest kernel too much, e.g. injecting #PF would not be
484662306a36Sopenharmony_ci		 * coherent with respect to the guest's page tables.  Request
484762306a36Sopenharmony_ci		 * triple fault if the fault occurred in the kernel as there's
484862306a36Sopenharmony_ci		 * no fault that KVM can inject without confusing the guest.
484962306a36Sopenharmony_ci		 * In practice, the triple fault is moot as no sane SEV kernel
485062306a36Sopenharmony_ci		 * will execute from user memory while also running with SMAP=1.
485162306a36Sopenharmony_ci		 */
485262306a36Sopenharmony_ci		if (is_user)
485362306a36Sopenharmony_ci			kvm_inject_gp(vcpu, 0);
485462306a36Sopenharmony_ci		else
485562306a36Sopenharmony_ci			kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
485662306a36Sopenharmony_ci	}
485762306a36Sopenharmony_ci
485862306a36Sopenharmony_ciresume_guest:
485962306a36Sopenharmony_ci	/*
486062306a36Sopenharmony_ci	 * If the erratum was not hit, simply resume the guest and let it fault
486162306a36Sopenharmony_ci	 * again.  While awful, e.g. the vCPU may get stuck in an infinite loop
486262306a36Sopenharmony_ci	 * if the fault is at CPL=0, it's the lesser of all evils.  Exiting to
486362306a36Sopenharmony_ci	 * userspace will kill the guest, and letting the emulator read garbage
486462306a36Sopenharmony_ci	 * will yield random behavior and potentially corrupt the guest.
486562306a36Sopenharmony_ci	 *
486662306a36Sopenharmony_ci	 * Simply resuming the guest is technically not a violation of the SEV
486762306a36Sopenharmony_ci	 * architecture.  AMD's APM states that all code fetches and page table
486862306a36Sopenharmony_ci	 * accesses for SEV guest are encrypted, regardless of the C-Bit.  The
486962306a36Sopenharmony_ci	 * APM also states that encrypted accesses to MMIO are "ignored", but
487062306a36Sopenharmony_ci	 * doesn't explicitly define "ignored", i.e. doing nothing and letting
487162306a36Sopenharmony_ci	 * the guest spin is technically "ignoring" the access.
487262306a36Sopenharmony_ci	 */
487362306a36Sopenharmony_ci	return false;
487462306a36Sopenharmony_ci}
487562306a36Sopenharmony_ci
487662306a36Sopenharmony_cistatic bool svm_apic_init_signal_blocked(struct kvm_vcpu *vcpu)
487762306a36Sopenharmony_ci{
487862306a36Sopenharmony_ci	struct vcpu_svm *svm = to_svm(vcpu);
487962306a36Sopenharmony_ci
488062306a36Sopenharmony_ci	return !gif_set(svm);
488162306a36Sopenharmony_ci}
488262306a36Sopenharmony_ci
488362306a36Sopenharmony_cistatic void svm_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector)
488462306a36Sopenharmony_ci{
488562306a36Sopenharmony_ci	if (!sev_es_guest(vcpu->kvm))
488662306a36Sopenharmony_ci		return kvm_vcpu_deliver_sipi_vector(vcpu, vector);
488762306a36Sopenharmony_ci
488862306a36Sopenharmony_ci	sev_vcpu_deliver_sipi_vector(vcpu, vector);
488962306a36Sopenharmony_ci}
489062306a36Sopenharmony_ci
489162306a36Sopenharmony_cistatic void svm_vm_destroy(struct kvm *kvm)
489262306a36Sopenharmony_ci{
489362306a36Sopenharmony_ci	avic_vm_destroy(kvm);
489462306a36Sopenharmony_ci	sev_vm_destroy(kvm);
489562306a36Sopenharmony_ci}
489662306a36Sopenharmony_ci
489762306a36Sopenharmony_cistatic int svm_vm_init(struct kvm *kvm)
489862306a36Sopenharmony_ci{
489962306a36Sopenharmony_ci	if (!pause_filter_count || !pause_filter_thresh)
490062306a36Sopenharmony_ci		kvm->arch.pause_in_guest = true;
490162306a36Sopenharmony_ci
490262306a36Sopenharmony_ci	if (enable_apicv) {
490362306a36Sopenharmony_ci		int ret = avic_vm_init(kvm);
490462306a36Sopenharmony_ci		if (ret)
490562306a36Sopenharmony_ci			return ret;
490662306a36Sopenharmony_ci	}
490762306a36Sopenharmony_ci
490862306a36Sopenharmony_ci	return 0;
490962306a36Sopenharmony_ci}
491062306a36Sopenharmony_ci
491162306a36Sopenharmony_cistatic struct kvm_x86_ops svm_x86_ops __initdata = {
491262306a36Sopenharmony_ci	.name = KBUILD_MODNAME,
491362306a36Sopenharmony_ci
491462306a36Sopenharmony_ci	.check_processor_compatibility = svm_check_processor_compat,
491562306a36Sopenharmony_ci
491662306a36Sopenharmony_ci	.hardware_unsetup = svm_hardware_unsetup,
491762306a36Sopenharmony_ci	.hardware_enable = svm_hardware_enable,
491862306a36Sopenharmony_ci	.hardware_disable = svm_hardware_disable,
491962306a36Sopenharmony_ci	.has_emulated_msr = svm_has_emulated_msr,
492062306a36Sopenharmony_ci
492162306a36Sopenharmony_ci	.vcpu_create = svm_vcpu_create,
492262306a36Sopenharmony_ci	.vcpu_free = svm_vcpu_free,
492362306a36Sopenharmony_ci	.vcpu_reset = svm_vcpu_reset,
492462306a36Sopenharmony_ci
492562306a36Sopenharmony_ci	.vm_size = sizeof(struct kvm_svm),
492662306a36Sopenharmony_ci	.vm_init = svm_vm_init,
492762306a36Sopenharmony_ci	.vm_destroy = svm_vm_destroy,
492862306a36Sopenharmony_ci
492962306a36Sopenharmony_ci	.prepare_switch_to_guest = svm_prepare_switch_to_guest,
493062306a36Sopenharmony_ci	.vcpu_load = svm_vcpu_load,
493162306a36Sopenharmony_ci	.vcpu_put = svm_vcpu_put,
493262306a36Sopenharmony_ci	.vcpu_blocking = avic_vcpu_blocking,
493362306a36Sopenharmony_ci	.vcpu_unblocking = avic_vcpu_unblocking,
493462306a36Sopenharmony_ci
493562306a36Sopenharmony_ci	.update_exception_bitmap = svm_update_exception_bitmap,
493662306a36Sopenharmony_ci	.get_msr_feature = svm_get_msr_feature,
493762306a36Sopenharmony_ci	.get_msr = svm_get_msr,
493862306a36Sopenharmony_ci	.set_msr = svm_set_msr,
493962306a36Sopenharmony_ci	.get_segment_base = svm_get_segment_base,
494062306a36Sopenharmony_ci	.get_segment = svm_get_segment,
494162306a36Sopenharmony_ci	.set_segment = svm_set_segment,
494262306a36Sopenharmony_ci	.get_cpl = svm_get_cpl,
494362306a36Sopenharmony_ci	.get_cs_db_l_bits = svm_get_cs_db_l_bits,
494462306a36Sopenharmony_ci	.is_valid_cr0 = svm_is_valid_cr0,
494562306a36Sopenharmony_ci	.set_cr0 = svm_set_cr0,
494662306a36Sopenharmony_ci	.post_set_cr3 = sev_post_set_cr3,
494762306a36Sopenharmony_ci	.is_valid_cr4 = svm_is_valid_cr4,
494862306a36Sopenharmony_ci	.set_cr4 = svm_set_cr4,
494962306a36Sopenharmony_ci	.set_efer = svm_set_efer,
495062306a36Sopenharmony_ci	.get_idt = svm_get_idt,
495162306a36Sopenharmony_ci	.set_idt = svm_set_idt,
495262306a36Sopenharmony_ci	.get_gdt = svm_get_gdt,
495362306a36Sopenharmony_ci	.set_gdt = svm_set_gdt,
495462306a36Sopenharmony_ci	.set_dr7 = svm_set_dr7,
495562306a36Sopenharmony_ci	.sync_dirty_debug_regs = svm_sync_dirty_debug_regs,
495662306a36Sopenharmony_ci	.cache_reg = svm_cache_reg,
495762306a36Sopenharmony_ci	.get_rflags = svm_get_rflags,
495862306a36Sopenharmony_ci	.set_rflags = svm_set_rflags,
495962306a36Sopenharmony_ci	.get_if_flag = svm_get_if_flag,
496062306a36Sopenharmony_ci
496162306a36Sopenharmony_ci	.flush_tlb_all = svm_flush_tlb_all,
496262306a36Sopenharmony_ci	.flush_tlb_current = svm_flush_tlb_current,
496362306a36Sopenharmony_ci	.flush_tlb_gva = svm_flush_tlb_gva,
496462306a36Sopenharmony_ci	.flush_tlb_guest = svm_flush_tlb_asid,
496562306a36Sopenharmony_ci
496662306a36Sopenharmony_ci	.vcpu_pre_run = svm_vcpu_pre_run,
496762306a36Sopenharmony_ci	.vcpu_run = svm_vcpu_run,
496862306a36Sopenharmony_ci	.handle_exit = svm_handle_exit,
496962306a36Sopenharmony_ci	.skip_emulated_instruction = svm_skip_emulated_instruction,
497062306a36Sopenharmony_ci	.update_emulated_instruction = NULL,
497162306a36Sopenharmony_ci	.set_interrupt_shadow = svm_set_interrupt_shadow,
497262306a36Sopenharmony_ci	.get_interrupt_shadow = svm_get_interrupt_shadow,
497362306a36Sopenharmony_ci	.patch_hypercall = svm_patch_hypercall,
497462306a36Sopenharmony_ci	.inject_irq = svm_inject_irq,
497562306a36Sopenharmony_ci	.inject_nmi = svm_inject_nmi,
497662306a36Sopenharmony_ci	.is_vnmi_pending = svm_is_vnmi_pending,
497762306a36Sopenharmony_ci	.set_vnmi_pending = svm_set_vnmi_pending,
497862306a36Sopenharmony_ci	.inject_exception = svm_inject_exception,
497962306a36Sopenharmony_ci	.cancel_injection = svm_cancel_injection,
498062306a36Sopenharmony_ci	.interrupt_allowed = svm_interrupt_allowed,
498162306a36Sopenharmony_ci	.nmi_allowed = svm_nmi_allowed,
498262306a36Sopenharmony_ci	.get_nmi_mask = svm_get_nmi_mask,
498362306a36Sopenharmony_ci	.set_nmi_mask = svm_set_nmi_mask,
498462306a36Sopenharmony_ci	.enable_nmi_window = svm_enable_nmi_window,
498562306a36Sopenharmony_ci	.enable_irq_window = svm_enable_irq_window,
498662306a36Sopenharmony_ci	.update_cr8_intercept = svm_update_cr8_intercept,
498762306a36Sopenharmony_ci	.set_virtual_apic_mode = avic_refresh_virtual_apic_mode,
498862306a36Sopenharmony_ci	.refresh_apicv_exec_ctrl = avic_refresh_apicv_exec_ctrl,
498962306a36Sopenharmony_ci	.apicv_post_state_restore = avic_apicv_post_state_restore,
499062306a36Sopenharmony_ci	.required_apicv_inhibits = AVIC_REQUIRED_APICV_INHIBITS,
499162306a36Sopenharmony_ci
499262306a36Sopenharmony_ci	.get_exit_info = svm_get_exit_info,
499362306a36Sopenharmony_ci
499462306a36Sopenharmony_ci	.vcpu_after_set_cpuid = svm_vcpu_after_set_cpuid,
499562306a36Sopenharmony_ci
499662306a36Sopenharmony_ci	.has_wbinvd_exit = svm_has_wbinvd_exit,
499762306a36Sopenharmony_ci
499862306a36Sopenharmony_ci	.get_l2_tsc_offset = svm_get_l2_tsc_offset,
499962306a36Sopenharmony_ci	.get_l2_tsc_multiplier = svm_get_l2_tsc_multiplier,
500062306a36Sopenharmony_ci	.write_tsc_offset = svm_write_tsc_offset,
500162306a36Sopenharmony_ci	.write_tsc_multiplier = svm_write_tsc_multiplier,
500262306a36Sopenharmony_ci
500362306a36Sopenharmony_ci	.load_mmu_pgd = svm_load_mmu_pgd,
500462306a36Sopenharmony_ci
500562306a36Sopenharmony_ci	.check_intercept = svm_check_intercept,
500662306a36Sopenharmony_ci	.handle_exit_irqoff = svm_handle_exit_irqoff,
500762306a36Sopenharmony_ci
500862306a36Sopenharmony_ci	.request_immediate_exit = __kvm_request_immediate_exit,
500962306a36Sopenharmony_ci
501062306a36Sopenharmony_ci	.sched_in = svm_sched_in,
501162306a36Sopenharmony_ci
501262306a36Sopenharmony_ci	.nested_ops = &svm_nested_ops,
501362306a36Sopenharmony_ci
501462306a36Sopenharmony_ci	.deliver_interrupt = svm_deliver_interrupt,
501562306a36Sopenharmony_ci	.pi_update_irte = avic_pi_update_irte,
501662306a36Sopenharmony_ci	.setup_mce = svm_setup_mce,
501762306a36Sopenharmony_ci
501862306a36Sopenharmony_ci#ifdef CONFIG_KVM_SMM
501962306a36Sopenharmony_ci	.smi_allowed = svm_smi_allowed,
502062306a36Sopenharmony_ci	.enter_smm = svm_enter_smm,
502162306a36Sopenharmony_ci	.leave_smm = svm_leave_smm,
502262306a36Sopenharmony_ci	.enable_smi_window = svm_enable_smi_window,
502362306a36Sopenharmony_ci#endif
502462306a36Sopenharmony_ci
502562306a36Sopenharmony_ci	.mem_enc_ioctl = sev_mem_enc_ioctl,
502662306a36Sopenharmony_ci	.mem_enc_register_region = sev_mem_enc_register_region,
502762306a36Sopenharmony_ci	.mem_enc_unregister_region = sev_mem_enc_unregister_region,
502862306a36Sopenharmony_ci	.guest_memory_reclaimed = sev_guest_memory_reclaimed,
502962306a36Sopenharmony_ci
503062306a36Sopenharmony_ci	.vm_copy_enc_context_from = sev_vm_copy_enc_context_from,
503162306a36Sopenharmony_ci	.vm_move_enc_context_from = sev_vm_move_enc_context_from,
503262306a36Sopenharmony_ci
503362306a36Sopenharmony_ci	.can_emulate_instruction = svm_can_emulate_instruction,
503462306a36Sopenharmony_ci
503562306a36Sopenharmony_ci	.apic_init_signal_blocked = svm_apic_init_signal_blocked,
503662306a36Sopenharmony_ci
503762306a36Sopenharmony_ci	.msr_filter_changed = svm_msr_filter_changed,
503862306a36Sopenharmony_ci	.complete_emulated_msr = svm_complete_emulated_msr,
503962306a36Sopenharmony_ci
504062306a36Sopenharmony_ci	.vcpu_deliver_sipi_vector = svm_vcpu_deliver_sipi_vector,
504162306a36Sopenharmony_ci	.vcpu_get_apicv_inhibit_reasons = avic_vcpu_get_apicv_inhibit_reasons,
504262306a36Sopenharmony_ci};
504362306a36Sopenharmony_ci
504462306a36Sopenharmony_ci/*
504562306a36Sopenharmony_ci * The default MMIO mask is a single bit (excluding the present bit),
504662306a36Sopenharmony_ci * which could conflict with the memory encryption bit. Check for
504762306a36Sopenharmony_ci * memory encryption support and override the default MMIO mask if
504862306a36Sopenharmony_ci * memory encryption is enabled.
504962306a36Sopenharmony_ci */
505062306a36Sopenharmony_cistatic __init void svm_adjust_mmio_mask(void)
505162306a36Sopenharmony_ci{
505262306a36Sopenharmony_ci	unsigned int enc_bit, mask_bit;
505362306a36Sopenharmony_ci	u64 msr, mask;
505462306a36Sopenharmony_ci
505562306a36Sopenharmony_ci	/* If there is no memory encryption support, use existing mask */
505662306a36Sopenharmony_ci	if (cpuid_eax(0x80000000) < 0x8000001f)
505762306a36Sopenharmony_ci		return;
505862306a36Sopenharmony_ci
505962306a36Sopenharmony_ci	/* If memory encryption is not enabled, use existing mask */
506062306a36Sopenharmony_ci	rdmsrl(MSR_AMD64_SYSCFG, msr);
506162306a36Sopenharmony_ci	if (!(msr & MSR_AMD64_SYSCFG_MEM_ENCRYPT))
506262306a36Sopenharmony_ci		return;
506362306a36Sopenharmony_ci
506462306a36Sopenharmony_ci	enc_bit = cpuid_ebx(0x8000001f) & 0x3f;
506562306a36Sopenharmony_ci	mask_bit = boot_cpu_data.x86_phys_bits;
506662306a36Sopenharmony_ci
506762306a36Sopenharmony_ci	/* Increment the mask bit if it is the same as the encryption bit */
506862306a36Sopenharmony_ci	if (enc_bit == mask_bit)
506962306a36Sopenharmony_ci		mask_bit++;
507062306a36Sopenharmony_ci
507162306a36Sopenharmony_ci	/*
507262306a36Sopenharmony_ci	 * If the mask bit location is below 52, then some bits above the
507362306a36Sopenharmony_ci	 * physical addressing limit will always be reserved, so use the
507462306a36Sopenharmony_ci	 * rsvd_bits() function to generate the mask. This mask, along with
507562306a36Sopenharmony_ci	 * the present bit, will be used to generate a page fault with
507662306a36Sopenharmony_ci	 * PFER.RSV = 1.
507762306a36Sopenharmony_ci	 *
507862306a36Sopenharmony_ci	 * If the mask bit location is 52 (or above), then clear the mask.
507962306a36Sopenharmony_ci	 */
508062306a36Sopenharmony_ci	mask = (mask_bit < 52) ? rsvd_bits(mask_bit, 51) | PT_PRESENT_MASK : 0;
508162306a36Sopenharmony_ci
508262306a36Sopenharmony_ci	kvm_mmu_set_mmio_spte_mask(mask, mask, PT_WRITABLE_MASK | PT_USER_MASK);
508362306a36Sopenharmony_ci}
508462306a36Sopenharmony_ci
508562306a36Sopenharmony_cistatic __init void svm_set_cpu_caps(void)
508662306a36Sopenharmony_ci{
508762306a36Sopenharmony_ci	kvm_set_cpu_caps();
508862306a36Sopenharmony_ci
508962306a36Sopenharmony_ci	kvm_caps.supported_perf_cap = 0;
509062306a36Sopenharmony_ci	kvm_caps.supported_xss = 0;
509162306a36Sopenharmony_ci
509262306a36Sopenharmony_ci	/* CPUID 0x80000001 and 0x8000000A (SVM features) */
509362306a36Sopenharmony_ci	if (nested) {
509462306a36Sopenharmony_ci		kvm_cpu_cap_set(X86_FEATURE_SVM);
509562306a36Sopenharmony_ci		kvm_cpu_cap_set(X86_FEATURE_VMCBCLEAN);
509662306a36Sopenharmony_ci
509762306a36Sopenharmony_ci		if (nrips)
509862306a36Sopenharmony_ci			kvm_cpu_cap_set(X86_FEATURE_NRIPS);
509962306a36Sopenharmony_ci
510062306a36Sopenharmony_ci		if (npt_enabled)
510162306a36Sopenharmony_ci			kvm_cpu_cap_set(X86_FEATURE_NPT);
510262306a36Sopenharmony_ci
510362306a36Sopenharmony_ci		if (tsc_scaling)
510462306a36Sopenharmony_ci			kvm_cpu_cap_set(X86_FEATURE_TSCRATEMSR);
510562306a36Sopenharmony_ci
510662306a36Sopenharmony_ci		if (vls)
510762306a36Sopenharmony_ci			kvm_cpu_cap_set(X86_FEATURE_V_VMSAVE_VMLOAD);
510862306a36Sopenharmony_ci		if (lbrv)
510962306a36Sopenharmony_ci			kvm_cpu_cap_set(X86_FEATURE_LBRV);
511062306a36Sopenharmony_ci
511162306a36Sopenharmony_ci		if (boot_cpu_has(X86_FEATURE_PAUSEFILTER))
511262306a36Sopenharmony_ci			kvm_cpu_cap_set(X86_FEATURE_PAUSEFILTER);
511362306a36Sopenharmony_ci
511462306a36Sopenharmony_ci		if (boot_cpu_has(X86_FEATURE_PFTHRESHOLD))
511562306a36Sopenharmony_ci			kvm_cpu_cap_set(X86_FEATURE_PFTHRESHOLD);
511662306a36Sopenharmony_ci
511762306a36Sopenharmony_ci		if (vgif)
511862306a36Sopenharmony_ci			kvm_cpu_cap_set(X86_FEATURE_VGIF);
511962306a36Sopenharmony_ci
512062306a36Sopenharmony_ci		if (vnmi)
512162306a36Sopenharmony_ci			kvm_cpu_cap_set(X86_FEATURE_VNMI);
512262306a36Sopenharmony_ci
512362306a36Sopenharmony_ci		/* Nested VM can receive #VMEXIT instead of triggering #GP */
512462306a36Sopenharmony_ci		kvm_cpu_cap_set(X86_FEATURE_SVME_ADDR_CHK);
512562306a36Sopenharmony_ci	}
512662306a36Sopenharmony_ci
512762306a36Sopenharmony_ci	/* CPUID 0x80000008 */
512862306a36Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD) ||
512962306a36Sopenharmony_ci	    boot_cpu_has(X86_FEATURE_AMD_SSBD))
513062306a36Sopenharmony_ci		kvm_cpu_cap_set(X86_FEATURE_VIRT_SSBD);
513162306a36Sopenharmony_ci
513262306a36Sopenharmony_ci	if (enable_pmu) {
513362306a36Sopenharmony_ci		/*
513462306a36Sopenharmony_ci		 * Enumerate support for PERFCTR_CORE if and only if KVM has
513562306a36Sopenharmony_ci		 * access to enough counters to virtualize "core" support,
513662306a36Sopenharmony_ci		 * otherwise limit vPMU support to the legacy number of counters.
513762306a36Sopenharmony_ci		 */
513862306a36Sopenharmony_ci		if (kvm_pmu_cap.num_counters_gp < AMD64_NUM_COUNTERS_CORE)
513962306a36Sopenharmony_ci			kvm_pmu_cap.num_counters_gp = min(AMD64_NUM_COUNTERS,
514062306a36Sopenharmony_ci							  kvm_pmu_cap.num_counters_gp);
514162306a36Sopenharmony_ci		else
514262306a36Sopenharmony_ci			kvm_cpu_cap_check_and_set(X86_FEATURE_PERFCTR_CORE);
514362306a36Sopenharmony_ci
514462306a36Sopenharmony_ci		if (kvm_pmu_cap.version != 2 ||
514562306a36Sopenharmony_ci		    !kvm_cpu_cap_has(X86_FEATURE_PERFCTR_CORE))
514662306a36Sopenharmony_ci			kvm_cpu_cap_clear(X86_FEATURE_PERFMON_V2);
514762306a36Sopenharmony_ci	}
514862306a36Sopenharmony_ci
514962306a36Sopenharmony_ci	/* CPUID 0x8000001F (SME/SEV features) */
515062306a36Sopenharmony_ci	sev_set_cpu_caps();
515162306a36Sopenharmony_ci}
515262306a36Sopenharmony_ci
515362306a36Sopenharmony_cistatic __init int svm_hardware_setup(void)
515462306a36Sopenharmony_ci{
515562306a36Sopenharmony_ci	int cpu;
515662306a36Sopenharmony_ci	struct page *iopm_pages;
515762306a36Sopenharmony_ci	void *iopm_va;
515862306a36Sopenharmony_ci	int r;
515962306a36Sopenharmony_ci	unsigned int order = get_order(IOPM_SIZE);
516062306a36Sopenharmony_ci
516162306a36Sopenharmony_ci	/*
516262306a36Sopenharmony_ci	 * NX is required for shadow paging and for NPT if the NX huge pages
516362306a36Sopenharmony_ci	 * mitigation is enabled.
516462306a36Sopenharmony_ci	 */
516562306a36Sopenharmony_ci	if (!boot_cpu_has(X86_FEATURE_NX)) {
516662306a36Sopenharmony_ci		pr_err_ratelimited("NX (Execute Disable) not supported\n");
516762306a36Sopenharmony_ci		return -EOPNOTSUPP;
516862306a36Sopenharmony_ci	}
516962306a36Sopenharmony_ci	kvm_enable_efer_bits(EFER_NX);
517062306a36Sopenharmony_ci
517162306a36Sopenharmony_ci	iopm_pages = alloc_pages(GFP_KERNEL, order);
517262306a36Sopenharmony_ci
517362306a36Sopenharmony_ci	if (!iopm_pages)
517462306a36Sopenharmony_ci		return -ENOMEM;
517562306a36Sopenharmony_ci
517662306a36Sopenharmony_ci	iopm_va = page_address(iopm_pages);
517762306a36Sopenharmony_ci	memset(iopm_va, 0xff, PAGE_SIZE * (1 << order));
517862306a36Sopenharmony_ci	iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT;
517962306a36Sopenharmony_ci
518062306a36Sopenharmony_ci	init_msrpm_offsets();
518162306a36Sopenharmony_ci
518262306a36Sopenharmony_ci	kvm_caps.supported_xcr0 &= ~(XFEATURE_MASK_BNDREGS |
518362306a36Sopenharmony_ci				     XFEATURE_MASK_BNDCSR);
518462306a36Sopenharmony_ci
518562306a36Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_FXSR_OPT))
518662306a36Sopenharmony_ci		kvm_enable_efer_bits(EFER_FFXSR);
518762306a36Sopenharmony_ci
518862306a36Sopenharmony_ci	if (tsc_scaling) {
518962306a36Sopenharmony_ci		if (!boot_cpu_has(X86_FEATURE_TSCRATEMSR)) {
519062306a36Sopenharmony_ci			tsc_scaling = false;
519162306a36Sopenharmony_ci		} else {
519262306a36Sopenharmony_ci			pr_info("TSC scaling supported\n");
519362306a36Sopenharmony_ci			kvm_caps.has_tsc_control = true;
519462306a36Sopenharmony_ci		}
519562306a36Sopenharmony_ci	}
519662306a36Sopenharmony_ci	kvm_caps.max_tsc_scaling_ratio = SVM_TSC_RATIO_MAX;
519762306a36Sopenharmony_ci	kvm_caps.tsc_scaling_ratio_frac_bits = 32;
519862306a36Sopenharmony_ci
519962306a36Sopenharmony_ci	tsc_aux_uret_slot = kvm_add_user_return_msr(MSR_TSC_AUX);
520062306a36Sopenharmony_ci
520162306a36Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_AUTOIBRS))
520262306a36Sopenharmony_ci		kvm_enable_efer_bits(EFER_AUTOIBRS);
520362306a36Sopenharmony_ci
520462306a36Sopenharmony_ci	/* Check for pause filtering support */
520562306a36Sopenharmony_ci	if (!boot_cpu_has(X86_FEATURE_PAUSEFILTER)) {
520662306a36Sopenharmony_ci		pause_filter_count = 0;
520762306a36Sopenharmony_ci		pause_filter_thresh = 0;
520862306a36Sopenharmony_ci	} else if (!boot_cpu_has(X86_FEATURE_PFTHRESHOLD)) {
520962306a36Sopenharmony_ci		pause_filter_thresh = 0;
521062306a36Sopenharmony_ci	}
521162306a36Sopenharmony_ci
521262306a36Sopenharmony_ci	if (nested) {
521362306a36Sopenharmony_ci		pr_info("Nested Virtualization enabled\n");
521462306a36Sopenharmony_ci		kvm_enable_efer_bits(EFER_SVME | EFER_LMSLE);
521562306a36Sopenharmony_ci	}
521662306a36Sopenharmony_ci
521762306a36Sopenharmony_ci	/*
521862306a36Sopenharmony_ci	 * KVM's MMU doesn't support using 2-level paging for itself, and thus
521962306a36Sopenharmony_ci	 * NPT isn't supported if the host is using 2-level paging since host
522062306a36Sopenharmony_ci	 * CR4 is unchanged on VMRUN.
522162306a36Sopenharmony_ci	 */
522262306a36Sopenharmony_ci	if (!IS_ENABLED(CONFIG_X86_64) && !IS_ENABLED(CONFIG_X86_PAE))
522362306a36Sopenharmony_ci		npt_enabled = false;
522462306a36Sopenharmony_ci
522562306a36Sopenharmony_ci	if (!boot_cpu_has(X86_FEATURE_NPT))
522662306a36Sopenharmony_ci		npt_enabled = false;
522762306a36Sopenharmony_ci
522862306a36Sopenharmony_ci	/* Force VM NPT level equal to the host's paging level */
522962306a36Sopenharmony_ci	kvm_configure_mmu(npt_enabled, get_npt_level(),
523062306a36Sopenharmony_ci			  get_npt_level(), PG_LEVEL_1G);
523162306a36Sopenharmony_ci	pr_info("Nested Paging %sabled\n", npt_enabled ? "en" : "dis");
523262306a36Sopenharmony_ci
523362306a36Sopenharmony_ci	/* Setup shadow_me_value and shadow_me_mask */
523462306a36Sopenharmony_ci	kvm_mmu_set_me_spte_mask(sme_me_mask, sme_me_mask);
523562306a36Sopenharmony_ci
523662306a36Sopenharmony_ci	svm_adjust_mmio_mask();
523762306a36Sopenharmony_ci
523862306a36Sopenharmony_ci	nrips = nrips && boot_cpu_has(X86_FEATURE_NRIPS);
523962306a36Sopenharmony_ci
524062306a36Sopenharmony_ci	/*
524162306a36Sopenharmony_ci	 * Note, SEV setup consumes npt_enabled and enable_mmio_caching (which
524262306a36Sopenharmony_ci	 * may be modified by svm_adjust_mmio_mask()), as well as nrips.
524362306a36Sopenharmony_ci	 */
524462306a36Sopenharmony_ci	sev_hardware_setup();
524562306a36Sopenharmony_ci
524662306a36Sopenharmony_ci	svm_hv_hardware_setup();
524762306a36Sopenharmony_ci
524862306a36Sopenharmony_ci	for_each_possible_cpu(cpu) {
524962306a36Sopenharmony_ci		r = svm_cpu_init(cpu);
525062306a36Sopenharmony_ci		if (r)
525162306a36Sopenharmony_ci			goto err;
525262306a36Sopenharmony_ci	}
525362306a36Sopenharmony_ci
525462306a36Sopenharmony_ci	enable_apicv = avic = avic && avic_hardware_setup();
525562306a36Sopenharmony_ci
525662306a36Sopenharmony_ci	if (!enable_apicv) {
525762306a36Sopenharmony_ci		svm_x86_ops.vcpu_blocking = NULL;
525862306a36Sopenharmony_ci		svm_x86_ops.vcpu_unblocking = NULL;
525962306a36Sopenharmony_ci		svm_x86_ops.vcpu_get_apicv_inhibit_reasons = NULL;
526062306a36Sopenharmony_ci	} else if (!x2avic_enabled) {
526162306a36Sopenharmony_ci		svm_x86_ops.allow_apicv_in_x2apic_without_x2apic_virtualization = true;
526262306a36Sopenharmony_ci	}
526362306a36Sopenharmony_ci
526462306a36Sopenharmony_ci	if (vls) {
526562306a36Sopenharmony_ci		if (!npt_enabled ||
526662306a36Sopenharmony_ci		    !boot_cpu_has(X86_FEATURE_V_VMSAVE_VMLOAD) ||
526762306a36Sopenharmony_ci		    !IS_ENABLED(CONFIG_X86_64)) {
526862306a36Sopenharmony_ci			vls = false;
526962306a36Sopenharmony_ci		} else {
527062306a36Sopenharmony_ci			pr_info("Virtual VMLOAD VMSAVE supported\n");
527162306a36Sopenharmony_ci		}
527262306a36Sopenharmony_ci	}
527362306a36Sopenharmony_ci
527462306a36Sopenharmony_ci	if (boot_cpu_has(X86_FEATURE_SVME_ADDR_CHK))
527562306a36Sopenharmony_ci		svm_gp_erratum_intercept = false;
527662306a36Sopenharmony_ci
527762306a36Sopenharmony_ci	if (vgif) {
527862306a36Sopenharmony_ci		if (!boot_cpu_has(X86_FEATURE_VGIF))
527962306a36Sopenharmony_ci			vgif = false;
528062306a36Sopenharmony_ci		else
528162306a36Sopenharmony_ci			pr_info("Virtual GIF supported\n");
528262306a36Sopenharmony_ci	}
528362306a36Sopenharmony_ci
528462306a36Sopenharmony_ci	vnmi = vgif && vnmi && boot_cpu_has(X86_FEATURE_VNMI);
528562306a36Sopenharmony_ci	if (vnmi)
528662306a36Sopenharmony_ci		pr_info("Virtual NMI enabled\n");
528762306a36Sopenharmony_ci
528862306a36Sopenharmony_ci	if (!vnmi) {
528962306a36Sopenharmony_ci		svm_x86_ops.is_vnmi_pending = NULL;
529062306a36Sopenharmony_ci		svm_x86_ops.set_vnmi_pending = NULL;
529162306a36Sopenharmony_ci	}
529262306a36Sopenharmony_ci
529362306a36Sopenharmony_ci
529462306a36Sopenharmony_ci	if (lbrv) {
529562306a36Sopenharmony_ci		if (!boot_cpu_has(X86_FEATURE_LBRV))
529662306a36Sopenharmony_ci			lbrv = false;
529762306a36Sopenharmony_ci		else
529862306a36Sopenharmony_ci			pr_info("LBR virtualization supported\n");
529962306a36Sopenharmony_ci	}
530062306a36Sopenharmony_ci
530162306a36Sopenharmony_ci	if (!enable_pmu)
530262306a36Sopenharmony_ci		pr_info("PMU virtualization is disabled\n");
530362306a36Sopenharmony_ci
530462306a36Sopenharmony_ci	svm_set_cpu_caps();
530562306a36Sopenharmony_ci
530662306a36Sopenharmony_ci	/*
530762306a36Sopenharmony_ci	 * It seems that on AMD processors PTE's accessed bit is
530862306a36Sopenharmony_ci	 * being set by the CPU hardware before the NPF vmexit.
530962306a36Sopenharmony_ci	 * This is not expected behaviour and our tests fail because
531062306a36Sopenharmony_ci	 * of it.
531162306a36Sopenharmony_ci	 * A workaround here is to disable support for
531262306a36Sopenharmony_ci	 * GUEST_MAXPHYADDR < HOST_MAXPHYADDR if NPT is enabled.
531362306a36Sopenharmony_ci	 * In this case userspace can know if there is support using
531462306a36Sopenharmony_ci	 * KVM_CAP_SMALLER_MAXPHYADDR extension and decide how to handle
531562306a36Sopenharmony_ci	 * it
531662306a36Sopenharmony_ci	 * If future AMD CPU models change the behaviour described above,
531762306a36Sopenharmony_ci	 * this variable can be changed accordingly
531862306a36Sopenharmony_ci	 */
531962306a36Sopenharmony_ci	allow_smaller_maxphyaddr = !npt_enabled;
532062306a36Sopenharmony_ci
532162306a36Sopenharmony_ci	return 0;
532262306a36Sopenharmony_ci
532362306a36Sopenharmony_cierr:
532462306a36Sopenharmony_ci	svm_hardware_unsetup();
532562306a36Sopenharmony_ci	return r;
532662306a36Sopenharmony_ci}
532762306a36Sopenharmony_ci
532862306a36Sopenharmony_ci
532962306a36Sopenharmony_cistatic struct kvm_x86_init_ops svm_init_ops __initdata = {
533062306a36Sopenharmony_ci	.hardware_setup = svm_hardware_setup,
533162306a36Sopenharmony_ci
533262306a36Sopenharmony_ci	.runtime_ops = &svm_x86_ops,
533362306a36Sopenharmony_ci	.pmu_ops = &amd_pmu_ops,
533462306a36Sopenharmony_ci};
533562306a36Sopenharmony_ci
533662306a36Sopenharmony_cistatic void __svm_exit(void)
533762306a36Sopenharmony_ci{
533862306a36Sopenharmony_ci	kvm_x86_vendor_exit();
533962306a36Sopenharmony_ci
534062306a36Sopenharmony_ci	cpu_emergency_unregister_virt_callback(svm_emergency_disable);
534162306a36Sopenharmony_ci}
534262306a36Sopenharmony_ci
534362306a36Sopenharmony_cistatic int __init svm_init(void)
534462306a36Sopenharmony_ci{
534562306a36Sopenharmony_ci	int r;
534662306a36Sopenharmony_ci
534762306a36Sopenharmony_ci	__unused_size_checks();
534862306a36Sopenharmony_ci
534962306a36Sopenharmony_ci	if (!kvm_is_svm_supported())
535062306a36Sopenharmony_ci		return -EOPNOTSUPP;
535162306a36Sopenharmony_ci
535262306a36Sopenharmony_ci	r = kvm_x86_vendor_init(&svm_init_ops);
535362306a36Sopenharmony_ci	if (r)
535462306a36Sopenharmony_ci		return r;
535562306a36Sopenharmony_ci
535662306a36Sopenharmony_ci	cpu_emergency_register_virt_callback(svm_emergency_disable);
535762306a36Sopenharmony_ci
535862306a36Sopenharmony_ci	/*
535962306a36Sopenharmony_ci	 * Common KVM initialization _must_ come last, after this, /dev/kvm is
536062306a36Sopenharmony_ci	 * exposed to userspace!
536162306a36Sopenharmony_ci	 */
536262306a36Sopenharmony_ci	r = kvm_init(sizeof(struct vcpu_svm), __alignof__(struct vcpu_svm),
536362306a36Sopenharmony_ci		     THIS_MODULE);
536462306a36Sopenharmony_ci	if (r)
536562306a36Sopenharmony_ci		goto err_kvm_init;
536662306a36Sopenharmony_ci
536762306a36Sopenharmony_ci	return 0;
536862306a36Sopenharmony_ci
536962306a36Sopenharmony_cierr_kvm_init:
537062306a36Sopenharmony_ci	__svm_exit();
537162306a36Sopenharmony_ci	return r;
537262306a36Sopenharmony_ci}
537362306a36Sopenharmony_ci
537462306a36Sopenharmony_cistatic void __exit svm_exit(void)
537562306a36Sopenharmony_ci{
537662306a36Sopenharmony_ci	kvm_exit();
537762306a36Sopenharmony_ci	__svm_exit();
537862306a36Sopenharmony_ci}
537962306a36Sopenharmony_ci
538062306a36Sopenharmony_cimodule_init(svm_init)
538162306a36Sopenharmony_cimodule_exit(svm_exit)
5382