Linux-libre 4.9.123-gnu
[librecmc/linux-libre.git] / tools / testing / selftests / powerpc / pmu / ebb / ebb_lmr.c
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
23 void ebb_lmr_handler(void)
24 {
25         lmr_count++;
26 }
27
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
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
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
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 }