]>
Commit | Line | Data |
---|---|---|
d9a64523 A |
1 | /* |
2 | * Copyright (c) 2016 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
0a7de745 | 5 | * |
d9a64523 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
0a7de745 | 14 | * |
d9a64523 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
0a7de745 | 17 | * |
d9a64523 A |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
0a7de745 | 25 | * |
d9a64523 A |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ | |
28 | ||
29 | #include <vm/vm_page.h> | |
30 | #include <vm/pmap.h> | |
31 | #include <kern/ledger.h> | |
32 | #include <kern/thread.h> | |
cb323159 A |
33 | #if defined(__arm64__) |
34 | #include <pexpert/arm64/board_config.h> | |
35 | #endif | |
d9a64523 A |
36 | |
37 | extern ledger_template_t task_ledger_template; | |
38 | ||
cb323159 A |
39 | extern boolean_t arm_force_fast_fault(ppnum_t, vm_prot_t, int, void*); |
40 | extern kern_return_t arm_fast_fault(pmap_t, vm_map_address_t, vm_prot_t, bool, bool); | |
41 | ||
d9a64523 A |
42 | kern_return_t test_pmap_enter_disconnect(unsigned int num_loops); |
43 | kern_return_t test_pmap_iommu_disconnect(void); | |
cb323159 | 44 | kern_return_t test_pmap_extended(void); |
d9a64523 A |
45 | |
46 | #define PMAP_TEST_VA (0xDEAD << PAGE_SHIFT) | |
47 | ||
48 | typedef struct { | |
49 | pmap_t pmap; | |
50 | volatile boolean_t stop; | |
51 | ppnum_t pn; | |
0a7de745 | 52 | } pmap_test_thread_args; |
d9a64523 A |
53 | |
54 | static pmap_t | |
cb323159 | 55 | pmap_create_wrapper(unsigned int flags) |
0a7de745 | 56 | { |
d9a64523 A |
57 | pmap_t new_pmap = NULL; |
58 | ledger_t ledger; | |
59 | assert(task_ledger_template != NULL); | |
0a7de745 | 60 | if ((ledger = ledger_instantiate(task_ledger_template, LEDGER_CREATE_ACTIVE_ENTRIES)) == NULL) { |
d9a64523 | 61 | return NULL; |
0a7de745 | 62 | } |
cb323159 | 63 | new_pmap = pmap_create_options(ledger, 0, flags); |
d9a64523 A |
64 | ledger_dereference(ledger); |
65 | return new_pmap; | |
66 | } | |
67 | ||
68 | static void | |
0a7de745 A |
69 | pmap_disconnect_thread(void *arg, wait_result_t __unused wres) |
70 | { | |
d9a64523 A |
71 | pmap_test_thread_args *args = arg; |
72 | do { | |
73 | pmap_disconnect(args->pn); | |
74 | } while (!args->stop); | |
75 | thread_wakeup((event_t)args); | |
76 | } | |
77 | ||
78 | kern_return_t | |
79 | test_pmap_enter_disconnect(unsigned int num_loops) | |
80 | { | |
81 | kern_return_t kr = KERN_SUCCESS; | |
82 | thread_t disconnect_thread; | |
cb323159 | 83 | pmap_t new_pmap = pmap_create_wrapper(0); |
0a7de745 | 84 | if (new_pmap == NULL) { |
d9a64523 | 85 | return KERN_FAILURE; |
0a7de745 | 86 | } |
d9a64523 A |
87 | vm_page_t m = vm_page_grab(); |
88 | if (m == VM_PAGE_NULL) { | |
89 | pmap_destroy(new_pmap); | |
90 | return KERN_FAILURE; | |
91 | } | |
92 | ppnum_t phys_page = VM_PAGE_GET_PHYS_PAGE(m); | |
93 | pmap_test_thread_args args = {new_pmap, FALSE, phys_page}; | |
94 | kern_return_t res = kernel_thread_start(pmap_disconnect_thread, &args, &disconnect_thread); | |
95 | if (res) { | |
96 | pmap_destroy(new_pmap); | |
97 | vm_page_lock_queues(); | |
98 | vm_page_free(m); | |
99 | vm_page_unlock_queues(); | |
100 | return res; | |
101 | } | |
102 | thread_deallocate(disconnect_thread); | |
103 | ||
104 | while (num_loops-- != 0) { | |
105 | kr = pmap_enter(new_pmap, PMAP_TEST_VA, phys_page, | |
0a7de745 | 106 | VM_PROT_READ | VM_PROT_WRITE, VM_PROT_NONE, VM_WIMG_USE_DEFAULT, FALSE); |
d9a64523 A |
107 | assert(kr == KERN_SUCCESS); |
108 | } | |
109 | ||
110 | assert_wait((event_t)&args, THREAD_UNINT); | |
111 | args.stop = TRUE; | |
112 | thread_block(THREAD_CONTINUE_NULL); | |
113 | ||
114 | pmap_remove(new_pmap, PMAP_TEST_VA, PMAP_TEST_VA + PAGE_SIZE); | |
115 | vm_page_lock_queues(); | |
116 | vm_page_free(m); | |
117 | vm_page_unlock_queues(); | |
118 | pmap_destroy(new_pmap); | |
119 | return KERN_SUCCESS; | |
120 | } | |
121 | ||
122 | kern_return_t | |
123 | test_pmap_iommu_disconnect(void) | |
124 | { | |
125 | return KERN_SUCCESS; | |
126 | } | |
cb323159 | 127 | |
f427ee49 | 128 | |
cb323159 A |
129 | kern_return_t |
130 | test_pmap_extended(void) | |
131 | { | |
132 | return KERN_SUCCESS; | |
133 | } |