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