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