Blame view

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