Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial support for powerpc64le initialization. #267

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ IF(NOT CMAKE_SYSTEM_PROCESSOR)
"cpuinfo will compile, but cpuinfo_initialize() will always fail.")
SET(CPUINFO_SUPPORTED_PLATFORM FALSE)
ENDIF()
ELSEIF(NOT CPUINFO_TARGET_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?|armv[5-8].*|aarch64|arm64.*|ARM64.*|riscv(32|64))$")
ELSEIF(NOT CPUINFO_TARGET_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?|armv[5-8].*|aarch64|arm64.*|ARM64.*|riscv(32|64)|ppc64le)$")
MESSAGE(WARNING
"Target processor architecture \"${CPUINFO_TARGET_PROCESSOR}\" is not supported in cpuinfo. "
"cpuinfo will compile, but cpuinfo_initialize() will always fail.")
Expand Down Expand Up @@ -184,6 +184,14 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
LIST(APPEND CPUINFO_SRCS src/x86/freebsd/init.c)
ENDIF()
ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(ppc64le)$" )
LIST(APPEND CPUINFO_SRCS
src/powerpc/uarch.c
src/powerpc/cache.c
src/powerpc/linux/cpuinfo.c
src/powerpc/linux/ppc64-hw.c
src/powerpc/linux/init.c
src/powerpc/linux/ppc64-isa.c)
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "^Windows" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(ARM64|arm64)$")
LIST(APPEND CPUINFO_SRCS
src/arm/windows/init-by-logical-sys-info.c
Expand Down Expand Up @@ -856,6 +864,14 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_UNIT_TESTS)
TARGET_LINK_LIBRARIES(cache-test PRIVATE cpuinfo_internals gtest gtest_main)
ADD_TEST(NAME cache-test COMMAND cache-test)
ENDIF()

IF(CMAKE_SYSTEM_NAME STREQUAL "POWER" OR CMAKE_SYSTEM_PROCESSOR MATCHES "^(ppc64le)$")
ADD_EXECUTABLE(power-features-test test/name/power-features.cc)
CPUINFO_TARGET_ENABLE_CXX11(power-features-test)
CPUINFO_TARGET_RUNTIME_LIBRARY(power-features-test)
TARGET_LINK_LIBRARIES(power-features-test PRIVATE cpuinfo_internals gtest gtest_main)
ADD_TEST(NAME power-features-test COMMAND power-features-test)
ENDIF()
ENDIF()

# ---[ Helper and debug tools
Expand Down
12 changes: 12 additions & 0 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ def main(args):
if options.mock:
sources += ["linux/mockfile.c"]
build.static_library("cpuinfo", map(build.cc, sources))
if build.target.is_ppc64:
sources += [ "powerpc/uarch.c", "powerpc/cache.c"]
if build.target.is_linux:
sources += [
"powerpc/linux/cpuinfo.c"
"powerpc/linux/ppc64-hw.c",
"powerpc/linux/init.c",
"powerpc/linux/ppc64-isa.c",
]


with build.options(source_dir="tools", deps=[build, build.deps.clog]):
build.executable("cpu-info", build.cc("cpu-info.c"))
Expand All @@ -91,6 +101,8 @@ def main(args):
build.smoketest("get-current-test", build.cxx("get-current.cc"))
if build.target.is_x86_64:
build.smoketest("brand-string-test", build.cxx("name/brand-string.cc"))
if build.target.is_ppc64:
build.smoketest("power-features-test", build.cxx("name/power-features.cc"))
if options.mock:
with build.options(source_dir="test", include_dirs="test", macros="CPUINFO_MOCK", deps=[build, build.deps.googletest]):
if build.target.is_arm64 and build.target.is_linux:
Expand Down
60 changes: 60 additions & 0 deletions include/cpuinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,21 @@ enum cpuinfo_uarch {

/** HiSilicon TaiShan v110 (Huawei Kunpeng 920 series processors). */
cpuinfo_uarch_taishan_v110 = 0x00C00100,

/** IBM POWER 7. */
cpuinfo_uarch_power7 = 0x00D00100,
/** IBM POWER 7p. */
cpuinfo_uarch_power7p = 0x00D00101,
/** IBM POWER 8. */
cpuinfo_uarch_power8 = 0x00D00200,
/** IBM POWER8E. */
cpuinfo_uarch_power8e = 0x00D00201,
/** IBM POWER8NVL */
cpuinfo_uarch_power8nvl = 0x00D00202,
/** IBM POWER 9. */
cpuinfo_uarch_power9 = 0x00D00303,
/** IBM POWER 10. */
cpuinfo_uarch_power10 = 0x00D00400,
};

