xref: /aosp_15_r20/trusty/kernel/app/mmutest/mmutest.c (revision 344aa361028b423587d4ef3fa52a23d194628137)
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