diff --git a/libcpuid/CMakeLists.txt b/libcpuid/CMakeLists.txt index 1a10ccc..65d7556 100644 --- a/libcpuid/CMakeLists.txt +++ b/libcpuid/CMakeLists.txt @@ -7,7 +7,8 @@ set(cpuid_sources rdtsc.c libcpuid_util.c rdmsr.c - asm-bits.c) + asm-bits.c + rdcpuid.c) if(WIN32) list(APPEND cpuid_sources msrdriver.c) diff --git a/libcpuid/cpuid_main.c b/libcpuid/cpuid_main.c index 057be0c..5f694d0 100644 --- a/libcpuid/cpuid_main.c +++ b/libcpuid/cpuid_main.c @@ -31,6 +31,10 @@ #include "recog_intel.h" #include "asm-bits.h" #include "libcpuid_util.h" +#if defined(PLATFORM_ARM) || defined(PLATFORM_AARCH64) +# include "libcpuid_arm_driver.h" +# include "rdcpuid.h" +#endif /* ARM */ #ifdef HAVE_CONFIG_H # include "config.h" #endif /* HAVE_CONFIG_H */ @@ -1280,9 +1284,6 @@ int cpuid_get_raw_data_core(struct cpu_raw_data_t* data, logical_cpu_t logical_c { bool affinity_saved = false; - if (!cpuid_present()) - return cpuid_set_error(ERR_NO_CPUID); - if (logical_cpu != (logical_cpu_t) -1) { debugf(2, "Getting raw dump for logical CPU %u\n", logical_cpu); if (!set_cpu_affinity(logical_cpu)) @@ -1292,6 +1293,10 @@ int cpuid_get_raw_data_core(struct cpu_raw_data_t* data, logical_cpu_t logical_c #if defined(PLATFORM_X86) || defined(PLATFORM_X64) unsigned i; + + if (!cpuid_present()) + return cpuid_set_error(ERR_NO_CPUID); + for (i = 0; i < 32; i++) cpu_exec_cpuid(i, data->basic_cpuid[i]); for (i = 0; i < 32; i++) @@ -1332,33 +1337,54 @@ int cpuid_get_raw_data_core(struct cpu_raw_data_t* data, logical_cpu_t logical_c data->amd_fn80000026h[i][ECX] = i; cpu_exec_cpuid_ext(data->amd_fn80000026h[i]); } -#elif defined(PLATFORM_ARM) - /* We cannot support ARM CPUs running in 32-bit mode, because the Main ID Register is accessible only in privileged modes - Some related links: - - https://github.com/anrieff/libcpuid/issues/96 - - https://developer.arm.com/documentation/ddi0406/b/System-Level-Architecture/Protected-Memory-System-Architecture--PMSA-/CP15-registers-for-a-PMSA-implementation/c0--Main-ID-Register--MIDR- - */ -# warning The 32-bit ARM platform is not supported (Main ID Register is accessible only in privileged modes) - UNUSED(data); -#elif defined(PLATFORM_AARCH64) - cpu_exec_mrs("MIDR_EL1", data->arm_midr); - cpu_exec_mrs("MPIDR_EL1", data->arm_mpidr); - cpu_exec_mrs("REVIDR_EL1", data->arm_revidr); - cpu_exec_mrs(SYS_ID_AA64DFR0_EL1, data->arm_id_aa64dfr[0]); - cpu_exec_mrs(SYS_ID_AA64DFR1_EL1, data->arm_id_aa64dfr[1]); - cpu_exec_mrs(SYS_ID_AA64ISAR0_EL1, data->arm_id_aa64isar[0]); - cpu_exec_mrs(SYS_ID_AA64ISAR1_EL1, data->arm_id_aa64isar[1]); - cpu_exec_mrs(SYS_ID_AA64ISAR2_EL1, data->arm_id_aa64isar[2]); - cpu_exec_mrs(SYS_ID_AA64MMFR0_EL1, data->arm_id_aa64mmfr[0]); - cpu_exec_mrs(SYS_ID_AA64MMFR1_EL1, data->arm_id_aa64mmfr[1]); - cpu_exec_mrs(SYS_ID_AA64MMFR2_EL1, data->arm_id_aa64mmfr[2]); - cpu_exec_mrs(SYS_ID_AA64MMFR3_EL1, data->arm_id_aa64mmfr[3]); - cpu_exec_mrs(SYS_ID_AA64MMFR4_EL1, data->arm_id_aa64mmfr[4]); - cpu_exec_mrs(SYS_ID_AA64PFR0_EL1, data->arm_id_aa64pfr[0]); - cpu_exec_mrs(SYS_ID_AA64PFR1_EL1, data->arm_id_aa64pfr[1]); - cpu_exec_mrs(SYS_ID_AA64PFR2_EL1, data->arm_id_aa64pfr[2]); - cpu_exec_mrs(SYS_ID_AA64SMFR0_EL1, data->arm_id_aa64smfr[0]); - cpu_exec_mrs(SYS_ID_AA64ZFR0_EL1, data->arm_id_aa64zfr[0]); +#elif defined(PLATFORM_ARM) || defined(PLATFORM_AARCH64) + unsigned i; + struct cpuid_driver_t *handle; + + if ((handle = cpu_cpuid_driver_open_core(logical_cpu)) != NULL) { + debugf(2, "Using kernel driver to read register on logical CPU %u\n", logical_cpu); + cpu_read_arm_register_64b(handle, REQ_MIDR, &data->arm_midr); + cpu_read_arm_register_64b(handle, REQ_MPIDR, &data->arm_mpidr); + cpu_read_arm_register_64b(handle, REQ_REVIDR, &data->arm_revidr); + for (i = 0; i < MAX_ARM_ID_AFR_REGS; i++) + cpu_read_arm_register_32b(handle, REQ_ID_AFR0 + i, &data->arm_id_afr[i]); + for (i = 0; i < MAX_ARM_ID_DFR_REGS; i++) + cpu_read_arm_register_32b(handle, REQ_ID_DFR0 + i, &data->arm_id_dfr[i]); + for (i = 0; i < MAX_ARM_ID_ISAR_REGS; i++) + cpu_read_arm_register_32b(handle, REQ_ID_ISAR0 + i, &data->arm_id_isar[i]); + for (i = 0; i < MAX_ARM_ID_MMFR_REGS; i++) + cpu_read_arm_register_32b(handle, REQ_ID_MMFR0 + i, &data->arm_id_mmfr[i]); + for (i = 0; i < MAX_ARM_ID_PFR_REGS; i++) + cpu_read_arm_register_32b(handle, REQ_ID_PFR0 + i, &data->arm_id_pfr[i]); + cpu_cpuid_driver_close(handle); + } +# if defined(PLATFORM_AARCH64) + else { + if (!cpuid_present()) + return cpuid_set_error(ERR_NO_CPUID); + debugf(2, "Using MRS instruction to read register on logical CPU %u\n", logical_cpu); + cpu_exec_mrs(AARCH64_REG_MIDR_EL1, data->arm_midr); + cpu_exec_mrs(AARCH64_REG_MPIDR_EL1, data->arm_mpidr); + cpu_exec_mrs(AARCH64_REG_REVIDR_EL1, data->arm_revidr); + cpu_exec_mrs(AARCH64_REG_ID_AA64AFR0_EL1, data->arm_id_aa64afr[0]); + cpu_exec_mrs(AARCH64_REG_ID_AA64AFR1_EL1, data->arm_id_aa64afr[1]); + cpu_exec_mrs(AARCH64_REG_ID_AA64DFR0_EL1, data->arm_id_aa64dfr[0]); + cpu_exec_mrs(AARCH64_REG_ID_AA64DFR1_EL1, data->arm_id_aa64dfr[1]); + cpu_exec_mrs(AARCH64_REG_ID_AA64ISAR0_EL1, data->arm_id_aa64isar[0]); + cpu_exec_mrs(AARCH64_REG_ID_AA64ISAR1_EL1, data->arm_id_aa64isar[1]); + cpu_exec_mrs(AARCH64_REG_ID_AA64ISAR2_EL1, data->arm_id_aa64isar[2]); + cpu_exec_mrs(AARCH64_REG_ID_AA64MMFR0_EL1, data->arm_id_aa64mmfr[0]); + cpu_exec_mrs(AARCH64_REG_ID_AA64MMFR1_EL1, data->arm_id_aa64mmfr[1]); + cpu_exec_mrs(AARCH64_REG_ID_AA64MMFR2_EL1, data->arm_id_aa64mmfr[2]); + cpu_exec_mrs(AARCH64_REG_ID_AA64MMFR3_EL1, data->arm_id_aa64mmfr[3]); + cpu_exec_mrs(AARCH64_REG_ID_AA64MMFR4_EL1, data->arm_id_aa64mmfr[4]); + cpu_exec_mrs(AARCH64_REG_ID_AA64PFR0_EL1, data->arm_id_aa64pfr[0]); + cpu_exec_mrs(AARCH64_REG_ID_AA64PFR1_EL1, data->arm_id_aa64pfr[1]); + cpu_exec_mrs(AARCH64_REG_ID_AA64PFR2_EL1, data->arm_id_aa64pfr[2]); + cpu_exec_mrs(AARCH64_REG_ID_AA64SMFR0_EL1, data->arm_id_aa64smfr[0]); + cpu_exec_mrs(AARCH64_REG_ID_AA64ZFR0_EL1, data->arm_id_aa64zfr[0]); + } +# endif /* PLATFORM_AARCH64 */ #else # warning This CPU architecture is not supported by libcpuid UNUSED(data); @@ -2204,6 +2230,7 @@ const char* cpuid_error(void) { ERR_HANDLE_R , "Error on handle read"}, { ERR_INVRANGE , "Invalid given range"}, { ERR_NOT_FOUND, "Requested type not found"}, + { ERR_IOCTL, "Error on ioctl"}, }; unsigned i; for (i = 0; i < COUNT_OF(matchtable); i++) diff --git a/libcpuid/libcpuid.h b/libcpuid/libcpuid.h index 6a1360c..e94e849 100644 --- a/libcpuid/libcpuid.h +++ b/libcpuid/libcpuid.h @@ -1202,6 +1202,7 @@ typedef enum { ERR_HANDLE_R = -15, /*!< Error on handle read */ ERR_INVRANGE = -16, /*!< Invalid given range */ ERR_NOT_FOUND= -17, /*!< Requested type not found */ + ERR_IOCTL = -18, /*!< Error on ioctl */ } cpu_error_t; /** diff --git a/libcpuid/libcpuid_arm_driver.h b/libcpuid/libcpuid_arm_driver.h new file mode 100644 index 0000000..79778a1 --- /dev/null +++ b/libcpuid/libcpuid_arm_driver.h @@ -0,0 +1,129 @@ +/* + * Copyright 2024 Veselin Georgiev, + * anrieffNOSPAM @ mgail_DOT.com (convert to gmail) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __LIBCPUID_ARM_DRIVER_H__ +#define __LIBCPUID_ARM_DRIVER_H__ + +#define AARCH64_REG_MIDR_EL1 "S3_0_C0_C0_0" +#define AARCH64_REG_MPIDR_EL1 "S3_0_C0_C0_5" +#define AARCH64_REG_REVIDR_EL1 "S3_0_C0_C0_6" +#define AARCH64_REG_ID_AFR0 "S3_0_C0_C1_3" +#define AARCH64_REG_ID_DFR0 "S3_0_C0_C1_2" +#define AARCH64_REG_ID_DFR1 "S3_0_C0_C3_5" +#define AARCH64_REG_ID_ISAR0 "S3_0_C0_C2_0" +#define AARCH64_REG_ID_ISAR1 "S3_0_C0_C2_1" +#define AARCH64_REG_ID_ISAR2 "S3_0_C0_C2_2" +#define AARCH64_REG_ID_ISAR3 "S3_0_C0_C2_3" +#define AARCH64_REG_ID_ISAR4 "S3_0_C0_C2_4" +#define AARCH64_REG_ID_ISAR5 "S3_0_C0_C2_5" +#define AARCH64_REG_ID_ISAR6 "S3_0_C0_C2_7" +#define AARCH64_REG_ID_MMFR0 "S3_0_C0_C1_4" +#define AARCH64_REG_ID_MMFR1 "S3_0_C0_C1_5" +#define AARCH64_REG_ID_MMFR2 "S3_0_C0_C1_6" +#define AARCH64_REG_ID_MMFR3 "S3_0_C0_C1_7" +#define AARCH64_REG_ID_MMFR4 "S3_0_C0_C2_6" +#define AARCH64_REG_ID_MMFR5 "S3_0_C0_C3_6" +#define AARCH64_REG_ID_PFR0 "S3_0_C0_C1_0" +#define AARCH64_REG_ID_PFR1 "S3_0_C0_C1_1" +#define AARCH64_REG_ID_PFR2 "S3_0_C0_C3_4" +#define AARCH64_REG_ID_AA64AFR0_EL1 "S3_0_C0_C5_4" +#define AARCH64_REG_ID_AA64AFR1_EL1 "S3_0_C0_C5_5" +#define AARCH64_REG_ID_AA64DFR0_EL1 "S3_0_C0_C5_0" +#define AARCH64_REG_ID_AA64DFR1_EL1 "S3_0_C0_C5_1" +#define AARCH64_REG_ID_AA64ISAR0_EL1 "S3_0_C0_C6_0" +#define AARCH64_REG_ID_AA64ISAR1_EL1 "S3_0_C0_C6_1" +#define AARCH64_REG_ID_AA64ISAR2_EL1 "S3_0_C0_C6_2" +#define AARCH64_REG_ID_AA64MMFR0_EL1 "S3_0_C0_C7_0" +#define AARCH64_REG_ID_AA64MMFR1_EL1 "S3_0_C0_C7_1" +#define AARCH64_REG_ID_AA64MMFR2_EL1 "S3_0_C0_C7_2" +#define AARCH64_REG_ID_AA64MMFR3_EL1 "S3_0_C0_C7_3" +#define AARCH64_REG_ID_AA64MMFR4_EL1 "S3_0_C0_C7_4" +#define AARCH64_REG_ID_AA64PFR0_EL1 "S3_0_C0_C4_0" +#define AARCH64_REG_ID_AA64PFR1_EL1 "S3_0_C0_C4_1" +#define AARCH64_REG_ID_AA64PFR2_EL1 "S3_0_C0_C4_2" +#define AARCH64_REG_ID_AA64SMFR0_EL1 "S3_0_C0_C4_5" +#define AARCH64_REG_ID_AA64ZFR0_EL1 "S3_0_C0_C4_4" + +typedef enum { + REQ_MIDR, + REQ_MPIDR, + REQ_REVIDR, + REQ_ID_AFR0, + REQ_ID_DFR0, + REQ_ID_DFR1, + REQ_ID_ISAR0, + REQ_ID_ISAR1, + REQ_ID_ISAR2, + REQ_ID_ISAR3, + REQ_ID_ISAR4, + REQ_ID_ISAR5, + REQ_ID_ISAR6, + REQ_ID_MMFR0, + REQ_ID_MMFR1, + REQ_ID_MMFR2, + REQ_ID_MMFR3, + REQ_ID_MMFR4, + REQ_ID_MMFR5, + REQ_ID_PFR0, + REQ_ID_PFR1, + REQ_ID_PFR2, +#if defined(__aarch64__) + REQ_ID_AA64AFR0, + REQ_ID_AA64AFR1, + REQ_ID_AA64DFR0, + REQ_ID_AA64DFR1, + REQ_ID_AA64ISAR0, + REQ_ID_AA64ISAR1, + REQ_ID_AA64ISAR2, + REQ_ID_AA64MMFR0, + REQ_ID_AA64MMFR1, + REQ_ID_AA64MMFR2, + REQ_ID_AA64MMFR3, + REQ_ID_AA64MMFR4, + REQ_ID_AA64PFR0, + REQ_ID_AA64PFR1, + REQ_ID_AA64PFR2, + REQ_ID_AA64SMFR0, + REQ_ID_AA64ZFR0, +#endif /* __aarch64__ */ + /* termination: */ + NUM_REG_REQUESTS, + REQ_INVALID = -1 +} reg_request_t; + +struct read_reg_t { + reg_request_t request; + union { + uint32_t value_32b; + uint64_t value_64b; + }; + int err; +}; +typedef struct read_reg_t read_reg_t; + +#define ARM_IOC_READ_REG _IOWR('c', 0xB0, read_reg_t) + +#endif /* __LIBCPUID_ARM_DRIVER_H__ */ diff --git a/libcpuid/rdcpuid.c b/libcpuid/rdcpuid.c new file mode 100644 index 0000000..8263b2e --- /dev/null +++ b/libcpuid/rdcpuid.c @@ -0,0 +1,179 @@ +/* + * Copyright 2024 Veselin Georgiev, + * anrieffNOSPAM @ mgail_DOT.com (convert to gmail) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* freebsd requires _XOPEN_SOURCE 600 for snprintf() + * for linux it is enough 500 */ +#define _XOPEN_SOURCE 600 +#include +#include +#include +#include "libcpuid.h" +#include "libcpuid_util.h" +#include "libcpuid_arm_driver.h" +#include "rdcpuid.h" + +#define CPUID_PATH_LEN 32 + +#if defined (__linux__) || defined (__gnu_linux__) || defined (__FreeBSD__) || defined (__DragonFly__) +/* Assuming linux with /dev/cpu/x/cpuid: */ +/* Assuming FreeBSD with /dev/cpuctlX */ +#include +#include +#include +#include +#include +#include +struct cpuid_driver_t { int fd; }; +static int load_driver(char *cpuid_path) +{ + const int file_exists = !access(cpuid_path, F_OK); + const int file_readable = !access(cpuid_path, R_OK); + + if (file_exists && file_readable) + return 1; + else if (file_exists && !file_readable) + return 0; + else if (getuid() != 0) + return 0; + else +# if defined (__linux__) || defined (__gnu_linux__) + return !system("modprobe cpuid 2> /dev/null"); +# elif defined (__FreeBSD__) || defined (__DragonFly__) + return !system("kldload -n cpuctl 2> /dev/null"); +# endif +} + +struct cpuid_driver_t* cpu_cpuid_driver_open_core(unsigned core_num) +{ + char cpuid[CPUID_PATH_LEN]; + struct cpuid_driver_t* handle; + if (core_num >= cpuid_get_total_cpus()) { + cpuid_set_error(ERR_INVCNB); + return NULL; + } +# if defined (__linux__) || defined (__gnu_linux__) + snprintf(cpuid, CPUID_PATH_LEN, "/dev/cpu/%u/cpuid", core_num); +# elif defined (__FreeBSD__) || defined (__DragonFly__) + snprintf(cpuid, CPUID_PATH_LEN, "/dev/cpuid%u", core_num); +# endif + if(!load_driver(cpuid)) { + cpuid_set_error(ERR_NO_DRIVER); + return NULL; + } + int fd = open(cpuid, O_RDONLY); + if (fd < 0) { + if (errno == EIO) { + cpuid_set_error(ERR_NO_CPUID); + return NULL; + } + cpuid_set_error(ERR_NO_DRIVER); + return NULL; + } + handle = (struct cpuid_driver_t*) malloc(sizeof(struct cpuid_driver_t)); + if (!handle) { + cpuid_set_error(ERR_NO_MEM); + close(fd); + return NULL; + } + handle->fd = fd; + return handle; +} + +int cpu_read_arm_register_32b(struct cpuid_driver_t* driver, reg_request_t request, uint32_t* result) +{ + struct read_reg_t read_reg; + read_reg.request = request; + + if (!driver || driver->fd < 0) + return cpuid_set_error(ERR_HANDLE); + + if(ioctl(driver->fd, ARM_IOC_READ_REG, &read_reg)) + return cpuid_set_error(ERR_IOCTL); + + *result = read_reg.value_32b; + return 0; +} + +int cpu_read_arm_register_64b(struct cpuid_driver_t* driver, reg_request_t request, uint64_t* result) +{ + struct read_reg_t read_reg; + read_reg.request = request; + + if (!driver || driver->fd < 0) + return cpuid_set_error(ERR_HANDLE); + + if(ioctl(driver->fd, ARM_IOC_READ_REG, &read_reg)) + return cpuid_set_error(ERR_IOCTL); + + *result = read_reg.value_64b; + return 0; +} + +int cpu_cpuid_driver_close(struct cpuid_driver_t* drv) +{ + if (drv && drv->fd >= 0) { + close(drv->fd); + free(drv); + } + return 0; +} + +#else /* Unsupported OS */ +/* On others OS (i.e., Darwin), we still do not support RDCPUID, so supply dummy struct + and functions */ + +struct cpuid_driver_t { int dummy; }; + +struct cpuid_driver_t* cpu_cpuid_driver_open_core(unsigned core_num) +{ + UNUSED(core_num); + cpuid_set_error(ERR_NOT_IMP); + return NULL; +} + +int cpu_read_arm_register_32b(struct cpuid_driver_t* driver, reg_request_t request, uint32_t* result) +{ + UNUSED(driver); + UNUSED(request); + UNUSED(result); + return cpuid_set_error(ERR_NOT_IMP); +} + +int cpu_read_arm_register_64b(struct cpuid_driver_t* driver, reg_request_t request, uint64_t* result) +{ + UNUSED(driver); + UNUSED(request); + UNUSED(result); + return cpuid_set_error(ERR_NOT_IMP); +} + +int cpu_cpuid_driver_close(struct cpuid_driver_t* driver) +{ + UNUSED(driver); + return cpuid_set_error(ERR_NOT_IMP); +} + +#endif /* Unsupported OS */ diff --git a/libcpuid/rdcpuid.h b/libcpuid/rdcpuid.h new file mode 100644 index 0000000..76364c9 --- /dev/null +++ b/libcpuid/rdcpuid.h @@ -0,0 +1,34 @@ +/* + * Copyright 2024 Veselin Georgiev, + * anrieffNOSPAM @ mgail_DOT.com (convert to gmail) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __RDCPUID_H__ +#define __RDCPUID_H__ + +struct cpuid_driver_t* cpu_cpuid_driver_open_core(unsigned core_num); +int cpu_read_arm_register_32b(struct cpuid_driver_t* driver, reg_request_t request, uint32_t* result); +int cpu_read_arm_register_64b(struct cpuid_driver_t* driver, reg_request_t request, uint64_t* result); +int cpu_cpuid_driver_close(struct cpuid_driver_t* drv); + +#endif /* __RDCPUID_H__ */