From 78c728fdbadef7703d1e26ecc1d17de92a3e0241 Mon Sep 17 00:00:00 2001 From: rootkiller6788 Date: Fri, 21 Aug 2026 19:34:18 +0800 Subject: [PATCH] riscv: detect Zicsr/Zifencei without leading underscore The kernel riscv,isa binding allows the first multi-letter extension to omit its leading underscore (e.g. rv64imafdczicsr_zifencei). The parser looked for "_zicsr" and "_zifencei" with the underscore, so those extensions were missed when the first multi-letter extension dropped the underscore. Match them without the underscore to catch both spellings. Also update the comment to the current devicetree binding regex and add regression tests for the underscore-less and canonical spellings. --- src/impl_riscv_linux.c | 10 ++++-- test/cpuinfo_riscv_test.cc | 69 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/impl_riscv_linux.c b/src/impl_riscv_linux.c index 8abec6eb..8e227456 100644 --- a/src/impl_riscv_linux.c +++ b/src/impl_riscv_linux.c @@ -22,10 +22,14 @@ // According to // https://elixir.bootlin.com/linux/latest/source/Documentation/devicetree/bindings/riscv/cpus.yaml // isa string should match the following regex -// ^rv(?:64|32)imaf?d?q?c?b?v?k?h?(?:_[hsxz](?:[a-z])+)*$ +// ^rv(?:64|32)imaf?d?q?c?b?k?j?p?v?h?(?:[hsxz](?:[a-z])+)?(?:_[hsxz](?:[a-z])+)*$ // // This means we can test for features in this exact order except for Z // extensions. +// +// Note that the first multi-letter extension may omit its leading underscore +// (e.g. "rv64imafdczicsr_zifencei"), so Z extensions are matched without the +// underscore to catch both spellings. //////////////////////////////////////////////////////////////////////////////// // Definitions for introspection. @@ -40,8 +44,8 @@ LINE(RISCV_Q, Q, "q", RISCV_HWCAP_Q, 0) \ LINE(RISCV_C, C, "c", RISCV_HWCAP_C, 0) \ LINE(RISCV_V, V, "v", RISCV_HWCAP_V, 0) \ - LINE(RISCV_Zicsr, Zicsr, "_zicsr", 0, 0) \ - LINE(RISCV_Zifencei, Zifencei, "_zifencei", 0, 0) + LINE(RISCV_Zicsr, Zicsr, "zicsr", 0, 0) \ + LINE(RISCV_Zifencei, Zifencei, "zifencei", 0, 0) #define INTROSPECTION_PREFIX Riscv #define INTROSPECTION_ENUM_PREFIX RISCV #include "define_introspection_and_hwcaps.inl" diff --git a/test/cpuinfo_riscv_test.cc b/test/cpuinfo_riscv_test.cc index 2ffe2b35..25a6bc4b 100644 --- a/test/cpuinfo_riscv_test.cc +++ b/test/cpuinfo_riscv_test.cc @@ -176,5 +176,74 @@ mmu : sv48)"); EXPECT_TRUE(info.features.V); } +// The first multi-letter extension may omit its leading underscore +// (https://github.com/google/cpu_features/issues/301). Make sure Z +// extensions are still detected in both spellings. +TEST(CpuinfoRiscvTest, ZicsrZifenceiWithoutUnderscore) { + ResetHwcaps(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"( +processor : 0 +hart : 0 +isa : rv64imafdczicsr_zifencei +mmu : sv39)"); + const auto info = GetRiscvInfo(); + EXPECT_FALSE(info.features.RV32I); + EXPECT_TRUE(info.features.RV64I); + EXPECT_TRUE(info.features.M); + EXPECT_TRUE(info.features.A); + EXPECT_TRUE(info.features.F); + EXPECT_TRUE(info.features.D); + EXPECT_FALSE(info.features.Q); + EXPECT_TRUE(info.features.C); + EXPECT_FALSE(info.features.V); + EXPECT_TRUE(info.features.Zicsr); + EXPECT_TRUE(info.features.Zifencei); +} + +TEST(CpuinfoRiscvTest, ZifenceiWithoutUnderscore) { + ResetHwcaps(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"( +processor : 0 +hart : 0 +isa : rv64imafdczifencei +mmu : sv39)"); + const auto info = GetRiscvInfo(); + EXPECT_FALSE(info.features.RV32I); + EXPECT_TRUE(info.features.RV64I); + EXPECT_TRUE(info.features.M); + EXPECT_TRUE(info.features.A); + EXPECT_TRUE(info.features.F); + EXPECT_TRUE(info.features.D); + EXPECT_FALSE(info.features.Q); + EXPECT_TRUE(info.features.C); + EXPECT_FALSE(info.features.V); + EXPECT_FALSE(info.features.Zicsr); + EXPECT_TRUE(info.features.Zifencei); +} + +TEST(CpuinfoRiscvTest, ZicsrZifenceiWithUnderscore) { + ResetHwcaps(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"( +processor : 0 +hart : 0 +isa : rv64imafdc_zicsr_zifencei +mmu : sv39)"); + const auto info = GetRiscvInfo(); + EXPECT_FALSE(info.features.RV32I); + EXPECT_TRUE(info.features.RV64I); + EXPECT_TRUE(info.features.M); + EXPECT_TRUE(info.features.A); + EXPECT_TRUE(info.features.F); + EXPECT_TRUE(info.features.D); + EXPECT_FALSE(info.features.Q); + EXPECT_TRUE(info.features.C); + EXPECT_FALSE(info.features.V); + EXPECT_TRUE(info.features.Zicsr); + EXPECT_TRUE(info.features.Zifencei); +} + } // namespace } // namespace cpu_features