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