1/*
2 * Copyright 2016, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(D61_BSD)
11 */
12
13#include <autoconf.h>
14#ifdef CONFIG_REFOS_RUN_TESTS
15
16#include <stdlib.h>
17#include <string.h>
18#include <autoconf.h>
19#include <refos/test.h>
20#include "test.h"
21#include "test_addrspace.h"
22#include "../state.h"
23#include "../system/addrspace/vspace.h"
24#include <refos/test.h>
25
26/* ------------------------------- Page Dir module test ------------------------------- */
27
28int
29test_pd(void)
30{
31    test_start("page directory");
32    seL4_CPtr p[PD_MAX];
33    for (int i = 0; i < PD_MAX; i++) {
34        p[i] = pd_assign(&procServ.PDList).kpdObject;
35        test_assert(p[i] != 0);
36    }
37    for (int i = 0; i < PD_MAX; i++) {
38        pd_free(&procServ.PDList, p[i]);
39    }
40    for (int i = 0; i < 2; i++) {
41        p[i] = pd_assign(&procServ.PDList).kpdObject;
42        test_assert(p[i] != 0);
43    }
44    for (int i = 0; i < 2; i++) {
45        pd_free(&procServ.PDList, p[i]);
46    }
47    return test_success();
48}
49
50/* ------------------------------- VSpace module test ------------------------------- */
51
52int
53test_vspace(int run)
54{
55    test_start(run == 0 ? "vspace (run 1)" : "vspace (run 2)");
56    const int numTestVS = MIN(8, MIN((PID_MAX - 1), PD_MAX));
57    int error = -1;
58
59    struct vs_vspace vs[numTestVS];
60
61    /* Allocate ALL the vspaces. */
62    for (int i = 0; i < numTestVS; i++) {
63        uint32_t bogusPID = (i * 31337 % 1234);
64        error = vs_initialise(&vs[i], bogusPID);
65
66        test_assert(error == ESUCCESS);
67        test_assert(vs[i].magic == REFOS_VSPACE_MAGIC);
68        test_assert(vs[i].ref == 1);
69        test_assert(vs[i].pid == bogusPID);
70        test_assert(vs[i].kpd != 0);
71        test_assert(vs[i].cspace.capPtr != 0);
72        test_assert(vs[i].cspaceSize == REFOS_CSPACE_RADIX);
73    }
74
75    /* Ref every second one thrice. */
76    for (int i = 0; i < numTestVS; i+=2) {
77        vs_ref(&vs[i]);
78        vs_ref(&vs[i]);
79        vs_ref(&vs[i]);
80    }
81
82    /* Deref every VS. */
83    for (int i = 0; i < numTestVS; i++) {
84        vs_unref(&vs[i]);
85    }
86
87    /* Check that every second one is still alive. */
88    for (int i = 0; i < numTestVS; i++) {
89        if (i % 2 == 0) {
90            test_assert(vs[i].ref == 3);
91            test_assert(vs[i].magic == REFOS_VSPACE_MAGIC);
92            vs_unref(&vs[i]);
93            test_assert(vs[i].ref == 2);
94            test_assert(vs[i].magic == REFOS_VSPACE_MAGIC);
95            vs_unref(&vs[i]);
96            test_assert(vs[i].ref == 1);
97            test_assert(vs[i].magic == REFOS_VSPACE_MAGIC);
98            vs_unref(&vs[i]);
99            test_assert(vs[i].ref == 0);
100            test_assert(vs[i].magic != REFOS_VSPACE_MAGIC);
101        } else {
102            test_assert(vs[i].ref == 0);
103            test_assert(vs[i].magic != REFOS_VSPACE_MAGIC);
104        }
105    }
106
107    return test_success();
108}
109
110int
111test_vspace_mapping(void)
112{
113    test_start("vspace mapping");
114
115    /* Create a vspace for testing mapping. */
116    struct vs_vspace vs;
117    int error = vs_initialise(&vs, 31337);
118    test_assert(error == ESUCCESS);
119    test_assert(vs.magic == REFOS_VSPACE_MAGIC);
120
121    /* Create a memory segment window. */
122    const vaddr_t window = 0x10000;
123    const vaddr_t windowSize = 0x8000;
124    int windowID;
125    error = vs_create_window(&vs, window, windowSize, W_PERMISSION_WRITE | W_PERMISSION_READ,
126            true, &windowID);
127    test_assert(error == ESUCCESS);
128    test_assert(windowID != W_INVALID_WINID);
129
130    /* Allocate a frame to map. */
131    vka_object_t frame;
132    error = vka_alloc_frame(&procServ.vka, seL4_PageBits, &frame);
133    test_assert(error == ESUCCESS);
134    test_assert(frame.cptr != 0);
135
136    /* Try to map in some invalid spots. */
137    tvprintf("trying mapping into invalid spots...\n");
138    error = vs_map(&vs, 0x9A0, &frame.cptr, 1);
139    test_assert(error == EINVALIDWINDOW);
140    error = vs_map(&vs, window - 0x9A0, &frame.cptr, 1);
141    test_assert(error == EINVALIDWINDOW);
142    error = vs_map(&vs, window + windowSize + 0x1, &frame.cptr, 1);
143    test_assert(error == EINVALIDWINDOW);
144    error = vs_map(&vs, window + windowSize + 0x5123, &frame.cptr, 1);
145    test_assert(error == EINVALIDWINDOW);
146
147    /* Try to unmap from some invalid spots. */
148    tvprintf("trying unmapping from invalid spots...\n");
149    error = vs_unmap(&vs, window - 0x9A0, 1);
150    test_assert(error == EINVALIDWINDOW);
151    error = vs_unmap(&vs, window + windowSize + 0x423, 5);
152    test_assert(error == EINVALIDWINDOW);
153    error = vs_unmap(&vs, window, windowSize + 1);
154    test_assert(error == EINVALIDWINDOW);
155
156    /* Map the frame many times in all the valid spots. */
157    for (vaddr_t waddr = window; waddr < window + windowSize; waddr += (1 << seL4_PageBits)) {
158        tvprintf("trying mapping into valid spot 0x%x...\n", (uint32_t) waddr);
159        /* Map the frame. */
160        error = vs_map(&vs, waddr, &frame.cptr, 1);
161        test_assert(error == ESUCCESS);
162        /* Try to map frame here again. Should complain. */
163        error = vs_map(&vs, waddr, &frame.cptr, 1);
164        test_assert(error == EUNMAPFIRST);
165    }
166
167    /* Unmap and remap the frame many times in all the valid spots. */
168    for (vaddr_t waddr = window; waddr < window + windowSize; waddr += (1 << seL4_PageBits)) {
169        tvprintf("trying remapping into valid spot 0x%x...\n", (uint32_t) waddr);
170        /* Unmap the frame. */
171        error = vs_unmap(&vs, waddr, 1);
172        test_assert(error == ESUCCESS);
173        /* Remap the frame. */
174        error = vs_map(&vs, waddr, &frame.cptr, 1);
175        test_assert(error == ESUCCESS);
176    }
177
178    /* Clean up. Note that deleting the vspace should delete the created window. */
179    tvprintf("cleaning up everything in vspace...\n");
180    vs_unref(&vs);
181    test_assert(vs.magic != REFOS_VSPACE_MAGIC);
182    vka_free_object(&procServ.vka, &frame);
183
184    return test_success();
185}
186
187#endif /* CONFIG_REFOS_RUN_TESTS */