From 38eb8ac91317f777c32cb23ae916a59721cefe3b Mon Sep 17 00:00:00 2001 From: Balakrishnan Unnithan Date: Fri, 27 Jun 2025 19:46:02 +0530 Subject: [PATCH] cache cpu info in a file at boot Instrumented cpuinfo to read the populated cpu info data from cpuid.info file during initialization. Consumers of the library or OEMs can trigger a oneshot service - cpuinfo-svc - during device boot to link libcpuinfo and dump all cpu info related to processor, model, arch and isa capabilities into cpuid.info file. This arrangement will limit cpuid() intrinsic calls (which causes VM-Exit events and performance overhead) to only once during the init of libcpuinfo at boot by cpuinfo-svc. CPUID being a privileged instn costs considerable number of CPU cycles. Test: Test stub to invoke libcpuinfo before and after start of cpuinfo-svc while recording the TSC counter. Result: 4B CPU cycles are saved in initializing cpuinfo library with the changes. Signed-off-by: Balakrishnan Unnithan --- Android.bp | 134 ++++++++++++++++++++++++++++++++++++++++ include/cpuinfo.h | 112 +++++++++++++++++++++++++++++++++ src/cpuinfo/log.h | 5 ++ src/x86/api.h | 74 ---------------------- src/x86/init.c | 43 ++++++++++++- src/x86/isa.c | 18 ++++++ src/x86/linux/api.h | 9 +++ src/x86/linux/cpuinfo.c | 106 +++++++++++++++++++++++++++++++ tools/Android.bp | 42 +++++++++++++ tools/cpuinfo-svc.c | 98 +++++++++++++++++++++++++++++ 10 files changed, 566 insertions(+), 75 deletions(-) create mode 100644 Android.bp create mode 100644 tools/Android.bp create mode 100644 tools/cpuinfo-svc.c diff --git a/Android.bp b/Android.bp new file mode 100644 index 00000000..8465b945 --- /dev/null +++ b/Android.bp @@ -0,0 +1,134 @@ +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["external_cpuinfo_license"], +} + +// Added automatically by a large-scale-change +// See: http://go/android-license-faq +license { + name: "external_cpuinfo_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-BSD", + ], + license_text: [ + "LICENSE", + ], +} + +cpuinfo_arm_common_src_files = [ + "src/arm/uarch.c", + "src/arm/cache.c", + "src/arm/linux/init.c", + "src/arm/linux/cpuinfo.c", + "src/arm/linux/clusters.c", + "src/arm/linux/chipset.c", + "src/arm/linux/midr.c", + "src/arm/linux/hwcap.c", + "src/arm/android/properties.c", +] + +cpuinfo_x86_common_src_files = [ + "src/x86/init.c", + "src/x86/info.c", + "src/x86/name.c", + "src/x86/isa.c", + "src/x86/vendor.c", + "src/x86/uarch.c", + "src/x86/topology.c", + "src/x86/cache/init.c", + "src/x86/cache/descriptor.c", + "src/x86/cache/deterministic.c", + "src/x86/linux/cpuinfo.c", + "src/x86/linux/init.c", +] + +cc_library { + name: "libcpuinfo", + export_include_dirs: ["include"], + host_supported: true, + vendor_available: true, + product_available: true, + min_sdk_version: "29", + sdk_version: "current", + local_include_dirs: [ + "src", + "include", + ], + srcs: [ + "src/init.c", + "src/api.c", + "src/cache.c", + "src/log.c", + "src/linux/processors.c", + "src/linux/smallfile.c", + "src/linux/multiline.c", + "src/linux/cpulist.c", + ], + arch: { + arm: { + srcs: cpuinfo_arm_common_src_files + [ + "src/arm/linux/aarch32-isa.c", + ], + }, + arm64: { + srcs: cpuinfo_arm_common_src_files + [ + "src/arm/linux/aarch64-isa.c", + ], + }, + riscv64: { + srcs: [ + "src/riscv/linux/init.c", + "src/riscv/linux/riscv-hw.c", + "src/riscv/linux/riscv-isa.c", + "src/riscv/uarch.c", + ], + }, + x86: { + srcs: cpuinfo_x86_common_src_files, + }, + x86_64: { + srcs: cpuinfo_x86_common_src_files, + }, + }, + cflags: [ + "-std=c99", + "-Oz", + "-D_GNU_SOURCE=1", + "-DCPUINFO_LOG_LEVEL=2", + "-Wno-unused-function", + "-Wno-unused-parameter", + "-Wno-missing-field-initializers", + // __riscv_hwprobe() changed from unsigned long* to cpu_set_t*, + // but upstream hasn't updated yet. + "-Wno-incompatible-pointer-types", + ], + product_variables: { + debuggable: { + cflags: [ + "-DDEBUG_CPUINFO", + ], + }, + }, + shared_libs: [ + "liblog", + "libclog", + ], + apex_available: [ + "//apex_available:platform", + "//apex_available:anyapex", + ], +} diff --git a/include/cpuinfo.h b/include/cpuinfo.h index 891416ab..7dae54e7 100644 --- a/include/cpuinfo.h +++ b/include/cpuinfo.h @@ -890,10 +890,122 @@ struct cpuinfo_x86_isa { bool phe; bool pmm; bool lwp; + bool erms; + bool smap; + bool serialize; }; extern struct cpuinfo_x86_isa cpuinfo_isa; + +struct cpuid_regs { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; +}; + +struct cpuinfo_x86_cache { + uint32_t size; + uint32_t associativity; + uint32_t sets; + uint32_t partitions; + uint32_t line_size; + uint32_t flags; + uint32_t apic_bits; +}; + +struct cpuinfo_x86_caches { + struct cpuinfo_trace_cache trace; + struct cpuinfo_x86_cache l1i; + struct cpuinfo_x86_cache l1d; + struct cpuinfo_x86_cache l2; + struct cpuinfo_x86_cache l3; + struct cpuinfo_x86_cache l4; + uint32_t prefetch_size; +}; + +struct cpuinfo_x86_tlbs { + struct cpuinfo_tlb itlb_4KB; + struct cpuinfo_tlb itlb_2MB; + struct cpuinfo_tlb itlb_4MB; + struct cpuinfo_tlb dtlb0_4KB; + struct cpuinfo_tlb dtlb0_2MB; + struct cpuinfo_tlb dtlb0_4MB; + struct cpuinfo_tlb dtlb_4KB; + struct cpuinfo_tlb dtlb_2MB; + struct cpuinfo_tlb dtlb_4MB; + struct cpuinfo_tlb dtlb_1GB; + struct cpuinfo_tlb stlb2_4KB; + struct cpuinfo_tlb stlb2_2MB; + struct cpuinfo_tlb stlb2_1GB; +}; + +struct cpuinfo_x86_model_info { + uint32_t model; + uint32_t family; + uint32_t base_model; + uint32_t base_family; + uint32_t stepping; + uint32_t extended_model; + uint32_t extended_family; + uint32_t processor_type; +}; + +struct cpuinfo_x86_topology { + uint32_t apic_id; + uint32_t thread_bits_offset; + uint32_t thread_bits_length; + uint32_t core_bits_offset; + uint32_t core_bits_length; +}; + +struct cpuinfo_x86_processor { + uint32_t cpuid; + enum cpuinfo_vendor vendor; + enum cpuinfo_uarch uarch; +#ifdef __linux__ + int linux_id; +#endif + struct cpuinfo_x86_caches cache; + struct cpuinfo_x86_tlbs tlb; + struct cpuinfo_x86_topology topology; + char brand_string[CPUINFO_PACKAGE_NAME_MAX]; +}; + +#ifdef __ANDROID__ +static const char CPUID_INFO_FILE[] = "/data/vendor/cpuinfo/cpuid.info"; + +struct cpuinfo_x86_cpuid_info { + struct cpuinfo_x86_isa isa; + struct cpuinfo_x86_model_info model; + struct cpuinfo_x86_processor processor; +}; +#endif //__ANDROID__ +#endif //CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64 + +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 diff --git a/src/cpuinfo/log.h b/src/cpuinfo/log.h index 52e3475f..53888eee 100644 --- a/src/cpuinfo/log.h +++ b/src/cpuinfo/log.h @@ -15,6 +15,11 @@ #define CPUINFO_LOG_INFO 4 #define CPUINFO_LOG_DEBUG 5 +#ifdef DEBUG_CPUINFO +#undef CPUINFO_LOG_LEVEL +#define CPUINFO_LOG_LEVEL CPUINFO_LOG_DEBUG +#endif + #ifndef CPUINFO_LOG_DEBUG_PARSERS #define CPUINFO_LOG_DEBUG_PARSERS 0 #endif diff --git a/src/x86/api.h b/src/x86/api.h index 1331ed04..b76c572f 100644 --- a/src/x86/api.h +++ b/src/x86/api.h @@ -6,80 +6,6 @@ #include #include -struct cpuid_regs { - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; -}; - -struct cpuinfo_x86_cache { - uint32_t size; - uint32_t associativity; - uint32_t sets; - uint32_t partitions; - uint32_t line_size; - uint32_t flags; - uint32_t apic_bits; -}; - -struct cpuinfo_x86_caches { - struct cpuinfo_trace_cache trace; - struct cpuinfo_x86_cache l1i; - struct cpuinfo_x86_cache l1d; - struct cpuinfo_x86_cache l2; - struct cpuinfo_x86_cache l3; - struct cpuinfo_x86_cache l4; - uint32_t prefetch_size; -}; - -struct cpuinfo_x86_model_info { - uint32_t model; - uint32_t family; - - uint32_t base_model; - uint32_t base_family; - uint32_t stepping; - uint32_t extended_model; - uint32_t extended_family; - uint32_t processor_type; -}; - -struct cpuinfo_x86_topology { - uint32_t apic_id; - uint32_t thread_bits_offset; - uint32_t thread_bits_length; - uint32_t core_bits_offset; - uint32_t core_bits_length; -}; - -struct cpuinfo_x86_processor { - uint32_t cpuid; - enum cpuinfo_vendor vendor; - enum cpuinfo_uarch uarch; -#ifdef __linux__ - int linux_id; -#endif - struct cpuinfo_x86_caches cache; - struct { - struct cpuinfo_tlb itlb_4KB; - struct cpuinfo_tlb itlb_2MB; - struct cpuinfo_tlb itlb_4MB; - struct cpuinfo_tlb dtlb0_4KB; - struct cpuinfo_tlb dtlb0_2MB; - struct cpuinfo_tlb dtlb0_4MB; - struct cpuinfo_tlb dtlb_4KB; - struct cpuinfo_tlb dtlb_2MB; - struct cpuinfo_tlb dtlb_4MB; - struct cpuinfo_tlb dtlb_1GB; - struct cpuinfo_tlb stlb2_4KB; - struct cpuinfo_tlb stlb2_2MB; - struct cpuinfo_tlb stlb2_1GB; - } tlb; - struct cpuinfo_x86_topology topology; - char brand_string[CPUINFO_PACKAGE_NAME_MAX]; -}; - CPUINFO_INTERNAL void cpuinfo_x86_init_processor(struct cpuinfo_x86_processor* processor); CPUINFO_INTERNAL enum cpuinfo_vendor cpuinfo_x86_decode_vendor(uint32_t ebx, uint32_t ecx, uint32_t edx); diff --git a/src/x86/init.c b/src/x86/init.c index adc5d361..12283fb1 100644 --- a/src/x86/init.c +++ b/src/x86/init.c @@ -7,11 +7,41 @@ #include #include #include +#include -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. + * CPUID being a privileged instn costs considerable number of CPU cycles. + */ + +#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_CPUINFO + debug_print_cpuid_info_file(); + #endif //DEBUG_CPUINFO + 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 = @@ -66,6 +96,10 @@ 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]; @@ -75,4 +109,11 @@ 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.processor = *processor; + x86_cpuid_info.isa = cpuinfo_isa; + #ifdef DEBUG_CPUINFO + debug_print_cpuid_info_file(); + #endif //DEBUG_CPUINFO + #endif //__ANDROID__ } diff --git a/src/x86/isa.c b/src/x86/isa.c index 222bd231..eb54a052 100644 --- a/src/x86/isa.c +++ b/src/x86/isa.c @@ -828,5 +828,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; } diff --git a/src/x86/linux/api.h b/src/x86/linux/api.h index 26fc5de0..9c868a1c 100644 --- a/src/x86/linux/api.h +++ b/src/x86/linux/api.h @@ -17,3 +17,12 @@ 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__ +CPUINFO_INTERNAL bool cpuinfo_x86_linux_parse_cpuid_info( + struct cpuinfo_x86_cpuid_info* x86_cpuid_info); + +#ifdef DEBUG_CPUINFO +CPUINFO_INTERNAL void debug_print_cpuid_info_file(void); +#endif //DEBUG_CPUINFO +#endif //__ANDROID__ diff --git a/src/x86/linux/cpuinfo.c b/src/x86/linux/cpuinfo.c index f09d1c9f..a55b8e36 100644 --- a/src/x86/linux/cpuinfo.c +++ b/src/x86/linux/cpuinfo.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -213,3 +214,108 @@ bool cpuinfo_x86_linux_parse_proc_cpuinfo( }; return cpuinfo_linux_parse_multiline_file("/proc/cpuinfo", BUFFER_SIZE, 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_CPUINFO +void debug_print_cpuid_info_file (void) { + cpuinfo_log_debug("cpuinfo: ----------------------------"); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "erms", cpuinfo_has_x86_erms()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "smap", cpuinfo_has_x86_smap()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "serialize", cpuinfo_has_x86_serialize()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "adx", cpuinfo_has_x86_adx()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "aes", cpuinfo_has_x86_aes()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx", cpuinfo_has_x86_avx()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx2", cpuinfo_has_x86_avx2()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512bf16", cpuinfo_has_x86_avx512bf16()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512bitalg", cpuinfo_has_x86_avx512bitalg()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512bw", cpuinfo_has_x86_avx512bw()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512cd", cpuinfo_has_x86_avx512cd()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512dq", cpuinfo_has_x86_avx512dq()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512er", cpuinfo_has_x86_avx512er()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512f", cpuinfo_has_x86_avx512f()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512ifma", cpuinfo_has_x86_avx512ifma()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512pf", cpuinfo_has_x86_avx512pf()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512vbmi", cpuinfo_has_x86_avx512vbmi()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512vbmi2", cpuinfo_has_x86_avx512vbmi2()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512vl", cpuinfo_has_x86_avx512vl()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512vnni", cpuinfo_has_x86_avx512vnni()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512vp2intersect", cpuinfo_has_x86_avx512vp2intersect()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512vpopcntdq", cpuinfo_has_x86_avx512vpopcntdq()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512_4fmaps", cpuinfo_has_x86_avx512_4fmaps()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "avx512_4vnniw", cpuinfo_has_x86_avx512_4vnniw()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "bmi", cpuinfo_has_x86_bmi()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "bmi2", cpuinfo_has_x86_bmi2()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "clwb", cpuinfo_has_x86_clwb()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "clzero", cpuinfo_has_x86_clzero()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "cmpxchg16b", cpuinfo_has_x86_cmpxchg16b()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "f16c", cpuinfo_has_x86_f16c()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "fma3", cpuinfo_has_x86_fma3()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "fma4", cpuinfo_has_x86_fma4()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "gfni", cpuinfo_has_x86_gfni()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "hle", cpuinfo_has_x86_hle()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "lzcnt", cpuinfo_has_x86_lzcnt()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "misaligned_sse", cpuinfo_has_x86_misaligned_sse()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "movbe", cpuinfo_has_x86_movbe()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "mpx", cpuinfo_has_x86_mpx()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "mwait", cpuinfo_has_x86_mwait()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "mwaitx", cpuinfo_has_x86_mwaitx()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "pclmulqdq", cpuinfo_has_x86_pclmulqdq()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "popcnt", cpuinfo_has_x86_popcnt()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "prefetch", cpuinfo_has_x86_prefetch()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "prefetchw", cpuinfo_has_x86_prefetchw()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "prefetchwt1", cpuinfo_has_x86_prefetchwt1()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "rdpid", cpuinfo_has_x86_rdpid()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "rdrand", cpuinfo_has_x86_rdrand()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "rdseed", cpuinfo_has_x86_rdseed()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "rdtscp", cpuinfo_has_x86_rdtscp()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "rtm", cpuinfo_has_x86_rtm()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "sha", cpuinfo_has_x86_sha()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "sse3", cpuinfo_has_x86_sse3()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "sse4a", cpuinfo_has_x86_sse4a()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "sse4_1", cpuinfo_has_x86_sse4_1()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "sse4_2", cpuinfo_has_x86_sse4_2()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "ssse3", cpuinfo_has_x86_ssse3()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "tbm", cpuinfo_has_x86_tbm()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "three_d_now", cpuinfo_has_x86_3dnow()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "three_d_now_plus", cpuinfo_has_x86_3dnow_plus()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "vaes", cpuinfo_has_x86_vaes()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "vpclmulqdq", cpuinfo_has_x86_vpclmulqdq()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "xop", cpuinfo_has_x86_xop()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "xsave", cpuinfo_has_x86_xsave()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "xtest", cpuinfo_has_x86_xtest()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "cmov", cpuinfo_has_x86_cmov()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "cmpxchg8b", cpuinfo_has_x86_cmpxchg8b()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "daz", cpuinfo_has_x86_daz()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "fpu", cpuinfo_has_x86_fpu()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "mmx", cpuinfo_has_x86_mmx()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "mmx_plus", cpuinfo_has_x86_mmx_plus()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "rdtsc", cpuinfo_has_x86_rdtsc()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "sse", cpuinfo_has_x86_sse()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "sse2", cpuinfo_has_x86_sse2()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "three_d_now_geode", cpuinfo_has_x86_3dnow_geode()); + cpuinfo_log_debug("cpuinfo: %-20s: %d", "lahf_sahf", cpuinfo_has_x86_lahf_sahf()); + cpuinfo_log_debug("cpuinfo: ----------------------------"); +} +#endif //DEBUG_CPUINFO +#endif //__ANDROID__ diff --git a/tools/Android.bp b/tools/Android.bp new file mode 100644 index 00000000..055d6ccc --- /dev/null +++ b/tools/Android.bp @@ -0,0 +1,42 @@ +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +cc_binary { + name: "cpuinfo-svc", + vendor: true, + host_supported: true, + min_sdk_version: "29", + sdk_version: "current", + + include_dirs: [ + "external/cpuinfo/include", + ], + srcs: [ + "cpuinfo-svc.c", + ], + cflags: [ + "-std=c99", + "-Oz", + "-D_GNU_SOURCE=1", + "-Wno-unused-function", + "-Wno-unused-parameter", + "-Wno-missing-field-initializers", + ], + whole_static_libs: [ + "libcpuinfo", + ], + shared_libs: [ + "liblog", + ], +} diff --git a/tools/cpuinfo-svc.c b/tools/cpuinfo-svc.c new file mode 100644 index 00000000..bf814568 --- /dev/null +++ b/tools/cpuinfo-svc.c @@ -0,0 +1,98 @@ +/* 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 exists and create new. + * + * Author: Unnithan, Balakrishnan + */ + + +#include +#include +#include +#include + +#include + +#ifdef __ANDROID__ +#include + +extern struct cpuinfo_x86_cpuid_info x86_cpuid_info; + +static bool write_cpuid_info_file (void) { + ALOGI("writing cpuid.info file"); + FILE* fd_info = fopen(CPUID_INFO_FILE, "wb"); + if (!fd_info) { + ALOGE("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) { + ALOGE("failed to write file %s: %s", + CPUID_INFO_FILE, strerror(errno)); + } + + if (fclose(fd_info)) { + ALOGE("failed to close file %s: %s", + CPUID_INFO_FILE, strerror(errno)); + return false; + } + + return ret ? true : false; +} +#endif //__ANDROID_ + +int main (void) { +#ifdef __ANDROID__ + ALOGI("start service"); + if (remove(CPUID_INFO_FILE)) { + ALOGW("failed to delete file %s: %s", + CPUID_INFO_FILE, strerror(errno)); + } + + if (!cpuinfo_initialize()) { + ALOGE("failed to init cpuinfo lib. exit"); + return 1; + } + + if (!write_cpuid_info_file()) { + ALOGE("failed to save cpuid info. exit"); + return 1; + } + ALOGI("exit service"); +#endif //__ANDROID_ + return 0; +} \ No newline at end of file