@@ -107,6 +107,24 @@ DECLARE_BITMAP(boot_capabilities, ARM64_NPATCHABLE);
107107bool arm64_use_ng_mappings = false;
108108EXPORT_SYMBOL (arm64_use_ng_mappings );
109109
110+ /*
111+ * Permit PER_LINUX32 and execve() of 32-bit binaries even if not all CPUs
112+ * support it?
113+ */
114+ static bool __read_mostly allow_mismatched_32bit_el0 ;
115+
116+ /*
117+ * Static branch enabled only if allow_mismatched_32bit_el0 is set and we have
118+ * seen at least one CPU capable of 32-bit EL0.
119+ */
120+ DEFINE_STATIC_KEY_FALSE (arm64_mismatched_32bit_el0 );
121+
122+ /*
123+ * Mask of CPUs supporting 32-bit EL0.
124+ * Only valid if arm64_mismatched_32bit_el0 is enabled.
125+ */
126+ static cpumask_var_t cpu_32bit_el0_mask __cpumask_var_read_mostly ;
127+
110128/*
111129 * Flag to indicate if we have computed the system wide
112130 * capabilities based on the boot time active CPUs. This
@@ -775,7 +793,7 @@ static void __init sort_ftr_regs(void)
775793 * Any bits that are not covered by an arm64_ftr_bits entry are considered
776794 * RES0 for the system-wide value, and must strictly match.
777795 */
778- static void __init init_cpu_ftr_reg (u32 sys_reg , u64 new )
796+ static void init_cpu_ftr_reg (u32 sys_reg , u64 new )
779797{
780798 u64 val = 0 ;
781799 u64 strict_mask = ~0x0ULL ;
@@ -871,7 +889,7 @@ static void __init init_cpu_hwcaps_indirect_list(void)
871889
872890static void __init setup_boot_cpu_capabilities (void );
873891
874- static void __init init_32bit_cpu_features (struct cpuinfo_32bit * info )
892+ static void init_32bit_cpu_features (struct cpuinfo_32bit * info )
875893{
876894 init_cpu_ftr_reg (SYS_ID_DFR0_EL1 , info -> reg_id_dfr0 );
877895 init_cpu_ftr_reg (SYS_ID_DFR1_EL1 , info -> reg_id_dfr1 );
@@ -990,6 +1008,22 @@ static void relax_cpu_ftr_reg(u32 sys_id, int field)
9901008 WARN_ON (!ftrp -> width );
9911009}
9921010
1011+ static void lazy_init_32bit_cpu_features (struct cpuinfo_arm64 * info ,
1012+ struct cpuinfo_arm64 * boot )
1013+ {
1014+ static bool boot_cpu_32bit_regs_overridden = false;
1015+
1016+ if (!allow_mismatched_32bit_el0 || boot_cpu_32bit_regs_overridden )
1017+ return ;
1018+
1019+ if (id_aa64pfr0_32bit_el0 (boot -> reg_id_aa64pfr0 ))
1020+ return ;
1021+
1022+ boot -> aarch32 = info -> aarch32 ;
1023+ init_32bit_cpu_features (& boot -> aarch32 );
1024+ boot_cpu_32bit_regs_overridden = true;
1025+ }
1026+
9931027static int update_32bit_cpu_features (int cpu , struct cpuinfo_32bit * info ,
9941028 struct cpuinfo_32bit * boot )
9951029{
@@ -1161,6 +1195,7 @@ void update_cpu_features(int cpu,
11611195 * (e.g. SYS_ID_AA64PFR0_EL1), so we call it last.
11621196 */
11631197 if (id_aa64pfr0_32bit_el0 (info -> reg_id_aa64pfr0 )) {
1198+ lazy_init_32bit_cpu_features (info , boot );
11641199 taint |= update_32bit_cpu_features (cpu , & info -> aarch32 ,
11651200 & boot -> aarch32 );
11661201 }
@@ -1273,6 +1308,28 @@ has_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope)
12731308 return feature_matches (val , entry );
12741309}
12751310
1311+ const struct cpumask * system_32bit_el0_cpumask (void )
1312+ {
1313+ if (!system_supports_32bit_el0 ())
1314+ return cpu_none_mask ;
1315+
1316+ if (static_branch_unlikely (& arm64_mismatched_32bit_el0 ))
1317+ return cpu_32bit_el0_mask ;
1318+
1319+ return cpu_possible_mask ;
1320+ }
1321+
1322+ static bool has_32bit_el0 (const struct arm64_cpu_capabilities * entry , int scope )
1323+ {
1324+ if (!has_cpuid_feature (entry , scope ))
1325+ return allow_mismatched_32bit_el0 ;
1326+
1327+ if (scope == SCOPE_SYSTEM )
1328+ pr_info ("detected: 32-bit EL0 Support\n" );
1329+
1330+ return true;
1331+ }
1332+
12761333static bool has_useable_gicv3_cpuif (const struct arm64_cpu_capabilities * entry , int scope )
12771334{
12781335 bool has_sre ;
@@ -1891,10 +1948,9 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
18911948 .cpu_enable = cpu_copy_el2regs ,
18921949 },
18931950 {
1894- .desc = "32-bit EL0 Support" ,
1895- .capability = ARM64_HAS_32BIT_EL0 ,
1951+ .capability = ARM64_HAS_32BIT_EL0_DO_NOT_USE ,
18961952 .type = ARM64_CPUCAP_SYSTEM_FEATURE ,
1897- .matches = has_cpuid_feature ,
1953+ .matches = has_32bit_el0 ,
18981954 .sys_reg = SYS_ID_AA64PFR0_EL1 ,
18991955 .sign = FTR_UNSIGNED ,
19001956 .field_pos = ID_AA64PFR0_EL0_SHIFT ,
@@ -2403,7 +2459,7 @@ static const struct arm64_cpu_capabilities compat_elf_hwcaps[] = {
24032459 {},
24042460};
24052461
2406- static void __init cap_set_elf_hwcap (const struct arm64_cpu_capabilities * cap )
2462+ static void cap_set_elf_hwcap (const struct arm64_cpu_capabilities * cap )
24072463{
24082464 switch (cap -> hwcap_type ) {
24092465 case CAP_HWCAP :
@@ -2448,7 +2504,7 @@ static bool cpus_have_elf_hwcap(const struct arm64_cpu_capabilities *cap)
24482504 return rc ;
24492505}
24502506
2451- static void __init setup_elf_hwcaps (const struct arm64_cpu_capabilities * hwcaps )
2507+ static void setup_elf_hwcaps (const struct arm64_cpu_capabilities * hwcaps )
24522508{
24532509 /* We support emulation of accesses to CPU ID feature registers */
24542510 cpu_set_named_feature (CPUID );
@@ -2623,7 +2679,7 @@ static void check_early_cpu_features(void)
26232679}
26242680
26252681static void
2626- verify_local_elf_hwcaps (const struct arm64_cpu_capabilities * caps )
2682+ __verify_local_elf_hwcaps (const struct arm64_cpu_capabilities * caps )
26272683{
26282684
26292685 for (; caps -> matches ; caps ++ )
@@ -2634,6 +2690,14 @@ verify_local_elf_hwcaps(const struct arm64_cpu_capabilities *caps)
26342690 }
26352691}
26362692
2693+ static void verify_local_elf_hwcaps (void )
2694+ {
2695+ __verify_local_elf_hwcaps (arm64_elf_hwcaps );
2696+
2697+ if (id_aa64pfr0_32bit_el0 (read_cpuid (ID_AA64PFR0_EL1 )))
2698+ __verify_local_elf_hwcaps (compat_elf_hwcaps );
2699+ }
2700+
26372701static void verify_sve_features (void )
26382702{
26392703 u64 safe_zcr = read_sanitised_ftr_reg (SYS_ZCR_EL1 );
@@ -2698,11 +2762,7 @@ static void verify_local_cpu_capabilities(void)
26982762 * on all secondary CPUs.
26992763 */
27002764 verify_local_cpu_caps (SCOPE_ALL & ~SCOPE_BOOT_CPU );
2701-
2702- verify_local_elf_hwcaps (arm64_elf_hwcaps );
2703-
2704- if (system_supports_32bit_el0 ())
2705- verify_local_elf_hwcaps (compat_elf_hwcaps );
2765+ verify_local_elf_hwcaps ();
27062766
27072767 if (system_supports_sve ())
27082768 verify_sve_features ();
@@ -2837,6 +2897,34 @@ void __init setup_cpu_features(void)
28372897 ARCH_DMA_MINALIGN );
28382898}
28392899
2900+ static int enable_mismatched_32bit_el0 (unsigned int cpu )
2901+ {
2902+ struct cpuinfo_arm64 * info = & per_cpu (cpu_data , cpu );
2903+ bool cpu_32bit = id_aa64pfr0_32bit_el0 (info -> reg_id_aa64pfr0 );
2904+
2905+ if (cpu_32bit ) {
2906+ cpumask_set_cpu (cpu , cpu_32bit_el0_mask );
2907+ static_branch_enable_cpuslocked (& arm64_mismatched_32bit_el0 );
2908+ setup_elf_hwcaps (compat_elf_hwcaps );
2909+ }
2910+
2911+ return 0 ;
2912+ }
2913+
2914+ static int __init init_32bit_el0_mask (void )
2915+ {
2916+ if (!allow_mismatched_32bit_el0 )
2917+ return 0 ;
2918+
2919+ if (!zalloc_cpumask_var (& cpu_32bit_el0_mask , GFP_KERNEL ))
2920+ return - ENOMEM ;
2921+
2922+ return cpuhp_setup_state (CPUHP_AP_ONLINE_DYN ,
2923+ "arm64/mismatched_32bit_el0:online" ,
2924+ enable_mismatched_32bit_el0 , NULL );
2925+ }
2926+ subsys_initcall_sync (init_32bit_el0_mask );
2927+
28402928static void __maybe_unused cpu_enable_cnp (struct arm64_cpu_capabilities const * cap )
28412929{
28422930 cpu_replace_ttbr1 (lm_alias (swapper_pg_dir ));
0 commit comments