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#include <signal.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <sys/mman.h>
32#include <sys/types.h>
33#include <sys/wait.h>
34#include <unistd.h>
35
36#include "utils.h"
37
38#ifndef MAP_FIXED_NOREPLACE
39#define MAP_FIXED_NOREPLACE MAP_FIXED
40#endif
41
42#define BASE_ADDRESS (1ul << 50)
43#define STRIDE (2ul << 40)
44#define SLB_SIZE 32
45#define NR_MAPPINGS (SLB_SIZE * 2)
46
47static volatile sig_atomic_t signaled;
48
49static void signal_handler(int sig)
50{
51 signaled = 1;
52}
53
54#define CHECK_REG(_reg) \
55 if (_reg != _reg##_orig) { \
56 printf(str(_reg) " corrupted! Expected 0x%lx != 0x%lx\n", _reg##_orig, \
57 _reg); \
58 _exit(1); \
59 }
60
61static int touch_mappings(void)
62{
63 unsigned long r9_orig, r10_orig, r11_orig, r12_orig, r13_orig;
64 unsigned long r9, r10, r11, r12, r13;
65 unsigned long addr, *p;
66 int i;
67
68 for (i = 0; i < NR_MAPPINGS; i++) {
69 addr = BASE_ADDRESS + (i * STRIDE);
70 p = (unsigned long *)addr;
71
72 asm volatile("mr %0, %%r9 ;"
73 "mr %1, %%r10 ;"
74 "mr %2, %%r11 ;"
75 "mr %3, %%r12 ;"
76 "mr %4, %%r13 ;"
77 "std %10, 0(%11) ;"
78 "mr %5, %%r9 ;"
79 "mr %6, %%r10 ;"
80 "mr %7, %%r11 ;"
81 "mr %8, %%r12 ;"
82 "mr %9, %%r13 ;"
83 "mr %%r9, %0 ;"
84 "mr %%r10, %1 ;"
85 "mr %%r11, %2 ;"
86 "mr %%r12, %3 ;"
87 "mr %%r13, %4 ;"
88 : "=&b"(r9_orig), "=&b"(r10_orig), "=&b"(r11_orig),
89 "=&b"(r12_orig), "=&b"(r13_orig), "=&b"(r9), "=&b"(r10),
90 "=&b"(r11), "=&b"(r12), "=&b"(r13)
91 : "b"(i), "b"(p)
92 : "r9", "r10", "r11", "r12", "r13");
93
94 CHECK_REG(r9);
95 CHECK_REG(r10);
96 CHECK_REG(r11);
97 CHECK_REG(r12);
98 CHECK_REG(r13);
99 }
100
101 return 0;
102}
103
104static int test(void)
105{
106 unsigned long page_size, addr, *p;
107 struct sigaction action;
108 bool hash_mmu;
109 int i, status;
110 pid_t pid;
111
112
113 FAIL_IF(using_hash_mmu(&hash_mmu));
114 SKIP_IF(!hash_mmu);
115
116 page_size = sysconf(_SC_PAGESIZE);
117
118 for (i = 0; i < NR_MAPPINGS; i++) {
119 addr = BASE_ADDRESS + (i * STRIDE);
120
121 p = mmap((void *)addr, page_size, PROT_READ | PROT_WRITE,
122 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE, -1, 0);
123 if (p == MAP_FAILED) {
124 perror("mmap");
125 printf("Error: couldn't mmap(), confirm kernel has 4PB support?\n");
126 return 1;
127 }
128 }
129
130 action.sa_handler = signal_handler;
131 action.sa_flags = SA_RESTART;
132 FAIL_IF(sigaction(SIGALRM, &action, NULL) < 0);
133
134
135 alarm(30);
136
137 while (!signaled) {
138
139
140 pid = fork();
141 if (pid == 0)
142 exit(touch_mappings());
143
144 FAIL_IF(waitpid(-1, &status, 0) == -1);
145 FAIL_IF(WIFSIGNALED(status));
146 FAIL_IF(!WIFEXITED(status));
147 FAIL_IF(WEXITSTATUS(status));
148 }
149
150 return 0;
151}
152
153int main(void)
154{
155 return test_harness(test, "large_vm_gpr_corruption");
156}
157