aliasing-test.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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 <bjorn.helgaas@hp.com>
  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. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <sys/types.h>
  14. #include <dirent.h>
  15. #include <fcntl.h>
  16. #include <fnmatch.h>
  17. #include <string.h>
  18. #include <sys/mman.h>
  19. #include <sys/stat.h>
  20. #include <unistd.h>
  21. int sum;
  22. int map_mem(char *path, off_t offset, size_t length, int touch)
  23. {
  24. int fd, rc;
  25. void *addr;
  26. int *c;
  27. fd = open(path, O_RDWR);
  28. if (fd == -1) {
  29. perror(path);
  30. return -1;
  31. }
  32. addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
  33. if (addr == MAP_FAILED)
  34. return 1;
  35. if (touch) {
  36. c = (int *) addr;
  37. while (c < (int *) (offset + length))
  38. sum += *c++;
  39. }
  40. rc = munmap(addr, length);
  41. if (rc == -1) {
  42. perror("munmap");
  43. return -1;
  44. }
  45. close(fd);
  46. return 0;
  47. }
  48. int scan_sysfs(char *path, char *file, off_t offset, size_t length, int touch)
  49. {
  50. struct dirent **namelist;
  51. char *name, *path2;
  52. int i, n, r, rc, result = 0;
  53. struct stat buf;
  54. n = scandir(path, &namelist, 0, alphasort);
  55. if (n < 0) {
  56. perror("scandir");
  57. return -1;
  58. }
  59. for (i = 0; i < n; i++) {
  60. name = namelist[i]->d_name;
  61. if (fnmatch(".", name, 0) == 0)
  62. goto skip;
  63. if (fnmatch("..", name, 0) == 0)
  64. goto skip;
  65. path2 = malloc(strlen(path) + strlen(name) + 3);
  66. strcpy(path2, path);
  67. strcat(path2, "/");
  68. strcat(path2, name);
  69. if (fnmatch(file, name, 0) == 0) {
  70. rc = map_mem(path2, offset, length, touch);
  71. if (rc == 0)
  72. fprintf(stderr, "PASS: %s 0x%lx-0x%lx is %s\n", path2, offset, offset + length, touch ? "readable" : "mappable");
  73. else if (rc > 0)
  74. fprintf(stderr, "PASS: %s 0x%lx-0x%lx not mappable\n", path2, offset, offset + length);
  75. else {
  76. fprintf(stderr, "FAIL: %s 0x%lx-0x%lx not accessible\n", path2, offset, offset + length);
  77. return rc;
  78. }
  79. } else {
  80. r = lstat(path2, &buf);
  81. if (r == 0 && S_ISDIR(buf.st_mode)) {
  82. rc = scan_sysfs(path2, file, offset, length, touch);
  83. if (rc < 0)
  84. return rc;
  85. }
  86. }
  87. result |= rc;
  88. free(path2);
  89. skip:
  90. free(namelist[i]);
  91. }
  92. free(namelist);
  93. return rc;
  94. }
  95. char buf[1024];
  96. int read_rom(char *path)
  97. {
  98. int fd, rc;
  99. size_t size = 0;
  100. fd = open(path, O_RDWR);
  101. if (fd == -1) {
  102. perror(path);
  103. return -1;
  104. }
  105. rc = write(fd, "1", 2);
  106. if (rc <= 0) {
  107. perror("write");
  108. return -1;
  109. }
  110. do {
  111. rc = read(fd, buf, sizeof(buf));
  112. if (rc > 0)
  113. size += rc;
  114. } while (rc > 0);
  115. close(fd);
  116. return size;
  117. }
  118. int scan_rom(char *path, char *file)
  119. {
  120. struct dirent **namelist;
  121. char *name, *path2;
  122. int i, n, r, rc, result = 0;
  123. struct stat buf;
  124. n = scandir(path, &namelist, 0, alphasort);
  125. if (n < 0) {
  126. perror("scandir");
  127. return -1;
  128. }
  129. for (i = 0; i < n; i++) {
  130. name = namelist[i]->d_name;
  131. if (fnmatch(".", name, 0) == 0)
  132. goto skip;
  133. if (fnmatch("..", name, 0) == 0)
  134. goto skip;
  135. path2 = malloc(strlen(path) + strlen(name) + 3);
  136. strcpy(path2, path);
  137. strcat(path2, "/");
  138. strcat(path2, name);
  139. if (fnmatch(file, name, 0) == 0) {
  140. rc = read_rom(path2);
  141. /*
  142. * It's OK if the ROM is unreadable. Maybe there
  143. * is no ROM, or some other error ocurred. The
  144. * important thing is that no MCA happened.
  145. */
  146. if (rc > 0)
  147. fprintf(stderr, "PASS: %s read %ld bytes\n", path2, rc);
  148. else {
  149. fprintf(stderr, "PASS: %s not readable\n", path2);
  150. return rc;
  151. }
  152. } else {
  153. r = lstat(path2, &buf);
  154. if (r == 0 && S_ISDIR(buf.st_mode)) {
  155. rc = scan_rom(path2, file);
  156. if (rc < 0)
  157. return rc;
  158. }
  159. }
  160. result |= rc;
  161. free(path2);
  162. skip:
  163. free(namelist[i]);
  164. }
  165. free(namelist);
  166. return rc;
  167. }
  168. int main()
  169. {
  170. int rc;
  171. if (map_mem("/dev/mem", 0, 0xA0000, 1) == 0)
  172. fprintf(stderr, "PASS: /dev/mem 0x0-0xa0000 is readable\n");
  173. else
  174. fprintf(stderr, "FAIL: /dev/mem 0x0-0xa0000 not accessible\n");
  175. /*
  176. * It's not safe to blindly read the VGA frame buffer. If you know
  177. * how to poke the card the right way, it should respond, but it's
  178. * not safe in general. Many machines, e.g., Intel chipsets, cover
  179. * up a non-responding card by just returning -1, but others will
  180. * report the failure as a machine check.
  181. */
  182. if (map_mem("/dev/mem", 0xA0000, 0x20000, 0) == 0)
  183. fprintf(stderr, "PASS: /dev/mem 0xa0000-0xc0000 is mappable\n");
  184. else
  185. fprintf(stderr, "FAIL: /dev/mem 0xa0000-0xc0000 not accessible\n");
  186. if (map_mem("/dev/mem", 0xC0000, 0x40000, 1) == 0)
  187. fprintf(stderr, "PASS: /dev/mem 0xc0000-0x100000 is readable\n");
  188. else
  189. fprintf(stderr, "FAIL: /dev/mem 0xc0000-0x100000 not accessible\n");
  190. /*
  191. * Often you can map all the individual pieces above (0-0xA0000,
  192. * 0xA0000-0xC0000, and 0xC0000-0x100000), but can't map the whole
  193. * thing at once. This is because the individual pieces use different
  194. * attributes, and there's no single attribute supported over the
  195. * whole region.
  196. */
  197. rc = map_mem("/dev/mem", 0, 1024*1024, 0);
  198. if (rc == 0)
  199. fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 is mappable\n");
  200. else if (rc > 0)
  201. fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 not mappable\n");
  202. else
  203. fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
  204. scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
  205. scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
  206. scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
  207. scan_sysfs("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
  208. scan_rom("/sys/devices", "rom");
  209. }