diff --git a/deps/clog/include/clog.h b/deps/clog/include/clog.h index 41437611..3186c552 100644 --- a/deps/clog/include/clog.h +++ b/deps/clog/include/clog.h @@ -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"))) diff --git a/include/cpuinfo.h b/include/cpuinfo.h index 5f93819e..c43d9806 100644 --- a/include/cpuinfo.h +++ b/include/cpuinfo.h @@ -866,11 +866,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; diff --git a/src/x86/api.h b/src/x86/api.h index 1331ed04..3d276347 100644 --- a/src/x86/api.h +++ b/src/x86/api.h @@ -33,6 +33,22 @@ struct cpuinfo_x86_caches { 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; @@ -61,21 +77,7 @@ struct cpuinfo_x86_processor { 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_tlbs tlb; struct cpuinfo_x86_topology topology; char brand_string[CPUINFO_PACKAGE_NAME_MAX]; }; @@ -109,40 +111,15 @@ CPUINFO_INTERNAL void cpuinfo_x86_detect_cache( enum cpuinfo_vendor vendor, const struct cpuinfo_x86_model_info* model_info, struct cpuinfo_x86_caches* cache, - 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, - uint32_t* log2_package_cores_max); + struct cpuinfo_x86_tlbs* tlb, + struct cpuinfo_x86_topology* topology); CPUINFO_INTERNAL void cpuinfo_x86_decode_cache_descriptor( uint8_t descriptor, enum cpuinfo_vendor vendor, const struct cpuinfo_x86_model_info* model_info, struct cpuinfo_x86_caches* cache, - 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, - uint32_t* prefetch_size); + struct cpuinfo_x86_tlbs* tlb); CPUINFO_INTERNAL bool cpuinfo_x86_decode_deterministic_cache_parameters( struct cpuid_regs regs, diff --git a/src/x86/cache/descriptor.c b/src/x86/cache/descriptor.c index 93d855ae..404c0235 100644 --- a/src/x86/cache/descriptor.c +++ b/src/x86/cache/descriptor.c @@ -8,20 +8,8 @@ void cpuinfo_x86_decode_cache_descriptor( enum cpuinfo_vendor vendor, const struct cpuinfo_x86_model_info* model_info, struct cpuinfo_x86_caches* cache, - 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, - uint32_t* prefetch_size) { + struct cpuinfo_x86_tlbs* tlb) +{ /* * Descriptors are parsed according to: * - Application Note 485: Intel Processor Indentification and CPUID @@ -41,7 +29,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 4-KB Pages, 4-way set * associative, 32 entries" */ - *itlb_4KB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = (struct cpuinfo_tlb) { .entries = 32, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -55,7 +43,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 4-MB Pages, fully associative, * 2 entries" */ - *itlb_4MB = (struct cpuinfo_tlb){ + tlb->itlb_4MB = (struct cpuinfo_tlb) { .entries = 2, .associativity = 2, .pages = CPUINFO_PAGE_SIZE_4MB, @@ -68,7 +56,7 @@ void cpuinfo_x86_decode_cache_descriptor( * 64 entries" Application Note 485: "Data TLB: 4-KB * Pages, 4-way set associative, 64 entries" */ - *dtlb_4KB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = (struct cpuinfo_tlb) { .entries = 64, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -81,7 +69,7 @@ void cpuinfo_x86_decode_cache_descriptor( * 8 entries" Application Note 485: "Data TLB: 4-MB * Pages, 4-way set associative, 8 entries" */ - *dtlb_4MB = (struct cpuinfo_tlb){ + tlb->dtlb_4MB = (struct cpuinfo_tlb) { .entries = 8, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4MB, @@ -94,7 +82,7 @@ void cpuinfo_x86_decode_cache_descriptor( * 32 entries" Application Note 485: "Data TLB: 4-MB * Pages, 4-way set associative, 32 entries" */ - *dtlb_4MB = (struct cpuinfo_tlb){ + tlb->dtlb_4MB = (struct cpuinfo_tlb) { .entries = 32, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4MB, @@ -172,7 +160,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 4-MB pages, 4-way set * associative, 4 entries" */ - *itlb_4MB = (struct cpuinfo_tlb){ + tlb->itlb_4MB = (struct cpuinfo_tlb) { .entries = 4, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4MB, @@ -710,7 +698,7 @@ void cpuinfo_x86_decode_cache_descriptor( * Application Note 485: * "Instruction TLB: 4-KB pages, 32 entries" */ - *itlb_4KB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = (struct cpuinfo_tlb) { .entries = 32, /* Assume full associativity from nearby * entries: manual lacks detail @@ -727,7 +715,7 @@ void cpuinfo_x86_decode_cache_descriptor( * TLB: 4-KB, 2-MB or 4-MB pages, fully associative, 64 * entries" */ - *itlb_4KB = *itlb_2MB = *itlb_4MB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = tlb->itlb_2MB = tlb->itlb_4MB = (struct cpuinfo_tlb) { .entries = 64, .associativity = 64, .pages = CPUINFO_PAGE_SIZE_4KB | CPUINFO_PAGE_SIZE_2MB | CPUINFO_PAGE_SIZE_4MB, @@ -741,7 +729,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 4-KB, 2-MB or 4-MB pages, fully * associative, 128 entries" */ - *itlb_4KB = *itlb_2MB = *itlb_4MB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = tlb->itlb_2MB = tlb->itlb_4MB = (struct cpuinfo_tlb) { .entries = 128, .associativity = 128, .pages = CPUINFO_PAGE_SIZE_4KB | CPUINFO_PAGE_SIZE_2MB | CPUINFO_PAGE_SIZE_4MB, @@ -755,7 +743,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 4-KB, 2-MB or 4-MB pages, fully * associative, 256 entries" */ - *itlb_4KB = *itlb_2MB = *itlb_4MB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = tlb->itlb_2MB = tlb->itlb_4MB = (struct cpuinfo_tlb) { .entries = 256, .associativity = 256, .pages = CPUINFO_PAGE_SIZE_4KB | CPUINFO_PAGE_SIZE_2MB | CPUINFO_PAGE_SIZE_4MB, @@ -769,7 +757,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 2-MB or 4-MB pages, fully * associative, 7 entries" */ - *itlb_2MB = *itlb_4MB = (struct cpuinfo_tlb){ + tlb->itlb_2MB = tlb->itlb_4MB = (struct cpuinfo_tlb) { .entries = 7, .associativity = 7, .pages = CPUINFO_PAGE_SIZE_2MB | CPUINFO_PAGE_SIZE_4MB, @@ -782,7 +770,7 @@ void cpuinfo_x86_decode_cache_descriptor( * 16 entries" Application Note 485: "L1 Data TLB: 4-MB * pages, 4-way set associative, 16 entries" */ - *dtlb0_4MB = (struct cpuinfo_tlb){ + tlb->dtlb0_4MB = (struct cpuinfo_tlb) { .entries = 16, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4MB, @@ -795,7 +783,7 @@ void cpuinfo_x86_decode_cache_descriptor( * entries" Application Note 485: "L1 Data TLB: 4-KB * pages, 4-way set associative, 16 entries" */ - *dtlb0_4KB = (struct cpuinfo_tlb){ + tlb->dtlb0_4KB = (struct cpuinfo_tlb) { .entries = 16, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -808,7 +796,7 @@ void cpuinfo_x86_decode_cache_descriptor( * entries" Application Note 485: "Data TLB0: 4-KB * pages, fully associative, 16 entries" */ - *dtlb0_4KB = (struct cpuinfo_tlb){ + tlb->dtlb0_4KB = (struct cpuinfo_tlb) { .entries = 16, .associativity = 16, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -822,7 +810,7 @@ void cpuinfo_x86_decode_cache_descriptor( * TLB0: 2-MB or 4-MB pages, 4-way associative, 32 * entries" */ - *dtlb0_2MB = *dtlb0_4MB = (struct cpuinfo_tlb){ + tlb->dtlb0_2MB = tlb->dtlb0_4MB = (struct cpuinfo_tlb) { .entries = 32, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_2MB | CPUINFO_PAGE_SIZE_4MB, @@ -836,7 +824,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Data TLB: 4-KB or 4-MB pages, fully associative, * 64 entries" */ - *dtlb_4KB = *dtlb_4MB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = tlb->dtlb_4MB = (struct cpuinfo_tlb) { .entries = 64, .associativity = 64, .pages = CPUINFO_PAGE_SIZE_4KB | CPUINFO_PAGE_SIZE_4MB, @@ -849,7 +837,7 @@ void cpuinfo_x86_decode_cache_descriptor( * entries" Application Note 485: "Data TLB: 4-KB or * 4-MB pages, fully associative, 128 entries" */ - *dtlb_4KB = *dtlb_4MB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = tlb->dtlb_4MB = (struct cpuinfo_tlb) { .entries = 128, .associativity = 128, .pages = CPUINFO_PAGE_SIZE_4KB | CPUINFO_PAGE_SIZE_4MB, @@ -862,7 +850,7 @@ void cpuinfo_x86_decode_cache_descriptor( * entries" Application Note 485: "Data TLB: 4-KB or * 4-MB pages, fully associative, 256 entries" */ - *dtlb_4KB = *dtlb_4MB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = tlb->dtlb_4MB = (struct cpuinfo_tlb) { .entries = 256, .associativity = 256, .pages = CPUINFO_PAGE_SIZE_4KB | CPUINFO_PAGE_SIZE_4MB, @@ -888,7 +876,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 4 KByte pages, fully * associative, 48 entries" */ - *itlb_4KB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = (struct cpuinfo_tlb) { .entries = 48, .associativity = 48, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -901,12 +889,12 @@ void cpuinfo_x86_decode_cache_descriptor( * associative, 32 entries and a separate array with 1 * GByte pages, 4-way set associative, 4 entries" */ - *dtlb_2MB = *dtlb_4MB = (struct cpuinfo_tlb){ + tlb->dtlb_2MB = tlb->dtlb_4MB = (struct cpuinfo_tlb) { .entries = 32, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_2MB | CPUINFO_PAGE_SIZE_4MB, }; - *dtlb_1GB = (struct cpuinfo_tlb){ + tlb->dtlb_1GB = (struct cpuinfo_tlb) { .entries = 4, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_1GB, @@ -919,7 +907,7 @@ void cpuinfo_x86_decode_cache_descriptor( * 512 entries" * */ - *dtlb_4KB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = (struct cpuinfo_tlb) { .entries = 512, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -977,7 +965,7 @@ void cpuinfo_x86_decode_cache_descriptor( /* uTLB is, an fact, a normal 1-level DTLB on Silvermont * & Knoghts Landing */ - *dtlb_4KB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = (struct cpuinfo_tlb) { .entries = 64, .associativity = 8, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -989,7 +977,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "DTLB: 4 KByte pages, 8-way set associative, 256 * entries" */ - *dtlb_4KB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = (struct cpuinfo_tlb) { .entries = 256, .associativity = 8, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -1001,7 +989,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "DTLB: 2M/4M pages, 8-way set associative, 128 * entries" */ - *dtlb_2MB = *dtlb_4MB = (struct cpuinfo_tlb){ + tlb->dtlb_2MB = tlb->dtlb_4MB = (struct cpuinfo_tlb) { .entries = 128, .associativity = 8, .pages = CPUINFO_PAGE_SIZE_2MB | CPUINFO_PAGE_SIZE_4MB, @@ -1013,7 +1001,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "DTLB: 1 GByte pages, fully associative, 16 * entries" */ - *dtlb_1GB = (struct cpuinfo_tlb){ + tlb->dtlb_1GB = (struct cpuinfo_tlb) { .entries = 16, .associativity = 16, .pages = CPUINFO_PAGE_SIZE_1GB, @@ -1033,7 +1021,7 @@ void cpuinfo_x86_decode_cache_descriptor( #if CPUINFO_ARCH_X86 case cpuinfo_vendor_cyrix: case cpuinfo_vendor_nsc: - *dtlb_4KB = *itlb_4KB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = tlb->itlb_4KB = (struct cpuinfo_tlb) { .entries = 32, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -1085,7 +1073,7 @@ void cpuinfo_x86_decode_cache_descriptor( * 8 entries" Application Note 485: "Instruction TLB: * 2M/4M pages, fully associative, 8 entries" */ - *itlb_2MB = *itlb_4MB = (struct cpuinfo_tlb){ + tlb->itlb_2MB = tlb->itlb_4MB = (struct cpuinfo_tlb) { .entries = 8, .associativity = 8, .pages = CPUINFO_PAGE_SIZE_2MB | CPUINFO_PAGE_SIZE_4MB, @@ -1352,7 +1340,7 @@ void cpuinfo_x86_decode_cache_descriptor( * Intel ISA Reference: * "DTLB: 4k pages, fully associative, 32 entries" */ - *dtlb_4KB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = (struct cpuinfo_tlb) { .entries = 32, .associativity = 32, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -1366,7 +1354,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 4-KB Pages, 4-way set associative, * 128 entries" */ - *itlb_4KB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = (struct cpuinfo_tlb) { .entries = 128, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -1380,12 +1368,12 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 2-MB pages, 4-way, 8 entries or 4M * pages, 4-way, 4 entries" */ - *itlb_2MB = (struct cpuinfo_tlb){ + tlb->itlb_2MB = (struct cpuinfo_tlb) { .entries = 8, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_2MB | CPUINFO_PAGE_SIZE_4MB, }; - *itlb_4MB = (struct cpuinfo_tlb){ + tlb->itlb_4MB = (struct cpuinfo_tlb) { .entries = 4, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_2MB | CPUINFO_PAGE_SIZE_4MB, @@ -1399,7 +1387,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 4-KB pages, 4-way set * associative, 64 entries" */ - *itlb_4KB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = (struct cpuinfo_tlb) { .entries = 64, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -1412,7 +1400,7 @@ void cpuinfo_x86_decode_cache_descriptor( * 128 entries" Application Note 485: "Data TLB: 4-KB * Pages, 4-way set associative, 128 entries" */ - *dtlb_4KB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = (struct cpuinfo_tlb) { .entries = 128, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -1425,7 +1413,7 @@ void cpuinfo_x86_decode_cache_descriptor( * entries" Application Note 485: "Data TLB: 4-KB Pages, * 4-way set associative, 256 entries" */ - *dtlb_4KB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = (struct cpuinfo_tlb) { .entries = 256, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -1437,7 +1425,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 4KByte pages, 8-way set * associative, 64 entries" */ - *itlb_4KB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = (struct cpuinfo_tlb) { .entries = 64, .associativity = 8, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -1449,7 +1437,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Instruction TLB: 4KByte pages, 8-way set * associative, 128 entries" */ - *itlb_4KB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = (struct cpuinfo_tlb) { .entries = 128, .associativity = 8, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -1462,7 +1450,7 @@ void cpuinfo_x86_decode_cache_descriptor( * entries" Application Note 485: "Data TLB: 4-KB Pages, * 4-way set associative, 64 entries" */ - *itlb_4KB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = (struct cpuinfo_tlb) { .entries = 64, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB, @@ -1476,7 +1464,7 @@ void cpuinfo_x86_decode_cache_descriptor( * TLB: 4-KB or 4-MB Pages, 4-way set associative, 8 * entries" */ - *itlb_4KB = *itlb_4MB = (struct cpuinfo_tlb){ + tlb->itlb_4KB = tlb->itlb_4MB = (struct cpuinfo_tlb) { .entries = 8, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB | CPUINFO_PAGE_SIZE_4MB, @@ -1488,7 +1476,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Shared 2nd-Level TLB: 4 KByte/2MByte pages, * 8-way associative, 1024 entries" */ - *stlb2_4KB = *stlb2_2MB = (struct cpuinfo_tlb){ + tlb->stlb2_4KB = tlb->stlb2_2MB = (struct cpuinfo_tlb) { .entries = 1024, .associativity = 8, .pages = CPUINFO_PAGE_SIZE_4KB | CPUINFO_PAGE_SIZE_2MB, @@ -1500,7 +1488,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "DTLB: 4 KByte/2 MByte pages, 4-way associative, * 16 entries" */ - *dtlb_4KB = *dtlb_2MB = (struct cpuinfo_tlb){ + tlb->dtlb_4KB = tlb->dtlb_2MB = (struct cpuinfo_tlb) { .entries = 16, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB | CPUINFO_PAGE_SIZE_2MB, @@ -1513,12 +1501,12 @@ void cpuinfo_x86_decode_cache_descriptor( * 6-way associative, 1536 entries. Also 1GBbyte pages, * 4-way, 16 entries." */ - *stlb2_4KB = *stlb2_2MB = (struct cpuinfo_tlb){ + tlb->stlb2_4KB = tlb->stlb2_2MB = (struct cpuinfo_tlb) { .entries = 1536, .associativity = 6, .pages = CPUINFO_PAGE_SIZE_4KB | CPUINFO_PAGE_SIZE_2MB, }; - *stlb2_1GB = (struct cpuinfo_tlb){ + tlb->stlb2_1GB = (struct cpuinfo_tlb) { .entries = 16, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_1GB, @@ -1530,7 +1518,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "DTLB: 2M/4M Byte pages, 4-way associative, 32 * entries" */ - *dtlb_2MB = *dtlb_4MB = (struct cpuinfo_tlb){ + tlb->dtlb_2MB = tlb->dtlb_4MB = (struct cpuinfo_tlb) { .entries = 32, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_2MB | CPUINFO_PAGE_SIZE_4MB, @@ -1544,7 +1532,7 @@ void cpuinfo_x86_decode_cache_descriptor( * "Shared 2nd-level TLB: 4 KB pages, 4-way set * associative, 512 entries" */ - *stlb2_4KB = (struct cpuinfo_tlb){ + tlb->stlb2_4KB = (struct cpuinfo_tlb) { .entries = 512, .associativity = 4, .pages = CPUINFO_PAGE_SIZE_4KB, diff --git a/src/x86/cache/init.c b/src/x86/cache/init.c index 34af90e7..04d95491 100644 --- a/src/x86/cache/init.c +++ b/src/x86/cache/init.c @@ -25,20 +25,9 @@ void cpuinfo_x86_detect_cache( enum cpuinfo_vendor vendor, const struct cpuinfo_x86_model_info* model_info, struct cpuinfo_x86_caches* cache, - 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, - uint32_t* log2_package_cores_max) { + struct cpuinfo_x86_tlbs* tlb, + struct cpuinfo_x86_topology* topology) +{ if (max_base_index >= 2) { union cpuinfo_x86_cache_descriptors descriptors; descriptors.regs = cpuid(2); @@ -49,24 +38,7 @@ void cpuinfo_x86_detect_cache( const uint8_t descriptor = descriptors.as_bytes[i]; if (descriptor != 0) { cpuinfo_x86_decode_cache_descriptor( - descriptor, - vendor, - model_info, - cache, - itlb_4KB, - itlb_2MB, - itlb_4MB, - dtlb0_4KB, - dtlb0_2MB, - dtlb0_4MB, - dtlb_4KB, - dtlb_2MB, - dtlb_4MB, - dtlb_1GB, - stlb2_4KB, - stlb2_2MB, - stlb2_1GB, - &cache->prefetch_size); + descriptor, vendor, model_info, cache, tlb); } } if (--iterations != 0) { @@ -83,7 +55,7 @@ void cpuinfo_x86_detect_cache( leaf4 = cpuidex(4, input_ecx++); } while (cpuinfo_x86_decode_deterministic_cache_parameters(leaf4, cache, &package_cores_max)); if (package_cores_max != 0) { - *log2_package_cores_max = bit_length(package_cores_max); + topology->core_bits_length = bit_length(package_cores_max); } } } diff --git a/src/x86/init.c b/src/x86/init.c index adc5d361..eb96e2fc 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. + */ + + +#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 = @@ -41,31 +71,16 @@ void cpuinfo_x86_init_processor(struct cpuinfo_x86_processor* processor) { const bool amd_topology_extensions = !!(leaf0x80000001.ecx & UINT32_C(0x00400000)); cpuinfo_x86_detect_cache( - max_base_index, - max_extended_index, - amd_topology_extensions, - vendor, - &model_info, - &processor->cache, - &processor->tlb.itlb_4KB, - &processor->tlb.itlb_2MB, - &processor->tlb.itlb_4MB, - &processor->tlb.dtlb0_4KB, - &processor->tlb.dtlb0_2MB, - &processor->tlb.dtlb0_4MB, - &processor->tlb.dtlb_4KB, - &processor->tlb.dtlb_2MB, - &processor->tlb.dtlb_4MB, - &processor->tlb.dtlb_1GB, - &processor->tlb.stlb2_4KB, - &processor->tlb.stlb2_2MB, - &processor->tlb.stlb2_1GB, - &processor->topology.core_bits_length); + max_base_index, max_extended_index, amd_topology_extensions, vendor, + &model_info, &processor->cache, &processor->tlb, &processor->topology); cpuinfo_x86_detect_topology(max_base_index, max_extended_index, leaf1, &processor->topology); 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 +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__ } 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..c13b0f4d 100644 --- a/src/x86/linux/api.h +++ b/src/x86/linux/api.h @@ -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__ diff --git a/src/x86/linux/cpuinfo.c b/src/x86/linux/cpuinfo.c index 8f038b07..de11b391 100644 --- a/src/x86/linux/cpuinfo.c +++ b/src/x86/linux/cpuinfo.c @@ -218,3 +218,126 @@ 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__ +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__ diff --git a/tools/cpuinfo-svc.c b/tools/cpuinfo-svc.c new file mode 100644 index 00000000..2148363b --- /dev/null +++ b/tools/cpuinfo-svc.c @@ -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 + */ + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#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; +} \ No newline at end of file