1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker * Copyright (c) 2015, Google Inc. All rights reserved
3*344aa361SAndroid Build Coastguard Worker *
4*344aa361SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining
5*344aa361SAndroid Build Coastguard Worker * a copy of this software and associated documentation files
6*344aa361SAndroid Build Coastguard Worker * (the "Software"), to deal in the Software without restriction,
7*344aa361SAndroid Build Coastguard Worker * including without limitation the rights to use, copy, modify, merge,
8*344aa361SAndroid Build Coastguard Worker * publish, distribute, sublicense, and/or sell copies of the Software,
9*344aa361SAndroid Build Coastguard Worker * and to permit persons to whom the Software is furnished to do so,
10*344aa361SAndroid Build Coastguard Worker * subject to the following conditions:
11*344aa361SAndroid Build Coastguard Worker *
12*344aa361SAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be
13*344aa361SAndroid Build Coastguard Worker * included in all copies or substantial portions of the Software.
14*344aa361SAndroid Build Coastguard Worker *
15*344aa361SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*344aa361SAndroid Build Coastguard Worker * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*344aa361SAndroid Build Coastguard Worker * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18*344aa361SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*344aa361SAndroid Build Coastguard Worker * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20*344aa361SAndroid Build Coastguard Worker * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21*344aa361SAndroid Build Coastguard Worker * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22*344aa361SAndroid Build Coastguard Worker */
23*344aa361SAndroid Build Coastguard Worker
24*344aa361SAndroid Build Coastguard Worker #include <err.h>
25*344aa361SAndroid Build Coastguard Worker #include <kernel/thread.h>
26*344aa361SAndroid Build Coastguard Worker #include <kernel/vm.h>
27*344aa361SAndroid Build Coastguard Worker #include <lib/mmutest/mmutest.h>
28*344aa361SAndroid Build Coastguard Worker #include <lib/unittest/unittest.h>
29*344aa361SAndroid Build Coastguard Worker #include <lk/init.h>
30*344aa361SAndroid Build Coastguard Worker #include <pow2.h>
31*344aa361SAndroid Build Coastguard Worker #include <stdbool.h>
32*344aa361SAndroid Build Coastguard Worker #include <stdio.h>
33*344aa361SAndroid Build Coastguard Worker #include <string.h>
34*344aa361SAndroid Build Coastguard Worker
35*344aa361SAndroid Build Coastguard Worker /*
36*344aa361SAndroid Build Coastguard Worker * These below declarations are made to avoid issues with CFI
37*344aa361SAndroid Build Coastguard Worker * while copying heap allocated method, this is to reduce the
38*344aa361SAndroid Build Coastguard Worker * probability of it breaking in future toolchain versions
39*344aa361SAndroid Build Coastguard Worker */
40*344aa361SAndroid Build Coastguard Worker extern uint8_t mmutest_arch_nop[];
41*344aa361SAndroid Build Coastguard Worker extern uint8_t mmutest_arch_nop_end[];
42*344aa361SAndroid Build Coastguard Worker
mmutest_run_in_thread(const char * thread_name,int (* func)(void * arg),void * arg)43*344aa361SAndroid Build Coastguard Worker static int mmutest_run_in_thread(const char* thread_name,
44*344aa361SAndroid Build Coastguard Worker int (*func)(void* arg),
45*344aa361SAndroid Build Coastguard Worker void* arg) {
46*344aa361SAndroid Build Coastguard Worker int ret;
47*344aa361SAndroid Build Coastguard Worker int thread_ret;
48*344aa361SAndroid Build Coastguard Worker struct thread* thread;
49*344aa361SAndroid Build Coastguard Worker uint8_t* canary;
50*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace = vmm_get_kernel_aspace();
51*344aa361SAndroid Build Coastguard Worker
52*344aa361SAndroid Build Coastguard Worker thread = thread_create("mmu_test_execute", func, arg, DEFAULT_PRIORITY,
53*344aa361SAndroid Build Coastguard Worker DEFAULT_STACK_SIZE);
54*344aa361SAndroid Build Coastguard Worker if (!thread) {
55*344aa361SAndroid Build Coastguard Worker return ERR_NO_MEMORY;
56*344aa361SAndroid Build Coastguard Worker }
57*344aa361SAndroid Build Coastguard Worker
58*344aa361SAndroid Build Coastguard Worker canary = (uint8_t*)thread->stack - PAGE_SIZE * 2;
59*344aa361SAndroid Build Coastguard Worker
60*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "canary", PAGE_SIZE, (void**)&canary, 0,
61*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
62*344aa361SAndroid Build Coastguard Worker if (ret) {
63*344aa361SAndroid Build Coastguard Worker canary = NULL;
64*344aa361SAndroid Build Coastguard Worker } else {
65*344aa361SAndroid Build Coastguard Worker memset(canary, 0x55, PAGE_SIZE);
66*344aa361SAndroid Build Coastguard Worker }
67*344aa361SAndroid Build Coastguard Worker
68*344aa361SAndroid Build Coastguard Worker thread_set_flag_exit_on_panic(thread, true);
69*344aa361SAndroid Build Coastguard Worker ret = thread_resume(thread);
70*344aa361SAndroid Build Coastguard Worker if (ret) {
71*344aa361SAndroid Build Coastguard Worker return ret;
72*344aa361SAndroid Build Coastguard Worker }
73*344aa361SAndroid Build Coastguard Worker
74*344aa361SAndroid Build Coastguard Worker ret = thread_join(thread, &thread_ret, INFINITE_TIME);
75*344aa361SAndroid Build Coastguard Worker if (ret) {
76*344aa361SAndroid Build Coastguard Worker return ret;
77*344aa361SAndroid Build Coastguard Worker }
78*344aa361SAndroid Build Coastguard Worker
79*344aa361SAndroid Build Coastguard Worker if (canary) {
80*344aa361SAndroid Build Coastguard Worker size_t i;
81*344aa361SAndroid Build Coastguard Worker for (i = 0; i < PAGE_SIZE; i++) {
82*344aa361SAndroid Build Coastguard Worker if (canary[i] != 0x55)
83*344aa361SAndroid Build Coastguard Worker break;
84*344aa361SAndroid Build Coastguard Worker }
85*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(i, PAGE_SIZE, "memory below stack corrupted\n");
86*344aa361SAndroid Build Coastguard Worker
87*344aa361SAndroid Build Coastguard Worker vmm_free_region(aspace, (vaddr_t)canary);
88*344aa361SAndroid Build Coastguard Worker }
89*344aa361SAndroid Build Coastguard Worker
90*344aa361SAndroid Build Coastguard Worker return thread_ret;
91*344aa361SAndroid Build Coastguard Worker }
92*344aa361SAndroid Build Coastguard Worker
mmutest_alloc(void ** ptrp,uint arch_mmu_flags)93*344aa361SAndroid Build Coastguard Worker static int mmutest_alloc(void** ptrp, uint arch_mmu_flags) {
94*344aa361SAndroid Build Coastguard Worker int ret;
95*344aa361SAndroid Build Coastguard Worker uint arch_mmu_flags_query = ~0U;
96*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace = vmm_get_kernel_aspace();
97*344aa361SAndroid Build Coastguard Worker
98*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc_contiguous(aspace, "mmutest", PAGE_SIZE, ptrp, 0, 0,
99*344aa361SAndroid Build Coastguard Worker arch_mmu_flags);
100*344aa361SAndroid Build Coastguard Worker
101*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret, "vmm_alloc_contiguous failed\n");
102*344aa361SAndroid Build Coastguard Worker if (ret) {
103*344aa361SAndroid Build Coastguard Worker return ret;
104*344aa361SAndroid Build Coastguard Worker }
105*344aa361SAndroid Build Coastguard Worker
106*344aa361SAndroid Build Coastguard Worker arch_mmu_query(&aspace->arch_aspace, (vaddr_t)*ptrp, NULL,
107*344aa361SAndroid Build Coastguard Worker &arch_mmu_flags_query);
108*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(arch_mmu_flags_query, arch_mmu_flags,
109*344aa361SAndroid Build Coastguard Worker "arch_mmu_query, 0x%x, does not match requested flags, 0x%x\n",
110*344aa361SAndroid Build Coastguard Worker arch_mmu_flags_query, arch_mmu_flags);
111*344aa361SAndroid Build Coastguard Worker return 0;
112*344aa361SAndroid Build Coastguard Worker }
113*344aa361SAndroid Build Coastguard Worker
mmutest_vmm_store_uint32(uint arch_mmu_flags,bool user)114*344aa361SAndroid Build Coastguard Worker static int mmutest_vmm_store_uint32(uint arch_mmu_flags, bool user) {
115*344aa361SAndroid Build Coastguard Worker int ret;
116*344aa361SAndroid Build Coastguard Worker void* ptr;
117*344aa361SAndroid Build Coastguard Worker
118*344aa361SAndroid Build Coastguard Worker ret = mmutest_alloc(&ptr, arch_mmu_flags);
119*344aa361SAndroid Build Coastguard Worker if (ret) {
120*344aa361SAndroid Build Coastguard Worker return ret;
121*344aa361SAndroid Build Coastguard Worker }
122*344aa361SAndroid Build Coastguard Worker
123*344aa361SAndroid Build Coastguard Worker ret = mmutest_arch_store_uint32(ptr, user);
124*344aa361SAndroid Build Coastguard Worker
125*344aa361SAndroid Build Coastguard Worker vmm_free_region(vmm_get_kernel_aspace(), (vaddr_t)ptr);
126*344aa361SAndroid Build Coastguard Worker return ret;
127*344aa361SAndroid Build Coastguard Worker }
128*344aa361SAndroid Build Coastguard Worker
mmutest_vmm_store_uint32_kernel(uint arch_mmu_flags)129*344aa361SAndroid Build Coastguard Worker static int mmutest_vmm_store_uint32_kernel(uint arch_mmu_flags) {
130*344aa361SAndroid Build Coastguard Worker return mmutest_vmm_store_uint32(arch_mmu_flags, false);
131*344aa361SAndroid Build Coastguard Worker }
132*344aa361SAndroid Build Coastguard Worker
mmutest_vmm_store_uint32_user(uint arch_mmu_flags)133*344aa361SAndroid Build Coastguard Worker static int mmutest_vmm_store_uint32_user(uint arch_mmu_flags) {
134*344aa361SAndroid Build Coastguard Worker return mmutest_vmm_store_uint32(arch_mmu_flags, true);
135*344aa361SAndroid Build Coastguard Worker }
136*344aa361SAndroid Build Coastguard Worker
137*344aa361SAndroid Build Coastguard Worker /*
138*344aa361SAndroid Build Coastguard Worker * disabling the cfi-icall as a workaround to avoid cfi check
139*344aa361SAndroid Build Coastguard Worker * failure errors while calling heap allocated functions
140*344aa361SAndroid Build Coastguard Worker */
mmu_test_execute_thread_func(void * arg)141*344aa361SAndroid Build Coastguard Worker static int mmu_test_execute_thread_func(void* arg)
142*344aa361SAndroid Build Coastguard Worker __attribute__((no_sanitize("cfi-icall"))) {
143*344aa361SAndroid Build Coastguard Worker void (*func)(void) = arg;
144*344aa361SAndroid Build Coastguard Worker func();
145*344aa361SAndroid Build Coastguard Worker return 0;
146*344aa361SAndroid Build Coastguard Worker }
147*344aa361SAndroid Build Coastguard Worker
148*344aa361SAndroid Build Coastguard Worker /*
149*344aa361SAndroid Build Coastguard Worker * Executes 'mmutest_arch_nop' code from a memory mapped with the passed flags.
150*344aa361SAndroid Build Coastguard Worker * To simplify test writing, this first creates a writable allocation and vmm
151*344aa361SAndroid Build Coastguard Worker * mapping before making a second mapping with the requested arch_mmu_flags and
152*344aa361SAndroid Build Coastguard Worker * executing the test thread. This avoids violating W^X semantics which are
153*344aa361SAndroid Build Coastguard Worker * enforced on some architectures.
154*344aa361SAndroid Build Coastguard Worker */
mmu_test_execute(uint arch_mmu_flags)155*344aa361SAndroid Build Coastguard Worker static int mmu_test_execute(uint arch_mmu_flags) {
156*344aa361SAndroid Build Coastguard Worker const size_t len = mmutest_arch_nop_end - mmutest_arch_nop;
157*344aa361SAndroid Build Coastguard Worker const size_t alloc_len = round_up(len, PAGE_SIZE);
158*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace = vmm_get_kernel_aspace();
159*344aa361SAndroid Build Coastguard Worker struct obj_ref vmm_obj_ref = OBJ_REF_INITIAL_VALUE(vmm_obj_ref);
160*344aa361SAndroid Build Coastguard Worker struct vmm_obj* vmm_obj = NULL;
161*344aa361SAndroid Build Coastguard Worker void *ptr = NULL, *execute_ptr = NULL;
162*344aa361SAndroid Build Coastguard Worker uint arch_mmu_flags_query;
163*344aa361SAndroid Build Coastguard Worker int ret;
164*344aa361SAndroid Build Coastguard Worker
165*344aa361SAndroid Build Coastguard Worker /* Allocate pages to hold the test code and create writable mapping */
166*344aa361SAndroid Build Coastguard Worker ret = pmm_alloc(&vmm_obj, &vmm_obj_ref, alloc_len / PAGE_SIZE,
167*344aa361SAndroid Build Coastguard Worker PMM_ALLOC_FLAG_CONTIGUOUS, 0);
168*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret, "pmm_alloc failed\n");
169*344aa361SAndroid Build Coastguard Worker
170*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc_obj(aspace, "mmutest_w", vmm_obj, 0, alloc_len, &ptr, 0, 0,
171*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
172*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret, "vmm_alloc_obj failed\n");
173*344aa361SAndroid Build Coastguard Worker
174*344aa361SAndroid Build Coastguard Worker /* Populate the memory */
175*344aa361SAndroid Build Coastguard Worker memcpy(ptr, mmutest_arch_nop, len);
176*344aa361SAndroid Build Coastguard Worker arch_sync_cache_range((addr_t)ptr, len);
177*344aa361SAndroid Build Coastguard Worker
178*344aa361SAndroid Build Coastguard Worker /* Now create a new mapping with the desired test arch_mmu_flags */
179*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc_obj(aspace, "mmutest_flags", vmm_obj, 0, alloc_len,
180*344aa361SAndroid Build Coastguard Worker &execute_ptr, 0, 0, arch_mmu_flags);
181*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret, "vmm_alloc_obj failed\n");
182*344aa361SAndroid Build Coastguard Worker
183*344aa361SAndroid Build Coastguard Worker /* Ensure the new mapping reflects the initialised memory */
184*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(0, memcmp(ptr, execute_ptr, alloc_len),
185*344aa361SAndroid Build Coastguard Worker "mapping contents mismatch\n");
186*344aa361SAndroid Build Coastguard Worker
187*344aa361SAndroid Build Coastguard Worker /* Double check the flags are as expected on the new memory */
188*344aa361SAndroid Build Coastguard Worker arch_mmu_query(&aspace->arch_aspace, (vaddr_t)execute_ptr, NULL,
189*344aa361SAndroid Build Coastguard Worker &arch_mmu_flags_query);
190*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(arch_mmu_flags_query, arch_mmu_flags,
191*344aa361SAndroid Build Coastguard Worker "arch_mmu_query, 0x%x, does not match requested flags, 0x%x\n",
192*344aa361SAndroid Build Coastguard Worker arch_mmu_flags_query, arch_mmu_flags);
193*344aa361SAndroid Build Coastguard Worker
194*344aa361SAndroid Build Coastguard Worker /* Execute the test */
195*344aa361SAndroid Build Coastguard Worker ret = mmutest_run_in_thread("mmu_test_execute",
196*344aa361SAndroid Build Coastguard Worker mmu_test_execute_thread_func, execute_ptr);
197*344aa361SAndroid Build Coastguard Worker
198*344aa361SAndroid Build Coastguard Worker test_abort:
199*344aa361SAndroid Build Coastguard Worker if (execute_ptr) {
200*344aa361SAndroid Build Coastguard Worker int tmp_ret = vmm_free_region(aspace, (vaddr_t)execute_ptr);
201*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, tmp_ret, "vmm_free_region failed\n");
202*344aa361SAndroid Build Coastguard Worker }
203*344aa361SAndroid Build Coastguard Worker
204*344aa361SAndroid Build Coastguard Worker if (ptr) {
205*344aa361SAndroid Build Coastguard Worker int tmp_ret = vmm_free_region(aspace, (vaddr_t)ptr);
206*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, tmp_ret, "vmm_free_region failed\n");
207*344aa361SAndroid Build Coastguard Worker }
208*344aa361SAndroid Build Coastguard Worker
209*344aa361SAndroid Build Coastguard Worker if (vmm_obj) {
210*344aa361SAndroid Build Coastguard Worker vmm_obj_del_ref(vmm_obj, &vmm_obj_ref);
211*344aa361SAndroid Build Coastguard Worker }
212*344aa361SAndroid Build Coastguard Worker
213*344aa361SAndroid Build Coastguard Worker return ret;
214*344aa361SAndroid Build Coastguard Worker }
215*344aa361SAndroid Build Coastguard Worker
216*344aa361SAndroid Build Coastguard Worker /* Skip kernel permission tests on ARM as it uses 1MB mappings */
217*344aa361SAndroid Build Coastguard Worker #if ARCH_ARM
218*344aa361SAndroid Build Coastguard Worker #define DISABLED_ON_ARM_NAME(name) DISABLED_##name
219*344aa361SAndroid Build Coastguard Worker #else
220*344aa361SAndroid Build Coastguard Worker #define DISABLED_ON_ARM_NAME(name) name
221*344aa361SAndroid Build Coastguard Worker #endif
222*344aa361SAndroid Build Coastguard Worker
223*344aa361SAndroid Build Coastguard Worker typedef struct {
224*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace;
225*344aa361SAndroid Build Coastguard Worker size_t allocation_size;
226*344aa361SAndroid Build Coastguard Worker } mmutestvmm_t;
227*344aa361SAndroid Build Coastguard Worker
TEST_F_SETUP(mmutestvmm)228*344aa361SAndroid Build Coastguard Worker TEST_F_SETUP(mmutestvmm) {
229*344aa361SAndroid Build Coastguard Worker int ret;
230*344aa361SAndroid Build Coastguard Worker const void* const* params = GetParam();
231*344aa361SAndroid Build Coastguard Worker const size_t* allocation_size_p = params[0];
232*344aa361SAndroid Build Coastguard Worker const bool* is_kernel_aspace = params[1];
233*344aa361SAndroid Build Coastguard Worker
234*344aa361SAndroid Build Coastguard Worker _state->allocation_size = *allocation_size_p;
235*344aa361SAndroid Build Coastguard Worker if (*is_kernel_aspace) {
236*344aa361SAndroid Build Coastguard Worker _state->aspace = vmm_get_kernel_aspace();
237*344aa361SAndroid Build Coastguard Worker } else {
238*344aa361SAndroid Build Coastguard Worker ret = vmm_create_aspace(&_state->aspace, "mmutestvmm", 0);
239*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
240*344aa361SAndroid Build Coastguard Worker }
241*344aa361SAndroid Build Coastguard Worker
242*344aa361SAndroid Build Coastguard Worker ASSERT_GE(_state->allocation_size, PAGE_SIZE);
243*344aa361SAndroid Build Coastguard Worker ASSERT_LT(_state->allocation_size, _state->aspace->size);
244*344aa361SAndroid Build Coastguard Worker test_abort:;
245*344aa361SAndroid Build Coastguard Worker }
246*344aa361SAndroid Build Coastguard Worker
247*344aa361SAndroid Build Coastguard Worker static size_t mmutestvmm_allocation_sizes[] = {
248*344aa361SAndroid Build Coastguard Worker PAGE_SIZE,
249*344aa361SAndroid Build Coastguard Worker 2 * 1024 * 1024, /* large enough to use section/block mapping on arm */
250*344aa361SAndroid Build Coastguard Worker };
251*344aa361SAndroid Build Coastguard Worker
TEST_F_TEARDOWN(mmutestvmm)252*344aa361SAndroid Build Coastguard Worker TEST_F_TEARDOWN(mmutestvmm) {
253*344aa361SAndroid Build Coastguard Worker if (!(_state->aspace->flags & VMM_ASPACE_FLAG_KERNEL)) {
254*344aa361SAndroid Build Coastguard Worker vmm_free_aspace(_state->aspace);
255*344aa361SAndroid Build Coastguard Worker }
256*344aa361SAndroid Build Coastguard Worker }
257*344aa361SAndroid Build Coastguard Worker
258*344aa361SAndroid Build Coastguard Worker /* Smoke test for vmm_alloc */
TEST_P(mmutestvmm,vmm_alloc)259*344aa361SAndroid Build Coastguard Worker TEST_P(mmutestvmm, vmm_alloc) {
260*344aa361SAndroid Build Coastguard Worker int ret;
261*344aa361SAndroid Build Coastguard Worker void* ptr = NULL;
262*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "mmutest", _state->allocation_size, &ptr, 0,
263*344aa361SAndroid Build Coastguard Worker 0, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
264*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret);
265*344aa361SAndroid Build Coastguard Worker EXPECT_NE(NULL, ptr);
266*344aa361SAndroid Build Coastguard Worker ret = vmm_free_region(_state->aspace, (vaddr_t)ptr);
267*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret, "vmm_free_region failed\n");
268*344aa361SAndroid Build Coastguard Worker }
269*344aa361SAndroid Build Coastguard Worker
270*344aa361SAndroid Build Coastguard Worker /* Smoke test for vmm_alloc_contiguous */
TEST_P(mmutestvmm,vmm_alloc_contiguous)271*344aa361SAndroid Build Coastguard Worker TEST_P(mmutestvmm, vmm_alloc_contiguous) {
272*344aa361SAndroid Build Coastguard Worker int ret;
273*344aa361SAndroid Build Coastguard Worker void* ptr = NULL;
274*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc_contiguous(_state->aspace, "mmutest",
275*344aa361SAndroid Build Coastguard Worker _state->allocation_size, &ptr,
276*344aa361SAndroid Build Coastguard Worker log2_uint(_state->allocation_size), 0,
277*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
278*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret);
279*344aa361SAndroid Build Coastguard Worker EXPECT_NE(NULL, ptr);
280*344aa361SAndroid Build Coastguard Worker ret = vmm_free_region(_state->aspace, (vaddr_t)ptr);
281*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret, "vmm_free_region failed\n");
282*344aa361SAndroid Build Coastguard Worker }
283*344aa361SAndroid Build Coastguard Worker
284*344aa361SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(
285*344aa361SAndroid Build Coastguard Worker allocationsize,
286*344aa361SAndroid Build Coastguard Worker mmutestvmm,
287*344aa361SAndroid Build Coastguard Worker testing_Combine(testing_ValuesIn(mmutestvmm_allocation_sizes),
288*344aa361SAndroid Build Coastguard Worker /* user(false) and kernel(true) aspaces */
289*344aa361SAndroid Build Coastguard Worker testing_Bool()));
290*344aa361SAndroid Build Coastguard Worker
mmutest_panic_thread_func(void * _unused)291*344aa361SAndroid Build Coastguard Worker static int mmutest_panic_thread_func(void* _unused) {
292*344aa361SAndroid Build Coastguard Worker panic("mmutest-panic");
293*344aa361SAndroid Build Coastguard Worker }
294*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,panic)295*344aa361SAndroid Build Coastguard Worker TEST(mmutest, panic) {
296*344aa361SAndroid Build Coastguard Worker /* Check thread_set_flag_exit_on_panic feature needed by other tests */
297*344aa361SAndroid Build Coastguard Worker int ret = mmutest_run_in_thread("mmutest-panic", mmutest_panic_thread_func,
298*344aa361SAndroid Build Coastguard Worker NULL);
299*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_FAULT, ret);
300*344aa361SAndroid Build Coastguard Worker }
301*344aa361SAndroid Build Coastguard Worker
mmutest_panic_thread_lock_thread_func(void * _unused)302*344aa361SAndroid Build Coastguard Worker static int mmutest_panic_thread_lock_thread_func(void* _unused) {
303*344aa361SAndroid Build Coastguard Worker THREAD_LOCK(state);
304*344aa361SAndroid Build Coastguard Worker panic("mmutest-panic-thread-lock");
305*344aa361SAndroid Build Coastguard Worker }
306*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,panic_thread_lock)307*344aa361SAndroid Build Coastguard Worker TEST(mmutest, panic_thread_lock) {
308*344aa361SAndroid Build Coastguard Worker /*
309*344aa361SAndroid Build Coastguard Worker * Test panic with thread locked. Both _panic and platform_halt locks the
310*344aa361SAndroid Build Coastguard Worker * thread_lock, so _panic needs to release it if it was already held by the
311*344aa361SAndroid Build Coastguard Worker * current CPU.
312*344aa361SAndroid Build Coastguard Worker */
313*344aa361SAndroid Build Coastguard Worker int ret =
314*344aa361SAndroid Build Coastguard Worker mmutest_run_in_thread("mmutest-panic-thread-lock",
315*344aa361SAndroid Build Coastguard Worker mmutest_panic_thread_lock_thread_func, NULL);
316*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_FAULT, ret);
317*344aa361SAndroid Build Coastguard Worker }
318*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,alloc_last_kernel_page)319*344aa361SAndroid Build Coastguard Worker TEST(mmutest, alloc_last_kernel_page) {
320*344aa361SAndroid Build Coastguard Worker int ret;
321*344aa361SAndroid Build Coastguard Worker void* ptr1;
322*344aa361SAndroid Build Coastguard Worker void* ptr2;
323*344aa361SAndroid Build Coastguard Worker void* ptr3;
324*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace = vmm_get_kernel_aspace();
325*344aa361SAndroid Build Coastguard Worker struct vmm_obj_slice slice;
326*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_init(&slice);
327*344aa361SAndroid Build Coastguard Worker
328*344aa361SAndroid Build Coastguard Worker /*
329*344aa361SAndroid Build Coastguard Worker * Perform allocations at a specific address and at a vmm chosen address
330*344aa361SAndroid Build Coastguard Worker * with and without the last page allocated. There are different code paths
331*344aa361SAndroid Build Coastguard Worker * in the vmm allocator where the virtual address can overflow for the
332*344aa361SAndroid Build Coastguard Worker * region that is being allocated and for regions already allocated.
333*344aa361SAndroid Build Coastguard Worker */
334*344aa361SAndroid Build Coastguard Worker
335*344aa361SAndroid Build Coastguard Worker /* Allocate last kernel aspace page. */
336*344aa361SAndroid Build Coastguard Worker ptr1 = (void*)(aspace->base + (aspace->size - PAGE_SIZE));
337*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr1, 0,
338*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_START_GUARD |
339*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_END_GUARD,
340*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
341*344aa361SAndroid Build Coastguard Worker /* TODO: allow this to fail as page could already be in use */
342*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret, "vmm_alloc failed last page\n");
343*344aa361SAndroid Build Coastguard Worker
344*344aa361SAndroid Build Coastguard Worker /* While the last page is allocated, get an object corresponding to it */
345*344aa361SAndroid Build Coastguard Worker ret = vmm_get_obj(aspace, (vaddr_t)ptr1, PAGE_SIZE, &slice);
346*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret, "vmm_get_obj failed to get last page object");
347*344aa361SAndroid Build Coastguard Worker /* Check the slice we got back */
348*344aa361SAndroid Build Coastguard Worker EXPECT_NE(NULL, slice.obj);
349*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(PAGE_SIZE, slice.size);
350*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, slice.offset);
351*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_release(&slice);
352*344aa361SAndroid Build Coastguard Worker
353*344aa361SAndroid Build Coastguard Worker /* Allocate page anywhere, while the last page is allocated. */
354*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr2, 0, 0,
355*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
356*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret, "vmm_alloc failed anywhere page\n");
357*344aa361SAndroid Build Coastguard Worker
358*344aa361SAndroid Build Coastguard Worker /* Try to allocate last kernel aspace page again, should fail */
359*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr1, 0,
360*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_END_GUARD,
361*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
362*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_NO_MEMORY, ret, "vmm_alloc last page\n");
363*344aa361SAndroid Build Coastguard Worker
364*344aa361SAndroid Build Coastguard Worker /* Allocate 2nd last kernel aspace page, while last page is allocated. */
365*344aa361SAndroid Build Coastguard Worker ptr3 = (void*)(aspace->base + (aspace->size - 2 * PAGE_SIZE));
366*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr3, 0,
367*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_END_GUARD,
368*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
369*344aa361SAndroid Build Coastguard Worker /* TODO: allow this to fail as page could already be in use */
370*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret, "vmm_alloc failed 2nd last page\n");
371*344aa361SAndroid Build Coastguard Worker
372*344aa361SAndroid Build Coastguard Worker /* Free allocated pages */
373*344aa361SAndroid Build Coastguard Worker ret = vmm_free_region(aspace, (vaddr_t)ptr1);
374*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret, "vmm_free_region failed\n");
375*344aa361SAndroid Build Coastguard Worker ret = vmm_free_region(aspace, (vaddr_t)ptr2);
376*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret, "vmm_free_region failed\n");
377*344aa361SAndroid Build Coastguard Worker ret = vmm_free_region(aspace, (vaddr_t)ptr3);
378*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret, "vmm_free_region failed\n");
379*344aa361SAndroid Build Coastguard Worker
380*344aa361SAndroid Build Coastguard Worker /* Try to allocate last page without VMM_FLAG_NO_END_GUARD flag */
381*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr1, 0,
382*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
383*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_OUT_OF_RANGE, ret, "vmm_alloc succeeded unexpectedly\n");
384*344aa361SAndroid Build Coastguard Worker
385*344aa361SAndroid Build Coastguard Worker /* Allocate and free last page */
386*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr1, 0,
387*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_END_GUARD,
388*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
389*344aa361SAndroid Build Coastguard Worker /* TODO: allow this to fail as page could be in use */
390*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret, "vmm_alloc failed last page\n");
391*344aa361SAndroid Build Coastguard Worker ret = vmm_free_region(aspace, (vaddr_t)ptr1);
392*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret, "vmm_free_region failed\n");
393*344aa361SAndroid Build Coastguard Worker
394*344aa361SAndroid Build Coastguard Worker /* Allocate and free page anywhere, while last page is free */
395*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr2, 0, 0,
396*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
397*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret, "vmm_alloc failed anywhere page\n");
398*344aa361SAndroid Build Coastguard Worker ret = vmm_free_region(aspace, (vaddr_t)ptr2);
399*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret, "vmm_free_region failed\n");
400*344aa361SAndroid Build Coastguard Worker
401*344aa361SAndroid Build Coastguard Worker test_abort:;
402*344aa361SAndroid Build Coastguard Worker }
403*344aa361SAndroid Build Coastguard Worker
404*344aa361SAndroid Build Coastguard Worker typedef struct {
405*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace;
406*344aa361SAndroid Build Coastguard Worker } mmutestaspace_t;
407*344aa361SAndroid Build Coastguard Worker
TEST_F_SETUP(mmutestaspace)408*344aa361SAndroid Build Coastguard Worker TEST_F_SETUP(mmutestaspace) {
409*344aa361SAndroid Build Coastguard Worker int ret;
410*344aa361SAndroid Build Coastguard Worker const bool* is_kernel_aspace = GetParam();
411*344aa361SAndroid Build Coastguard Worker
412*344aa361SAndroid Build Coastguard Worker if (*is_kernel_aspace) {
413*344aa361SAndroid Build Coastguard Worker _state->aspace = vmm_get_kernel_aspace();
414*344aa361SAndroid Build Coastguard Worker } else {
415*344aa361SAndroid Build Coastguard Worker ret = vmm_create_aspace(&_state->aspace, "mmutestaspace", 0);
416*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
417*344aa361SAndroid Build Coastguard Worker }
418*344aa361SAndroid Build Coastguard Worker
419*344aa361SAndroid Build Coastguard Worker test_abort:;
420*344aa361SAndroid Build Coastguard Worker }
421*344aa361SAndroid Build Coastguard Worker
TEST_F_TEARDOWN(mmutestaspace)422*344aa361SAndroid Build Coastguard Worker TEST_F_TEARDOWN(mmutestaspace) {
423*344aa361SAndroid Build Coastguard Worker if (!(_state->aspace->flags & VMM_ASPACE_FLAG_KERNEL)) {
424*344aa361SAndroid Build Coastguard Worker vmm_free_aspace(_state->aspace);
425*344aa361SAndroid Build Coastguard Worker }
426*344aa361SAndroid Build Coastguard Worker }
427*344aa361SAndroid Build Coastguard Worker
TEST_P(mmutestaspace,guard_page)428*344aa361SAndroid Build Coastguard Worker TEST_P(mmutestaspace, guard_page) {
429*344aa361SAndroid Build Coastguard Worker int ret;
430*344aa361SAndroid Build Coastguard Worker bool retb;
431*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace = _state->aspace;
432*344aa361SAndroid Build Coastguard Worker size_t size = PAGE_SIZE * 6;
433*344aa361SAndroid Build Coastguard Worker vaddr_t base;
434*344aa361SAndroid Build Coastguard Worker void* ptr1 = NULL;
435*344aa361SAndroid Build Coastguard Worker void* ptr2 = NULL;
436*344aa361SAndroid Build Coastguard Worker void* ptr3 = NULL;
437*344aa361SAndroid Build Coastguard Worker void* ptr4 = NULL;
438*344aa361SAndroid Build Coastguard Worker void* ptr5 = NULL;
439*344aa361SAndroid Build Coastguard Worker struct vmm_obj_slice slice;
440*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_init(&slice);
441*344aa361SAndroid Build Coastguard Worker
442*344aa361SAndroid Build Coastguard Worker /* Allocate a page at a random spot with guard pages. */
443*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr1, 0, 0,
444*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
445*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
446*344aa361SAndroid Build Coastguard Worker
447*344aa361SAndroid Build Coastguard Worker /*
448*344aa361SAndroid Build Coastguard Worker * We may get an allocation right at the beginning of the address space
449*344aa361SAndroid Build Coastguard Worker * by chance or because ASLR is disabled. In that case, we make another
450*344aa361SAndroid Build Coastguard Worker * allocation to ensure that ptr1 - PAGE_SIZE >= aspace->base holds.
451*344aa361SAndroid Build Coastguard Worker */
452*344aa361SAndroid Build Coastguard Worker if (aspace->base > (vaddr_t)ptr1 - PAGE_SIZE) {
453*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr3, 0, 0,
454*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
455*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
456*344aa361SAndroid Build Coastguard Worker ASSERT_GE((vaddr_t)ptr3 - PAGE_SIZE, aspace->base);
457*344aa361SAndroid Build Coastguard Worker vmm_free_region(aspace, (vaddr_t)ptr1);
458*344aa361SAndroid Build Coastguard Worker ptr1 = ptr3;
459*344aa361SAndroid Build Coastguard Worker ptr3 = NULL;
460*344aa361SAndroid Build Coastguard Worker }
461*344aa361SAndroid Build Coastguard Worker
462*344aa361SAndroid Build Coastguard Worker /* Check that there are no existing adjacent allocations. */
463*344aa361SAndroid Build Coastguard Worker ret = vmm_get_obj(aspace, (vaddr_t)ptr1 - PAGE_SIZE, PAGE_SIZE, &slice);
464*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_NOT_FOUND, ret);
465*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_release(&slice);
466*344aa361SAndroid Build Coastguard Worker
467*344aa361SAndroid Build Coastguard Worker ret = vmm_get_obj(aspace, (vaddr_t)ptr1 + PAGE_SIZE, PAGE_SIZE, &slice);
468*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_NOT_FOUND, ret);
469*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_release(&slice);
470*344aa361SAndroid Build Coastguard Worker
471*344aa361SAndroid Build Coastguard Worker /* Check that guard pages cannot be allocated. */
472*344aa361SAndroid Build Coastguard Worker ptr2 = (void*)((vaddr_t)ptr1 - PAGE_SIZE);
473*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr2, 0,
474*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_START_GUARD |
475*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_END_GUARD,
476*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
477*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
478*344aa361SAndroid Build Coastguard Worker
479*344aa361SAndroid Build Coastguard Worker ptr2 = (void*)((vaddr_t)ptr1 + PAGE_SIZE);
480*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr2, 0,
481*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_START_GUARD |
482*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_END_GUARD,
483*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
484*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
485*344aa361SAndroid Build Coastguard Worker
486*344aa361SAndroid Build Coastguard Worker ptr2 = NULL;
487*344aa361SAndroid Build Coastguard Worker vmm_free_region(aspace, (vaddr_t)ptr1);
488*344aa361SAndroid Build Coastguard Worker ptr1 = NULL;
489*344aa361SAndroid Build Coastguard Worker
490*344aa361SAndroid Build Coastguard Worker /* Check that we cannot allocate at a random spot without guard page */
491*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr1, 0,
492*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_START_GUARD | VMM_FLAG_NO_END_GUARD,
493*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
494*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_INVALID_ARGS, ret);
495*344aa361SAndroid Build Coastguard Worker
496*344aa361SAndroid Build Coastguard Worker /* Find a range to to more specific tests in. */
497*344aa361SAndroid Build Coastguard Worker retb = vmm_find_spot(aspace, size, &base);
498*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(true, retb, "failed to find region for test\n");
499*344aa361SAndroid Build Coastguard Worker
500*344aa361SAndroid Build Coastguard Worker /* Allocate first test page. */
501*344aa361SAndroid Build Coastguard Worker ptr1 = (void*)base;
502*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr1, 0,
503*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
504*344aa361SAndroid Build Coastguard Worker if (ret) {
505*344aa361SAndroid Build Coastguard Worker /*
506*344aa361SAndroid Build Coastguard Worker * This allocation can fail if another thread allocated the page after
507*344aa361SAndroid Build Coastguard Worker * vmm_find_spot returned as that call does not reserve the memory.
508*344aa361SAndroid Build Coastguard Worker * Set ptr1 to NULL so we don't free memory belonging to someone else.
509*344aa361SAndroid Build Coastguard Worker */
510*344aa361SAndroid Build Coastguard Worker ptr1 = NULL;
511*344aa361SAndroid Build Coastguard Worker }
512*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
513*344aa361SAndroid Build Coastguard Worker
514*344aa361SAndroid Build Coastguard Worker /* Test adjacent page. Should all fail as ptr1 has guard on both sides. */
515*344aa361SAndroid Build Coastguard Worker ptr2 = (void*)(base + PAGE_SIZE);
516*344aa361SAndroid Build Coastguard Worker
517*344aa361SAndroid Build Coastguard Worker /* No flags. Should fail as both regions have a guard page. */
518*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr2, 0,
519*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC, 0);
520*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
521*344aa361SAndroid Build Coastguard Worker
522*344aa361SAndroid Build Coastguard Worker /* No start guard. Should fail as first region has a guard page. */
523*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr2, 0,
524*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_START_GUARD,
525*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
526*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
527*344aa361SAndroid Build Coastguard Worker
528*344aa361SAndroid Build Coastguard Worker /* No end guard. Should fail as both regions have a guard page. */
529*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr2, 0,
530*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_END_GUARD,
531*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
532*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
533*344aa361SAndroid Build Coastguard Worker
534*344aa361SAndroid Build Coastguard Worker /* No guard pages. Should fail as first region has a guard page. */
535*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr2, 0,
536*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_START_GUARD |
537*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_END_GUARD,
538*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
539*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
540*344aa361SAndroid Build Coastguard Worker
541*344aa361SAndroid Build Coastguard Worker /* Allocate page after guard page with no end guard */
542*344aa361SAndroid Build Coastguard Worker ptr2 = (void*)(base + PAGE_SIZE * 2);
543*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr2, 0,
544*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_END_GUARD,
545*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
546*344aa361SAndroid Build Coastguard Worker if (ret) {
547*344aa361SAndroid Build Coastguard Worker ptr2 = NULL;
548*344aa361SAndroid Build Coastguard Worker }
549*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
550*344aa361SAndroid Build Coastguard Worker
551*344aa361SAndroid Build Coastguard Worker /* Test page directly after ptr2 */
552*344aa361SAndroid Build Coastguard Worker ptr3 = (void*)(base + PAGE_SIZE * 3);
553*344aa361SAndroid Build Coastguard Worker
554*344aa361SAndroid Build Coastguard Worker /* No flags. Should fail as second region has a guard page. */
555*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr3, 0,
556*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
557*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
558*344aa361SAndroid Build Coastguard Worker
559*344aa361SAndroid Build Coastguard Worker /* No end guard. Should fail as second region has a guard page. */
560*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr3, 0,
561*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_END_GUARD,
562*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
563*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
564*344aa361SAndroid Build Coastguard Worker
565*344aa361SAndroid Build Coastguard Worker /* No guard pages. Should succeed as neither region has a guard page. */
566*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr3, 0,
567*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_START_GUARD |
568*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_END_GUARD,
569*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
570*344aa361SAndroid Build Coastguard Worker if (ret) {
571*344aa361SAndroid Build Coastguard Worker ptr3 = NULL;
572*344aa361SAndroid Build Coastguard Worker }
573*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
574*344aa361SAndroid Build Coastguard Worker
575*344aa361SAndroid Build Coastguard Worker /* Test page directly after ptr3 */
576*344aa361SAndroid Build Coastguard Worker ptr4 = (void*)(base + PAGE_SIZE * 4);
577*344aa361SAndroid Build Coastguard Worker
578*344aa361SAndroid Build Coastguard Worker /* No flags. Should fail as second region has a guard page. */
579*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr4, 0,
580*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
581*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
582*344aa361SAndroid Build Coastguard Worker
583*344aa361SAndroid Build Coastguard Worker /* No end guard. Should fail as second region has a guard page. */
584*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr4, 0,
585*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_END_GUARD,
586*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
587*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
588*344aa361SAndroid Build Coastguard Worker
589*344aa361SAndroid Build Coastguard Worker /* No start guard. Should succeed as neither region has a guard page. */
590*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr4, 0,
591*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_START_GUARD,
592*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
593*344aa361SAndroid Build Coastguard Worker if (ret) {
594*344aa361SAndroid Build Coastguard Worker ptr4 = NULL;
595*344aa361SAndroid Build Coastguard Worker }
596*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
597*344aa361SAndroid Build Coastguard Worker
598*344aa361SAndroid Build Coastguard Worker /*
599*344aa361SAndroid Build Coastguard Worker * Test page directly after ptr4. Should all fail as ptr4 has end guard.
600*344aa361SAndroid Build Coastguard Worker * Similar the test after ptr1, but checks that disabling start guard does
601*344aa361SAndroid Build Coastguard Worker * not affect end guard.
602*344aa361SAndroid Build Coastguard Worker */
603*344aa361SAndroid Build Coastguard Worker ptr5 = (void*)(base + PAGE_SIZE * 5);
604*344aa361SAndroid Build Coastguard Worker
605*344aa361SAndroid Build Coastguard Worker /* No flags. Should fail as both regions have a guard page. */
606*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr5, 0,
607*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
608*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
609*344aa361SAndroid Build Coastguard Worker
610*344aa361SAndroid Build Coastguard Worker /* No start guard. Should fail as first region has a guard page. */
611*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr5, 0,
612*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_START_GUARD,
613*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
614*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
615*344aa361SAndroid Build Coastguard Worker
616*344aa361SAndroid Build Coastguard Worker /* No end guard. Should fail as both regions have a guard page. */
617*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr5, 0,
618*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_END_GUARD,
619*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
620*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
621*344aa361SAndroid Build Coastguard Worker
622*344aa361SAndroid Build Coastguard Worker /* No guard pages. Should fail as first region has a guard page. */
623*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr5, 0,
624*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_START_GUARD |
625*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_END_GUARD,
626*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
627*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
628*344aa361SAndroid Build Coastguard Worker
629*344aa361SAndroid Build Coastguard Worker /*
630*344aa361SAndroid Build Coastguard Worker * Clear ptr5 so we don't try to free it. Not strictly needed as the guard
631*344aa361SAndroid Build Coastguard Worker * page around ptr4 will prevent anyone else from allocating memory at this
632*344aa361SAndroid Build Coastguard Worker * location, and ptr5 is freed first below, but useful if vmm tracing is
633*344aa361SAndroid Build Coastguard Worker * enabled as failing vmm_free_region calls should all be for vaddr 0.
634*344aa361SAndroid Build Coastguard Worker */
635*344aa361SAndroid Build Coastguard Worker ptr5 = NULL;
636*344aa361SAndroid Build Coastguard Worker
637*344aa361SAndroid Build Coastguard Worker test_abort:
638*344aa361SAndroid Build Coastguard Worker vmm_free_region(aspace, (vaddr_t)ptr5);
639*344aa361SAndroid Build Coastguard Worker vmm_free_region(aspace, (vaddr_t)ptr4);
640*344aa361SAndroid Build Coastguard Worker vmm_free_region(aspace, (vaddr_t)ptr3);
641*344aa361SAndroid Build Coastguard Worker vmm_free_region(aspace, (vaddr_t)ptr2);
642*344aa361SAndroid Build Coastguard Worker vmm_free_region(aspace, (vaddr_t)ptr1);
643*344aa361SAndroid Build Coastguard Worker }
644*344aa361SAndroid Build Coastguard Worker
TEST_P(mmutestaspace,find_slice_no_guard)645*344aa361SAndroid Build Coastguard Worker TEST_P(mmutestaspace, find_slice_no_guard) {
646*344aa361SAndroid Build Coastguard Worker int ret;
647*344aa361SAndroid Build Coastguard Worker bool retb;
648*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace = _state->aspace;
649*344aa361SAndroid Build Coastguard Worker void* ptr[8];
650*344aa361SAndroid Build Coastguard Worker size_t num_regions = countof(ptr);
651*344aa361SAndroid Build Coastguard Worker size_t size = PAGE_SIZE * num_regions;
652*344aa361SAndroid Build Coastguard Worker vaddr_t base;
653*344aa361SAndroid Build Coastguard Worker uint vmm_flags = VMM_FLAG_VALLOC_SPECIFIC | VMM_FLAG_NO_START_GUARD |
654*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_END_GUARD;
655*344aa361SAndroid Build Coastguard Worker struct vmm_obj_slice slice;
656*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_init(&slice);
657*344aa361SAndroid Build Coastguard Worker
658*344aa361SAndroid Build Coastguard Worker for (size_t i = 0; i < num_regions; i++) {
659*344aa361SAndroid Build Coastguard Worker ptr[i] = NULL;
660*344aa361SAndroid Build Coastguard Worker }
661*344aa361SAndroid Build Coastguard Worker
662*344aa361SAndroid Build Coastguard Worker retb = vmm_find_spot(aspace, size, &base);
663*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(true, retb, "failed to find region for test\n");
664*344aa361SAndroid Build Coastguard Worker
665*344aa361SAndroid Build Coastguard Worker for (int i = num_regions - 1; i >= 0; --i) {
666*344aa361SAndroid Build Coastguard Worker ptr[i] = (void*)(base + PAGE_SIZE * i);
667*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "mmutest", PAGE_SIZE, &ptr[i], 0, vmm_flags,
668*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
669*344aa361SAndroid Build Coastguard Worker if (ret) {
670*344aa361SAndroid Build Coastguard Worker ptr[i] = NULL;
671*344aa361SAndroid Build Coastguard Worker }
672*344aa361SAndroid Build Coastguard Worker
673*344aa361SAndroid Build Coastguard Worker if (ptr[i]) {
674*344aa361SAndroid Build Coastguard Worker /* Test that we can find slice corresponding to allocated page. */
675*344aa361SAndroid Build Coastguard Worker ret = vmm_get_obj(aspace, (vaddr_t)ptr[i], PAGE_SIZE, &slice);
676*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
677*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_release(&slice);
678*344aa361SAndroid Build Coastguard Worker }
679*344aa361SAndroid Build Coastguard Worker }
680*344aa361SAndroid Build Coastguard Worker
681*344aa361SAndroid Build Coastguard Worker test_abort:
682*344aa361SAndroid Build Coastguard Worker for (size_t i = 0; i < num_regions; i++) {
683*344aa361SAndroid Build Coastguard Worker vmm_free_region(aspace, (vaddr_t)ptr[i]);
684*344aa361SAndroid Build Coastguard Worker }
685*344aa361SAndroid Build Coastguard Worker }
686*344aa361SAndroid Build Coastguard Worker
687*344aa361SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(aspacetype,
688*344aa361SAndroid Build Coastguard Worker mmutestaspace,
689*344aa361SAndroid Build Coastguard Worker /* user(false) and kernel(true) aspaces */
690*344aa361SAndroid Build Coastguard Worker testing_Bool());
691*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,check_stack_guard_page_bad_ptr)692*344aa361SAndroid Build Coastguard Worker TEST(mmutest, check_stack_guard_page_bad_ptr)
693*344aa361SAndroid Build Coastguard Worker __attribute__((no_sanitize("bounds"))) {
694*344aa361SAndroid Build Coastguard Worker char data[4];
695*344aa361SAndroid Build Coastguard Worker void* ptr1 = data;
696*344aa361SAndroid Build Coastguard Worker void* ptr2 = data - DEFAULT_STACK_SIZE;
697*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, mmutest_arch_store_uint32(ptr1, false));
698*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_GENERIC, mmutest_arch_store_uint32(ptr2, false));
699*344aa361SAndroid Build Coastguard Worker }
700*344aa361SAndroid Build Coastguard Worker
mmutest_stack_overflow_thread_func(void * arg)701*344aa361SAndroid Build Coastguard Worker static int mmutest_stack_overflow_thread_func(void* arg) {
702*344aa361SAndroid Build Coastguard Worker char data[DEFAULT_STACK_SIZE] __attribute((uninitialized));
703*344aa361SAndroid Build Coastguard Worker void* ptr = data;
704*344aa361SAndroid Build Coastguard Worker mmutest_arch_store_uint32(ptr, false);
705*344aa361SAndroid Build Coastguard Worker return 0;
706*344aa361SAndroid Build Coastguard Worker }
707*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,check_stack_guard_page_stack_overflow)708*344aa361SAndroid Build Coastguard Worker TEST(mmutest, check_stack_guard_page_stack_overflow) {
709*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_FAULT,
710*344aa361SAndroid Build Coastguard Worker mmutest_run_in_thread("stack-overflow",
711*344aa361SAndroid Build Coastguard Worker mmutest_stack_overflow_thread_func, NULL));
712*344aa361SAndroid Build Coastguard Worker }
713*344aa361SAndroid Build Coastguard Worker
mmutest_recursive_stack_overflow_thread_func(void * arg)714*344aa361SAndroid Build Coastguard Worker static int mmutest_recursive_stack_overflow_thread_func(void* arg) {
715*344aa361SAndroid Build Coastguard Worker char b;
716*344aa361SAndroid Build Coastguard Worker if ((vaddr_t)arg == 1) {
717*344aa361SAndroid Build Coastguard Worker return 0;
718*344aa361SAndroid Build Coastguard Worker }
719*344aa361SAndroid Build Coastguard Worker return mmutest_recursive_stack_overflow_thread_func(&b) + 1;
720*344aa361SAndroid Build Coastguard Worker }
721*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,check_stack_guard_page_recursive_stack_overflow)722*344aa361SAndroid Build Coastguard Worker TEST(mmutest, check_stack_guard_page_recursive_stack_overflow) {
723*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_FAULT,
724*344aa361SAndroid Build Coastguard Worker mmutest_run_in_thread(
725*344aa361SAndroid Build Coastguard Worker "stack-overflow",
726*344aa361SAndroid Build Coastguard Worker mmutest_recursive_stack_overflow_thread_func, 0));
727*344aa361SAndroid Build Coastguard Worker }
728*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,DISABLED_ON_ARM_NAME (rodata_pnx))729*344aa361SAndroid Build Coastguard Worker TEST(mmutest, DISABLED_ON_ARM_NAME(rodata_pnx)) {
730*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_FAULT, mmutest_arch_rodata_pnx());
731*344aa361SAndroid Build Coastguard Worker }
732*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,DISABLED_ON_ARM_NAME (data_pnx))733*344aa361SAndroid Build Coastguard Worker TEST(mmutest, DISABLED_ON_ARM_NAME(data_pnx)) {
734*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_FAULT, mmutest_arch_data_pnx());
735*344aa361SAndroid Build Coastguard Worker }
736*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,DISABLED_ON_ARM_NAME (rodata_ro))737*344aa361SAndroid Build Coastguard Worker TEST(mmutest, DISABLED_ON_ARM_NAME(rodata_ro)) {
738*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_FAULT, mmutest_arch_rodata_ro());
739*344aa361SAndroid Build Coastguard Worker }
740*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,pan)741*344aa361SAndroid Build Coastguard Worker TEST(mmutest, pan) {
742*344aa361SAndroid Build Coastguard Worker if (!mmutest_arch_pan_supported()) {
743*344aa361SAndroid Build Coastguard Worker trusty_unittest_printf("[ INFO ] PAN is not supported\n");
744*344aa361SAndroid Build Coastguard Worker GTEST_SKIP();
745*344aa361SAndroid Build Coastguard Worker }
746*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(true, mmutest_arch_pan_enabled());
747*344aa361SAndroid Build Coastguard Worker test_abort:;
748*344aa361SAndroid Build Coastguard Worker }
749*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,store_kernel)750*344aa361SAndroid Build Coastguard Worker TEST(mmutest, store_kernel) {
751*344aa361SAndroid Build Coastguard Worker int expected_user_rw_access;
752*344aa361SAndroid Build Coastguard Worker int expected_user_ro_access;
753*344aa361SAndroid Build Coastguard Worker
754*344aa361SAndroid Build Coastguard Worker if (mmutest_arch_pan_enabled()) {
755*344aa361SAndroid Build Coastguard Worker expected_user_rw_access = ERR_GENERIC;
756*344aa361SAndroid Build Coastguard Worker expected_user_ro_access = ERR_GENERIC;
757*344aa361SAndroid Build Coastguard Worker } else {
758*344aa361SAndroid Build Coastguard Worker expected_user_rw_access = 0;
759*344aa361SAndroid Build Coastguard Worker expected_user_ro_access = ERR_FAULT;
760*344aa361SAndroid Build Coastguard Worker }
761*344aa361SAndroid Build Coastguard Worker
762*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR,
763*344aa361SAndroid Build Coastguard Worker mmutest_vmm_store_uint32_kernel(ARCH_MMU_FLAG_CACHED |
764*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE));
765*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(expected_user_rw_access,
766*344aa361SAndroid Build Coastguard Worker mmutest_vmm_store_uint32_kernel(ARCH_MMU_FLAG_CACHED |
767*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE |
768*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_USER));
769*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR,
770*344aa361SAndroid Build Coastguard Worker mmutest_vmm_store_uint32_kernel(ARCH_MMU_FLAG_CACHED |
771*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE));
772*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(expected_user_rw_access,
773*344aa361SAndroid Build Coastguard Worker mmutest_vmm_store_uint32_kernel(ARCH_MMU_FLAG_CACHED |
774*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE |
775*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_USER));
776*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_FAULT, mmutest_vmm_store_uint32_kernel(
777*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_CACHED | ARCH_MMU_FLAG_PERM_RO));
778*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(expected_user_ro_access,
779*344aa361SAndroid Build Coastguard Worker mmutest_vmm_store_uint32_kernel(ARCH_MMU_FLAG_CACHED |
780*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_RO |
781*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_USER));
782*344aa361SAndroid Build Coastguard Worker }
783*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,store_user)784*344aa361SAndroid Build Coastguard Worker TEST(mmutest, store_user) {
785*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_GENERIC,
786*344aa361SAndroid Build Coastguard Worker mmutest_vmm_store_uint32_user(ARCH_MMU_FLAG_CACHED |
787*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE));
788*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR,
789*344aa361SAndroid Build Coastguard Worker mmutest_vmm_store_uint32_user(ARCH_MMU_FLAG_CACHED |
790*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE |
791*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_USER));
792*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_GENERIC,
793*344aa361SAndroid Build Coastguard Worker mmutest_vmm_store_uint32_user(ARCH_MMU_FLAG_CACHED |
794*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE));
795*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR,
796*344aa361SAndroid Build Coastguard Worker mmutest_vmm_store_uint32_user(ARCH_MMU_FLAG_CACHED |
797*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE |
798*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_USER));
799*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_GENERIC,
800*344aa361SAndroid Build Coastguard Worker mmutest_vmm_store_uint32_user(ARCH_MMU_FLAG_CACHED |
801*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_RO));
802*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_FAULT, mmutest_vmm_store_uint32_user(
803*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_CACHED | ARCH_MMU_FLAG_PERM_RO |
804*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_USER));
805*344aa361SAndroid Build Coastguard Worker }
806*344aa361SAndroid Build Coastguard Worker
807*344aa361SAndroid Build Coastguard Worker /*
808*344aa361SAndroid Build Coastguard Worker * The current implementation of this test checks checks that the data is lost
809*344aa361SAndroid Build Coastguard Worker * when reading back from memory, but allows the store to reach the cache. This
810*344aa361SAndroid Build Coastguard Worker * is not the only allowed behavior and the emulator does not emulate this
811*344aa361SAndroid Build Coastguard Worker * behavior, so disable this test for now.
812*344aa361SAndroid Build Coastguard Worker */
TEST(mmutest,DISABLED_store_ns)813*344aa361SAndroid Build Coastguard Worker TEST(mmutest, DISABLED_store_ns) {
814*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(2, mmutest_vmm_store_uint32_kernel(ARCH_MMU_FLAG_CACHED |
815*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_NS));
816*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(2, mmutest_vmm_store_uint32_kernel(ARCH_MMU_FLAG_CACHED |
817*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_NS |
818*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_USER));
819*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_GENERIC, mmutest_vmm_store_uint32_user(ARCH_MMU_FLAG_CACHED |
820*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_NS));
821*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(2, mmutest_vmm_store_uint32_user(ARCH_MMU_FLAG_CACHED |
822*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_NS |
823*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_USER));
824*344aa361SAndroid Build Coastguard Worker }
825*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,run_x)826*344aa361SAndroid Build Coastguard Worker TEST(mmutest, run_x) {
827*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, mmu_test_execute(ARCH_MMU_FLAG_PERM_RO));
828*344aa361SAndroid Build Coastguard Worker }
829*344aa361SAndroid Build Coastguard Worker
830*344aa361SAndroid Build Coastguard Worker #if ARCH_ARM64
831*344aa361SAndroid Build Coastguard Worker #include <arch/arm64/sregs.h>
832*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,run_wx)833*344aa361SAndroid Build Coastguard Worker TEST(mmutest, run_wx) {
834*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace = vmm_get_kernel_aspace();
835*344aa361SAndroid Build Coastguard Worker struct obj_ref vmm_obj_ref = OBJ_REF_INITIAL_VALUE(vmm_obj_ref);
836*344aa361SAndroid Build Coastguard Worker struct vmm_obj* vmm_obj = NULL;
837*344aa361SAndroid Build Coastguard Worker void* ptr = NULL;
838*344aa361SAndroid Build Coastguard Worker int ret;
839*344aa361SAndroid Build Coastguard Worker
840*344aa361SAndroid Build Coastguard Worker /* Allocate a single page */
841*344aa361SAndroid Build Coastguard Worker ret = pmm_alloc(&vmm_obj, &vmm_obj_ref, 1, PMM_ALLOC_FLAG_CONTIGUOUS, 0);
842*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret, "pmm_alloc failed\n");
843*344aa361SAndroid Build Coastguard Worker
844*344aa361SAndroid Build Coastguard Worker /* Try to map as w+x and check it fails */
845*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc_obj(aspace, "mmutest_wx", vmm_obj, 0, PAGE_SIZE, &ptr, 0, 0,
846*344aa361SAndroid Build Coastguard Worker 0);
847*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_INVALID_ARGS, ret);
848*344aa361SAndroid Build Coastguard Worker
849*344aa361SAndroid Build Coastguard Worker /*
850*344aa361SAndroid Build Coastguard Worker * ARM64 should have WXN enabled.
851*344aa361SAndroid Build Coastguard Worker * This means that any writable page is NX irrespective of the PTE entry.
852*344aa361SAndroid Build Coastguard Worker */
853*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(SCTLR_EL1_WXN, ARM64_READ_SYSREG(SCTLR_EL1) & SCTLR_EL1_WXN);
854*344aa361SAndroid Build Coastguard Worker
855*344aa361SAndroid Build Coastguard Worker test_abort:
856*344aa361SAndroid Build Coastguard Worker if (vmm_obj) {
857*344aa361SAndroid Build Coastguard Worker vmm_obj_del_ref(vmm_obj, &vmm_obj_ref);
858*344aa361SAndroid Build Coastguard Worker }
859*344aa361SAndroid Build Coastguard Worker }
860*344aa361SAndroid Build Coastguard Worker #else
TEST(mmutest,run_wx)861*344aa361SAndroid Build Coastguard Worker TEST(mmutest, run_wx) {
862*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, mmu_test_execute(0));
863*344aa361SAndroid Build Coastguard Worker }
864*344aa361SAndroid Build Coastguard Worker #endif
865*344aa361SAndroid Build Coastguard Worker
TEST(mmutest,run_nx)866*344aa361SAndroid Build Coastguard Worker TEST(mmutest, run_nx) {
867*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ERR_FAULT, mmu_test_execute(ARCH_MMU_FLAG_PERM_NO_EXECUTE));
868*344aa361SAndroid Build Coastguard Worker }
869*344aa361SAndroid Build Coastguard Worker
870*344aa361SAndroid Build Coastguard Worker /*
871*344aa361SAndroid Build Coastguard Worker * Tests that allocations with conflicting NS bits are not allowed
872*344aa361SAndroid Build Coastguard Worker * near each other
873*344aa361SAndroid Build Coastguard Worker */
TEST(mmutest,ns_conflict)874*344aa361SAndroid Build Coastguard Worker TEST(mmutest, ns_conflict) {
875*344aa361SAndroid Build Coastguard Worker int ret;
876*344aa361SAndroid Build Coastguard Worker void* ptr_ns = NULL;
877*344aa361SAndroid Build Coastguard Worker void* ptr_s = NULL;
878*344aa361SAndroid Build Coastguard Worker uint arch_mmu_flags_query, ns_flag;
879*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace = vmm_get_kernel_aspace();
880*344aa361SAndroid Build Coastguard Worker
881*344aa361SAndroid Build Coastguard Worker /*
882*344aa361SAndroid Build Coastguard Worker * Allocate a NS page with a 16K alignment to ensure that there
883*344aa361SAndroid Build Coastguard Worker * is enough room after it in the 1MB section for both the guard page
884*344aa361SAndroid Build Coastguard Worker * and the S page below.
885*344aa361SAndroid Build Coastguard Worker */
886*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "ns_conflict_ns", PAGE_SIZE, &ptr_ns,
887*344aa361SAndroid Build Coastguard Worker PAGE_SIZE_SHIFT + 2, 0,
888*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_NS | ARCH_MMU_FLAG_PERM_NO_EXECUTE);
889*344aa361SAndroid Build Coastguard Worker if (ret == ERR_NOT_SUPPORTED) {
890*344aa361SAndroid Build Coastguard Worker GTEST_SKIP();
891*344aa361SAndroid Build Coastguard Worker }
892*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret);
893*344aa361SAndroid Build Coastguard Worker
894*344aa361SAndroid Build Coastguard Worker ret = arch_mmu_query(&aspace->arch_aspace, (vaddr_t)ptr_ns, NULL,
895*344aa361SAndroid Build Coastguard Worker &arch_mmu_flags_query);
896*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ret);
897*344aa361SAndroid Build Coastguard Worker
898*344aa361SAndroid Build Coastguard Worker ns_flag = arch_mmu_flags_query & ARCH_MMU_FLAG_NS;
899*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(ARCH_MMU_FLAG_NS, ns_flag);
900*344aa361SAndroid Build Coastguard Worker
901*344aa361SAndroid Build Coastguard Worker /*
902*344aa361SAndroid Build Coastguard Worker * Allocate an S page just after the previous one (plus the guard page).
903*344aa361SAndroid Build Coastguard Worker * This should fail on arm32 because the kernel shouldn't let us mix the
904*344aa361SAndroid Build Coastguard Worker * two kinds.
905*344aa361SAndroid Build Coastguard Worker */
906*344aa361SAndroid Build Coastguard Worker ptr_s = (uint8_t*)ptr_ns + 2 * PAGE_SIZE;
907*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(aspace, "ns_conflict_s", PAGE_SIZE, &ptr_s, PAGE_SIZE_SHIFT,
908*344aa361SAndroid Build Coastguard Worker VMM_FLAG_VALLOC_SPECIFIC, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
909*344aa361SAndroid Build Coastguard Worker if (ret) {
910*344aa361SAndroid Build Coastguard Worker ptr_s = NULL;
911*344aa361SAndroid Build Coastguard Worker } else {
912*344aa361SAndroid Build Coastguard Worker ret = arch_mmu_query(&aspace->arch_aspace, (vaddr_t)ptr_s, NULL,
913*344aa361SAndroid Build Coastguard Worker &arch_mmu_flags_query);
914*344aa361SAndroid Build Coastguard Worker if (!ret) {
915*344aa361SAndroid Build Coastguard Worker ns_flag = arch_mmu_flags_query & ARCH_MMU_FLAG_NS;
916*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(NO_ERROR, ns_flag);
917*344aa361SAndroid Build Coastguard Worker }
918*344aa361SAndroid Build Coastguard Worker }
919*344aa361SAndroid Build Coastguard Worker
920*344aa361SAndroid Build Coastguard Worker test_abort:
921*344aa361SAndroid Build Coastguard Worker if (ptr_ns) {
922*344aa361SAndroid Build Coastguard Worker vmm_free_region(aspace, (vaddr_t)ptr_ns);
923*344aa361SAndroid Build Coastguard Worker }
924*344aa361SAndroid Build Coastguard Worker if (ptr_s) {
925*344aa361SAndroid Build Coastguard Worker vmm_free_region(aspace, (vaddr_t)ptr_s);
926*344aa361SAndroid Build Coastguard Worker }
927*344aa361SAndroid Build Coastguard Worker }
928*344aa361SAndroid Build Coastguard Worker
929*344aa361SAndroid Build Coastguard Worker /* Test suite for vmm_obj_slice and vmm_get_obj */
930*344aa361SAndroid Build Coastguard Worker
931*344aa361SAndroid Build Coastguard Worker typedef struct {
932*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace;
933*344aa361SAndroid Build Coastguard Worker vaddr_t spot_a_2_page;
934*344aa361SAndroid Build Coastguard Worker vaddr_t spot_b_1_page;
935*344aa361SAndroid Build Coastguard Worker struct vmm_obj_slice slice;
936*344aa361SAndroid Build Coastguard Worker } mmutest_slice_t;
937*344aa361SAndroid Build Coastguard Worker
TEST_F_SETUP(mmutest_slice)938*344aa361SAndroid Build Coastguard Worker TEST_F_SETUP(mmutest_slice) {
939*344aa361SAndroid Build Coastguard Worker _state->aspace = vmm_get_kernel_aspace();
940*344aa361SAndroid Build Coastguard Worker _state->spot_a_2_page = 0;
941*344aa361SAndroid Build Coastguard Worker _state->spot_b_1_page = 0;
942*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_init(&_state->slice);
943*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(vmm_alloc(_state->aspace, "mmutest_slice", 2 * PAGE_SIZE,
944*344aa361SAndroid Build Coastguard Worker (void**)&_state->spot_a_2_page, 0, 0,
945*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE),
946*344aa361SAndroid Build Coastguard Worker NO_ERROR);
947*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(vmm_alloc(_state->aspace, "mmutest_slice", PAGE_SIZE,
948*344aa361SAndroid Build Coastguard Worker (void**)&_state->spot_b_1_page, 0, 0,
949*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE),
950*344aa361SAndroid Build Coastguard Worker NO_ERROR);
951*344aa361SAndroid Build Coastguard Worker test_abort:;
952*344aa361SAndroid Build Coastguard Worker }
953*344aa361SAndroid Build Coastguard Worker
TEST_F_TEARDOWN(mmutest_slice)954*344aa361SAndroid Build Coastguard Worker TEST_F_TEARDOWN(mmutest_slice) {
955*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_release(&_state->slice);
956*344aa361SAndroid Build Coastguard Worker if (_state->spot_a_2_page) {
957*344aa361SAndroid Build Coastguard Worker vmm_free_region(_state->aspace, (vaddr_t)_state->spot_a_2_page);
958*344aa361SAndroid Build Coastguard Worker }
959*344aa361SAndroid Build Coastguard Worker
960*344aa361SAndroid Build Coastguard Worker if (_state->spot_b_1_page) {
961*344aa361SAndroid Build Coastguard Worker vmm_free_region(_state->aspace, (vaddr_t)_state->spot_b_1_page);
962*344aa361SAndroid Build Coastguard Worker }
963*344aa361SAndroid Build Coastguard Worker }
964*344aa361SAndroid Build Coastguard Worker
965*344aa361SAndroid Build Coastguard Worker /*
966*344aa361SAndroid Build Coastguard Worker * Simplest use of interface - get the slice for a mapped region,
967*344aa361SAndroid Build Coastguard Worker * of the whole size
968*344aa361SAndroid Build Coastguard Worker */
TEST_F(mmutest_slice,simple)969*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_slice, simple) {
970*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(vmm_get_obj(_state->aspace, _state->spot_b_1_page, PAGE_SIZE,
971*344aa361SAndroid Build Coastguard Worker &_state->slice),
972*344aa361SAndroid Build Coastguard Worker NO_ERROR);
973*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(_state->slice.offset, 0);
974*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(_state->slice.size, PAGE_SIZE);
975*344aa361SAndroid Build Coastguard Worker test_abort:;
976*344aa361SAndroid Build Coastguard Worker }
977*344aa361SAndroid Build Coastguard Worker
978*344aa361SAndroid Build Coastguard Worker /* Validate that we will reject an attempt to span two slices */
TEST_F(mmutest_slice,two_objs)979*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_slice, two_objs) {
980*344aa361SAndroid Build Coastguard Worker vaddr_t base;
981*344aa361SAndroid Build Coastguard Worker size_t size;
982*344aa361SAndroid Build Coastguard Worker vaddr_t spot_a = _state->spot_a_2_page;
983*344aa361SAndroid Build Coastguard Worker vaddr_t spot_b = _state->spot_b_1_page;
984*344aa361SAndroid Build Coastguard Worker
985*344aa361SAndroid Build Coastguard Worker base = MIN(spot_a, spot_b);
986*344aa361SAndroid Build Coastguard Worker size = MAX(spot_a, spot_b) - base + PAGE_SIZE;
987*344aa361SAndroid Build Coastguard Worker
988*344aa361SAndroid Build Coastguard Worker /* We should not be able to create a slice spanning both objects */
989*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(vmm_get_obj(_state->aspace, base, size, &_state->slice),
990*344aa361SAndroid Build Coastguard Worker ERR_OUT_OF_RANGE);
991*344aa361SAndroid Build Coastguard Worker
992*344aa361SAndroid Build Coastguard Worker test_abort:;
993*344aa361SAndroid Build Coastguard Worker }
994*344aa361SAndroid Build Coastguard Worker
995*344aa361SAndroid Build Coastguard Worker /* Check we can acquire a subslice of a mapped object */
TEST_F(mmutest_slice,subobj)996*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_slice, subobj) {
997*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(vmm_get_obj(_state->aspace, _state->spot_a_2_page + PAGE_SIZE,
998*344aa361SAndroid Build Coastguard Worker PAGE_SIZE, &_state->slice),
999*344aa361SAndroid Build Coastguard Worker NO_ERROR);
1000*344aa361SAndroid Build Coastguard Worker
1001*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(_state->slice.offset, PAGE_SIZE);
1002*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(_state->slice.size, PAGE_SIZE);
1003*344aa361SAndroid Build Coastguard Worker
1004*344aa361SAndroid Build Coastguard Worker test_abort:;
1005*344aa361SAndroid Build Coastguard Worker }
1006*344aa361SAndroid Build Coastguard Worker
1007*344aa361SAndroid Build Coastguard Worker /* Check for rejection of the requested range overflows */
TEST_F(mmutest_slice,overflow)1008*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_slice, overflow) {
1009*344aa361SAndroid Build Coastguard Worker EXPECT_EQ(vmm_get_obj(_state->aspace, _state->spot_a_2_page, SIZE_MAX,
1010*344aa361SAndroid Build Coastguard Worker &_state->slice),
1011*344aa361SAndroid Build Coastguard Worker ERR_INVALID_ARGS);
1012*344aa361SAndroid Build Coastguard Worker }
1013*344aa361SAndroid Build Coastguard Worker
1014*344aa361SAndroid Build Coastguard Worker /* Test suite for PMM */
1015*344aa361SAndroid Build Coastguard Worker
1016*344aa361SAndroid Build Coastguard Worker #define RESERVE_PAGES 500
1017*344aa361SAndroid Build Coastguard Worker
1018*344aa361SAndroid Build Coastguard Worker typedef struct {
1019*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace;
1020*344aa361SAndroid Build Coastguard Worker } mmutest_pmm_t;
1021*344aa361SAndroid Build Coastguard Worker
TEST_F_SETUP(mmutest_pmm)1022*344aa361SAndroid Build Coastguard Worker TEST_F_SETUP(mmutest_pmm) {
1023*344aa361SAndroid Build Coastguard Worker _state->aspace = NULL;
1024*344aa361SAndroid Build Coastguard Worker status_t ret = vmm_create_aspace_with_quota(&_state->aspace, "mmutestpmm",
1025*344aa361SAndroid Build Coastguard Worker PAGE_SIZE * 2, 0);
1026*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1027*344aa361SAndroid Build Coastguard Worker test_abort:;
1028*344aa361SAndroid Build Coastguard Worker }
1029*344aa361SAndroid Build Coastguard Worker
TEST_F_TEARDOWN(mmutest_pmm)1030*344aa361SAndroid Build Coastguard Worker TEST_F_TEARDOWN(mmutest_pmm) {
1031*344aa361SAndroid Build Coastguard Worker if (_state->aspace) {
1032*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, vmm_free_aspace(_state->aspace));
1033*344aa361SAndroid Build Coastguard Worker }
1034*344aa361SAndroid Build Coastguard Worker test_abort:;
1035*344aa361SAndroid Build Coastguard Worker }
1036*344aa361SAndroid Build Coastguard Worker
probe_max_aspace_quota_pages(void)1037*344aa361SAndroid Build Coastguard Worker static uint probe_max_aspace_quota_pages(void) {
1038*344aa361SAndroid Build Coastguard Worker struct vmm_aspace* probe_aspace = NULL;
1039*344aa361SAndroid Build Coastguard Worker uint alloc_pages = 4096;
1040*344aa361SAndroid Build Coastguard Worker uint alloc_step = 4096;
1041*344aa361SAndroid Build Coastguard Worker status_t ret;
1042*344aa361SAndroid Build Coastguard Worker
1043*344aa361SAndroid Build Coastguard Worker do {
1044*344aa361SAndroid Build Coastguard Worker ret = vmm_create_aspace_with_quota(&probe_aspace, "probe_aspace",
1045*344aa361SAndroid Build Coastguard Worker PAGE_SIZE * alloc_pages, 0);
1046*344aa361SAndroid Build Coastguard Worker
1047*344aa361SAndroid Build Coastguard Worker if (probe_aspace) {
1048*344aa361SAndroid Build Coastguard Worker vmm_free_aspace(probe_aspace);
1049*344aa361SAndroid Build Coastguard Worker probe_aspace = NULL;
1050*344aa361SAndroid Build Coastguard Worker }
1051*344aa361SAndroid Build Coastguard Worker
1052*344aa361SAndroid Build Coastguard Worker if (ret == NO_ERROR) {
1053*344aa361SAndroid Build Coastguard Worker alloc_pages += alloc_step;
1054*344aa361SAndroid Build Coastguard Worker } else if (alloc_step) {
1055*344aa361SAndroid Build Coastguard Worker alloc_pages -= alloc_step;
1056*344aa361SAndroid Build Coastguard Worker alloc_step = alloc_step / 2;
1057*344aa361SAndroid Build Coastguard Worker } else {
1058*344aa361SAndroid Build Coastguard Worker alloc_pages--;
1059*344aa361SAndroid Build Coastguard Worker }
1060*344aa361SAndroid Build Coastguard Worker
1061*344aa361SAndroid Build Coastguard Worker } while (alloc_step > 0 || ret != NO_ERROR);
1062*344aa361SAndroid Build Coastguard Worker
1063*344aa361SAndroid Build Coastguard Worker return alloc_pages;
1064*344aa361SAndroid Build Coastguard Worker }
1065*344aa361SAndroid Build Coastguard Worker
1066*344aa361SAndroid Build Coastguard Worker /*
1067*344aa361SAndroid Build Coastguard Worker * Reserve physical pages and allocate from reserved memory.
1068*344aa361SAndroid Build Coastguard Worker */
TEST_F(mmutest_pmm,reserve)1069*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_pmm, reserve) {
1070*344aa361SAndroid Build Coastguard Worker void* ptr = NULL;
1071*344aa361SAndroid Build Coastguard Worker void* ptr_unused = NULL;
1072*344aa361SAndroid Build Coastguard Worker status_t ret;
1073*344aa361SAndroid Build Coastguard Worker struct vmm_aspace* temp_aspace = NULL;
1074*344aa361SAndroid Build Coastguard Worker uint max_pages, temp_aspace_pages;
1075*344aa361SAndroid Build Coastguard Worker
1076*344aa361SAndroid Build Coastguard Worker /* Allocate virtual space without quota or pmm, which should pass */
1077*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_reserve",
1078*344aa361SAndroid Build Coastguard Worker PAGE_SIZE * (RESERVE_PAGES + 2), &ptr, 0,
1079*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_PHYSICAL, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1080*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1081*344aa361SAndroid Build Coastguard Worker
1082*344aa361SAndroid Build Coastguard Worker /* Allocate all quota pages at previous virtual address */
1083*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_from_reserved", PAGE_SIZE * 2, &ptr,
1084*344aa361SAndroid Build Coastguard Worker 0, VMM_FLAG_QUOTA | VMM_FLAG_VALLOC_SPECIFIC,
1085*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1086*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1087*344aa361SAndroid Build Coastguard Worker
1088*344aa361SAndroid Build Coastguard Worker /* Check the maximum quota that can be allocated to an aspace */
1089*344aa361SAndroid Build Coastguard Worker max_pages = probe_max_aspace_quota_pages();
1090*344aa361SAndroid Build Coastguard Worker ASSERT_GT(max_pages, RESERVE_PAGES);
1091*344aa361SAndroid Build Coastguard Worker
1092*344aa361SAndroid Build Coastguard Worker /* Reserve most pages for temp_aspace, leaving RESERVE_PAGES / 2 free */
1093*344aa361SAndroid Build Coastguard Worker temp_aspace_pages = max_pages - (RESERVE_PAGES / 2);
1094*344aa361SAndroid Build Coastguard Worker ret = vmm_create_aspace_with_quota(&temp_aspace, "temp_aspace",
1095*344aa361SAndroid Build Coastguard Worker PAGE_SIZE * temp_aspace_pages, 0);
1096*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1097*344aa361SAndroid Build Coastguard Worker
1098*344aa361SAndroid Build Coastguard Worker /* Almost all pages are reserved for temp_aspace quota; this should fail */
1099*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_failure", PAGE_SIZE * RESERVE_PAGES,
1100*344aa361SAndroid Build Coastguard Worker &ptr_unused, 0, 0, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1101*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
1102*344aa361SAndroid Build Coastguard Worker
1103*344aa361SAndroid Build Coastguard Worker /* Allocate from the temp_aspace quota reservation; should succeed */
1104*344aa361SAndroid Build Coastguard Worker ptr += PAGE_SIZE * 2;
1105*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(temp_aspace, "test_from_reserved_success",
1106*344aa361SAndroid Build Coastguard Worker PAGE_SIZE * MIN(temp_aspace_pages, RESERVE_PAGES), &ptr, 0,
1107*344aa361SAndroid Build Coastguard Worker VMM_FLAG_QUOTA | VMM_FLAG_VALLOC_SPECIFIC,
1108*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1109*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1110*344aa361SAndroid Build Coastguard Worker test_abort:
1111*344aa361SAndroid Build Coastguard Worker if (temp_aspace)
1112*344aa361SAndroid Build Coastguard Worker vmm_free_aspace(temp_aspace);
1113*344aa361SAndroid Build Coastguard Worker }
1114*344aa361SAndroid Build Coastguard Worker
TEST_F(mmutest_pmm,reserve_contiguous)1115*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_pmm, reserve_contiguous) {
1116*344aa361SAndroid Build Coastguard Worker void* ptr = NULL;
1117*344aa361SAndroid Build Coastguard Worker status_t ret;
1118*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_reserve", PAGE_SIZE * 2, &ptr, 0,
1119*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_PHYSICAL, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1120*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1121*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc_contiguous(_state->aspace, "test_from_reserved_continuous",
1122*344aa361SAndroid Build Coastguard Worker PAGE_SIZE * 2, &ptr, 0,
1123*344aa361SAndroid Build Coastguard Worker VMM_FLAG_QUOTA | VMM_FLAG_VALLOC_SPECIFIC,
1124*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1125*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1126*344aa361SAndroid Build Coastguard Worker test_abort:;
1127*344aa361SAndroid Build Coastguard Worker }
1128*344aa361SAndroid Build Coastguard Worker
TEST_F(mmutest_pmm,reserve_too_small)1129*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_pmm, reserve_too_small) {
1130*344aa361SAndroid Build Coastguard Worker void* ptr = NULL;
1131*344aa361SAndroid Build Coastguard Worker status_t ret;
1132*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_reserve", PAGE_SIZE * 2, &ptr, 0,
1133*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_PHYSICAL, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1134*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1135*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_from_reserved_too_small",
1136*344aa361SAndroid Build Coastguard Worker PAGE_SIZE * 3, &ptr, 0,
1137*344aa361SAndroid Build Coastguard Worker VMM_FLAG_QUOTA | VMM_FLAG_VALLOC_SPECIFIC,
1138*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1139*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
1140*344aa361SAndroid Build Coastguard Worker test_abort:;
1141*344aa361SAndroid Build Coastguard Worker }
1142*344aa361SAndroid Build Coastguard Worker
TEST_F(mmutest_pmm,reserve_outside_region)1143*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_pmm, reserve_outside_region) {
1144*344aa361SAndroid Build Coastguard Worker void* ptr = NULL;
1145*344aa361SAndroid Build Coastguard Worker status_t ret;
1146*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_reserve", PAGE_SIZE * 2, &ptr, 0,
1147*344aa361SAndroid Build Coastguard Worker VMM_FLAG_NO_PHYSICAL, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1148*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1149*344aa361SAndroid Build Coastguard Worker ptr += PAGE_SIZE;
1150*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_from_reserved_outside_region",
1151*344aa361SAndroid Build Coastguard Worker PAGE_SIZE * 2, &ptr, 0,
1152*344aa361SAndroid Build Coastguard Worker VMM_FLAG_QUOTA | VMM_FLAG_VALLOC_SPECIFIC,
1153*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1154*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_INVALID_ARGS, ret);
1155*344aa361SAndroid Build Coastguard Worker test_abort:;
1156*344aa361SAndroid Build Coastguard Worker }
1157*344aa361SAndroid Build Coastguard Worker
1158*344aa361SAndroid Build Coastguard Worker /* Test suite for PMM */
1159*344aa361SAndroid Build Coastguard Worker
1160*344aa361SAndroid Build Coastguard Worker typedef struct {
1161*344aa361SAndroid Build Coastguard Worker vmm_aspace_t* aspace;
1162*344aa361SAndroid Build Coastguard Worker } mmutest_res_group_t;
1163*344aa361SAndroid Build Coastguard Worker
TEST_F_SETUP(mmutest_res_group)1164*344aa361SAndroid Build Coastguard Worker TEST_F_SETUP(mmutest_res_group) {
1165*344aa361SAndroid Build Coastguard Worker _state->aspace = NULL;
1166*344aa361SAndroid Build Coastguard Worker status_t ret = vmm_create_aspace_with_quota(&_state->aspace, "mmutestrg",
1167*344aa361SAndroid Build Coastguard Worker PAGE_SIZE, 0);
1168*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1169*344aa361SAndroid Build Coastguard Worker test_abort:;
1170*344aa361SAndroid Build Coastguard Worker }
1171*344aa361SAndroid Build Coastguard Worker
TEST_F_TEARDOWN(mmutest_res_group)1172*344aa361SAndroid Build Coastguard Worker TEST_F_TEARDOWN(mmutest_res_group) {
1173*344aa361SAndroid Build Coastguard Worker if (_state->aspace) {
1174*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, vmm_free_aspace(_state->aspace));
1175*344aa361SAndroid Build Coastguard Worker }
1176*344aa361SAndroid Build Coastguard Worker test_abort:;
1177*344aa361SAndroid Build Coastguard Worker }
1178*344aa361SAndroid Build Coastguard Worker
TEST_F(mmutest_res_group,reserve_group_too_big)1179*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_res_group, reserve_group_too_big) {
1180*344aa361SAndroid Build Coastguard Worker void* ptr;
1181*344aa361SAndroid Build Coastguard Worker status_t ret = vmm_alloc(_state->aspace, "test_alloc", PAGE_SIZE + 1, &ptr,
1182*344aa361SAndroid Build Coastguard Worker 0, VMM_FLAG_QUOTA, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1183*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
1184*344aa361SAndroid Build Coastguard Worker test_abort:;
1185*344aa361SAndroid Build Coastguard Worker }
1186*344aa361SAndroid Build Coastguard Worker
TEST_F(mmutest_res_group,reserve_group_release_ref)1187*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_res_group, reserve_group_release_ref) {
1188*344aa361SAndroid Build Coastguard Worker /* Destroying an aspace releases refs on its vmm_objs. */
1189*344aa361SAndroid Build Coastguard Worker status_t slice_init = ERR_INVALID_ARGS;
1190*344aa361SAndroid Build Coastguard Worker void* ptr;
1191*344aa361SAndroid Build Coastguard Worker struct vmm_obj_slice slice;
1192*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_init(&slice);
1193*344aa361SAndroid Build Coastguard Worker status_t alloc_ret =
1194*344aa361SAndroid Build Coastguard Worker vmm_alloc(_state->aspace, "test_alloc", PAGE_SIZE, &ptr, 0,
1195*344aa361SAndroid Build Coastguard Worker VMM_FLAG_QUOTA, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1196*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, alloc_ret);
1197*344aa361SAndroid Build Coastguard Worker slice_init = vmm_get_obj(_state->aspace, (vaddr_t)ptr, PAGE_SIZE, &slice);
1198*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, slice_init);
1199*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, vmm_free_aspace(_state->aspace));
1200*344aa361SAndroid Build Coastguard Worker _state->aspace = NULL;
1201*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(true, obj_has_only_ref(&slice.obj->obj, &slice.obj_ref));
1202*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_release(&slice);
1203*344aa361SAndroid Build Coastguard Worker test_abort:;
1204*344aa361SAndroid Build Coastguard Worker }
1205*344aa361SAndroid Build Coastguard Worker
TEST_F(mmutest_res_group,no_physical_inner_obj)1206*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_res_group, no_physical_inner_obj) {
1207*344aa361SAndroid Build Coastguard Worker void* ptr;
1208*344aa361SAndroid Build Coastguard Worker struct vmm_obj_slice slice;
1209*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_init(&slice);
1210*344aa361SAndroid Build Coastguard Worker status_t ret = vmm_alloc(_state->aspace, "test_alloc", PAGE_SIZE * 2, &ptr,
1211*344aa361SAndroid Build Coastguard Worker 0, VMM_FLAG_QUOTA | VMM_FLAG_NO_PHYSICAL,
1212*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1213*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_alloc", PAGE_SIZE, &ptr, 0,
1214*344aa361SAndroid Build Coastguard Worker VMM_FLAG_QUOTA | VMM_FLAG_VALLOC_SPECIFIC,
1215*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1216*344aa361SAndroid Build Coastguard Worker /* vmm_get_obj should look inside NO_PHYSICAL regions and return nested
1217*344aa361SAndroid Build Coastguard Worker * vmm_objs from inside. */
1218*344aa361SAndroid Build Coastguard Worker ret = vmm_get_obj(_state->aspace, (vaddr_t)ptr, PAGE_SIZE, &slice);
1219*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1220*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(PAGE_SIZE, slice.size);
1221*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, vmm_free_region(_state->aspace, (vaddr_t)ptr));
1222*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(true, obj_has_only_ref(&slice.obj->obj, &slice.obj_ref));
1223*344aa361SAndroid Build Coastguard Worker vmm_obj_slice_release(&slice);
1224*344aa361SAndroid Build Coastguard Worker test_abort:;
1225*344aa361SAndroid Build Coastguard Worker }
1226*344aa361SAndroid Build Coastguard Worker
TEST_F(mmutest_res_group,reserve_group_no_physical)1227*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_res_group, reserve_group_no_physical) {
1228*344aa361SAndroid Build Coastguard Worker /* NO_PHYSICAL allocations don't count towards memory usage. */
1229*344aa361SAndroid Build Coastguard Worker void* ptr;
1230*344aa361SAndroid Build Coastguard Worker status_t ret =
1231*344aa361SAndroid Build Coastguard Worker vmm_alloc(_state->aspace, "test_reserved_alloc", PAGE_SIZE * 10,
1232*344aa361SAndroid Build Coastguard Worker &ptr, 0, VMM_FLAG_QUOTA | VMM_FLAG_NO_PHYSICAL,
1233*344aa361SAndroid Build Coastguard Worker ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1234*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1235*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_alloc", PAGE_SIZE, &ptr, 0,
1236*344aa361SAndroid Build Coastguard Worker VMM_FLAG_QUOTA, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1237*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1238*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_alloc", PAGE_SIZE, &ptr, 0,
1239*344aa361SAndroid Build Coastguard Worker VMM_FLAG_QUOTA, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1240*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
1241*344aa361SAndroid Build Coastguard Worker test_abort:;
1242*344aa361SAndroid Build Coastguard Worker }
1243*344aa361SAndroid Build Coastguard Worker
TEST_F(mmutest_res_group,reserve_group_disable_quota)1244*344aa361SAndroid Build Coastguard Worker TEST_F(mmutest_res_group, reserve_group_disable_quota) {
1245*344aa361SAndroid Build Coastguard Worker /* Allocations without VMM_FLAG_QUOTA set don't count towards memory usage.
1246*344aa361SAndroid Build Coastguard Worker */
1247*344aa361SAndroid Build Coastguard Worker void* ptr;
1248*344aa361SAndroid Build Coastguard Worker status_t ret =
1249*344aa361SAndroid Build Coastguard Worker vmm_alloc(_state->aspace, "test_reserved_alloc", PAGE_SIZE * 10,
1250*344aa361SAndroid Build Coastguard Worker &ptr, 0, 0, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1251*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1252*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_alloc", PAGE_SIZE, &ptr, 0,
1253*344aa361SAndroid Build Coastguard Worker VMM_FLAG_QUOTA, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1254*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(NO_ERROR, ret);
1255*344aa361SAndroid Build Coastguard Worker ret = vmm_alloc(_state->aspace, "test_alloc", PAGE_SIZE, &ptr, 0,
1256*344aa361SAndroid Build Coastguard Worker VMM_FLAG_QUOTA, ARCH_MMU_FLAG_PERM_NO_EXECUTE);
1257*344aa361SAndroid Build Coastguard Worker ASSERT_EQ(ERR_NO_MEMORY, ret);
1258*344aa361SAndroid Build Coastguard Worker test_abort:;
1259*344aa361SAndroid Build Coastguard Worker }
1260*344aa361SAndroid Build Coastguard Worker
1261*344aa361SAndroid Build Coastguard Worker PORT_TEST(mmutest, "com.android.kernel.mmutest");
1262