Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / tools / testing / selftests / ia64 / aliasing-test.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Exercise /dev/mem mmap cases that have been troublesome in the past
4  *
5  * (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
6  *      Bjorn Helgaas <bjorn.helgaas@hp.com>
7  */
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <sys/types.h>
12 #include <dirent.h>
13 #include <fcntl.h>
14 #include <fnmatch.h>
15 #include <string.h>
16 #include <sys/ioctl.h>
17 #include <sys/mman.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 #include <linux/pci.h>
21
22 int sum;
23
24 static int map_mem(char *path, off_t offset, size_t length, int touch)
25 {
26         int fd, rc;
27         void *addr;
28         int *c;
29
30         fd = open(path, O_RDWR);
31         if (fd == -1) {
32                 perror(path);
33                 return -1;
34         }
35
36         if (fnmatch("/proc/bus/pci/*", path, 0) == 0) {
37                 rc = ioctl(fd, PCIIOC_MMAP_IS_MEM);
38                 if (rc == -1)
39                         perror("PCIIOC_MMAP_IS_MEM ioctl");
40         }
41
42         addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
43         if (addr == MAP_FAILED)
44                 return 1;
45
46         if (touch) {
47                 c = (int *) addr;
48                 while (c < (int *) (addr + length))
49                         sum += *c++;
50         }
51
52         rc = munmap(addr, length);
53         if (rc == -1) {
54                 perror("munmap");
55                 return -1;
56         }
57
58         close(fd);
59         return 0;
60 }
61
62 static int scan_tree(char *path, char *file, off_t offset, size_t length, int touch)
63 {
64         struct dirent **namelist;
65         char *name, *path2;
66         int i, n, r, rc = 0, result = 0;
67         struct stat buf;
68
69         n = scandir(path, &namelist, 0, alphasort);
70         if (n < 0) {
71                 perror("scandir");
72                 return -1;
73         }
74
75         for (i = 0; i < n; i++) {
76                 name = namelist[i]->d_name;
77
78                 if (fnmatch(".", name, 0) == 0)
79                         goto skip;
80                 if (fnmatch("..", name, 0) == 0)
81                         goto skip;
82
83                 path2 = malloc(strlen(path) + strlen(name) + 3);
84                 strcpy(path2, path);
85                 strcat(path2, "/");
86                 strcat(path2, name);
87
88                 if (fnmatch(file, name, 0) == 0) {
89                         rc = map_mem(path2, offset, length, touch);
90                         if (rc == 0)
91                                 fprintf(stderr, "PASS: %s 0x%lx-0x%lx is %s\n", path2, offset, offset + length, touch ? "readable" : "mappable");
92                         else if (rc > 0)
93                                 fprintf(stderr, "PASS: %s 0x%lx-0x%lx not mappable\n", path2, offset, offset + length);
94                         else {
95                                 fprintf(stderr, "FAIL: %s 0x%lx-0x%lx not accessible\n", path2, offset, offset + length);
96                                 return rc;
97                         }
98                 } else {
99                         r = lstat(path2, &buf);
100                         if (r == 0 && S_ISDIR(buf.st_mode)) {
101                                 rc = scan_tree(path2, file, offset, length, touch);
102                                 if (rc < 0)
103                                         return rc;
104                         }
105                 }
106
107                 result |= rc;
108                 free(path2);
109
110 skip:
111                 free(namelist[i]);
112         }
113         free(namelist);
114         return result;
115 }
116
117 char buf[1024];
118
119 static int read_rom(char *path)
120 {
121         int fd, rc;
122         size_t size = 0;
123
124         fd = open(path, O_RDWR);
125         if (fd == -1) {
126                 perror(path);
127                 return -1;
128         }
129
130         rc = write(fd, "1", 2);
131         if (rc <= 0) {
132                 close(fd);
133                 perror("write");
134                 return -1;
135         }
136
137         do {
138                 rc = read(fd, buf, sizeof(buf));
139                 if (rc > 0)
140                         size += rc;
141         } while (rc > 0);
142
143         close(fd);
144         return size;
145 }
146
147 static int scan_rom(char *path, char *file)
148 {
149         struct dirent **namelist;
150         char *name, *path2;
151         int i, n, r, rc = 0, result = 0;
152         struct stat buf;
153
154         n = scandir(path, &namelist, 0, alphasort);
155         if (n < 0) {
156                 perror("scandir");
157                 return -1;
158         }
159
160         for (i = 0; i < n; i++) {
161                 name = namelist[i]->d_name;
162
163                 if (fnmatch(".", name, 0) == 0)
164                         goto skip;
165                 if (fnmatch("..", name, 0) == 0)
166                         goto skip;
167
168                 path2 = malloc(strlen(path) + strlen(name) + 3);
169                 strcpy(path2, path);
170                 strcat(path2, "/");
171                 strcat(path2, name);
172
173                 if (fnmatch(file, name, 0) == 0) {
174                         rc = read_rom(path2);
175
176                         /*
177                          * It's OK if the ROM is unreadable.  Maybe there
178                          * is no ROM, or some other error occurred.  The
179                          * important thing is that no MCA happened.
180                          */
181                         if (rc > 0)
182                                 fprintf(stderr, "PASS: %s read %d bytes\n", path2, rc);
183                         else {
184                                 fprintf(stderr, "PASS: %s not readable\n", path2);
185                                 return rc;
186                         }
187                 } else {
188                         r = lstat(path2, &buf);
189                         if (r == 0 && S_ISDIR(buf.st_mode)) {
190                                 rc = scan_rom(path2, file);
191                                 if (rc < 0)
192                                         return rc;
193                         }
194                 }
195
196                 result |= rc;
197                 free(path2);
198
199 skip:
200                 free(namelist[i]);
201         }
202         free(namelist);
203         return result;
204 }
205
206 int main(void)
207 {
208         int rc;
209
210         if (map_mem("/dev/mem", 0, 0xA0000, 1) == 0)
211                 fprintf(stderr, "PASS: /dev/mem 0x0-0xa0000 is readable\n");
212         else
213                 fprintf(stderr, "FAIL: /dev/mem 0x0-0xa0000 not accessible\n");
214
215         /*
216          * It's not safe to blindly read the VGA frame buffer.  If you know
217          * how to poke the card the right way, it should respond, but it's
218          * not safe in general.  Many machines, e.g., Intel chipsets, cover
219          * up a non-responding card by just returning -1, but others will
220          * report the failure as a machine check.
221          */
222         if (map_mem("/dev/mem", 0xA0000, 0x20000, 0) == 0)
223                 fprintf(stderr, "PASS: /dev/mem 0xa0000-0xc0000 is mappable\n");
224         else
225                 fprintf(stderr, "FAIL: /dev/mem 0xa0000-0xc0000 not accessible\n");
226
227         if (map_mem("/dev/mem", 0xC0000, 0x40000, 1) == 0)
228                 fprintf(stderr, "PASS: /dev/mem 0xc0000-0x100000 is readable\n");
229         else
230                 fprintf(stderr, "FAIL: /dev/mem 0xc0000-0x100000 not accessible\n");
231
232         /*
233          * Often you can map all the individual pieces above (0-0xA0000,
234          * 0xA0000-0xC0000, and 0xC0000-0x100000), but can't map the whole
235          * thing at once.  This is because the individual pieces use different
236          * attributes, and there's no single attribute supported over the
237          * whole region.
238          */
239         rc = map_mem("/dev/mem", 0, 1024*1024, 0);
240         if (rc == 0)
241                 fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 is mappable\n");
242         else if (rc > 0)
243                 fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 not mappable\n");
244         else
245                 fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
246
247         scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
248         scan_tree("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
249         scan_tree("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
250         scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
251
252         scan_rom("/sys/devices", "rom");
253
254         scan_tree("/proc/bus/pci", "??.?", 0, 0xA0000, 1);
255         scan_tree("/proc/bus/pci", "??.?", 0xA0000, 0x20000, 0);
256         scan_tree("/proc/bus/pci", "??.?", 0xC0000, 0x40000, 1);
257         scan_tree("/proc/bus/pci", "??.?", 0, 1024*1024, 0);
258
259         return rc;
260 }