Home | History | Annotate | Download | only in cache_shape
      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