1 /*
2  * Copyright 2016, Jack Miller, IBM Corp.
3  * Licensed under GPLv2.
4  */
5 
6 #include <stdlib.h>
7 #include <stdio.h>
8 
9 #include "ebb.h"
10 #include "ebb_lmr.h"
11 
12 #define SIZE		(32 * 1024 * 1024)	/* 32M */
13 #define LM_SIZE		0	/* Smallest encoding, 32M */
14 
15 #define SECTIONS	64	/* 1 per bit in LMSER */
16 #define SECTION_SIZE	(SIZE / SECTIONS)
17 #define SECTION_LONGS   (SECTION_SIZE / sizeof(long))
18 
19 static unsigned long *test_mem;
20 
21 static int lmr_count = 0;
22 
ebb_lmr_handler(void)23 void ebb_lmr_handler(void)
24 {
25 	lmr_count++;
26 }
27 
ldmx_full_section(unsigned long * mem,int section)28 void ldmx_full_section(unsigned long *mem, int section)
29 {
30 	unsigned long *ptr;
31 	int i;
32 
33 	for (i = 0; i < SECTION_LONGS; i++) {
34 		ptr = &mem[(SECTION_LONGS * section) + i];
35 		ldmx((unsigned long) &ptr);
36 		ebb_lmr_reset();
37 	}
38 }
39 
40 unsigned long section_masks[] = {
41 	0x8000000000000000,
42 	0xFF00000000000000,
43 	0x0000000F70000000,
44 	0x8000000000000001,
45 	0xF0F0F0F0F0F0F0F0,
46 	0x0F0F0F0F0F0F0F0F,
47 	0x0
48 };
49 
ebb_lmr_section_test(unsigned long * mem)50 int ebb_lmr_section_test(unsigned long *mem)
51 {
52 	unsigned long *mask = section_masks;
53 	int i;
54 
55 	for (; *mask; mask++) {
56 		mtspr(SPRN_LMSER, *mask);
57 		printf("Testing mask 0x%016lx\n", mfspr(SPRN_LMSER));
58 
59 		for (i = 0; i < 64; i++) {
60 			lmr_count = 0;
61 			ldmx_full_section(mem, i);
62 			if (*mask & (1UL << (63 - i)))
63 				FAIL_IF(lmr_count != SECTION_LONGS);
64 			else
65 				FAIL_IF(lmr_count);
66 		}
67 	}
68 
69 	return 0;
70 }
71 
ebb_lmr(void)72 int ebb_lmr(void)
73 {
74 	int i;
75 
76 	SKIP_IF(!lmr_is_supported());
77 
78 	setup_ebb_handler(ebb_lmr_handler);
79 
80 	ebb_global_enable();
81 
82 	FAIL_IF(posix_memalign((void **)&test_mem, SIZE, SIZE) != 0);
83 
84 	mtspr(SPRN_LMSER, 0);
85 
86 	FAIL_IF(mfspr(SPRN_LMSER) != 0);
87 
88 	mtspr(SPRN_LMRR, ((unsigned long)test_mem | LM_SIZE));
89 
90 	FAIL_IF(mfspr(SPRN_LMRR) != ((unsigned long)test_mem | LM_SIZE));
91 
92 	/* Read every single byte to ensure we get no false positives */
93 	for (i = 0; i < SECTIONS; i++)
94 		ldmx_full_section(test_mem, i);
95 
96 	FAIL_IF(lmr_count != 0);
97 
98 	/* Turn on the first section */
99 
100 	mtspr(SPRN_LMSER, (1UL << 63));
101 	FAIL_IF(mfspr(SPRN_LMSER) != (1UL << 63));
102 
103 	/* Enable LM (BESCR) */
104 
105 	mtspr(SPRN_BESCR, mfspr(SPRN_BESCR) | BESCR_LME);
106 	FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LME));
107 
108 	ldmx((unsigned long)&test_mem);
109 
110 	FAIL_IF(lmr_count != 1);	// exactly one exception
111 	FAIL_IF(mfspr(SPRN_BESCR) & BESCR_LME);	// LM now disabled
112 	FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LMEO));	// occurred bit set
113 
114 	printf("Simple LMR EBB OK\n");
115 
116 	/* This shouldn't cause an EBB since it's been disabled */
117 	ldmx((unsigned long)&test_mem);
118 	FAIL_IF(lmr_count != 1);
119 
120 	printf("LMR disable on EBB OK\n");
121 
122 	ebb_lmr_reset();
123 
124 	/* This should cause an EBB or reset is broken */
125 	ldmx((unsigned long)&test_mem);
126 	FAIL_IF(lmr_count != 2);
127 
128 	printf("LMR reset EBB OK\n");
129 
130 	ebb_lmr_reset();
131 
132 	return ebb_lmr_section_test(test_mem);
133 }
134 
main(void)135 int main(void)
136 {
137 	int ret = test_harness(ebb_lmr, "ebb_lmr");
138 
139 	if (test_mem)
140 		free(test_mem);
141 
142 	return ret;
143 }
144