diff options
Diffstat (limited to 'roms/skiboot/hw/test')
-rw-r--r-- | roms/skiboot/hw/test/Makefile.check | 29 | ||||
-rw-r--r-- | roms/skiboot/hw/test/phys-map-test.c | 203 | ||||
-rw-r--r-- | roms/skiboot/hw/test/run-port80h.c | 99 |
3 files changed, 331 insertions, 0 deletions
diff --git a/roms/skiboot/hw/test/Makefile.check b/roms/skiboot/hw/test/Makefile.check new file mode 100644 index 000000000..45eb8072f --- /dev/null +++ b/roms/skiboot/hw/test/Makefile.check @@ -0,0 +1,29 @@ +# -*-Makefile-*- +SUBDIRS += hw/test/ +HW_TEST := hw/test/phys-map-test hw/test/run-port80h + +.PHONY : hw-check +hw-check: $(HW_TEST:%=%-check) + +.PHONY : hw-coverage +hw-coverage: $(HW_TEST:%=%-gcov-run) + +check: hw-check +coverage: hw-coverage + +$(HW_TEST:%=%-gcov-run) : %-run: % + $(call QTEST, TEST-COVERAGE ,$< , $<) + +$(HW_TEST:%=%-check) : %-check: % + $(call QTEST, RUN-TEST ,$(VALGRIND) $<, $<) + +$(HW_TEST) : % : %.c hw/phys-map.o + $(call Q, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) -O0 -g -I include -I . -o $@ $<, $<) + +$(HW_TEST:%=%-gcov): %-gcov : %.c % + $(call QTEST, HOSTCC ,$(HOSTCC) $(HOSTCFLAGS) $(HOSTGCOVCFLAGS) -I include -I . -lgcov -o $@ $<, $<) + +clean: hw-clean + +hw-clean: + $(RM) -f hw/test/*.[od] $(HW_TEST) $(HW_TEST:%=%-gcov) 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); +} diff --git a/roms/skiboot/hw/test/run-port80h.c b/roms/skiboot/hw/test/run-port80h.c new file mode 100644 index 000000000..860a4244d --- /dev/null +++ b/roms/skiboot/hw/test/run-port80h.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Test result of our LPC port 80h boot progress code + * + * Copyright 2018-2019 IBM Corp. + */ + +#include <stdio.h> +#include <stdarg.h> +#include <stdint.h> +#include <assert.h> + +#define __unused __attribute__((unused)) + +#define __LPC_H + +uint8_t port80; +uint16_t port8x; + +static int64_t lpc_probe_write(int addr_type __unused, uint32_t addr, + uint32_t data, uint32_t sz) +{ + assert((addr - 0x80) <= 2); + assert(sz == 1); + if (addr == 0x80) + port80 = data; + if (addr == 0x81) + port8x = data << 8 | (port8x & 0xff); + if (addr == 0x82) + port8x = (port8x & 0xff00) | data; + return 0; +} + +#include "op-panel.h" + +void op_display_lpc(enum op_severity s, enum op_module m, uint16_t c); + +#include "../lpc-port80h.c" +#include "../../core/test/stubs.c" + +enum proc_chip_quirks proc_chip_quirks; + +int main(void) +{ + op_display_lpc(OP_LOG, OP_MOD_INIT, 0x00); + assert(port80 == 0x80); + assert(port8x == 0x8000); + op_display_lpc(OP_WARN, OP_MOD_INIT, 0x00); + assert(port80 == 0x82); + assert(port8x == 0x8002); + op_display_lpc(OP_ERROR, OP_MOD_INIT, 0x00); + assert(port80 == 0x81); + assert(port8x == 0x8001); + op_display_lpc(OP_FATAL, OP_MOD_INIT, 0x00); + assert(port80 == 0x83); + assert(port8x == 0x8003); + op_display_lpc(OP_FATAL, OP_MOD_INIT, 0x0f); + assert(port80 == 0xBF); + assert(port8x == 0x803F); + op_display_lpc(OP_LOG, OP_MOD_INIT, 0x0f); + assert(port80 == 0xBC); + assert(port8x == 0x803C); + op_display_lpc(OP_FATAL, OP_MOD_CORE, 0x6666); + assert(port80 == 0xBF); + assert(port8x == 0x803F); + op_display_lpc(OP_LOG, OP_MOD_INIT, 0x01); + assert(port80 == 0x84); + assert(port8x == 0x8004); + op_display_lpc(OP_LOG, OP_MOD_CPU, 0x05); + assert(port80 == 0xC4); + assert(port8x == 0xC014); + op_display_lpc(OP_LOG, OP_MOD_LOCK, 0x07); + assert(port80 == 0xDC); + assert(port8x == 0xD01C); + op_display_lpc(OP_FATAL, OP_MOD_LOCK, 0x07); + assert(port80 == 0xDF); + assert(port8x == 0xD01F); + op_display_lpc(OP_FATAL, OP_MOD_MEM, 0x07); + assert(port80 == 0xEF); + assert(port8x == 0xE01F); + op_display_lpc(OP_WARN, OP_MOD_MEM, 0x02); + assert(port80 == 0xEA); + assert(port8x == 0xE00A); + op_display_lpc(OP_WARN, OP_MOD_CHIPTOD, 0x02); + assert(port80 == 0xFA); + assert(port8x == 0xF00A); + + /* + * We can't assert that OP_MOD_FSP is invalid as we'd end up + * trying to set port80 in the assert parth + */ + op_display_lpc(OP_LOG, OP_MOD_FSP, 0x00); + assert(port80 == 0x80); + assert(port8x == 0x8000); + op_display_lpc(OP_LOG, OP_MOD_FSPCON, 0x00); + assert(port80 == 0x80); + assert(port8x == 0x8000); + return 0; +} |