--- /dev/null
+From 85f1506337f0c79a4955edfeee86a18628e3735f Mon Sep 17 00:00:00 2001
+From: Amit Daniel Kachhap <amit.kachhap@arm.com>
+Date: Thu, 3 Nov 2022 13:52:32 +0530
+Subject: arm64: cpufeature: Fix the visibility of compat hwcaps
+
+From: Amit Daniel Kachhap <amit.kachhap@arm.com>
+
+commit 85f1506337f0c79a4955edfeee86a18628e3735f upstream.
+
+Commit 237405ebef58 ("arm64: cpufeature: Force HWCAP to be based on the
+sysreg visible to user-space") forced the hwcaps to use sanitised
+user-space view of the id registers. However, the ID register structures
+used to select few compat cpufeatures (vfp, crc32, ...) are masked and
+hence such hwcaps do not appear in /proc/cpuinfo anymore for PER_LINUX32
+personality.
+
+Add the ID register structures explicitly and set the relevant entry as
+visible. As these ID registers are now of type visible so make them
+available in 64-bit userspace by making necessary changes in register
+emulation logic and documentation.
+
+While at it, update the comment for structure ftr_generic_32bits[] which
+lists the ID register that use it.
+
+Fixes: 237405ebef58 ("arm64: cpufeature: Force HWCAP to be based on the sysreg visible to user-space")
+Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
+Reviewed-by: James Morse <james.morse@arm.com>
+Signed-off-by: Amit Daniel Kachhap <amit.kachhap@arm.com>
+Link: https://lore.kernel.org/r/20221103082232.19189-1-amit.kachhap@arm.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/arm64/cpu-feature-registers.rst | 38 ++++++++++++++++++++++-
+ arch/arm64/kernel/cpufeature.c | 42 ++++++++++++++++++++------
+ 2 files changed, 70 insertions(+), 10 deletions(-)
+
+--- a/Documentation/arm64/cpu-feature-registers.rst
++++ b/Documentation/arm64/cpu-feature-registers.rst
+@@ -92,7 +92,7 @@ operation if the source belongs to the s
+
+ The infrastructure emulates only the following system register space::
+
+- Op0=3, Op1=0, CRn=0, CRm=0,4,5,6,7
++ Op0=3, Op1=0, CRn=0, CRm=0,2,3,4,5,6,7
+
+ (See Table C5-6 'System instruction encodings for non-Debug System
+ register accesses' in ARMv8 ARM DDI 0487A.h, for the list of
+@@ -291,6 +291,42 @@ infrastructure:
+ | RPRES | [7-4] | y |
+ +------------------------------+---------+---------+
+
++ 10) MVFR0_EL1 - AArch32 Media and VFP Feature Register 0
++
++ +------------------------------+---------+---------+
++ | Name | bits | visible |
++ +------------------------------+---------+---------+
++ | FPDP | [11-8] | y |
++ +------------------------------+---------+---------+
++
++ 11) MVFR1_EL1 - AArch32 Media and VFP Feature Register 1
++
++ +------------------------------+---------+---------+
++ | Name | bits | visible |
++ +------------------------------+---------+---------+
++ | SIMDFMAC | [31-28] | y |
++ +------------------------------+---------+---------+
++ | SIMDSP | [19-16] | y |
++ +------------------------------+---------+---------+
++ | SIMDInt | [15-12] | y |
++ +------------------------------+---------+---------+
++ | SIMDLS | [11-8] | y |
++ +------------------------------+---------+---------+
++
++ 12) ID_ISAR5_EL1 - AArch32 Instruction Set Attribute Register 5
++
++ +------------------------------+---------+---------+
++ | Name | bits | visible |
++ +------------------------------+---------+---------+
++ | CRC32 | [19-16] | y |
++ +------------------------------+---------+---------+
++ | SHA2 | [15-12] | y |
++ +------------------------------+---------+---------+
++ | SHA1 | [11-8] | y |
++ +------------------------------+---------+---------+
++ | AES | [7-4] | y |
++ +------------------------------+---------+---------+
++
+
+ Appendix I: Example
+ -------------------
+--- a/arch/arm64/kernel/cpufeature.c
++++ b/arch/arm64/kernel/cpufeature.c
+@@ -399,6 +399,30 @@ static const struct arm64_ftr_bits ftr_i
+ ARM64_FTR_END,
+ };
+
++static const struct arm64_ftr_bits ftr_mvfr0[] = {
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPROUND_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSHVEC_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSQRT_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPDIVIDE_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPTRAP_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPDP_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSP_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_SIMD_SHIFT, 4, 0),
++ ARM64_FTR_END,
++};
++
++static const struct arm64_ftr_bits ftr_mvfr1[] = {
++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDFMAC_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPHP_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDHP_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDSP_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDINT_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDLS_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPDNAN_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPFTZ_SHIFT, 4, 0),
++ ARM64_FTR_END,
++};
++
+ static const struct arm64_ftr_bits ftr_mvfr2[] = {
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR2_FPMISC_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR2_SIMDMISC_SHIFT, 4, 0),
+@@ -424,10 +448,10 @@ static const struct arm64_ftr_bits ftr_i
+
+ static const struct arm64_ftr_bits ftr_id_isar5[] = {
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_RDM_SHIFT, 4, 0),
+- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0),
+- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA2_SHIFT, 4, 0),
+- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA1_SHIFT, 4, 0),
+- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_AES_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA2_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA1_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_AES_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SEVL_SHIFT, 4, 0),
+ ARM64_FTR_END,
+ };
+@@ -534,7 +558,7 @@ static const struct arm64_ftr_bits ftr_z
+ * Common ftr bits for a 32bit register with all hidden, strict
+ * attributes, with 4bit feature fields and a default safe value of
+ * 0. Covers the following 32bit registers:
+- * id_isar[1-4], id_mmfr[1-3], id_pfr1, mvfr[0-1]
++ * id_isar[1-3], id_mmfr[1-3]
+ */
+ static const struct arm64_ftr_bits ftr_generic_32bits[] = {
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0),
+@@ -590,8 +614,8 @@ static const struct __ftr_reg_entry {
+ ARM64_FTR_REG(SYS_ID_ISAR6_EL1, ftr_id_isar6),
+
+ /* Op1 = 0, CRn = 0, CRm = 3 */
+- ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_generic_32bits),
+- ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_generic_32bits),
++ ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_mvfr0),
++ ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_mvfr1),
+ ARM64_FTR_REG(SYS_MVFR2_EL1, ftr_mvfr2),
+ ARM64_FTR_REG(SYS_ID_PFR2_EL1, ftr_id_pfr2),
+ ARM64_FTR_REG(SYS_ID_DFR1_EL1, ftr_id_dfr1),
+@@ -2814,7 +2838,7 @@ static void __maybe_unused cpu_enable_cn
+
+ /*
+ * We emulate only the following system register space.
+- * Op0 = 0x3, CRn = 0x0, Op1 = 0x0, CRm = [0, 4 - 7]
++ * Op0 = 0x3, CRn = 0x0, Op1 = 0x0, CRm = [0, 2 - 7]
+ * See Table C5-6 System instruction encodings for System register accesses,
+ * ARMv8 ARM(ARM DDI 0487A.f) for more details.
+ */
+@@ -2824,7 +2848,7 @@ static inline bool __attribute_const__ i
+ sys_reg_CRn(id) == 0x0 &&
+ sys_reg_Op1(id) == 0x0 &&
+ (sys_reg_CRm(id) == 0 ||
+- ((sys_reg_CRm(id) >= 4) && (sys_reg_CRm(id) <= 7))));
++ ((sys_reg_CRm(id) >= 2) && (sys_reg_CRm(id) <= 7))));
+ }
+
+ /*