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

cache cpu info in a file at boot. #261

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 5 additions & 1 deletion deps/clog/include/clog.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
#define CLOG_DEBUG 5

#ifndef CLOG_VISIBILITY
#if defined(__ELF__)
#if defined(__GNUC__)
// ld.lld: error: undefined hidden symbol: clog_vlog_error
// referenced by log.h:16 (external/cpuinfo/src/cpuinfo/log.h)
#define CLOG_VISIBILITY
#elif defined(__ELF__)
#define CLOG_VISIBILITY __attribute__((__visibility__("internal")))
#elif defined(__MACH__)
#define CLOG_VISIBILITY __attribute__((__visibility__("hidden")))
Expand Down
27 changes: 27 additions & 0 deletions include/cpuinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -860,11 +860,38 @@ struct cpuinfo_x86_isa {
bool phe;
bool pmm;
bool lwp;
bool erms;
bool smap;
bool serialize;
};

extern struct cpuinfo_x86_isa cpuinfo_isa;
#endif

static inline bool cpuinfo_has_x86_erms(void) {
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
return cpuinfo_isa.erms;
#else
return false;
#endif
}

static inline bool cpuinfo_has_x86_smap(void) {
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
return cpuinfo_isa.smap;
#else
return false;
#endif
}

static inline bool cpuinfo_has_x86_serialize(void) {
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
return cpuinfo_isa.serialize;
#else
return false;
#endif
}

