1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2359b7064SMarc Zyngier /* 3359b7064SMarc Zyngier * Contains CPU feature definitions 4359b7064SMarc Zyngier * 5359b7064SMarc Zyngier * Copyright (C) 2015 ARM Ltd. 6a2a69963SWill Deacon * 7a2a69963SWill Deacon * A note for the weary kernel hacker: the code here is confusing and hard to 8a2a69963SWill Deacon * follow! That's partly because it's solving a nasty problem, but also because 9a2a69963SWill Deacon * there's a little bit of over-abstraction that tends to obscure what's going 10a2a69963SWill Deacon * on behind a maze of helper functions and macros. 11a2a69963SWill Deacon * 12a2a69963SWill Deacon * The basic problem is that hardware folks have started gluing together CPUs 13a2a69963SWill Deacon * with distinct architectural features; in some cases even creating SoCs where 14a2a69963SWill Deacon * user-visible instructions are available only on a subset of the available 15a2a69963SWill Deacon * cores. We try to address this by snapshotting the feature registers of the 16a2a69963SWill Deacon * boot CPU and comparing these with the feature registers of each secondary 17a2a69963SWill Deacon * CPU when bringing them up. If there is a mismatch, then we update the 18a2a69963SWill Deacon * snapshot state to indicate the lowest-common denominator of the feature, 19a2a69963SWill Deacon * known as the "safe" value. This snapshot state can be queried to view the 20a2a69963SWill Deacon * "sanitised" value of a feature register. 21a2a69963SWill Deacon * 22a2a69963SWill Deacon * The sanitised register values are used to decide which capabilities we 23a2a69963SWill Deacon * have in the system. These may be in the form of traditional "hwcaps" 24a2a69963SWill Deacon * advertised to userspace or internal "cpucaps" which are used to configure 25a2a69963SWill Deacon * things like alternative patching and static keys. While a feature mismatch 26a2a69963SWill Deacon * may result in a TAINT_CPU_OUT_OF_SPEC kernel taint, a capability mismatch 27a2a69963SWill Deacon * may prevent a CPU from being onlined at all. 28a2a69963SWill Deacon * 29a2a69963SWill Deacon * Some implementation details worth remembering: 30a2a69963SWill Deacon * 31a2a69963SWill Deacon * - Mismatched features are *always* sanitised to a "safe" value, which 32a2a69963SWill Deacon * usually indicates that the feature is not supported. 33a2a69963SWill Deacon * 34a2a69963SWill Deacon * - A mismatched feature marked with FTR_STRICT will cause a "SANITY CHECK" 35a2a69963SWill Deacon * warning when onlining an offending CPU and the kernel will be tainted 36a2a69963SWill Deacon * with TAINT_CPU_OUT_OF_SPEC. 37a2a69963SWill Deacon * 38a2a69963SWill Deacon * - Features marked as FTR_VISIBLE have their sanitised value visible to 39a2a69963SWill Deacon * userspace. FTR_VISIBLE features in registers that are only visible 40a2a69963SWill Deacon * to EL0 by trapping *must* have a corresponding HWCAP so that late 41a2a69963SWill Deacon * onlining of CPUs cannot lead to features disappearing at runtime. 42a2a69963SWill Deacon * 43a2a69963SWill Deacon * - A "feature" is typically a 4-bit register field. A "capability" is the 44a2a69963SWill Deacon * high-level description derived from the sanitised field value. 45a2a69963SWill Deacon * 46a2a69963SWill Deacon * - Read the Arm ARM (DDI 0487F.a) section D13.1.3 ("Principles of the ID 47a2a69963SWill Deacon * scheme for fields in ID registers") to understand when feature fields 48a2a69963SWill Deacon * may be signed or unsigned (FTR_SIGNED and FTR_UNSIGNED accordingly). 49a2a69963SWill Deacon * 50a2a69963SWill Deacon * - KVM exposes its own view of the feature registers to guest operating 51a2a69963SWill Deacon * systems regardless of FTR_VISIBLE. This is typically driven from the 52a2a69963SWill Deacon * sanitised register values to allow virtual CPUs to be migrated between 53a2a69963SWill Deacon * arbitrary physical CPUs, but some features not present on the host are 54a2a69963SWill Deacon * also advertised and emulated. Look at sys_reg_descs[] for the gory 55a2a69963SWill Deacon * details. 56433022b5SWill Deacon * 57433022b5SWill Deacon * - If the arm64_ftr_bits[] for a register has a missing field, then this 58433022b5SWill Deacon * field is treated as STRICT RES0, including for read_sanitised_ftr_reg(). 59433022b5SWill Deacon * This is stronger than FTR_HIDDEN and can be used to hide features from 60433022b5SWill Deacon * KVM guests. 61359b7064SMarc Zyngier */ 62359b7064SMarc Zyngier 639cdf8ec4SSuzuki K. Poulose #define pr_fmt(fmt) "CPU features: " fmt 64359b7064SMarc Zyngier 653c739b57SSuzuki K. Poulose #include <linux/bsearch.h> 662a6dcb2bSJames Morse #include <linux/cpumask.h> 675ffdfaedSVladimir Murzin #include <linux/crash_dump.h> 683c739b57SSuzuki K. Poulose #include <linux/sort.h> 692a6dcb2bSJames Morse #include <linux/stop_machine.h> 70359b7064SMarc Zyngier #include <linux/types.h> 712077be67SLaura Abbott #include <linux/mm.h> 72a111b7c0SJosh Poimboeuf #include <linux/cpu.h> 732e903b91SAndrey Konovalov #include <linux/kasan.h> 74359b7064SMarc Zyngier #include <asm/cpu.h> 75359b7064SMarc Zyngier #include <asm/cpufeature.h> 76dbb4e152SSuzuki K. Poulose #include <asm/cpu_ops.h> 772e0f2478SDave Martin #include <asm/fpsimd.h> 783eb681fbSDavid Brazdil #include <asm/kvm_host.h> 7913f417f3SSuzuki K Poulose #include <asm/mmu_context.h> 8034bfeea4SCatalin Marinas #include <asm/mte.h> 81338d4f49SJames Morse #include <asm/processor.h> 82cdcf817bSSuzuki K. Poulose #include <asm/sysreg.h> 8377c97b4eSSuzuki K Poulose #include <asm/traps.h> 84d88701beSMarc Zyngier #include <asm/virt.h> 85359b7064SMarc Zyngier 86aec0bff7SAndrew Murray /* Kernel representation of AT_HWCAP and AT_HWCAP2 */ 87aec0bff7SAndrew Murray static unsigned long elf_hwcap __read_mostly; 889cdf8ec4SSuzuki K. Poulose 899cdf8ec4SSuzuki K. Poulose #ifdef CONFIG_COMPAT 909cdf8ec4SSuzuki K. Poulose #define COMPAT_ELF_HWCAP_DEFAULT \ 919cdf8ec4SSuzuki K. Poulose (COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\ 929cdf8ec4SSuzuki K. Poulose COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\ 937559950aSSuzuki K Poulose COMPAT_HWCAP_TLS|COMPAT_HWCAP_IDIV|\ 949cdf8ec4SSuzuki K. Poulose COMPAT_HWCAP_LPAE) 959cdf8ec4SSuzuki K. Poulose unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; 969cdf8ec4SSuzuki K. Poulose unsigned int compat_elf_hwcap2 __read_mostly; 979cdf8ec4SSuzuki K. Poulose #endif 989cdf8ec4SSuzuki K. Poulose 999cdf8ec4SSuzuki K. Poulose DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); 1004b65a5dbSCatalin Marinas EXPORT_SYMBOL(cpu_hwcaps); 10182a3a21bSSuzuki K Poulose static struct arm64_cpu_capabilities const __ro_after_init *cpu_hwcaps_ptrs[ARM64_NCAPS]; 1029cdf8ec4SSuzuki K. Poulose 1030ceb0d56SDaniel Thompson /* Need also bit for ARM64_CB_PATCH */ 1040ceb0d56SDaniel Thompson DECLARE_BITMAP(boot_capabilities, ARM64_NPATCHABLE); 1050ceb0d56SDaniel Thompson 10609e3c22aSMark Brown bool arm64_use_ng_mappings = false; 10709e3c22aSMark Brown EXPORT_SYMBOL(arm64_use_ng_mappings); 10809e3c22aSMark Brown 1098f1eec57SDave Martin /* 1108f1eec57SDave Martin * Flag to indicate if we have computed the system wide 1118f1eec57SDave Martin * capabilities based on the boot time active CPUs. This 1128f1eec57SDave Martin * will be used to determine if a new booting CPU should 1138f1eec57SDave Martin * go through the verification process to make sure that it 1148f1eec57SDave Martin * supports the system capabilities, without using a hotplug 115b51c6ac2SSuzuki K Poulose * notifier. This is also used to decide if we could use 116b51c6ac2SSuzuki K Poulose * the fast path for checking constant CPU caps. 1178f1eec57SDave Martin */ 118b51c6ac2SSuzuki K Poulose DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready); 119b51c6ac2SSuzuki K Poulose EXPORT_SYMBOL(arm64_const_caps_ready); 120b51c6ac2SSuzuki K Poulose static inline void finalize_system_capabilities(void) 1218f1eec57SDave Martin { 122b51c6ac2SSuzuki K Poulose static_branch_enable(&arm64_const_caps_ready); 1238f1eec57SDave Martin } 1248f1eec57SDave Martin 125638d5031SAnshuman Khandual void dump_cpu_features(void) 1268effeaafSMark Rutland { 1278effeaafSMark Rutland /* file-wide pr_fmt adds "CPU features: " prefix */ 1288effeaafSMark Rutland pr_emerg("0x%*pb\n", ARM64_NCAPS, &cpu_hwcaps); 1298effeaafSMark Rutland } 1308effeaafSMark Rutland 131efd9e03fSCatalin Marinas DEFINE_STATIC_KEY_ARRAY_FALSE(cpu_hwcap_keys, ARM64_NCAPS); 132efd9e03fSCatalin Marinas EXPORT_SYMBOL(cpu_hwcap_keys); 133efd9e03fSCatalin Marinas 134fe4fbdbcSSuzuki K Poulose #define __ARM64_FTR_BITS(SIGNED, VISIBLE, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \ 1353c739b57SSuzuki K. Poulose { \ 1364f0a606bSSuzuki K. Poulose .sign = SIGNED, \ 137fe4fbdbcSSuzuki K Poulose .visible = VISIBLE, \ 1383c739b57SSuzuki K. Poulose .strict = STRICT, \ 1393c739b57SSuzuki K. Poulose .type = TYPE, \ 1403c739b57SSuzuki K. Poulose .shift = SHIFT, \ 1413c739b57SSuzuki K. Poulose .width = WIDTH, \ 1423c739b57SSuzuki K. Poulose .safe_val = SAFE_VAL, \ 1433c739b57SSuzuki K. Poulose } 1443c739b57SSuzuki K. Poulose 1450710cfdbSSuzuki K Poulose /* Define a feature with unsigned values */ 146fe4fbdbcSSuzuki K Poulose #define ARM64_FTR_BITS(VISIBLE, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \ 147fe4fbdbcSSuzuki K Poulose __ARM64_FTR_BITS(FTR_UNSIGNED, VISIBLE, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) 1484f0a606bSSuzuki K. Poulose 1490710cfdbSSuzuki K Poulose /* Define a feature with a signed value */ 150fe4fbdbcSSuzuki K Poulose #define S_ARM64_FTR_BITS(VISIBLE, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) \ 151fe4fbdbcSSuzuki K Poulose __ARM64_FTR_BITS(FTR_SIGNED, VISIBLE, STRICT, TYPE, SHIFT, WIDTH, SAFE_VAL) 1520710cfdbSSuzuki K Poulose 1533c739b57SSuzuki K. Poulose #define ARM64_FTR_END \ 1543c739b57SSuzuki K. Poulose { \ 1553c739b57SSuzuki K. Poulose .width = 0, \ 1563c739b57SSuzuki K. Poulose } 1573c739b57SSuzuki K. Poulose 1585ffdfaedSVladimir Murzin static void cpu_enable_cnp(struct arm64_cpu_capabilities const *cap); 15970544196SJames Morse 1603ff047f6SAmit Daniel Kachhap static bool __system_matches_cap(unsigned int n); 1613ff047f6SAmit Daniel Kachhap 1624aa8a472SSuzuki K Poulose /* 1634aa8a472SSuzuki K Poulose * NOTE: Any changes to the visibility of features should be kept in 1644aa8a472SSuzuki K Poulose * sync with the documentation of the CPU feature register ABI. 1654aa8a472SSuzuki K Poulose */ 1665e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_id_aa64isar0[] = { 1671a50ec0bSRichard Henderson ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_RNDR_SHIFT, 4, 0), 1687cd51a5aSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_TLB_SHIFT, 4, 0), 1697206dc93SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_TS_SHIFT, 4, 0), 1703b3b6810SDongjiu Geng ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_FHM_SHIFT, 4, 0), 1715bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_DP_SHIFT, 4, 0), 1725bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SM4_SHIFT, 4, 0), 1735bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SM3_SHIFT, 4, 0), 1745bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA3_SHIFT, 4, 0), 1755bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_RDM_SHIFT, 4, 0), 176fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_ATOMICS_SHIFT, 4, 0), 177fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_CRC32_SHIFT, 4, 0), 178fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA2_SHIFT, 4, 0), 179fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_SHA1_SHIFT, 4, 0), 180fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR0_AES_SHIFT, 4, 0), 1813c739b57SSuzuki K. Poulose ARM64_FTR_END, 1823c739b57SSuzuki K. Poulose }; 1833c739b57SSuzuki K. Poulose 184c8c3798dSSuzuki K Poulose static const struct arm64_ftr_bits ftr_id_aa64isar1[] = { 185d4209d8bSSteven Price ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_I8MM_SHIFT, 4, 0), 186d4209d8bSSteven Price ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_DGH_SHIFT, 4, 0), 187d4209d8bSSteven Price ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_BF16_SHIFT, 4, 0), 188d4209d8bSSteven Price ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_SPECRES_SHIFT, 4, 0), 189bd4fb6d2SWill Deacon ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_SB_SHIFT, 4, 0), 1907230f7e9SJulien Grall ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_FRINTTS_SHIFT, 4, 0), 1916984eb47SMark Rutland ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH), 1926984eb47SMark Rutland FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_GPI_SHIFT, 4, 0), 1936984eb47SMark Rutland ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH), 1946984eb47SMark Rutland FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_GPA_SHIFT, 4, 0), 1955bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_LRCPC_SHIFT, 4, 0), 1965bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_FCMA_SHIFT, 4, 0), 1975bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_JSCVT_SHIFT, 4, 0), 1986984eb47SMark Rutland ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH), 199ba9d1d3eSAmit Daniel Kachhap FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_API_SHIFT, 4, 0), 2006984eb47SMark Rutland ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH), 201ba9d1d3eSAmit Daniel Kachhap FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_APA_SHIFT, 4, 0), 2025bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_DPB_SHIFT, 4, 0), 203c8c3798dSSuzuki K Poulose ARM64_FTR_END, 204c8c3798dSSuzuki K Poulose }; 205c8c3798dSSuzuki K Poulose 2065e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { 207179a56f6SWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV3_SHIFT, 4, 0), 2080f15adbbSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV2_SHIFT, 4, 0), 2097206dc93SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_DIT_SHIFT, 4, 0), 2102c9d45b4SIonela Voinescu ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_AMU_SHIFT, 4, 0), 211011e5f5bSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_MPAM_SHIFT, 4, 0), 212011e5f5bSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SEL2_SHIFT, 4, 0), 2133fab3999SDave Martin ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), 2143fab3999SDave Martin FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SVE_SHIFT, 4, 0), 21564c02720SXie XiuQi ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_RAS_SHIFT, 4, 0), 2165bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_GIC_SHIFT, 4, 0), 217fe4fbdbcSSuzuki K Poulose S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI), 218fe4fbdbcSSuzuki K Poulose S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI), 2195bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL3_SHIFT, 4, 0), 22098448cdfSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL2_SHIFT, 4, 0), 22198448cdfSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_SHIFT, 4, ID_AA64PFR0_EL1_64BIT_ONLY), 22298448cdfSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_EL0_64BIT_ONLY), 2233c739b57SSuzuki K. Poulose ARM64_FTR_END, 2243c739b57SSuzuki K. Poulose }; 2253c739b57SSuzuki K. Poulose 226d71be2b6SWill Deacon static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = { 22714e270faSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_MPAMFRAC_SHIFT, 4, 0), 22814e270faSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_RASFRAC_SHIFT, 4, 0), 2293b714d24SVincenzo Frascino ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_MTE), 2303b714d24SVincenzo Frascino FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_MTE_SHIFT, 4, ID_AA64PFR1_MTE_NI), 231532d5815SWill Deacon ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR1_SSBS_SHIFT, 4, ID_AA64PFR1_SSBS_PSTATE_NI), 2328ef8f360SDave Martin ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_BTI), 2338ef8f360SDave Martin FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_BT_SHIFT, 4, 0), 234d71be2b6SWill Deacon ARM64_FTR_END, 235d71be2b6SWill Deacon }; 236d71be2b6SWill Deacon 23706a916feSDave Martin static const struct arm64_ftr_bits ftr_id_aa64zfr0[] = { 238ec52c713SJulien Grall ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), 239d4209d8bSSteven Price FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_F64MM_SHIFT, 4, 0), 240d4209d8bSSteven Price ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), 241d4209d8bSSteven Price FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_F32MM_SHIFT, 4, 0), 242d4209d8bSSteven Price ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), 243d4209d8bSSteven Price FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_I8MM_SHIFT, 4, 0), 244d4209d8bSSteven Price ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), 245ec52c713SJulien Grall FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SM4_SHIFT, 4, 0), 246ec52c713SJulien Grall ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), 247ec52c713SJulien Grall FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SHA3_SHIFT, 4, 0), 248ec52c713SJulien Grall ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), 249d4209d8bSSteven Price FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_BF16_SHIFT, 4, 0), 250d4209d8bSSteven Price ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), 251ec52c713SJulien Grall FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_BITPERM_SHIFT, 4, 0), 252ec52c713SJulien Grall ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), 253ec52c713SJulien Grall FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_AES_SHIFT, 4, 0), 254ec52c713SJulien Grall ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE), 255ec52c713SJulien Grall FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ZFR0_SVEVER_SHIFT, 4, 0), 25606a916feSDave Martin ARM64_FTR_END, 25706a916feSDave Martin }; 25806a916feSDave Martin 2595e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = { 260bc67f10aSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_ECV_SHIFT, 4, 0), 261bc67f10aSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_FGT_SHIFT, 4, 0), 262bc67f10aSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_EXS_SHIFT, 4, 0), 2635717fe5aSWill Deacon /* 264b130a8f7SMarc Zyngier * Page size not being supported at Stage-2 is not fatal. You 265b130a8f7SMarc Zyngier * just give up KVM if PAGE_SIZE isn't supported there. Go fix 266b130a8f7SMarc Zyngier * your favourite nesting hypervisor. 267b130a8f7SMarc Zyngier * 268b130a8f7SMarc Zyngier * There is a small corner case where the hypervisor explicitly 269b130a8f7SMarc Zyngier * advertises a given granule size at Stage-2 (value 2) on some 270b130a8f7SMarc Zyngier * vCPUs, and uses the fallback to Stage-1 (value 0) for other 271b130a8f7SMarc Zyngier * vCPUs. Although this is not forbidden by the architecture, it 272b130a8f7SMarc Zyngier * indicates that the hypervisor is being silly (or buggy). 273b130a8f7SMarc Zyngier * 274b130a8f7SMarc Zyngier * We make no effort to cope with this and pretend that if these 275b130a8f7SMarc Zyngier * fields are inconsistent across vCPUs, then it isn't worth 276b130a8f7SMarc Zyngier * trying to bring KVM up. 277b130a8f7SMarc Zyngier */ 278b130a8f7SMarc Zyngier ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN4_2_SHIFT, 4, 1), 279b130a8f7SMarc Zyngier ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN64_2_SHIFT, 4, 1), 280b130a8f7SMarc Zyngier ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64MMFR0_TGRAN16_2_SHIFT, 4, 1), 281b130a8f7SMarc Zyngier /* 2825717fe5aSWill Deacon * We already refuse to boot CPUs that don't support our configured 2835717fe5aSWill Deacon * page size, so we can only detect mismatches for a page size other 2845717fe5aSWill Deacon * than the one we're currently using. Unfortunately, SoCs like this 2855717fe5aSWill Deacon * exist in the wild so, even though we don't like it, we'll have to go 2865717fe5aSWill Deacon * along with it and treat them as non-strict. 2875717fe5aSWill Deacon */ 2885717fe5aSWill Deacon S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI), 2895717fe5aSWill Deacon S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI), 2905717fe5aSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI), 2915717fe5aSWill Deacon 2925bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0), 2933c739b57SSuzuki K. Poulose /* Linux shouldn't care about secure memory */ 2945bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0), 2955bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_BIGENDEL_SHIFT, 4, 0), 2965bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_ASID_SHIFT, 4, 0), 2973c739b57SSuzuki K. Poulose /* 2983c739b57SSuzuki K. Poulose * Differing PARange is fine as long as all peripherals and memory are mapped 2993c739b57SSuzuki K. Poulose * within the minimum PARange of all CPUs 3003c739b57SSuzuki K. Poulose */ 301fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_PARANGE_SHIFT, 4, 0), 3023c739b57SSuzuki K. Poulose ARM64_FTR_END, 3033c739b57SSuzuki K. Poulose }; 3043c739b57SSuzuki K. Poulose 3055e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_id_aa64mmfr1[] = { 306853772baSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_ETS_SHIFT, 4, 0), 307853772baSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_TWED_SHIFT, 4, 0), 308853772baSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_XNX_SHIFT, 4, 0), 309853772baSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64MMFR1_SPECSEI_SHIFT, 4, 0), 310fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_PAN_SHIFT, 4, 0), 3115bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_LOR_SHIFT, 4, 0), 3125bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_HPD_SHIFT, 4, 0), 3135bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_VHE_SHIFT, 4, 0), 3145bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_VMIDBITS_SHIFT, 4, 0), 3155bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR1_HADBS_SHIFT, 4, 0), 3163c739b57SSuzuki K. Poulose ARM64_FTR_END, 3173c739b57SSuzuki K. Poulose }; 3183c739b57SSuzuki K. Poulose 3195e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_id_aa64mmfr2[] = { 3203e6c69a0SMark Brown ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_E0PD_SHIFT, 4, 0), 321356fdfbeSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_EVT_SHIFT, 4, 0), 322356fdfbeSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_BBM_SHIFT, 4, 0), 323356fdfbeSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_TTL_SHIFT, 4, 0), 324e48d53a9SMarc Zyngier ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_FWB_SHIFT, 4, 0), 325356fdfbeSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_IDS_SHIFT, 4, 0), 3267206dc93SSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_AT_SHIFT, 4, 0), 327356fdfbeSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_ST_SHIFT, 4, 0), 328356fdfbeSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_NV_SHIFT, 4, 0), 329356fdfbeSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_CCIDX_SHIFT, 4, 0), 3305bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_LVA_SHIFT, 4, 0), 3319d3f8881SSai Prakash Ranjan ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_IESB_SHIFT, 4, 0), 3325bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_LSM_SHIFT, 4, 0), 3335bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_UAO_SHIFT, 4, 0), 3345bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR2_CNP_SHIFT, 4, 0), 335406e3087SJames Morse ARM64_FTR_END, 336406e3087SJames Morse }; 337406e3087SJames Morse 3385e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_ctr[] = { 339be68a8aaSWill Deacon ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1), /* RES1 */ 3406ae4b6e0SShanker Donthineni ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_DIC_SHIFT, 1, 1), 3416ae4b6e0SShanker Donthineni ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_IDC_SHIFT, 1, 1), 342147b9635SWill Deacon ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_OR_ZERO_SAFE, CTR_CWG_SHIFT, 4, 0), 343147b9635SWill Deacon ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_OR_ZERO_SAFE, CTR_ERG_SHIFT, 4, 0), 3446ae4b6e0SShanker Donthineni ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_DMINLINE_SHIFT, 4, 1), 3453c739b57SSuzuki K. Poulose /* 3463c739b57SSuzuki K. Poulose * Linux can handle differing I-cache policies. Userspace JITs will 347ee7bc638SSuzuki K Poulose * make use of *minLine. 348155433cbSWill Deacon * If we have differing I-cache policies, report it as the weakest - VIPT. 3493c739b57SSuzuki K. Poulose */ 3508d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_EXACT, CTR_L1IP_SHIFT, 2, ICACHE_POLICY_VIPT), /* L1Ip */ 3514c4a39ddSSuzuki K Poulose ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_IMINLINE_SHIFT, 4, 0), 3523c739b57SSuzuki K. Poulose ARM64_FTR_END, 3533c739b57SSuzuki K. Poulose }; 3543c739b57SSuzuki K. Poulose 3558f266a5dSMarc Zyngier static struct arm64_ftr_override __ro_after_init no_override = { }; 3568f266a5dSMarc Zyngier 357675b0563SArd Biesheuvel struct arm64_ftr_reg arm64_ftr_reg_ctrel0 = { 358675b0563SArd Biesheuvel .name = "SYS_CTR_EL0", 3598f266a5dSMarc Zyngier .ftr_bits = ftr_ctr, 3608f266a5dSMarc Zyngier .override = &no_override, 361675b0563SArd Biesheuvel }; 362675b0563SArd Biesheuvel 3635e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_id_mmfr0[] = { 3648d3154afSAnshuman Khandual S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_INNERSHR_SHIFT, 4, 0xf), 3658d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_FCSE_SHIFT, 4, 0), 3668d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_MMFR0_AUXREG_SHIFT, 4, 0), 3678d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_TCM_SHIFT, 4, 0), 3688d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_SHARELVL_SHIFT, 4, 0), 3698d3154afSAnshuman Khandual S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_OUTERSHR_SHIFT, 4, 0xf), 3708d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_PMSA_SHIFT, 4, 0), 3718d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_VMSA_SHIFT, 4, 0), 3723c739b57SSuzuki K. Poulose ARM64_FTR_END, 3733c739b57SSuzuki K. Poulose }; 3743c739b57SSuzuki K. Poulose 3755e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = { 3768d3154afSAnshuman Khandual S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_DOUBLELOCK_SHIFT, 4, 0), 377fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64DFR0_PMSVER_SHIFT, 4, 0), 378fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_CTX_CMPS_SHIFT, 4, 0), 379fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_WRPS_SHIFT, 4, 0), 380fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64DFR0_BRPS_SHIFT, 4, 0), 381b20d1ba3SWill Deacon /* 382b20d1ba3SWill Deacon * We can instantiate multiple PMU instances with different levels 383b20d1ba3SWill Deacon * of support. 384fe4fbdbcSSuzuki K Poulose */ 385fe4fbdbcSSuzuki K Poulose S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0), 386fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0), 387fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6), 3883c739b57SSuzuki K. Poulose ARM64_FTR_END, 3893c739b57SSuzuki K. Poulose }; 3903c739b57SSuzuki K. Poulose 3915e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_mvfr2[] = { 3928d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR2_FPMISC_SHIFT, 4, 0), 3938d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR2_SIMDMISC_SHIFT, 4, 0), 3943c739b57SSuzuki K. Poulose ARM64_FTR_END, 3953c739b57SSuzuki K. Poulose }; 3963c739b57SSuzuki K. Poulose 3975e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_dczid[] = { 3988d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, DCZID_DZP_SHIFT, 1, 1), 3998d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, DCZID_BS_SHIFT, 4, 0), 4003c739b57SSuzuki K. Poulose ARM64_FTR_END, 4013c739b57SSuzuki K. Poulose }; 4023c739b57SSuzuki K. Poulose 4032a5bc6c4SAnshuman Khandual static const struct arm64_ftr_bits ftr_id_isar0[] = { 4042a5bc6c4SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_DIVIDE_SHIFT, 4, 0), 4052a5bc6c4SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_DEBUG_SHIFT, 4, 0), 4062a5bc6c4SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_COPROC_SHIFT, 4, 0), 4072a5bc6c4SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_CMPBRANCH_SHIFT, 4, 0), 4082a5bc6c4SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_BITFIELD_SHIFT, 4, 0), 4092a5bc6c4SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_BITCOUNT_SHIFT, 4, 0), 4102a5bc6c4SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_SWAP_SHIFT, 4, 0), 4112a5bc6c4SAnshuman Khandual ARM64_FTR_END, 4122a5bc6c4SAnshuman Khandual }; 4133c739b57SSuzuki K. Poulose 4145e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_id_isar5[] = { 4155bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_RDM_SHIFT, 4, 0), 4165bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0), 4175bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA2_SHIFT, 4, 0), 4185bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA1_SHIFT, 4, 0), 4195bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_AES_SHIFT, 4, 0), 4205bdecb79SSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SEVL_SHIFT, 4, 0), 4213c739b57SSuzuki K. Poulose ARM64_FTR_END, 4223c739b57SSuzuki K. Poulose }; 4233c739b57SSuzuki K. Poulose 4245e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_id_mmfr4[] = { 425fcd65353SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_EVT_SHIFT, 4, 0), 426fcd65353SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_CCIDX_SHIFT, 4, 0), 427fcd65353SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_LSM_SHIFT, 4, 0), 428fcd65353SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_HPDS_SHIFT, 4, 0), 429fcd65353SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_CNP_SHIFT, 4, 0), 430fcd65353SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_XNX_SHIFT, 4, 0), 4318d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_AC2_SHIFT, 4, 0), 4328d3154afSAnshuman Khandual 433fcd65353SAnshuman Khandual /* 434fcd65353SAnshuman Khandual * SpecSEI = 1 indicates that the PE might generate an SError on an 435fcd65353SAnshuman Khandual * external abort on speculative read. It is safe to assume that an 436fcd65353SAnshuman Khandual * SError might be generated than it will not be. Hence it has been 437fcd65353SAnshuman Khandual * classified as FTR_HIGHER_SAFE. 438fcd65353SAnshuman Khandual */ 439fcd65353SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_MMFR4_SPECSEI_SHIFT, 4, 0), 4403c739b57SSuzuki K. Poulose ARM64_FTR_END, 4413c739b57SSuzuki K. Poulose }; 4423c739b57SSuzuki K. Poulose 4430113340eSWill Deacon static const struct arm64_ftr_bits ftr_id_isar4[] = { 4440113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_SWP_FRAC_SHIFT, 4, 0), 4450113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_PSR_M_SHIFT, 4, 0), 4460113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_SYNCH_PRIM_FRAC_SHIFT, 4, 0), 4470113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_BARRIER_SHIFT, 4, 0), 4480113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_SMC_SHIFT, 4, 0), 4490113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_WRITEBACK_SHIFT, 4, 0), 4500113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_WITHSHIFTS_SHIFT, 4, 0), 4510113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_UNPRIV_SHIFT, 4, 0), 4520113340eSWill Deacon ARM64_FTR_END, 4530113340eSWill Deacon }; 4540113340eSWill Deacon 455152accf8SAnshuman Khandual static const struct arm64_ftr_bits ftr_id_mmfr5[] = { 456152accf8SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR5_ETS_SHIFT, 4, 0), 457152accf8SAnshuman Khandual ARM64_FTR_END, 458152accf8SAnshuman Khandual }; 459152accf8SAnshuman Khandual 4608e3747beSAnshuman Khandual static const struct arm64_ftr_bits ftr_id_isar6[] = { 4618e3747beSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_I8MM_SHIFT, 4, 0), 4628e3747beSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_BF16_SHIFT, 4, 0), 4638e3747beSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_SPECRES_SHIFT, 4, 0), 4648e3747beSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_SB_SHIFT, 4, 0), 4658e3747beSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_FHM_SHIFT, 4, 0), 4668e3747beSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_DP_SHIFT, 4, 0), 4678e3747beSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_JSCVT_SHIFT, 4, 0), 4688e3747beSAnshuman Khandual ARM64_FTR_END, 4698e3747beSAnshuman Khandual }; 4708e3747beSAnshuman Khandual 4715e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_id_pfr0[] = { 4720ae43a99SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_DIT_SHIFT, 4, 0), 4730ae43a99SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_PFR0_CSV2_SHIFT, 4, 0), 4748d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_STATE3_SHIFT, 4, 0), 4758d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_STATE2_SHIFT, 4, 0), 4768d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_STATE1_SHIFT, 4, 0), 4778d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_STATE0_SHIFT, 4, 0), 4783c739b57SSuzuki K. Poulose ARM64_FTR_END, 4793c739b57SSuzuki K. Poulose }; 4803c739b57SSuzuki K. Poulose 4810113340eSWill Deacon static const struct arm64_ftr_bits ftr_id_pfr1[] = { 4820113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_GIC_SHIFT, 4, 0), 4830113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_VIRT_FRAC_SHIFT, 4, 0), 4840113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_SEC_FRAC_SHIFT, 4, 0), 4850113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_GENTIMER_SHIFT, 4, 0), 4860113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_VIRTUALIZATION_SHIFT, 4, 0), 4870113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_MPROGMOD_SHIFT, 4, 0), 4880113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_SECURITY_SHIFT, 4, 0), 4890113340eSWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_PROGMOD_SHIFT, 4, 0), 4900113340eSWill Deacon ARM64_FTR_END, 4910113340eSWill Deacon }; 4920113340eSWill Deacon 49316824085SAnshuman Khandual static const struct arm64_ftr_bits ftr_id_pfr2[] = { 494532d5815SWill Deacon ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_PFR2_SSBS_SHIFT, 4, 0), 49516824085SAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_PFR2_CSV3_SHIFT, 4, 0), 49616824085SAnshuman Khandual ARM64_FTR_END, 49716824085SAnshuman Khandual }; 49816824085SAnshuman Khandual 4995e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_id_dfr0[] = { 5001ed1b90aSAnshuman Khandual /* [31:28] TraceFilt */ 5018d3154afSAnshuman Khandual S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_PERFMON_SHIFT, 4, 0xf), 5028d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_MPROFDBG_SHIFT, 4, 0), 5038d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_MMAPTRC_SHIFT, 4, 0), 5048d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_COPTRC_SHIFT, 4, 0), 5058d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_MMAPDBG_SHIFT, 4, 0), 5068d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_COPSDBG_SHIFT, 4, 0), 5078d3154afSAnshuman Khandual ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_COPDBG_SHIFT, 4, 0), 508e5343503SSuzuki K Poulose ARM64_FTR_END, 509e5343503SSuzuki K Poulose }; 510e5343503SSuzuki K Poulose 511dd35ec07SAnshuman Khandual static const struct arm64_ftr_bits ftr_id_dfr1[] = { 512dd35ec07SAnshuman Khandual S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR1_MTPMU_SHIFT, 4, 0), 513dd35ec07SAnshuman Khandual ARM64_FTR_END, 514dd35ec07SAnshuman Khandual }; 515dd35ec07SAnshuman Khandual 5162e0f2478SDave Martin static const struct arm64_ftr_bits ftr_zcr[] = { 5172e0f2478SDave Martin ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, 5182e0f2478SDave Martin ZCR_ELx_LEN_SHIFT, ZCR_ELx_LEN_SIZE, 0), /* LEN */ 5192e0f2478SDave Martin ARM64_FTR_END, 5202e0f2478SDave Martin }; 5212e0f2478SDave Martin 5223c739b57SSuzuki K. Poulose /* 5233c739b57SSuzuki K. Poulose * Common ftr bits for a 32bit register with all hidden, strict 5243c739b57SSuzuki K. Poulose * attributes, with 4bit feature fields and a default safe value of 5253c739b57SSuzuki K. Poulose * 0. Covers the following 32bit registers: 5262a5bc6c4SAnshuman Khandual * id_isar[1-4], id_mmfr[1-3], id_pfr1, mvfr[0-1] 5273c739b57SSuzuki K. Poulose */ 5285e49d73cSArd Biesheuvel static const struct arm64_ftr_bits ftr_generic_32bits[] = { 529fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0), 530fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 24, 4, 0), 531fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0), 532fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 0), 533fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 12, 4, 0), 534fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 8, 4, 0), 535fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0), 536fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0), 5373c739b57SSuzuki K. Poulose ARM64_FTR_END, 5383c739b57SSuzuki K. Poulose }; 5393c739b57SSuzuki K. Poulose 540eab43e88SSuzuki K Poulose /* Table for a single 32bit feature value */ 541eab43e88SSuzuki K Poulose static const struct arm64_ftr_bits ftr_single32[] = { 542fe4fbdbcSSuzuki K Poulose ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, 0, 32, 0), 5433c739b57SSuzuki K. Poulose ARM64_FTR_END, 5443c739b57SSuzuki K. Poulose }; 5453c739b57SSuzuki K. Poulose 546eab43e88SSuzuki K Poulose static const struct arm64_ftr_bits ftr_raz[] = { 5473c739b57SSuzuki K. Poulose ARM64_FTR_END, 5483c739b57SSuzuki K. Poulose }; 5493c739b57SSuzuki K. Poulose 5508f266a5dSMarc Zyngier #define ARM64_FTR_REG_OVERRIDE(id, table, ovr) { \ 5513c739b57SSuzuki K. Poulose .sys_id = id, \ 5526f2b7eefSArd Biesheuvel .reg = &(struct arm64_ftr_reg){ \ 5533c739b57SSuzuki K. Poulose .name = #id, \ 5548f266a5dSMarc Zyngier .override = (ovr), \ 5553c739b57SSuzuki K. Poulose .ftr_bits = &((table)[0]), \ 5566f2b7eefSArd Biesheuvel }} 5573c739b57SSuzuki K. Poulose 5588f266a5dSMarc Zyngier #define ARM64_FTR_REG(id, table) ARM64_FTR_REG_OVERRIDE(id, table, &no_override) 5598f266a5dSMarc Zyngier 560361db0fcSMarc Zyngier struct arm64_ftr_override __ro_after_init id_aa64mmfr1_override; 56193ad55b7SMarc Zyngier struct arm64_ftr_override __ro_after_init id_aa64pfr1_override; 562f8da5752SMarc Zyngier struct arm64_ftr_override __ro_after_init id_aa64isar1_override; 563361db0fcSMarc Zyngier 5646f2b7eefSArd Biesheuvel static const struct __ftr_reg_entry { 5656f2b7eefSArd Biesheuvel u32 sys_id; 5666f2b7eefSArd Biesheuvel struct arm64_ftr_reg *reg; 5676f2b7eefSArd Biesheuvel } arm64_ftr_regs[] = { 5683c739b57SSuzuki K. Poulose 5693c739b57SSuzuki K. Poulose /* Op1 = 0, CRn = 0, CRm = 1 */ 5703c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_PFR0_EL1, ftr_id_pfr0), 5710113340eSWill Deacon ARM64_FTR_REG(SYS_ID_PFR1_EL1, ftr_id_pfr1), 572e5343503SSuzuki K Poulose ARM64_FTR_REG(SYS_ID_DFR0_EL1, ftr_id_dfr0), 5733c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_MMFR0_EL1, ftr_id_mmfr0), 5743c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_MMFR1_EL1, ftr_generic_32bits), 5753c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_MMFR2_EL1, ftr_generic_32bits), 5763c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_MMFR3_EL1, ftr_generic_32bits), 5773c739b57SSuzuki K. Poulose 5783c739b57SSuzuki K. Poulose /* Op1 = 0, CRn = 0, CRm = 2 */ 5792a5bc6c4SAnshuman Khandual ARM64_FTR_REG(SYS_ID_ISAR0_EL1, ftr_id_isar0), 5803c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_ISAR1_EL1, ftr_generic_32bits), 5813c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_ISAR2_EL1, ftr_generic_32bits), 5823c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_ISAR3_EL1, ftr_generic_32bits), 5830113340eSWill Deacon ARM64_FTR_REG(SYS_ID_ISAR4_EL1, ftr_id_isar4), 5843c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_ISAR5_EL1, ftr_id_isar5), 5853c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_MMFR4_EL1, ftr_id_mmfr4), 5868e3747beSAnshuman Khandual ARM64_FTR_REG(SYS_ID_ISAR6_EL1, ftr_id_isar6), 5873c739b57SSuzuki K. Poulose 5883c739b57SSuzuki K. Poulose /* Op1 = 0, CRn = 0, CRm = 3 */ 5893c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_generic_32bits), 5903c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_generic_32bits), 5913c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_MVFR2_EL1, ftr_mvfr2), 59216824085SAnshuman Khandual ARM64_FTR_REG(SYS_ID_PFR2_EL1, ftr_id_pfr2), 593dd35ec07SAnshuman Khandual ARM64_FTR_REG(SYS_ID_DFR1_EL1, ftr_id_dfr1), 594152accf8SAnshuman Khandual ARM64_FTR_REG(SYS_ID_MMFR5_EL1, ftr_id_mmfr5), 5953c739b57SSuzuki K. Poulose 5963c739b57SSuzuki K. Poulose /* Op1 = 0, CRn = 0, CRm = 4 */ 5973c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_AA64PFR0_EL1, ftr_id_aa64pfr0), 59893ad55b7SMarc Zyngier ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64PFR1_EL1, ftr_id_aa64pfr1, 59993ad55b7SMarc Zyngier &id_aa64pfr1_override), 60006a916feSDave Martin ARM64_FTR_REG(SYS_ID_AA64ZFR0_EL1, ftr_id_aa64zfr0), 6013c739b57SSuzuki K. Poulose 6023c739b57SSuzuki K. Poulose /* Op1 = 0, CRn = 0, CRm = 5 */ 6033c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_AA64DFR0_EL1, ftr_id_aa64dfr0), 604eab43e88SSuzuki K Poulose ARM64_FTR_REG(SYS_ID_AA64DFR1_EL1, ftr_raz), 6053c739b57SSuzuki K. Poulose 6063c739b57SSuzuki K. Poulose /* Op1 = 0, CRn = 0, CRm = 6 */ 6073c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_AA64ISAR0_EL1, ftr_id_aa64isar0), 608f8da5752SMarc Zyngier ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64ISAR1_EL1, ftr_id_aa64isar1, 609f8da5752SMarc Zyngier &id_aa64isar1_override), 6103c739b57SSuzuki K. Poulose 6113c739b57SSuzuki K. Poulose /* Op1 = 0, CRn = 0, CRm = 7 */ 6123c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_ID_AA64MMFR0_EL1, ftr_id_aa64mmfr0), 613361db0fcSMarc Zyngier ARM64_FTR_REG_OVERRIDE(SYS_ID_AA64MMFR1_EL1, ftr_id_aa64mmfr1, 614361db0fcSMarc Zyngier &id_aa64mmfr1_override), 615406e3087SJames Morse ARM64_FTR_REG(SYS_ID_AA64MMFR2_EL1, ftr_id_aa64mmfr2), 6163c739b57SSuzuki K. Poulose 6172e0f2478SDave Martin /* Op1 = 0, CRn = 1, CRm = 2 */ 6182e0f2478SDave Martin ARM64_FTR_REG(SYS_ZCR_EL1, ftr_zcr), 6192e0f2478SDave Martin 6203c739b57SSuzuki K. Poulose /* Op1 = 3, CRn = 0, CRm = 0 */ 621675b0563SArd Biesheuvel { SYS_CTR_EL0, &arm64_ftr_reg_ctrel0 }, 6223c739b57SSuzuki K. Poulose ARM64_FTR_REG(SYS_DCZID_EL0, ftr_dczid), 6233c739b57SSuzuki K. Poulose 6243c739b57SSuzuki K. Poulose /* Op1 = 3, CRn = 14, CRm = 0 */ 625eab43e88SSuzuki K Poulose ARM64_FTR_REG(SYS_CNTFRQ_EL0, ftr_single32), 6263c739b57SSuzuki K. Poulose }; 6273c739b57SSuzuki K. Poulose 6283c739b57SSuzuki K. Poulose static int search_cmp_ftr_reg(const void *id, const void *regp) 6293c739b57SSuzuki K. Poulose { 6306f2b7eefSArd Biesheuvel return (int)(unsigned long)id - (int)((const struct __ftr_reg_entry *)regp)->sys_id; 6313c739b57SSuzuki K. Poulose } 6323c739b57SSuzuki K. Poulose 6333c739b57SSuzuki K. Poulose /* 6343577dd37SAnshuman Khandual * get_arm64_ftr_reg_nowarn - Looks up a feature register entry using 6353577dd37SAnshuman Khandual * its sys_reg() encoding. With the array arm64_ftr_regs sorted in the 6363c739b57SSuzuki K. Poulose * ascending order of sys_id, we use binary search to find a matching 6373c739b57SSuzuki K. Poulose * entry. 6383c739b57SSuzuki K. Poulose * 6393c739b57SSuzuki K. Poulose * returns - Upon success, matching ftr_reg entry for id. 6403c739b57SSuzuki K. Poulose * - NULL on failure. It is upto the caller to decide 6413c739b57SSuzuki K. Poulose * the impact of a failure. 6423c739b57SSuzuki K. Poulose */ 6433577dd37SAnshuman Khandual static struct arm64_ftr_reg *get_arm64_ftr_reg_nowarn(u32 sys_id) 6443c739b57SSuzuki K. Poulose { 6456f2b7eefSArd Biesheuvel const struct __ftr_reg_entry *ret; 6466f2b7eefSArd Biesheuvel 6476f2b7eefSArd Biesheuvel ret = bsearch((const void *)(unsigned long)sys_id, 6483c739b57SSuzuki K. Poulose arm64_ftr_regs, 6493c739b57SSuzuki K. Poulose ARRAY_SIZE(arm64_ftr_regs), 6503c739b57SSuzuki K. Poulose sizeof(arm64_ftr_regs[0]), 6513c739b57SSuzuki K. Poulose search_cmp_ftr_reg); 6526f2b7eefSArd Biesheuvel if (ret) 6536f2b7eefSArd Biesheuvel return ret->reg; 6546f2b7eefSArd Biesheuvel return NULL; 6553c739b57SSuzuki K. Poulose } 6563c739b57SSuzuki K. Poulose 6573577dd37SAnshuman Khandual /* 6583577dd37SAnshuman Khandual * get_arm64_ftr_reg - Looks up a feature register entry using 6593577dd37SAnshuman Khandual * its sys_reg() encoding. This calls get_arm64_ftr_reg_nowarn(). 6603577dd37SAnshuman Khandual * 6613577dd37SAnshuman Khandual * returns - Upon success, matching ftr_reg entry for id. 6623577dd37SAnshuman Khandual * - NULL on failure but with an WARN_ON(). 6633577dd37SAnshuman Khandual */ 6643577dd37SAnshuman Khandual static struct arm64_ftr_reg *get_arm64_ftr_reg(u32 sys_id) 6653577dd37SAnshuman Khandual { 6663577dd37SAnshuman Khandual struct arm64_ftr_reg *reg; 6673577dd37SAnshuman Khandual 6683577dd37SAnshuman Khandual reg = get_arm64_ftr_reg_nowarn(sys_id); 6693577dd37SAnshuman Khandual 6703577dd37SAnshuman Khandual /* 6713577dd37SAnshuman Khandual * Requesting a non-existent register search is an error. Warn 6723577dd37SAnshuman Khandual * and let the caller handle it. 6733577dd37SAnshuman Khandual */ 6743577dd37SAnshuman Khandual WARN_ON(!reg); 6753577dd37SAnshuman Khandual return reg; 6763577dd37SAnshuman Khandual } 6773577dd37SAnshuman Khandual 6785e49d73cSArd Biesheuvel static u64 arm64_ftr_set_value(const struct arm64_ftr_bits *ftrp, s64 reg, 6795e49d73cSArd Biesheuvel s64 ftr_val) 6803c739b57SSuzuki K. Poulose { 6813c739b57SSuzuki K. Poulose u64 mask = arm64_ftr_mask(ftrp); 6823c739b57SSuzuki K. Poulose 6833c739b57SSuzuki K. Poulose reg &= ~mask; 6843c739b57SSuzuki K. Poulose reg |= (ftr_val << ftrp->shift) & mask; 6853c739b57SSuzuki K. Poulose return reg; 6863c739b57SSuzuki K. Poulose } 6873c739b57SSuzuki K. Poulose 6885e49d73cSArd Biesheuvel static s64 arm64_ftr_safe_value(const struct arm64_ftr_bits *ftrp, s64 new, 6895e49d73cSArd Biesheuvel s64 cur) 6903c739b57SSuzuki K. Poulose { 6913c739b57SSuzuki K. Poulose s64 ret = 0; 6923c739b57SSuzuki K. Poulose 6933c739b57SSuzuki K. Poulose switch (ftrp->type) { 6943c739b57SSuzuki K. Poulose case FTR_EXACT: 6953c739b57SSuzuki K. Poulose ret = ftrp->safe_val; 6963c739b57SSuzuki K. Poulose break; 6973c739b57SSuzuki K. Poulose case FTR_LOWER_SAFE: 6983c739b57SSuzuki K. Poulose ret = new < cur ? new : cur; 6993c739b57SSuzuki K. Poulose break; 700147b9635SWill Deacon case FTR_HIGHER_OR_ZERO_SAFE: 701147b9635SWill Deacon if (!cur || !new) 702147b9635SWill Deacon break; 703df561f66SGustavo A. R. Silva fallthrough; 7043c739b57SSuzuki K. Poulose case FTR_HIGHER_SAFE: 7053c739b57SSuzuki K. Poulose ret = new > cur ? new : cur; 7063c739b57SSuzuki K. Poulose break; 7073c739b57SSuzuki K. Poulose default: 7083c739b57SSuzuki K. Poulose BUG(); 7093c739b57SSuzuki K. Poulose } 7103c739b57SSuzuki K. Poulose 7113c739b57SSuzuki K. Poulose return ret; 7123c739b57SSuzuki K. Poulose } 7133c739b57SSuzuki K. Poulose 7143c739b57SSuzuki K. Poulose static void __init sort_ftr_regs(void) 7153c739b57SSuzuki K. Poulose { 716c6c83d75SAnshuman Khandual unsigned int i; 7176f2b7eefSArd Biesheuvel 718c6c83d75SAnshuman Khandual for (i = 0; i < ARRAY_SIZE(arm64_ftr_regs); i++) { 719c6c83d75SAnshuman Khandual const struct arm64_ftr_reg *ftr_reg = arm64_ftr_regs[i].reg; 720c6c83d75SAnshuman Khandual const struct arm64_ftr_bits *ftr_bits = ftr_reg->ftr_bits; 721c6c83d75SAnshuman Khandual unsigned int j = 0; 722c6c83d75SAnshuman Khandual 723c6c83d75SAnshuman Khandual /* 724c6c83d75SAnshuman Khandual * Features here must be sorted in descending order with respect 725c6c83d75SAnshuman Khandual * to their shift values and should not overlap with each other. 726c6c83d75SAnshuman Khandual */ 727c6c83d75SAnshuman Khandual for (; ftr_bits->width != 0; ftr_bits++, j++) { 728c6c83d75SAnshuman Khandual unsigned int width = ftr_reg->ftr_bits[j].width; 729c6c83d75SAnshuman Khandual unsigned int shift = ftr_reg->ftr_bits[j].shift; 730c6c83d75SAnshuman Khandual unsigned int prev_shift; 731c6c83d75SAnshuman Khandual 732c6c83d75SAnshuman Khandual WARN((shift + width) > 64, 733c6c83d75SAnshuman Khandual "%s has invalid feature at shift %d\n", 734c6c83d75SAnshuman Khandual ftr_reg->name, shift); 735c6c83d75SAnshuman Khandual 736c6c83d75SAnshuman Khandual /* 737c6c83d75SAnshuman Khandual * Skip the first feature. There is nothing to 738c6c83d75SAnshuman Khandual * compare against for now. 739c6c83d75SAnshuman Khandual */ 740c6c83d75SAnshuman Khandual if (j == 0) 741c6c83d75SAnshuman Khandual continue; 742c6c83d75SAnshuman Khandual 743c6c83d75SAnshuman Khandual prev_shift = ftr_reg->ftr_bits[j - 1].shift; 744c6c83d75SAnshuman Khandual WARN((shift + width) > prev_shift, 745c6c83d75SAnshuman Khandual "%s has feature overlap at shift %d\n", 746c6c83d75SAnshuman Khandual ftr_reg->name, shift); 747c6c83d75SAnshuman Khandual } 748c6c83d75SAnshuman Khandual 749c6c83d75SAnshuman Khandual /* 750c6c83d75SAnshuman Khandual * Skip the first register. There is nothing to 751c6c83d75SAnshuman Khandual * compare against for now. 752c6c83d75SAnshuman Khandual */ 753c6c83d75SAnshuman Khandual if (i == 0) 754c6c83d75SAnshuman Khandual continue; 755c6c83d75SAnshuman Khandual /* 756c6c83d75SAnshuman Khandual * Registers here must be sorted in ascending order with respect 757c6c83d75SAnshuman Khandual * to sys_id for subsequent binary search in get_arm64_ftr_reg() 758c6c83d75SAnshuman Khandual * to work correctly. 759c6c83d75SAnshuman Khandual */ 7606f2b7eefSArd Biesheuvel BUG_ON(arm64_ftr_regs[i].sys_id < arm64_ftr_regs[i - 1].sys_id); 7613c739b57SSuzuki K. Poulose } 762c6c83d75SAnshuman Khandual } 7633c739b57SSuzuki K. Poulose 7643c739b57SSuzuki K. Poulose /* 7653c739b57SSuzuki K. Poulose * Initialise the CPU feature register from Boot CPU values. 7663c739b57SSuzuki K. Poulose * Also initiliases the strict_mask for the register. 767b389d799SMark Rutland * Any bits that are not covered by an arm64_ftr_bits entry are considered 768b389d799SMark Rutland * RES0 for the system-wide value, and must strictly match. 7693c739b57SSuzuki K. Poulose */ 7703c739b57SSuzuki K. Poulose static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new) 7713c739b57SSuzuki K. Poulose { 7723c739b57SSuzuki K. Poulose u64 val = 0; 7733c739b57SSuzuki K. Poulose u64 strict_mask = ~0x0ULL; 774fe4fbdbcSSuzuki K Poulose u64 user_mask = 0; 775b389d799SMark Rutland u64 valid_mask = 0; 776b389d799SMark Rutland 7775e49d73cSArd Biesheuvel const struct arm64_ftr_bits *ftrp; 7783c739b57SSuzuki K. Poulose struct arm64_ftr_reg *reg = get_arm64_ftr_reg(sys_reg); 7793c739b57SSuzuki K. Poulose 7803577dd37SAnshuman Khandual if (!reg) 7813577dd37SAnshuman Khandual return; 7823c739b57SSuzuki K. Poulose 7833c739b57SSuzuki K. Poulose for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) { 784b389d799SMark Rutland u64 ftr_mask = arm64_ftr_mask(ftrp); 7853c739b57SSuzuki K. Poulose s64 ftr_new = arm64_ftr_value(ftrp, new); 7868f266a5dSMarc Zyngier s64 ftr_ovr = arm64_ftr_value(ftrp, reg->override->val); 7878f266a5dSMarc Zyngier 7888f266a5dSMarc Zyngier if ((ftr_mask & reg->override->mask) == ftr_mask) { 7898f266a5dSMarc Zyngier s64 tmp = arm64_ftr_safe_value(ftrp, ftr_ovr, ftr_new); 7908f266a5dSMarc Zyngier char *str = NULL; 7918f266a5dSMarc Zyngier 7928f266a5dSMarc Zyngier if (ftr_ovr != tmp) { 7938f266a5dSMarc Zyngier /* Unsafe, remove the override */ 7948f266a5dSMarc Zyngier reg->override->mask &= ~ftr_mask; 7958f266a5dSMarc Zyngier reg->override->val &= ~ftr_mask; 7968f266a5dSMarc Zyngier tmp = ftr_ovr; 7978f266a5dSMarc Zyngier str = "ignoring override"; 7988f266a5dSMarc Zyngier } else if (ftr_new != tmp) { 7998f266a5dSMarc Zyngier /* Override was valid */ 8008f266a5dSMarc Zyngier ftr_new = tmp; 8018f266a5dSMarc Zyngier str = "forced"; 8028f266a5dSMarc Zyngier } else if (ftr_ovr == tmp) { 8038f266a5dSMarc Zyngier /* Override was the safe value */ 8048f266a5dSMarc Zyngier str = "already set"; 8058f266a5dSMarc Zyngier } 8068f266a5dSMarc Zyngier 8078f266a5dSMarc Zyngier if (str) 8088f266a5dSMarc Zyngier pr_warn("%s[%d:%d]: %s to %llx\n", 8098f266a5dSMarc Zyngier reg->name, 8108f266a5dSMarc Zyngier ftrp->shift + ftrp->width - 1, 8118f266a5dSMarc Zyngier ftrp->shift, str, tmp); 812*cac642c1SMarc Zyngier } else if ((ftr_mask & reg->override->val) == ftr_mask) { 813*cac642c1SMarc Zyngier reg->override->val &= ~ftr_mask; 814*cac642c1SMarc Zyngier pr_warn("%s[%d:%d]: impossible override, ignored\n", 815*cac642c1SMarc Zyngier reg->name, 816*cac642c1SMarc Zyngier ftrp->shift + ftrp->width - 1, 817*cac642c1SMarc Zyngier ftrp->shift); 8188f266a5dSMarc Zyngier } 8193c739b57SSuzuki K. Poulose 8203c739b57SSuzuki K. Poulose val = arm64_ftr_set_value(ftrp, val, ftr_new); 821b389d799SMark Rutland 822b389d799SMark Rutland valid_mask |= ftr_mask; 8233c739b57SSuzuki K. Poulose if (!ftrp->strict) 824b389d799SMark Rutland strict_mask &= ~ftr_mask; 825fe4fbdbcSSuzuki K Poulose if (ftrp->visible) 826fe4fbdbcSSuzuki K Poulose user_mask |= ftr_mask; 827fe4fbdbcSSuzuki K Poulose else 828fe4fbdbcSSuzuki K Poulose reg->user_val = arm64_ftr_set_value(ftrp, 829fe4fbdbcSSuzuki K Poulose reg->user_val, 830fe4fbdbcSSuzuki K Poulose ftrp->safe_val); 8313c739b57SSuzuki K. Poulose } 832b389d799SMark Rutland 833b389d799SMark Rutland val &= valid_mask; 834b389d799SMark Rutland 8353c739b57SSuzuki K. Poulose reg->sys_val = val; 8363c739b57SSuzuki K. Poulose reg->strict_mask = strict_mask; 837fe4fbdbcSSuzuki K Poulose reg->user_mask = user_mask; 8383c739b57SSuzuki K. Poulose } 8393c739b57SSuzuki K. Poulose 8401e89baedSSuzuki K Poulose extern const struct arm64_cpu_capabilities arm64_errata[]; 84182a3a21bSSuzuki K Poulose static const struct arm64_cpu_capabilities arm64_features[]; 84282a3a21bSSuzuki K Poulose 84382a3a21bSSuzuki K Poulose static void __init 84482a3a21bSSuzuki K Poulose init_cpu_hwcaps_indirect_list_from_array(const struct arm64_cpu_capabilities *caps) 84582a3a21bSSuzuki K Poulose { 84682a3a21bSSuzuki K Poulose for (; caps->matches; caps++) { 84782a3a21bSSuzuki K Poulose if (WARN(caps->capability >= ARM64_NCAPS, 84882a3a21bSSuzuki K Poulose "Invalid capability %d\n", caps->capability)) 84982a3a21bSSuzuki K Poulose continue; 85082a3a21bSSuzuki K Poulose if (WARN(cpu_hwcaps_ptrs[caps->capability], 85182a3a21bSSuzuki K Poulose "Duplicate entry for capability %d\n", 85282a3a21bSSuzuki K Poulose caps->capability)) 85382a3a21bSSuzuki K Poulose continue; 85482a3a21bSSuzuki K Poulose cpu_hwcaps_ptrs[caps->capability] = caps; 85582a3a21bSSuzuki K Poulose } 85682a3a21bSSuzuki K Poulose } 85782a3a21bSSuzuki K Poulose 85882a3a21bSSuzuki K Poulose static void __init init_cpu_hwcaps_indirect_list(void) 85982a3a21bSSuzuki K Poulose { 86082a3a21bSSuzuki K Poulose init_cpu_hwcaps_indirect_list_from_array(arm64_features); 86182a3a21bSSuzuki K Poulose init_cpu_hwcaps_indirect_list_from_array(arm64_errata); 86282a3a21bSSuzuki K Poulose } 86382a3a21bSSuzuki K Poulose 864fd9d63daSSuzuki K Poulose static void __init setup_boot_cpu_capabilities(void); 8651e89baedSSuzuki K Poulose 8663c739b57SSuzuki K. Poulose void __init init_cpu_features(struct cpuinfo_arm64 *info) 8673c739b57SSuzuki K. Poulose { 8683c739b57SSuzuki K. Poulose /* Before we start using the tables, make sure it is sorted */ 8693c739b57SSuzuki K. Poulose sort_ftr_regs(); 8703c739b57SSuzuki K. Poulose 8713c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_CTR_EL0, info->reg_ctr); 8723c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_DCZID_EL0, info->reg_dczid); 8733c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_CNTFRQ_EL0, info->reg_cntfrq); 8743c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_AA64DFR0_EL1, info->reg_id_aa64dfr0); 8753c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_AA64DFR1_EL1, info->reg_id_aa64dfr1); 8763c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_AA64ISAR0_EL1, info->reg_id_aa64isar0); 8773c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_AA64ISAR1_EL1, info->reg_id_aa64isar1); 8783c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_AA64MMFR0_EL1, info->reg_id_aa64mmfr0); 8793c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_AA64MMFR1_EL1, info->reg_id_aa64mmfr1); 880406e3087SJames Morse init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2); 8813c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_AA64PFR0_EL1, info->reg_id_aa64pfr0); 8823c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_AA64PFR1_EL1, info->reg_id_aa64pfr1); 8832e0f2478SDave Martin init_cpu_ftr_reg(SYS_ID_AA64ZFR0_EL1, info->reg_id_aa64zfr0); 884a6dc3cd7SSuzuki K Poulose 885a6dc3cd7SSuzuki K Poulose if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) { 8863c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_DFR0_EL1, info->reg_id_dfr0); 887dd35ec07SAnshuman Khandual init_cpu_ftr_reg(SYS_ID_DFR1_EL1, info->reg_id_dfr1); 8883c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_ISAR0_EL1, info->reg_id_isar0); 8893c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_ISAR1_EL1, info->reg_id_isar1); 8903c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_ISAR2_EL1, info->reg_id_isar2); 8913c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_ISAR3_EL1, info->reg_id_isar3); 8923c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_ISAR4_EL1, info->reg_id_isar4); 8933c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_ISAR5_EL1, info->reg_id_isar5); 8948e3747beSAnshuman Khandual init_cpu_ftr_reg(SYS_ID_ISAR6_EL1, info->reg_id_isar6); 8953c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_MMFR0_EL1, info->reg_id_mmfr0); 8963c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_MMFR1_EL1, info->reg_id_mmfr1); 8973c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_MMFR2_EL1, info->reg_id_mmfr2); 8983c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_MMFR3_EL1, info->reg_id_mmfr3); 899858b8a80SAnshuman Khandual init_cpu_ftr_reg(SYS_ID_MMFR4_EL1, info->reg_id_mmfr4); 900152accf8SAnshuman Khandual init_cpu_ftr_reg(SYS_ID_MMFR5_EL1, info->reg_id_mmfr5); 9013c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_PFR0_EL1, info->reg_id_pfr0); 9023c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_ID_PFR1_EL1, info->reg_id_pfr1); 90316824085SAnshuman Khandual init_cpu_ftr_reg(SYS_ID_PFR2_EL1, info->reg_id_pfr2); 9043c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_MVFR0_EL1, info->reg_mvfr0); 9053c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_MVFR1_EL1, info->reg_mvfr1); 9063c739b57SSuzuki K. Poulose init_cpu_ftr_reg(SYS_MVFR2_EL1, info->reg_mvfr2); 9073c739b57SSuzuki K. Poulose } 9083c739b57SSuzuki K. Poulose 9092e0f2478SDave Martin if (id_aa64pfr0_sve(info->reg_id_aa64pfr0)) { 9102e0f2478SDave Martin init_cpu_ftr_reg(SYS_ZCR_EL1, info->reg_zcr); 9112e0f2478SDave Martin sve_init_vq_map(); 9122e0f2478SDave Martin } 9135e91107bSSuzuki K Poulose 9145e91107bSSuzuki K Poulose /* 91582a3a21bSSuzuki K Poulose * Initialize the indirect array of CPU hwcaps capabilities pointers 91682a3a21bSSuzuki K Poulose * before we handle the boot CPU below. 91782a3a21bSSuzuki K Poulose */ 91882a3a21bSSuzuki K Poulose init_cpu_hwcaps_indirect_list(); 91982a3a21bSSuzuki K Poulose 92082a3a21bSSuzuki K Poulose /* 921fd9d63daSSuzuki K Poulose * Detect and enable early CPU capabilities based on the boot CPU, 922fd9d63daSSuzuki K Poulose * after we have initialised the CPU feature infrastructure. 9235e91107bSSuzuki K Poulose */ 924fd9d63daSSuzuki K Poulose setup_boot_cpu_capabilities(); 925a6dc3cd7SSuzuki K Poulose } 926a6dc3cd7SSuzuki K Poulose 9273086d391SSuzuki K. Poulose static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new) 9283c739b57SSuzuki K. Poulose { 9295e49d73cSArd Biesheuvel const struct arm64_ftr_bits *ftrp; 9303c739b57SSuzuki K. Poulose 9313c739b57SSuzuki K. Poulose for (ftrp = reg->ftr_bits; ftrp->width; ftrp++) { 9323c739b57SSuzuki K. Poulose s64 ftr_cur = arm64_ftr_value(ftrp, reg->sys_val); 9333c739b57SSuzuki K. Poulose s64 ftr_new = arm64_ftr_value(ftrp, new); 9343c739b57SSuzuki K. Poulose 9353c739b57SSuzuki K. Poulose if (ftr_cur == ftr_new) 9363c739b57SSuzuki K. Poulose continue; 9373c739b57SSuzuki K. Poulose /* Find a safe value */ 9383c739b57SSuzuki K. Poulose ftr_new = arm64_ftr_safe_value(ftrp, ftr_new, ftr_cur); 9393c739b57SSuzuki K. Poulose reg->sys_val = arm64_ftr_set_value(ftrp, reg->sys_val, ftr_new); 9403c739b57SSuzuki K. Poulose } 9413c739b57SSuzuki K. Poulose 9423c739b57SSuzuki K. Poulose } 9433c739b57SSuzuki K. Poulose 9443086d391SSuzuki K. Poulose static int check_update_ftr_reg(u32 sys_id, int cpu, u64 val, u64 boot) 945cdcf817bSSuzuki K. Poulose { 9463086d391SSuzuki K. Poulose struct arm64_ftr_reg *regp = get_arm64_ftr_reg(sys_id); 9473086d391SSuzuki K. Poulose 9483577dd37SAnshuman Khandual if (!regp) 9493577dd37SAnshuman Khandual return 0; 9503577dd37SAnshuman Khandual 9513086d391SSuzuki K. Poulose update_cpu_ftr_reg(regp, val); 9523086d391SSuzuki K. Poulose if ((boot & regp->strict_mask) == (val & regp->strict_mask)) 9533086d391SSuzuki K. Poulose return 0; 9543086d391SSuzuki K. Poulose pr_warn("SANITY CHECK: Unexpected variation in %s. Boot CPU: %#016llx, CPU%d: %#016llx\n", 9553086d391SSuzuki K. Poulose regp->name, boot, cpu, val); 9563086d391SSuzuki K. Poulose return 1; 9573086d391SSuzuki K. Poulose } 9583086d391SSuzuki K. Poulose 959eab2f926SWill Deacon static void relax_cpu_ftr_reg(u32 sys_id, int field) 960eab2f926SWill Deacon { 961eab2f926SWill Deacon const struct arm64_ftr_bits *ftrp; 962eab2f926SWill Deacon struct arm64_ftr_reg *regp = get_arm64_ftr_reg(sys_id); 963eab2f926SWill Deacon 9643577dd37SAnshuman Khandual if (!regp) 965eab2f926SWill Deacon return; 966eab2f926SWill Deacon 967eab2f926SWill Deacon for (ftrp = regp->ftr_bits; ftrp->width; ftrp++) { 968eab2f926SWill Deacon if (ftrp->shift == field) { 969eab2f926SWill Deacon regp->strict_mask &= ~arm64_ftr_mask(ftrp); 970eab2f926SWill Deacon break; 971eab2f926SWill Deacon } 972eab2f926SWill Deacon } 973eab2f926SWill Deacon 974eab2f926SWill Deacon /* Bogus field? */ 975eab2f926SWill Deacon WARN_ON(!ftrp->width); 976eab2f926SWill Deacon } 977eab2f926SWill Deacon 9781efcfe79SWill Deacon static int update_32bit_cpu_features(int cpu, struct cpuinfo_arm64 *info, 9791efcfe79SWill Deacon struct cpuinfo_arm64 *boot) 9801efcfe79SWill Deacon { 9811efcfe79SWill Deacon int taint = 0; 9821efcfe79SWill Deacon u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1); 9831efcfe79SWill Deacon 9841efcfe79SWill Deacon /* 9851efcfe79SWill Deacon * If we don't have AArch32 at all then skip the checks entirely 9861efcfe79SWill Deacon * as the register values may be UNKNOWN and we're not going to be 9871efcfe79SWill Deacon * using them for anything. 9881efcfe79SWill Deacon */ 9891efcfe79SWill Deacon if (!id_aa64pfr0_32bit_el0(pfr0)) 9901efcfe79SWill Deacon return taint; 9911efcfe79SWill Deacon 992eab2f926SWill Deacon /* 993eab2f926SWill Deacon * If we don't have AArch32 at EL1, then relax the strictness of 994eab2f926SWill Deacon * EL1-dependent register fields to avoid spurious sanity check fails. 995eab2f926SWill Deacon */ 996eab2f926SWill Deacon if (!id_aa64pfr0_32bit_el1(pfr0)) { 997eab2f926SWill Deacon relax_cpu_ftr_reg(SYS_ID_ISAR4_EL1, ID_ISAR4_SMC_SHIFT); 998eab2f926SWill Deacon relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_VIRT_FRAC_SHIFT); 999eab2f926SWill Deacon relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_SEC_FRAC_SHIFT); 1000eab2f926SWill Deacon relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_VIRTUALIZATION_SHIFT); 1001eab2f926SWill Deacon relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_SECURITY_SHIFT); 1002eab2f926SWill Deacon relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_PROGMOD_SHIFT); 1003eab2f926SWill Deacon } 1004eab2f926SWill Deacon 10051efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_DFR0_EL1, cpu, 10061efcfe79SWill Deacon info->reg_id_dfr0, boot->reg_id_dfr0); 1007dd35ec07SAnshuman Khandual taint |= check_update_ftr_reg(SYS_ID_DFR1_EL1, cpu, 1008dd35ec07SAnshuman Khandual info->reg_id_dfr1, boot->reg_id_dfr1); 10091efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_ISAR0_EL1, cpu, 10101efcfe79SWill Deacon info->reg_id_isar0, boot->reg_id_isar0); 10111efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_ISAR1_EL1, cpu, 10121efcfe79SWill Deacon info->reg_id_isar1, boot->reg_id_isar1); 10131efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_ISAR2_EL1, cpu, 10141efcfe79SWill Deacon info->reg_id_isar2, boot->reg_id_isar2); 10151efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_ISAR3_EL1, cpu, 10161efcfe79SWill Deacon info->reg_id_isar3, boot->reg_id_isar3); 10171efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_ISAR4_EL1, cpu, 10181efcfe79SWill Deacon info->reg_id_isar4, boot->reg_id_isar4); 10191efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_ISAR5_EL1, cpu, 10201efcfe79SWill Deacon info->reg_id_isar5, boot->reg_id_isar5); 10211efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_ISAR6_EL1, cpu, 10221efcfe79SWill Deacon info->reg_id_isar6, boot->reg_id_isar6); 10231efcfe79SWill Deacon 10241efcfe79SWill Deacon /* 10251efcfe79SWill Deacon * Regardless of the value of the AuxReg field, the AIFSR, ADFSR, and 10261efcfe79SWill Deacon * ACTLR formats could differ across CPUs and therefore would have to 10271efcfe79SWill Deacon * be trapped for virtualization anyway. 10281efcfe79SWill Deacon */ 10291efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_MMFR0_EL1, cpu, 10301efcfe79SWill Deacon info->reg_id_mmfr0, boot->reg_id_mmfr0); 10311efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_MMFR1_EL1, cpu, 10321efcfe79SWill Deacon info->reg_id_mmfr1, boot->reg_id_mmfr1); 10331efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_MMFR2_EL1, cpu, 10341efcfe79SWill Deacon info->reg_id_mmfr2, boot->reg_id_mmfr2); 10351efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_MMFR3_EL1, cpu, 10361efcfe79SWill Deacon info->reg_id_mmfr3, boot->reg_id_mmfr3); 1037858b8a80SAnshuman Khandual taint |= check_update_ftr_reg(SYS_ID_MMFR4_EL1, cpu, 1038858b8a80SAnshuman Khandual info->reg_id_mmfr4, boot->reg_id_mmfr4); 1039152accf8SAnshuman Khandual taint |= check_update_ftr_reg(SYS_ID_MMFR5_EL1, cpu, 1040152accf8SAnshuman Khandual info->reg_id_mmfr5, boot->reg_id_mmfr5); 10411efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_PFR0_EL1, cpu, 10421efcfe79SWill Deacon info->reg_id_pfr0, boot->reg_id_pfr0); 10431efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_ID_PFR1_EL1, cpu, 10441efcfe79SWill Deacon info->reg_id_pfr1, boot->reg_id_pfr1); 104516824085SAnshuman Khandual taint |= check_update_ftr_reg(SYS_ID_PFR2_EL1, cpu, 104616824085SAnshuman Khandual info->reg_id_pfr2, boot->reg_id_pfr2); 10471efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_MVFR0_EL1, cpu, 10481efcfe79SWill Deacon info->reg_mvfr0, boot->reg_mvfr0); 10491efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_MVFR1_EL1, cpu, 10501efcfe79SWill Deacon info->reg_mvfr1, boot->reg_mvfr1); 10511efcfe79SWill Deacon taint |= check_update_ftr_reg(SYS_MVFR2_EL1, cpu, 10521efcfe79SWill Deacon info->reg_mvfr2, boot->reg_mvfr2); 10531efcfe79SWill Deacon 10541efcfe79SWill Deacon return taint; 10551efcfe79SWill Deacon } 10561efcfe79SWill Deacon 10573086d391SSuzuki K. Poulose /* 10583086d391SSuzuki K. Poulose * Update system wide CPU feature registers with the values from a 10593086d391SSuzuki K. Poulose * non-boot CPU. Also performs SANITY checks to make sure that there 10603086d391SSuzuki K. Poulose * aren't any insane variations from that of the boot CPU. 10613086d391SSuzuki K. Poulose */ 10623086d391SSuzuki K. Poulose void update_cpu_features(int cpu, 10633086d391SSuzuki K. Poulose struct cpuinfo_arm64 *info, 10643086d391SSuzuki K. Poulose struct cpuinfo_arm64 *boot) 10653086d391SSuzuki K. Poulose { 10663086d391SSuzuki K. Poulose int taint = 0; 10673086d391SSuzuki K. Poulose 10683086d391SSuzuki K. Poulose /* 10693086d391SSuzuki K. Poulose * The kernel can handle differing I-cache policies, but otherwise 10703086d391SSuzuki K. Poulose * caches should look identical. Userspace JITs will make use of 10713086d391SSuzuki K. Poulose * *minLine. 10723086d391SSuzuki K. Poulose */ 10733086d391SSuzuki K. Poulose taint |= check_update_ftr_reg(SYS_CTR_EL0, cpu, 10743086d391SSuzuki K. Poulose info->reg_ctr, boot->reg_ctr); 10753086d391SSuzuki K. Poulose 10763086d391SSuzuki K. Poulose /* 10773086d391SSuzuki K. Poulose * Userspace may perform DC ZVA instructions. Mismatched block sizes 10783086d391SSuzuki K. Poulose * could result in too much or too little memory being zeroed if a 10793086d391SSuzuki K. Poulose * process is preempted and migrated between CPUs. 10803086d391SSuzuki K. Poulose */ 10813086d391SSuzuki K. Poulose taint |= check_update_ftr_reg(SYS_DCZID_EL0, cpu, 10823086d391SSuzuki K. Poulose info->reg_dczid, boot->reg_dczid); 10833086d391SSuzuki K. Poulose 10843086d391SSuzuki K. Poulose /* If different, timekeeping will be broken (especially with KVM) */ 10853086d391SSuzuki K. Poulose taint |= check_update_ftr_reg(SYS_CNTFRQ_EL0, cpu, 10863086d391SSuzuki K. Poulose info->reg_cntfrq, boot->reg_cntfrq); 10873086d391SSuzuki K. Poulose 10883086d391SSuzuki K. Poulose /* 10893086d391SSuzuki K. Poulose * The kernel uses self-hosted debug features and expects CPUs to 10903086d391SSuzuki K. Poulose * support identical debug features. We presently need CTX_CMPs, WRPs, 10913086d391SSuzuki K. Poulose * and BRPs to be identical. 10923086d391SSuzuki K. Poulose * ID_AA64DFR1 is currently RES0. 10933086d391SSuzuki K. Poulose */ 10943086d391SSuzuki K. Poulose taint |= check_update_ftr_reg(SYS_ID_AA64DFR0_EL1, cpu, 10953086d391SSuzuki K. Poulose info->reg_id_aa64dfr0, boot->reg_id_aa64dfr0); 10963086d391SSuzuki K. Poulose taint |= check_update_ftr_reg(SYS_ID_AA64DFR1_EL1, cpu, 10973086d391SSuzuki K. Poulose info->reg_id_aa64dfr1, boot->reg_id_aa64dfr1); 10983086d391SSuzuki K. Poulose /* 10993086d391SSuzuki K. Poulose * Even in big.LITTLE, processors should be identical instruction-set 11003086d391SSuzuki K. Poulose * wise. 11013086d391SSuzuki K. Poulose */ 11023086d391SSuzuki K. Poulose taint |= check_update_ftr_reg(SYS_ID_AA64ISAR0_EL1, cpu, 11033086d391SSuzuki K. Poulose info->reg_id_aa64isar0, boot->reg_id_aa64isar0); 11043086d391SSuzuki K. Poulose taint |= check_update_ftr_reg(SYS_ID_AA64ISAR1_EL1, cpu, 11053086d391SSuzuki K. Poulose info->reg_id_aa64isar1, boot->reg_id_aa64isar1); 11063086d391SSuzuki K. Poulose 11073086d391SSuzuki K. Poulose /* 11083086d391SSuzuki K. Poulose * Differing PARange support is fine as long as all peripherals and 11093086d391SSuzuki K. Poulose * memory are mapped within the minimum PARange of all CPUs. 11103086d391SSuzuki K. Poulose * Linux should not care about secure memory. 11113086d391SSuzuki K. Poulose */ 11123086d391SSuzuki K. Poulose taint |= check_update_ftr_reg(SYS_ID_AA64MMFR0_EL1, cpu, 11133086d391SSuzuki K. Poulose info->reg_id_aa64mmfr0, boot->reg_id_aa64mmfr0); 11143086d391SSuzuki K. Poulose taint |= check_update_ftr_reg(SYS_ID_AA64MMFR1_EL1, cpu, 11153086d391SSuzuki K. Poulose info->reg_id_aa64mmfr1, boot->reg_id_aa64mmfr1); 1116406e3087SJames Morse taint |= check_update_ftr_reg(SYS_ID_AA64MMFR2_EL1, cpu, 1117406e3087SJames Morse info->reg_id_aa64mmfr2, boot->reg_id_aa64mmfr2); 11183086d391SSuzuki K. Poulose 11193086d391SSuzuki K. Poulose taint |= check_update_ftr_reg(SYS_ID_AA64PFR0_EL1, cpu, 11203086d391SSuzuki K. Poulose info->reg_id_aa64pfr0, boot->reg_id_aa64pfr0); 11213086d391SSuzuki K. Poulose taint |= check_update_ftr_reg(SYS_ID_AA64PFR1_EL1, cpu, 11223086d391SSuzuki K. Poulose info->reg_id_aa64pfr1, boot->reg_id_aa64pfr1); 11233086d391SSuzuki K. Poulose 11242e0f2478SDave Martin taint |= check_update_ftr_reg(SYS_ID_AA64ZFR0_EL1, cpu, 11252e0f2478SDave Martin info->reg_id_aa64zfr0, boot->reg_id_aa64zfr0); 11262e0f2478SDave Martin 11272e0f2478SDave Martin if (id_aa64pfr0_sve(info->reg_id_aa64pfr0)) { 11282e0f2478SDave Martin taint |= check_update_ftr_reg(SYS_ZCR_EL1, cpu, 11292e0f2478SDave Martin info->reg_zcr, boot->reg_zcr); 11302e0f2478SDave Martin 11312e0f2478SDave Martin /* Probe vector lengths, unless we already gave up on SVE */ 11322e0f2478SDave Martin if (id_aa64pfr0_sve(read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1)) && 1133b51c6ac2SSuzuki K Poulose !system_capabilities_finalized()) 11342e0f2478SDave Martin sve_update_vq_map(); 11352e0f2478SDave Martin } 11362e0f2478SDave Martin 11373086d391SSuzuki K. Poulose /* 11381efcfe79SWill Deacon * This relies on a sanitised view of the AArch64 ID registers 11391efcfe79SWill Deacon * (e.g. SYS_ID_AA64PFR0_EL1), so we call it last. 11401efcfe79SWill Deacon */ 11411efcfe79SWill Deacon taint |= update_32bit_cpu_features(cpu, info, boot); 11421efcfe79SWill Deacon 11431efcfe79SWill Deacon /* 11443086d391SSuzuki K. Poulose * Mismatched CPU features are a recipe for disaster. Don't even 11453086d391SSuzuki K. Poulose * pretend to support them. 11463086d391SSuzuki K. Poulose */ 11478dd0ee65SWill Deacon if (taint) { 11483fde2999SWill Deacon pr_warn_once("Unsupported CPU feature variation detected.\n"); 11493fde2999SWill Deacon add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK); 1150cdcf817bSSuzuki K. Poulose } 11518dd0ee65SWill Deacon } 1152cdcf817bSSuzuki K. Poulose 115346823dd1SDave Martin u64 read_sanitised_ftr_reg(u32 id) 1154b3f15378SSuzuki K. Poulose { 1155b3f15378SSuzuki K. Poulose struct arm64_ftr_reg *regp = get_arm64_ftr_reg(id); 1156b3f15378SSuzuki K. Poulose 11573577dd37SAnshuman Khandual if (!regp) 11583577dd37SAnshuman Khandual return 0; 1159b3f15378SSuzuki K. Poulose return regp->sys_val; 1160b3f15378SSuzuki K. Poulose } 11616f3c4afaSJean-Philippe Brucker EXPORT_SYMBOL_GPL(read_sanitised_ftr_reg); 1162359b7064SMarc Zyngier 1163965861d6SMark Rutland #define read_sysreg_case(r) \ 1164b3341ae0SMarc Zyngier case r: val = read_sysreg_s(r); break; 1165965861d6SMark Rutland 116692406f0cSSuzuki K Poulose /* 116746823dd1SDave Martin * __read_sysreg_by_encoding() - Used by a STARTING cpu before cpuinfo is populated. 116892406f0cSSuzuki K Poulose * Read the system register on the current CPU 116992406f0cSSuzuki K Poulose */ 1170b3341ae0SMarc Zyngier u64 __read_sysreg_by_encoding(u32 sys_id) 117192406f0cSSuzuki K Poulose { 1172b3341ae0SMarc Zyngier struct arm64_ftr_reg *regp; 1173b3341ae0SMarc Zyngier u64 val; 1174b3341ae0SMarc Zyngier 117592406f0cSSuzuki K Poulose switch (sys_id) { 1176965861d6SMark Rutland read_sysreg_case(SYS_ID_PFR0_EL1); 1177965861d6SMark Rutland read_sysreg_case(SYS_ID_PFR1_EL1); 117816824085SAnshuman Khandual read_sysreg_case(SYS_ID_PFR2_EL1); 1179965861d6SMark Rutland read_sysreg_case(SYS_ID_DFR0_EL1); 1180dd35ec07SAnshuman Khandual read_sysreg_case(SYS_ID_DFR1_EL1); 1181965861d6SMark Rutland read_sysreg_case(SYS_ID_MMFR0_EL1); 1182965861d6SMark Rutland read_sysreg_case(SYS_ID_MMFR1_EL1); 1183965861d6SMark Rutland read_sysreg_case(SYS_ID_MMFR2_EL1); 1184965861d6SMark Rutland read_sysreg_case(SYS_ID_MMFR3_EL1); 1185858b8a80SAnshuman Khandual read_sysreg_case(SYS_ID_MMFR4_EL1); 1186152accf8SAnshuman Khandual read_sysreg_case(SYS_ID_MMFR5_EL1); 1187965861d6SMark Rutland read_sysreg_case(SYS_ID_ISAR0_EL1); 1188965861d6SMark Rutland read_sysreg_case(SYS_ID_ISAR1_EL1); 1189965861d6SMark Rutland read_sysreg_case(SYS_ID_ISAR2_EL1); 1190965861d6SMark Rutland read_sysreg_case(SYS_ID_ISAR3_EL1); 1191965861d6SMark Rutland read_sysreg_case(SYS_ID_ISAR4_EL1); 1192965861d6SMark Rutland read_sysreg_case(SYS_ID_ISAR5_EL1); 11938e3747beSAnshuman Khandual read_sysreg_case(SYS_ID_ISAR6_EL1); 1194965861d6SMark Rutland read_sysreg_case(SYS_MVFR0_EL1); 1195965861d6SMark Rutland read_sysreg_case(SYS_MVFR1_EL1); 1196965861d6SMark Rutland read_sysreg_case(SYS_MVFR2_EL1); 119792406f0cSSuzuki K Poulose 1198965861d6SMark Rutland read_sysreg_case(SYS_ID_AA64PFR0_EL1); 1199965861d6SMark Rutland read_sysreg_case(SYS_ID_AA64PFR1_EL1); 120078ed70bfSDave Martin read_sysreg_case(SYS_ID_AA64ZFR0_EL1); 1201965861d6SMark Rutland read_sysreg_case(SYS_ID_AA64DFR0_EL1); 1202965861d6SMark Rutland read_sysreg_case(SYS_ID_AA64DFR1_EL1); 1203965861d6SMark Rutland read_sysreg_case(SYS_ID_AA64MMFR0_EL1); 1204965861d6SMark Rutland read_sysreg_case(SYS_ID_AA64MMFR1_EL1); 1205965861d6SMark Rutland read_sysreg_case(SYS_ID_AA64MMFR2_EL1); 1206965861d6SMark Rutland read_sysreg_case(SYS_ID_AA64ISAR0_EL1); 1207965861d6SMark Rutland read_sysreg_case(SYS_ID_AA64ISAR1_EL1); 120892406f0cSSuzuki K Poulose 1209965861d6SMark Rutland read_sysreg_case(SYS_CNTFRQ_EL0); 1210965861d6SMark Rutland read_sysreg_case(SYS_CTR_EL0); 1211965861d6SMark Rutland read_sysreg_case(SYS_DCZID_EL0); 1212965861d6SMark Rutland 121392406f0cSSuzuki K Poulose default: 121492406f0cSSuzuki K Poulose BUG(); 121592406f0cSSuzuki K Poulose return 0; 121692406f0cSSuzuki K Poulose } 1217b3341ae0SMarc Zyngier 1218b3341ae0SMarc Zyngier regp = get_arm64_ftr_reg(sys_id); 1219b3341ae0SMarc Zyngier if (regp) { 1220b3341ae0SMarc Zyngier val &= ~regp->override->mask; 1221b3341ae0SMarc Zyngier val |= (regp->override->val & regp->override->mask); 1222b3341ae0SMarc Zyngier } 1223b3341ae0SMarc Zyngier 1224b3341ae0SMarc Zyngier return val; 122592406f0cSSuzuki K Poulose } 122692406f0cSSuzuki K Poulose 1227963fcd40SMarc Zyngier #include <linux/irqchip/arm-gic-v3.h> 1228963fcd40SMarc Zyngier 122994a9e04aSMarc Zyngier static bool 123018ffa046SJames Morse feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry) 123118ffa046SJames Morse { 123228c5dcb2SSuzuki K Poulose int val = cpuid_feature_extract_field(reg, entry->field_pos, entry->sign); 123318ffa046SJames Morse 123418ffa046SJames Morse return val >= entry->min_field_value; 123518ffa046SJames Morse } 123618ffa046SJames Morse 1237da8d02d1SSuzuki K. Poulose static bool 123892406f0cSSuzuki K Poulose has_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope) 1239da8d02d1SSuzuki K. Poulose { 1240da8d02d1SSuzuki K. Poulose u64 val; 124194a9e04aSMarc Zyngier 124292406f0cSSuzuki K Poulose WARN_ON(scope == SCOPE_LOCAL_CPU && preemptible()); 124392406f0cSSuzuki K Poulose if (scope == SCOPE_SYSTEM) 124446823dd1SDave Martin val = read_sanitised_ftr_reg(entry->sys_reg); 124592406f0cSSuzuki K Poulose else 124646823dd1SDave Martin val = __read_sysreg_by_encoding(entry->sys_reg); 124792406f0cSSuzuki K Poulose 1248da8d02d1SSuzuki K. Poulose return feature_matches(val, entry); 1249da8d02d1SSuzuki K. Poulose } 1250338d4f49SJames Morse 125192406f0cSSuzuki K Poulose static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry, int scope) 1252963fcd40SMarc Zyngier { 1253963fcd40SMarc Zyngier bool has_sre; 1254963fcd40SMarc Zyngier 125592406f0cSSuzuki K Poulose if (!has_cpuid_feature(entry, scope)) 1256963fcd40SMarc Zyngier return false; 1257963fcd40SMarc Zyngier 1258963fcd40SMarc Zyngier has_sre = gic_enable_sre(); 1259963fcd40SMarc Zyngier if (!has_sre) 1260963fcd40SMarc Zyngier pr_warn_once("%s present but disabled by higher exception level\n", 1261963fcd40SMarc Zyngier entry->desc); 1262963fcd40SMarc Zyngier 1263963fcd40SMarc Zyngier return has_sre; 1264963fcd40SMarc Zyngier } 1265963fcd40SMarc Zyngier 126692406f0cSSuzuki K Poulose static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry, int __unused) 1267d5370f75SWill Deacon { 1268d5370f75SWill Deacon u32 midr = read_cpuid_id(); 1269d5370f75SWill Deacon 1270d5370f75SWill Deacon /* Cavium ThunderX pass 1.x and 2.x */ 1271b99286b0SQian Cai return midr_is_cpu_model_range(midr, MIDR_THUNDERX, 1272fa5ce3d1SRobert Richter MIDR_CPU_VAR_REV(0, 0), 1273fa5ce3d1SRobert Richter MIDR_CPU_VAR_REV(1, MIDR_REVISION_MASK)); 1274d5370f75SWill Deacon } 1275d5370f75SWill Deacon 127682e0191aSSuzuki K Poulose static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unused) 127782e0191aSSuzuki K Poulose { 127846823dd1SDave Martin u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1); 127982e0191aSSuzuki K Poulose 128082e0191aSSuzuki K Poulose return cpuid_feature_extract_signed_field(pfr0, 128182e0191aSSuzuki K Poulose ID_AA64PFR0_FP_SHIFT) < 0; 128282e0191aSSuzuki K Poulose } 128382e0191aSSuzuki K Poulose 12846ae4b6e0SShanker Donthineni static bool has_cache_idc(const struct arm64_cpu_capabilities *entry, 12858ab66cbeSSuzuki K Poulose int scope) 12866ae4b6e0SShanker Donthineni { 12878ab66cbeSSuzuki K Poulose u64 ctr; 12888ab66cbeSSuzuki K Poulose 12898ab66cbeSSuzuki K Poulose if (scope == SCOPE_SYSTEM) 12908ab66cbeSSuzuki K Poulose ctr = arm64_ftr_reg_ctrel0.sys_val; 12918ab66cbeSSuzuki K Poulose else 12921602df02SSuzuki K Poulose ctr = read_cpuid_effective_cachetype(); 12938ab66cbeSSuzuki K Poulose 12948ab66cbeSSuzuki K Poulose return ctr & BIT(CTR_IDC_SHIFT); 12956ae4b6e0SShanker Donthineni } 12966ae4b6e0SShanker Donthineni 12971602df02SSuzuki K Poulose static void cpu_emulate_effective_ctr(const struct arm64_cpu_capabilities *__unused) 12981602df02SSuzuki K Poulose { 12991602df02SSuzuki K Poulose /* 13001602df02SSuzuki K Poulose * If the CPU exposes raw CTR_EL0.IDC = 0, while effectively 13011602df02SSuzuki K Poulose * CTR_EL0.IDC = 1 (from CLIDR values), we need to trap accesses 13021602df02SSuzuki K Poulose * to the CTR_EL0 on this CPU and emulate it with the real/safe 13031602df02SSuzuki K Poulose * value. 13041602df02SSuzuki K Poulose */ 13051602df02SSuzuki K Poulose if (!(read_cpuid_cachetype() & BIT(CTR_IDC_SHIFT))) 13061602df02SSuzuki K Poulose sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCT, 0); 13071602df02SSuzuki K Poulose } 13081602df02SSuzuki K Poulose 13096ae4b6e0SShanker Donthineni static bool has_cache_dic(const struct arm64_cpu_capabilities *entry, 13108ab66cbeSSuzuki K Poulose int scope) 13116ae4b6e0SShanker Donthineni { 13128ab66cbeSSuzuki K Poulose u64 ctr; 13138ab66cbeSSuzuki K Poulose 13148ab66cbeSSuzuki K Poulose if (scope == SCOPE_SYSTEM) 13158ab66cbeSSuzuki K Poulose ctr = arm64_ftr_reg_ctrel0.sys_val; 13168ab66cbeSSuzuki K Poulose else 13178ab66cbeSSuzuki K Poulose ctr = read_cpuid_cachetype(); 13188ab66cbeSSuzuki K Poulose 13198ab66cbeSSuzuki K Poulose return ctr & BIT(CTR_DIC_SHIFT); 13206ae4b6e0SShanker Donthineni } 13216ae4b6e0SShanker Donthineni 13225ffdfaedSVladimir Murzin static bool __maybe_unused 13235ffdfaedSVladimir Murzin has_useable_cnp(const struct arm64_cpu_capabilities *entry, int scope) 13245ffdfaedSVladimir Murzin { 13255ffdfaedSVladimir Murzin /* 13265ffdfaedSVladimir Murzin * Kdump isn't guaranteed to power-off all secondary CPUs, CNP 13275ffdfaedSVladimir Murzin * may share TLB entries with a CPU stuck in the crashed 13285ffdfaedSVladimir Murzin * kernel. 13295ffdfaedSVladimir Murzin */ 13305ffdfaedSVladimir Murzin if (is_kdump_kernel()) 13315ffdfaedSVladimir Murzin return false; 13325ffdfaedSVladimir Murzin 13335ffdfaedSVladimir Murzin return has_cpuid_feature(entry, scope); 13345ffdfaedSVladimir Murzin } 13355ffdfaedSVladimir Murzin 133609e3c22aSMark Brown /* 133709e3c22aSMark Brown * This check is triggered during the early boot before the cpufeature 133809e3c22aSMark Brown * is initialised. Checking the status on the local CPU allows the boot 133909e3c22aSMark Brown * CPU to detect the need for non-global mappings and thus avoiding a 134009e3c22aSMark Brown * pagetable re-write after all the CPUs are booted. This check will be 134109e3c22aSMark Brown * anyway run on individual CPUs, allowing us to get the consistent 134209e3c22aSMark Brown * state once the SMP CPUs are up and thus make the switch to non-global 134309e3c22aSMark Brown * mappings if required. 134409e3c22aSMark Brown */ 134509e3c22aSMark Brown bool kaslr_requires_kpti(void) 134609e3c22aSMark Brown { 134709e3c22aSMark Brown if (!IS_ENABLED(CONFIG_RANDOMIZE_BASE)) 134809e3c22aSMark Brown return false; 134909e3c22aSMark Brown 135009e3c22aSMark Brown /* 135109e3c22aSMark Brown * E0PD does a similar job to KPTI so can be used instead 135209e3c22aSMark Brown * where available. 135309e3c22aSMark Brown */ 135409e3c22aSMark Brown if (IS_ENABLED(CONFIG_ARM64_E0PD)) { 1355a569f5f3SWill Deacon u64 mmfr2 = read_sysreg_s(SYS_ID_AA64MMFR2_EL1); 1356a569f5f3SWill Deacon if (cpuid_feature_extract_unsigned_field(mmfr2, 1357a569f5f3SWill Deacon ID_AA64MMFR2_E0PD_SHIFT)) 135809e3c22aSMark Brown return false; 135909e3c22aSMark Brown } 136009e3c22aSMark Brown 136109e3c22aSMark Brown /* 136209e3c22aSMark Brown * Systems affected by Cavium erratum 24756 are incompatible 136309e3c22aSMark Brown * with KPTI. 136409e3c22aSMark Brown */ 1365ebac96edSWill Deacon if (IS_ENABLED(CONFIG_CAVIUM_ERRATUM_27456)) { 136609e3c22aSMark Brown extern const struct midr_range cavium_erratum_27456_cpus[]; 136709e3c22aSMark Brown 1368ebac96edSWill Deacon if (is_midr_in_range_list(read_cpuid_id(), 1369ebac96edSWill Deacon cavium_erratum_27456_cpus)) 137009e3c22aSMark Brown return false; 1371ebac96edSWill Deacon } 137209e3c22aSMark Brown 137309e3c22aSMark Brown return kaslr_offset() > 0; 137409e3c22aSMark Brown } 137509e3c22aSMark Brown 13761b3ccf4bSJeremy Linton static bool __meltdown_safe = true; 1377ea1e3de8SWill Deacon static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */ 1378ea1e3de8SWill Deacon 1379ea1e3de8SWill Deacon static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry, 1380d3aec8a2SSuzuki K Poulose int scope) 1381ea1e3de8SWill Deacon { 1382be5b2998SSuzuki K Poulose /* List of CPUs that are not vulnerable and don't need KPTI */ 1383be5b2998SSuzuki K Poulose static const struct midr_range kpti_safe_list[] = { 1384be5b2998SSuzuki K Poulose MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), 1385be5b2998SSuzuki K Poulose MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN), 138631d868c4SFlorian Fainelli MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53), 13872a355ec2SWill Deacon MIDR_ALL_VERSIONS(MIDR_CORTEX_A35), 13882a355ec2SWill Deacon MIDR_ALL_VERSIONS(MIDR_CORTEX_A53), 13892a355ec2SWill Deacon MIDR_ALL_VERSIONS(MIDR_CORTEX_A55), 13902a355ec2SWill Deacon MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), 13912a355ec2SWill Deacon MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), 13922a355ec2SWill Deacon MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), 13930ecc471aSHanjun Guo MIDR_ALL_VERSIONS(MIDR_HISI_TSV110), 1394918e1946SRich Wiley MIDR_ALL_VERSIONS(MIDR_NVIDIA_CARMEL), 1395e3dd11a9SKonrad Dybcio MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_2XX_GOLD), 1396e3dd11a9SKonrad Dybcio MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_2XX_SILVER), 1397f4617be3SSai Prakash Ranjan MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_3XX_SILVER), 1398f4617be3SSai Prakash Ranjan MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER), 139971c751f2SMark Rutland { /* sentinel */ } 1400be5b2998SSuzuki K Poulose }; 1401a111b7c0SJosh Poimboeuf char const *str = "kpti command line option"; 14021b3ccf4bSJeremy Linton bool meltdown_safe; 14031b3ccf4bSJeremy Linton 14041b3ccf4bSJeremy Linton meltdown_safe = is_midr_in_range_list(read_cpuid_id(), kpti_safe_list); 14051b3ccf4bSJeremy Linton 14061b3ccf4bSJeremy Linton /* Defer to CPU feature registers */ 14071b3ccf4bSJeremy Linton if (has_cpuid_feature(entry, scope)) 14081b3ccf4bSJeremy Linton meltdown_safe = true; 14091b3ccf4bSJeremy Linton 14101b3ccf4bSJeremy Linton if (!meltdown_safe) 14111b3ccf4bSJeremy Linton __meltdown_safe = false; 1412179a56f6SWill Deacon 14136dc52b15SMarc Zyngier /* 14146dc52b15SMarc Zyngier * For reasons that aren't entirely clear, enabling KPTI on Cavium 14156dc52b15SMarc Zyngier * ThunderX leads to apparent I-cache corruption of kernel text, which 14166dc52b15SMarc Zyngier * ends as well as you might imagine. Don't even try. 14176dc52b15SMarc Zyngier */ 14186dc52b15SMarc Zyngier if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_27456)) { 14196dc52b15SMarc Zyngier str = "ARM64_WORKAROUND_CAVIUM_27456"; 14206dc52b15SMarc Zyngier __kpti_forced = -1; 14216dc52b15SMarc Zyngier } 14226dc52b15SMarc Zyngier 14231b3ccf4bSJeremy Linton /* Useful for KASLR robustness */ 1424c2d92353SMark Brown if (kaslr_requires_kpti()) { 14251b3ccf4bSJeremy Linton if (!__kpti_forced) { 14261b3ccf4bSJeremy Linton str = "KASLR"; 14271b3ccf4bSJeremy Linton __kpti_forced = 1; 14281b3ccf4bSJeremy Linton } 14291b3ccf4bSJeremy Linton } 14301b3ccf4bSJeremy Linton 1431a111b7c0SJosh Poimboeuf if (cpu_mitigations_off() && !__kpti_forced) { 1432a111b7c0SJosh Poimboeuf str = "mitigations=off"; 1433a111b7c0SJosh Poimboeuf __kpti_forced = -1; 1434a111b7c0SJosh Poimboeuf } 1435a111b7c0SJosh Poimboeuf 14361b3ccf4bSJeremy Linton if (!IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) { 14371b3ccf4bSJeremy Linton pr_info_once("kernel page table isolation disabled by kernel configuration\n"); 14381b3ccf4bSJeremy Linton return false; 14391b3ccf4bSJeremy Linton } 14401b3ccf4bSJeremy Linton 14416dc52b15SMarc Zyngier /* Forced? */ 1442ea1e3de8SWill Deacon if (__kpti_forced) { 14436dc52b15SMarc Zyngier pr_info_once("kernel page table isolation forced %s by %s\n", 14446dc52b15SMarc Zyngier __kpti_forced > 0 ? "ON" : "OFF", str); 1445ea1e3de8SWill Deacon return __kpti_forced > 0; 1446ea1e3de8SWill Deacon } 1447ea1e3de8SWill Deacon 14481b3ccf4bSJeremy Linton return !meltdown_safe; 1449ea1e3de8SWill Deacon } 1450ea1e3de8SWill Deacon 14511b3ccf4bSJeremy Linton #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 1452c0cda3b8SDave Martin static void 1453c0cda3b8SDave Martin kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused) 1454f992b4dfSWill Deacon { 1455f992b4dfSWill Deacon typedef void (kpti_remap_fn)(int, int, phys_addr_t); 1456f992b4dfSWill Deacon extern kpti_remap_fn idmap_kpti_install_ng_mappings; 1457f992b4dfSWill Deacon kpti_remap_fn *remap_fn; 1458f992b4dfSWill Deacon 1459f992b4dfSWill Deacon int cpu = smp_processor_id(); 1460f992b4dfSWill Deacon 1461b89d82efSWill Deacon /* 1462b89d82efSWill Deacon * We don't need to rewrite the page-tables if either we've done 1463b89d82efSWill Deacon * it already or we have KASLR enabled and therefore have not 1464b89d82efSWill Deacon * created any global mappings at all. 1465b89d82efSWill Deacon */ 146609e3c22aSMark Brown if (arm64_use_ng_mappings) 1467c0cda3b8SDave Martin return; 1468f992b4dfSWill Deacon 1469f992b4dfSWill Deacon remap_fn = (void *)__pa_symbol(idmap_kpti_install_ng_mappings); 1470f992b4dfSWill Deacon 1471f992b4dfSWill Deacon cpu_install_idmap(); 1472f992b4dfSWill Deacon remap_fn(cpu, num_online_cpus(), __pa_symbol(swapper_pg_dir)); 1473f992b4dfSWill Deacon cpu_uninstall_idmap(); 1474f992b4dfSWill Deacon 1475f992b4dfSWill Deacon if (!cpu) 147609e3c22aSMark Brown arm64_use_ng_mappings = true; 1477f992b4dfSWill Deacon 1478c0cda3b8SDave Martin return; 1479f992b4dfSWill Deacon } 14801b3ccf4bSJeremy Linton #else 14811b3ccf4bSJeremy Linton static void 14821b3ccf4bSJeremy Linton kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused) 14831b3ccf4bSJeremy Linton { 14841b3ccf4bSJeremy Linton } 14851b3ccf4bSJeremy Linton #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ 1486f992b4dfSWill Deacon 1487ea1e3de8SWill Deacon static int __init parse_kpti(char *str) 1488ea1e3de8SWill Deacon { 1489ea1e3de8SWill Deacon bool enabled; 1490ea1e3de8SWill Deacon int ret = strtobool(str, &enabled); 1491ea1e3de8SWill Deacon 1492ea1e3de8SWill Deacon if (ret) 1493ea1e3de8SWill Deacon return ret; 1494ea1e3de8SWill Deacon 1495ea1e3de8SWill Deacon __kpti_forced = enabled ? 1 : -1; 1496ea1e3de8SWill Deacon return 0; 1497ea1e3de8SWill Deacon } 1498b5b7dd64SWill Deacon early_param("kpti", parse_kpti); 1499ea1e3de8SWill Deacon 150005abb595SSuzuki K Poulose #ifdef CONFIG_ARM64_HW_AFDBM 150105abb595SSuzuki K Poulose static inline void __cpu_enable_hw_dbm(void) 150205abb595SSuzuki K Poulose { 150305abb595SSuzuki K Poulose u64 tcr = read_sysreg(tcr_el1) | TCR_HD; 150405abb595SSuzuki K Poulose 150505abb595SSuzuki K Poulose write_sysreg(tcr, tcr_el1); 150605abb595SSuzuki K Poulose isb(); 150780d6b466SWill Deacon local_flush_tlb_all(); 150805abb595SSuzuki K Poulose } 150905abb595SSuzuki K Poulose 1510ece1397cSSuzuki K Poulose static bool cpu_has_broken_dbm(void) 1511ece1397cSSuzuki K Poulose { 1512ece1397cSSuzuki K Poulose /* List of CPUs which have broken DBM support. */ 1513ece1397cSSuzuki K Poulose static const struct midr_range cpus[] = { 1514ece1397cSSuzuki K Poulose #ifdef CONFIG_ARM64_ERRATUM_1024718 1515c0b15c25SSuzuki K Poulose MIDR_ALL_VERSIONS(MIDR_CORTEX_A55), 15169b23d95cSSai Prakash Ranjan /* Kryo4xx Silver (rdpe => r1p0) */ 15179b23d95cSSai Prakash Ranjan MIDR_REV(MIDR_QCOM_KRYO_4XX_SILVER, 0xd, 0xe), 1518ece1397cSSuzuki K Poulose #endif 1519ece1397cSSuzuki K Poulose {}, 1520ece1397cSSuzuki K Poulose }; 1521ece1397cSSuzuki K Poulose 1522ece1397cSSuzuki K Poulose return is_midr_in_range_list(read_cpuid_id(), cpus); 1523ece1397cSSuzuki K Poulose } 1524ece1397cSSuzuki K Poulose 152505abb595SSuzuki K Poulose static bool cpu_can_use_dbm(const struct arm64_cpu_capabilities *cap) 152605abb595SSuzuki K Poulose { 1527ece1397cSSuzuki K Poulose return has_cpuid_feature(cap, SCOPE_LOCAL_CPU) && 1528ece1397cSSuzuki K Poulose !cpu_has_broken_dbm(); 152905abb595SSuzuki K Poulose } 153005abb595SSuzuki K Poulose 153105abb595SSuzuki K Poulose static void cpu_enable_hw_dbm(struct arm64_cpu_capabilities const *cap) 153205abb595SSuzuki K Poulose { 153305abb595SSuzuki K Poulose if (cpu_can_use_dbm(cap)) 153405abb595SSuzuki K Poulose __cpu_enable_hw_dbm(); 153505abb595SSuzuki K Poulose } 153605abb595SSuzuki K Poulose 153705abb595SSuzuki K Poulose static bool has_hw_dbm(const struct arm64_cpu_capabilities *cap, 153805abb595SSuzuki K Poulose int __unused) 153905abb595SSuzuki K Poulose { 154005abb595SSuzuki K Poulose static bool detected = false; 154105abb595SSuzuki K Poulose /* 154205abb595SSuzuki K Poulose * DBM is a non-conflicting feature. i.e, the kernel can safely 154305abb595SSuzuki K Poulose * run a mix of CPUs with and without the feature. So, we 154405abb595SSuzuki K Poulose * unconditionally enable the capability to allow any late CPU 154505abb595SSuzuki K Poulose * to use the feature. We only enable the control bits on the 154605abb595SSuzuki K Poulose * CPU, if it actually supports. 154705abb595SSuzuki K Poulose * 154805abb595SSuzuki K Poulose * We have to make sure we print the "feature" detection only 154905abb595SSuzuki K Poulose * when at least one CPU actually uses it. So check if this CPU 155005abb595SSuzuki K Poulose * can actually use it and print the message exactly once. 155105abb595SSuzuki K Poulose * 155205abb595SSuzuki K Poulose * This is safe as all CPUs (including secondary CPUs - due to the 155305abb595SSuzuki K Poulose * LOCAL_CPU scope - and the hotplugged CPUs - via verification) 155405abb595SSuzuki K Poulose * goes through the "matches" check exactly once. Also if a CPU 155505abb595SSuzuki K Poulose * matches the criteria, it is guaranteed that the CPU will turn 155605abb595SSuzuki K Poulose * the DBM on, as the capability is unconditionally enabled. 155705abb595SSuzuki K Poulose */ 155805abb595SSuzuki K Poulose if (!detected && cpu_can_use_dbm(cap)) { 155905abb595SSuzuki K Poulose detected = true; 156005abb595SSuzuki K Poulose pr_info("detected: Hardware dirty bit management\n"); 156105abb595SSuzuki K Poulose } 156205abb595SSuzuki K Poulose 156305abb595SSuzuki K Poulose return true; 156405abb595SSuzuki K Poulose } 156505abb595SSuzuki K Poulose 156605abb595SSuzuki K Poulose #endif 156705abb595SSuzuki K Poulose 15682c9d45b4SIonela Voinescu #ifdef CONFIG_ARM64_AMU_EXTN 15692c9d45b4SIonela Voinescu 15702c9d45b4SIonela Voinescu /* 15712c9d45b4SIonela Voinescu * The "amu_cpus" cpumask only signals that the CPU implementation for the 15722c9d45b4SIonela Voinescu * flagged CPUs supports the Activity Monitors Unit (AMU) but does not provide 15732c9d45b4SIonela Voinescu * information regarding all the events that it supports. When a CPU bit is 15742c9d45b4SIonela Voinescu * set in the cpumask, the user of this feature can only rely on the presence 15752c9d45b4SIonela Voinescu * of the 4 fixed counters for that CPU. But this does not guarantee that the 15762c9d45b4SIonela Voinescu * counters are enabled or access to these counters is enabled by code 15772c9d45b4SIonela Voinescu * executed at higher exception levels (firmware). 15782c9d45b4SIonela Voinescu */ 15792c9d45b4SIonela Voinescu static struct cpumask amu_cpus __read_mostly; 15802c9d45b4SIonela Voinescu 15812c9d45b4SIonela Voinescu bool cpu_has_amu_feat(int cpu) 15822c9d45b4SIonela Voinescu { 15832c9d45b4SIonela Voinescu return cpumask_test_cpu(cpu, &amu_cpus); 15842c9d45b4SIonela Voinescu } 15852c9d45b4SIonela Voinescu 158668c5debcSIonela Voinescu int get_cpu_with_amu_feat(void) 158768c5debcSIonela Voinescu { 158868c5debcSIonela Voinescu return cpumask_any(&amu_cpus); 158968c5debcSIonela Voinescu } 1590cd0ed03aSIonela Voinescu 15912c9d45b4SIonela Voinescu static void cpu_amu_enable(struct arm64_cpu_capabilities const *cap) 15922c9d45b4SIonela Voinescu { 15932c9d45b4SIonela Voinescu if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU)) { 15942c9d45b4SIonela Voinescu pr_info("detected CPU%d: Activity Monitors Unit (AMU)\n", 15952c9d45b4SIonela Voinescu smp_processor_id()); 15962c9d45b4SIonela Voinescu cpumask_set_cpu(smp_processor_id(), &amu_cpus); 15974b9cf23cSIonela Voinescu update_freq_counters_refs(); 15982c9d45b4SIonela Voinescu } 15992c9d45b4SIonela Voinescu } 16002c9d45b4SIonela Voinescu 16012c9d45b4SIonela Voinescu static bool has_amu(const struct arm64_cpu_capabilities *cap, 16022c9d45b4SIonela Voinescu int __unused) 16032c9d45b4SIonela Voinescu { 16042c9d45b4SIonela Voinescu /* 16052c9d45b4SIonela Voinescu * The AMU extension is a non-conflicting feature: the kernel can 16062c9d45b4SIonela Voinescu * safely run a mix of CPUs with and without support for the 16072c9d45b4SIonela Voinescu * activity monitors extension. Therefore, unconditionally enable 16082c9d45b4SIonela Voinescu * the capability to allow any late CPU to use the feature. 16092c9d45b4SIonela Voinescu * 16102c9d45b4SIonela Voinescu * With this feature unconditionally enabled, the cpu_enable 16112c9d45b4SIonela Voinescu * function will be called for all CPUs that match the criteria, 16122c9d45b4SIonela Voinescu * including secondary and hotplugged, marking this feature as 16132c9d45b4SIonela Voinescu * present on that respective CPU. The enable function will also 16142c9d45b4SIonela Voinescu * print a detection message. 16152c9d45b4SIonela Voinescu */ 16162c9d45b4SIonela Voinescu 16172c9d45b4SIonela Voinescu return true; 16182c9d45b4SIonela Voinescu } 161968c5debcSIonela Voinescu #else 162068c5debcSIonela Voinescu int get_cpu_with_amu_feat(void) 162168c5debcSIonela Voinescu { 162268c5debcSIonela Voinescu return nr_cpu_ids; 162368c5debcSIonela Voinescu } 16242c9d45b4SIonela Voinescu #endif 16252c9d45b4SIonela Voinescu 162612eb3691SWill Deacon #ifdef CONFIG_ARM64_VHE 162712eb3691SWill Deacon static bool runs_at_el2(const struct arm64_cpu_capabilities *entry, int __unused) 162812eb3691SWill Deacon { 162912eb3691SWill Deacon return is_kernel_in_hyp_mode(); 163012eb3691SWill Deacon } 163112eb3691SWill Deacon 1632c0cda3b8SDave Martin static void cpu_copy_el2regs(const struct arm64_cpu_capabilities *__unused) 16336d99b689SJames Morse { 16346d99b689SJames Morse /* 16356d99b689SJames Morse * Copy register values that aren't redirected by hardware. 16366d99b689SJames Morse * 16376d99b689SJames Morse * Before code patching, we only set tpidr_el1, all CPUs need to copy 16386d99b689SJames Morse * this value to tpidr_el2 before we patch the code. Once we've done 16396d99b689SJames Morse * that, freshly-onlined CPUs will set tpidr_el2, so we don't need to 16406d99b689SJames Morse * do anything here. 16416d99b689SJames Morse */ 1642e9ab7a2eSJulien Thierry if (!alternative_is_applied(ARM64_HAS_VIRT_HOST_EXTN)) 16436d99b689SJames Morse write_sysreg(read_sysreg(tpidr_el1), tpidr_el2); 16446d99b689SJames Morse } 164512eb3691SWill Deacon #endif 16466d99b689SJames Morse 1647e48d53a9SMarc Zyngier static void cpu_has_fwb(const struct arm64_cpu_capabilities *__unused) 1648e48d53a9SMarc Zyngier { 1649e48d53a9SMarc Zyngier u64 val = read_sysreg_s(SYS_CLIDR_EL1); 1650e48d53a9SMarc Zyngier 1651e48d53a9SMarc Zyngier /* Check that CLIDR_EL1.LOU{U,IS} are both 0 */ 1652e48d53a9SMarc Zyngier WARN_ON(val & (7 << 27 | 7 << 21)); 1653e48d53a9SMarc Zyngier } 1654e48d53a9SMarc Zyngier 1655b8925ee2SWill Deacon #ifdef CONFIG_ARM64_PAN 1656b8925ee2SWill Deacon static void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused) 1657b8925ee2SWill Deacon { 1658b8925ee2SWill Deacon /* 1659b8925ee2SWill Deacon * We modify PSTATE. This won't work from irq context as the PSTATE 1660b8925ee2SWill Deacon * is discarded once we return from the exception. 1661b8925ee2SWill Deacon */ 1662b8925ee2SWill Deacon WARN_ON_ONCE(in_interrupt()); 1663b8925ee2SWill Deacon 1664b8925ee2SWill Deacon sysreg_clear_set(sctlr_el1, SCTLR_EL1_SPAN, 0); 1665515d5c8aSMark Rutland set_pstate_pan(1); 1666b8925ee2SWill Deacon } 1667b8925ee2SWill Deacon #endif /* CONFIG_ARM64_PAN */ 1668b8925ee2SWill Deacon 1669b8925ee2SWill Deacon #ifdef CONFIG_ARM64_RAS_EXTN 1670b8925ee2SWill Deacon static void cpu_clear_disr(const struct arm64_cpu_capabilities *__unused) 1671b8925ee2SWill Deacon { 1672b8925ee2SWill Deacon /* Firmware may have left a deferred SError in this register. */ 1673b8925ee2SWill Deacon write_sysreg_s(0, SYS_DISR_EL1); 1674b8925ee2SWill Deacon } 1675b8925ee2SWill Deacon #endif /* CONFIG_ARM64_RAS_EXTN */ 1676b8925ee2SWill Deacon 16776984eb47SMark Rutland #ifdef CONFIG_ARM64_PTR_AUTH 1678ba9d1d3eSAmit Daniel Kachhap static bool has_address_auth_cpucap(const struct arm64_cpu_capabilities *entry, int scope) 167975031975SMark Rutland { 1680ba9d1d3eSAmit Daniel Kachhap int boot_val, sec_val; 1681ba9d1d3eSAmit Daniel Kachhap 1682ba9d1d3eSAmit Daniel Kachhap /* We don't expect to be called with SCOPE_SYSTEM */ 1683ba9d1d3eSAmit Daniel Kachhap WARN_ON(scope == SCOPE_SYSTEM); 1684ba9d1d3eSAmit Daniel Kachhap /* 1685ba9d1d3eSAmit Daniel Kachhap * The ptr-auth feature levels are not intercompatible with lower 1686ba9d1d3eSAmit Daniel Kachhap * levels. Hence we must match ptr-auth feature level of the secondary 1687ba9d1d3eSAmit Daniel Kachhap * CPUs with that of the boot CPU. The level of boot cpu is fetched 1688ba9d1d3eSAmit Daniel Kachhap * from the sanitised register whereas direct register read is done for 1689ba9d1d3eSAmit Daniel Kachhap * the secondary CPUs. 1690ba9d1d3eSAmit Daniel Kachhap * The sanitised feature state is guaranteed to match that of the 1691ba9d1d3eSAmit Daniel Kachhap * boot CPU as a mismatched secondary CPU is parked before it gets 1692ba9d1d3eSAmit Daniel Kachhap * a chance to update the state, with the capability. 1693ba9d1d3eSAmit Daniel Kachhap */ 1694ba9d1d3eSAmit Daniel Kachhap boot_val = cpuid_feature_extract_field(read_sanitised_ftr_reg(entry->sys_reg), 1695ba9d1d3eSAmit Daniel Kachhap entry->field_pos, entry->sign); 1696ba9d1d3eSAmit Daniel Kachhap if (scope & SCOPE_BOOT_CPU) 1697ba9d1d3eSAmit Daniel Kachhap return boot_val >= entry->min_field_value; 1698ba9d1d3eSAmit Daniel Kachhap /* Now check for the secondary CPUs with SCOPE_LOCAL_CPU scope */ 1699ba9d1d3eSAmit Daniel Kachhap sec_val = cpuid_feature_extract_field(__read_sysreg_by_encoding(entry->sys_reg), 1700ba9d1d3eSAmit Daniel Kachhap entry->field_pos, entry->sign); 1701ba9d1d3eSAmit Daniel Kachhap return sec_val == boot_val; 1702ba9d1d3eSAmit Daniel Kachhap } 1703ba9d1d3eSAmit Daniel Kachhap 1704ba9d1d3eSAmit Daniel Kachhap static bool has_address_auth_metacap(const struct arm64_cpu_capabilities *entry, 1705ba9d1d3eSAmit Daniel Kachhap int scope) 1706ba9d1d3eSAmit Daniel Kachhap { 1707ba9d1d3eSAmit Daniel Kachhap return has_address_auth_cpucap(cpu_hwcaps_ptrs[ARM64_HAS_ADDRESS_AUTH_ARCH], scope) || 1708ba9d1d3eSAmit Daniel Kachhap has_address_auth_cpucap(cpu_hwcaps_ptrs[ARM64_HAS_ADDRESS_AUTH_IMP_DEF], scope); 1709cfef06bdSKristina Martsenko } 1710cfef06bdSKristina Martsenko 1711cfef06bdSKristina Martsenko static bool has_generic_auth(const struct arm64_cpu_capabilities *entry, 1712cfef06bdSKristina Martsenko int __unused) 1713cfef06bdSKristina Martsenko { 1714cfef06bdSKristina Martsenko return __system_matches_cap(ARM64_HAS_GENERIC_AUTH_ARCH) || 1715cfef06bdSKristina Martsenko __system_matches_cap(ARM64_HAS_GENERIC_AUTH_IMP_DEF); 171675031975SMark Rutland } 17176984eb47SMark Rutland #endif /* CONFIG_ARM64_PTR_AUTH */ 17186984eb47SMark Rutland 17193e6c69a0SMark Brown #ifdef CONFIG_ARM64_E0PD 17203e6c69a0SMark Brown static void cpu_enable_e0pd(struct arm64_cpu_capabilities const *cap) 17213e6c69a0SMark Brown { 17223e6c69a0SMark Brown if (this_cpu_has_cap(ARM64_HAS_E0PD)) 17233e6c69a0SMark Brown sysreg_clear_set(tcr_el1, 0, TCR_E0PD1); 17243e6c69a0SMark Brown } 17253e6c69a0SMark Brown #endif /* CONFIG_ARM64_E0PD */ 17263e6c69a0SMark Brown 1727b90d2b22SJulien Thierry #ifdef CONFIG_ARM64_PSEUDO_NMI 1728bc3c03ccSJulien Thierry static bool enable_pseudo_nmi; 1729bc3c03ccSJulien Thierry 1730bc3c03ccSJulien Thierry static int __init early_enable_pseudo_nmi(char *p) 1731bc3c03ccSJulien Thierry { 1732bc3c03ccSJulien Thierry return strtobool(p, &enable_pseudo_nmi); 1733bc3c03ccSJulien Thierry } 1734bc3c03ccSJulien Thierry early_param("irqchip.gicv3_pseudo_nmi", early_enable_pseudo_nmi); 1735bc3c03ccSJulien Thierry 1736b90d2b22SJulien Thierry static bool can_use_gic_priorities(const struct arm64_cpu_capabilities *entry, 1737b90d2b22SJulien Thierry int scope) 1738b90d2b22SJulien Thierry { 1739bc3c03ccSJulien Thierry return enable_pseudo_nmi && has_useable_gicv3_cpuif(entry, scope); 1740b90d2b22SJulien Thierry } 1741b90d2b22SJulien Thierry #endif 1742b90d2b22SJulien Thierry 17438ef8f360SDave Martin #ifdef CONFIG_ARM64_BTI 17448ef8f360SDave Martin static void bti_enable(const struct arm64_cpu_capabilities *__unused) 17458ef8f360SDave Martin { 17468ef8f360SDave Martin /* 17478ef8f360SDave Martin * Use of X16/X17 for tail-calls and trampolines that jump to 17488ef8f360SDave Martin * function entry points using BR is a requirement for 17498ef8f360SDave Martin * marking binaries with GNU_PROPERTY_AARCH64_FEATURE_1_BTI. 17508ef8f360SDave Martin * So, be strict and forbid other BRs using other registers to 17518ef8f360SDave Martin * jump onto a PACIxSP instruction: 17528ef8f360SDave Martin */ 17538ef8f360SDave Martin sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_BT0 | SCTLR_EL1_BT1); 17548ef8f360SDave Martin isb(); 17558ef8f360SDave Martin } 17568ef8f360SDave Martin #endif /* CONFIG_ARM64_BTI */ 17578ef8f360SDave Martin 175834bfeea4SCatalin Marinas #ifdef CONFIG_ARM64_MTE 175934bfeea4SCatalin Marinas static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap) 176034bfeea4SCatalin Marinas { 176134bfeea4SCatalin Marinas /* 176234bfeea4SCatalin Marinas * Clear the tags in the zero page. This needs to be done via the 176334bfeea4SCatalin Marinas * linear map which has the Tagged attribute. 176434bfeea4SCatalin Marinas */ 176568d54ceeSCatalin Marinas if (!test_and_set_bit(PG_mte_tagged, &ZERO_PAGE(0)->flags)) 176634bfeea4SCatalin Marinas mte_clear_page_tags(lm_alias(empty_zero_page)); 17672e903b91SAndrey Konovalov 17682e903b91SAndrey Konovalov kasan_init_hw_tags_cpu(); 176934bfeea4SCatalin Marinas } 177034bfeea4SCatalin Marinas #endif /* CONFIG_ARM64_MTE */ 177134bfeea4SCatalin Marinas 17723eb681fbSDavid Brazdil #ifdef CONFIG_KVM 17733eb681fbSDavid Brazdil static bool is_kvm_protected_mode(const struct arm64_cpu_capabilities *entry, int __unused) 17743eb681fbSDavid Brazdil { 17753eb681fbSDavid Brazdil if (kvm_get_mode() != KVM_MODE_PROTECTED) 17763eb681fbSDavid Brazdil return false; 17773eb681fbSDavid Brazdil 17783eb681fbSDavid Brazdil if (is_kernel_in_hyp_mode()) { 17793eb681fbSDavid Brazdil pr_warn("Protected KVM not available with VHE\n"); 17803eb681fbSDavid Brazdil return false; 17813eb681fbSDavid Brazdil } 17823eb681fbSDavid Brazdil 17833eb681fbSDavid Brazdil return true; 17843eb681fbSDavid Brazdil } 17853eb681fbSDavid Brazdil #endif /* CONFIG_KVM */ 17863eb681fbSDavid Brazdil 17878c176e16SAmit Daniel Kachhap /* Internal helper functions to match cpu capability type */ 17888c176e16SAmit Daniel Kachhap static bool 17898c176e16SAmit Daniel Kachhap cpucap_late_cpu_optional(const struct arm64_cpu_capabilities *cap) 17908c176e16SAmit Daniel Kachhap { 17918c176e16SAmit Daniel Kachhap return !!(cap->type & ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU); 17928c176e16SAmit Daniel Kachhap } 17938c176e16SAmit Daniel Kachhap 17948c176e16SAmit Daniel Kachhap static bool 17958c176e16SAmit Daniel Kachhap cpucap_late_cpu_permitted(const struct arm64_cpu_capabilities *cap) 17968c176e16SAmit Daniel Kachhap { 17978c176e16SAmit Daniel Kachhap return !!(cap->type & ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU); 17988c176e16SAmit Daniel Kachhap } 17998c176e16SAmit Daniel Kachhap 1800deeaac51SKristina Martsenko static bool 1801deeaac51SKristina Martsenko cpucap_panic_on_conflict(const struct arm64_cpu_capabilities *cap) 1802deeaac51SKristina Martsenko { 1803deeaac51SKristina Martsenko return !!(cap->type & ARM64_CPUCAP_PANIC_ON_CONFLICT); 1804deeaac51SKristina Martsenko } 1805deeaac51SKristina Martsenko 1806359b7064SMarc Zyngier static const struct arm64_cpu_capabilities arm64_features[] = { 180794a9e04aSMarc Zyngier { 180894a9e04aSMarc Zyngier .desc = "GIC system register CPU interface", 180994a9e04aSMarc Zyngier .capability = ARM64_HAS_SYSREG_GIC_CPUIF, 1810c9bfdf73SJulien Thierry .type = ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE, 1811963fcd40SMarc Zyngier .matches = has_useable_gicv3_cpuif, 1812da8d02d1SSuzuki K. Poulose .sys_reg = SYS_ID_AA64PFR0_EL1, 1813da8d02d1SSuzuki K. Poulose .field_pos = ID_AA64PFR0_GIC_SHIFT, 1814ff96f7bcSSuzuki K Poulose .sign = FTR_UNSIGNED, 181518ffa046SJames Morse .min_field_value = 1, 181694a9e04aSMarc Zyngier }, 1817338d4f49SJames Morse #ifdef CONFIG_ARM64_PAN 1818338d4f49SJames Morse { 1819338d4f49SJames Morse .desc = "Privileged Access Never", 1820338d4f49SJames Morse .capability = ARM64_HAS_PAN, 18215b4747c5SSuzuki K Poulose .type = ARM64_CPUCAP_SYSTEM_FEATURE, 1822da8d02d1SSuzuki K. Poulose .matches = has_cpuid_feature, 1823da8d02d1SSuzuki K. Poulose .sys_reg = SYS_ID_AA64MMFR1_EL1, 1824da8d02d1SSuzuki K. Poulose .field_pos = ID_AA64MMFR1_PAN_SHIFT, 1825ff96f7bcSSuzuki K Poulose .sign = FTR_UNSIGNED, 1826338d4f49SJames Morse .min_field_value = 1, 1827c0cda3b8SDave Martin .cpu_enable = cpu_enable_pan, 1828338d4f49SJames Morse }, 1829338d4f49SJames Morse #endif /* CONFIG_ARM64_PAN */ 1830395af861SCatalin Marinas #ifdef CONFIG_ARM64_LSE_ATOMICS 18312e94da13SWill Deacon { 18322e94da13SWill Deacon .desc = "LSE atomic instructions", 18332e94da13SWill Deacon .capability = ARM64_HAS_LSE_ATOMICS, 18345b4747c5SSuzuki K Poulose .type = ARM64_CPUCAP_SYSTEM_FEATURE, 1835da8d02d1SSuzuki K. Poulose .matches = has_cpuid_feature, 1836da8d02d1SSuzuki K. Poulose .sys_reg = SYS_ID_AA64ISAR0_EL1, 1837da8d02d1SSuzuki K. Poulose .field_pos = ID_AA64ISAR0_ATOMICS_SHIFT, 1838ff96f7bcSSuzuki K Poulose .sign = FTR_UNSIGNED, 18392e94da13SWill Deacon .min_field_value = 2, 18402e94da13SWill Deacon }, 1841395af861SCatalin Marinas #endif /* CONFIG_ARM64_LSE_ATOMICS */ 1842d88701beSMarc Zyngier { 1843d5370f75SWill Deacon .desc = "Software prefetching using PRFM", 1844d5370f75SWill Deacon .capability = ARM64_HAS_NO_HW_PREFETCH, 18455c137714SSuzuki K Poulose .type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE, 1846d5370f75SWill Deacon .matches = has_no_hw_prefetch, 1847d5370f75SWill Deacon }, 1848830dcc9fSSuzuki K Poulose #ifdef CONFIG_ARM64_VHE 1849588ab3f9SLinus Torvalds { 1850d88701beSMarc Zyngier .desc = "Virtualization Host Extensions", 1851d88701beSMarc Zyngier .capability = ARM64_HAS_VIRT_HOST_EXTN, 1852830dcc9fSSuzuki K Poulose .type = ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE, 1853d88701beSMarc Zyngier .matches = runs_at_el2, 1854c0cda3b8SDave Martin .cpu_enable = cpu_copy_el2regs, 1855d88701beSMarc Zyngier }, 1856830dcc9fSSuzuki K Poulose #endif /* CONFIG_ARM64_VHE */ 1857042446a3SSuzuki K Poulose { 1858042446a3SSuzuki K Poulose .desc = "32-bit EL0 Support", 1859042446a3SSuzuki K Poulose .capability = ARM64_HAS_32BIT_EL0, 18605b4747c5SSuzuki K Poulose .type = ARM64_CPUCAP_SYSTEM_FEATURE, 1861042446a3SSuzuki K Poulose .matches = has_cpuid_feature, 1862042446a3SSuzuki K Poulose .sys_reg = SYS_ID_AA64PFR0_EL1, 1863042446a3SSuzuki K Poulose .sign = FTR_UNSIGNED, 1864042446a3SSuzuki K Poulose .field_pos = ID_AA64PFR0_EL0_SHIFT, 1865042446a3SSuzuki K Poulose .min_field_value = ID_AA64PFR0_EL0_32BIT_64BIT, 1866042446a3SSuzuki K Poulose }, 1867540f76d1SWill Deacon #ifdef CONFIG_KVM 1868540f76d1SWill Deacon { 1869540f76d1SWill Deacon .desc = "32-bit EL1 Support", 1870540f76d1SWill Deacon .capability = ARM64_HAS_32BIT_EL1, 1871540f76d1SWill Deacon .type = ARM64_CPUCAP_SYSTEM_FEATURE, 1872540f76d1SWill Deacon .matches = has_cpuid_feature, 1873540f76d1SWill Deacon .sys_reg = SYS_ID_AA64PFR0_EL1, 1874540f76d1SWill Deacon .sign = FTR_UNSIGNED, 1875540f76d1SWill Deacon .field_pos = ID_AA64PFR0_EL1_SHIFT, 1876540f76d1SWill Deacon .min_field_value = ID_AA64PFR0_EL1_32BIT_64BIT, 1877540f76d1SWill Deacon }, 18783eb681fbSDavid Brazdil { 18793eb681fbSDavid Brazdil .desc = "Protected KVM", 18803eb681fbSDavid Brazdil .capability = ARM64_KVM_PROTECTED_MODE, 18813eb681fbSDavid Brazdil .type = ARM64_CPUCAP_SYSTEM_FEATURE, 18823eb681fbSDavid Brazdil .matches = is_kvm_protected_mode, 18833eb681fbSDavid Brazdil }, 1884540f76d1SWill Deacon #endif 1885ea1e3de8SWill Deacon { 1886179a56f6SWill Deacon .desc = "Kernel page table isolation (KPTI)", 1887ea1e3de8SWill Deacon .capability = ARM64_UNMAP_KERNEL_AT_EL0, 1888d3aec8a2SSuzuki K Poulose .type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE, 1889d3aec8a2SSuzuki K Poulose /* 1890d3aec8a2SSuzuki K Poulose * The ID feature fields below are used to indicate that 1891d3aec8a2SSuzuki K Poulose * the CPU doesn't need KPTI. See unmap_kernel_at_el0 for 1892d3aec8a2SSuzuki K Poulose * more details. 1893d3aec8a2SSuzuki K Poulose */ 1894d3aec8a2SSuzuki K Poulose .sys_reg = SYS_ID_AA64PFR0_EL1, 1895d3aec8a2SSuzuki K Poulose .field_pos = ID_AA64PFR0_CSV3_SHIFT, 1896d3aec8a2SSuzuki K Poulose .min_field_value = 1, 1897ea1e3de8SWill Deacon .matches = unmap_kernel_at_el0, 1898c0cda3b8SDave Martin .cpu_enable = kpti_install_ng_mappings, 1899ea1e3de8SWill Deacon }, 190082e0191aSSuzuki K Poulose { 190182e0191aSSuzuki K Poulose /* FP/SIMD is not implemented */ 190282e0191aSSuzuki K Poulose .capability = ARM64_HAS_NO_FPSIMD, 1903449443c0SSuzuki K Poulose .type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE, 190482e0191aSSuzuki K Poulose .min_field_value = 0, 190582e0191aSSuzuki K Poulose .matches = has_no_fpsimd, 190682e0191aSSuzuki K Poulose }, 1907d50e071fSRobin Murphy #ifdef CONFIG_ARM64_PMEM 1908d50e071fSRobin Murphy { 1909d50e071fSRobin Murphy .desc = "Data cache clean to Point of Persistence", 1910d50e071fSRobin Murphy .capability = ARM64_HAS_DCPOP, 19115b4747c5SSuzuki K Poulose .type = ARM64_CPUCAP_SYSTEM_FEATURE, 1912d50e071fSRobin Murphy .matches = has_cpuid_feature, 1913d50e071fSRobin Murphy .sys_reg = SYS_ID_AA64ISAR1_EL1, 1914d50e071fSRobin Murphy .field_pos = ID_AA64ISAR1_DPB_SHIFT, 1915d50e071fSRobin Murphy .min_field_value = 1, 1916d50e071fSRobin Murphy }, 1917b9585f53SAndrew Murray { 1918b9585f53SAndrew Murray .desc = "Data cache clean to Point of Deep Persistence", 1919b9585f53SAndrew Murray .capability = ARM64_HAS_DCPODP, 1920b9585f53SAndrew Murray .type = ARM64_CPUCAP_SYSTEM_FEATURE, 1921b9585f53SAndrew Murray .matches = has_cpuid_feature, 1922b9585f53SAndrew Murray .sys_reg = SYS_ID_AA64ISAR1_EL1, 1923b9585f53SAndrew Murray .sign = FTR_UNSIGNED, 1924b9585f53SAndrew Murray .field_pos = ID_AA64ISAR1_DPB_SHIFT, 1925b9585f53SAndrew Murray .min_field_value = 2, 1926b9585f53SAndrew Murray }, 1927d50e071fSRobin Murphy #endif 192843994d82SDave Martin #ifdef CONFIG_ARM64_SVE 192943994d82SDave Martin { 193043994d82SDave Martin .desc = "Scalable Vector Extension", 19315b4747c5SSuzuki K Poulose .type = ARM64_CPUCAP_SYSTEM_FEATURE, 193243994d82SDave Martin .capability = ARM64_SVE, 193343994d82SDave Martin .sys_reg = SYS_ID_AA64PFR0_EL1, 193443994d82SDave Martin .sign = FTR_UNSIGNED, 193543994d82SDave Martin .field_pos = ID_AA64PFR0_SVE_SHIFT, 193643994d82SDave Martin .min_field_value = ID_AA64PFR0_SVE, 193743994d82SDave Martin .matches = has_cpuid_feature, 1938c0cda3b8SDave Martin .cpu_enable = sve_kernel_enable, 193943994d82SDave Martin }, 194043994d82SDave Martin #endif /* CONFIG_ARM64_SVE */ 194164c02720SXie XiuQi #ifdef CONFIG_ARM64_RAS_EXTN 194264c02720SXie XiuQi { 194364c02720SXie XiuQi .desc = "RAS Extension Support", 194464c02720SXie XiuQi .capability = ARM64_HAS_RAS_EXTN, 19455b4747c5SSuzuki K Poulose .type = ARM64_CPUCAP_SYSTEM_FEATURE, 194664c02720SXie XiuQi .matches = has_cpuid_feature, 194764c02720SXie XiuQi .sys_reg = SYS_ID_AA64PFR0_EL1, 194864c02720SXie XiuQi .sign = FTR_UNSIGNED, 194964c02720SXie XiuQi .field_pos = ID_AA64PFR0_RAS_SHIFT, 195064c02720SXie XiuQi .min_field_value = ID_AA64PFR0_RAS_V1, 1951c0cda3b8SDave Martin .cpu_enable = cpu_clear_disr, 195264c02720SXie XiuQi }, 195364c02720SXie XiuQi #endif /* CONFIG_ARM64_RAS_EXTN */ 19542c9d45b4SIonela Voinescu #ifdef CONFIG_ARM64_AMU_EXTN 19552c9d45b4SIonela Voinescu { 19562c9d45b4SIonela Voinescu /* 19572c9d45b4SIonela Voinescu * The feature is enabled by default if CONFIG_ARM64_AMU_EXTN=y. 19582c9d45b4SIonela Voinescu * Therefore, don't provide .desc as we don't want the detection 19592c9d45b4SIonela Voinescu * message to be shown until at least one CPU is detected to 19602c9d45b4SIonela Voinescu * support the feature. 19612c9d45b4SIonela Voinescu */ 19622c9d45b4SIonela Voinescu .capability = ARM64_HAS_AMU_EXTN, 19632c9d45b4SIonela Voinescu .type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE, 19642c9d45b4SIonela Voinescu .matches = has_amu, 19652c9d45b4SIonela Voinescu .sys_reg = SYS_ID_AA64PFR0_EL1, 19662c9d45b4SIonela Voinescu .sign = FTR_UNSIGNED, 19672c9d45b4SIonela Voinescu .field_pos = ID_AA64PFR0_AMU_SHIFT, 19682c9d45b4SIonela Voinescu .min_field_value = ID_AA64PFR0_AMU, 19692c9d45b4SIonela Voinescu .cpu_enable = cpu_amu_enable, 19702c9d45b4SIonela Voinescu }, 19712c9d45b4SIonela Voinescu #endif /* CONFIG_ARM64_AMU_EXTN */ 19726ae4b6e0SShanker Donthineni { 19736ae4b6e0SShanker Donthineni .desc = "Data cache clean to the PoU not required for I/D coherence", 19746ae4b6e0SShanker Donthineni .capability = ARM64_HAS_CACHE_IDC, 19755b4747c5SSuzuki K Poulose .type = ARM64_CPUCAP_SYSTEM_FEATURE, 19766ae4b6e0SShanker Donthineni .matches = has_cache_idc, 19771602df02SSuzuki K Poulose .cpu_enable = cpu_emulate_effective_ctr, 19786ae4b6e0SShanker Donthineni }, 19796ae4b6e0SShanker Donthineni { 19806ae4b6e0SShanker Donthineni .desc = "Instruction cache invalidation not required for I/D coherence", 19816ae4b6e0SShanker Donthineni .capability = ARM64_HAS_CACHE_DIC, 19825b4747c5SSuzuki K Poulose .type = ARM64_CPUCAP_SYSTEM_FEATURE, 19836ae4b6e0SShanker Donthineni .matches = has_cache_dic, 19846ae4b6e0SShanker Donthineni }, 1985e48d53a9SMarc Zyngier { 1986e48d53a9SMarc Zyngier .desc = "Stage-2 Force Write-Back", 1987e48d53a9SMarc Zyngier .type = ARM64_CPUCAP_SYSTEM_FEATURE, 1988e48d53a9SMarc Zyngier .capability = ARM64_HAS_STAGE2_FWB, 1989e48d53a9SMarc Zyngier .sys_reg = SYS_ID_AA64MMFR2_EL1, 1990e48d53a9SMarc Zyngier .sign = FTR_UNSIGNED, 1991e48d53a9SMarc Zyngier .field_pos = ID_AA64MMFR2_FWB_SHIFT, 1992e48d53a9SMarc Zyngier .min_field_value = 1, 1993e48d53a9SMarc Zyngier .matches = has_cpuid_feature, 1994e48d53a9SMarc Zyngier .cpu_enable = cpu_has_fwb, 1995e48d53a9SMarc Zyngier }, 1996552ae76fSMarc Zyngier { 1997552ae76fSMarc Zyngier .desc = "ARMv8.4 Translation Table Level", 1998552ae76fSMarc Zyngier .type = ARM64_CPUCAP_SYSTEM_FEATURE, 1999552ae76fSMarc Zyngier .capability = ARM64_HAS_ARMv8_4_TTL, 2000552ae76fSMarc Zyngier .sys_reg = SYS_ID_AA64MMFR2_EL1, 2001552ae76fSMarc Zyngier .sign = FTR_UNSIGNED, 2002552ae76fSMarc Zyngier .field_pos = ID_AA64MMFR2_TTL_SHIFT, 2003552ae76fSMarc Zyngier .min_field_value = 1, 2004552ae76fSMarc Zyngier .matches = has_cpuid_feature, 2005552ae76fSMarc Zyngier }, 2006b620ba54SZhenyu Ye { 2007b620ba54SZhenyu Ye .desc = "TLB range maintenance instructions", 2008b620ba54SZhenyu Ye .capability = ARM64_HAS_TLB_RANGE, 2009b620ba54SZhenyu Ye .type = ARM64_CPUCAP_SYSTEM_FEATURE, 2010b620ba54SZhenyu Ye .matches = has_cpuid_feature, 2011b620ba54SZhenyu Ye .sys_reg = SYS_ID_AA64ISAR0_EL1, 2012b620ba54SZhenyu Ye .field_pos = ID_AA64ISAR0_TLB_SHIFT, 2013b620ba54SZhenyu Ye .sign = FTR_UNSIGNED, 2014b620ba54SZhenyu Ye .min_field_value = ID_AA64ISAR0_TLB_RANGE, 2015b620ba54SZhenyu Ye }, 201605abb595SSuzuki K Poulose #ifdef CONFIG_ARM64_HW_AFDBM 201705abb595SSuzuki K Poulose { 201805abb595SSuzuki K Poulose /* 201905abb595SSuzuki K Poulose * Since we turn this on always, we don't want the user to 202005abb595SSuzuki K Poulose * think that the feature is available when it may not be. 202105abb595SSuzuki K Poulose * So hide the description. 202205abb595SSuzuki K Poulose * 202305abb595SSuzuki K Poulose * .desc = "Hardware pagetable Dirty Bit Management", 202405abb595SSuzuki K Poulose * 202505abb595SSuzuki K Poulose */ 202605abb595SSuzuki K Poulose .type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE, 202705abb595SSuzuki K Poulose .capability = ARM64_HW_DBM, 202805abb595SSuzuki K Poulose .sys_reg = SYS_ID_AA64MMFR1_EL1, 202905abb595SSuzuki K Poulose .sign = FTR_UNSIGNED, 203005abb595SSuzuki K Poulose .field_pos = ID_AA64MMFR1_HADBS_SHIFT, 203105abb595SSuzuki K Poulose .min_field_value = 2, 203205abb595SSuzuki K Poulose .matches = has_hw_dbm, 203305abb595SSuzuki K Poulose .cpu_enable = cpu_enable_hw_dbm, 203405abb595SSuzuki K Poulose }, 203505abb595SSuzuki K Poulose #endif 203686d0dd34SArd Biesheuvel { 203786d0dd34SArd Biesheuvel .desc = "CRC32 instructions", 203886d0dd34SArd Biesheuvel .capability = ARM64_HAS_CRC32, 203986d0dd34SArd Biesheuvel .type = ARM64_CPUCAP_SYSTEM_FEATURE, 204086d0dd34SArd Biesheuvel .matches = has_cpuid_feature, 204186d0dd34SArd Biesheuvel .sys_reg = SYS_ID_AA64ISAR0_EL1, 204286d0dd34SArd Biesheuvel .field_pos = ID_AA64ISAR0_CRC32_SHIFT, 204386d0dd34SArd Biesheuvel .min_field_value = 1, 204486d0dd34SArd Biesheuvel }, 2045d71be2b6SWill Deacon { 2046d71be2b6SWill Deacon .desc = "Speculative Store Bypassing Safe (SSBS)", 2047d71be2b6SWill Deacon .capability = ARM64_SSBS, 2048532d5815SWill Deacon .type = ARM64_CPUCAP_SYSTEM_FEATURE, 2049d71be2b6SWill Deacon .matches = has_cpuid_feature, 2050d71be2b6SWill Deacon .sys_reg = SYS_ID_AA64PFR1_EL1, 2051d71be2b6SWill Deacon .field_pos = ID_AA64PFR1_SSBS_SHIFT, 2052d71be2b6SWill Deacon .sign = FTR_UNSIGNED, 2053d71be2b6SWill Deacon .min_field_value = ID_AA64PFR1_SSBS_PSTATE_ONLY, 2054d71be2b6SWill Deacon }, 20555ffdfaedSVladimir Murzin #ifdef CONFIG_ARM64_CNP 20565ffdfaedSVladimir Murzin { 20575ffdfaedSVladimir Murzin .desc = "Common not Private translations", 20585ffdfaedSVladimir Murzin .capability = ARM64_HAS_CNP, 20595ffdfaedSVladimir Murzin .type = ARM64_CPUCAP_SYSTEM_FEATURE, 20605ffdfaedSVladimir Murzin .matches = has_useable_cnp, 20615ffdfaedSVladimir Murzin .sys_reg = SYS_ID_AA64MMFR2_EL1, 20625ffdfaedSVladimir Murzin .sign = FTR_UNSIGNED, 20635ffdfaedSVladimir Murzin .field_pos = ID_AA64MMFR2_CNP_SHIFT, 20645ffdfaedSVladimir Murzin .min_field_value = 1, 20655ffdfaedSVladimir Murzin .cpu_enable = cpu_enable_cnp, 20665ffdfaedSVladimir Murzin }, 20675ffdfaedSVladimir Murzin #endif 2068bd4fb6d2SWill Deacon { 2069bd4fb6d2SWill Deacon .desc = "Speculation barrier (SB)", 2070bd4fb6d2SWill Deacon .capability = ARM64_HAS_SB, 2071bd4fb6d2SWill Deacon .type = ARM64_CPUCAP_SYSTEM_FEATURE, 2072bd4fb6d2SWill Deacon .matches = has_cpuid_feature, 2073bd4fb6d2SWill Deacon .sys_reg = SYS_ID_AA64ISAR1_EL1, 2074bd4fb6d2SWill Deacon .field_pos = ID_AA64ISAR1_SB_SHIFT, 2075bd4fb6d2SWill Deacon .sign = FTR_UNSIGNED, 2076bd4fb6d2SWill Deacon .min_field_value = 1, 2077bd4fb6d2SWill Deacon }, 20786984eb47SMark Rutland #ifdef CONFIG_ARM64_PTR_AUTH 20796984eb47SMark Rutland { 20806984eb47SMark Rutland .desc = "Address authentication (architected algorithm)", 20816984eb47SMark Rutland .capability = ARM64_HAS_ADDRESS_AUTH_ARCH, 20826982934eSKristina Martsenko .type = ARM64_CPUCAP_BOOT_CPU_FEATURE, 20836984eb47SMark Rutland .sys_reg = SYS_ID_AA64ISAR1_EL1, 20846984eb47SMark Rutland .sign = FTR_UNSIGNED, 20856984eb47SMark Rutland .field_pos = ID_AA64ISAR1_APA_SHIFT, 20866984eb47SMark Rutland .min_field_value = ID_AA64ISAR1_APA_ARCHITECTED, 2087ba9d1d3eSAmit Daniel Kachhap .matches = has_address_auth_cpucap, 20886984eb47SMark Rutland }, 20896984eb47SMark Rutland { 20906984eb47SMark Rutland .desc = "Address authentication (IMP DEF algorithm)", 20916984eb47SMark Rutland .capability = ARM64_HAS_ADDRESS_AUTH_IMP_DEF, 20926982934eSKristina Martsenko .type = ARM64_CPUCAP_BOOT_CPU_FEATURE, 20936984eb47SMark Rutland .sys_reg = SYS_ID_AA64ISAR1_EL1, 20946984eb47SMark Rutland .sign = FTR_UNSIGNED, 20956984eb47SMark Rutland .field_pos = ID_AA64ISAR1_API_SHIFT, 20966984eb47SMark Rutland .min_field_value = ID_AA64ISAR1_API_IMP_DEF, 2097ba9d1d3eSAmit Daniel Kachhap .matches = has_address_auth_cpucap, 2098cfef06bdSKristina Martsenko }, 2099cfef06bdSKristina Martsenko { 2100cfef06bdSKristina Martsenko .capability = ARM64_HAS_ADDRESS_AUTH, 21016982934eSKristina Martsenko .type = ARM64_CPUCAP_BOOT_CPU_FEATURE, 2102ba9d1d3eSAmit Daniel Kachhap .matches = has_address_auth_metacap, 21036984eb47SMark Rutland }, 21046984eb47SMark Rutland { 21056984eb47SMark Rutland .desc = "Generic authentication (architected algorithm)", 21066984eb47SMark Rutland .capability = ARM64_HAS_GENERIC_AUTH_ARCH, 21076984eb47SMark Rutland .type = ARM64_CPUCAP_SYSTEM_FEATURE, 21086984eb47SMark Rutland .sys_reg = SYS_ID_AA64ISAR1_EL1, 21096984eb47SMark Rutland .sign = FTR_UNSIGNED, 21106984eb47SMark Rutland .field_pos = ID_AA64ISAR1_GPA_SHIFT, 21116984eb47SMark Rutland .min_field_value = ID_AA64ISAR1_GPA_ARCHITECTED, 21126984eb47SMark Rutland .matches = has_cpuid_feature, 21136984eb47SMark Rutland }, 21146984eb47SMark Rutland { 21156984eb47SMark Rutland .desc = "Generic authentication (IMP DEF algorithm)", 21166984eb47SMark Rutland .capability = ARM64_HAS_GENERIC_AUTH_IMP_DEF, 21176984eb47SMark Rutland .type = ARM64_CPUCAP_SYSTEM_FEATURE, 21186984eb47SMark Rutland .sys_reg = SYS_ID_AA64ISAR1_EL1, 21196984eb47SMark Rutland .sign = FTR_UNSIGNED, 21206984eb47SMark Rutland .field_pos = ID_AA64ISAR1_GPI_SHIFT, 21216984eb47SMark Rutland .min_field_value = ID_AA64ISAR1_GPI_IMP_DEF, 21226984eb47SMark Rutland .matches = has_cpuid_feature, 21236984eb47SMark Rutland }, 2124cfef06bdSKristina Martsenko { 2125cfef06bdSKristina Martsenko .capability = ARM64_HAS_GENERIC_AUTH, 2126cfef06bdSKristina Martsenko .type = ARM64_CPUCAP_SYSTEM_FEATURE, 2127cfef06bdSKristina Martsenko .matches = has_generic_auth, 2128cfef06bdSKristina Martsenko }, 21296984eb47SMark Rutland #endif /* CONFIG_ARM64_PTR_AUTH */ 2130b90d2b22SJulien Thierry #ifdef CONFIG_ARM64_PSEUDO_NMI 2131b90d2b22SJulien Thierry { 2132b90d2b22SJulien Thierry /* 2133b90d2b22SJulien Thierry * Depends on having GICv3 2134b90d2b22SJulien Thierry */ 2135b90d2b22SJulien Thierry .desc = "IRQ priority masking", 2136b90d2b22SJulien Thierry .capability = ARM64_HAS_IRQ_PRIO_MASKING, 2137b90d2b22SJulien Thierry .type = ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE, 2138b90d2b22SJulien Thierry .matches = can_use_gic_priorities, 2139b90d2b22SJulien Thierry .sys_reg = SYS_ID_AA64PFR0_EL1, 2140b90d2b22SJulien Thierry .field_pos = ID_AA64PFR0_GIC_SHIFT, 2141b90d2b22SJulien Thierry .sign = FTR_UNSIGNED, 2142b90d2b22SJulien Thierry .min_field_value = 1, 2143b90d2b22SJulien Thierry }, 2144b90d2b22SJulien Thierry #endif 21453e6c69a0SMark Brown #ifdef CONFIG_ARM64_E0PD 21463e6c69a0SMark Brown { 21473e6c69a0SMark Brown .desc = "E0PD", 21483e6c69a0SMark Brown .capability = ARM64_HAS_E0PD, 21493e6c69a0SMark Brown .type = ARM64_CPUCAP_SYSTEM_FEATURE, 21503e6c69a0SMark Brown .sys_reg = SYS_ID_AA64MMFR2_EL1, 21513e6c69a0SMark Brown .sign = FTR_UNSIGNED, 21523e6c69a0SMark Brown .field_pos = ID_AA64MMFR2_E0PD_SHIFT, 21533e6c69a0SMark Brown .matches = has_cpuid_feature, 21543e6c69a0SMark Brown .min_field_value = 1, 21553e6c69a0SMark Brown .cpu_enable = cpu_enable_e0pd, 21563e6c69a0SMark Brown }, 21573e6c69a0SMark Brown #endif 21581a50ec0bSRichard Henderson #ifdef CONFIG_ARCH_RANDOM 21591a50ec0bSRichard Henderson { 21601a50ec0bSRichard Henderson .desc = "Random Number Generator", 21611a50ec0bSRichard Henderson .capability = ARM64_HAS_RNG, 21621a50ec0bSRichard Henderson .type = ARM64_CPUCAP_SYSTEM_FEATURE, 21631a50ec0bSRichard Henderson .matches = has_cpuid_feature, 21641a50ec0bSRichard Henderson .sys_reg = SYS_ID_AA64ISAR0_EL1, 21651a50ec0bSRichard Henderson .field_pos = ID_AA64ISAR0_RNDR_SHIFT, 21661a50ec0bSRichard Henderson .sign = FTR_UNSIGNED, 21671a50ec0bSRichard Henderson .min_field_value = 1, 21681a50ec0bSRichard Henderson }, 21691a50ec0bSRichard Henderson #endif 21708ef8f360SDave Martin #ifdef CONFIG_ARM64_BTI 21718ef8f360SDave Martin { 21728ef8f360SDave Martin .desc = "Branch Target Identification", 21738ef8f360SDave Martin .capability = ARM64_BTI, 2174c8027285SMark Brown #ifdef CONFIG_ARM64_BTI_KERNEL 2175c8027285SMark Brown .type = ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE, 2176c8027285SMark Brown #else 21778ef8f360SDave Martin .type = ARM64_CPUCAP_SYSTEM_FEATURE, 2178c8027285SMark Brown #endif 21798ef8f360SDave Martin .matches = has_cpuid_feature, 21808ef8f360SDave Martin .cpu_enable = bti_enable, 21818ef8f360SDave Martin .sys_reg = SYS_ID_AA64PFR1_EL1, 21828ef8f360SDave Martin .field_pos = ID_AA64PFR1_BT_SHIFT, 21838ef8f360SDave Martin .min_field_value = ID_AA64PFR1_BT_BTI, 21848ef8f360SDave Martin .sign = FTR_UNSIGNED, 21858ef8f360SDave Martin }, 21868ef8f360SDave Martin #endif 21873b714d24SVincenzo Frascino #ifdef CONFIG_ARM64_MTE 21883b714d24SVincenzo Frascino { 21893b714d24SVincenzo Frascino .desc = "Memory Tagging Extension", 21903b714d24SVincenzo Frascino .capability = ARM64_MTE, 21913b714d24SVincenzo Frascino .type = ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE, 21923b714d24SVincenzo Frascino .matches = has_cpuid_feature, 21933b714d24SVincenzo Frascino .sys_reg = SYS_ID_AA64PFR1_EL1, 21943b714d24SVincenzo Frascino .field_pos = ID_AA64PFR1_MTE_SHIFT, 21953b714d24SVincenzo Frascino .min_field_value = ID_AA64PFR1_MTE, 21963b714d24SVincenzo Frascino .sign = FTR_UNSIGNED, 219734bfeea4SCatalin Marinas .cpu_enable = cpu_enable_mte, 21983b714d24SVincenzo Frascino }, 21993b714d24SVincenzo Frascino #endif /* CONFIG_ARM64_MTE */ 2200364a5a8aSWill Deacon { 2201364a5a8aSWill Deacon .desc = "RCpc load-acquire (LDAPR)", 2202364a5a8aSWill Deacon .capability = ARM64_HAS_LDAPR, 2203364a5a8aSWill Deacon .type = ARM64_CPUCAP_SYSTEM_FEATURE, 2204364a5a8aSWill Deacon .sys_reg = SYS_ID_AA64ISAR1_EL1, 2205364a5a8aSWill Deacon .sign = FTR_UNSIGNED, 2206364a5a8aSWill Deacon .field_pos = ID_AA64ISAR1_LRCPC_SHIFT, 2207364a5a8aSWill Deacon .matches = has_cpuid_feature, 2208364a5a8aSWill Deacon .min_field_value = 1, 2209364a5a8aSWill Deacon }, 2210359b7064SMarc Zyngier {}, 2211359b7064SMarc Zyngier }; 2212359b7064SMarc Zyngier 22131e013d06SWill Deacon #define HWCAP_CPUID_MATCH(reg, field, s, min_value) \ 221437b01d53SSuzuki K. Poulose .matches = has_cpuid_feature, \ 221537b01d53SSuzuki K. Poulose .sys_reg = reg, \ 221637b01d53SSuzuki K. Poulose .field_pos = field, \ 2217ff96f7bcSSuzuki K Poulose .sign = s, \ 22181e013d06SWill Deacon .min_field_value = min_value, 22191e013d06SWill Deacon 22201e013d06SWill Deacon #define __HWCAP_CAP(name, cap_type, cap) \ 22211e013d06SWill Deacon .desc = name, \ 22221e013d06SWill Deacon .type = ARM64_CPUCAP_SYSTEM_FEATURE, \ 2223143ba05dSSuzuki K Poulose .hwcap_type = cap_type, \ 222437b01d53SSuzuki K. Poulose .hwcap = cap, \ 22251e013d06SWill Deacon 22261e013d06SWill Deacon #define HWCAP_CAP(reg, field, s, min_value, cap_type, cap) \ 22271e013d06SWill Deacon { \ 22281e013d06SWill Deacon __HWCAP_CAP(#cap, cap_type, cap) \ 22291e013d06SWill Deacon HWCAP_CPUID_MATCH(reg, field, s, min_value) \ 223037b01d53SSuzuki K. Poulose } 223137b01d53SSuzuki K. Poulose 22321e013d06SWill Deacon #define HWCAP_MULTI_CAP(list, cap_type, cap) \ 22331e013d06SWill Deacon { \ 22341e013d06SWill Deacon __HWCAP_CAP(#cap, cap_type, cap) \ 22351e013d06SWill Deacon .matches = cpucap_multi_entry_cap_matches, \ 22361e013d06SWill Deacon .match_list = list, \ 22371e013d06SWill Deacon } 22381e013d06SWill Deacon 22397559950aSSuzuki K Poulose #define HWCAP_CAP_MATCH(match, cap_type, cap) \ 22407559950aSSuzuki K Poulose { \ 22417559950aSSuzuki K Poulose __HWCAP_CAP(#cap, cap_type, cap) \ 22427559950aSSuzuki K Poulose .matches = match, \ 22437559950aSSuzuki K Poulose } 22447559950aSSuzuki K Poulose 22451e013d06SWill Deacon #ifdef CONFIG_ARM64_PTR_AUTH 22461e013d06SWill Deacon static const struct arm64_cpu_capabilities ptr_auth_hwcap_addr_matches[] = { 22471e013d06SWill Deacon { 22481e013d06SWill Deacon HWCAP_CPUID_MATCH(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_APA_SHIFT, 22491e013d06SWill Deacon FTR_UNSIGNED, ID_AA64ISAR1_APA_ARCHITECTED) 22501e013d06SWill Deacon }, 22511e013d06SWill Deacon { 22521e013d06SWill Deacon HWCAP_CPUID_MATCH(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_API_SHIFT, 22531e013d06SWill Deacon FTR_UNSIGNED, ID_AA64ISAR1_API_IMP_DEF) 22541e013d06SWill Deacon }, 22551e013d06SWill Deacon {}, 22561e013d06SWill Deacon }; 22571e013d06SWill Deacon 22581e013d06SWill Deacon static const struct arm64_cpu_capabilities ptr_auth_hwcap_gen_matches[] = { 22591e013d06SWill Deacon { 22601e013d06SWill Deacon HWCAP_CPUID_MATCH(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_GPA_SHIFT, 22611e013d06SWill Deacon FTR_UNSIGNED, ID_AA64ISAR1_GPA_ARCHITECTED) 22621e013d06SWill Deacon }, 22631e013d06SWill Deacon { 22641e013d06SWill Deacon HWCAP_CPUID_MATCH(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_GPI_SHIFT, 22651e013d06SWill Deacon FTR_UNSIGNED, ID_AA64ISAR1_GPI_IMP_DEF) 22661e013d06SWill Deacon }, 22671e013d06SWill Deacon {}, 22681e013d06SWill Deacon }; 22691e013d06SWill Deacon #endif 22701e013d06SWill Deacon 2271f3efb675SSuzuki K Poulose static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { 2272aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, KERNEL_HWCAP_PMULL), 2273aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_AES_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_AES), 2274aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_SHA1), 2275aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA2_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_SHA2), 2276aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA2_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, KERNEL_HWCAP_SHA512), 2277aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_CRC32_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_CRC32), 2278aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_ATOMICS_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, KERNEL_HWCAP_ATOMICS), 2279aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_RDM_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ASIMDRDM), 2280aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SHA3_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_SHA3), 2281aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SM3_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_SM3), 2282aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_SM4_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_SM4), 2283aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_DP_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ASIMDDP), 2284aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_FHM_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ASIMDFHM), 2285aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_TS_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_FLAGM), 228612019374SMark Brown HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_TS_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, KERNEL_HWCAP_FLAGM2), 22871a50ec0bSRichard Henderson HWCAP_CAP(SYS_ID_AA64ISAR0_EL1, ID_AA64ISAR0_RNDR_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_RNG), 2288aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, KERNEL_HWCAP_FP), 2289aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_FP_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_FPHP), 2290aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 0, CAP_HWCAP, KERNEL_HWCAP_ASIMD), 2291aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_ASIMD_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ASIMDHP), 2292aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_DIT_SHIFT, FTR_SIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_DIT), 2293aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_DPB_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_DCPOP), 2294671db581SAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_DPB_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, KERNEL_HWCAP_DCPODP), 2295aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_JSCVT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_JSCVT), 2296aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_FCMA_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_FCMA), 2297aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_LRCPC), 2298aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 2, CAP_HWCAP, KERNEL_HWCAP_ILRCPC), 2299ca9503fcSMark Brown HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_FRINTTS_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_FRINT), 2300aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_SB_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_SB), 2301d4209d8bSSteven Price HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_BF16_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_BF16), 2302d4209d8bSSteven Price HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_DGH_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_DGH), 2303d4209d8bSSteven Price HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_I8MM_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_I8MM), 2304aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64MMFR2_EL1, ID_AA64MMFR2_AT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_USCAT), 230543994d82SDave Martin #ifdef CONFIG_ARM64_SVE 2306aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_SVE_SHIFT, FTR_UNSIGNED, ID_AA64PFR0_SVE, CAP_HWCAP, KERNEL_HWCAP_SVE), 230706a916feSDave Martin HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_SVEVER_SHIFT, FTR_UNSIGNED, ID_AA64ZFR0_SVEVER_SVE2, CAP_HWCAP, KERNEL_HWCAP_SVE2), 230806a916feSDave Martin HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_AES_SHIFT, FTR_UNSIGNED, ID_AA64ZFR0_AES, CAP_HWCAP, KERNEL_HWCAP_SVEAES), 230906a916feSDave Martin HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_AES_SHIFT, FTR_UNSIGNED, ID_AA64ZFR0_AES_PMULL, CAP_HWCAP, KERNEL_HWCAP_SVEPMULL), 231006a916feSDave Martin HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_BITPERM_SHIFT, FTR_UNSIGNED, ID_AA64ZFR0_BITPERM, CAP_HWCAP, KERNEL_HWCAP_SVEBITPERM), 2311d4209d8bSSteven Price HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_BF16_SHIFT, FTR_UNSIGNED, ID_AA64ZFR0_BF16, CAP_HWCAP, KERNEL_HWCAP_SVEBF16), 231206a916feSDave Martin HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_SHA3_SHIFT, FTR_UNSIGNED, ID_AA64ZFR0_SHA3, CAP_HWCAP, KERNEL_HWCAP_SVESHA3), 231306a916feSDave Martin HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_SM4_SHIFT, FTR_UNSIGNED, ID_AA64ZFR0_SM4, CAP_HWCAP, KERNEL_HWCAP_SVESM4), 2314d4209d8bSSteven Price HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_I8MM_SHIFT, FTR_UNSIGNED, ID_AA64ZFR0_I8MM, CAP_HWCAP, KERNEL_HWCAP_SVEI8MM), 2315d4209d8bSSteven Price HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_F32MM_SHIFT, FTR_UNSIGNED, ID_AA64ZFR0_F32MM, CAP_HWCAP, KERNEL_HWCAP_SVEF32MM), 2316d4209d8bSSteven Price HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_F64MM_SHIFT, FTR_UNSIGNED, ID_AA64ZFR0_F64MM, CAP_HWCAP, KERNEL_HWCAP_SVEF64MM), 231743994d82SDave Martin #endif 2318aaba098fSAndrew Murray HWCAP_CAP(SYS_ID_AA64PFR1_EL1, ID_AA64PFR1_SSBS_SHIFT, FTR_UNSIGNED, ID_AA64PFR1_SSBS_PSTATE_INSNS, CAP_HWCAP, KERNEL_HWCAP_SSBS), 23198ef8f360SDave Martin #ifdef CONFIG_ARM64_BTI 23208ef8f360SDave Martin HWCAP_CAP(SYS_ID_AA64PFR1_EL1, ID_AA64PFR1_BT_SHIFT, FTR_UNSIGNED, ID_AA64PFR1_BT_BTI, CAP_HWCAP, KERNEL_HWCAP_BTI), 23218ef8f360SDave Martin #endif 232275031975SMark Rutland #ifdef CONFIG_ARM64_PTR_AUTH 2323aaba098fSAndrew Murray HWCAP_MULTI_CAP(ptr_auth_hwcap_addr_matches, CAP_HWCAP, KERNEL_HWCAP_PACA), 2324aaba098fSAndrew Murray HWCAP_MULTI_CAP(ptr_auth_hwcap_gen_matches, CAP_HWCAP, KERNEL_HWCAP_PACG), 232575031975SMark Rutland #endif 23263b714d24SVincenzo Frascino #ifdef CONFIG_ARM64_MTE 23273b714d24SVincenzo Frascino HWCAP_CAP(SYS_ID_AA64PFR1_EL1, ID_AA64PFR1_MTE_SHIFT, FTR_UNSIGNED, ID_AA64PFR1_MTE, CAP_HWCAP, KERNEL_HWCAP_MTE), 23283b714d24SVincenzo Frascino #endif /* CONFIG_ARM64_MTE */ 232975283501SSuzuki K Poulose {}, 233075283501SSuzuki K Poulose }; 233175283501SSuzuki K Poulose 23327559950aSSuzuki K Poulose #ifdef CONFIG_COMPAT 23337559950aSSuzuki K Poulose static bool compat_has_neon(const struct arm64_cpu_capabilities *cap, int scope) 23347559950aSSuzuki K Poulose { 23357559950aSSuzuki K Poulose /* 23367559950aSSuzuki K Poulose * Check that all of MVFR1_EL1.{SIMDSP, SIMDInt, SIMDLS} are available, 23377559950aSSuzuki K Poulose * in line with that of arm32 as in vfp_init(). We make sure that the 23387559950aSSuzuki K Poulose * check is future proof, by making sure value is non-zero. 23397559950aSSuzuki K Poulose */ 23407559950aSSuzuki K Poulose u32 mvfr1; 23417559950aSSuzuki K Poulose 23427559950aSSuzuki K Poulose WARN_ON(scope == SCOPE_LOCAL_CPU && preemptible()); 23437559950aSSuzuki K Poulose if (scope == SCOPE_SYSTEM) 23447559950aSSuzuki K Poulose mvfr1 = read_sanitised_ftr_reg(SYS_MVFR1_EL1); 23457559950aSSuzuki K Poulose else 23467559950aSSuzuki K Poulose mvfr1 = read_sysreg_s(SYS_MVFR1_EL1); 23477559950aSSuzuki K Poulose 23487559950aSSuzuki K Poulose return cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDSP_SHIFT) && 23497559950aSSuzuki K Poulose cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDINT_SHIFT) && 23507559950aSSuzuki K Poulose cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDLS_SHIFT); 23517559950aSSuzuki K Poulose } 23527559950aSSuzuki K Poulose #endif 23537559950aSSuzuki K Poulose 235475283501SSuzuki K Poulose static const struct arm64_cpu_capabilities compat_elf_hwcaps[] = { 235537b01d53SSuzuki K. Poulose #ifdef CONFIG_COMPAT 23567559950aSSuzuki K Poulose HWCAP_CAP_MATCH(compat_has_neon, CAP_COMPAT_HWCAP, COMPAT_HWCAP_NEON), 23577559950aSSuzuki K Poulose HWCAP_CAP(SYS_MVFR1_EL1, MVFR1_SIMDFMAC_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv4), 23587559950aSSuzuki K Poulose /* Arm v8 mandates MVFR0.FPDP == {0, 2}. So, piggy back on this for the presence of VFP support */ 23597559950aSSuzuki K Poulose HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_FPDP_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFP), 23607559950aSSuzuki K Poulose HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_FPDP_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv3), 2361ff96f7bcSSuzuki K Poulose HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL), 2362ff96f7bcSSuzuki K Poulose HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES), 2363ff96f7bcSSuzuki K Poulose HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA1), 2364ff96f7bcSSuzuki K Poulose HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA2_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA2), 2365ff96f7bcSSuzuki K Poulose HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_CRC32_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_CRC32), 236637b01d53SSuzuki K. Poulose #endif 236737b01d53SSuzuki K. Poulose {}, 236837b01d53SSuzuki K. Poulose }; 236937b01d53SSuzuki K. Poulose 2370f3efb675SSuzuki K Poulose static void __init cap_set_elf_hwcap(const struct arm64_cpu_capabilities *cap) 237137b01d53SSuzuki K. Poulose { 237237b01d53SSuzuki K. Poulose switch (cap->hwcap_type) { 237337b01d53SSuzuki K. Poulose case CAP_HWCAP: 2374aaba098fSAndrew Murray cpu_set_feature(cap->hwcap); 237537b01d53SSuzuki K. Poulose break; 237637b01d53SSuzuki K. Poulose #ifdef CONFIG_COMPAT 237737b01d53SSuzuki K. Poulose case CAP_COMPAT_HWCAP: 237837b01d53SSuzuki K. Poulose compat_elf_hwcap |= (u32)cap->hwcap; 237937b01d53SSuzuki K. Poulose break; 238037b01d53SSuzuki K. Poulose case CAP_COMPAT_HWCAP2: 238137b01d53SSuzuki K. Poulose compat_elf_hwcap2 |= (u32)cap->hwcap; 238237b01d53SSuzuki K. Poulose break; 238337b01d53SSuzuki K. Poulose #endif 238437b01d53SSuzuki K. Poulose default: 238537b01d53SSuzuki K. Poulose WARN_ON(1); 238637b01d53SSuzuki K. Poulose break; 238737b01d53SSuzuki K. Poulose } 238837b01d53SSuzuki K. Poulose } 238937b01d53SSuzuki K. Poulose 239037b01d53SSuzuki K. Poulose /* Check if we have a particular HWCAP enabled */ 2391f3efb675SSuzuki K Poulose static bool cpus_have_elf_hwcap(const struct arm64_cpu_capabilities *cap) 239237b01d53SSuzuki K. Poulose { 239337b01d53SSuzuki K. Poulose bool rc; 239437b01d53SSuzuki K. Poulose 239537b01d53SSuzuki K. Poulose switch (cap->hwcap_type) { 239637b01d53SSuzuki K. Poulose case CAP_HWCAP: 2397aaba098fSAndrew Murray rc = cpu_have_feature(cap->hwcap); 239837b01d53SSuzuki K. Poulose break; 239937b01d53SSuzuki K. Poulose #ifdef CONFIG_COMPAT 240037b01d53SSuzuki K. Poulose case CAP_COMPAT_HWCAP: 240137b01d53SSuzuki K. Poulose rc = (compat_elf_hwcap & (u32)cap->hwcap) != 0; 240237b01d53SSuzuki K. Poulose break; 240337b01d53SSuzuki K. Poulose case CAP_COMPAT_HWCAP2: 240437b01d53SSuzuki K. Poulose rc = (compat_elf_hwcap2 & (u32)cap->hwcap) != 0; 240537b01d53SSuzuki K. Poulose break; 240637b01d53SSuzuki K. Poulose #endif 240737b01d53SSuzuki K. Poulose default: 240837b01d53SSuzuki K. Poulose WARN_ON(1); 240937b01d53SSuzuki K. Poulose rc = false; 241037b01d53SSuzuki K. Poulose } 241137b01d53SSuzuki K. Poulose 241237b01d53SSuzuki K. Poulose return rc; 241337b01d53SSuzuki K. Poulose } 241437b01d53SSuzuki K. Poulose 241575283501SSuzuki K Poulose static void __init setup_elf_hwcaps(const struct arm64_cpu_capabilities *hwcaps) 241637b01d53SSuzuki K. Poulose { 241777c97b4eSSuzuki K Poulose /* We support emulation of accesses to CPU ID feature registers */ 2418aaba098fSAndrew Murray cpu_set_named_feature(CPUID); 241975283501SSuzuki K Poulose for (; hwcaps->matches; hwcaps++) 2420143ba05dSSuzuki K Poulose if (hwcaps->matches(hwcaps, cpucap_default_scope(hwcaps))) 242175283501SSuzuki K Poulose cap_set_elf_hwcap(hwcaps); 242237b01d53SSuzuki K. Poulose } 242337b01d53SSuzuki K. Poulose 2424606f8e7bSSuzuki K Poulose static void update_cpu_capabilities(u16 scope_mask) 242567948af4SSuzuki K Poulose { 2426606f8e7bSSuzuki K Poulose int i; 242767948af4SSuzuki K Poulose const struct arm64_cpu_capabilities *caps; 242867948af4SSuzuki K Poulose 2429cce360b5SSuzuki K Poulose scope_mask &= ARM64_CPUCAP_SCOPE_MASK; 2430606f8e7bSSuzuki K Poulose for (i = 0; i < ARM64_NCAPS; i++) { 2431606f8e7bSSuzuki K Poulose caps = cpu_hwcaps_ptrs[i]; 2432606f8e7bSSuzuki K Poulose if (!caps || !(caps->type & scope_mask) || 2433606f8e7bSSuzuki K Poulose cpus_have_cap(caps->capability) || 2434cce360b5SSuzuki K Poulose !caps->matches(caps, cpucap_default_scope(caps))) 2435359b7064SMarc Zyngier continue; 2436359b7064SMarc Zyngier 2437606f8e7bSSuzuki K Poulose if (caps->desc) 2438606f8e7bSSuzuki K Poulose pr_info("detected: %s\n", caps->desc); 243975283501SSuzuki K Poulose cpus_set_cap(caps->capability); 24400ceb0d56SDaniel Thompson 24410ceb0d56SDaniel Thompson if ((scope_mask & SCOPE_BOOT_CPU) && (caps->type & SCOPE_BOOT_CPU)) 24420ceb0d56SDaniel Thompson set_bit(caps->capability, boot_capabilities); 2443359b7064SMarc Zyngier } 2444359b7064SMarc Zyngier } 2445359b7064SMarc Zyngier 24460b587c84SSuzuki K Poulose /* 24470b587c84SSuzuki K Poulose * Enable all the available capabilities on this CPU. The capabilities 24480b587c84SSuzuki K Poulose * with BOOT_CPU scope are handled separately and hence skipped here. 24490b587c84SSuzuki K Poulose */ 24500b587c84SSuzuki K Poulose static int cpu_enable_non_boot_scope_capabilities(void *__unused) 2451ed478b3fSSuzuki K Poulose { 24520b587c84SSuzuki K Poulose int i; 24530b587c84SSuzuki K Poulose u16 non_boot_scope = SCOPE_ALL & ~SCOPE_BOOT_CPU; 2454ed478b3fSSuzuki K Poulose 24550b587c84SSuzuki K Poulose for_each_available_cap(i) { 24560b587c84SSuzuki K Poulose const struct arm64_cpu_capabilities *cap = cpu_hwcaps_ptrs[i]; 2457c0cda3b8SDave Martin 24580b587c84SSuzuki K Poulose if (WARN_ON(!cap)) 24590b587c84SSuzuki K Poulose continue; 24600b587c84SSuzuki K Poulose 24610b587c84SSuzuki K Poulose if (!(cap->type & non_boot_scope)) 24620b587c84SSuzuki K Poulose continue; 24630b587c84SSuzuki K Poulose 24640b587c84SSuzuki K Poulose if (cap->cpu_enable) 2465c0cda3b8SDave Martin cap->cpu_enable(cap); 24660b587c84SSuzuki K Poulose } 2467c0cda3b8SDave Martin return 0; 2468c0cda3b8SDave Martin } 2469c0cda3b8SDave Martin 2470ce8b602cSSuzuki K. Poulose /* 2471dbb4e152SSuzuki K. Poulose * Run through the enabled capabilities and enable() it on all active 2472dbb4e152SSuzuki K. Poulose * CPUs 2473ce8b602cSSuzuki K. Poulose */ 24740b587c84SSuzuki K Poulose static void __init enable_cpu_capabilities(u16 scope_mask) 2475359b7064SMarc Zyngier { 24760b587c84SSuzuki K Poulose int i; 24770b587c84SSuzuki K Poulose const struct arm64_cpu_capabilities *caps; 24780b587c84SSuzuki K Poulose bool boot_scope; 247963a1e1c9SMark Rutland 24800b587c84SSuzuki K Poulose scope_mask &= ARM64_CPUCAP_SCOPE_MASK; 24810b587c84SSuzuki K Poulose boot_scope = !!(scope_mask & SCOPE_BOOT_CPU); 24820b587c84SSuzuki K Poulose 24830b587c84SSuzuki K Poulose for (i = 0; i < ARM64_NCAPS; i++) { 24840b587c84SSuzuki K Poulose unsigned int num; 24850b587c84SSuzuki K Poulose 24860b587c84SSuzuki K Poulose caps = cpu_hwcaps_ptrs[i]; 24870b587c84SSuzuki K Poulose if (!caps || !(caps->type & scope_mask)) 24880b587c84SSuzuki K Poulose continue; 24890b587c84SSuzuki K Poulose num = caps->capability; 24900b587c84SSuzuki K Poulose if (!cpus_have_cap(num)) 249163a1e1c9SMark Rutland continue; 249263a1e1c9SMark Rutland 249363a1e1c9SMark Rutland /* Ensure cpus_have_const_cap(num) works */ 249463a1e1c9SMark Rutland static_branch_enable(&cpu_hwcap_keys[num]); 249563a1e1c9SMark Rutland 24960b587c84SSuzuki K Poulose if (boot_scope && caps->cpu_enable) 24972a6dcb2bSJames Morse /* 2498fd9d63daSSuzuki K Poulose * Capabilities with SCOPE_BOOT_CPU scope are finalised 2499fd9d63daSSuzuki K Poulose * before any secondary CPU boots. Thus, each secondary 2500fd9d63daSSuzuki K Poulose * will enable the capability as appropriate via 2501fd9d63daSSuzuki K Poulose * check_local_cpu_capabilities(). The only exception is 2502fd9d63daSSuzuki K Poulose * the boot CPU, for which the capability must be 2503fd9d63daSSuzuki K Poulose * enabled here. This approach avoids costly 2504fd9d63daSSuzuki K Poulose * stop_machine() calls for this case. 25052a6dcb2bSJames Morse */ 2506fd9d63daSSuzuki K Poulose caps->cpu_enable(caps); 250763a1e1c9SMark Rutland } 2508dbb4e152SSuzuki K. Poulose 25090b587c84SSuzuki K Poulose /* 25100b587c84SSuzuki K Poulose * For all non-boot scope capabilities, use stop_machine() 25110b587c84SSuzuki K Poulose * as it schedules the work allowing us to modify PSTATE, 25120b587c84SSuzuki K Poulose * instead of on_each_cpu() which uses an IPI, giving us a 25130b587c84SSuzuki K Poulose * PSTATE that disappears when we return. 25140b587c84SSuzuki K Poulose */ 25150b587c84SSuzuki K Poulose if (!boot_scope) 25160b587c84SSuzuki K Poulose stop_machine(cpu_enable_non_boot_scope_capabilities, 25170b587c84SSuzuki K Poulose NULL, cpu_online_mask); 2518ed478b3fSSuzuki K Poulose } 2519ed478b3fSSuzuki K Poulose 2520dbb4e152SSuzuki K. Poulose /* 2521eaac4d83SSuzuki K Poulose * Run through the list of capabilities to check for conflicts. 2522eaac4d83SSuzuki K Poulose * If the system has already detected a capability, take necessary 2523eaac4d83SSuzuki K Poulose * action on this CPU. 2524eaac4d83SSuzuki K Poulose */ 2525deeaac51SKristina Martsenko static void verify_local_cpu_caps(u16 scope_mask) 2526eaac4d83SSuzuki K Poulose { 2527606f8e7bSSuzuki K Poulose int i; 2528eaac4d83SSuzuki K Poulose bool cpu_has_cap, system_has_cap; 2529606f8e7bSSuzuki K Poulose const struct arm64_cpu_capabilities *caps; 2530eaac4d83SSuzuki K Poulose 2531cce360b5SSuzuki K Poulose scope_mask &= ARM64_CPUCAP_SCOPE_MASK; 2532cce360b5SSuzuki K Poulose 2533606f8e7bSSuzuki K Poulose for (i = 0; i < ARM64_NCAPS; i++) { 2534606f8e7bSSuzuki K Poulose caps = cpu_hwcaps_ptrs[i]; 2535606f8e7bSSuzuki K Poulose if (!caps || !(caps->type & scope_mask)) 2536cce360b5SSuzuki K Poulose continue; 2537cce360b5SSuzuki K Poulose 2538ba7d9233SSuzuki K Poulose cpu_has_cap = caps->matches(caps, SCOPE_LOCAL_CPU); 2539eaac4d83SSuzuki K Poulose system_has_cap = cpus_have_cap(caps->capability); 2540eaac4d83SSuzuki K Poulose 2541eaac4d83SSuzuki K Poulose if (system_has_cap) { 2542eaac4d83SSuzuki K Poulose /* 2543eaac4d83SSuzuki K Poulose * Check if the new CPU misses an advertised feature, 2544eaac4d83SSuzuki K Poulose * which is not safe to miss. 2545eaac4d83SSuzuki K Poulose */ 2546eaac4d83SSuzuki K Poulose if (!cpu_has_cap && !cpucap_late_cpu_optional(caps)) 2547eaac4d83SSuzuki K Poulose break; 2548eaac4d83SSuzuki K Poulose /* 2549eaac4d83SSuzuki K Poulose * We have to issue cpu_enable() irrespective of 2550eaac4d83SSuzuki K Poulose * whether the CPU has it or not, as it is enabeld 2551eaac4d83SSuzuki K Poulose * system wide. It is upto the call back to take 2552eaac4d83SSuzuki K Poulose * appropriate action on this CPU. 2553eaac4d83SSuzuki K Poulose */ 2554eaac4d83SSuzuki K Poulose if (caps->cpu_enable) 2555eaac4d83SSuzuki K Poulose caps->cpu_enable(caps); 2556eaac4d83SSuzuki K Poulose } else { 2557eaac4d83SSuzuki K Poulose /* 2558eaac4d83SSuzuki K Poulose * Check if the CPU has this capability if it isn't 2559eaac4d83SSuzuki K Poulose * safe to have when the system doesn't. 2560eaac4d83SSuzuki K Poulose */ 2561eaac4d83SSuzuki K Poulose if (cpu_has_cap && !cpucap_late_cpu_permitted(caps)) 2562eaac4d83SSuzuki K Poulose break; 2563eaac4d83SSuzuki K Poulose } 2564eaac4d83SSuzuki K Poulose } 2565eaac4d83SSuzuki K Poulose 2566606f8e7bSSuzuki K Poulose if (i < ARM64_NCAPS) { 2567eaac4d83SSuzuki K Poulose pr_crit("CPU%d: Detected conflict for capability %d (%s), System: %d, CPU: %d\n", 2568eaac4d83SSuzuki K Poulose smp_processor_id(), caps->capability, 2569eaac4d83SSuzuki K Poulose caps->desc, system_has_cap, cpu_has_cap); 2570eaac4d83SSuzuki K Poulose 2571deeaac51SKristina Martsenko if (cpucap_panic_on_conflict(caps)) 2572deeaac51SKristina Martsenko cpu_panic_kernel(); 2573deeaac51SKristina Martsenko else 2574deeaac51SKristina Martsenko cpu_die_early(); 2575deeaac51SKristina Martsenko } 2576eaac4d83SSuzuki K Poulose } 2577eaac4d83SSuzuki K Poulose 2578eaac4d83SSuzuki K Poulose /* 257913f417f3SSuzuki K Poulose * Check for CPU features that are used in early boot 258013f417f3SSuzuki K Poulose * based on the Boot CPU value. 2581dbb4e152SSuzuki K. Poulose */ 258213f417f3SSuzuki K Poulose static void check_early_cpu_features(void) 2583dbb4e152SSuzuki K. Poulose { 258413f417f3SSuzuki K Poulose verify_cpu_asid_bits(); 2585deeaac51SKristina Martsenko 2586deeaac51SKristina Martsenko verify_local_cpu_caps(SCOPE_BOOT_CPU); 2587dbb4e152SSuzuki K. Poulose } 2588dbb4e152SSuzuki K. Poulose 258975283501SSuzuki K Poulose static void 259075283501SSuzuki K Poulose verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps) 259175283501SSuzuki K Poulose { 259275283501SSuzuki K Poulose 259392406f0cSSuzuki K Poulose for (; caps->matches; caps++) 259492406f0cSSuzuki K Poulose if (cpus_have_elf_hwcap(caps) && !caps->matches(caps, SCOPE_LOCAL_CPU)) { 259575283501SSuzuki K Poulose pr_crit("CPU%d: missing HWCAP: %s\n", 259675283501SSuzuki K Poulose smp_processor_id(), caps->desc); 259775283501SSuzuki K Poulose cpu_die_early(); 259875283501SSuzuki K Poulose } 259975283501SSuzuki K Poulose } 260075283501SSuzuki K Poulose 26012e0f2478SDave Martin static void verify_sve_features(void) 26022e0f2478SDave Martin { 26032e0f2478SDave Martin u64 safe_zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1); 26042e0f2478SDave Martin u64 zcr = read_zcr_features(); 26052e0f2478SDave Martin 26062e0f2478SDave Martin unsigned int safe_len = safe_zcr & ZCR_ELx_LEN_MASK; 26072e0f2478SDave Martin unsigned int len = zcr & ZCR_ELx_LEN_MASK; 26082e0f2478SDave Martin 26092e0f2478SDave Martin if (len < safe_len || sve_verify_vq_map()) { 2610d06b76beSDave Martin pr_crit("CPU%d: SVE: vector length support mismatch\n", 26112e0f2478SDave Martin smp_processor_id()); 26122e0f2478SDave Martin cpu_die_early(); 26132e0f2478SDave Martin } 26142e0f2478SDave Martin 26152e0f2478SDave Martin /* Add checks on other ZCR bits here if necessary */ 26162e0f2478SDave Martin } 26172e0f2478SDave Martin 2618c73433fcSAnshuman Khandual static void verify_hyp_capabilities(void) 2619c73433fcSAnshuman Khandual { 2620c73433fcSAnshuman Khandual u64 safe_mmfr1, mmfr0, mmfr1; 2621c73433fcSAnshuman Khandual int parange, ipa_max; 2622c73433fcSAnshuman Khandual unsigned int safe_vmid_bits, vmid_bits; 2623c73433fcSAnshuman Khandual 262445ba7b19SShannon Zhao if (!IS_ENABLED(CONFIG_KVM)) 2625c73433fcSAnshuman Khandual return; 2626c73433fcSAnshuman Khandual 2627c73433fcSAnshuman Khandual safe_mmfr1 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1); 2628c73433fcSAnshuman Khandual mmfr0 = read_cpuid(ID_AA64MMFR0_EL1); 2629c73433fcSAnshuman Khandual mmfr1 = read_cpuid(ID_AA64MMFR1_EL1); 2630c73433fcSAnshuman Khandual 2631c73433fcSAnshuman Khandual /* Verify VMID bits */ 2632c73433fcSAnshuman Khandual safe_vmid_bits = get_vmid_bits(safe_mmfr1); 2633c73433fcSAnshuman Khandual vmid_bits = get_vmid_bits(mmfr1); 2634c73433fcSAnshuman Khandual if (vmid_bits < safe_vmid_bits) { 2635c73433fcSAnshuman Khandual pr_crit("CPU%d: VMID width mismatch\n", smp_processor_id()); 2636c73433fcSAnshuman Khandual cpu_die_early(); 2637c73433fcSAnshuman Khandual } 2638c73433fcSAnshuman Khandual 2639c73433fcSAnshuman Khandual /* Verify IPA range */ 2640f73531f0SAnshuman Khandual parange = cpuid_feature_extract_unsigned_field(mmfr0, 2641f73531f0SAnshuman Khandual ID_AA64MMFR0_PARANGE_SHIFT); 2642c73433fcSAnshuman Khandual ipa_max = id_aa64mmfr0_parange_to_phys_shift(parange); 2643c73433fcSAnshuman Khandual if (ipa_max < get_kvm_ipa_limit()) { 2644c73433fcSAnshuman Khandual pr_crit("CPU%d: IPA range mismatch\n", smp_processor_id()); 2645c73433fcSAnshuman Khandual cpu_die_early(); 2646c73433fcSAnshuman Khandual } 2647c73433fcSAnshuman Khandual } 26481e89baedSSuzuki K Poulose 26491e89baedSSuzuki K Poulose /* 2650dbb4e152SSuzuki K. Poulose * Run through the enabled system capabilities and enable() it on this CPU. 2651dbb4e152SSuzuki K. Poulose * The capabilities were decided based on the available CPUs at the boot time. 2652dbb4e152SSuzuki K. Poulose * Any new CPU should match the system wide status of the capability. If the 2653dbb4e152SSuzuki K. Poulose * new CPU doesn't have a capability which the system now has enabled, we 2654dbb4e152SSuzuki K. Poulose * cannot do anything to fix it up and could cause unexpected failures. So 2655dbb4e152SSuzuki K. Poulose * we park the CPU. 2656dbb4e152SSuzuki K. Poulose */ 2657c47a1900SSuzuki K Poulose static void verify_local_cpu_capabilities(void) 2658dbb4e152SSuzuki K. Poulose { 2659fd9d63daSSuzuki K Poulose /* 2660fd9d63daSSuzuki K Poulose * The capabilities with SCOPE_BOOT_CPU are checked from 2661fd9d63daSSuzuki K Poulose * check_early_cpu_features(), as they need to be verified 2662fd9d63daSSuzuki K Poulose * on all secondary CPUs. 2663fd9d63daSSuzuki K Poulose */ 2664deeaac51SKristina Martsenko verify_local_cpu_caps(SCOPE_ALL & ~SCOPE_BOOT_CPU); 2665ed478b3fSSuzuki K Poulose 266675283501SSuzuki K Poulose verify_local_elf_hwcaps(arm64_elf_hwcaps); 26672e0f2478SDave Martin 2668643d703dSSuzuki K Poulose if (system_supports_32bit_el0()) 266975283501SSuzuki K Poulose verify_local_elf_hwcaps(compat_elf_hwcaps); 26702e0f2478SDave Martin 26712e0f2478SDave Martin if (system_supports_sve()) 26722e0f2478SDave Martin verify_sve_features(); 2673c73433fcSAnshuman Khandual 2674c73433fcSAnshuman Khandual if (is_hyp_mode_available()) 2675c73433fcSAnshuman Khandual verify_hyp_capabilities(); 2676dbb4e152SSuzuki K. Poulose } 2677dbb4e152SSuzuki K. Poulose 2678c47a1900SSuzuki K Poulose void check_local_cpu_capabilities(void) 2679c47a1900SSuzuki K Poulose { 2680c47a1900SSuzuki K Poulose /* 2681c47a1900SSuzuki K Poulose * All secondary CPUs should conform to the early CPU features 2682c47a1900SSuzuki K Poulose * in use by the kernel based on boot CPU. 2683c47a1900SSuzuki K Poulose */ 2684c47a1900SSuzuki K Poulose check_early_cpu_features(); 2685c47a1900SSuzuki K Poulose 2686c47a1900SSuzuki K Poulose /* 2687c47a1900SSuzuki K Poulose * If we haven't finalised the system capabilities, this CPU gets 2688fbd890b9SSuzuki K Poulose * a chance to update the errata work arounds and local features. 2689c47a1900SSuzuki K Poulose * Otherwise, this CPU should verify that it has all the system 2690c47a1900SSuzuki K Poulose * advertised capabilities. 2691c47a1900SSuzuki K Poulose */ 2692b51c6ac2SSuzuki K Poulose if (!system_capabilities_finalized()) 2693ed478b3fSSuzuki K Poulose update_cpu_capabilities(SCOPE_LOCAL_CPU); 2694ed478b3fSSuzuki K Poulose else 2695c47a1900SSuzuki K Poulose verify_local_cpu_capabilities(); 2696c47a1900SSuzuki K Poulose } 2697c47a1900SSuzuki K Poulose 2698fd9d63daSSuzuki K Poulose static void __init setup_boot_cpu_capabilities(void) 2699fd9d63daSSuzuki K Poulose { 2700fd9d63daSSuzuki K Poulose /* Detect capabilities with either SCOPE_BOOT_CPU or SCOPE_LOCAL_CPU */ 2701fd9d63daSSuzuki K Poulose update_cpu_capabilities(SCOPE_BOOT_CPU | SCOPE_LOCAL_CPU); 2702fd9d63daSSuzuki K Poulose /* Enable the SCOPE_BOOT_CPU capabilities alone right away */ 2703fd9d63daSSuzuki K Poulose enable_cpu_capabilities(SCOPE_BOOT_CPU); 2704fd9d63daSSuzuki K Poulose } 2705fd9d63daSSuzuki K Poulose 2706f7bfc14aSSuzuki K Poulose bool this_cpu_has_cap(unsigned int n) 27078f413758SMarc Zyngier { 2708f7bfc14aSSuzuki K Poulose if (!WARN_ON(preemptible()) && n < ARM64_NCAPS) { 2709f7bfc14aSSuzuki K Poulose const struct arm64_cpu_capabilities *cap = cpu_hwcaps_ptrs[n]; 2710f7bfc14aSSuzuki K Poulose 2711f7bfc14aSSuzuki K Poulose if (cap) 2712f7bfc14aSSuzuki K Poulose return cap->matches(cap, SCOPE_LOCAL_CPU); 2713f7bfc14aSSuzuki K Poulose } 2714f7bfc14aSSuzuki K Poulose 2715f7bfc14aSSuzuki K Poulose return false; 27168f413758SMarc Zyngier } 27178f413758SMarc Zyngier 27183ff047f6SAmit Daniel Kachhap /* 27193ff047f6SAmit Daniel Kachhap * This helper function is used in a narrow window when, 27203ff047f6SAmit Daniel Kachhap * - The system wide safe registers are set with all the SMP CPUs and, 27213ff047f6SAmit Daniel Kachhap * - The SYSTEM_FEATURE cpu_hwcaps may not have been set. 27223ff047f6SAmit Daniel Kachhap * In all other cases cpus_have_{const_}cap() should be used. 27233ff047f6SAmit Daniel Kachhap */ 2724701f4906SMark Rutland static bool __maybe_unused __system_matches_cap(unsigned int n) 27253ff047f6SAmit Daniel Kachhap { 27263ff047f6SAmit Daniel Kachhap if (n < ARM64_NCAPS) { 27273ff047f6SAmit Daniel Kachhap const struct arm64_cpu_capabilities *cap = cpu_hwcaps_ptrs[n]; 27283ff047f6SAmit Daniel Kachhap 27293ff047f6SAmit Daniel Kachhap if (cap) 27303ff047f6SAmit Daniel Kachhap return cap->matches(cap, SCOPE_SYSTEM); 27313ff047f6SAmit Daniel Kachhap } 27323ff047f6SAmit Daniel Kachhap return false; 27333ff047f6SAmit Daniel Kachhap } 27343ff047f6SAmit Daniel Kachhap 2735aec0bff7SAndrew Murray void cpu_set_feature(unsigned int num) 2736aec0bff7SAndrew Murray { 2737aec0bff7SAndrew Murray WARN_ON(num >= MAX_CPU_FEATURES); 2738aec0bff7SAndrew Murray elf_hwcap |= BIT(num); 2739aec0bff7SAndrew Murray } 2740aec0bff7SAndrew Murray EXPORT_SYMBOL_GPL(cpu_set_feature); 2741aec0bff7SAndrew Murray 2742aec0bff7SAndrew Murray bool cpu_have_feature(unsigned int num) 2743aec0bff7SAndrew Murray { 2744aec0bff7SAndrew Murray WARN_ON(num >= MAX_CPU_FEATURES); 2745aec0bff7SAndrew Murray return elf_hwcap & BIT(num); 2746aec0bff7SAndrew Murray } 2747aec0bff7SAndrew Murray EXPORT_SYMBOL_GPL(cpu_have_feature); 2748aec0bff7SAndrew Murray 2749aec0bff7SAndrew Murray unsigned long cpu_get_elf_hwcap(void) 2750aec0bff7SAndrew Murray { 2751aec0bff7SAndrew Murray /* 2752aec0bff7SAndrew Murray * We currently only populate the first 32 bits of AT_HWCAP. Please 2753aec0bff7SAndrew Murray * note that for userspace compatibility we guarantee that bits 62 2754aec0bff7SAndrew Murray * and 63 will always be returned as 0. 2755aec0bff7SAndrew Murray */ 2756aec0bff7SAndrew Murray return lower_32_bits(elf_hwcap); 2757aec0bff7SAndrew Murray } 2758aec0bff7SAndrew Murray 2759aec0bff7SAndrew Murray unsigned long cpu_get_elf_hwcap2(void) 2760aec0bff7SAndrew Murray { 2761aec0bff7SAndrew Murray return upper_32_bits(elf_hwcap); 2762aec0bff7SAndrew Murray } 2763aec0bff7SAndrew Murray 2764ed478b3fSSuzuki K Poulose static void __init setup_system_capabilities(void) 2765ed478b3fSSuzuki K Poulose { 2766ed478b3fSSuzuki K Poulose /* 2767ed478b3fSSuzuki K Poulose * We have finalised the system-wide safe feature 2768ed478b3fSSuzuki K Poulose * registers, finalise the capabilities that depend 2769fd9d63daSSuzuki K Poulose * on it. Also enable all the available capabilities, 2770fd9d63daSSuzuki K Poulose * that are not enabled already. 2771ed478b3fSSuzuki K Poulose */ 2772ed478b3fSSuzuki K Poulose update_cpu_capabilities(SCOPE_SYSTEM); 2773fd9d63daSSuzuki K Poulose enable_cpu_capabilities(SCOPE_ALL & ~SCOPE_BOOT_CPU); 2774ed478b3fSSuzuki K Poulose } 2775ed478b3fSSuzuki K Poulose 27769cdf8ec4SSuzuki K. Poulose void __init setup_cpu_features(void) 27779cdf8ec4SSuzuki K. Poulose { 27789cdf8ec4SSuzuki K. Poulose u32 cwg; 27799cdf8ec4SSuzuki K. Poulose 2780ed478b3fSSuzuki K Poulose setup_system_capabilities(); 278175283501SSuzuki K Poulose setup_elf_hwcaps(arm64_elf_hwcaps); 2782643d703dSSuzuki K Poulose 2783643d703dSSuzuki K Poulose if (system_supports_32bit_el0()) 278475283501SSuzuki K Poulose setup_elf_hwcaps(compat_elf_hwcaps); 2785dbb4e152SSuzuki K. Poulose 27862e6f549fSKees Cook if (system_uses_ttbr0_pan()) 27872e6f549fSKees Cook pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n"); 27882e6f549fSKees Cook 27892e0f2478SDave Martin sve_setup(); 279094b07c1fSDave Martin minsigstksz_setup(); 27912e0f2478SDave Martin 2792dbb4e152SSuzuki K. Poulose /* Advertise that we have computed the system capabilities */ 2793b51c6ac2SSuzuki K Poulose finalize_system_capabilities(); 2794dbb4e152SSuzuki K. Poulose 27959cdf8ec4SSuzuki K. Poulose /* 27969cdf8ec4SSuzuki K. Poulose * Check for sane CTR_EL0.CWG value. 27979cdf8ec4SSuzuki K. Poulose */ 27989cdf8ec4SSuzuki K. Poulose cwg = cache_type_cwg(); 27999cdf8ec4SSuzuki K. Poulose if (!cwg) 2800ebc7e21eSCatalin Marinas pr_warn("No Cache Writeback Granule information, assuming %d\n", 2801ebc7e21eSCatalin Marinas ARCH_DMA_MINALIGN); 2802359b7064SMarc Zyngier } 280370544196SJames Morse 28045ffdfaedSVladimir Murzin static void __maybe_unused cpu_enable_cnp(struct arm64_cpu_capabilities const *cap) 28055ffdfaedSVladimir Murzin { 28065ffdfaedSVladimir Murzin cpu_replace_ttbr1(lm_alias(swapper_pg_dir)); 28075ffdfaedSVladimir Murzin } 28085ffdfaedSVladimir Murzin 280977c97b4eSSuzuki K Poulose /* 281077c97b4eSSuzuki K Poulose * We emulate only the following system register space. 281177c97b4eSSuzuki K Poulose * Op0 = 0x3, CRn = 0x0, Op1 = 0x0, CRm = [0, 4 - 7] 281277c97b4eSSuzuki K Poulose * See Table C5-6 System instruction encodings for System register accesses, 281377c97b4eSSuzuki K Poulose * ARMv8 ARM(ARM DDI 0487A.f) for more details. 281477c97b4eSSuzuki K Poulose */ 281577c97b4eSSuzuki K Poulose static inline bool __attribute_const__ is_emulated(u32 id) 281677c97b4eSSuzuki K Poulose { 281777c97b4eSSuzuki K Poulose return (sys_reg_Op0(id) == 0x3 && 281877c97b4eSSuzuki K Poulose sys_reg_CRn(id) == 0x0 && 281977c97b4eSSuzuki K Poulose sys_reg_Op1(id) == 0x0 && 282077c97b4eSSuzuki K Poulose (sys_reg_CRm(id) == 0 || 282177c97b4eSSuzuki K Poulose ((sys_reg_CRm(id) >= 4) && (sys_reg_CRm(id) <= 7)))); 282277c97b4eSSuzuki K Poulose } 282377c97b4eSSuzuki K Poulose 282477c97b4eSSuzuki K Poulose /* 282577c97b4eSSuzuki K Poulose * With CRm == 0, reg should be one of : 282677c97b4eSSuzuki K Poulose * MIDR_EL1, MPIDR_EL1 or REVIDR_EL1. 282777c97b4eSSuzuki K Poulose */ 282877c97b4eSSuzuki K Poulose static inline int emulate_id_reg(u32 id, u64 *valp) 282977c97b4eSSuzuki K Poulose { 283077c97b4eSSuzuki K Poulose switch (id) { 283177c97b4eSSuzuki K Poulose case SYS_MIDR_EL1: 283277c97b4eSSuzuki K Poulose *valp = read_cpuid_id(); 283377c97b4eSSuzuki K Poulose break; 283477c97b4eSSuzuki K Poulose case SYS_MPIDR_EL1: 283577c97b4eSSuzuki K Poulose *valp = SYS_MPIDR_SAFE_VAL; 283677c97b4eSSuzuki K Poulose break; 283777c97b4eSSuzuki K Poulose case SYS_REVIDR_EL1: 283877c97b4eSSuzuki K Poulose /* IMPLEMENTATION DEFINED values are emulated with 0 */ 283977c97b4eSSuzuki K Poulose *valp = 0; 284077c97b4eSSuzuki K Poulose break; 284177c97b4eSSuzuki K Poulose default: 284277c97b4eSSuzuki K Poulose return -EINVAL; 284377c97b4eSSuzuki K Poulose } 284477c97b4eSSuzuki K Poulose 284577c97b4eSSuzuki K Poulose return 0; 284677c97b4eSSuzuki K Poulose } 284777c97b4eSSuzuki K Poulose 284877c97b4eSSuzuki K Poulose static int emulate_sys_reg(u32 id, u64 *valp) 284977c97b4eSSuzuki K Poulose { 285077c97b4eSSuzuki K Poulose struct arm64_ftr_reg *regp; 285177c97b4eSSuzuki K Poulose 285277c97b4eSSuzuki K Poulose if (!is_emulated(id)) 285377c97b4eSSuzuki K Poulose return -EINVAL; 285477c97b4eSSuzuki K Poulose 285577c97b4eSSuzuki K Poulose if (sys_reg_CRm(id) == 0) 285677c97b4eSSuzuki K Poulose return emulate_id_reg(id, valp); 285777c97b4eSSuzuki K Poulose 28583577dd37SAnshuman Khandual regp = get_arm64_ftr_reg_nowarn(id); 285977c97b4eSSuzuki K Poulose if (regp) 286077c97b4eSSuzuki K Poulose *valp = arm64_ftr_reg_user_value(regp); 286177c97b4eSSuzuki K Poulose else 286277c97b4eSSuzuki K Poulose /* 286377c97b4eSSuzuki K Poulose * The untracked registers are either IMPLEMENTATION DEFINED 286477c97b4eSSuzuki K Poulose * (e.g, ID_AFR0_EL1) or reserved RAZ. 286577c97b4eSSuzuki K Poulose */ 286677c97b4eSSuzuki K Poulose *valp = 0; 286777c97b4eSSuzuki K Poulose return 0; 286877c97b4eSSuzuki K Poulose } 286977c97b4eSSuzuki K Poulose 2870520ad988SAnshuman Khandual int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt) 287177c97b4eSSuzuki K Poulose { 287277c97b4eSSuzuki K Poulose int rc; 287377c97b4eSSuzuki K Poulose u64 val; 287477c97b4eSSuzuki K Poulose 2875520ad988SAnshuman Khandual rc = emulate_sys_reg(sys_reg, &val); 2876520ad988SAnshuman Khandual if (!rc) { 2877520ad988SAnshuman Khandual pt_regs_write_reg(regs, rt, val); 2878520ad988SAnshuman Khandual arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); 2879520ad988SAnshuman Khandual } 2880520ad988SAnshuman Khandual return rc; 2881520ad988SAnshuman Khandual } 2882520ad988SAnshuman Khandual 2883520ad988SAnshuman Khandual static int emulate_mrs(struct pt_regs *regs, u32 insn) 2884520ad988SAnshuman Khandual { 2885520ad988SAnshuman Khandual u32 sys_reg, rt; 2886520ad988SAnshuman Khandual 288777c97b4eSSuzuki K Poulose /* 288877c97b4eSSuzuki K Poulose * sys_reg values are defined as used in mrs/msr instruction. 288977c97b4eSSuzuki K Poulose * shift the imm value to get the encoding. 289077c97b4eSSuzuki K Poulose */ 289177c97b4eSSuzuki K Poulose sys_reg = (u32)aarch64_insn_decode_immediate(AARCH64_INSN_IMM_16, insn) << 5; 2892520ad988SAnshuman Khandual rt = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RT, insn); 2893520ad988SAnshuman Khandual return do_emulate_mrs(regs, sys_reg, rt); 289477c97b4eSSuzuki K Poulose } 289577c97b4eSSuzuki K Poulose 289677c97b4eSSuzuki K Poulose static struct undef_hook mrs_hook = { 289777c97b4eSSuzuki K Poulose .instr_mask = 0xfff00000, 289877c97b4eSSuzuki K Poulose .instr_val = 0xd5300000, 2899d64567f6SMark Rutland .pstate_mask = PSR_AA32_MODE_MASK, 290077c97b4eSSuzuki K Poulose .pstate_val = PSR_MODE_EL0t, 290177c97b4eSSuzuki K Poulose .fn = emulate_mrs, 290277c97b4eSSuzuki K Poulose }; 290377c97b4eSSuzuki K Poulose 290477c97b4eSSuzuki K Poulose static int __init enable_mrs_emulation(void) 290577c97b4eSSuzuki K Poulose { 290677c97b4eSSuzuki K Poulose register_undef_hook(&mrs_hook); 290777c97b4eSSuzuki K Poulose return 0; 290877c97b4eSSuzuki K Poulose } 290977c97b4eSSuzuki K Poulose 2910c0d8832eSSuzuki K Poulose core_initcall(enable_mrs_emulation); 29111b3ccf4bSJeremy Linton 29127f43c201SMarc Zyngier enum mitigation_state arm64_get_meltdown_state(void) 29137f43c201SMarc Zyngier { 29147f43c201SMarc Zyngier if (__meltdown_safe) 29157f43c201SMarc Zyngier return SPECTRE_UNAFFECTED; 29167f43c201SMarc Zyngier 29177f43c201SMarc Zyngier if (arm64_kernel_unmapped_at_el0()) 29187f43c201SMarc Zyngier return SPECTRE_MITIGATED; 29197f43c201SMarc Zyngier 29207f43c201SMarc Zyngier return SPECTRE_VULNERABLE; 29217f43c201SMarc Zyngier } 29227f43c201SMarc Zyngier 29231b3ccf4bSJeremy Linton ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, 29241b3ccf4bSJeremy Linton char *buf) 29251b3ccf4bSJeremy Linton { 29267f43c201SMarc Zyngier switch (arm64_get_meltdown_state()) { 29277f43c201SMarc Zyngier case SPECTRE_UNAFFECTED: 29281b3ccf4bSJeremy Linton return sprintf(buf, "Not affected\n"); 29291b3ccf4bSJeremy Linton 29307f43c201SMarc Zyngier case SPECTRE_MITIGATED: 29311b3ccf4bSJeremy Linton return sprintf(buf, "Mitigation: PTI\n"); 29321b3ccf4bSJeremy Linton 29337f43c201SMarc Zyngier default: 29341b3ccf4bSJeremy Linton return sprintf(buf, "Vulnerable\n"); 29351b3ccf4bSJeremy Linton } 29367f43c201SMarc Zyngier } 2937