1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copied from arch/arm64/kernel/cpufeature.c
5 * Copyright (C) 2015 ARM Ltd.
6 * Copyright (C) 2017 SiFive
9 #include <linux/bitmap.h>
11 #include <asm/processor.h>
12 #include <asm/hwcap.h>
14 #include <asm/switch_to.h>
16 unsigned long elf_hwcap __read_mostly
;
19 static DECLARE_BITMAP(riscv_isa
, RISCV_ISA_EXT_MAX
) __read_mostly
;
22 bool has_fpu __read_mostly
;
26 * riscv_isa_extension_base() - Get base extension word
28 * @isa_bitmap: ISA bitmap to use
29 * Return: base extension word as unsigned long value
31 * NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used.
33 unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap
)
39 EXPORT_SYMBOL_GPL(riscv_isa_extension_base
);
42 * __riscv_isa_extension_available() - Check whether given extension
45 * @isa_bitmap: ISA bitmap to use
46 * @bit: bit position of the desired extension
47 * Return: true or false
49 * NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used.
51 bool __riscv_isa_extension_available(const unsigned long *isa_bitmap
, int bit
)
53 const unsigned long *bmap
= (isa_bitmap
) ? isa_bitmap
: riscv_isa
;
55 if (bit
>= RISCV_ISA_EXT_MAX
)
58 return test_bit(bit
, bmap
) ? true : false;
60 EXPORT_SYMBOL_GPL(__riscv_isa_extension_available
);
62 void riscv_fill_hwcap(void)
64 struct device_node
*node
;
66 char print_str
[BITS_PER_LONG
+ 1];
68 static unsigned long isa2hwcap
[256] = {0};
70 isa2hwcap
['i'] = isa2hwcap
['I'] = COMPAT_HWCAP_ISA_I
;
71 isa2hwcap
['m'] = isa2hwcap
['M'] = COMPAT_HWCAP_ISA_M
;
72 isa2hwcap
['a'] = isa2hwcap
['A'] = COMPAT_HWCAP_ISA_A
;
73 isa2hwcap
['f'] = isa2hwcap
['F'] = COMPAT_HWCAP_ISA_F
;
74 isa2hwcap
['d'] = isa2hwcap
['D'] = COMPAT_HWCAP_ISA_D
;
75 isa2hwcap
['c'] = isa2hwcap
['C'] = COMPAT_HWCAP_ISA_C
;
79 bitmap_zero(riscv_isa
, RISCV_ISA_EXT_MAX
);
81 for_each_of_cpu_node(node
) {
82 unsigned long this_hwcap
= 0;
83 unsigned long this_isa
= 0;
85 if (riscv_of_processor_hartid(node
) < 0)
88 if (of_property_read_string(node
, "riscv,isa", &isa
)) {
89 pr_warn("Unable to find \"riscv,isa\" devicetree entry\n");
94 isa_len
= strlen(isa
);
95 #if IS_ENABLED(CONFIG_32BIT)
96 if (!strncmp(isa
, "rv32", 4))
98 #elif IS_ENABLED(CONFIG_64BIT)
99 if (!strncmp(isa
, "rv64", 4))
102 for (; i
< isa_len
; ++i
) {
103 this_hwcap
|= isa2hwcap
[(unsigned char)(isa
[i
])];
105 * TODO: X, Y and Z extension parsing for Host ISA
106 * bitmap will be added in-future.
108 if ('a' <= isa
[i
] && isa
[i
] < 'x')
109 this_isa
|= (1UL << (isa
[i
] - 'a'));
113 * All "okay" hart should have same isa. Set HWCAP based on
114 * common capabilities of every "okay" hart, in case they don't
118 elf_hwcap
&= this_hwcap
;
120 elf_hwcap
= this_hwcap
;
123 riscv_isa
[0] &= this_isa
;
125 riscv_isa
[0] = this_isa
;
128 /* We don't support systems with F but without D, so mask those out
130 if ((elf_hwcap
& COMPAT_HWCAP_ISA_F
) && !(elf_hwcap
& COMPAT_HWCAP_ISA_D
)) {
131 pr_info("This kernel does not support systems with F but not D\n");
132 elf_hwcap
&= ~COMPAT_HWCAP_ISA_F
;
135 memset(print_str
, 0, sizeof(print_str
));
136 for (i
= 0, j
= 0; i
< BITS_PER_LONG
; i
++)
137 if (riscv_isa
[0] & BIT_MASK(i
))
138 print_str
[j
++] = (char)('a' + i
);
139 pr_info("riscv: ISA extensions %s\n", print_str
);
141 memset(print_str
, 0, sizeof(print_str
));
142 for (i
= 0, j
= 0; i
< BITS_PER_LONG
; i
++)
143 if (elf_hwcap
& BIT_MASK(i
))
144 print_str
[j
++] = (char)('a' + i
);
145 pr_info("riscv: ELF capabilities %s\n", print_str
);
148 if (elf_hwcap
& (COMPAT_HWCAP_ISA_F
| COMPAT_HWCAP_ISA_D
))