blob: 2aabdb826f23a5291b27e6e08336efb10c6de98e [file] [log] [blame]
// 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
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, 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 */
};
int main(void)
{
/* Fake we are POWER9 */
proc_gen = proc_gen_p9;
for (int i = 0; i < ARRAY_SIZE(fake_pvr); i++) {
phys_map_init(fake_pvr[i]);
/* Run tests */
check_table_directly();
check_map_call();
}
return(0);
}