/* XMRig * Copyright (c) 2025 Slayingripper * Copyright (c) 2018-2025 SChernykh * Copyright (c) 2016-2025 XMRig * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "base/tools/String.h" #include "3rdparty/fmt/core.h" #include #include #include namespace xmrig { struct riscv_cpu_desc { String model; String isa; String uarch; bool has_vector = false; bool has_aes = false; inline bool isReady() const { return !isa.isNull(); } }; static bool lookup_riscv(char *line, const char *pattern, String &value) { char *p = strstr(line, pattern); if (!p) { return false; } p += strlen(pattern); while (isspace(*p)) { ++p; } if (*p == ':') { ++p; } while (isspace(*p)) { ++p; } // Remove trailing newline size_t len = strlen(p); if (len > 0 && p[len - 1] == '\n') { p[len - 1] = '\0'; } // Ensure we call the const char* assignment (which performs a copy) // instead of the char* overload (which would take ownership of the pointer) value = (const char*)p; return true; } static bool read_riscv_cpuinfo(riscv_cpu_desc *desc) { auto fp = fopen("/proc/cpuinfo", "r"); if (!fp) { return false; } char buf[2048]; // Larger buffer for long ISA strings while (fgets(buf, sizeof(buf), fp) != nullptr) { lookup_riscv(buf, "model name", desc->model); if (lookup_riscv(buf, "isa", desc->isa)) { desc->isa.toLower(); for (const String& s : desc->isa.split('_')) { const char* p = s.data(); const size_t n = s.size(); if ((s.size() > 4) && (memcmp(p, "rv64", 4) == 0)) { for (size_t i = 4; i < n; ++i) { if (p[i] == 'v') { desc->has_vector = true; break; } } } else if (s == "zve64d") { desc->has_vector = true; } else if ((s == "zvkn") || (s == "zvknc") || (s == "zvkned") || (s == "zvkng")){ desc->has_aes = true; } } } lookup_riscv(buf, "uarch", desc->uarch); if (desc->isReady()) { break; } } fclose(fp); return desc->isReady(); } String cpu_name_riscv() { riscv_cpu_desc desc; if (read_riscv_cpuinfo(&desc)) { if (!desc.uarch.isNull()) { return fmt::format("{} ({})", desc.model, desc.uarch).c_str(); } return desc.model; } return "RISC-V"; } bool has_riscv_vector() { riscv_cpu_desc desc; if (read_riscv_cpuinfo(&desc)) { return desc.has_vector; } return false; } bool has_riscv_aes() { riscv_cpu_desc desc; if (read_riscv_cpuinfo(&desc)) { return desc.has_aes; } return false; } } // namespace xmrig