Skip to content

Commit 6bcff51

Browse files
avpatelpalmer-dabbelt
authored andcommitted
RISC-V: Add bitmap reprensenting ISA features common across CPUs
This patch adds riscv_isa bitmap which represents Host ISA features common across all Host CPUs. The riscv_isa is not same as elf_hwcap because elf_hwcap will only have ISA features relevant for user-space apps whereas riscv_isa will have ISA features relevant to both kernel and user-space apps. One of the use-case for riscv_isa bitmap is in KVM hypervisor where we will use it to do following operations: 1. Check whether hypervisor extension is available 2. Find ISA features that need to be virtualized (e.g. floating point support, vector extension, etc.) Signed-off-by: Anup Patel <[email protected]> Signed-off-by: Atish Patra <[email protected]> Reviewed-by: Alexander Graf <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 7391efa commit 6bcff51

File tree

2 files changed

+102
-3
lines changed

2 files changed

+102
-3
lines changed

arch/riscv/include/asm/hwcap.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#ifndef _ASM_RISCV_HWCAP_H
99
#define _ASM_RISCV_HWCAP_H
1010

11+
#include <linux/bits.h>
1112
#include <uapi/asm/hwcap.h>
1213

1314
#ifndef __ASSEMBLY__
@@ -22,6 +23,27 @@ enum {
2223
};
2324

2425
extern unsigned long elf_hwcap;
26+
27+
#define RISCV_ISA_EXT_a ('a' - 'a')
28+
#define RISCV_ISA_EXT_c ('c' - 'a')
29+
#define RISCV_ISA_EXT_d ('d' - 'a')
30+
#define RISCV_ISA_EXT_f ('f' - 'a')
31+
#define RISCV_ISA_EXT_h ('h' - 'a')
32+
#define RISCV_ISA_EXT_i ('i' - 'a')
33+
#define RISCV_ISA_EXT_m ('m' - 'a')
34+
#define RISCV_ISA_EXT_s ('s' - 'a')
35+
#define RISCV_ISA_EXT_u ('u' - 'a')
36+
37+
#define RISCV_ISA_EXT_MAX 64
38+
39+
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
40+
41+
#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
42+
43+
bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
44+
#define riscv_isa_extension_available(isa_bitmap, ext) \
45+
__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
46+
2547
#endif
2648

2749
#endif /* _ASM_RISCV_HWCAP_H */

arch/riscv/kernel/cpufeature.c

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,65 @@
66
* Copyright (C) 2017 SiFive
77
*/
88

9+
#include <linux/bitmap.h>
910
#include <linux/of.h>
1011
#include <asm/processor.h>
1112
#include <asm/hwcap.h>
1213
#include <asm/smp.h>
1314
#include <asm/switch_to.h>
1415

1516
unsigned long elf_hwcap __read_mostly;
17+
18+
/* Host ISA bitmap */
19+
static DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX) __read_mostly;
20+
1621
#ifdef CONFIG_FPU
1722
bool has_fpu __read_mostly;
1823
#endif
1924

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+
*/
33+
unsigned 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+
}
39+
EXPORT_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+
*/
51+
bool __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+
}
60+
EXPORT_SYMBOL_GPL(__riscv_isa_extension_available);
61+
2062
void riscv_fill_hwcap(void)
2163
{
2264
struct device_node *node;
2365
const char *isa;
24-
size_t i;
66+
char print_str[BITS_PER_LONG + 1];
67+
size_t i, j, isa_len;
2568
static unsigned long isa2hwcap[256] = {0};
2669

2770
isa2hwcap['i'] = isa2hwcap['I'] = COMPAT_HWCAP_ISA_I;
@@ -33,8 +76,11 @@ void riscv_fill_hwcap(void)
3376

3477
elf_hwcap = 0;
3578

79+
bitmap_zero(riscv_isa, RISCV_ISA_EXT_MAX);
80+
3681
for_each_of_cpu_node(node) {
3782
unsigned long this_hwcap = 0;
83+
unsigned long this_isa = 0;
3884

3985
if (riscv_of_processor_hartid(node) < 0)
4086
continue;
@@ -44,8 +90,24 @@ void riscv_fill_hwcap(void)
4490
continue;
4591
}
4692

47-
for (i = 0; i < strlen(isa); ++i)
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) {
48103
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+
}
49111

50112
/*
51113
* All "okay" hart should have same isa. Set HWCAP based on
@@ -56,6 +118,11 @@ void riscv_fill_hwcap(void)
56118
elf_hwcap &= this_hwcap;
57119
else
58120
elf_hwcap = this_hwcap;
121+
122+
if (riscv_isa[0])
123+
riscv_isa[0] &= this_isa;
124+
else
125+
riscv_isa[0] = this_isa;
59126
}
60127

61128
/* We don't support systems with F but without D, so mask those out
@@ -65,7 +132,17 @@ void riscv_fill_hwcap(void)
65132
elf_hwcap &= ~COMPAT_HWCAP_ISA_F;
66133
}
67134

68-
pr_info("elf_hwcap is 0x%lx\n", elf_hwcap);
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);
69146

70147
#ifdef CONFIG_FPU
71148
if (elf_hwcap & (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D))

0 commit comments

Comments
 (0)