1/**
2 * \file
3 * \brief Test program for large page code
4 */
5
6/*
7 * Copyright (c) 2014, HP Labs.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <barrelfish/barrelfish.h>
16#include <barrelfish/sys_debug.h>
17
18#define RUNS 2
19
20int main(void)
21{
22    errval_t err;
23    struct capref frame;
24    size_t retsize;
25    void *vbuf;
26    struct vregion *vregion;
27    uint8_t *buf;
28    int errors;
29
30    // get frame
31    err = frame_alloc(&frame, X86_64_HUGE_PAGE_SIZE, &retsize);
32    assert(retsize >= X86_64_HUGE_PAGE_SIZE);
33    if (err_is_fail(err)) {
34        debug_printf("frame_alloc: %s\n", err_getstring(err));
35        return 1;
36    }
37
38    for (int k = 0; k < RUNS; k++) {
39        debug_printf("Running 2M/1G test\n");
40        // map with alignment and large flag (don't need memobj)
41        err = vspace_map_one_frame_attr_aligned(&vbuf, retsize, frame,
42                VREGION_FLAGS_READ_WRITE | VREGION_FLAGS_LARGE,
43                X86_64_HUGE_PAGE_SIZE, NULL, &vregion);
44        if (err_is_fail(err)) {
45            debug_printf("vspace_map: %s\n", err_getstring(err));
46            return 1;
47        }
48
49        debug_printf("vaddr: %p\n", vbuf);
50
51        // touch every 4k page in region
52        buf = vbuf;
53        for (int i = 0; i < X86_64_HUGE_PAGE_SIZE / X86_64_BASE_PAGE_SIZE; i++) {
54            buf[i*BASE_PAGE_SIZE] = i % 256;
55        }
56        // clear out caches
57        sys_debug_flush_cache();
58        errors = 0;
59        for (int i = 0; i < X86_64_HUGE_PAGE_SIZE / X86_64_BASE_PAGE_SIZE; i++) {
60            if (buf[i*BASE_PAGE_SIZE] != i % 256) {
61                debug_printf("mismatch in page %d: expected %d, was %d\n",
62                        i, i % 256, buf[i*BASE_PAGE_SIZE]);
63                errors++;
64            }
65        }
66        debug_printf("2M/1G test %s\n", errors ? "FAILED" : "PASSED");
67        if (errors) {
68            debug_printf("  %d errors\n", errors);
69        }
70
71        vregion_destroy(vregion);
72    }
73    for (int k = 0; k < RUNS; k++) {
74        debug_printf("Running 2M/2M test\n");
75        // map with large flag
76        err = vspace_map_one_frame_attr_aligned(&vbuf, retsize, frame,
77                VREGION_FLAGS_READ_WRITE | VREGION_FLAGS_LARGE,
78                X86_64_LARGE_PAGE_SIZE, NULL, &vregion);
79        if (err_is_fail(err)) {
80            debug_printf("vspace_map: %s\n", err_getstring(err));
81            return 1;
82        }
83
84        debug_printf("vaddr: %p\n", vbuf);
85
86        // touch every 4k page in region
87        buf = vbuf;
88        for (int i = 0; i < X86_64_HUGE_PAGE_SIZE / X86_64_BASE_PAGE_SIZE; i++) {
89            buf[i*BASE_PAGE_SIZE] = i % 256;
90        }
91        // clear out caches
92        sys_debug_flush_cache();
93        errors = 0;
94        for (int i = 0; i < X86_64_HUGE_PAGE_SIZE / X86_64_BASE_PAGE_SIZE; i++) {
95            if (buf[i*BASE_PAGE_SIZE] != i % 256) {
96                debug_printf("mismatch in page %d: expected %d, was %d\n",
97                        i, i % 256, buf[i*BASE_PAGE_SIZE]);
98                errors++;
99            }
100        }
101        debug_printf("2M/2M test %s\n", errors ? "FAILED" : "PASSED");
102        if (errors) {
103            debug_printf("  %d errors\n", errors);
104        }
105
106        vregion_destroy(vregion);
107    }
108
109    uint32_t eax, ebx, ecx, edx;
110    cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
111    if ((edx >> 26) & 1) {
112        debug_printf("Running 1G/1G test\n");
113        err = vspace_map_one_frame_attr_aligned(&vbuf, retsize, frame,
114                VREGION_FLAGS_READ_WRITE | VREGION_FLAGS_HUGE,
115                X86_64_HUGE_PAGE_SIZE, NULL, &vregion);
116        if (err_is_fail(err)) {
117            debug_printf("vspace_map: %s\n", err_getstring(err));
118            return 1;
119        }
120
121        // touch every 4k page in region
122        buf = vbuf;
123        for (int i = 0; i < X86_64_HUGE_PAGE_SIZE / X86_64_BASE_PAGE_SIZE; i++) {
124            buf[i*BASE_PAGE_SIZE] = i % 256;
125        }
126        // clear out caches
127        sys_debug_flush_cache();
128        errors = 0;
129        for (int i = 0; i < X86_64_HUGE_PAGE_SIZE / X86_64_BASE_PAGE_SIZE; i++) {
130            if (buf[i*BASE_PAGE_SIZE] != i % 256) {
131                debug_printf("mismatch in page %d: expected %d, was %d\n",
132                        i, i % 256, buf[i*BASE_PAGE_SIZE]);
133                errors++;
134            }
135        }
136        debug_printf("1G/1G test %s\n", errors ? "FAILED" : "PASSED");
137        if (errors) {
138            debug_printf("  %d errors\n", errors);
139        }
140    }
141    return 0;
142}
143