static inline bool cpuinfo_has_x86_rdtsc(void) {
#if CPUINFO_ARCH_X86_64
return true;
Expand Down
39 changes: 38 additions & 1 deletion src/x86/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,41 @@
#include <cpuinfo/utils.h>
#include <x86/api.h>
#include <x86/cpuid.h>
#include <x86/linux/api.h>

struct cpuinfo_x86_isa cpuinfo_isa = {0};
/*
* Structs cpuinfo_x86_isa, cpuinfo_x86_model_info and cpuinfo_x86_processor
* are dumped into cpuid.info file by cpuinfo-svc service on boot.
* Whenever libcpuinfo is initialized by any application, it will attempt to
* read cpuid.info file, if it exists, and the binary dump in the file is
* copied to these structs. If the file doesn't exist, we will fall back to
* original method of calling __cpuid() intrinsics to get the info.
* By this method, we can avoid __cpuid() calls during each init of cpuinfo.
* This will reduce VMX events in virtualized environments thereby
* improving performance.
*/


#ifdef __ANDROID__
struct cpuinfo_x86_cpuid_info x86_cpuid_info = { 0 };
#endif // __ANDROID__

struct cpuinfo_x86_isa cpuinfo_isa = { 0 };
CPUINFO_INTERNAL uint32_t cpuinfo_x86_clflush_size = 0;

void cpuinfo_x86_init_processor(struct cpuinfo_x86_processor* processor) {
#ifdef __ANDROID__
if (cpuinfo_x86_linux_parse_cpuid_info(&x86_cpuid_info)) {
*processor = x86_cpuid_info.processor;
cpuinfo_isa = x86_cpuid_info.isa;
#ifdef __DEBUG__
print_cpuid_info_file();
#endif
return;
}
cpuinfo_log_debug("falling back to __cpuid() method");
#endif // __ANDROID__

const struct cpuid_regs leaf0 = cpuid(0);
const uint32_t max_base_index = leaf0.eax;
const enum cpuinfo_vendor vendor = processor->vendor =
Expand Down Expand Up @@ -48,6 +78,9 @@ void cpuinfo_x86_init_processor(struct cpuinfo_x86_processor* processor) {

cpuinfo_isa = cpuinfo_x86_detect_isa(
leaf1, leaf0x80000001, max_base_index, max_extended_index, vendor, uarch);
#ifdef __ANDROID__
x86_cpuid_info.model = model_info;
#endif // __ANDROID__
}
if (max_extended_index >= UINT32_C(0x80000004)) {
struct cpuid_regs brand_string[3];
Expand All @@ -57,4 +90,8 @@ void cpuinfo_x86_init_processor(struct cpuinfo_x86_processor* processor) {
memcpy(processor->brand_string, brand_string, sizeof(processor->brand_string));
cpuinfo_log_debug("raw CPUID brand string: \"%48s\"", processor->brand_string);
}
#ifdef __ANDROID__
x86_cpuid_info.isa = cpuinfo_isa;
x86_cpuid_info.processor = *processor;
#endif // __ANDROID__
}
18 changes: 18 additions & 0 deletions src/x86/isa.c
Original file line number Diff line number Diff line change
Expand Up @@ -814,5 +814,23 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
*/
isa.rdpid = !!(structured_feature_info0.ecx & UINT32_C(0x00400000));

/*
* ERMS instruction:
* - Intel: ebx[bit 9] in structured feature info (ecx = 0).
*/
isa.erms = !!(structured_feature_info0.ebx & UINT32_C(0x00000200));

/*
* SMAP instruction:
* - Intel: ebx[bit 20] in structured feature info (ecx = 0).
*/
isa.smap = !!(structured_feature_info0.ebx & UINT32_C(0x00100000));

/*
* SERIALIZE instruction:
* - Intel: edx[bit 14] in structured feature info (ecx = 0).
*/
isa.serialize = !!(structured_feature_info0.edx & UINT32_C(0x00004000));

return isa;
}
17 changes: 17 additions & 0 deletions src/x86/linux/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,20 @@ struct cpuinfo_x86_linux_processor {
CPUINFO_INTERNAL bool cpuinfo_x86_linux_parse_proc_cpuinfo(
uint32_t max_processors_count,
struct cpuinfo_x86_linux_processor processors[restrict static max_processors_count]);

#ifdef __ANDROID__
#define CPUID_INFO_FILE "/data/system/cpuid.info"

struct cpuinfo_x86_cpuid_info {
struct cpuinfo_x86_isa isa;
struct cpuinfo_x86_model_info model;
struct cpuinfo_x86_processor processor;
};

CPUINFO_INTERNAL bool cpuinfo_x86_linux_parse_cpuid_info(
struct cpuinfo_x86_cpuid_info* x86_cpuid_info);

#ifdef __DEBUG__
CPUINFO_INTERNAL void print_cpuid_info_file(void);
#endif //__DEBUG__
#endif //__ANDROID__
123 changes: 123 additions & 0 deletions src/x86/linux/cpuinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,126 @@ bool cpuinfo_x86_linux_parse_proc_cpuinfo(
return cpuinfo_linux_parse_multiline_file(
"/proc/cpuinfo", BUFFER_SIZE, (cpuinfo_line_callback)parse_line, &state);
}

#ifdef __ANDROID__
bool cpuinfo_x86_linux_parse_cpuid_info(
struct cpuinfo_x86_cpuid_info* x86_cpuid_info)
{
cpuinfo_log_debug("reading cpuid.info file");
FILE* fd_info = fopen(CPUID_INFO_FILE, "rb");
if (!fd_info) {
cpuinfo_log_warning("failed to open file %s: %s", CPUID_INFO_FILE, strerror(errno));
return false;
}

int ret = fread(x86_cpuid_info, sizeof(struct cpuinfo_x86_cpuid_info), 1, fd_info);
if (!ret) {
cpuinfo_log_warning("failed to read cpuid info from %s: %s", CPUID_INFO_FILE, strerror(errno));
}

if (fclose(fd_info)) {
cpuinfo_log_warning("failed to close file %s: %s", CPUID_INFO_FILE, strerror(errno));
}

return ret ? true : false;
}

#ifdef __DEBUG__
void print_cpuid_info_file (void)
{
cpuinfo_log_debug("----------------------------");
/*
cpuinfo_log_debug("%-20s: %d", "ace", cpuinfo_has_x86_ace());
cpuinfo_log_debug("%-20s: %d", "ace2", cpuinfo_has_x86_ace2());
cpuinfo_log_debug("%-20s: %d", "clflush", cpuinfo_has_x86_clflush());
cpuinfo_log_debug("%-20s: %d", "clflushopt", cpuinfo_has_x86_clflushopt());
cpuinfo_log_debug("%-20s: %d", "lwp", cpuinfo_has_x86_lwp());
cpuinfo_log_debug("%-20s: %d", "msr", cpuinfo_has_x86_msr());
cpuinfo_log_debug("%-20s: %d", "phe", cpuinfo_has_x86_phe());
cpuinfo_log_debug("%-20s: %d", "pmm", cpuinfo_has_x86_pmm());
cpuinfo_log_debug("%-20s: %d", "rng", cpuinfo_has_x86_rng());
cpuinfo_log_debug("%-20s: %d", "sysenter", cpuinfo_has_x86_sysenter());
cpuinfo_log_debug("%-20s: %d", "syscall", cpuinfo_has_x86_syscall());
cpuinfo_log_debug("%-20s: %d", "emmx", cpuinfo_has_x86_emmx());
cpuinfo_log_debug("%-20s: %d", "fs_gs_base", cpuinfo_has_x86_fs_gs_base());
cpuinfo_log_debug("%-20s: %d", "fxsave", cpuinfo_has_x86_fxsave());
*/
cpuinfo_log_debug("%-20s: %d", "erms", cpuinfo_has_x86_erms());
cpuinfo_log_debug("%-20s: %d", "smap", cpuinfo_has_x86_smap());
cpuinfo_log_debug("%-20s: %d", "serialize", cpuinfo_has_x86_serialize());
cpuinfo_log_debug("%-20s: %d", "adx", cpuinfo_has_x86_adx());
cpuinfo_log_debug("%-20s: %d", "aes", cpuinfo_has_x86_aes());
cpuinfo_log_debug("%-20s: %d", "avx", cpuinfo_has_x86_avx());
cpuinfo_log_debug("%-20s: %d", "avx2", cpuinfo_has_x86_avx2());
cpuinfo_log_debug("%-20s: %d", "avx512bf16", cpuinfo_has_x86_avx512bf16());
cpuinfo_log_debug("%-20s: %d", "avx512bitalg", cpuinfo_has_x86_avx512bitalg());
cpuinfo_log_debug("%-20s: %d", "avx512bw", cpuinfo_has_x86_avx512bw());
cpuinfo_log_debug("%-20s: %d", "avx512cd", cpuinfo_has_x86_avx512cd());
cpuinfo_log_debug("%-20s: %d", "avx512dq", cpuinfo_has_x86_avx512dq());
cpuinfo_log_debug("%-20s: %d", "avx512er", cpuinfo_has_x86_avx512er());
cpuinfo_log_debug("%-20s: %d", "avx512f", cpuinfo_has_x86_avx512f());
cpuinfo_log_debug("%-20s: %d", "avx512ifma", cpuinfo_has_x86_avx512ifma());
cpuinfo_log_debug("%-20s: %d", "avx512pf", cpuinfo_has_x86_avx512pf());
cpuinfo_log_debug("%-20s: %d", "avx512vbmi", cpuinfo_has_x86_avx512vbmi());
cpuinfo_log_debug("%-20s: %d", "avx512vbmi2", cpuinfo_has_x86_avx512vbmi2());
cpuinfo_log_debug("%-20s: %d", "avx512vl", cpuinfo_has_x86_avx512vl());
cpuinfo_log_debug("%-20s: %d", "avx512vnni", cpuinfo_has_x86_avx512vnni());
cpuinfo_log_debug("%-20s: %d", "avx512vp2intersect", cpuinfo_has_x86_avx512vp2intersect());
cpuinfo_log_debug("%-20s: %d", "avx512vpopcntdq", cpuinfo_has_x86_avx512vpopcntdq());
cpuinfo_log_debug("%-20s: %d", "avx512_4fmaps", cpuinfo_has_x86_avx512_4fmaps());
cpuinfo_log_debug("%-20s: %d", "avx512_4vnniw", cpuinfo_has_x86_avx512_4vnniw());
cpuinfo_log_debug("%-20s: %d", "bmi", cpuinfo_has_x86_bmi());
cpuinfo_log_debug("%-20s: %d", "bmi2", cpuinfo_has_x86_bmi2());
cpuinfo_log_debug("%-20s: %d", "clwb", cpuinfo_has_x86_clwb());
cpuinfo_log_debug("%-20s: %d", "clzero", cpuinfo_has_x86_clzero());
cpuinfo_log_debug("%-20s: %d", "cmpxchg16b", cpuinfo_has_x86_cmpxchg16b());
cpuinfo_log_debug("%-20s: %d", "f16c", cpuinfo_has_x86_f16c());
cpuinfo_log_debug("%-20s: %d", "fma3", cpuinfo_has_x86_fma3());
cpuinfo_log_debug("%-20s: %d", "fma4", cpuinfo_has_x86_fma4());
cpuinfo_log_debug("%-20s: %d", "gfni", cpuinfo_has_x86_gfni());
cpuinfo_log_debug("%-20s: %d", "hle", cpuinfo_has_x86_hle());
cpuinfo_log_debug("%-20s: %d", "lzcnt", cpuinfo_has_x86_lzcnt());
cpuinfo_log_debug("%-20s: %d", "misaligned_sse", cpuinfo_has_x86_misaligned_sse());
cpuinfo_log_debug("%-20s: %d", "movbe", cpuinfo_has_x86_movbe());
cpuinfo_log_debug("%-20s: %d", "mpx", cpuinfo_has_x86_mpx());
cpuinfo_log_debug("%-20s: %d", "mwait", cpuinfo_has_x86_mwait());
cpuinfo_log_debug("%-20s: %d", "mwaitx", cpuinfo_has_x86_mwaitx());
cpuinfo_log_debug("%-20s: %d", "pclmulqdq", cpuinfo_has_x86_pclmulqdq());
cpuinfo_log_debug("%-20s: %d", "popcnt", cpuinfo_has_x86_popcnt());
cpuinfo_log_debug("%-20s: %d", "prefetch", cpuinfo_has_x86_prefetch());
cpuinfo_log_debug("%-20s: %d", "prefetchw", cpuinfo_has_x86_prefetchw());
cpuinfo_log_debug("%-20s: %d", "prefetchwt1", cpuinfo_has_x86_prefetchwt1());
cpuinfo_log_debug("%-20s: %d", "rdpid", cpuinfo_has_x86_rdpid());
cpuinfo_log_debug("%-20s: %d", "rdrand", cpuinfo_has_x86_rdrand());
cpuinfo_log_debug("%-20s: %d", "rdseed", cpuinfo_has_x86_rdseed());
cpuinfo_log_debug("%-20s: %d", "rdtscp", cpuinfo_has_x86_rdtscp());
cpuinfo_log_debug("%-20s: %d", "rtm", cpuinfo_has_x86_rtm());
cpuinfo_log_debug("%-20s: %d", "sha", cpuinfo_has_x86_sha());
cpuinfo_log_debug("%-20s: %d", "sse3", cpuinfo_has_x86_sse3());
cpuinfo_log_debug("%-20s: %d", "sse4a", cpuinfo_has_x86_sse4a());
cpuinfo_log_debug("%-20s: %d", "sse4_1", cpuinfo_has_x86_sse4_1());
cpuinfo_log_debug("%-20s: %d", "sse4_2", cpuinfo_has_x86_sse4_2());
cpuinfo_log_debug("%-20s: %d", "ssse3", cpuinfo_has_x86_ssse3());
cpuinfo_log_debug("%-20s: %d", "tbm", cpuinfo_has_x86_tbm());
cpuinfo_log_debug("%-20s: %d", "three_d_now", cpuinfo_has_x86_3dnow());
cpuinfo_log_debug("%-20s: %d", "three_d_now_plus", cpuinfo_has_x86_3dnow_plus());
cpuinfo_log_debug("%-20s: %d", "vaes", cpuinfo_has_x86_vaes());
cpuinfo_log_debug("%-20s: %d", "vpclmulqdq", cpuinfo_has_x86_vpclmulqdq());
cpuinfo_log_debug("%-20s: %d", "xop", cpuinfo_has_x86_xop());
cpuinfo_log_debug("%-20s: %d", "xsave", cpuinfo_has_x86_xsave());
cpuinfo_log_debug("%-20s: %d", "xtest", cpuinfo_has_x86_xtest());
cpuinfo_log_debug("%-20s: %d", "cmov", cpuinfo_has_x86_cmov());
cpuinfo_log_debug("%-20s: %d", "cmpxchg8b", cpuinfo_has_x86_cmpxchg8b());
cpuinfo_log_debug("%-20s: %d", "daz", cpuinfo_has_x86_daz());
cpuinfo_log_debug("%-20s: %d", "fpu", cpuinfo_has_x86_fpu());
cpuinfo_log_debug("%-20s: %d", "mmx", cpuinfo_has_x86_mmx());
cpuinfo_log_debug("%-20s: %d", "mmx_plus", cpuinfo_has_x86_mmx_plus());
cpuinfo_log_debug("%-20s: %d", "rdtsc", cpuinfo_has_x86_rdtsc());
cpuinfo_log_debug("%-20s: %d", "sse", cpuinfo_has_x86_sse());
cpuinfo_log_debug("%-20s: %d", "sse2", cpuinfo_has_x86_sse2());
cpuinfo_log_debug("%-20s: %d", "three_d_now_geode", cpuinfo_has_x86_3dnow_geode());
cpuinfo_log_debug("%-20s: %d", "lahf_sahf", cpuinfo_has_x86_lahf_sahf());
cpuinfo_log_debug("----------------------------");
}
#endif // __DEBUG__
#endif // __ANDROID__
94 changes: 94 additions & 0 deletions tools/cpuinfo-svc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* Copyright (C) 2024 Intel Corporation
* All rights reserved.
*
* 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.
* 3. Neither the name of the copyright holder nor the names of its contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS
* 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.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

/*
* Description: cpuinfo-service to initialize and dump cpu info collected
* through __cpuid() calls during device boot.
* it will delete cpuid.info file if it exits and create new.
*
* Author: Unnithan, Balakrishnan <[email protected]>
*/


#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <cpuinfo.h>
#include <cpuinfo/common.h>
#include <cpuinfo/log.h>
#include <x86/linux/api.h>

#ifdef __ANDROID__
extern struct cpuinfo_x86_cpuid_info x86_cpuid_info;

CPUINFO_INTERNAL bool write_cpuid_info_file (void) {
cpuinfo_log_debug("writing cpuid.info file");
FILE* fd_info = fopen(CPUID_INFO_FILE, "wb");
if (!fd_info) {
cpuinfo_log_error("failed to open file %s: %s", CPUID_INFO_FILE, strerror(errno));
return false;
}

int ret = fwrite(&x86_cpuid_info, sizeof(struct cpuinfo_x86_cpuid_info), 1, fd_info);
if (!ret) {
cpuinfo_log_error("failed to write cpuid info in %s: %s", CPUID_INFO_FILE, strerror(errno));
}

if (fclose(fd_info)) {
cpuinfo_log_error("failed to close file %s: %s", CPUID_INFO_FILE, strerror(errno));
return false;
}

return ret ? true : false;
}
#endif // __ANDROID__

int main (void) {
cpuinfo_log_info("start service");
#ifdef __ANDROID__
if (remove(CPUID_INFO_FILE)) {
cpuinfo_log_warning("failed to delete file %s: %s", CPUID_INFO_FILE, strerror(errno));
}

if (!cpuinfo_initialize()) {
cpuinfo_log_error("failed to init cpuinfo lib. exit");
return 1;
}

if (!write_cpuid_info_file()) {
cpuinfo_log_error("failed to save cpuid info. exit");
return 1;
}
#endif // __ANDROID__
cpuinfo_log_info("exit service");
return 0;
}
Loading