1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13#include <autoconf.h>
14#include <assert.h>
15
16#include <sel4/sel4.h>
17#include <vka/object.h>
18#include <utils/util.h>
19
20#include "../helpers.h"
21#include "frame_type.h"
22
23#if defined(CONFIG_ARCH_ARM)
24static int fill_memory(seL4_Word addr, seL4_Word size_bytes)
25{
26    test_assert(IS_ALIGNED(addr, sizeof(seL4_Word)));
27    test_assert(IS_ALIGNED(size_bytes, sizeof(seL4_Word)));
28    seL4_Word *p = (void *)addr;
29    seL4_Word size_words = size_bytes / sizeof(seL4_Word);
30    while (size_words--) {
31        *p++ = size_words ^ 0xbeefcafe;
32    }
33    return SUCCESS;
34}
35
36static int __attribute__((warn_unused_result))
37check_memory(seL4_Word addr, seL4_Word size_bytes)
38{
39    test_assert(IS_ALIGNED(addr, sizeof(seL4_Word)));
40    test_assert(IS_ALIGNED(size_bytes, sizeof(seL4_Word)));
41    seL4_Word *p = (void *)addr;
42    seL4_Word size_words = size_bytes / sizeof(seL4_Word);
43    while (size_words--) {
44        if (*p++ != (size_words ^ 0xbeefcafe)) {
45            return 0;
46        }
47    }
48    return 1;
49}
50
51#if defined(CONFIG_ARCH_AARCH32)
52#define LPAGE_SIZE   (1 << (vka_get_object_size(seL4_ARM_LargePageObject, 0)))
53#define SECT_SIZE    (1 << (vka_get_object_size(seL4_ARM_SectionObject, 0)))
54#define SUPSECT_SIZE (1 << (vka_get_object_size(seL4_ARM_SuperSectionObject, 0)))
55
56/* Assumes caps can be mapped in at vaddr (= [vaddr,vaddr + 3*size) */
57static int do_test_pagetable_tlbflush_on_vaddr_reuse(env_t env, seL4_CPtr cap1, seL4_CPtr cap2, seL4_Word vstart,
58                                                     seL4_Word size)
59{
60    int error;
61    seL4_Word vaddr;
62    volatile seL4_Word *vptr = NULL;
63
64    /* map, touch page 1 */
65    vaddr = vstart;
66    vptr = (seL4_Word *)vaddr;
67    error = seL4_ARM_Page_Map(cap1, env->page_directory,
68                              vaddr, seL4_AllRights,
69                              seL4_ARM_Default_VMAttributes);
70    test_error_eq(error, 0);
71    vptr[0] = 1;
72    error = seL4_ARM_Page_Unmap(cap1);
73    test_error_eq(error, 0);
74
75    /* map, touch page 2 */
76    vaddr = vstart + size;
77    vptr = (seL4_Word *)vaddr;
78    error = seL4_ARM_Page_Map(cap2, env->page_directory,
79                              vaddr, seL4_AllRights,
80                              seL4_ARM_Default_VMAttributes);
81    test_error_eq(error, 0);
82    vptr[0] = 2;
83    error = seL4_ARM_Page_Unmap(cap2);
84    test_error_eq(error, 0);
85
86    /* Test TLB */
87    vaddr = vstart + 2 * size;
88    vptr = (seL4_Word *)vaddr;
89    error = seL4_ARM_Page_Map(cap1, env->page_directory,
90                              vaddr, seL4_AllRights,
91                              seL4_ARM_Default_VMAttributes);
92    test_error_eq(error, 0);
93    test_check(vptr[0] == 1);
94
95    error = seL4_ARM_Page_Map(cap2, env->page_directory,
96                              vaddr, seL4_AllRights,
97                              seL4_ARM_Default_VMAttributes);
98    test_error_eq(error, 0);
99    test_check(vptr[0] == 2 || !"TLB contains stale entry");
100
101    /* clean up */
102    error = seL4_ARM_Page_Unmap(cap1);
103    test_error_eq(error, 0);
104    error = seL4_ARM_Page_Unmap(cap2);
105    test_error_eq(error, 0);
106    return sel4test_get_result();
107}
108
109static int test_pagetable_arm(env_t env)
110{
111    int error;
112
113    /* Grab some free vspace big enough to hold a couple of supersections. */
114    seL4_Word vstart;
115    reservation_t reserve = vspace_reserve_range(&env->vspace, SUPSECT_SIZE * 4,
116                                                 seL4_AllRights, 1, (void **) &vstart);
117    vstart = ALIGN_UP(vstart, SUPSECT_SIZE * 2);
118
119    /* Create us some frames to play with. */
120    seL4_CPtr small_page = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0);
121    seL4_CPtr small_page2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0);
122    seL4_CPtr large_page = vka_alloc_object_leaky(&env->vka, seL4_ARM_LargePageObject, 0);
123    seL4_CPtr section = vka_alloc_object_leaky(&env->vka, seL4_ARM_SectionObject, 0);
124    seL4_CPtr supersection = vka_alloc_object_leaky(&env->vka, seL4_ARM_SuperSectionObject, 0);
125
126    test_assert(small_page != 0);
127    test_assert(small_page2 != 0);
128    test_assert(large_page != 0);
129    test_assert(section != 0);
130    test_assert(supersection != 0);
131
132    /* Also create a pagetable to map the pages into. */
133    seL4_CPtr pt = vka_alloc_page_table_leaky(&env->vka);
134
135    /* Check we can't map the supersection in at an address it's not aligned
136     * to. */
137    test_assert(supersection != 0);
138    error = seL4_ARM_Page_Map(supersection, env->page_directory,
139                              vstart + SUPSECT_SIZE / 2, seL4_AllRights, seL4_ARM_Default_VMAttributes);
140    test_error_eq(error, seL4_AlignmentError);
141
142    /* Check we can map it in somewhere correctly aligned. */
143    error = seL4_ARM_Page_Map(supersection, env->page_directory,
144                              vstart + SUPSECT_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes);
145    test_error_eq(error, 0);
146
147    /* Now fill it with stuff to check later. */
148    /* TDDO fx these constants */
149    error = fill_memory(vstart + SUPSECT_SIZE, SUPSECT_SIZE);
150    test_assert(error == SUCCESS);
151
152    /* Check we now can't map a section over the top. */
153    error = seL4_ARM_Page_Map(section, env->page_directory,
154                              vstart + SUPSECT_SIZE + SUPSECT_SIZE / 2, seL4_AllRights,
155                              seL4_ARM_Default_VMAttributes);
156    test_error_eq(error, seL4_DeleteFirst);
157
158    /* Unmapping the section shouldn't do anything. */
159    error = seL4_ARM_Page_Unmap(section);
160    test_error_eq(error, 0);
161
162    /* Unmap supersection and try again. */
163    error = seL4_ARM_Page_Unmap(supersection);
164    test_error_eq(error, 0);
165
166    error = seL4_ARM_Page_Map(section, env->page_directory,
167                              vstart + SUPSECT_SIZE + SUPSECT_SIZE / 2, seL4_AllRights,
168                              seL4_ARM_Default_VMAttributes);
169    test_error_eq(error, 0);
170
171    fill_memory(vstart + SUPSECT_SIZE + SUPSECT_SIZE / 2, SECT_SIZE);
172
173    /* Now that a section is there, see if we can map a supersection over the
174     * top. */
175    error = seL4_ARM_Page_Map(supersection, env->page_directory,
176                              vstart + SUPSECT_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes);
177    test_error_eq(error, seL4_DeleteFirst);
178
179    if (!check_memory(vstart + SUPSECT_SIZE + SUPSECT_SIZE / 2, SECT_SIZE)) {
180        return FAILURE;
181    }
182
183    /* Unmap the section, leaving nothing mapped. */
184    error = seL4_ARM_Page_Unmap(section);
185    test_error_eq(error, 0);
186
187    /* Now, try mapping in the supersection into two places. */
188    error = seL4_ARM_Page_Map(supersection, env->page_directory,
189                              vstart, seL4_AllRights, seL4_ARM_Default_VMAttributes);
190    test_error_eq(error, 0);
191    error = seL4_ARM_Page_Map(supersection, env->page_directory,
192                              vstart + SUPSECT_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes);
193    test_error_eq(error, seL4_InvalidArgument);
194
195    /* Now check what we'd written earlier is still there. */
196    test_assert(check_memory(vstart, SUPSECT_SIZE));
197
198    /* Try mapping the section into two places. */
199    error = seL4_ARM_Page_Map(section, env->page_directory,
200                              vstart + 2 * SUPSECT_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes);
201    test_error_eq(error, 0);
202    error = seL4_ARM_Page_Map(section, env->page_directory,
203                              vstart + SUPSECT_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes);
204    test_error_eq(error, seL4_InvalidArgument);
205
206    /* Unmap everything again. */
207    error = seL4_ARM_Page_Unmap(section);
208    test_error_eq(error, 0);
209    error = seL4_ARM_Page_Unmap(supersection);
210    test_error_eq(error, 0);
211
212    /* Map a large page somewhere with no pagetable. */
213    error = seL4_ARM_Page_Map(large_page, env->page_directory,
214                              vstart, seL4_AllRights, seL4_ARM_Default_VMAttributes);
215    test_error_eq(error, seL4_FailedLookup);
216
217    /* Map a pagetable at an unaligned address. Oddly enough, this will succeed
218     * as the kernel silently truncates the address to the nearest correct
219     * boundary. */
220    error = seL4_ARM_PageTable_Map(pt, env->page_directory,
221                                   vstart + SECT_SIZE + 10, seL4_ARM_Default_VMAttributes);
222    test_error_eq(error, 0);
223
224    /* Map the large page in at an unaligned address. */
225    error = seL4_ARM_Page_Map(large_page, env->page_directory,
226                              vstart + SECT_SIZE + LPAGE_SIZE / 2,
227                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
228    test_error_eq(error, seL4_AlignmentError);
229
230    /* Map the large page in at an aligned address. */
231    error = seL4_ARM_Page_Map(large_page, env->page_directory,
232                              vstart + SECT_SIZE + LPAGE_SIZE,
233                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
234    test_error_eq(error, 0);
235
236    /* Map it again, to a different vaddr, and it should fail. */
237    error = seL4_ARM_Page_Map(large_page, env->page_directory,
238                              vstart + SECT_SIZE + 2 * LPAGE_SIZE,
239                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
240    test_error_eq(error, seL4_InvalidArgument);
241
242    /* Fill it with more stuff to check. */
243    fill_memory(vstart + SECT_SIZE + LPAGE_SIZE, LPAGE_SIZE);
244
245    /* Try mapping a small page over the top of it. */
246    error = seL4_ARM_Page_Map(small_page, env->page_directory,
247                              vstart + SECT_SIZE + LPAGE_SIZE,
248                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
249    test_error_eq(error, seL4_DeleteFirst);
250
251    /* Try mapping a small page elsewhere useful. */
252    error = seL4_ARM_Page_Map(small_page, env->page_directory,
253                              vstart + SECT_SIZE + 3 * LPAGE_SIZE,
254                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
255    test_error_eq(error, 0);
256
257    /* Fill the small page with useful data too. */
258    fill_memory(vstart + SECT_SIZE + 3 * LPAGE_SIZE, PAGE_SIZE_4K);
259
260    /* Pull the plug on the page table. Apparently a recycle isn't good enough.
261     * Get another pagetable! */
262    error = seL4_CNode_Delete(env->cspace_root, pt, seL4_WordBits);
263    test_error_eq(error, 0);
264    error = seL4_ARM_Page_Unmap(small_page);
265    test_error_eq(error, 0);
266    error = seL4_ARM_Page_Unmap(large_page);
267    test_error_eq(error, 0);
268    pt = vka_alloc_page_table_leaky(&env->vka);
269
270    /* Map the pagetable somewhere new. */
271    error = seL4_ARM_PageTable_Map(pt, env->page_directory,
272                                   vstart, seL4_ARM_Default_VMAttributes);
273    test_error_eq(error, 0);
274
275    /* Map our small page and large page back in. */
276    error = seL4_ARM_Page_Map(small_page, env->page_directory,
277                              vstart + PAGE_SIZE_4K,
278                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
279    test_error_eq(error, 0);
280
281    error = seL4_ARM_Page_Map(large_page, env->page_directory,
282                              vstart + LPAGE_SIZE,
283                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
284    test_error_eq(error, 0);
285
286    /* Check their contents. */
287    test_assert(check_memory(vstart + PAGE_SIZE_4K, PAGE_SIZE_4K));
288    test_assert(check_memory(vstart + LPAGE_SIZE, LPAGE_SIZE));
289
290    /* Now unmap the small page */
291    error = seL4_ARM_Page_Unmap(small_page);
292    test_error_eq(error, 0);
293
294    /* Unmap the large page. */
295    error = seL4_ARM_Page_Unmap(large_page);
296    test_error_eq(error, 0);
297
298    /* Now map the large page where the small page was. */
299    error = seL4_ARM_Page_Map(large_page, env->page_directory,
300                              vstart,
301                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
302    test_error_eq(error, 0);
303
304    /* Now check the contents of the large page. */
305    test_assert(check_memory(vstart, LPAGE_SIZE));
306
307    /* Map the small page elsewhere. */
308    error = seL4_ARM_Page_Map(small_page, env->page_directory,
309                              vstart + LPAGE_SIZE,
310                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
311    test_error_eq(error, 0);
312
313    /* Now unmap the small page */
314    error = seL4_ARM_Page_Unmap(small_page);
315    test_error_eq(error, 0);
316
317    /* Map a different small page in its place. */
318    error = seL4_ARM_Page_Map(small_page2, env->page_directory,
319                              vstart + LPAGE_SIZE,
320                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
321    test_error_eq(error, 0);
322
323    /* Fill it in with stuff. */
324    fill_memory(vstart + LPAGE_SIZE, PAGE_SIZE_4K);
325
326    vspace_free_reservation(&env->vspace, reserve);
327
328    return sel4test_get_result();
329}
330DEFINE_TEST(PT0001, "Fun with page tables on ARM", test_pagetable_arm, true)
331
332static int
333test_pagetable_tlbflush_on_vaddr_reuse(env_t env)
334{
335    int error;
336    int result = SUCCESS;
337
338    /* Grab some free vspace big enough to hold a couple of supersections. */
339    void *vstart;
340    reservation_t reserve = vspace_reserve_range_aligned(&env->vspace, VSPACE_RV_SIZE, VSPACE_RV_ALIGN_BITS,
341                                                         seL4_AllRights, 1, &vstart);
342    test_assert(reserve.res);
343
344    seL4_CPtr cap1, cap2;
345    /* Create us some frames to play with. */
346
347    /* Also create a pagetable to map the pages into. */
348    seL4_CPtr pt = vka_alloc_page_table_leaky(&env->vka);
349
350    /* supersection */
351    cap1 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SuperSectionObject, 0);
352    cap2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SuperSectionObject, 0);
353    if (do_test_pagetable_tlbflush_on_vaddr_reuse(env, cap1, cap2, (uintptr_t)vstart, SUPSECT_SIZE) == FAILURE) {
354        result = FAILURE;
355    }
356    /* section */
357    cap1 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SectionObject, 0);
358    cap2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SectionObject, 0);
359    if (do_test_pagetable_tlbflush_on_vaddr_reuse(env, cap1, cap2, (uintptr_t)vstart, SUPSECT_SIZE) == FAILURE) {
360        result = FAILURE;
361    }
362
363    /* map a PT for smaller page objects */
364    error = seL4_ARM_PageTable_Map(pt, env->page_directory,
365                                   (seL4_Word)vstart, seL4_ARM_Default_VMAttributes);
366    test_error_eq(error, 0);
367
368    /* Large page */
369    cap1 = vka_alloc_object_leaky(&env->vka, seL4_ARM_LargePageObject, 0);
370    cap2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_LargePageObject, 0);
371    if (do_test_pagetable_tlbflush_on_vaddr_reuse(env, cap1, cap2, (uintptr_t)vstart, LPAGE_SIZE) == FAILURE) {
372        result = FAILURE;
373    }
374    /* small page */
375    cap1 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0);
376    cap2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0);
377    if (do_test_pagetable_tlbflush_on_vaddr_reuse(env, cap1, cap2, (uintptr_t)vstart, PAGE_SIZE_4K) == FAILURE) {
378        result = FAILURE;
379    }
380
381    return result;
382}
383DEFINE_TEST(PT0002, "Reusing virtual addresses flushes TLB", test_pagetable_tlbflush_on_vaddr_reuse, true)
384
385#elif defined(CONFIG_ARCH_AARCH64)
386#define LPAGE_SIZE   (1 << (vka_get_object_size(seL4_ARM_LargePageObject, 0)))
387
388static int
389test_pagetable_arm(env_t env)
390{
391    int error;
392
393    /* Grab some free vspace big enough to hold a couple of large pages. */
394    seL4_Word vstart;
395    reservation_t reserve = vspace_reserve_range(&env->vspace, LPAGE_SIZE * 4,
396                                                 seL4_AllRights, 1, (void **) &vstart);
397    vstart = ALIGN_UP(vstart, LPAGE_SIZE * 2);
398
399    /* Create us some frames to play with. */
400    seL4_CPtr small_page = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0);
401    seL4_CPtr small_page2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0);
402    seL4_CPtr large_page = vka_alloc_object_leaky(&env->vka, seL4_ARM_LargePageObject, 0);
403
404    test_assert(small_page != 0);
405    test_assert(small_page2 != 0);
406    test_assert(large_page != 0);
407
408    /* Also create a pagetable to map the pages into. */
409    seL4_CPtr pt = vka_alloc_page_table_leaky(&env->vka);
410
411    /* Check we can't map the large page in at an address it's not aligned to. */
412    error = seL4_ARM_Page_Map(large_page, env->page_directory,
413                              vstart + LPAGE_SIZE / 2, seL4_AllRights, seL4_ARM_Default_VMAttributes);
414    test_error_eq(error, seL4_AlignmentError);
415
416    /* Check we can map it in somewhere correctly aligned. */
417    error = seL4_ARM_Page_Map(large_page, env->page_directory,
418                              vstart + LPAGE_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes);
419    test_error_eq(error, 0);
420
421    /* Unmap large page and try again. */
422    error = seL4_ARM_Page_Unmap(large_page);
423    test_error_eq(error, 0);
424
425    error = seL4_ARM_Page_Map(large_page, env->page_directory,
426                              vstart + LPAGE_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes);
427    test_error_eq(error, 0);
428
429    fill_memory(vstart + LPAGE_SIZE, LPAGE_SIZE);
430
431    /* Unmap the large page, leaving nothing mapped. */
432    error = seL4_ARM_Page_Unmap(large_page);
433    test_error_eq(error, 0);
434
435    /* Now, try mapping in the large page into two places. */
436    error = seL4_ARM_Page_Map(large_page, env->page_directory,
437                              vstart, seL4_AllRights, seL4_ARM_Default_VMAttributes);
438    test_error_eq(error, 0);
439
440    /* Trying to remap to a different vaddr */
441    error = seL4_ARM_Page_Map(large_page, env->page_directory,
442                              vstart + LPAGE_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes);
443    test_error_eq(error, seL4_InvalidArgument);
444
445    /* Now check what we'd written earlier is still there. */
446    test_assert(check_memory(vstart, LPAGE_SIZE));
447
448    /* Unmap everything again. */
449    error = seL4_ARM_Page_Unmap(large_page);
450    test_error_eq(error, 0);
451
452    /* Map a small page somewhere with no pagetable. */
453    error = seL4_ARM_Page_Map(small_page, env->page_directory,
454                              vstart, seL4_AllRights, seL4_ARM_Default_VMAttributes);
455    test_error_eq(error, seL4_FailedLookup);
456
457    /* Map a pagetable at an unaligned address. Oddly enough, this will succeed
458     * as the kernel silently truncates the address to the nearest correct
459     * boundary. */
460    error = seL4_ARM_PageTable_Map(pt, env->page_directory,
461                                   vstart + LPAGE_SIZE + 10, seL4_ARM_Default_VMAttributes);
462    test_error_eq(error, 0);
463
464    /* Try mapping a small page. */
465    error = seL4_ARM_Page_Map(small_page, env->page_directory, vstart + LPAGE_SIZE + PAGE_SIZE_4K,
466                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
467    test_error_eq(error, 0);
468
469    /* Fill the small page with useful data too. */
470    fill_memory(vstart + LPAGE_SIZE + PAGE_SIZE_4K, PAGE_SIZE_4K);
471
472    /* Pull the plug on the page table. Apparently a recycle isn't good enough.
473     * Get another pagetable! */
474    error = seL4_CNode_Delete(env->cspace_root, pt, seL4_WordBits);
475    test_error_eq(error, 0);
476    error = seL4_ARM_Page_Unmap(small_page);
477    test_error_eq(error, 0);
478    error = seL4_ARM_Page_Unmap(large_page);
479    test_error_eq(error, 0);
480    pt = vka_alloc_page_table_leaky(&env->vka);
481
482    /* Map the pagetable somewhere new. */
483    error = seL4_ARM_PageTable_Map(pt, env->page_directory,
484                                   vstart, seL4_ARM_Default_VMAttributes);
485    test_error_eq(error, 0);
486
487    /* Map our small page and large page back in. */
488    error = seL4_ARM_Page_Map(small_page, env->page_directory,
489                              vstart + PAGE_SIZE_4K,
490                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
491    test_error_eq(error, 0);
492
493    error = seL4_ARM_Page_Map(large_page, env->page_directory,
494                              vstart + LPAGE_SIZE,
495                              seL4_AllRights, seL4_ARM_Default_VMAttributes);
496    test_error_eq(error, 0);
497
498    /* Check their contents. */
499    test_assert(check_memory(vstart + PAGE_SIZE_4K, PAGE_SIZE_4K));
500    test_assert(check_memory(vstart + LPAGE_SIZE, LPAGE_SIZE));
501
502    /* Now unmap the small page */
503    error = seL4_ARM_Page_Unmap(small_page);
504    test_error_eq(error, 0);
505
506    /* Unmap the large page. */
507    error = seL4_ARM_Page_Unmap(large_page);
508    test_error_eq(error, 0);
509
510    vspace_free_reservation(&env->vspace, reserve);
511
512    return sel4test_get_result();
513}
514DEFINE_TEST(PT0001, "Fun with page tables on ARM", test_pagetable_arm, true)
515#endif /* CONFIG_ARCH_AARCHxx */
516#endif /* CONFIG_ARCH_ARM */
517