/* * Copyright 2016, Jack Miller, IBM Corp. * Licensed under GPLv2. */ #include #include #include "ebb.h" #include "ebb_lmr.h" #define SIZE (32 * 1024 * 1024) /* 32M */ #define LM_SIZE 0 /* Smallest encoding, 32M */ #define SECTIONS 64 /* 1 per bit in LMSER */ #define SECTION_SIZE (SIZE / SECTIONS) #define SECTION_LONGS (SECTION_SIZE / sizeof(long)) static unsigned long *test_mem; static int lmr_count = 0; void ebb_lmr_handler(void) { lmr_count++; } void ldmx_full_section(unsigned long *mem, int section) { unsigned long *ptr; int i; for (i = 0; i < SECTION_LONGS; i++) { ptr = &mem[(SECTION_LONGS * section) + i]; ldmx((unsigned long) &ptr); ebb_lmr_reset(); } } unsigned long section_masks[] = { 0x8000000000000000, 0xFF00000000000000, 0x0000000F70000000, 0x8000000000000001, 0xF0F0F0F0F0F0F0F0, 0x0F0F0F0F0F0F0F0F, 0x0 }; int ebb_lmr_section_test(unsigned long *mem) { unsigned long *mask = section_masks; int i; for (; *mask; mask++) { mtspr(SPRN_LMSER, *mask); printf("Testing mask 0x%016lx\n", mfspr(SPRN_LMSER)); for (i = 0; i < 64; i++) { lmr_count = 0; ldmx_full_section(mem, i); if (*mask & (1UL << (63 - i))) FAIL_IF(lmr_count != SECTION_LONGS); else FAIL_IF(lmr_count); } } return 0; } int ebb_lmr(void) { int i; SKIP_IF(!lmr_is_supported()); setup_ebb_handler(ebb_lmr_handler); ebb_global_enable(); FAIL_IF(posix_memalign((void **)&test_mem, SIZE, SIZE) != 0); mtspr(SPRN_LMSER, 0); FAIL_IF(mfspr(SPRN_LMSER) != 0); mtspr(SPRN_LMRR, ((unsigned long)test_mem | LM_SIZE)); FAIL_IF(mfspr(SPRN_LMRR) != ((unsigned long)test_mem | LM_SIZE)); /* Read every single byte to ensure we get no false positives */ for (i = 0; i < SECTIONS; i++) ldmx_full_section(test_mem, i); FAIL_IF(lmr_count != 0); /* Turn on the first section */ mtspr(SPRN_LMSER, (1UL << 63)); FAIL_IF(mfspr(SPRN_LMSER) != (1UL << 63)); /* Enable LM (BESCR) */ mtspr(SPRN_BESCR, mfspr(SPRN_BESCR) | BESCR_LME); FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LME)); ldmx((unsigned long)&test_mem); FAIL_IF(lmr_count != 1); // exactly one exception FAIL_IF(mfspr(SPRN_BESCR) & BESCR_LME); // LM now disabled FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LMEO)); // occurred bit set printf("Simple LMR EBB OK\n"); /* This shouldn't cause an EBB since it's been disabled */ ldmx((unsigned long)&test_mem); FAIL_IF(lmr_count != 1); printf("LMR disable on EBB OK\n"); ebb_lmr_reset(); /* This should cause an EBB or reset is broken */ ldmx((unsigned long)&test_mem); FAIL_IF(lmr_count != 2); printf("LMR reset EBB OK\n"); ebb_lmr_reset(); return ebb_lmr_section_test(test_mem); } int main(void) { int ret = test_harness(ebb_lmr, "ebb_lmr"); if (test_mem) free(test_mem); return ret; }