diff options
Diffstat (limited to 'roms/skiboot/hw/test/phys-map-test.c')
-rw-r--r-- | roms/skiboot/hw/test/phys-map-test.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/roms/skiboot/hw/test/phys-map-test.c b/roms/skiboot/hw/test/phys-map-test.c new file mode 100644 index 000000000..d507175fe --- /dev/null +++ b/roms/skiboot/hw/test/phys-map-test.c @@ -0,0 +1,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); +} |