42b89447b6
Conor Dooley <conor@kernel.org> says: From: Conor Dooley <conor.dooley@microchip.com> Here are some bits that were discussed with Drew on the "should we allow caps" threads that I have now created patches for: - splitting of riscv_of_processor_hartid() into two distinct functions, one for use purely during early boot, prior to the establishment of the possible-cpus mask & another to fit the other current use-cases - that then allows us to then completely skip some validation of the hartid in the parser - the biggest diff in the series is a rework of the comments in the parser, as I have mostly found the existing (sparse) ones to not be all that helpful whenever I have to go back and look at it - from writing the comments, I found a conditional doing a bit of a dance that I found counter-intuitive, so I've had a go at making that match what I would expect a little better - `i` implies 4 other extensions, so add them as extensions and set them for the craic. Sure why not like... * b4-shazam-merge: RISC-V: always report presence of extensions formerly part of the base ISA dt-bindings: riscv: explicitly mention assumption of Zicntr & Zihpm support RISC-V: remove decrement/increment dance in ISA string parser RISC-V: rework comments in ISA string parser RISC-V: validate riscv,isa at boot, not during ISA string parsing RISC-V: split early & late of_node to hartid mapping RISC-V: simplify register width check in ISA string parsing Link: https://lore.kernel.org/r/20230607-audacity-overhaul-82bb867a825f@spud Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
136 lines
3.5 KiB
C
136 lines
3.5 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copied from arch/arm64/include/asm/hwcap.h
|
|
*
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
* Copyright (C) 2017 SiFive
|
|
*/
|
|
#ifndef _ASM_RISCV_HWCAP_H
|
|
#define _ASM_RISCV_HWCAP_H
|
|
|
|
#include <asm/alternative-macros.h>
|
|
#include <asm/errno.h>
|
|
#include <linux/bits.h>
|
|
#include <uapi/asm/hwcap.h>
|
|
|
|
#define RISCV_ISA_EXT_a ('a' - 'a')
|
|
#define RISCV_ISA_EXT_c ('c' - 'a')
|
|
#define RISCV_ISA_EXT_d ('d' - 'a')
|
|
#define RISCV_ISA_EXT_f ('f' - 'a')
|
|
#define RISCV_ISA_EXT_h ('h' - 'a')
|
|
#define RISCV_ISA_EXT_i ('i' - 'a')
|
|
#define RISCV_ISA_EXT_m ('m' - 'a')
|
|
#define RISCV_ISA_EXT_s ('s' - 'a')
|
|
#define RISCV_ISA_EXT_u ('u' - 'a')
|
|
#define RISCV_ISA_EXT_v ('v' - 'a')
|
|
|
|
/*
|
|
* These macros represent the logical IDs of each multi-letter RISC-V ISA
|
|
* extension and are used in the ISA bitmap. The logical IDs start from
|
|
* RISCV_ISA_EXT_BASE, which allows the 0-25 range to be reserved for single
|
|
* letter extensions. The maximum, RISCV_ISA_EXT_MAX, is defined in order
|
|
* to allocate the bitmap and may be increased when necessary.
|
|
*
|
|
* New extensions should just be added to the bottom, rather than added
|
|
* alphabetically, in order to avoid unnecessary shuffling.
|
|
*/
|
|
#define RISCV_ISA_EXT_BASE 26
|
|
|
|
#define RISCV_ISA_EXT_SSCOFPMF 26
|
|
#define RISCV_ISA_EXT_SSTC 27
|
|
#define RISCV_ISA_EXT_SVINVAL 28
|
|
#define RISCV_ISA_EXT_SVPBMT 29
|
|
#define RISCV_ISA_EXT_ZBB 30
|
|
#define RISCV_ISA_EXT_ZICBOM 31
|
|
#define RISCV_ISA_EXT_ZIHINTPAUSE 32
|
|
#define RISCV_ISA_EXT_SVNAPOT 33
|
|
#define RISCV_ISA_EXT_ZICBOZ 34
|
|
#define RISCV_ISA_EXT_SMAIA 35
|
|
#define RISCV_ISA_EXT_SSAIA 36
|
|
#define RISCV_ISA_EXT_ZBA 37
|
|
#define RISCV_ISA_EXT_ZBS 38
|
|
#define RISCV_ISA_EXT_ZICNTR 39
|
|
#define RISCV_ISA_EXT_ZICSR 40
|
|
#define RISCV_ISA_EXT_ZIFENCEI 41
|
|
#define RISCV_ISA_EXT_ZIHPM 42
|
|
|
|
#define RISCV_ISA_EXT_MAX 64
|
|
#define RISCV_ISA_EXT_NAME_LEN_MAX 32
|
|
|
|
#ifdef CONFIG_RISCV_M_MODE
|
|
#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SMAIA
|
|
#else
|
|
#define RISCV_ISA_EXT_SxAIA RISCV_ISA_EXT_SSAIA
|
|
#endif
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
#include <linux/jump_label.h>
|
|
|
|
unsigned long riscv_get_elf_hwcap(void);
|
|
|
|
struct riscv_isa_ext_data {
|
|
/* Name of the extension displayed to userspace via /proc/cpuinfo */
|
|
char uprop[RISCV_ISA_EXT_NAME_LEN_MAX];
|
|
/* The logical ISA extension ID */
|
|
unsigned int isa_ext_id;
|
|
};
|
|
|
|
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
|
|
|
|
#define riscv_isa_extension_mask(ext) BIT_MASK(RISCV_ISA_EXT_##ext)
|
|
|
|
bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, int bit);
|
|
#define riscv_isa_extension_available(isa_bitmap, ext) \
|
|
__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
|
|
|
|
static __always_inline bool
|
|
riscv_has_extension_likely(const unsigned long ext)
|
|
{
|
|
compiletime_assert(ext < RISCV_ISA_EXT_MAX,
|
|
"ext must be < RISCV_ISA_EXT_MAX");
|
|
|
|
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
|
|
asm_volatile_goto(
|
|
ALTERNATIVE("j %l[l_no]", "nop", 0, %[ext], 1)
|
|
:
|
|
: [ext] "i" (ext)
|
|
:
|
|
: l_no);
|
|
} else {
|
|
if (!__riscv_isa_extension_available(NULL, ext))
|
|
goto l_no;
|
|
}
|
|
|
|
return true;
|
|
l_no:
|
|
return false;
|
|
}
|
|
|
|
static __always_inline bool
|
|
riscv_has_extension_unlikely(const unsigned long ext)
|
|
{
|
|
compiletime_assert(ext < RISCV_ISA_EXT_MAX,
|
|
"ext must be < RISCV_ISA_EXT_MAX");
|
|
|
|
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
|
|
asm_volatile_goto(
|
|
ALTERNATIVE("nop", "j %l[l_yes]", 0, %[ext], 1)
|
|
:
|
|
: [ext] "i" (ext)
|
|
:
|
|
: l_yes);
|
|
} else {
|
|
if (__riscv_isa_extension_available(NULL, ext))
|
|
goto l_yes;
|
|
}
|
|
|
|
return false;
|
|
l_yes:
|
|
return true;
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif /* _ASM_RISCV_HWCAP_H */
|