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