Loading...
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 | /* * Copyright 2016, Jack Miller, IBM Corp. * Licensed under GPLv2. */ #include <stdlib.h> #include <stdio.h> #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; } |