Linux Audio

Check our new training course

Loading...
v5.4
 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/of.h>
10#include <asm/processor.h>
11#include <asm/hwcap.h>
12#include <asm/smp.h>
13#include <asm/switch_to.h>
14
15unsigned long elf_hwcap __read_mostly;
 
 
 
 
16#ifdef CONFIG_FPU
17bool has_fpu __read_mostly;
18#endif
19
20void riscv_fill_hwcap(void)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21{
22	struct device_node *node;
23	const char *isa;
24	size_t i;
 
25	static unsigned long isa2hwcap[256] = {0};
26
27	isa2hwcap['i'] = isa2hwcap['I'] = COMPAT_HWCAP_ISA_I;
28	isa2hwcap['m'] = isa2hwcap['M'] = COMPAT_HWCAP_ISA_M;
29	isa2hwcap['a'] = isa2hwcap['A'] = COMPAT_HWCAP_ISA_A;
30	isa2hwcap['f'] = isa2hwcap['F'] = COMPAT_HWCAP_ISA_F;
31	isa2hwcap['d'] = isa2hwcap['D'] = COMPAT_HWCAP_ISA_D;
32	isa2hwcap['c'] = isa2hwcap['C'] = COMPAT_HWCAP_ISA_C;
33
34	elf_hwcap = 0;
35
 
 
36	for_each_of_cpu_node(node) {
37		unsigned long this_hwcap = 0;
 
38
39		if (riscv_of_processor_hartid(node) < 0)
40			continue;
41
42		if (of_property_read_string(node, "riscv,isa", &isa)) {
43			pr_warn("Unable to find \"riscv,isa\" devicetree entry\n");
44			continue;
45		}
46
47		for (i = 0; i < strlen(isa); ++i)
 
 
 
 
 
 
 
 
 
48			this_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
 
 
 
 
 
 
 
49
50		/*
51		 * All "okay" hart should have same isa. Set HWCAP based on
52		 * common capabilities of every "okay" hart, in case they don't
53		 * have.
54		 */
55		if (elf_hwcap)
56			elf_hwcap &= this_hwcap;
57		else
58			elf_hwcap = this_hwcap;
 
 
 
 
 
59	}
60
61	/* We don't support systems with F but without D, so mask those out
62	 * here. */
63	if ((elf_hwcap & COMPAT_HWCAP_ISA_F) && !(elf_hwcap & COMPAT_HWCAP_ISA_D)) {
64		pr_info("This kernel does not support systems with F but not D\n");
65		elf_hwcap &= ~COMPAT_HWCAP_ISA_F;
66	}
67
68	pr_info("elf_hwcap is 0x%lx\n", elf_hwcap);
 
 
 
 
 
 
 
 
 
 
69
70#ifdef CONFIG_FPU
71	if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
72		has_fpu = true;
73#endif
74}
v5.14.15
  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/of.h>
 11#include <asm/processor.h>
 12#include <asm/hwcap.h>
 13#include <asm/smp.h>
 14#include <asm/switch_to.h>
 15
 16unsigned long elf_hwcap __read_mostly;
 17
 18/* Host ISA bitmap */
 19static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
 20
 21#ifdef CONFIG_FPU
 22__ro_after_init DEFINE_STATIC_KEY_FALSE(cpu_hwcap_fpu);
 23#endif
 24
 25/**
 26 * riscv_isa_extension_base() - Get base extension word
 27 *
 28 * @isa_bitmap: ISA bitmap to use
 29 * Return: base extension word as unsigned long value
 30 *
 31 * NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used.
 32 */
 33unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap)
 34{
 35	if (!isa_bitmap)
 36		return riscv_isa[0];
 37	return isa_bitmap[0];
 38}
 39EXPORT_SYMBOL_GPL(riscv_isa_extension_base);
 40
 41/**
 42 * __riscv_isa_extension_available() - Check whether given extension
 43 * is available or not
 44 *
 45 * @isa_bitmap: ISA bitmap to use
 46 * @bit: bit position of the desired extension
 47 * Return: true or false
 48 *
 49 * NOTE: If isa_bitmap is NULL then Host ISA bitmap will be used.
 50 */
 51bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit)
 52{
 53	const unsigned long *bmap = (isa_bitmap) ? isa_bitmap : riscv_isa;
 54
 55	if (bit >= RISCV_ISA_EXT_MAX)
 56		return false;
 57
 58	return test_bit(bit, bmap) ? true : false;
 59}
 60EXPORT_SYMBOL_GPL(__riscv_isa_extension_available);
 61
 62void __init riscv_fill_hwcap(void)
 63{
 64	struct device_node *node;
 65	const char *isa;
 66	char print_str[BITS_PER_LONG + 1];
 67	size_t i, j, isa_len;
 68	static unsigned long isa2hwcap[256] = {0};
 69
 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;
 76
 77	elf_hwcap = 0;
 78
 79	bitmap_zero(riscv_isa, RISCV_ISA_EXT_MAX);
 80
 81	for_each_of_cpu_node(node) {
 82		unsigned long this_hwcap = 0;
 83		unsigned long this_isa = 0;
 84
 85		if (riscv_of_processor_hartid(node) < 0)
 86			continue;
 87
 88		if (of_property_read_string(node, "riscv,isa", &isa)) {
 89			pr_warn("Unable to find \"riscv,isa\" devicetree entry\n");
 90			continue;
 91		}
 92
 93		i = 0;
 94		isa_len = strlen(isa);
 95#if IS_ENABLED(CONFIG_32BIT)
 96		if (!strncmp(isa, "rv32", 4))
 97			i += 4;
 98#elif IS_ENABLED(CONFIG_64BIT)
 99		if (!strncmp(isa, "rv64", 4))
100			i += 4;
101#endif
102		for (; i < isa_len; ++i) {
103			this_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
104			/*
105			 * TODO: X, Y and Z extension parsing for Host ISA
106			 * bitmap will be added in-future.
107			 */
108			if ('a' <= isa[i] && isa[i] < 'x')
109				this_isa |= (1UL << (isa[i] - 'a'));
110		}
111
112		/*
113		 * All "okay" hart should have same isa. Set HWCAP based on
114		 * common capabilities of every "okay" hart, in case they don't
115		 * have.
116		 */
117		if (elf_hwcap)
118			elf_hwcap &= this_hwcap;
119		else
120			elf_hwcap = this_hwcap;
121
122		if (riscv_isa[0])
123			riscv_isa[0] &= this_isa;
124		else
125			riscv_isa[0] = this_isa;
126	}
127
128	/* We don't support systems with F but without D, so mask those out
129	 * here. */
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;
133	}
134
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);
140
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);
146
147#ifdef CONFIG_FPU
148	if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))
149		static_branch_enable(&cpu_hwcap_fpu);
150#endif
151}