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 cpuInfo support for Loongarch systems #92

Open
wants to merge 5 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 18 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,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)$")
ELSEIF(NOT CPUINFO_TARGET_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?|armv[5-8].*|aarch64|arm64|ARM64|loongarch64)$")
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 @@ -171,6 +171,23 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
LIST(APPEND CPUINFO_SRCS
src/arm/android/properties.c)
ENDIF()
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND CPUINFO_TARGET_PROCESSOR STREQUAL "ARM64")
LIST(APPEND CPUINFO_SRCS src/arm/windows/init-by-logical-sys-info.c)
LIST(APPEND CPUINFO_SRCS src/arm/windows/init.c)
ELSEIF(CPUINFO_TARGET_PROCESSOR MATCHES "^(loongarch64)$")
LIST(APPEND CPUINFO_SRCS
src/loongarch/uarch.c
src/loongarch/cache.c)
IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
LIST(APPEND CPUINFO_SRCS
src/loongarch/linux/init.c
src/loongarch/linux/cpuinfo.c
src/loongarch/linux/clusters.c
src/loongarch/linux/chipset.c
src/loongarch/linux/cpucfg.c
src/loongarch/linux/hwcap.c
src/loongarch/linux/loongarch64-isa.c)
ENDIF()
ENDIF()

IF(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
Expand Down
13 changes: 13 additions & 0 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,19 @@ def main(args):
"arm/android/properties.c",
]

if build.target.is_loongarch64:
sources += ["loongarch/uarch.c", "loongarch/cache.c"]
if build.target.is_linux:
sources += [
"loongarch/linux/init.c",
"loongarch/linux/cpuinfo.c",
"loongarch/linux/clusters.c",
"loongarch/linux/cpucfg.c",
"loongarch/linux/chipset.c",
"loongarch/linux/hwcap.c",
"loongarch/linux/loongarch64-isa.c",
]

if build.target.is_macos:
sources += ["mach/topology.c"]
if build.target.is_linux or build.target.is_android:
Expand Down
5 changes: 5 additions & 0 deletions include/cpuinfo-mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ struct cpuinfo_mock_property {
#if CPUINFO_ARCH_ARM
void CPUINFO_ABI cpuinfo_set_hwcap2(uint32_t hwcap2);
#endif

#if CPUINFO_ARCH_LOONGARCH64
void CPUINFO_ABI cpuinfo_set_hwcap(uint32_t hwcap);
#endif

#endif

#if defined(__ANDROID__)
Expand Down
154 changes: 154 additions & 0 deletions include/cpuinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
#define CPUINFO_ARCH_ARM64 1
#endif

#if defined(__loongarch64)
#define CPUINFO_ARCH_LOONGARCH64 1
#endif

#if defined(__PPC64__) || defined(__powerpc64__) || defined(_ARCH_PPC64)
#define CPUINFO_ARCH_PPC64 1
#endif
Expand Down Expand Up @@ -64,6 +68,10 @@
#define CPUINFO_ARCH_ARM64 0
#endif

#ifndef CPUINFO_ARCH_LOONGARCH64
#define CPUINFO_ARCH_LOONGARCH64 0
#endif

#ifndef CPUINFO_ARCH_PPC64
#define CPUINFO_ARCH_PPC64 0
#endif
Expand Down Expand Up @@ -255,6 +263,10 @@ enum cpuinfo_vendor {
* Sold its ARM designs in 1997. The last processor design was released in 1997.
*/
cpuinfo_vendor_dec = 57,
/**
* Loongson. Vendor of LOONGARCH processor microarchitecture.
*/
cpuinfo_vendor_loongson = 58,
};

/**
Expand Down Expand Up @@ -519,6 +531,9 @@ enum cpuinfo_uarch {

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

/** Loongson LA4 64 (Loongarch3 series processors). */
cpuinfo_uarch_LA464 = 0x00D00100,
};

