Skip to content

Commit e89c2e8

Browse files
nathanchancepalmer-dabbelt
authored andcommitted
riscv: Handle zicsr/zifencei issues between clang and binutils
There are two related issues that appear in certain combinations with clang and GNU binutils. The first occurs when a version of clang that supports zicsr or zifencei via '-march=' [1] (i.e, >= 17.x) is used in combination with a version of GNU binutils that do not recognize zicsr and zifencei in the '-march=' value (i.e., < 2.36): riscv64-linux-gnu-ld: -march=rv64i2p0_m2p0_a2p0_c2p0_zicsr2p0_zifencei2p0: Invalid or unknown z ISA extension: 'zifencei' riscv64-linux-gnu-ld: failed to merge target specific data of file fs/efivarfs/file.o riscv64-linux-gnu-ld: -march=rv64i2p0_m2p0_a2p0_c2p0_zicsr2p0_zifencei2p0: Invalid or unknown z ISA extension: 'zifencei' riscv64-linux-gnu-ld: failed to merge target specific data of file fs/efivarfs/super.o The second occurs when a version of clang that does not support zicsr or zifencei via '-march=' (i.e., <= 16.x) is used in combination with a version of GNU as that defaults to a newer ISA base spec, which requires specifying zicsr and zifencei in the '-march=' value explicitly (i.e, >= 2.38): ../arch/riscv/kernel/kexec_relocate.S: Assembler messages: ../arch/riscv/kernel/kexec_relocate.S:147: Error: unrecognized opcode `fence.i', extension `zifencei' required clang-12: error: assembler command failed with exit code 1 (use -v to see invocation) This is the same issue addressed by commit 6df2a01 ("riscv: fix build with binutils 2.38") (see [2] for additional information) but older versions of clang miss out on it because the cc-option check fails: clang-12: error: invalid arch name 'rv64imac_zicsr_zifencei', unsupported standard user-level extension 'zicsr' clang-12: error: invalid arch name 'rv64imac_zicsr_zifencei', unsupported standard user-level extension 'zicsr' To resolve the first issue, only attempt to add zicsr and zifencei to the march string when using the GNU assembler 2.38 or newer, which is when the default ISA spec was updated, requiring these extensions to be specified explicitly. LLVM implements an older version of the base specification for all currently released versions, so these instructions are available as part of the 'i' extension. If LLVM's implementation is updated in the future, a CONFIG_AS_IS_LLVM condition can be added to CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI. To resolve the second issue, use version 2.2 of the base ISA spec when using an older version of clang that does not support zicsr or zifencei via '-march=', as that is the spec version most compatible with the one clang/LLVM implements and avoids the need to specify zicsr and zifencei explicitly due to still being a part of 'i'. [1]: llvm/llvm-project@22e199e [2]: https://lore.kernel.org/[email protected]/ Cc: [email protected] Link: ClangBuiltLinux#1808 Co-developed-by: Conor Dooley <[email protected]> Signed-off-by: Conor Dooley <[email protected]> Signed-off-by: Nathan Chancellor <[email protected]> Acked-by: Conor Dooley <[email protected]> Link: https://lore.kernel.org/r/20230313-riscv-zicsr-zifencei-fiasco-v1-1-dd1b7840a551@kernel.org Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 9a801af commit e89c2e8

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

arch/riscv/Kconfig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,28 @@ config TOOLCHAIN_HAS_ZIHINTPAUSE
464464
depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zihintpause)
465465
depends on LLD_VERSION >= 150000 || LD_VERSION >= 23600
466466

467+
config TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
468+
def_bool y
469+
# https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=aed44286efa8ae8717a77d94b51ac3614e2ca6dc
470+
depends on AS_IS_GNU && AS_VERSION >= 23800
471+
help
472+
Newer binutils versions default to ISA spec version 20191213 which
473+
moves some instructions from the I extension to the Zicsr and Zifencei
474+
extensions.
475+
476+
config TOOLCHAIN_NEEDS_OLD_ISA_SPEC
477+
def_bool y
478+
depends on TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
479+
# https://github.com/llvm/llvm-project/commit/22e199e6afb1263c943c0c0d4498694e15bf8a16
480+
depends on CC_IS_CLANG && CLANG_VERSION < 170000
481+
help
482+
Certain versions of clang do not support zicsr and zifencei via -march
483+
but newer versions of binutils require it for the reasons noted in the
484+
help text of CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI. This
485+
option causes an older ISA spec compatible with these older versions
486+
of clang to be passed to GAS, which has the same result as passing zicsr
487+
and zifencei to -march.
488+
467489
config FPU
468490
bool "FPU support"
469491
default y

arch/riscv/Makefile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,12 @@ riscv-march-$(CONFIG_ARCH_RV64I) := rv64ima
5757
riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd
5858
riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
5959

60-
# Newer binutils versions default to ISA spec version 20191213 which moves some
61-
# instructions from the I extension to the Zicsr and Zifencei extensions.
62-
toolchain-need-zicsr-zifencei := $(call cc-option-yn, -march=$(riscv-march-y)_zicsr_zifencei)
63-
riscv-march-$(toolchain-need-zicsr-zifencei) := $(riscv-march-y)_zicsr_zifencei
60+
ifdef CONFIG_TOOLCHAIN_NEEDS_OLD_ISA_SPEC
61+
KBUILD_CFLAGS += -Wa,-misa-spec=2.2
62+
KBUILD_AFLAGS += -Wa,-misa-spec=2.2
63+
else
64+
riscv-march-$(CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI) := $(riscv-march-y)_zicsr_zifencei
65+
endif
6466

6567
# Check if the toolchain supports Zihintpause extension
6668
riscv-march-$(CONFIG_TOOLCHAIN_HAS_ZIHINTPAUSE) := $(riscv-march-y)_zihintpause

0 commit comments

Comments
 (0)