[PATCH OLK-6.6 0/2] Fix TLBI broadcast optimization loss and incorrect dvmbm handling
Fix 1 In the TLBI broadcast-optimization feature, the SYS_LSUDVM_CTRL_EL2 register controls whether the feature is enabled. When LPI low-power mode is enabled, this register is cleared as the pCPU powers down into LPI mode, causing the TLBI broadcast optimization to stop working. The fix saves and restores this control register in the callbacks for entering and exiting LPI mode. Fix 2 The current TLBI broadcast-optimization logic only supports normal VMs. If the feature is enabled globally, VMs that are not yet adapted for it, such as CCA will use an incorrect TLBI broadcast bitmap, which can cause a panic in CCA VMs. The fix moves the actual enable/disable of the dvmbm functionality into the vcpu load and vcpu put functions. Tian Zheng (2): KVM: arm64: Fix TLBI optimization broken in LPI mode KVM: arm64: Fix CCA guest panic when dvmbm is enabled arch/arm64/kvm/arm.c | 4 +++ arch/arm64/kvm/hisilicon/hisi_virt.c | 37 +++++++++++++++++++--------- arch/arm64/kvm/hisilicon/hisi_virt.h | 4 +++ 3 files changed, 33 insertions(+), 12 deletions(-) -- 2.33.0
virt inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/8610 -------------------------------------------------------------------- When LPI is enabled, a CPU may enter power-down mode. During this transition, dvmbm ctrl register is reset to 0 after the cpu was down, which leads to functional breakdown. At this mode, the kernel invokes a notifier during CPU suspend, and the CPU enters the CPU_PM_ENTER state. KVM has registered a handler for this state. To prevent the loss of configuration, the DVM broadcast management control register (SYS_LSUDVM_CTRL_EL2) must be saved on CPU suspend and restored on CPU resume. Fixes: e85b97c7e2b4 ("KVM: arm64: Probe and configure DVMBM capability on HiSi CPUs") Signed-off-by: Tian Zheng <zhengtian10@huawei.com> Reviewed-by: Yanan Wang <wangyanan55@huawei.com> --- arch/arm64/kvm/arm.c | 4 ++++ arch/arm64/kvm/hisilicon/hisi_virt.c | 19 +++++++++++++++++++ arch/arm64/kvm/hisilicon/hisi_virt.h | 4 ++++ 3 files changed, 27 insertions(+) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index e59152ad5c4a..f349f22b9dec 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -2424,6 +2424,8 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self, */ switch (cmd) { case CPU_PM_ENTER: + kvm_save_dvmbm_ctrl_el2(); + if (__this_cpu_read(kvm_hyp_initialized)) /* * don't update kvm_hyp_initialized here @@ -2439,6 +2441,8 @@ static int hyp_init_cpu_pm_notifier(struct notifier_block *self, /* The hyp was enabled before suspend. */ cpu_hyp_reinit(); + kvm_restore_dvmbm_ctrl_el2(); + return NOTIFY_OK; default: diff --git a/arch/arm64/kvm/hisilicon/hisi_virt.c b/arch/arm64/kvm/hisilicon/hisi_virt.c index 5731d337b228..d5a8a6d66dbc 100644 --- a/arch/arm64/kvm/hisilicon/hisi_virt.c +++ b/arch/arm64/kvm/hisilicon/hisi_virt.c @@ -13,6 +13,7 @@ static enum hisi_cpu_type cpu_type = UNKNOWN_HI_TYPE; static bool dvmbm_enabled; +static DEFINE_PER_CPU(u64, kvm_dvmbm_ctrl_el2_val); #ifdef CONFIG_ARM64_HISI_IPIV static bool ipiv_enabled; @@ -162,6 +163,24 @@ static void hardware_disable_dvmbm(void *data) write_sysreg_s(val, SYS_LSUDVM_CTRL_EL2); } +void kvm_save_dvmbm_ctrl_el2(void) +{ + if (!kvm_dvmbm_support) + return; + + __this_cpu_write(kvm_dvmbm_ctrl_el2_val, + read_sysreg_s(SYS_LSUDVM_CTRL_EL2)); +} + +void kvm_restore_dvmbm_ctrl_el2(void) +{ + if (!kvm_dvmbm_support) + return; + + write_sysreg_s(__this_cpu_read(kvm_dvmbm_ctrl_el2_val), + SYS_LSUDVM_CTRL_EL2); +} + #ifdef CONFIG_ARM64_HISI_IPIV static int __init early_ipiv_enable(char *buf) { diff --git a/arch/arm64/kvm/hisilicon/hisi_virt.h b/arch/arm64/kvm/hisilicon/hisi_virt.h index 180618e42cbc..e0fca8236197 100644 --- a/arch/arm64/kvm/hisilicon/hisi_virt.h +++ b/arch/arm64/kvm/hisilicon/hisi_virt.h @@ -94,6 +94,8 @@ enum hisi_cpu_type { void probe_hisi_cpu_type(void); bool hisi_ncsnp_supported(void); bool hisi_dvmbm_supported(void); +void kvm_save_dvmbm_ctrl_el2(void); +void kvm_restore_dvmbm_ctrl_el2(void); #ifdef CONFIG_ARM64_HISI_IPIV bool hisi_ipiv_supported(void); bool hisi_ipiv_supported_per_vm(struct kvm *kvm); @@ -119,6 +121,8 @@ static inline bool hisi_dvmbm_supported(void) { return false; } +static inline void kvm_save_dvmbm_ctrl_el2(void) {} +static inline void kvm_restore_dvmbm_ctrl_el2(void) {} #ifdef CONFIG_ARM64_HISI_IPIV static inline bool hisi_ipiv_supported(void) { -- 2.33.0
virt inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/8610 -------------------------------------------------------------------- Enabling TLBI optimization via kvm-arm.dvmbm_enabled=1 permanently sets the LSUDVM_CTRL_EL2 control bit. Since CCA doesn't yet support this feature, CCA VMs will read an erroneous bitmap from SYS_LSUDVMBM_EL2 when performing TLB flushes, causing a panic. To avoid this issue, this patch dynamically sets/clears the bit in vcpu_load/vcpu_put, limiting the optimization to normal VMs only. Fixes: e85b97c7e2b4 ("KVM: arm64: Probe and configure DVMBM capability on HiSi CPUs") Signed-off-by: Tian Zheng <zhengtian10@huawei.com> Reviewed-by: Yanan Wang <wangyanan55@huawei.com> --- arch/arm64/kvm/hisilicon/hisi_virt.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/arch/arm64/kvm/hisilicon/hisi_virt.c b/arch/arm64/kvm/hisilicon/hisi_virt.c index d5a8a6d66dbc..1bd71044c2e7 100644 --- a/arch/arm64/kvm/hisilicon/hisi_virt.c +++ b/arch/arm64/kvm/hisilicon/hisi_virt.c @@ -145,7 +145,7 @@ static int __init early_dvmbm_enable(char *buf) } early_param("kvm-arm.dvmbm_enabled", early_dvmbm_enable); -static void hardware_enable_dvmbm(void *data) +static void hardware_enable_dvmbm(void) { u64 val; @@ -264,18 +264,10 @@ bool hisi_dvmbm_supported(void) if (!(read_sysreg(aidr_el1) & AIDR_EL1_DVMBM_MASK)) return false; - /* User provided kernel command-line parameter */ - if (!dvmbm_enabled) { - on_each_cpu(hardware_disable_dvmbm, NULL, 1); - return false; - } + /* reset */ + on_each_cpu(hardware_disable_dvmbm, NULL, 1); - /* - * Enable TLBI Broadcast optimization by setting - * LSUDVM_CTRL_EL2's bit[0]. - */ - on_each_cpu(hardware_enable_dvmbm, NULL, 1); - return true; + return dvmbm_enabled; } int kvm_sched_affinity_vcpu_init(struct kvm_vcpu *vcpu) @@ -574,6 +566,7 @@ void kvm_tlbi_dvmbm_vcpu_load(struct kvm_vcpu *vcpu) if (!kvm_dvmbm_support) return; + hardware_enable_dvmbm(); cpumask_copy(vcpu->arch.sched_cpus, current->cpus_ptr); if (likely(cpumask_equal(vcpu->arch.sched_cpus, @@ -624,6 +617,7 @@ void kvm_tlbi_dvmbm_vcpu_put(struct kvm_vcpu *vcpu) return; cpumask_copy(vcpu->arch.pre_sched_cpus, vcpu->arch.sched_cpus); + hardware_disable_dvmbm(NULL); } void kvm_get_pg_cfg(void) -- 2.33.0
participants (1)
-
Tian Zheng