Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /*
3 : : * Physical memory map test
4 : : *
5 : : * Copyright 2013-2017 IBM Corp.
6 : : */
7 : :
8 : : #include "../../core/test/stubs.c"
9 : : #include "../phys-map.c"
10 : :
11 : : enum proc_gen proc_gen;
12 : :
13 : 0 : static inline void print_entry(const struct phys_map_entry *e)
14 : : {
15 : 0 : printf("type:%i index:%i addr:%016lx size:%016lx",
16 : 0 : e->type, e->index, e->addr, e->size);
17 : 0 : }
18 : :
19 : : /* Check table directly for overlaps */
20 : 3 : static void check_table_directly(void)
21 : : {
22 : : const struct phys_map_entry *e, *prev;
23 : : uint64_t start, end, pstart, pend;
24 : : bool passed;
25 : :
26 : : /* Loop over table entries ... */
27 : 283 : for (e = phys_map->table; !phys_map_entry_null(e); e++) {
28 : :
29 : 280 : start = e->addr;
30 : 280 : end = e->addr + e->size;
31 : : /* ... see if they overlap with previous entries */
32 : 13391 : for (prev = phys_map->table; prev != e; prev++) {
33 : 13111 : passed = true;
34 : : /* Check for overlaping regions */
35 : 13111 : pstart = prev->addr;
36 : 13111 : pend = prev->addr + prev->size;
37 : 13111 : if ((start > pstart) && (start < pend))
38 : 0 : passed = false;
39 : 13111 : if ((end > pstart) && (end < pend))
40 : 0 : passed = false;
41 : :
42 : : /* Check for duplicate entries */
43 : 13111 : if ((e->type == prev->type) &&
44 : 941 : (e->index == prev->index))
45 : 0 : passed = false;
46 : :
47 : 13111 : if (passed)
48 : 13111 : continue;
49 : :
50 : 0 : printf("Phys map direct test FAILED: Entry overlaps\n");
51 : 0 : printf("First: ");
52 : 0 : print_entry(prev);
53 : 0 : printf("\n");
54 : 0 : printf("Second: ");
55 : 0 : print_entry(e);
56 : 0 : printf("\n");
57 : 0 : assert(0);
58 : : }
59 : : }
60 : 3 : }
61 : :
62 : : struct map_call_entry {
63 : : uint64_t start;
64 : : uint64_t end;
65 : : };
66 : :
67 : 13671 : static inline bool map_call_entry_null(const struct map_call_entry *t)
68 : : {
69 : 13671 : if ((t->start == 0) &&
70 : 283 : (t->end == 0))
71 : 283 : return true;
72 : 13388 : return false;
73 : : }
74 : :
75 : : /* Check calls to map to see if they overlap.
76 : : * Creates a new table for each of the entries it gets to check against
77 : : */
78 : :
79 : : /* Pick a chip ID, any ID. */
80 : : #define FAKE_CHIP_ID 8
81 : :
82 : 0 : struct proc_chip *get_chip(uint32_t chip_id __unused)
83 : : {
84 : 0 : return NULL;
85 : : }
86 : :
87 : 3 : static void check_map_call(void)
88 : : {
89 : : uint64_t start, size, end;
90 : : const struct phys_map_entry *e;
91 : : struct map_call_entry *tbl, *t, *tnext;
92 : 3 : int tbl_size = 0;
93 : : bool passed;
94 : :
95 : 283 : for (e = phys_map->table; !phys_map_entry_null(e); e++)
96 : 280 : tbl_size++;
97 : :
98 : 3 : tbl_size++; /* allow for null entry at end */
99 : 3 : tbl_size *= sizeof(struct map_call_entry);
100 : 3 : tbl = malloc(tbl_size);
101 : 3 : assert(tbl != NULL);
102 : 3 : memset(tbl, 0, tbl_size);
103 : :
104 : : /* Loop over table entries ... */
105 : 283 : for (e = phys_map->table; !phys_map_entry_null(e); e++) {
106 : 280 : __phys_map_get(FAKE_CHIP_ID, FAKE_CHIP_ID, e->type, e->index, &start, &size);
107 : :
108 : : /* Check for alignment */
109 : 280 : if ((e->type != SYSTEM_MEM) && (e->type != RESV)) {
110 : : /* Size is power of 2? */
111 : 245 : assert(__builtin_popcountl(size) == 1);
112 : : /* Start is aligned to size? */
113 : 245 : assert((start % size) == 0);
114 : : }
115 : :
116 : 280 : end = start + size;
117 : 13391 : for (t = tbl; !map_call_entry_null(t); t++) {
118 : 13111 : passed = true;
119 : :
120 : : /* Check for overlaping regions */
121 : 13111 : if ((start > t->start) && (start < t->end))
122 : 0 : passed = false;
123 : 13111 : if ((end > t->start) && (end < t->end))
124 : 0 : passed = false;
125 : :
126 : 13111 : if (passed)
127 : 13111 : continue;
128 : :
129 : 0 : printf("Phys map call test FAILED: Entry overlaps\n");
130 : 0 : printf("First: addr:%016lx size:%016lx\n",
131 : 0 : t->start, t->end - t->start);
132 : 0 : printf("Second: addr:%016lx size:%016lx\n ",
133 : : start, size);
134 : 0 : print_entry(e);
135 : 0 : printf("\n");
136 : 0 : assert(0);
137 : : }
138 : : /* Insert entry at end of table */
139 : 280 : t->start = start;
140 : 280 : t->end = end;
141 : : }
142 : :
143 : 280 : for (t = tbl; !map_call_entry_null(t + 1); t++) {
144 : 277 : tnext = t + 1;
145 : : /* Make sure the table is sorted */
146 : 277 : if (t->start > tnext->start) {
147 : 0 : printf("Phys map test FAILED: Entry not sorted\n");
148 : 0 : printf("First: addr:%016lx size:%016lx\n",
149 : 0 : t->start, t->end - t->start);
150 : 0 : printf("Second: addr:%016lx size:%016lx\n",
151 : 0 : tnext->start, tnext->end - tnext->start);
152 : 0 : assert(0);
153 : : }
154 : :
155 : : /* Look for holes in the table in MMIO region */
156 : : /* We assume over 1PB is MMIO. */
157 : 277 : if ((t->end != tnext->start) &&
158 : 8 : (t->start > 0x0004000000000000)) {
159 : 0 : printf("Phys map test FAILED: Hole in map\n");
160 : 0 : printf("First: addr:%016lx size:%016lx\n",
161 : 0 : t->start, t->end - t->start);
162 : 0 : printf("Second: addr:%016lx size:%016lx\n",
163 : 0 : tnext->start, tnext->end - tnext->start);
164 : 0 : assert(0);
165 : : }
166 : : }
167 : :
168 : 3 : free(tbl);
169 : 3 : }
170 : :
171 : : /* Fake PVR definitions. See include/processor.h */
172 : : unsigned long fake_pvr[] = {
173 : : 0x004e0200, /* PVR_P9 */
174 : : 0x004f0100, /* PVR_P9P */
175 : : 0x00800100, /* PVR_P10 */
176 : : };
177 : :
178 : 1 : int main(void)
179 : : {
180 : 4 : for (int i = 0; i < ARRAY_SIZE(fake_pvr); i++) {
181 : 3 : switch(PVR_TYPE(fake_pvr[i])) {
182 : 2 : case PVR_TYPE_P9:
183 : : case PVR_TYPE_P9P:
184 : 2 : proc_gen = proc_gen_p9;
185 : 2 : break;
186 : 1 : case PVR_TYPE_P10:
187 : 1 : proc_gen = proc_gen_p10;
188 : 1 : break;
189 : 0 : default:
190 : 0 : printf("Unknown PVR 0x%lx\n", fake_pvr[i]);
191 : 0 : return 1;
192 : : break;
193 : : }
194 : :
195 : 3 : phys_map_init(fake_pvr[i]);
196 : :
197 : : /* Run tests */
198 : 3 : check_table_directly();
199 : 3 : check_map_call();
200 : : }
201 : :
202 : 1 : return(0);
203 : : }
|