This is a backport of 2a3f93459d689d990b3ecfbe782fec89b97d3279 ("arm64: KVM: Sanitize PSTATE.M when being set from userspace") to 4.4-stable.
It requires a backport of 042446a31e3803d81c7e618dd80928dc3dce70c5 ("arm64: cpufeature: Track 32bit EL0 support") as a dependency.
Marc Zyngier (1): arm64: KVM: Sanitize PSTATE.M when being set from userspace
Suzuki K Poulose (1): arm64: cpufeature: Track 32bit EL0 support
arch/arm64/include/asm/cpufeature.h | 8 +++++++- arch/arm64/include/asm/kvm_emulate.h | 5 +++++ arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/kernel/cpufeature.c | 8 ++++++++ arch/arm64/kvm/guest.c | 10 +++++++++- 5 files changed, 30 insertions(+), 2 deletions(-)
From: Suzuki K Poulose suzuki.poulose@arm.com
commit 042446a31e3803d81c7e618dd80928dc3dce70c5 upstream.
Add cpu_hwcap bit for keeping track of the support for 32bit EL0.
Tested-by: Yury Norov ynorov@caviumnetworks.com Signed-off-by: Suzuki K Poulose suzuki.poulose@arm.com Signed-off-by: Will Deacon will.deacon@arm.com Signed-off-by: Marc Zyngier marc.zyngier@arm.com --- arch/arm64/include/asm/cpufeature.h | 8 +++++++- arch/arm64/include/asm/sysreg.h | 1 + arch/arm64/kernel/cpufeature.c | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 8884b5d5f48c..ad83c245781c 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -31,8 +31,9 @@ #define ARM64_WORKAROUND_CAVIUM_23154 6 #define ARM64_WORKAROUND_834220 7 #define ARM64_WORKAROUND_CAVIUM_27456 8 +#define ARM64_HAS_32BIT_EL0 9
-#define ARM64_NCAPS 9 +#define ARM64_NCAPS 10
#ifndef __ASSEMBLY__
@@ -180,6 +181,11 @@ static inline bool cpu_supports_mixed_endian_el0(void) return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1)); }
+static inline bool system_supports_32bit_el0(void) +{ + return cpus_have_cap(ARM64_HAS_32BIT_EL0); +} + static inline bool system_supports_mixed_endian_el0(void) { return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1)); diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index d48ab5b41f52..50150320f80d 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -109,6 +109,7 @@ #define ID_AA64PFR0_ASIMD_SUPPORTED 0x0 #define ID_AA64PFR0_EL1_64BIT_ONLY 0x1 #define ID_AA64PFR0_EL0_64BIT_ONLY 0x1 +#define ID_AA64PFR0_EL0_32BIT_64BIT 0x2
/* id_aa64mmfr0 */ #define ID_AA64MMFR0_TGRAN4_SHIFT 28 diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 2735bf814592..c1eddc07d996 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -653,6 +653,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .min_field_value = 2, }, #endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */ + { + .desc = "32-bit EL0 Support", + .capability = ARM64_HAS_32BIT_EL0, + .matches = has_cpuid_feature, + .sys_reg = SYS_ID_AA64PFR0_EL1, + .field_pos = ID_AA64PFR0_EL0_SHIFT, + .min_field_value = ID_AA64PFR0_EL0_32BIT_64BIT, + }, {}, };
commit 2a3f93459d689d990b3ecfbe782fec89b97d3279 upstream.
Not all execution modes are valid for a guest, and some of them depend on what the HW actually supports. Let's verify that what userspace provides is compatible with both the VM settings and the HW capabilities.
Cc: stable@vger.kernel.org Fixes: 0d854a60b1d7 ("arm64: KVM: enable initialization of a 32bit vcpu") Reviewed-by: Christoffer Dall christoffer.dall@arm.com Reviewed-by: Mark Rutland mark.rutland@arm.com Reviewed-by: Dave Martin Dave.Martin@arm.com Signed-off-by: Marc Zyngier marc.zyngier@arm.com Signed-off-by: Will Deacon will.deacon@arm.com Signed-off-by: Marc Zyngier marc.zyngier@arm.com --- arch/arm64/include/asm/kvm_emulate.h | 5 +++++ arch/arm64/kvm/guest.c | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 25a40213bd9b..0729a2f94482 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -41,6 +41,11 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu); void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr); void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
+static inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu) +{ + return !(vcpu->arch.hcr_el2 & HCR_RW); +} + static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) { vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 83aa598ed81e..79705fde8cc8 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -143,17 +143,25 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) }
if (off == KVM_REG_ARM_CORE_REG(regs.pstate)) { - u32 mode = (*(u32 *)valp) & COMPAT_PSR_MODE_MASK; + u64 mode = (*(u64 *)valp) & COMPAT_PSR_MODE_MASK; switch (mode) { case COMPAT_PSR_MODE_USR: + if (!system_supports_32bit_el0()) + return -EINVAL; + break; case COMPAT_PSR_MODE_FIQ: case COMPAT_PSR_MODE_IRQ: case COMPAT_PSR_MODE_SVC: case COMPAT_PSR_MODE_ABT: case COMPAT_PSR_MODE_UND: + if (!vcpu_el1_is_32bit(vcpu)) + return -EINVAL; + break; case PSR_MODE_EL0t: case PSR_MODE_EL1t: case PSR_MODE_EL1h: + if (vcpu_el1_is_32bit(vcpu)) + return -EINVAL; break; default: err = -EINVAL;
On Tue, Oct 02, 2018 at 04:04:03PM +0100, Marc Zyngier wrote:
This is a backport of 2a3f93459d689d990b3ecfbe782fec89b97d3279 ("arm64: KVM: Sanitize PSTATE.M when being set from userspace") to 4.4-stable.
It requires a backport of 042446a31e3803d81c7e618dd80928dc3dce70c5 ("arm64: cpufeature: Track 32bit EL0 support") as a dependency.
All now queued up, thanks.
greg k-h
linux-stable-mirror@lists.linaro.org