Commit f69080d2 authored by Zenghui Yu's avatar Zenghui Yu Committed by zhaolichang
Browse files

KVM: arm64: Allow vcpus running without HCR_EL2.FB

virt inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IBU2Y1
CVE: NA

--------------------------------

As per ARM DDI 0487G.a, seting the HCR_EL2.FB (Force broadcast) bit causes
a given set of TLBI and IC instructions to be broadcast within the Inner
Shareable domain when executed from EL1 (if HCR_EL2.TGE is 0).

And people complain that this leads to bad performance when running guests
on Kunpeng920 which has 128 physical CPUs in the IS domain, especially in
the case where vcpus are pinned to physical CPUs, where we indeed don't
need broadcast invalidations.

Introduce a new cmdline parameter "kvm-arm.hcr_nofb" for users and setting
it at boot time allows all vcpus running without HCR_EL2.FB. Note that we
now have to nuke the whole vcpu context in the general case (when vcpu is
loaded on to the new physical CPU).

Link: https://gitee.com/openeuler/kernel/commit/823f53c21805



Co-developed-by: default avatarNianyao Tang <tangnianyao@huawei.com>
Signed-off-by: default avatarNianyao Tang <tangnianyao@huawei.com>
Signed-off-by: default avatarZenghui Yu <yuzenghui@huawei.com>
Reviewed-by: default avatarCheng Jian <cj.chengjian@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: default avatarzhaolichang <zhaolichang@huawei.com>
parent 056f91a0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -776,6 +776,7 @@ CONFIG_KVM_ARM_MULTI_LPI_TRANSLATE_CACHE=y
CONFIG_ARCH_VCPU_STAT=y
CONFIG_VIRT_VTIMER_IRQ_BYPASS=y
CONFIG_CPU_MITIGATIONS=y
# CONFIG_ARM64_KVM_HCR_NOFB is not set

#
# Hardware Assisted OS Compartmentalization(HAOC)
+9 −0
Original line number Diff line number Diff line
@@ -66,6 +66,10 @@ static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
}
#endif

#ifdef CONFIG_ARM64_KVM_HCR_NOFB
extern bool kvm_hcr_nofb;
#endif

static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
{
	vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS;
@@ -101,6 +105,11 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)

	if (kvm_has_mte(vcpu->kvm))
		vcpu->arch.hcr_el2 |= HCR_ATA;

#ifdef CONFIG_ARM64_KVM_HCR_NOFB
	if (unlikely(kvm_hcr_nofb))
		vcpu->arch.hcr_el2 &= ~HCR_FB;
#endif
}

static inline unsigned long *vcpu_hcr(struct kvm_vcpu *vcpu)
+15 −0
Original line number Diff line number Diff line
@@ -99,4 +99,19 @@ config VIRT_VTIMER_IRQ_BYPASS
	depends on KVM && ARM64 && ARCH_HISI && HISILICON_IRQ_MBIGEN
	default n

config ARM64_KVM_HCR_NOFB
	bool "Disable HCR_EL2.FB on kvm(EXPERIMENTAL)"
	depends on ARM64
	default n
	help
	  Add new boot parameter 'kvm-arm.hcr_nofb' to allow all vcpus running
	  without HCR_EL2.FB.

	  NOTE(Important)
	  This feature is used for learning and debugging only. Please don't
	  enable it on commercial products.
	  If you know exactly what the impact of the feature is, you can
	  configure it as you do.

	  If unsure, say N.
endif # VIRTUALIZATION
+29 −0
Original line number Diff line number Diff line
@@ -67,6 +67,16 @@ bool kvm_ncsnp_support;
/* Capability of DVMBM */
bool kvm_dvmbm_support;

#ifdef CONFIG_ARM64_KVM_HCR_NOFB
bool kvm_hcr_nofb;

static int __init early_hcr_nofb_cfg(char *buf)
{
	return strtobool(buf, &kvm_hcr_nofb);
}
early_param("kvm-arm.hcr_nofb", early_hcr_nofb_cfg);
#endif

static DEFINE_PER_CPU(unsigned char, kvm_hyp_initialized);
DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use);

@@ -563,6 +573,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
	struct kvm_s2_mmu *mmu;
	int *last_ran;
#ifdef CONFIG_ARM64_KVM_HCR_NOFB
	bool flushed = false;
#endif

	mmu = vcpu->arch.hw_mmu;
	last_ran = this_cpu_ptr(mmu->last_vcpu_ran);
@@ -579,8 +592,21 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
	if (*last_ran != vcpu->vcpu_id) {
		kvm_call_hyp(__kvm_flush_cpu_context, mmu);
		*last_ran = vcpu->vcpu_id;
#ifdef CONFIG_ARM64_KVM_HCR_NOFB
		flushed = true;
#endif
	}

#ifdef CONFIG_ARM64_KVM_HCR_NOFB
	/*
	 * If FB (Force broadcast) is cleared, we have to nuke the
	 * vcpu context as well in case it is loaded on to the new
	 * physical CPU.
	 */
	if (unlikely(kvm_hcr_nofb) && vcpu->pre_pcpu != cpu && !flushed)
		kvm_call_hyp(__kvm_flush_cpu_context, mmu);
#endif

	vcpu->cpu = cpu;

#ifdef CONFIG_HISI_VIRTCCA_HOST
@@ -646,6 +672,9 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
	kvm_arm_vmid_clear_active();

	vcpu_clear_on_unsupported_cpu(vcpu);
#ifdef CONFIG_ARM64_KVM_HCR_NOFB
	vcpu->pre_pcpu = vcpu->cpu;
#endif
	vcpu->cpu = -1;

	kvm_tlbi_dvmbm_vcpu_put(vcpu);
+3 −0
Original line number Diff line number Diff line
@@ -336,6 +336,9 @@ struct kvm_vcpu {
	u64 requests;
	unsigned long guest_debug;

#ifdef CONFIG_ARM64_KVM_HCR_NOFB
	int pre_pcpu;
#endif
	struct mutex mutex;
	struct kvm_run *run;

Loading