1 /* Copyright 2013-2014 IBM Corp.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 * implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "../../core/test/stubs.c"
18 #include "../phys-map.c"
19
20 enum proc_gen proc_gen;
21
print_entry(const struct phys_map_entry * e)22 static inline void print_entry(const struct phys_map_entry *e)
23 {
24 printf("type:%i index:%i addr:%016lx size:%016lx",
25 e->type, e->index, e->addr, e->size);
26 }
27
28 /* Check table directly for overlaps */
check_table_directly(void)29 static void check_table_directly(void)
30 {
31 const struct phys_map_entry *e, *prev;
32 uint64_t start, end, pstart, pend;
33 bool passed;
34
35 /* Loop over table entries ... */
36 for (e = phys_map->table; !phys_map_entry_null(e); e++) {
37
38 start = e->addr;
39 end = e->addr + e->size;
40 /* ... see if they overlap with previous entries */
41 for (prev = phys_map->table; prev != e; prev++) {
42 passed = true;
43 /* Check for overlaping regions */
44 pstart = prev->addr;
45 pend = prev->addr + prev->size;
46 if ((start > pstart) && (start < pend))
47 passed = false;
48 if ((end > pstart) && (end < pend))
49 passed = false;
50
51 /* Check for duplicate entries */
52 if ((e->type == prev->type) &&
53 (e->index == prev->index))
54 passed = false;
55
56 if (passed)
57 continue;
58
59 printf("Phys map direct test FAILED: Entry overlaps\n");
60 printf("First: ");
61 print_entry(prev);
62 printf("\n");
63 printf("Second: ");
64 print_entry(e);
65 printf("\n");
66 assert(0);
67 }
68 }
69 }
70
71 struct map_call_entry {
72 uint64_t start;
73 uint64_t end;
74 };
75
map_call_entry_null(const struct map_call_entry * t)76 static inline bool map_call_entry_null(const struct map_call_entry *t)
77 {
78 if ((t->start == 0) &&
79 (t->end == 0))
80 return true;
81 return false;
82 }
83
84 /* Check calls to map to see if they overlap.
85 * Creates a new table for each of the entries it gets to check against
86 */
87
88 /* Pick a chip ID, any ID. */
89 #define FAKE_CHIP_ID 8
90
check_map_call(void)91 static void check_map_call(void)
92 {
93 uint64_t start, size, end;
94 const struct phys_map_entry *e;
95 struct map_call_entry *tbl, *t, *tnext;
96 int tbl_size = 0;
97 bool passed;
98
99 for (e = phys_map->table; !phys_map_entry_null(e); e++)
100 tbl_size++;
101
102 tbl_size++; /* allow for null entry at end */
103 tbl_size *= sizeof(struct map_call_entry);
104 tbl = malloc(tbl_size);
105 assert(tbl != NULL);
106 memset(tbl, 0, tbl_size);
107
108 /* Loop over table entries ... */
109 for (e = phys_map->table; !phys_map_entry_null(e); e++) {
110 phys_map_get(FAKE_CHIP_ID, e->type, e->index, &start, &size);
111
112 /* Check for alignment */
113 if ((e->type != SYSTEM_MEM) && (e->type != RESV)) {
114 /* Size is power of 2? */
115 assert(__builtin_popcountl(size) == 1);
116 /* Start is aligned to size? */
117 assert((start % size) == 0);
118 }
119
120 end = start + size;
121 for (t = tbl; !map_call_entry_null(t); t++) {
122 passed = true;
123
124 /* Check for overlaping regions */
125 if ((start > t->start) && (start < t->end))
126 passed = false;
127 if ((end > t->start) && (end < t->end))
128 passed = false;
129
130 if (passed)
131 continue;
132
133 printf("Phys map call test FAILED: Entry overlaps\n");
134 printf("First: addr:%016lx size:%016lx\n",
135 t->start, t->end - t->start);
136 printf("Second: addr:%016lx size:%016lx\n ",
137 start, size);
138 print_entry(e);
139 printf("\n");
140 assert(0);
141 }
142 /* Insert entry at end of table */
143 t->start = start;
144 t->end = end;
145 }
146
147 for (t = tbl; !map_call_entry_null(t + 1); t++) {
148 tnext = t + 1;
149 /* Make sure the table is sorted */
150 if (t->start > tnext->start) {
151 printf("Phys map test FAILED: Entry not sorted\n");
152 printf("First: addr:%016lx size:%016lx\n",
153 t->start, t->end - t->start);
154 printf("Second: addr:%016lx size:%016lx\n",
155 tnext->start, tnext->end - tnext->start);
156 assert(0);
157 }
158
159 /* Look for holes in the table in MMIO region */
160 /* We assume over 1PB is MMIO. */
161 if ((t->end != tnext->start) &&
162 (t->start > 0x0004000000000000)) {
163 printf("Phys map test FAILED: Hole in map\n");
164 printf("First: addr:%016lx size:%016lx\n",
165 t->start, t->end - t->start);
166 printf("Second: addr:%016lx size:%016lx\n",
167 tnext->start, tnext->end - tnext->start);
168 assert(0);
169 }
170 }
171
172 free(tbl);
173 }
174
main(void)175 int main(void)
176 {
177 /* Fake we are POWER9 */
178 proc_gen = proc_gen_p9;
179 phys_map_init();
180
181 /* Run tests */
182 check_table_directly();
183 check_map_call();
184
185 return(0);
186 }
187