diff --git a/CMakeLists.txt b/CMakeLists.txt index 99047e58..8ce3ffc9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -384,6 +384,13 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_MOCK_TESTS) TARGET_COMPILE_DEFINITIONS(cpuinfo_mock PRIVATE _GNU_SOURCE=1) ENDIF() + IF(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(riscv(32|64))$") + ADD_EXECUTABLE(starfive-visionfive-v2-test test/mock/starfive-visionfive-v2.cc) + TARGET_INCLUDE_DIRECTORIES(starfive-visionfive-v2-test BEFORE PRIVATE test/mock) + TARGET_LINK_LIBRARIES(starfive-visionfive-v2-test PRIVATE cpuinfo_mock gtest) + ADD_TEST(NAME starfive-visionfive-v2-test COMMAND starfive-visionfive-v2-test) + ENDIF() + IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv5te|armv7-a)$") ADD_EXECUTABLE(atm7029b-tablet-test test/mock/atm7029b-tablet.cc) TARGET_INCLUDE_DIRECTORIES(atm7029b-tablet-test BEFORE PRIVATE test/mock) diff --git a/include/cpuinfo-mock.h b/include/cpuinfo-mock.h index 3c1f637d..06741716 100644 --- a/include/cpuinfo-mock.h +++ b/include/cpuinfo-mock.h @@ -58,12 +58,22 @@ struct cpuinfo_mock_property { int CPUINFO_ABI cpuinfo_mock_close(int fd); ssize_t CPUINFO_ABI cpuinfo_mock_read(int fd, void* buffer, size_t capacity); - #if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 + #if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 \ + || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 void CPUINFO_ABI cpuinfo_set_hwcap(uint32_t hwcap); #endif #if CPUINFO_ARCH_ARM void CPUINFO_ABI cpuinfo_set_hwcap2(uint32_t hwcap2); #endif + #if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 + #include <sys/hwprobe.h> + typedef int (*cpuinfo_mock_riscv_hwprobe)(struct riscv_hwprobe* pairs, + size_t pair_count, + size_t cpu_count, + unsigned long *cpus, + unsigned int flags); + void CPUINFO_ABI cpuinfo_set_riscv_hwprobe(cpuinfo_mock_riscv_hwprobe riscv_hwprobe); + #endif #endif #if defined(__ANDROID__) diff --git a/src/riscv/linux/riscv-hw.c b/src/riscv/linux/riscv-hw.c index befdf3f6..4afc1082 100644 --- a/src/riscv/linux/riscv-hw.c +++ b/src/riscv/linux/riscv-hw.c @@ -5,6 +5,17 @@ #include <riscv/api.h> #include <riscv/linux/api.h> +#if CPUINFO_MOCK +#include <cpuinfo-mock.h> +#endif // CPUINFO_MOCK + +#if CPUINFO_MOCK +static cpuinfo_mock_riscv_hwprobe g_riscv_hwprobe; +void cpuinfo_set_riscv_hwprobe(cpuinfo_mock_riscv_hwprobe riscv_hwprobe) { + g_riscv_hwprobe = riscv_hwprobe; +} +#endif // CPUINFO_MOCK + void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe( uint32_t processor, enum cpuinfo_vendor vendor[restrict static 1], @@ -33,9 +44,13 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe( CPU_SET_S(processor, cpu_set_size, cpu_set); /* Request all available information from hwprobe. */ - int ret = __riscv_hwprobe(pairs, pairs_count, - cpu_set_size, (unsigned long*)cpu_set, - 0 /* flags */); +#if CPUINFO_MOCK + int ret = g_riscv_hwprobe(pairs, pairs_count, cpu_set_size, + (unsigned long*)cpu_set, 0 /* flags */); +#else + int ret = __riscv_hwprobe(pairs, pairs_count, cpu_set_size, + (unsigned long*)cpu_set, 0 /* flags */); +#endif if (ret < 0) { cpuinfo_log_warning("failed to get hwprobe information, err: %d", ret); goto cleanup; diff --git a/src/riscv/linux/riscv-isa.c b/src/riscv/linux/riscv-isa.c index ace451b8..112e705c 100644 --- a/src/riscv/linux/riscv-isa.c +++ b/src/riscv/linux/riscv-isa.c @@ -3,6 +3,10 @@ #include <riscv/linux/api.h> +#if CPUINFO_MOCK +#include <cpuinfo-mock.h> +#endif // CPUINFO_MOCK + /** * arch/riscv/include/uapi/asm/hwcap.h * @@ -16,9 +20,20 @@ #define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A')) #define COMPAT_HWCAP_ISA_V (1 << ('V' - 'A')) +#if CPUINFO_MOCK +static uint32_t g_mock_hwcap = 0; +void cpuinfo_set_hwcap(uint32_t hwcap) { + g_mock_hwcap = hwcap; +} +#endif // CPUINFO_MOCK + void cpuinfo_riscv_linux_decode_isa_from_hwcap( struct cpuinfo_riscv_isa isa[restrict static 1]) { - const unsigned long hwcap = getauxval(AT_HWCAP); +#if CPUINFO_MOCK + const uint32_t hwcap = g_mock_hwcap; +#else + const uint32_t hwcap = getauxval(AT_HWCAP); +#endif // CPUINFO_MOCK if (hwcap & COMPAT_HWCAP_ISA_I) { isa->i = true; diff --git a/test/mock/starfive-visionfive-v2.cc b/test/mock/starfive-visionfive-v2.cc new file mode 100644 index 00000000..a4dcb568 --- /dev/null +++ b/test/mock/starfive-visionfive-v2.cc @@ -0,0 +1,276 @@ +#include <gtest/gtest.h> + +#include <cpuinfo.h> +#include <cpuinfo-mock.h> + + +TEST(PROCESSORS, count) { + ASSERT_EQ(4, cpuinfo_get_processors_count()); +} + +TEST(PROCESSORS, non_null) { + ASSERT_TRUE(cpuinfo_get_processors()); +} + +TEST(PROCESSORS, core) { + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_EQ(cpuinfo_get_core(i), cpuinfo_get_processor(i)->core); + } +} + +TEST(PROCESSORS, cluster) { + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_EQ(cpuinfo_get_cluster(0), cpuinfo_get_processor(i)->cluster); + } +} + +TEST(PROCESSORS, package) { + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_EQ(cpuinfo_get_package(0), cpuinfo_get_processor(i)->package); + } +} + +TEST(PROCESSORS, linux_id) { + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_EQ(i, cpuinfo_get_processor(i)->linux_id); + } +} + +TEST(PROCESSORS, l1i) { + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_EQ(cpuinfo_get_l1i_cache(i), cpuinfo_get_processor(i)->cache.l1i); + } +} + +TEST(PROCESSORS, l1d) { + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_EQ(cpuinfo_get_l1d_cache(i), cpuinfo_get_processor(i)->cache.l1d); + } +} + +TEST(PROCESSORS, l2) { + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_EQ(cpuinfo_get_l2_cache(0), cpuinfo_get_processor(i)->cache.l2); + } +} + +TEST(PROCESSORS, l3) { + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_FALSE(cpuinfo_get_processor(i)->cache.l3); + } +} + +TEST(PROCESSORS, l4) { + for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) { + ASSERT_FALSE(cpuinfo_get_processor(i)->cache.l4); + } +} + +TEST(CORES, count) { + ASSERT_EQ(4, cpuinfo_get_cores_count()); +} + +TEST(CORES, non_null) { + ASSERT_TRUE(cpuinfo_get_cores()); +} + +TEST(CORES, processor_start) { + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + ASSERT_EQ(i, cpuinfo_get_core(i)->processor_start); + } +} + +TEST(CORES, processor_count) { + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + ASSERT_EQ(1, cpuinfo_get_core(i)->processor_count); + } +} + +TEST(CORES, core_id) { + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + ASSERT_EQ(i, cpuinfo_get_core(i)->core_id); + } +} + +TEST(CORES, cluster) { + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + ASSERT_EQ(cpuinfo_get_cluster(0), cpuinfo_get_core(i)->cluster); + } +} + +TEST(CORES, package) { + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + ASSERT_EQ(cpuinfo_get_package(0), cpuinfo_get_core(i)->package); + } +} + +TEST(CORES, vendor) { + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + ASSERT_EQ(cpuinfo_vendor_sifive, cpuinfo_get_core(i)->vendor); + } +} + +TEST(CORES, uarch) { + for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) { + ASSERT_EQ(cpuinfo_uarch_unknown, cpuinfo_get_core(i)->uarch); + } +} + +TEST(CLUSTERS, count) { + ASSERT_EQ(1, cpuinfo_get_clusters_count()); +} + +TEST(CLUSTERS, non_null) { + ASSERT_TRUE(cpuinfo_get_clusters()); +} + +TEST(CLUSTERS, processor_start) { + for (uint32_t i = 0; i < cpuinfo_get_clusters_count(); i++) { + ASSERT_EQ(0, cpuinfo_get_cluster(i)->processor_start); + } +} + +TEST(CLUSTERS, processor_count) { + for (uint32_t i = 0; i < cpuinfo_get_clusters_count(); i++) { + ASSERT_EQ(4, cpuinfo_get_cluster(i)->processor_count); + } +} + +TEST(CLUSTERS, core_start) { + for (uint32_t i = 0; i < cpuinfo_get_clusters_count(); i++) { + ASSERT_EQ(0, cpuinfo_get_cluster(i)->core_start); + } +} + +TEST(CLUSTERS, core_count) { + for (uint32_t i = 0; i < cpuinfo_get_clusters_count(); i++) { + ASSERT_EQ(4, cpuinfo_get_cluster(i)->core_count); + } +} + +TEST(CLUSTERS, cluster_id) { + for (uint32_t i = 0; i < cpuinfo_get_clusters_count(); i++) { + ASSERT_EQ(i, cpuinfo_get_cluster(i)->cluster_id); + } +} + +TEST(CLUSTERS, package) { + for (uint32_t i = 0; i < cpuinfo_get_clusters_count(); i++) { + ASSERT_EQ(cpuinfo_get_package(0), cpuinfo_get_cluster(i)->package); + } +} + +TEST(CLUSTERS, vendor) { + for (uint32_t i = 0; i < cpuinfo_get_clusters_count(); i++) { + ASSERT_EQ(cpuinfo_vendor_sifive, cpuinfo_get_cluster(i)->vendor); + } +} + +TEST(CLUSTERS, uarch) { + for (uint32_t i = 0; i < cpuinfo_get_clusters_count(); i++) { + ASSERT_EQ(cpuinfo_uarch_unknown, cpuinfo_get_cluster(i)->uarch); + } +} + +TEST(PACKAGES, count) { + ASSERT_EQ(1, cpuinfo_get_packages_count()); +} + +TEST(PACKAGES, name) { + for (uint32_t i = 0; i < cpuinfo_get_packages_count(); i++) { + ASSERT_EQ("", + std::string(cpuinfo_get_package(i)->name, + strnlen(cpuinfo_get_package(i)->name, CPUINFO_PACKAGE_NAME_MAX))); + } +} + +TEST(PACKAGES, processor_start) { + for (uint32_t i = 0; i < cpuinfo_get_packages_count(); i++) { + ASSERT_EQ(0, cpuinfo_get_package(i)->processor_start); + } +} + +TEST(PACKAGES, processor_count) { + for (uint32_t i = 0; i < cpuinfo_get_packages_count(); i++) { + ASSERT_EQ(4, cpuinfo_get_package(i)->processor_count); + } +} + +TEST(PACKAGES, core_start) { + for (uint32_t i = 0; i < cpuinfo_get_packages_count(); i++) { + ASSERT_EQ(0, cpuinfo_get_package(i)->core_start); + } +} + +TEST(PACKAGES, core_count) { + for (uint32_t i = 0; i < cpuinfo_get_packages_count(); i++) { + ASSERT_EQ(4, cpuinfo_get_package(i)->core_count); + } +} + +TEST(PACKAGES, cluster_start) { + for (uint32_t i = 0; i < cpuinfo_get_packages_count(); i++) { + ASSERT_EQ(0, cpuinfo_get_package(i)->cluster_start); + } +} + +TEST(PACKAGES, cluster_count) { + for (uint32_t i = 0; i < cpuinfo_get_packages_count(); i++) { + ASSERT_EQ(1, cpuinfo_get_package(i)->cluster_count); + } +} + +TEST(ISA, i) { + ASSERT_TRUE(cpuinfo_isa.i); +} + +TEST(ISA, m) { + ASSERT_TRUE(cpuinfo_isa.m); +} + +TEST(ISA, a) { + ASSERT_TRUE(cpuinfo_isa.a); +} + +TEST(ISA, f) { + ASSERT_TRUE(cpuinfo_isa.f); +} + +TEST(ISA, d) { + ASSERT_TRUE(cpuinfo_isa.d); +} + +TEST(ISA, c) { + ASSERT_TRUE(cpuinfo_isa.c); +} + +TEST(ISA, v) { + ASSERT_FALSE(cpuinfo_isa.v); +} + +#include <starfive-visionfive-v2.h> + +int riscv_hwprobe(struct riscv_hwprobe* pairs, size_t pair_count, + size_t /* cpu_count */, unsigned long * /* cpus */, + unsigned int /* flags */) { + for (size_t pair = 0; pair < pair_count; pair++) { + switch (pairs[pair].key) { + case RISCV_HWPROBE_KEY_MVENDORID: + pairs[pair].value = 0x489; + break; + default: + pairs[pair].key = -1; + break; + } + } + return 0; +} + +int main(int argc, char* argv[]) { + cpuinfo_mock_filesystem(filesystem); + cpuinfo_set_hwcap(UINT32_C(0x0000112D)); + cpuinfo_set_riscv_hwprobe(&riscv_hwprobe); + cpuinfo_initialize(); + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/mock/starfive-visionfive-v2.h b/test/mock/starfive-visionfive-v2.h new file mode 100644 index 00000000..1602de21 --- /dev/null +++ b/test/mock/starfive-visionfive-v2.h @@ -0,0 +1,187 @@ +struct cpuinfo_mock_file filesystem[] = { + { + .path = "/proc/cpuinfo", + .size = 292, + .content = + "processor\t: 0\n" + "hart\t: 1\n" + "isa\t: rv64imafdc\n" + "mmu\t: sv39\n" + "uarch\t: sifive,u74-mc\n" + "\n" + "processor\t: 1\n" + "hart\t: 2\n" + "isa\t: rv64imafdc\n" + "mmu\t: sv39\n" + "uarch\t: sifive,u74-mc\n" + "\n" + "processor\t: 2\n" + "hart\t: 3\n" + "isa\t: rv64imafdc\n" + "mmu\t: sv39\n" + "uarch\t: sifive,u74-mc\n" + "\n" + "processor\t: 3\n" + "hart\t: 4\n" + "isa\t: rv64imafdc\n" + "mmu\t: sv39\n" + "uarch\t: sifive,u74-mc\n" + "\n" + }, + { + .path = "/sys/devices/system/cpu/kernel_max", + .size = 3, + .content = "31\n", + }, + { + .path = "/sys/devices/system/cpu/possible", + .size = 4, + .content = "0-3\n", + }, + { + .path = "/sys/devices/system/cpu/present", + .size = 4, + .content = "0-3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu0/topology/physical_package_id", + .size = 2, + .content = "0\n", + }, + { + .path = "/sys/devices/system/cpu/cpu0/topology/core_cpus_list", + .size = 2, + .content = "0\n", + }, + { + .path = "/sys/devices/system/cpu/cpu0/topology/core_siblings_list", + .size = 2, + .content = "0\n", + }, + { + .path = "/sys/devices/system/cpu/cpu0/topology/cluster_cpus_list", + .size = 4, + .content = "0-3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu0/topology/package_cpus_list", + .size = 4, + .content = "0-3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu0/topology/core_id", + .size = 2, + .content = "0\n", + }, + { + .path = "/sys/devices/system/cpu/cpu0/topology/thread_siblings_list", + .size = 2, + .content = "0\n", + }, + { + .path = "/sys/devices/system/cpu/cpu1/topology/physical_package_id", + .size = 2, + .content = "0\n", + }, + { + .path = "/sys/devices/system/cpu/cpu1/topology/core_cpus_list", + .size = 2, + .content = "1\n", + }, + { + .path = "/sys/devices/system/cpu/cpu1/topology/core_siblings_list", + .size = 2, + .content = "1\n", + }, + { + .path = "/sys/devices/system/cpu/cpu1/topology/cluster_cpus_list", + .size = 4, + .content = "0-3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu1/topology/package_cpus_list", + .size = 4, + .content = "0-3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu1/topology/core_id", + .size = 2, + .content = "1\n", + }, + { + .path = "/sys/devices/system/cpu/cpu1/topology/thread_siblings_list", + .size = 2, + .content = "1\n", + }, + { + .path = "/sys/devices/system/cpu/cpu2/topology/physical_package_id", + .size = 2, + .content = "0\n", + }, + { + .path = "/sys/devices/system/cpu/cpu2/topology/core_cpus_list", + .size = 2, + .content = "2\n", + }, + { + .path = "/sys/devices/system/cpu/cpu2/topology/core_siblings_list", + .size = 2, + .content = "2\n", + }, + { + .path = "/sys/devices/system/cpu/cpu2/topology/cluster_cpus_list", + .size = 4, + .content = "0-3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu2/topology/package_cpus_list", + .size = 4, + .content = "0-3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu2/topology/core_id", + .size = 2, + .content = "2\n", + }, + { + .path = "/sys/devices/system/cpu/cpu2/topology/thread_siblings_list", + .size = 2, + .content = "2\n", + }, + { + .path = "/sys/devices/system/cpu/cpu3/topology/physical_package_id", + .size = 2, + .content = "0\n", + }, + { + .path = "/sys/devices/system/cpu/cpu3/topology/core_cpus_list", + .size = 2, + .content = "3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu3/topology/core_siblings_list", + .size = 2, + .content = "3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu3/topology/cluster_cpus_list", + .size = 4, + .content = "0-3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu3/topology/package_cpus_list", + .size = 4, + .content = "0-3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu3/topology/core_id", + .size = 2, + .content = "3\n", + }, + { + .path = "/sys/devices/system/cpu/cpu3/topology/thread_siblings_list", + .size = 2, + .content = "3\n", + }, + { NULL }, +};