|
@@ -27,6 +27,7 @@
|
|
|
#include <asm/cpu.h>
|
|
#include <asm/cpu.h>
|
|
|
#include <asm/cpufeature.h>
|
|
#include <asm/cpufeature.h>
|
|
|
#include <asm/cpu_ops.h>
|
|
#include <asm/cpu_ops.h>
|
|
|
|
|
+#include <asm/fpsimd.h>
|
|
|
#include <asm/mmu_context.h>
|
|
#include <asm/mmu_context.h>
|
|
|
#include <asm/processor.h>
|
|
#include <asm/processor.h>
|
|
|
#include <asm/sysreg.h>
|
|
#include <asm/sysreg.h>
|
|
@@ -51,6 +52,21 @@ unsigned int compat_elf_hwcap2 __read_mostly;
|
|
|
DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
|
|
DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
|
|
|
EXPORT_SYMBOL(cpu_hwcaps);
|
|
EXPORT_SYMBOL(cpu_hwcaps);
|
|
|
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+ * Flag to indicate if we have computed the system wide
|
|
|
|
|
+ * capabilities based on the boot time active CPUs. This
|
|
|
|
|
+ * will be used to determine if a new booting CPU should
|
|
|
|
|
+ * go through the verification process to make sure that it
|
|
|
|
|
+ * supports the system capabilities, without using a hotplug
|
|
|
|
|
+ * notifier.
|
|
|
|
|
+ */
|
|
|
|
|
+static bool sys_caps_initialised;
|
|
|
|
|
+
|
|
|
|
|
+static inline void set_sys_caps_initialised(void)
|
|
|
|
|
+{
|
|
|
|
|
+ sys_caps_initialised = true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static int dump_cpu_hwcaps(struct notifier_block *self, unsigned long v, void *p)
|
|
static int dump_cpu_hwcaps(struct notifier_block *self, unsigned long v, void *p)
|
|
|
{
|
|
{
|
|
|
/* file-wide pr_fmt adds "CPU features: " prefix */
|
|
/* file-wide pr_fmt adds "CPU features: " prefix */
|
|
@@ -107,7 +123,11 @@ cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused)
|
|
|
* sync with the documentation of the CPU feature register ABI.
|
|
* sync with the documentation of the CPU feature register ABI.
|
|
|
*/
|
|
*/
|
|
|
static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
|
|
static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
|
|
|
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR0_RDM_SHIFT, 4, 0),
|
|
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_DP_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SM4_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SM3_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA3_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_RDM_SHIFT, 4, 0),
|
|
|
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_ATOMICS_SHIFT, 4, 0),
|
|
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_ATOMICS_SHIFT, 4, 0),
|
|
|
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_CRC32_SHIFT, 4, 0),
|
|
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_CRC32_SHIFT, 4, 0),
|
|
|
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA2_SHIFT, 4, 0),
|
|
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA2_SHIFT, 4, 0),
|
|
@@ -117,34 +137,35 @@ static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
|
|
static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
|
|
|
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_LRCPC_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_FCMA_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_JSCVT_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_DPB_SHIFT, 4, 0),
|
|
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_LRCPC_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_FCMA_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_JSCVT_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_DPB_SHIFT, 4, 0),
|
|
|
ARM64_FTR_END,
|
|
ARM64_FTR_END,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
|
|
static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_GIC_SHIFT, 4, 0),
|
|
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SVE_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_GIC_SHIFT, 4, 0),
|
|
|
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
|
|
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
|
|
|
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI),
|
|
S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI),
|
|
|
/* Linux doesn't care about the EL3 */
|
|
/* Linux doesn't care about the EL3 */
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64PFR0_EL3_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_EL2_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_EL1_SHIFT, 4, ID_AA64PFR0_EL1_64BIT_ONLY),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_EL0_64BIT_ONLY),
|
|
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL3_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL2_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_SHIFT, 4, ID_AA64PFR0_EL1_64BIT_ONLY),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_EL0_64BIT_ONLY),
|
|
|
ARM64_FTR_END,
|
|
ARM64_FTR_END,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
|
|
static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
|
|
|
- S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
|
|
|
|
|
- S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0),
|
|
|
|
|
|
|
+ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
|
|
|
|
|
+ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0),
|
|
|
/* Linux shouldn't care about secure memory */
|
|
/* Linux shouldn't care about secure memory */
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_BIGENDEL_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR0_ASID_SHIFT, 4, 0),
|
|
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_BIGENDEL_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_ASID_SHIFT, 4, 0),
|
|
|
/*
|
|
/*
|
|
|
* Differing PARange is fine as long as all peripherals and memory are mapped
|
|
* Differing PARange is fine as long as all peripherals and memory are mapped
|
|
|
* within the minimum PARange of all CPUs
|
|
* within the minimum PARange of all CPUs
|
|
@@ -155,20 +176,20 @@ static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
|
|
|
|
|
|
|
|
static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
|
|
static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = {
|
|
|
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_PAN_SHIFT, 4, 0),
|
|
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_PAN_SHIFT, 4, 0),
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_LOR_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_HPD_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_VHE_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_VMIDBITS_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR1_HADBS_SHIFT, 4, 0),
|
|
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_LOR_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_HPD_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_VHE_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_VMIDBITS_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_HADBS_SHIFT, 4, 0),
|
|
|
ARM64_FTR_END,
|
|
ARM64_FTR_END,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
|
|
static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = {
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LVA_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_IESB_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_LSM_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_UAO_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64MMFR2_CNP_SHIFT, 4, 0),
|
|
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_LVA_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_IESB_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_LSM_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_UAO_SHIFT, 4, 0),
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_CNP_SHIFT, 4, 0),
|
|
|
ARM64_FTR_END,
|
|
ARM64_FTR_END,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -193,14 +214,14 @@ struct arm64_ftr_reg arm64_ftr_reg_ctrel0 = {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static const struct arm64_ftr_bits ftr_id_mmfr0[] = {
|
|
static const struct arm64_ftr_bits ftr_id_mmfr0[] = {
|
|
|
- S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 28, 4, 0xf), /* InnerShr */
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 24, 4, 0), /* FCSE */
|
|
|
|
|
|
|
+ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0xf), /* InnerShr */
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 24, 4, 0), /* FCSE */
|
|
|
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, 20, 4, 0), /* AuxReg */
|
|
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, 20, 4, 0), /* AuxReg */
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 16, 4, 0), /* TCM */
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 12, 4, 0), /* ShareLvl */
|
|
|
|
|
- S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 8, 4, 0xf), /* OuterShr */
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 4, 4, 0), /* PMSA */
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 0, 4, 0), /* VMSA */
|
|
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 0), /* TCM */
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 12, 4, 0), /* ShareLvl */
|
|
|
|
|
+ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 8, 4, 0xf), /* OuterShr */
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0), /* PMSA */
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* VMSA */
|
|
|
ARM64_FTR_END,
|
|
ARM64_FTR_END,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -221,8 +242,8 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static const struct arm64_ftr_bits ftr_mvfr2[] = {
|
|
static const struct arm64_ftr_bits ftr_mvfr2[] = {
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 4, 4, 0), /* FPMisc */
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 0, 4, 0), /* SIMDMisc */
|
|
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0), /* FPMisc */
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* SIMDMisc */
|
|
|
ARM64_FTR_END,
|
|
ARM64_FTR_END,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -234,25 +255,25 @@ static const struct arm64_ftr_bits ftr_dczid[] = {
|
|
|
|
|
|
|
|
|
|
|
|
|
static const struct arm64_ftr_bits ftr_id_isar5[] = {
|
|
static const struct arm64_ftr_bits ftr_id_isar5[] = {
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_RDM_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_CRC32_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_SHA2_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_SHA1_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_AES_SHIFT, 4, 0),
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_ISAR5_SEVL_SHIFT, 4, 0),
|
|
|
|
|
|
|
+ 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_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SEVL_SHIFT, 4, 0),
|
|
|
ARM64_FTR_END,
|
|
ARM64_FTR_END,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static const struct arm64_ftr_bits ftr_id_mmfr4[] = {
|
|
static const struct arm64_ftr_bits ftr_id_mmfr4[] = {
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 4, 4, 0), /* ac2 */
|
|
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0), /* ac2 */
|
|
|
ARM64_FTR_END,
|
|
ARM64_FTR_END,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
static const struct arm64_ftr_bits ftr_id_pfr0[] = {
|
|
static const struct arm64_ftr_bits ftr_id_pfr0[] = {
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 12, 4, 0), /* State3 */
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 8, 4, 0), /* State2 */
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 4, 4, 0), /* State1 */
|
|
|
|
|
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 0, 4, 0), /* State0 */
|
|
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 12, 4, 0), /* State3 */
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 8, 4, 0), /* State2 */
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0), /* State1 */
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), /* State0 */
|
|
|
ARM64_FTR_END,
|
|
ARM64_FTR_END,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -268,6 +289,12 @@ static const struct arm64_ftr_bits ftr_id_dfr0[] = {
|
|
|
ARM64_FTR_END,
|
|
ARM64_FTR_END,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+static const struct arm64_ftr_bits ftr_zcr[] = {
|
|
|
|
|
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE,
|
|
|
|
|
+ ZCR_ELx_LEN_SHIFT, ZCR_ELx_LEN_SIZE, 0), /* LEN */
|
|
|
|
|
+ ARM64_FTR_END,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* Common ftr bits for a 32bit register with all hidden, strict
|
|
* Common ftr bits for a 32bit register with all hidden, strict
|
|
|
* attributes, with 4bit feature fields and a default safe value of
|
|
* attributes, with 4bit feature fields and a default safe value of
|
|
@@ -334,6 +361,7 @@ static const struct __ftr_reg_entry {
|
|
|
/* Op1 = 0, CRn = 0, CRm = 4 */
|
|
/* Op1 = 0, CRn = 0, CRm = 4 */
|
|
|
ARM64_FTR_REG(SYS_ID_AA64PFR0_EL1, ftr_id_aa64pfr0),
|
|
ARM64_FTR_REG(SYS_ID_AA64PFR0_EL1, ftr_id_aa64pfr0),
|
|
|
ARM64_FTR_REG(SYS_ID_AA64PFR1_EL1, ftr_raz),
|
|
ARM64_FTR_REG(SYS_ID_AA64PFR1_EL1, ftr_raz),
|
|
|
|
|
+ ARM64_FTR_REG(SYS_ID_AA64ZFR0_EL1, ftr_raz),
|
|
|
|
|
|
|
|
/* Op1 = 0, CRn = 0, CRm = 5 */
|
|
/* Op1 = 0, CRn = 0, CRm = 5 */
|
|
|
ARM64_FTR_REG(SYS_ID_AA64DFR0_EL1, ftr_id_aa64dfr0),
|
|
ARM64_FTR_REG(SYS_ID_AA64DFR0_EL1, ftr_id_aa64dfr0),
|
|
@@ -348,6 +376,9 @@ static const struct __ftr_reg_entry {
|
|
|
ARM64_FTR_REG(SYS_ID_AA64MMFR1_EL1, ftr_id_aa64mmfr1),
|
|
ARM64_FTR_REG(SYS_ID_AA64MMFR1_EL1, ftr_id_aa64mmfr1),
|
|
|
ARM64_FTR_REG(SYS_ID_AA64MMFR2_EL1, ftr_id_aa64mmfr2),
|
|
ARM64_FTR_REG(SYS_ID_AA64MMFR2_EL1, ftr_id_aa64mmfr2),
|
|
|
|
|
|
|
|
|
|
+ /* Op1 = 0, CRn = 1, CRm = 2 */
|
|
|
|
|
+ ARM64_FTR_REG(SYS_ZCR_EL1, ftr_zcr),
|
|
|
|
|
+
|
|
|
/* Op1 = 3, CRn = 0, CRm = 0 */
|
|
/* Op1 = 3, CRn = 0, CRm = 0 */
|
|
|
{ SYS_CTR_EL0, &arm64_ftr_reg_ctrel0 },
|
|
{ SYS_CTR_EL0, &arm64_ftr_reg_ctrel0 },
|
|
|
ARM64_FTR_REG(SYS_DCZID_EL0, ftr_dczid),
|
|
ARM64_FTR_REG(SYS_DCZID_EL0, ftr_dczid),
|
|
@@ -485,6 +516,7 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
|
|
|
init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2);
|
|
init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2);
|
|
|
init_cpu_ftr_reg(SYS_ID_AA64PFR0_EL1, info->reg_id_aa64pfr0);
|
|
init_cpu_ftr_reg(SYS_ID_AA64PFR0_EL1, info->reg_id_aa64pfr0);
|
|
|
init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1);
|
|
init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1);
|
|
|
|
|
+ init_cpu_ftr_reg(SYS_ID_AA64ZFR0_EL1, info->reg_id_aa64zfr0);
|
|
|
|
|
|
|
|
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
|
|
if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
|
|
|
init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
|
|
init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0);
|
|
@@ -505,6 +537,10 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
|
|
|
init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
|
|
init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (id_aa64pfr0_sve(info->reg_id_aa64pfr0)) {
|
|
|
|
|
+ init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr);
|
|
|
|
|
+ sve_init_vq_map();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
|
|
static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
|
|
@@ -608,6 +644,9 @@ void update_cpu_features(int cpu,
|
|
|
taint |= check_update_ftr_reg(SYS_ID_AA64PFR1_EL1, cpu,
|
|
taint |= check_update_ftr_reg(SYS_ID_AA64PFR1_EL1, cpu,
|
|
|
info->reg_id_aa64pfr1, boot->reg_id_aa64pfr1);
|
|
info->reg_id_aa64pfr1, boot->reg_id_aa64pfr1);
|
|
|
|
|
|
|
|
|
|
+ taint |= check_update_ftr_reg(SYS_ID_AA64ZFR0_EL1, cpu,
|
|
|
|
|
+ info->reg_id_aa64zfr0, boot->reg_id_aa64zfr0);
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* If we have AArch32, we care about 32-bit features for compat.
|
|
* If we have AArch32, we care about 32-bit features for compat.
|
|
|
* If the system doesn't support AArch32, don't update them.
|
|
* If the system doesn't support AArch32, don't update them.
|
|
@@ -655,6 +694,16 @@ void update_cpu_features(int cpu,
|
|
|
info->reg_mvfr2, boot->reg_mvfr2);
|
|
info->reg_mvfr2, boot->reg_mvfr2);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (id_aa64pfr0_sve(info->reg_id_aa64pfr0)) {
|
|
|
|
|
+ taint |= check_update_ftr_reg(SYS_ZCR_EL1, cpu,
|
|
|
|
|
+ info->reg_zcr, boot->reg_zcr);
|
|
|
|
|
+
|
|
|
|
|
+ /* Probe vector lengths, unless we already gave up on SVE */
|
|
|
|
|
+ if (id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1)) &&
|
|
|
|
|
+ !sys_caps_initialised)
|
|
|
|
|
+ sve_update_vq_map();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* Mismatched CPU features are a recipe for disaster. Don't even
|
|
* Mismatched CPU features are a recipe for disaster. Don't even
|
|
|
* pretend to support them.
|
|
* pretend to support them.
|
|
@@ -900,6 +949,19 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
|
|
.min_field_value = 1,
|
|
.min_field_value = 1,
|
|
|
},
|
|
},
|
|
|
#endif
|
|
#endif
|
|
|
|
|
+#ifdef CONFIG_ARM64_SVE
|
|
|
|
|
+ {
|
|
|
|
|
+ .desc = "Scalable Vector Extension",
|
|
|
|
|
+ .capability = ARM64_SVE,
|
|
|
|
|
+ .def_scope = SCOPE_SYSTEM,
|
|
|
|
|
+ .sys_reg = SYS_ID_AA64PFR0_EL1,
|
|
|
|
|
+ .sign = FTR_UNSIGNED,
|
|
|
|
|
+ .field_pos = ID_AA64PFR0_SVE_SHIFT,
|
|
|
|
|
+ .min_field_value = ID_AA64PFR0_SVE,
|
|
|
|
|
+ .matches = has_cpuid_feature,
|
|
|
|
|
+ .enable = sve_kernel_enable,
|
|
|
|
|
+ },
|
|
|
|
|
+#endif /* CONFIG_ARM64_SVE */
|
|
|
{},
|
|
{},
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -921,9 +983,14 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
|
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_AES),
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_AES),
|
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SHA1),
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SHA1),
|
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA2_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SHA2),
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA2_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SHA2),
|
|
|
|
|
+ HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA2_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, HWCAP_SHA512),
|
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_CRC32_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_CRC32),
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_CRC32_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_CRC32),
|
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_ATOMICS_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, HWCAP_ATOMICS),
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_ATOMICS_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, HWCAP_ATOMICS),
|
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_RDM_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_ASIMDRDM),
|
|
HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_RDM_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_ASIMDRDM),
|
|
|
|
|
+ HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA3_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SHA3),
|
|
|
|
|
+ HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SM3_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SM3),
|
|
|
|
|
+ HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SM4_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_SM4),
|
|
|
|
|
+ HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_DP_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_ASIMDDP),
|
|
|
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_FP),
|
|
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_FP),
|
|
|
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_FPHP),
|
|
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, HWCAP_FPHP),
|
|
|
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_ASIMD),
|
|
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, HWCAP_ASIMD),
|
|
@@ -932,6 +999,9 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
|
|
|
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_JSCVT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_JSCVT),
|
|
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_JSCVT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_JSCVT),
|
|
|
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_FCMA_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_FCMA),
|
|
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_FCMA_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_FCMA),
|
|
|
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_LRCPC),
|
|
HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_LRCPC),
|
|
|
|
|
+#ifdef CONFIG_ARM64_SVE
|
|
|
|
|
+ HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_SVE_SHIFT, FTR_UNSIGNED, ID_AA64PFR0_SVE, CAP_HWCAP, HWCAP_SVE),
|
|
|
|
|
+#endif
|
|
|
{},
|
|
{},
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -1040,21 +1110,6 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * Flag to indicate if we have computed the system wide
|
|
|
|
|
- * capabilities based on the boot time active CPUs. This
|
|
|
|
|
- * will be used to determine if a new booting CPU should
|
|
|
|
|
- * go through the verification process to make sure that it
|
|
|
|
|
- * supports the system capabilities, without using a hotplug
|
|
|
|
|
- * notifier.
|
|
|
|
|
- */
|
|
|
|
|
-static bool sys_caps_initialised;
|
|
|
|
|
-
|
|
|
|
|
-static inline void set_sys_caps_initialised(void)
|
|
|
|
|
-{
|
|
|
|
|
- sys_caps_initialised = true;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
/*
|
|
/*
|
|
|
* Check for CPU features that are used in early boot
|
|
* Check for CPU features that are used in early boot
|
|
|
* based on the Boot CPU value.
|
|
* based on the Boot CPU value.
|
|
@@ -1097,6 +1152,23 @@ verify_local_cpu_features(const struct arm64_cpu_capabilities *caps)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void verify_sve_features(void)
|
|
|
|
|
+{
|
|
|
|
|
+ u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
|
|
|
|
|
+ u64 zcr = read_zcr_features();
|
|
|
|
|
+
|
|
|
|
|
+ unsigned int safe_len = safe_zcr & ZCR_ELx_LEN_MASK;
|
|
|
|
|
+ unsigned int len = zcr & ZCR_ELx_LEN_MASK;
|
|
|
|
|
+
|
|
|
|
|
+ if (len < safe_len || sve_verify_vq_map()) {
|
|
|
|
|
+ pr_crit("CPU%d: SVE: required vector length(s) missing\n",
|
|
|
|
|
+ smp_processor_id());
|
|
|
|
|
+ cpu_die_early();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Add checks on other ZCR bits here if necessary */
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* Run through the enabled system capabilities and enable() it on this CPU.
|
|
* Run through the enabled system capabilities and enable() it on this CPU.
|
|
|
* The capabilities were decided based on the available CPUs at the boot time.
|
|
* The capabilities were decided based on the available CPUs at the boot time.
|
|
@@ -1110,8 +1182,12 @@ static void verify_local_cpu_capabilities(void)
|
|
|
verify_local_cpu_errata_workarounds();
|
|
verify_local_cpu_errata_workarounds();
|
|
|
verify_local_cpu_features(arm64_features);
|
|
verify_local_cpu_features(arm64_features);
|
|
|
verify_local_elf_hwcaps(arm64_elf_hwcaps);
|
|
verify_local_elf_hwcaps(arm64_elf_hwcaps);
|
|
|
|
|
+
|
|
|
if (system_supports_32bit_el0())
|
|
if (system_supports_32bit_el0())
|
|
|
verify_local_elf_hwcaps(compat_elf_hwcaps);
|
|
verify_local_elf_hwcaps(compat_elf_hwcaps);
|
|
|
|
|
+
|
|
|
|
|
+ if (system_supports_sve())
|
|
|
|
|
+ verify_sve_features();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void check_local_cpu_capabilities(void)
|
|
void check_local_cpu_capabilities(void)
|
|
@@ -1189,6 +1265,8 @@ void __init setup_cpu_features(void)
|
|
|
if (system_supports_32bit_el0())
|
|
if (system_supports_32bit_el0())
|
|
|
setup_elf_hwcaps(compat_elf_hwcaps);
|
|
setup_elf_hwcaps(compat_elf_hwcaps);
|
|
|
|
|
|
|
|
|
|
+ sve_setup();
|
|
|
|
|
+
|
|
|
/* Advertise that we have computed the system capabilities */
|
|
/* Advertise that we have computed the system capabilities */
|
|
|
set_sys_caps_initialised();
|
|
set_sys_caps_initialised();
|
|
|
|
|
|
|
@@ -1287,7 +1365,7 @@ static int emulate_mrs(struct pt_regs *regs, u32 insn)
|
|
|
if (!rc) {
|
|
if (!rc) {
|
|
|
dst = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RT, insn);
|
|
dst = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RT, insn);
|
|
|
pt_regs_write_reg(regs, dst, val);
|
|
pt_regs_write_reg(regs, dst, val);
|
|
|
- regs->pc += 4;
|
|
|
|
|
|
|
+ arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
return rc;
|