Commit 69c49d89 authored by James Morse's avatar James Morse Committed by Zheng Zengkai
Browse files

KVM: arm64: Allow SMCCC_ARCH_WORKAROUND_3 to be discovered and migrated

stable inclusion
from stable-v5.10.105
commit 38c26bdb3cc53f219d6ab75ac1a95436f393c60f
category: bugfix
bugzilla: 186460 https://gitee.com/src-openeuler/kernel/issues/I53MHA
CVE: CVE-2022-23960

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=38c26bdb3cc5



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

commit a5905d6a upstream.

KVM allows the guest to discover whether the ARCH_WORKAROUND SMCCC are
implemented, and to preserve that state during migration through its
firmware register interface.

Add the necessary boiler plate for SMCCC_ARCH_WORKAROUND_3.

Reviewed-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarChen Jiahao <chenjiahao16@huawei.com>
Reviewed-by: default avatarLiao Chang <liaochang1@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 1c3543b5
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -273,6 +273,11 @@ struct kvm_vcpu_events {
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED	3
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED     	(1U << 4)

#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3	KVM_REG_ARM_FW_REG(3)
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL		0
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL		1
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED	2

/* SVE registers */
#define KVM_REG_ARM64_SVE		(0x15 << KVM_REG_ARM_COPROC_SHIFT)

+12 −0
Original line number Diff line number Diff line
@@ -58,6 +58,18 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
				break;
			}
			break;
		case ARM_SMCCC_ARCH_WORKAROUND_3:
			switch (arm64_get_spectre_bhb_state()) {
			case SPECTRE_VULNERABLE:
				break;
			case SPECTRE_MITIGATED:
				val = SMCCC_RET_SUCCESS;
				break;
			case SPECTRE_UNAFFECTED:
				val = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED;
				break;
			}
			break;
		case ARM_SMCCC_HV_PV_TIME_FEATURES:
			val = SMCCC_RET_SUCCESS;
			break;
+17 −1
Original line number Diff line number Diff line
@@ -397,7 +397,7 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)

int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
{
	return 3;		/* PSCI version and two workaround registers */
	return 4;		/* PSCI version and three workaround registers */
}

int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
@@ -411,6 +411,9 @@ int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
	if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2, uindices++))
		return -EFAULT;

	if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3, uindices++))
		return -EFAULT;

	return 0;
}

@@ -450,6 +453,17 @@ static int get_kernel_wa_level(u64 regid)
		case SPECTRE_VULNERABLE:
			return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL;
		}
		break;
	case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
		switch (arm64_get_spectre_bhb_state()) {
		case SPECTRE_VULNERABLE:
			return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL;
		case SPECTRE_MITIGATED:
			return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL;
		case SPECTRE_UNAFFECTED:
			return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED;
		}
		return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL;
	}

	return -EINVAL;
@@ -466,6 +480,7 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
		break;
	case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
	case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2:
	case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
		val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK;
		break;
	default:
@@ -511,6 +526,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
	}

	case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1:
	case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
		if (val & ~KVM_REG_FEATURE_LEVEL_MASK)
			return -EINVAL;