1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright 2017, Michael Ellerman, IBM Corp. 4 */ 5 6 #include <elf.h> 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <link.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <sys/stat.h> 14 #include <sys/types.h> 15 #include <sys/wait.h> 16 #include <unistd.h> 17 18 #include "utils.h" 19 20 #ifndef AT_L1I_CACHESIZE 21 #define AT_L1I_CACHESIZE 40 22 #define AT_L1I_CACHEGEOMETRY 41 23 #define AT_L1D_CACHESIZE 42 24 #define AT_L1D_CACHEGEOMETRY 43 25 #define AT_L2_CACHESIZE 44 26 #define AT_L2_CACHEGEOMETRY 45 27 #define AT_L3_CACHESIZE 46 28 #define AT_L3_CACHEGEOMETRY 47 29 #endif 30 31 static void print_size(const char *label, uint32_t val) 32 { 33 printf("%s cache size: %#10x %10dB %10dK\n", label, val, val, val / 1024); 34 } 35 36 static void print_geo(const char *label, uint32_t val) 37 { 38 uint16_t assoc; 39 40 printf("%s line size: %#10x ", label, val & 0xFFFF); 41 42 assoc = val >> 16; 43 if (assoc) 44 printf("%u-way", assoc); 45 else 46 printf("fully"); 47 48 printf(" associative\n"); 49 } 50 51 static int test_cache_shape() 52 { 53 static char buffer[4096]; 54 ElfW(auxv_t) *p; 55 int found; 56 57 FAIL_IF(read_auxv(buffer, sizeof(buffer))); 58 59 found = 0; 60 61 p = find_auxv_entry(AT_L1I_CACHESIZE, buffer); 62 if (p) { 63 found++; 64 print_size("L1I ", (uint32_t)p->a_un.a_val); 65 } 66 67 p = find_auxv_entry(AT_L1I_CACHEGEOMETRY, buffer); 68 if (p) { 69 found++; 70 print_geo("L1I ", (uint32_t)p->a_un.a_val); 71 } 72 73 p = find_auxv_entry(AT_L1D_CACHESIZE, buffer); 74 if (p) { 75 found++; 76 print_size("L1D ", (uint32_t)p->a_un.a_val); 77 } 78 79 p = find_auxv_entry(AT_L1D_CACHEGEOMETRY, buffer); 80 if (p) { 81 found++; 82 print_geo("L1D ", (uint32_t)p->a_un.a_val); 83 } 84 85 p = find_auxv_entry(AT_L2_CACHESIZE, buffer); 86 if (p) { 87 found++; 88 print_size("L2 ", (uint32_t)p->a_un.a_val); 89 } 90 91 p = find_auxv_entry(AT_L2_CACHEGEOMETRY, buffer); 92 if (p) { 93 found++; 94 print_geo("L2 ", (uint32_t)p->a_un.a_val); 95 } 96 97 p = find_auxv_entry(AT_L3_CACHESIZE, buffer); 98 if (p) { 99 found++; 100 print_size("L3 ", (uint32_t)p->a_un.a_val); 101 } 102 103 p = find_auxv_entry(AT_L3_CACHEGEOMETRY, buffer); 104 if (p) { 105 found++; 106 print_geo("L3 ", (uint32_t)p->a_un.a_val); 107 } 108 109 /* If we found none we're probably on a system where they don't exist */ 110 SKIP_IF(found == 0); 111 112 /* But if we found any, we expect to find them all */ 113 FAIL_IF(found != 8); 114 115 return 0; 116 } 117 118 int main(void) 119 { 120 return test_harness(test_cache_shape, "cache_shape"); 121 } 122