mirror of
https://github.com/anrieff/libcpuid
synced 2025-02-12 20:24:05 +00:00
Add rdcpuid interface for kernel drivers on ARM CPUs
This commit is contained in:
parent
6e6b4bcbf5
commit
0f0b1e6060
6 changed files with 402 additions and 31 deletions
|
@ -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)
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
129
libcpuid/libcpuid_arm_driver.h
Normal file
129
libcpuid/libcpuid_arm_driver.h
Normal file
|
@ -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__ */
|
179
libcpuid/rdcpuid.c
Normal file
179
libcpuid/rdcpuid.c
Normal file
|
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#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 <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
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 */
|
34
libcpuid/rdcpuid.h
Normal file
34
libcpuid/rdcpuid.h
Normal file
|
@ -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__ */
|
Loading…
Add table
Reference in a new issue