Root/Documentation/ia64/aliasing-test.c

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
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
25int sum;
26
27static 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
65static 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
113skip:
114        free(namelist[i]);
115    }
116    free(namelist);
117    return result;
118}
119
120char buf[1024];
121
122static 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        perror("write");
136        return -1;
137    }
138
139    do {
140        rc = read(fd, buf, sizeof(buf));
141        if (rc > 0)
142            size += rc;
143    } while (rc > 0);
144
145    close(fd);
146    return size;
147}
148
149static int scan_rom(char *path, char *file)
150{
151    struct dirent **namelist;
152    char *name, *path2;
153    int i, n, r, rc = 0, result = 0;
154    struct stat buf;
155
156    n = scandir(path, &namelist, 0, alphasort);
157    if (n < 0) {
158        perror("scandir");
159        return -1;
160    }
161
162    for (i = 0; i < n; i++) {
163        name = namelist[i]->d_name;
164
165        if (fnmatch(".", name, 0) == 0)
166            goto skip;
167        if (fnmatch("..", name, 0) == 0)
168            goto skip;
169
170        path2 = malloc(strlen(path) + strlen(name) + 3);
171        strcpy(path2, path);
172        strcat(path2, "/");
173        strcat(path2, name);
174
175        if (fnmatch(file, name, 0) == 0) {
176            rc = read_rom(path2);
177
178            /*
179             * It's OK if the ROM is unreadable. Maybe there
180             * is no ROM, or some other error ocurred. The
181             * important thing is that no MCA happened.
182             */
183            if (rc > 0)
184                fprintf(stderr, "PASS: %s read %d bytes\n", path2, rc);
185            else {
186                fprintf(stderr, "PASS: %s not readable\n", path2);
187                return rc;
188            }
189        } else {
190            r = lstat(path2, &buf);
191            if (r == 0 && S_ISDIR(buf.st_mode)) {
192                rc = scan_rom(path2, file);
193                if (rc < 0)
194                    return rc;
195            }
196        }
197
198        result |= rc;
199        free(path2);
200
201skip:
202        free(namelist[i]);
203    }
204    free(namelist);
205    return result;
206}
207
208int main(void)
209{
210    int rc;
211
212    if (map_mem("/dev/mem", 0, 0xA0000, 1) == 0)
213        fprintf(stderr, "PASS: /dev/mem 0x0-0xa0000 is readable\n");
214    else
215        fprintf(stderr, "FAIL: /dev/mem 0x0-0xa0000 not accessible\n");
216
217    /*
218     * It's not safe to blindly read the VGA frame buffer. If you know
219     * how to poke the card the right way, it should respond, but it's
220     * not safe in general. Many machines, e.g., Intel chipsets, cover
221     * up a non-responding card by just returning -1, but others will
222     * report the failure as a machine check.
223     */
224    if (map_mem("/dev/mem", 0xA0000, 0x20000, 0) == 0)
225        fprintf(stderr, "PASS: /dev/mem 0xa0000-0xc0000 is mappable\n");
226    else
227        fprintf(stderr, "FAIL: /dev/mem 0xa0000-0xc0000 not accessible\n");
228
229    if (map_mem("/dev/mem", 0xC0000, 0x40000, 1) == 0)
230        fprintf(stderr, "PASS: /dev/mem 0xc0000-0x100000 is readable\n");
231    else
232        fprintf(stderr, "FAIL: /dev/mem 0xc0000-0x100000 not accessible\n");
233
234    /*
235     * Often you can map all the individual pieces above (0-0xA0000,
236     * 0xA0000-0xC0000, and 0xC0000-0x100000), but can't map the whole
237     * thing at once. This is because the individual pieces use different
238     * attributes, and there's no single attribute supported over the
239     * whole region.
240     */
241    rc = map_mem("/dev/mem", 0, 1024*1024, 0);
242    if (rc == 0)
243        fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 is mappable\n");
244    else if (rc > 0)
245        fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 not mappable\n");
246    else
247        fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
248
249    scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
250    scan_tree("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
251    scan_tree("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
252    scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
253
254    scan_rom("/sys/devices", "rom");
255
256    scan_tree("/proc/bus/pci", "??.?", 0, 0xA0000, 1);
257    scan_tree("/proc/bus/pci", "??.?", 0xA0000, 0x20000, 0);
258    scan_tree("/proc/bus/pci", "??.?", 0xC0000, 0x40000, 1);
259    scan_tree("/proc/bus/pci", "??.?", 0, 1024*1024, 0);
260
261    return rc;
262}
263

Archive Download this file



interactive