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