Linux-libre 4.14.145-gnu
[librecmc/linux-libre.git] / tools / testing / selftests / powerpc / cache_shape / cache_shape.c
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 }