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