Commit 540f76d1 authored by Will Deacon's avatar Will Deacon
Browse files

arm64: cpufeature: Add CPU capability for AArch32 EL1 support



Although we emit a "SANITY CHECK" warning and taint the kernel if we
detect a CPU mismatch for AArch32 support at EL1, we still online the
CPU with disastrous consequences for any running 32-bit VMs.

Introduce a capability for AArch32 support at EL1 so that late onlining
of incompatible CPUs is forbidden.

Tested-by: default avatarSai Prakash Ranjan <saiprakash.ranjan@codeaurora.org>
Reviewed-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Acked-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20200421142922.18950-4-will@kernel.org


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent 0113340e
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -61,7 +61,8 @@
#define ARM64_HAS_AMU_EXTN			51
#define ARM64_HAS_ADDRESS_AUTH			52
#define ARM64_HAS_GENERIC_AUTH			53
#define ARM64_HAS_32BIT_EL1			54

#define ARM64_NCAPS				54
#define ARM64_NCAPS				55

#endif /* __ASM_CPUCAPS_H */
+1 −0
Original line number Diff line number Diff line
@@ -655,6 +655,7 @@
#define ID_AA64PFR0_ASIMD_NI		0xf
#define ID_AA64PFR0_ASIMD_SUPPORTED	0x0
#define ID_AA64PFR0_EL1_64BIT_ONLY	0x1
#define ID_AA64PFR0_EL1_32BIT_64BIT	0x2
#define ID_AA64PFR0_EL0_64BIT_ONLY	0x1
#define ID_AA64PFR0_EL0_32BIT_64BIT	0x2

+12 −0
Original line number Diff line number Diff line
@@ -1535,6 +1535,18 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
		.field_pos = ID_AA64PFR0_EL0_SHIFT,
		.min_field_value = ID_AA64PFR0_EL0_32BIT_64BIT,
	},
#ifdef CONFIG_KVM
	{
		.desc = "32-bit EL1 Support",
		.capability = ARM64_HAS_32BIT_EL1,
		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
		.matches = has_cpuid_feature,
		.sys_reg = SYS_ID_AA64PFR0_EL1,
		.sign = FTR_UNSIGNED,
		.field_pos = ID_AA64PFR0_EL1_SHIFT,
		.min_field_value = ID_AA64PFR0_EL1_32BIT_64BIT,
	},
#endif
	{
		.desc = "Kernel page table isolation (KPTI)",
		.capability = ARM64_UNMAP_KERNEL_AT_EL0,
+2 −10
Original line number Diff line number Diff line
@@ -46,14 +46,6 @@ static const struct kvm_regs default_regs_reset32 = {
			PSR_AA32_I_BIT | PSR_AA32_F_BIT),
};

static bool cpu_has_32bit_el1(void)
{
	u64 pfr0;

	pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
	return !!(pfr0 & 0x20);
}

/**
 * kvm_arch_vm_ioctl_check_extension
 *
@@ -66,7 +58,7 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)

	switch (ext) {
	case KVM_CAP_ARM_EL1_32BIT:
		r = cpu_has_32bit_el1();
		r = cpus_have_const_cap(ARM64_HAS_32BIT_EL1);
		break;
	case KVM_CAP_GUEST_DEBUG_HW_BPS:
		r = get_num_brps();
@@ -288,7 +280,7 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
	switch (vcpu->arch.target) {
	default:
		if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
			if (!cpu_has_32bit_el1())
			if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1))
				goto out;
			cpu_reset = &default_regs_reset32;
		} else {