struct cpuinfo_processor {
Expand Down Expand Up @@ -550,6 +565,10 @@ struct cpuinfo_processor {
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
/** APIC ID (unique x86-specific ID of the logical processor) */
uint32_t apic_id;
#endif
#if CPUINFO_ARCH_LOONGARCH64
/** CPUCFG ID (unique loongarch-specific ID of the logical processor) */
uint32_t cpucfg_id;
#endif
struct {
/** Level 1 instruction cache */
Expand Down Expand Up @@ -586,6 +605,9 @@ 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_LOONGARCH64
/** Value of CPUCFG for this core */
uint32_t cpucfg;
#endif
/** Clock rate (non-Turbo) of the core, in Hz */
uint64_t frequency;
Expand Down Expand Up @@ -614,6 +636,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_LOONGARCH64
/** Value of CPUCFG for this cores in the cluster */
uint32_t cpucfg;
#endif
/** Clock rate (non-Turbo) of the cores in the cluster, in Hz */
uint64_t frequency;
Expand Down Expand Up @@ -647,6 +672,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_LOONGARCH64
/** Value of CPUCFG for the microarchitecture */
uint32_t cpucfg;
#endif
/** Number of logical processors with the microarchitecture */
uint32_t processor_count;
Expand Down Expand Up @@ -1815,6 +1843,132 @@ static inline bool cpuinfo_has_arm_svebf16(void) {
#endif
}

#if CPUINFO_ARCH_LOONGARCH64
/* This structure is not a part of stable API. Use cpuinfo_has_loongarch_* functions instead. */
struct cpuinfo_loongarch_isa {
bool cpucfg;
bool lam;
bool ual;
bool fpu;
bool lsx;
bool lasx;

bool crc32;
bool complex;
bool crypto;
bool lvz;
bool lbt_x86;
bool lbt_arm;
bool lbt_mips;
};

extern struct cpuinfo_loongarch_isa cpuinfo_isa;
#endif

static inline bool cpuinfo_has_loongarch_cpucfg(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.cpucfg;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_lam(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.lam;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_ual(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.ual;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_fpu(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.fpu;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_lsx(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.lsx;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_lasx(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.lasx;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_crc32(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.crc32;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_complex(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.complex;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_crypto(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.crypto;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_lvz(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.lvz;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_lbt_x86(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.lbt_x86;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_lbt_arm(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.lbt_arm;
#else
return false;
#endif
}

static inline bool cpuinfo_has_loongarch_lbt_mips(void) {
#if CPUINFO_ARCH_LOONGARCH64
return cpuinfo_isa.lbt_mips;
#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: 14 additions & 0 deletions src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ uint32_t cpuinfo_max_cache_size = 0;
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
struct cpuinfo_uarch_info* cpuinfo_uarchs = NULL;
uint32_t cpuinfo_uarchs_count = 0;
#elif CPUINFO_ARCH_LOONGARCH64
struct cpuinfo_uarch_info* cpuinfo_uarchs = NULL;
uint32_t cpuinfo_uarchs_count = 0;
#else
struct cpuinfo_uarch_info cpuinfo_global_uarch = { cpuinfo_uarch_unknown };
#endif
Expand All @@ -43,6 +46,8 @@ uint32_t cpuinfo_max_cache_size = 0;
const struct cpuinfo_core** cpuinfo_linux_cpu_to_core_map = NULL;
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
const uint32_t* cpuinfo_linux_cpu_to_uarch_index_map = NULL;
#elif CPUINFO_ARCH_LOONGARCH64
const uint32_t* cpuinfo_linux_cpu_to_uarch_index_map = NULL;
#endif
#endif

Expand Down Expand Up @@ -81,6 +86,8 @@ const struct cpuinfo_uarch_info* cpuinfo_get_uarchs() {
}
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
return cpuinfo_uarchs;
#elif CPUINFO_ARCH_LOONGARCH64
return cpuinfo_uarchs;
#else
return &cpuinfo_global_uarch;
#endif
Expand Down Expand Up @@ -135,6 +142,11 @@ const struct cpuinfo_uarch_info* cpuinfo_get_uarch(uint32_t index) {
return NULL;
}
return &cpuinfo_uarchs[index];
#elif CPUINFO_ARCH_LOONGARCH64
if CPUINFO_UNLIKELY(index >= cpuinfo_uarchs_count) {
return NULL;
}
return &cpuinfo_uarchs[index];
#else
if CPUINFO_UNLIKELY(index != 0) {
return NULL;
Expand Down Expand Up @@ -177,6 +189,8 @@ uint32_t cpuinfo_get_uarchs_count(void) {
}
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
return cpuinfo_uarchs_count;
#elif CPUINFO_ARCH_LOONGARCH64
return cpuinfo_uarchs_count;
#else
return 1;
#endif
Expand Down
4 changes: 4 additions & 0 deletions src/cpuinfo/internal-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ extern CPUINFO_INTERNAL uint32_t cpuinfo_max_cache_size;
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
extern CPUINFO_INTERNAL struct cpuinfo_uarch_info* cpuinfo_uarchs;
extern CPUINFO_INTERNAL uint32_t cpuinfo_uarchs_count;
#elif CPUINFO_ARCH_LOONGARCH64
extern CPUINFO_INTERNAL struct cpuinfo_uarch_info* cpuinfo_uarchs;
extern CPUINFO_INTERNAL uint32_t cpuinfo_uarchs_count;
#else
extern CPUINFO_INTERNAL struct cpuinfo_uarch_info cpuinfo_global_uarch;
#endif
Expand All @@ -56,6 +59,7 @@ CPUINFO_PRIVATE void cpuinfo_x86_linux_init(void);
CPUINFO_PRIVATE void cpuinfo_arm_mach_init(void);
CPUINFO_PRIVATE void cpuinfo_arm_linux_init(void);
CPUINFO_PRIVATE void cpuinfo_emscripten_init(void);
CPUINFO_PRIVATE void cpuinfo_loongarch_linux_init(void);

CPUINFO_PRIVATE uint32_t cpuinfo_compute_max_cache_size(const struct cpuinfo_processor* processor);

Expand Down
7 changes: 7 additions & 0 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,16 @@ bool CPUINFO_ABI cpuinfo_initialize(void) {
}
init_guard = true;
#endif
#elif CPUINFO_ARCH_LOONGARCH64
#if defined(__linux__)
pthread_once(&init_guard, &cpuinfo_loongarch_linux_init);
#else
cpuinfo_log_error("loongarch operating system is not supported in cpuinfo");
#endif
#else
cpuinfo_log_error("processor architecture is not supported in cpuinfo");
#endif

return cpuinfo_is_initialized;
}

Expand Down
4 changes: 4 additions & 0 deletions src/linux/processors.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ uint32_t cpuinfo_linux_get_max_possible_processor(uint32_t max_processors_count)
if (!cpuinfo_linux_parse_cpulist(POSSIBLE_CPULIST_FILENAME, max_processor_number_parser, &max_possible_processor)) {
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
cpuinfo_log_error("failed to parse the list of possible processors in %s", POSSIBLE_CPULIST_FILENAME);
#elif CPUINFO_ARCH_LOONGARCH64
cpuinfo_log_error("failed to parse the list of possible processors in %s", POSSIBLE_CPULIST_FILENAME);
#else
cpuinfo_log_warning("failed to parse the list of possible processors in %s", POSSIBLE_CPULIST_FILENAME);
#endif
Expand All @@ -248,6 +250,8 @@ uint32_t cpuinfo_linux_get_max_present_processor(uint32_t max_processors_count)
if (!cpuinfo_linux_parse_cpulist(PRESENT_CPULIST_FILENAME, max_processor_number_parser, &max_present_processor)) {
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
cpuinfo_log_error("failed to parse the list of present processors in %s", PRESENT_CPULIST_FILENAME);
#elif CPUINFO_ARCH_LOONGARCH64
cpuinfo_log_error("failed to parse the list of present processors in %s", PRESENT_CPULIST_FILENAME);
#else
cpuinfo_log_warning("failed to parse the list of present processors in %s", PRESENT_CPULIST_FILENAME);
#endif
Expand Down