1241675Suqs/**
2241675Suqs * \file
3241675Suqs * \brief Test program for large page code
4241675Suqs */
5241675Suqs
6241675Suqs/*
7241675Suqs * Copyright (c) 2013, ETH Zurich.
8241675Suqs * All rights reserved.
9241675Suqs *
10241675Suqs * This file is distributed under the terms in the attached LICENSE file.
11241675Suqs * If you do not find this file, copies can be found by writing to:
12241675Suqs * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13241675Suqs */
14241675Suqs
15241675Suqs#include <barrelfish/barrelfish.h>
16241675Suqs#include <stdio.h>
17241675Suqs#include <stdlib.h>
18241675Suqs#include <string.h>
19241675Suqs#include <assert.h>
20241675Suqs#include <inttypes.h>
21241675Suqs#include <barrelfish/nameservice_client.h>
22241675Suqs#include <barrelfish/sys_debug.h>
23241675Suqs#include <bench/bench.h>
24241675Suqs
25241675Suqs#define SAFE_VADDR (genvaddr_t)(8ULL<<39)
26241675Suqs#define SAFE_PMAP_ADDR (genvaddr_t)(9ULL<<39)
27241675Suqs//0b 0000 0000 0000 0000 0000 0100 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000
28241675Suqs#define SAFE_PMAP_ADDR_L ((genvaddr_t) (12ULL<<39))
29241675Suqs// 40M
30241675Suqs#define DEFAULT_SIZE (30 * LARGE_PAGE_SIZE)
31241675Suqs
32241675Suqs
33241675Suqs#define RUN_COUNT 50
34241675Suqs
35241675Suqsunsigned long mean4k;
36241675Suqsunsigned long mean2m;
37241675Suqsunsigned long min4k;
38241675Suqsunsigned long min2m;
39241675Suqsunsigned long mean4krand;
40241675Suqsunsigned long mean2mrand;
41241675Suqsunsigned long min4krand;
42241675Suqsunsigned long min2mrand;
43241675Suqsunsigned long max4krand;
44241675Suqsunsigned long max2mrand;
45241675Suqsunsigned long max4k;
46241675Suqsunsigned long max2m;
47241675Suqs
48241675Suqsunsigned long mean4kshort;
49241675Suqsunsigned long mean2mshort;
50241675Suqsunsigned long mean4kshortrand;
51241675Suqsunsigned long mean2mshortrand;
52241675Suqsunsigned long min4kshort;
53241675Suqsunsigned long min2mshort;
54241675Suqsunsigned long min4kshortrand;
55241675Suqsunsigned long min2mshortrand;
56241675Suqsunsigned long max4kshort;
57241675Suqsunsigned long max2mshort;
58241675Suqsunsigned long max4kshortrand;
59241675Suqsunsigned long max2mshortrand;
60241675Suqs/*static paging_x86_64_flags_t PAGE_DEFAULT_ACCESS =
61241675Suqs    PTABLE_USER_SUPERVISOR |
62241675Suqs    PTABLE_EXECUTE_DISABLE |
63241675Suqs    PTABLE_READ_WRITE;
64241675Suqs */
65241675Suqsstatic vregion_flags_t PMAP_DEFAULT_ACCESS =
66241675Suqs    VREGION_FLAGS_READ_WRITE;
67241675Suqs
68241675Suqsstatic void test_region(uint32_t *buf, size_t size, bool large, bool area)
69241675Suqs{
70241675Suqs    cycles_t runs[RUN_COUNT];
71241675Suqs    cycles_t start, end;
72241675Suqs    uint64_t mean = 0;
73241675Suqs    unsigned long min = 0;
74241675Suqs    unsigned long max = 0;
75241675Suqs    printf("base address: %lx\n", (uint64_t) buf);
76241675Suqs
77241675Suqs    //sequential access
78241675Suqs    for (int j = 0; j < RUN_COUNT; j++) {
79241675Suqs
80241675Suqs        start = bench_tsc()/1000;
81241675Suqs        for (unsigned long i = 0; i < size; i+=4) {
82241675Suqs
83241675Suqs            buf[i/4] = i;
84241675Suqs        }
85241675Suqs        for (unsigned long i = 0; i < size; i+=4) {
86241675Suqs            assert(buf[i/4] == i);
87241675Suqs        }
88241675Suqs        end = bench_tsc()/1000;
89241675Suqs        runs[j] = end-start;
90241675Suqs        mean += (unsigned int) runs[j];
91241675Suqs        if (runs[j] < min || j == 0) {min = runs[j];}
92241675Suqs        if (runs[j] > max) {max = runs[j];}
93241675Suqs        printf("run: %u, cycles: %u\n", j, (unsigned int) runs[j]);
94241675Suqs    }
95241675Suqs    mean = mean/RUN_COUNT;
96241675Suqs    printf("\naverage cycles to write the whole area: %u\n", (unsigned int) mean);
97241675Suqs    if(!large && !area) {
98241675Suqs        mean4k = mean;
99241675Suqs        min4k = min;
100241675Suqs        max4k = max;
101241675Suqs    }
102241675Suqs    else if (large && !area) {
103241675Suqs        mean2m = mean;
104241675Suqs        min2m = min;
105241675Suqs        max2m = max;
106241675Suqs    }
107241675Suqs    else if (!large && area) {
108241675Suqs        mean4kshort = mean;
109241675Suqs        min4kshort = min;
110241675Suqs        max4kshort = max;
111241675Suqs    } else {
112241675Suqs        mean2mshort = mean;
113241675Suqs        min2mshort = min;
114241675Suqs        max2mshort = max;
115241675Suqs    }
116241675Suqs
117241675Suqs    //random access
118241675Suqs    //generate 1M random number array
119241675Suqs    unsigned int* addrs;
120241675Suqs    min = 0;
121241675Suqs    max = 0;
122241675Suqs    mean = 0;
123241675Suqs    addrs = malloc(2000000*sizeof(unsigned int));
124241675Suqs    printf("malloc'd\n");
125241675Suqs    for (int i = 0; i<2000000; i++)
126241675Suqs    {
127241675Suqs        addrs[i] = (rand() % (size/4));
128241675Suqs    }
129241675Suqs    printf("randomised\n");
130241675Suqs    for (int j = 0; j < RUN_COUNT; j++) {
131241675Suqs
132241675Suqs        start = bench_tsc()/1000;
133241675Suqs        for (int i = 0; i < 2000000; i++) {
134241675Suqs            buf[addrs[i]] = addrs[i];
135241675Suqs        }
136241675Suqs        for (unsigned long i = 0; i < 2000000; i++) {
137241675Suqs            assert(buf[addrs[i]] == addrs[i]);
138241675Suqs        }
139241675Suqs        end = bench_tsc()/1000;
140241675Suqs        runs[j] = end-start;
141241675Suqs        mean += (unsigned int) runs[j];
142241675Suqs        if (runs[j] < min || j == 0) {min = runs[j];}
143241675Suqs        if (runs[j] > max) {max = runs[j];}
144241675Suqs        printf("run: %u, cycles: %u\n", j, (unsigned int) runs[j]);
145241675Suqs    }
146241675Suqs    mean = mean/RUN_COUNT;
147241675Suqs    printf("\naverage cycles to write the whole area randomly: %u\n", (unsigned int) mean);
148241675Suqs    if(!large && !area) {
149241675Suqs        mean4krand = mean;
150241675Suqs        min4krand = min;
151241675Suqs        max4krand = max;
152241675Suqs    }
153241675Suqs    else if (large && !area){
154241675Suqs        mean2mrand = mean;
155241675Suqs        min2mrand = min;
156241675Suqs        max2mrand = max;
157241675Suqs    }else if (!large && area) {
158241675Suqs        mean4kshortrand = mean;
159241675Suqs        min4kshortrand = min;
160241675Suqs        max4kshortrand = max;
161241675Suqs    } else {
162241675Suqs        mean2mshortrand = mean;
163241675Suqs        min2mshortrand = min;
164241675Suqs        max2mshortrand = max;
165241675Suqs    }
166241675Suqs
167241675Suqs}
168241675Suqs
169241675Suqsint main(void)
170241675Suqs{
171241675Suqs    struct capref frame;
172241675Suqs    size_t bytes = DEFAULT_SIZE;
173241675Suqs    errval_t err;
174241675Suqs    mean4k = 0;
175241675Suqs    mean2m = 0;
176241675Suqs    genvaddr_t address;
177241675Suqs
178241675Suqs
179241675Suqs    //normal pages via pmap interface
180241675Suqs    printf("\nstart 4k map with pmap\n");
181241675Suqs    err = frame_alloc(&frame, bytes, &bytes);
182241675Suqs    if (err_is_fail(err))
183241675Suqs    {
184241675Suqs        printf("error in frame_alloc: %s\n", err_getstring(err));
185241675Suqs        exit(1);
186241675Suqs    }
187241675Suqs    assert(bytes >= DEFAULT_SIZE);
188241675Suqs    printf("    get pmap\n");
189241675Suqs    struct pmap *pmap = get_current_pmap();
190241675Suqs
191241675Suqs    printf("    obtain address\n");
192241675Suqs    err = pmap->f.determine_addr_raw(pmap, bytes, BASE_PAGE_SIZE, &address);
193241675Suqs    if (err_is_fail(err))
194241675Suqs    {
195241675Suqs        printf("error in determine_addr_raw: %s\n", err_getstring(err));
196241675Suqs        exit(1);
197241675Suqs    }
198241675Suqs
199241675Suqs    printf("    map\n");
200241675Suqs    err = pmap->f.map(pmap, address, frame, 0, bytes, PMAP_DEFAULT_ACCESS, NULL, &bytes);
201241675Suqs    if (err_is_fail(err))
202241675Suqs    {
203241675Suqs        printf("error in pmap: %s\n", err_getstring(err));
204241675Suqs        exit(1);
205241675Suqs    }
206241675Suqs    printf("addr: %lx\n", address);
207241675Suqs    test_region((uint32_t*)address, DEFAULT_SIZE, false, false);
208241675Suqs
209241675Suqs    printf("\tunmap\n");
210241675Suqs    err = pmap->f.unmap(pmap, address, bytes, NULL);
211241675Suqs    if (err_is_fail(err))
212241675Suqs    {
213241675Suqs        printf("error in unmap: %s\n", err_getstring(err));
214241675Suqs        exit(1);
215241675Suqs    }
216241675Suqs
217241675Suqs    //large page via pmap interface
218241675Suqs    printf("start 2m map with pmap\n");
219241675Suqs    bytes = DEFAULT_SIZE;
220241675Suqs    struct capref frame2;
221241675Suqs    err = frame_alloc(&frame2, bytes, &bytes);
222241675Suqs    if (err_is_fail(err))
223241675Suqs    {
224241675Suqs        printf("error in frame_alloc: %s\n", err_getstring(err));
225241675Suqs        exit(1);
226241675Suqs    }
227241675Suqs    assert(bytes >= DEFAULT_SIZE);
228241675Suqs    pmap = get_current_pmap();
229241675Suqs
230241675Suqs    printf("determine address\n");
231241675Suqs    err = pmap->f.determine_addr_raw(pmap, bytes, LARGE_PAGE_SIZE, &address);
232241675Suqs    if (err_is_fail(err))
233241675Suqs    {
234241675Suqs        printf("error in determine_addr_raw: %s\n", err_getstring(err));
235241675Suqs        exit(1);
236241675Suqs    }
237241675Suqs
238241675Suqs    printf("map\n");
239241675Suqs    err = pmap->f.map(pmap, address, frame, 0, bytes, PMAP_DEFAULT_ACCESS | 0x0100, NULL, &bytes);
240241675Suqs    if (err_is_fail(err))
241241675Suqs    {
242241675Suqs        printf("error in pmap: %s\n", err_getstring(err));
243241675Suqs        exit(1);
244241675Suqs    }
245241675Suqs    printf("addr: %lx\n", address);
246241675Suqs    test_region((uint32_t*)address, DEFAULT_SIZE, true, false);
247241675Suqs
248241675Suqs    err = pmap->f.unmap(pmap, address, bytes, NULL);
249241675Suqs    if (err_is_fail(err))
250241675Suqs    {
251241675Suqs        printf("error in unmap: %s\n", err_getstring(err));
252241675Suqs        exit(1);
253241675Suqs    }
254241675Suqs    //small area 4k
255241675Suqs    bytes = LARGE_PAGE_SIZE;
256241675Suqs    err = frame_alloc(&frame, bytes, &bytes);
257241675Suqs    if (err_is_fail(err))
258241675Suqs    {
259241675Suqs        printf("error in frame_alloc: %s\n", err_getstring(err));
260241675Suqs        exit(1);
261241675Suqs    }
262241675Suqs    assert(bytes >= LARGE_PAGE_SIZE);
263241675Suqs    pmap = get_current_pmap();
264241675Suqs    err = pmap->f.map(pmap, SAFE_PMAP_ADDR, frame, 0, bytes, PMAP_DEFAULT_ACCESS, NULL, &bytes);
265241675Suqs    if (err_is_fail(err))
266241675Suqs    {
267241675Suqs        printf("error in pmap small 4k\n");
268241675Suqs        exit(1);
269241675Suqs    }
270241675Suqs    test_region((uint32_t*) SAFE_PMAP_ADDR, LARGE_PAGE_SIZE, false, true);
271241675Suqs
272241675Suqs    //small area 2m
273241675Suqs    bytes = LARGE_PAGE_SIZE;
274241675Suqs    err = frame_alloc(&frame, bytes, &bytes);
275241675Suqs    if (err_is_fail(err))
276241675Suqs    {
277241675Suqs        printf("error in frame_alloc: %s\n", err_getstring(err));
278241675Suqs        exit(1);
279241675Suqs    }
280241675Suqs    assert(bytes >= LARGE_PAGE_SIZE);
281241675Suqs    pmap = get_current_pmap();
282241675Suqs
283241675Suqs    printf("map\n");
284241675Suqs    err = pmap->f.map(pmap, SAFE_PMAP_ADDR_L, frame, 0, bytes, PMAP_DEFAULT_ACCESS | 0x0100, NULL, &bytes);
285241675Suqs    if (err_is_fail(err))
286241675Suqs    {
287241675Suqs        printf("error in pmap: %s\n", err_getstring(err));
288241675Suqs        exit(1);
289241675Suqs    }
290241675Suqs    printf("addr: %lx\n", SAFE_PMAP_ADDR_L);
291241675Suqs    test_region((uint32_t*)SAFE_PMAP_ADDR_L, LARGE_PAGE_SIZE, true, true);
292241675Suqs
293241675Suqs
294241675Suqs
295241675Suqs    printf("large area\n");
296241675Suqs    printf("average 4k: %lu, average 2m: %lu\n", mean4k, mean2m);
297241675Suqs    printf("minimal 4k: %lu, minimal 2m: %lu\n", min4k, min2m);
298241675Suqs    printf("maximal 4k: %lu, maximal 2m: %lu\n", max4k, max2m);
299241675Suqs    printf("random: average 4k: %lu, average 2m: %lu\n", mean4krand, mean2mrand);
300241675Suqs    printf("random:minimal 4k: %lu, minimal 2m: %lu\n", min4krand, min2mrand);
301241675Suqs    printf("random:maximal 4k: %lu, maximal 2m: %lu\n\n", max4krand, max2mrand);
302241675Suqs    printf("short area\n");
303241675Suqs    printf("average 4k: %lu, average 2m: %lu\n", mean4kshort, mean2mshort);
304241675Suqs    printf("minimal 4k: %lu, minimal 2m: %lu\n", min4kshort, min2mshort);
305241675Suqs    printf("maximal 4k: %lu, maximal 2m: %lu\n", max4kshort, max2mshort);
306241675Suqs    printf("random: average 4k: %lu, average 2m: %lu\n", mean4kshortrand, mean2mshortrand);
307241675Suqs    printf("random:minimal 4k: %lu, minimal 2m: %lu\n", min4kshortrand, min2mshortrand);
308241675Suqs    printf("random:maximal 4k: %lu, maximal 2m: %lu\n", max4kshortrand, max2mshortrand);
309241675Suqs    printf("exited successfully\n");
310241675Suqs    return 0;
311241675Suqs}
312241675Suqs