diff options
Diffstat (limited to 'arch/x86/kvm/svm/svm.c')
| -rw-r--r-- | arch/x86/kvm/svm/svm.c | 90 | 
1 files changed, 62 insertions, 28 deletions
| diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 5630c241d5f6..46bcc706f257 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -192,6 +192,10 @@ module_param(vgif, int, 0444);  static int lbrv = true;  module_param(lbrv, int, 0444); +/* enable/disable PMU virtualization */ +bool pmu = true; +module_param(pmu, bool, 0444); +  static int tsc_scaling = true;  module_param(tsc_scaling, int, 0444); @@ -265,7 +269,7 @@ u32 svm_msrpm_offset(u32 msr)  #define MAX_INST_SIZE 15 -static int get_max_npt_level(void) +static int get_npt_level(void)  {  #ifdef CONFIG_X86_64  	return pgtable_l5_enabled() ? PT64_ROOT_5LEVEL : PT64_ROOT_4LEVEL; @@ -585,12 +589,10 @@ static int svm_cpu_init(int cpu)  	if (!sd)  		return ret;  	sd->cpu = cpu; -	sd->save_area = alloc_page(GFP_KERNEL); +	sd->save_area = alloc_page(GFP_KERNEL | __GFP_ZERO);  	if (!sd->save_area)  		goto free_cpu_data; -	clear_page(page_address(sd->save_area)); -  	ret = sev_cpu_init(sd);  	if (ret)  		goto free_save_area; @@ -954,6 +956,10 @@ static __init void svm_set_cpu_caps(void)  	    boot_cpu_has(X86_FEATURE_AMD_SSBD))  		kvm_cpu_cap_set(X86_FEATURE_VIRT_SSBD); +	/* AMD PMU PERFCTR_CORE CPUID */ +	if (pmu && boot_cpu_has(X86_FEATURE_PERFCTR_CORE)) +		kvm_cpu_cap_set(X86_FEATURE_PERFCTR_CORE); +  	/* CPUID 0x8000001F (SME/SEV features) */  	sev_set_cpu_caps();  } @@ -1029,9 +1035,9 @@ static __init int svm_hardware_setup(void)  	if (!boot_cpu_has(X86_FEATURE_NPT))  		npt_enabled = false; -	/* Force VM NPT level equal to the host's max NPT level */ -	kvm_configure_mmu(npt_enabled, get_max_npt_level(), -			  get_max_npt_level(), PG_LEVEL_1G); +	/* Force VM NPT level equal to the host's paging level */ +	kvm_configure_mmu(npt_enabled, get_npt_level(), +			  get_npt_level(), PG_LEVEL_1G);  	pr_info("kvm: Nested Paging %sabled\n", npt_enabled ? "en" : "dis");  	/* Note, SEV setup consumes npt_enabled. */ @@ -1087,6 +1093,9 @@ static __init int svm_hardware_setup(void)  			pr_info("LBR virtualization supported\n");  	} +	if (!pmu) +		pr_info("PMU virtualization is disabled\n"); +  	svm_set_cpu_caps();  	/* @@ -1585,12 +1594,27 @@ static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)  	to_svm(vcpu)->vmcb->save.rflags = rflags;  } +static bool svm_get_if_flag(struct kvm_vcpu *vcpu) +{ +	struct vmcb *vmcb = to_svm(vcpu)->vmcb; + +	return sev_es_guest(vcpu->kvm) +		? vmcb->control.int_state & SVM_GUEST_INTERRUPT_MASK +		: kvm_get_rflags(vcpu) & X86_EFLAGS_IF; +} +  static void svm_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)  { +	kvm_register_mark_available(vcpu, reg); +  	switch (reg) {  	case VCPU_EXREG_PDPTR: -		BUG_ON(!npt_enabled); -		load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu)); +		/* +		 * When !npt_enabled, mmu->pdptrs[] is already available since +		 * it is always updated per SDM when moving to CRs. +		 */ +		if (npt_enabled) +			load_pdptrs(vcpu, kvm_read_cr3(vcpu));  		break;  	default:  		KVM_BUG_ON(1, vcpu->kvm); @@ -1777,6 +1801,24 @@ static void svm_set_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)  	vmcb_mark_dirty(svm->vmcb, VMCB_DT);  } +static void svm_post_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) +{ +	struct vcpu_svm *svm = to_svm(vcpu); + +	/* +	 * For guests that don't set guest_state_protected, the cr3 update is +	 * handled via kvm_mmu_load() while entering the guest. For guests +	 * that do (SEV-ES/SEV-SNP), the cr3 update needs to be written to +	 * VMCB save area now, since the save area will become the initial +	 * contents of the VMSA, and future VMCB save area updates won't be +	 * seen. +	 */ +	if (sev_es_guest(vcpu->kvm)) { +		svm->vmcb->save.cr3 = cr3; +		vmcb_mark_dirty(svm->vmcb, VMCB_CR); +	} +} +  void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)  {  	struct vcpu_svm *svm = to_svm(vcpu); @@ -2508,7 +2550,7 @@ static bool check_selective_cr0_intercepted(struct kvm_vcpu *vcpu,  	bool ret = false;  	if (!is_guest_mode(vcpu) || -	    (!(vmcb_is_intercept(&svm->nested.ctl, INTERCEPT_SELECTIVE_CR0)))) +	    (!(vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_SELECTIVE_CR0))))  		return false;  	cr0 &= ~SVM_CR0_SELECTIVE_MASK; @@ -3568,14 +3610,7 @@ bool svm_interrupt_blocked(struct kvm_vcpu *vcpu)  	if (!gif_set(svm))  		return true; -	if (sev_es_guest(vcpu->kvm)) { -		/* -		 * SEV-ES guests to not expose RFLAGS. Use the VMCB interrupt mask -		 * bit to determine the state of the IF flag. -		 */ -		if (!(vmcb->control.int_state & SVM_GUEST_INTERRUPT_MASK)) -			return true; -	} else if (is_guest_mode(vcpu)) { +	if (is_guest_mode(vcpu)) {  		/* As long as interrupts are being delivered...  */  		if ((svm->nested.ctl.int_ctl & V_INTR_MASKING_MASK)  		    ? !(svm->vmcb01.ptr->save.rflags & X86_EFLAGS_IF) @@ -3586,7 +3621,7 @@ bool svm_interrupt_blocked(struct kvm_vcpu *vcpu)  		if (nested_exit_on_intr(svm))  			return false;  	} else { -		if (!(kvm_get_rflags(vcpu) & X86_EFLAGS_IF)) +		if (!svm_get_if_flag(vcpu))  			return true;  	} @@ -3929,9 +3964,10 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)  		vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;  		vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;  	} +	vcpu->arch.regs_dirty = 0;  	if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI)) -		kvm_before_interrupt(vcpu); +		kvm_before_interrupt(vcpu, KVM_HANDLING_NMI);  	kvm_load_host_xsave_state(vcpu);  	stgi(); @@ -3963,8 +3999,7 @@ static __no_kcsan fastpath_t svm_vcpu_run(struct kvm_vcpu *vcpu)  		vcpu->arch.apf.host_apf_flags =  			kvm_read_and_reset_apf_flags(); -	if (npt_enabled) -		kvm_register_clear_available(vcpu, VCPU_EXREG_PDPTR); +	vcpu->arch.regs_avail &= ~SVM_REGS_LAZY_LOAD_SET;  	/*  	 * We need to handle MC intercepts here before the vcpu has a chance to @@ -3994,9 +4029,6 @@ static void svm_load_mmu_pgd(struct kvm_vcpu *vcpu, hpa_t root_hpa,  		hv_track_root_tdp(vcpu, root_hpa); -		/* Loading L2's CR3 is handled by enter_svm_guest_mode.  */ -		if (!test_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail)) -			return;  		cr3 = vcpu->arch.cr3;  	} else if (vcpu->arch.mmu->shadow_root_level >= PT64_ROOT_4LEVEL) {  		cr3 = __sme_set(root_hpa) | kvm_get_active_pcid(vcpu); @@ -4215,7 +4247,7 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,  		    info->intercept == x86_intercept_clts)  			break; -		if (!(vmcb_is_intercept(&svm->nested.ctl, +		if (!(vmcb12_is_intercept(&svm->nested.ctl,  					INTERCEPT_SELECTIVE_CR0)))  			break; @@ -4434,7 +4466,8 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const char *smstate)  	 */  	vmcb12 = map.hva; -	nested_load_control_from_vmcb12(svm, &vmcb12->control); +	nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); +	nested_copy_vmcb_save_to_cache(svm, &vmcb12->save);  	ret = enter_svm_guest_mode(vcpu, vmcb12_gpa, vmcb12, false);  unmap_save: @@ -4609,6 +4642,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {  	.get_cpl = svm_get_cpl,  	.get_cs_db_l_bits = kvm_get_cs_db_l_bits,  	.set_cr0 = svm_set_cr0, +	.post_set_cr3 = svm_post_set_cr3,  	.is_valid_cr4 = svm_is_valid_cr4,  	.set_cr4 = svm_set_cr4,  	.set_efer = svm_set_efer, @@ -4621,6 +4655,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {  	.cache_reg = svm_cache_reg,  	.get_rflags = svm_get_rflags,  	.set_rflags = svm_set_rflags, +	.get_if_flag = svm_get_if_flag,  	.tlb_flush_all = svm_flush_tlb,  	.tlb_flush_current = svm_flush_tlb, @@ -4651,7 +4686,6 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {  	.load_eoi_exitmap = svm_load_eoi_exitmap,  	.hwapic_irr_update = svm_hwapic_irr_update,  	.hwapic_isr_update = svm_hwapic_isr_update, -	.sync_pir_to_irr = kvm_lapic_find_highest_irr,  	.apicv_post_state_restore = avic_post_state_restore,  	.set_tss_addr = svm_set_tss_addr, |