cpufeature.c (779fda86bdeb86bad6daa4f0ecf37788dfc26f6c) | cpufeature.c (1631ba1259d6d7f49b6028f2a1a0fa02be1c522a) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copied from arch/arm64/kernel/cpufeature.c 4 * 5 * Copyright (C) 2015 ARM Ltd. 6 * Copyright (C) 2017 SiFive 7 */ 8 9#include <linux/bitmap.h> 10#include <linux/ctype.h> 11#include <linux/libfdt.h> 12#include <linux/module.h> 13#include <linux/of.h> 14#include <asm/alternative.h> | 1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copied from arch/arm64/kernel/cpufeature.c 4 * 5 * Copyright (C) 2015 ARM Ltd. 6 * Copyright (C) 2017 SiFive 7 */ 8 9#include <linux/bitmap.h> 10#include <linux/ctype.h> 11#include <linux/libfdt.h> 12#include <linux/module.h> 13#include <linux/of.h> 14#include <asm/alternative.h> |
15#include <asm/cacheflush.h> |
|
15#include <asm/errata_list.h> 16#include <asm/hwcap.h> 17#include <asm/patch.h> 18#include <asm/pgtable.h> 19#include <asm/processor.h> 20#include <asm/smp.h> 21#include <asm/switch_to.h> 22 23#define NUM_ALPHA_EXTS ('z' - 'a' + 1) 24 25unsigned long elf_hwcap __read_mostly; 26 27/* Host ISA bitmap */ 28static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly; 29 | 16#include <asm/errata_list.h> 17#include <asm/hwcap.h> 18#include <asm/patch.h> 19#include <asm/pgtable.h> 20#include <asm/processor.h> 21#include <asm/smp.h> 22#include <asm/switch_to.h> 23 24#define NUM_ALPHA_EXTS ('z' - 'a' + 1) 25 26unsigned long elf_hwcap __read_mostly; 27 28/* Host ISA bitmap */ 29static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly; 30 |
30#ifdef CONFIG_FPU 31__ro_after_init DEFINE_STATIC_KEY_FALSE(cpu_hwcap_fpu); 32#endif | 31__ro_after_init DEFINE_STATIC_KEY_ARRAY_FALSE(riscv_isa_ext_keys, RISCV_ISA_EXT_KEY_MAX); 32EXPORT_SYMBOL(riscv_isa_ext_keys); |
33 34/** 35 * riscv_isa_extension_base() - Get base extension word 36 * 37 * @isa_bitmap: ISA bitmap to use 38 * Return: base extension word as unsigned long value 39 * 40 * NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used. --- 153 unchanged lines hidden (view full) --- 194 if (unlikely(ext_err)) 195 continue; 196 if (!ext_long) { 197 this_hwcap |= isa2hwcap[(unsigned char)(*ext)]; 198 set_bit(*ext - 'a', this_isa); 199 } else { 200 SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF); 201 SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT); | 33 34/** 35 * riscv_isa_extension_base() - Get base extension word 36 * 37 * @isa_bitmap: ISA bitmap to use 38 * Return: base extension word as unsigned long value 39 * 40 * NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used. --- 153 unchanged lines hidden (view full) --- 194 if (unlikely(ext_err)) 195 continue; 196 if (!ext_long) { 197 this_hwcap |= isa2hwcap[(unsigned char)(*ext)]; 198 set_bit(*ext - 'a', this_isa); 199 } else { 200 SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF); 201 SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT); |
202 SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM); |
|
202 } 203#undef SET_ISA_EXT_MAP 204 } 205 206 /* 207 * All "okay" hart should have same isa. Set HWCAP based on 208 * common capabilities of every "okay" hart, in case they don't 209 * have. --- 23 unchanged lines hidden (view full) --- 233 pr_info("riscv: base ISA extensions %s\n", print_str); 234 235 memset(print_str, 0, sizeof(print_str)); 236 for (i = 0, j = 0; i < NUM_ALPHA_EXTS; i++) 237 if (elf_hwcap & BIT_MASK(i)) 238 print_str[j++] = (char)('a' + i); 239 pr_info("riscv: ELF capabilities %s\n", print_str); 240 | 203 } 204#undef SET_ISA_EXT_MAP 205 } 206 207 /* 208 * All "okay" hart should have same isa. Set HWCAP based on 209 * common capabilities of every "okay" hart, in case they don't 210 * have. --- 23 unchanged lines hidden (view full) --- 234 pr_info("riscv: base ISA extensions %s\n", print_str); 235 236 memset(print_str, 0, sizeof(print_str)); 237 for (i = 0, j = 0; i < NUM_ALPHA_EXTS; i++) 238 if (elf_hwcap & BIT_MASK(i)) 239 print_str[j++] = (char)('a' + i); 240 pr_info("riscv: ELF capabilities %s\n", print_str); 241 |
241#ifdef CONFIG_FPU 242 if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)) 243 static_branch_enable(&cpu_hwcap_fpu); 244#endif | 242 for_each_set_bit(i, riscv_isa, RISCV_ISA_EXT_MAX) { 243 j = riscv_isa_ext2key(i); 244 if (j >= 0) 245 static_branch_enable(&riscv_isa_ext_keys[j]); 246 } |
245} 246 247#ifdef CONFIG_RISCV_ALTERNATIVE | 247} 248 249#ifdef CONFIG_RISCV_ALTERNATIVE |
248struct cpufeature_info { 249 char name[ERRATA_STRING_LENGTH_MAX]; 250 bool (*check_func)(unsigned int stage); 251}; 252 253static bool __init_or_module cpufeature_svpbmt_check_func(unsigned int stage) | 250static bool __init_or_module cpufeature_probe_svpbmt(unsigned int stage) |
254{ 255#ifdef CONFIG_RISCV_ISA_SVPBMT 256 switch (stage) { 257 case RISCV_ALTERNATIVES_EARLY_BOOT: 258 return false; 259 default: 260 return riscv_isa_extension_available(NULL, SVPBMT); 261 } 262#endif 263 264 return false; 265} 266 | 251{ 252#ifdef CONFIG_RISCV_ISA_SVPBMT 253 switch (stage) { 254 case RISCV_ALTERNATIVES_EARLY_BOOT: 255 return false; 256 default: 257 return riscv_isa_extension_available(NULL, SVPBMT); 258 } 259#endif 260 261 return false; 262} 263 |
267static const struct cpufeature_info __initdata_or_module 268cpufeature_list[CPUFEATURE_NUMBER] = { 269 { 270 .name = "svpbmt", 271 .check_func = cpufeature_svpbmt_check_func 272 }, 273}; | 264static bool __init_or_module cpufeature_probe_zicbom(unsigned int stage) 265{ 266#ifdef CONFIG_RISCV_ISA_ZICBOM 267 switch (stage) { 268 case RISCV_ALTERNATIVES_EARLY_BOOT: 269 return false; 270 default: 271 if (riscv_isa_extension_available(NULL, ZICBOM)) { 272 riscv_noncoherent_supported(); 273 return true; 274 } else { 275 return false; 276 } 277 } 278#endif |
274 | 279 |
280 return false; 281} 282 283/* 284 * Probe presence of individual extensions. 285 * 286 * This code may also be executed before kernel relocation, so we cannot use 287 * addresses generated by the address-of operator as they won't be valid in 288 * this context. 289 */ |
|
275static u32 __init_or_module cpufeature_probe(unsigned int stage) 276{ | 290static u32 __init_or_module cpufeature_probe(unsigned int stage) 291{ |
277 const struct cpufeature_info *info; | |
278 u32 cpu_req_feature = 0; | 292 u32 cpu_req_feature = 0; |
279 int idx; | |
280 | 293 |
281 for (idx = 0; idx < CPUFEATURE_NUMBER; idx++) { 282 info = &cpufeature_list[idx]; | 294 if (cpufeature_probe_svpbmt(stage)) 295 cpu_req_feature |= (1U << CPUFEATURE_SVPBMT); |
283 | 296 |
284 if (info->check_func(stage)) 285 cpu_req_feature |= (1U << idx); 286 } | 297 if (cpufeature_probe_zicbom(stage)) 298 cpu_req_feature |= (1U << CPUFEATURE_ZICBOM); |
287 288 return cpu_req_feature; 289} 290 291void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin, 292 struct alt_entry *end, 293 unsigned int stage) 294{ --- 19 unchanged lines hidden --- | 299 300 return cpu_req_feature; 301} 302 303void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin, 304 struct alt_entry *end, 305 unsigned int stage) 306{ --- 19 unchanged lines hidden --- |