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
31static 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
36static 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
51static 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
118int main(void)
119{
120 return test_harness(test_cache_shape, "cache_shape");
121}
122

source code of linux/tools/testing/selftests/powerpc/cache_shape/cache_shape.c