struct cpuinfo_processor {
Expand Down Expand Up @@ -671,9 +686,14 @@ struct cpuinfo_core {
#elif CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
/** Value of Main ID Register (MIDR) for this core */
uint32_t midr;
#elif CPUINFO_ARCH_PPC64
/** Value of Processor Version Register for this core */
uint32_t pvr;
#endif
/** Clock rate (non-Turbo) of the core, in Hz */
uint64_t frequency;

bool disabled;
};

struct cpuinfo_cluster {
Expand All @@ -699,6 +719,9 @@ struct cpuinfo_cluster {
#elif CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
/** Value of Main ID Register (MIDR) of the cores in the cluster */
uint32_t midr;
#elif CPUINFO_ARCH_PPC64
/** Value of Processor Version Register in this cluster */
uint32_t pvr;
#endif
/** Clock rate (non-Turbo) of the cores in the cluster, in Hz */
uint64_t frequency;
Expand Down Expand Up @@ -732,6 +755,9 @@ struct cpuinfo_uarch_info {
#elif CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
/** Value of Main ID Register (MIDR) for the microarchitecture */
uint32_t midr;
#elif CPUINFO_ARCH_PPC64
/** Value of Processor Version Register for this core */
uint32_t pvr;
#endif
/** Number of logical processors with the microarchitecture */
uint32_t processor_count;
Expand Down Expand Up @@ -2218,6 +2244,40 @@ static inline bool cpuinfo_has_riscv_v(void) {
#endif
}

#if CPUINFO_ARCH_PPC64
struct cpuinfo_powerpc_isa {
bool vsx;
bool htm;
bool mma;
};

extern struct cpuinfo_powerpc_isa cpuinfo_isa;
#endif

static inline bool cpuinfo_has_powerpc_vsx(void) {
#if CPUINFO_ARCH_PPC64
return cpuinfo_isa.vsx;
#else
return false;
#endif
}

static inline bool cpuinfo_has_powerpc_htm(void) {
#if CPUINFO_ARCH_PPC64
return cpuinfo_isa.htm;
#else
return false;
#endif
}

static inline bool cpuinfo_has_powerpc_mma(void) {
#if CPUINFO_ARCH_PPC64
return cpuinfo_isa.mma;
#else
return false;
#endif
}

const struct cpuinfo_processor* CPUINFO_ABI cpuinfo_get_processors(void);
const struct cpuinfo_core* CPUINFO_ABI cpuinfo_get_cores(void);
const struct cpuinfo_cluster* CPUINFO_ABI cpuinfo_get_clusters(void);
Expand Down
14 changes: 7 additions & 7 deletions src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ uint32_t cpuinfo_packages_count = 0;
uint32_t cpuinfo_cache_count[cpuinfo_cache_level_max] = {0};
uint32_t cpuinfo_max_cache_size = 0;

#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 || CPUINFO_ARCH_PPC64
struct cpuinfo_uarch_info* cpuinfo_uarchs = NULL;
uint32_t cpuinfo_uarchs_count = 0;
#else
Expand All @@ -41,7 +41,7 @@ struct cpuinfo_uarch_info cpuinfo_global_uarch = {cpuinfo_uarch_unknown};
uint32_t cpuinfo_linux_cpu_max = 0;
const struct cpuinfo_processor** cpuinfo_linux_cpu_to_processor_map = NULL;
const struct cpuinfo_core** cpuinfo_linux_cpu_to_core_map = NULL;
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 || CPUINFO_ARCH_PPC64
const uint32_t* cpuinfo_linux_cpu_to_uarch_index_map = NULL;
#endif
#endif
Expand Down Expand Up @@ -78,7 +78,7 @@ const struct cpuinfo_uarch_info* cpuinfo_get_uarchs() {
if (!cpuinfo_is_initialized) {
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarchs");
}
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 || CPUINFO_ARCH_PPC64
return cpuinfo_uarchs;
#else
return &cpuinfo_global_uarch;
Expand Down Expand Up @@ -129,7 +129,7 @@ const struct cpuinfo_uarch_info* cpuinfo_get_uarch(uint32_t index) {
if (!cpuinfo_is_initialized) {
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarch");
}
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 || CPUINFO_ARCH_PPC64
if CPUINFO_UNLIKELY (index >= cpuinfo_uarchs_count) {
return NULL;
}
Expand Down Expand Up @@ -174,7 +174,7 @@ uint32_t cpuinfo_get_uarchs_count(void) {
if (!cpuinfo_is_initialized) {
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "uarchs_count");
}
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 || CPUINFO_ARCH_PPC64
return cpuinfo_uarchs_count;
#else
return 1;
Expand Down Expand Up @@ -350,7 +350,7 @@ uint32_t CPUINFO_ABI cpuinfo_get_current_uarch_index(void) {
if CPUINFO_UNLIKELY (!cpuinfo_is_initialized) {
cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "current_uarch_index");
}
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 || CPUINFO_ARCH_PPC64
#ifdef __linux__
if (cpuinfo_linux_cpu_to_uarch_index_map == NULL) {
/* Special case: avoid syscall on systems with only a single
Expand Down Expand Up @@ -385,7 +385,7 @@ uint32_t CPUINFO_ABI cpuinfo_get_current_uarch_index_with_default(uint32_t defau
cpuinfo_log_fatal(
"cpuinfo_get_%s called before cpuinfo is initialized", "current_uarch_index_with_default");
}
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 || CPUINFO_ARCH_PPC64
#ifdef __linux__
if (cpuinfo_linux_cpu_to_uarch_index_map == NULL) {
/* Special case: avoid syscall on systems with only a single
Expand Down
3 changes: 2 additions & 1 deletion src/cpuinfo/internal-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extern CPUINFO_INTERNAL uint32_t cpuinfo_packages_count;
extern CPUINFO_INTERNAL uint32_t cpuinfo_cache_count[cpuinfo_cache_level_max];
extern CPUINFO_INTERNAL uint32_t cpuinfo_max_cache_size;

#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64 || CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 || CPUINFO_ARCH_PPC64
extern CPUINFO_INTERNAL struct cpuinfo_uarch_info* cpuinfo_uarchs;
extern CPUINFO_INTERNAL uint32_t cpuinfo_uarchs_count;
#else
Expand All @@ -61,6 +61,7 @@ CPUINFO_PRIVATE void cpuinfo_arm_mach_init(void);
CPUINFO_PRIVATE void cpuinfo_arm_linux_init(void);
CPUINFO_PRIVATE void cpuinfo_riscv_linux_init(void);
CPUINFO_PRIVATE void cpuinfo_emscripten_init(void);
CPUINFO_PRIVATE void cpuinfo_powerpc_linux_init(void);

CPUINFO_PRIVATE uint32_t cpuinfo_compute_max_cache_size(const struct cpuinfo_processor* processor);

Expand Down
6 changes: 6 additions & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ bool CPUINFO_ABI cpuinfo_initialize(void) {
#else
cpuinfo_log_error("operating system is not supported in cpuinfo");
#endif
#elif CPUINFO_ARCH_PPC64
#if defined(__linux__)
pthread_once(&init_guard, &cpuinfo_powerpc_linux_init);
#else
cpuinfo_log_error("operating system is not supported in cpuinfo");
#endif
#elif CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
#if defined(__linux__)
pthread_once(&init_guard, &cpuinfo_arm_linux_init);
Expand Down
1 change: 1 addition & 0 deletions src/linux/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ CPUINFO_INTERNAL bool cpuinfo_linux_get_processor_package_id(
uint32_t processor,
uint32_t package_id[restrict static 1]);
CPUINFO_INTERNAL bool cpuinfo_linux_get_processor_core_id(uint32_t processor, uint32_t core_id[restrict static 1]);
CPUINFO_INTERNAL bool cpuinfo_linux_get_processor_online_status(uint32_t processor, uint32_t* online_status);

CPUINFO_INTERNAL bool cpuinfo_linux_detect_possible_processors(
uint32_t max_processors_count,
Expand Down
30 changes: 30 additions & 0 deletions src/linux/processors.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
#define CORE_ID_FILENAME_FORMAT "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/core_id"
#define CORE_ID_FILESIZE 32

#define PROCESSOR_ONLINE_FILENAME_SIZE (sizeof("/sys/devices/system/cpu/cpu" STRINGIFY(UINT32_MAX) "/online"))
#define PROCESSOR_ONLINE_FILENAME_FORMAT "/sys/devices/system/cpu/cpu%" PRIu32 "/online"
#define PROCESSOR_ONLINE_FILESIZE 32
#define CORE_CPUS_FILENAME_SIZE (sizeof("/sys/devices/system/cpu/cpu" STRINGIFY(UINT32_MAX) "/topology/core_cpus_list"))
#define CORE_CPUS_FILENAME_FORMAT "/sys/devices/system/cpu/cpu%" PRIu32 "/topology/core_cpus_list"
#define CORE_SIBLINGS_FILENAME_SIZE \
Expand Down Expand Up @@ -280,6 +283,33 @@ bool cpuinfo_linux_get_processor_package_id(uint32_t processor, uint32_t package
}
}

bool cpuinfo_linux_get_processor_online_status(uint32_t processor, uint32_t* online_status_ptr) {
char processor_online_filename[PROCESSOR_ONLINE_FILENAME_SIZE];
const int chars_formatted = snprintf(
processor_online_filename, PROCESSOR_ONLINE_FILENAME_SIZE, PROCESSOR_ONLINE_FILENAME_FORMAT, processor);
if ((unsigned int)chars_formatted >= PROCESSOR_ONLINE_FILENAME_SIZE) {
cpuinfo_log_warning("failed to format filename for online status of processor %" PRIu32, processor);
return 0;
}
uint32_t online_status;
if (cpuinfo_linux_parse_small_file(
processor_online_filename, PROCESSOR_ONLINE_FILESIZE, uint32_parser, &online_status)) {
cpuinfo_log_debug(
"parsed online status value of %" PRIu32 " for logical processor %" PRIu32 " from %s",
online_status,
processor,
processor_online_filename);
*online_status_ptr = online_status;
return true;
} else {
cpuinfo_log_info(
"failed to parse online status for processor %" PRIu32 " from %s",
processor,
processor_online_filename);
return false;
}
}

static bool max_processor_number_parser(uint32_t processor_list_start, uint32_t processor_list_end, void* context) {
uint32_t* processor_number_ptr = (uint32_t*)context;
const uint32_t processor_list_last = processor_list_end - 1;
Expand Down
18 changes: 18 additions & 0 deletions src/powerpc/api.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include <stdbool.h>
#include <stdint.h>

#include <cpuinfo.h>

enum cpuinfo_powerpc_chipset_vendor { cpuinfo_powerpc_chipset_vendor_unknown = 0, cpuinfo_powerpc_chipset_vendor_ibm };
void cpuinfo_powerpc_decode_vendor_uarch(
uint32_t vendor_id,
enum cpuinfo_vendor vendor[restrict static 1],
enum cpuinfo_uarch uarch[restrict static 1]);

void cpuinfo_powerpc_decode_cache(
struct cpuinfo_cache l1i[restrict static 1],
struct cpuinfo_cache l1d[restrict static 1],
struct cpuinfo_cache l2[restrict static 1],
struct cpuinfo_cache l3[restrict static 1]);
Loading
Loading