1/**
2 * \file
3 * \brief Test program for large page code
4 */
5
6/*
7 * Copyright (c) 2013, ETH Zurich.
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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <barrelfish/barrelfish.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <assert.h>
20#include <inttypes.h>
21#include <barrelfish/nameservice_client.h>
22#include <barrelfish/sys_debug.h>
23#include <bench/bench.h>
24
25#define SAFE_VADDR (genvaddr_t)(8ULL<<39)
26#define SAFE_PMAP_ADDR (genvaddr_t)(9ULL<<39)
27//0b 0000 0000 0000 0000 0000 0100 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000
28#define SAFE_PMAP_ADDR_L ((genvaddr_t) (12ULL<<39))
29// 40M
30#define DEFAULT_SIZE 30*X86_64_LARGE_PAGE_SIZE
31
32#define LARGE_PAGE_SIZE X86_64_LARGE_PAGE_SIZE
33
34#define RUN_COUNT 50
35
36unsigned long mean4k;
37unsigned long mean2m;
38unsigned long min4k;
39unsigned long min2m;
40unsigned long mean4krand;
41unsigned long mean2mrand;
42unsigned long min4krand;
43unsigned long min2mrand;
44unsigned long max4krand;
45unsigned long max2mrand;
46unsigned long max4k;
47unsigned long max2m;
48
49unsigned long mean4kshort;
50unsigned long mean2mshort;
51unsigned long mean4kshortrand;
52unsigned long mean2mshortrand;
53unsigned long min4kshort;
54unsigned long min2mshort;
55unsigned long min4kshortrand;
56unsigned long min2mshortrand;
57unsigned long max4kshort;
58unsigned long max2mshort;
59unsigned long max4kshortrand;
60unsigned long max2mshortrand;
61/*static paging_x86_64_flags_t PAGE_DEFAULT_ACCESS =
62    PTABLE_USER_SUPERVISOR |
63    PTABLE_EXECUTE_DISABLE |
64    PTABLE_READ_WRITE;
65 */
66static vregion_flags_t PMAP_DEFAULT_ACCESS =
67    VREGION_FLAGS_READ_WRITE;
68
69static void test_region(uint32_t *buf, size_t size, bool large, bool area)
70{
71    cycles_t runs[RUN_COUNT];
72    cycles_t start, end;
73    uint64_t mean = 0;
74    unsigned long min = 0;
75    unsigned long max = 0;
76    printf("base address: %lx\n", (uint64_t) buf);
77
78    //sequential access
79    for (int j = 0; j < RUN_COUNT; j++) {
80
81        start = bench_tsc()/1000;
82        for (unsigned long i = 0; i < size; i+=4) {
83
84            buf[i/4] = i;
85        }
86        for (unsigned long i = 0; i < size; i+=4) {
87            assert(buf[i/4] == i);
88        }
89        end = bench_tsc()/1000;
90        runs[j] = end-start;
91        mean += (unsigned int) runs[j];
92        if (runs[j] < min || j == 0) {min = runs[j];}
93        if (runs[j] > max) {max = runs[j];}
94        printf("run: %u, cycles: %u\n", j, (unsigned int) runs[j]);
95    }
96    mean = mean/RUN_COUNT;
97    printf("\naverage cycles to write the whole area: %u\n", (unsigned int) mean);
98    if(!large && !area) {
99        mean4k = mean;
100        min4k = min;
101        max4k = max;
102    }
103    else if (large && !area) {
104        mean2m = mean;
105        min2m = min;
106        max2m = max;
107    }
108    else if (!large && area) {
109        mean4kshort = mean;
110        min4kshort = min;
111        max4kshort = max;
112    } else {
113        mean2mshort = mean;
114        min2mshort = min;
115        max2mshort = max;
116    }
117
118    //random access
119    //generate 1M random number array
120    unsigned int* addrs;
121    min = 0;
122    max = 0;
123    mean = 0;
124    addrs = malloc(2000000*sizeof(unsigned int));
125    printf("malloc'd\n");
126    for (int i = 0; i<2000000; i++)
127    {
128        addrs[i] = (rand() % (size/4));
129    }
130    printf("randomised\n");
131    for (int j = 0; j < RUN_COUNT; j++) {
132
133        start = bench_tsc()/1000;
134        for (int i = 0; i < 2000000; i++) {
135            buf[addrs[i]] = addrs[i];
136        }
137        for (unsigned long i = 0; i < 2000000; i++) {
138            assert(buf[addrs[i]] == addrs[i]);
139        }
140        end = bench_tsc()/1000;
141        runs[j] = end-start;
142        mean += (unsigned int) runs[j];
143        if (runs[j] < min || j == 0) {min = runs[j];}
144        if (runs[j] > max) {max = runs[j];}
145        printf("run: %u, cycles: %u\n", j, (unsigned int) runs[j]);
146    }
147    mean = mean/RUN_COUNT;
148    printf("\naverage cycles to write the whole area randomly: %u\n", (unsigned int) mean);
149    if(!large && !area) {
150        mean4krand = mean;
151        min4krand = min;
152        max4krand = max;
153    }
154    else if (large && !area){
155        mean2mrand = mean;
156        min2mrand = min;
157        max2mrand = max;
158    }else if (!large && area) {
159        mean4kshortrand = mean;
160        min4kshortrand = min;
161        max4kshortrand = max;
162    } else {
163        mean2mshortrand = mean;
164        min2mshortrand = min;
165        max2mshortrand = max;
166    }
167
168}
169
170int main(void)
171{
172    struct capref frame;
173    size_t bytes = DEFAULT_SIZE;
174    errval_t err;
175    mean4k = 0;
176    mean2m = 0;
177    genvaddr_t address;
178
179
180    //normal pages via pmap interface
181    printf("\nstart 4k map with pmap\n");
182    err = frame_alloc(&frame, bytes, &bytes);
183    if (err_is_fail(err))
184    {
185        printf("error in frame_alloc: %s\n", err_getstring(err));
186        exit(1);
187    }
188    assert(bytes >= DEFAULT_SIZE);
189    printf("    get pmap\n");
190    struct pmap *pmap = get_current_pmap();
191
192    printf("    obtain address\n");
193    err = pmap->f.determine_addr_raw(pmap, bytes, X86_64_BASE_PAGE_SIZE, &address);
194    if (err_is_fail(err))
195    {
196        printf("error in determine_addr_raw: %s\n", err_getstring(err));
197        exit(1);
198    }
199
200    printf("    map\n");
201    err = pmap->f.map(pmap, address, frame, 0, bytes, PMAP_DEFAULT_ACCESS, NULL, &bytes);
202    if (err_is_fail(err))
203    {
204        printf("error in pmap: %s\n", err_getstring(err));
205        exit(1);
206    }
207    printf("addr: %lx\n", address);
208    test_region((uint32_t*)address, DEFAULT_SIZE, false, false);
209
210    printf("\tunmap\n");
211    err = pmap->f.unmap(pmap, address, bytes, NULL);
212    if (err_is_fail(err))
213    {
214        printf("error in unmap: %s\n", err_getstring(err));
215        exit(1);
216    }
217
218    //large page via pmap interface
219    printf("start 2m map with pmap\n");
220    bytes = DEFAULT_SIZE;
221    struct capref frame2;
222    err = frame_alloc(&frame2, bytes, &bytes);
223    if (err_is_fail(err))
224    {
225        printf("error in frame_alloc: %s\n", err_getstring(err));
226        exit(1);
227    }
228    assert(bytes >= DEFAULT_SIZE);
229    pmap = get_current_pmap();
230
231    printf("determine address\n");
232    err = pmap->f.determine_addr_raw(pmap, bytes, X86_64_LARGE_PAGE_SIZE, &address);
233    if (err_is_fail(err))
234    {
235        printf("error in determine_addr_raw: %s\n", err_getstring(err));
236        exit(1);
237    }
238
239    printf("map\n");
240    err = pmap->f.map(pmap, address, frame, 0, bytes, PMAP_DEFAULT_ACCESS | 0x0100, NULL, &bytes);
241    if (err_is_fail(err))
242    {
243        printf("error in pmap: %s\n", err_getstring(err));
244        exit(1);
245    }
246    printf("addr: %lx\n", address);
247    test_region((uint32_t*)address, DEFAULT_SIZE, true, false);
248
249    err = pmap->f.unmap(pmap, address, bytes, NULL);
250    if (err_is_fail(err))
251    {
252        printf("error in unmap: %s\n", err_getstring(err));
253        exit(1);
254    }
255    //small area 4k
256    bytes = LARGE_PAGE_SIZE;
257    err = frame_alloc(&frame, bytes, &bytes);
258    if (err_is_fail(err))
259    {
260        printf("error in frame_alloc: %s\n", err_getstring(err));
261        exit(1);
262    }
263    assert(bytes >= LARGE_PAGE_SIZE);
264    pmap = get_current_pmap();
265    err = pmap->f.map(pmap, SAFE_PMAP_ADDR, frame, 0, bytes, PMAP_DEFAULT_ACCESS, NULL, &bytes);
266    if (err_is_fail(err))
267    {
268        printf("error in pmap small 4k\n");
269        exit(1);
270    }
271    test_region((uint32_t*) SAFE_PMAP_ADDR, LARGE_PAGE_SIZE, false, true);
272
273    //small area 2m
274    bytes = LARGE_PAGE_SIZE;
275    err = frame_alloc(&frame, bytes, &bytes);
276    if (err_is_fail(err))
277    {
278        printf("error in frame_alloc: %s\n", err_getstring(err));
279        exit(1);
280    }
281    assert(bytes >= LARGE_PAGE_SIZE);
282    pmap = get_current_pmap();
283
284    printf("map\n");
285    err = pmap->f.map(pmap, SAFE_PMAP_ADDR_L, frame, 0, bytes, PMAP_DEFAULT_ACCESS | 0x0100, NULL, &bytes);
286    if (err_is_fail(err))
287    {
288        printf("error in pmap: %s\n", err_getstring(err));
289        exit(1);
290    }
291    printf("addr: %lx\n", SAFE_PMAP_ADDR_L);
292    test_region((uint32_t*)SAFE_PMAP_ADDR_L, LARGE_PAGE_SIZE, true, true);
293
294
295
296    printf("large area\n");
297    printf("average 4k: %lu, average 2m: %lu\n", mean4k, mean2m);
298    printf("minimal 4k: %lu, minimal 2m: %lu\n", min4k, min2m);
299    printf("maximal 4k: %lu, maximal 2m: %lu\n", max4k, max2m);
300    printf("random: average 4k: %lu, average 2m: %lu\n", mean4krand, mean2mrand);
301    printf("random:minimal 4k: %lu, minimal 2m: %lu\n", min4krand, min2mrand);
302    printf("random:maximal 4k: %lu, maximal 2m: %lu\n\n", max4krand, max2mrand);
303    printf("short area\n");
304    printf("average 4k: %lu, average 2m: %lu\n", mean4kshort, mean2mshort);
305    printf("minimal 4k: %lu, minimal 2m: %lu\n", min4kshort, min2mshort);
306    printf("maximal 4k: %lu, maximal 2m: %lu\n", max4kshort, max2mshort);
307    printf("random: average 4k: %lu, average 2m: %lu\n", mean4kshortrand, mean2mshortrand);
308    printf("random:minimal 4k: %lu, minimal 2m: %lu\n", min4kshortrand, min2mshortrand);
309    printf("random:maximal 4k: %lu, maximal 2m: %lu\n", max4kshortrand, max2mshortrand);
310    printf("exited successfully\n");
311    return 0;
312}
313