selftests/powerpc: Load Monitor Register Tests
[deliverable/linux.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 }
This page took 0.04616 seconds and 5 git commands to generate.