1 /*
2 * Copyright (c) 2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <sys/sysctl.h>
30
31 extern kern_return_t test_pmap_enter_disconnect(unsigned int);
32 extern kern_return_t test_pmap_compress_remove(unsigned int);
33 extern kern_return_t test_pmap_exec_remove(unsigned int);
34 extern kern_return_t test_pmap_nesting(unsigned int);
35 extern kern_return_t test_pmap_iommu_disconnect(void);
36 extern kern_return_t test_pmap_extended(void);
37 extern void test_pmap_call_overhead(unsigned int);
38 extern uint64_t test_pmap_page_protect_overhead(unsigned int, unsigned int);
39 #if CONFIG_SPTM
40 extern kern_return_t test_pmap_huge_pv_list(unsigned int, unsigned int);
41 extern kern_return_t test_pmap_reentrance(unsigned int);
42 #endif
43
44 static int
sysctl_test_pmap_enter_disconnect(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)45 sysctl_test_pmap_enter_disconnect(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
46 {
47 unsigned int num_loops;
48 int error, changed;
49 error = sysctl_io_number(req, 0, sizeof(num_loops), &num_loops, &changed);
50 if (error || !changed) {
51 return error;
52 }
53 return test_pmap_enter_disconnect(num_loops);
54 }
55
56 SYSCTL_PROC(_kern, OID_AUTO, pmap_enter_disconnect_test,
57 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
58 0, 0, sysctl_test_pmap_enter_disconnect, "I", "");
59
60 static int
sysctl_test_pmap_compress_remove(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)61 sysctl_test_pmap_compress_remove(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
62 {
63 unsigned int num_loops;
64 int error, changed;
65 error = sysctl_io_number(req, 0, sizeof(num_loops), &num_loops, &changed);
66 if (error || !changed) {
67 return error;
68 }
69 return test_pmap_compress_remove(num_loops);
70 }
71
72 SYSCTL_PROC(_kern, OID_AUTO, pmap_compress_remove_test,
73 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
74 0, 0, sysctl_test_pmap_compress_remove, "I", "");
75
76 static int
sysctl_test_pmap_exec_remove(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)77 sysctl_test_pmap_exec_remove(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
78 {
79 unsigned int num_loops;
80 int error, changed;
81 error = sysctl_io_number(req, 0, sizeof(num_loops), &num_loops, &changed);
82 if (error || !changed) {
83 return error;
84 }
85 return test_pmap_exec_remove(num_loops);
86 }
87
88 SYSCTL_PROC(_kern, OID_AUTO, pmap_exec_remove_test,
89 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
90 0, 0, sysctl_test_pmap_exec_remove, "I", "");
91
92 static int
sysctl_test_pmap_nesting(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)93 sysctl_test_pmap_nesting(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
94 {
95 unsigned int num_loops;
96 int error, changed;
97 error = sysctl_io_number(req, 0, sizeof(num_loops), &num_loops, &changed);
98 if (error || !changed) {
99 return error;
100 }
101 return test_pmap_nesting(num_loops);
102 }
103 SYSCTL_PROC(_kern, OID_AUTO, pmap_nesting_test,
104 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
105 0, 0, sysctl_test_pmap_nesting, "I", "");
106
107 static int
sysctl_test_pmap_iommu_disconnect(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)108 sysctl_test_pmap_iommu_disconnect(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
109 {
110 unsigned int run = 0;
111 int error, changed;
112 error = sysctl_io_number(req, 0, sizeof(run), &run, &changed);
113 if (error || !changed) {
114 return error;
115 }
116 return test_pmap_iommu_disconnect();
117 }
118
119 SYSCTL_PROC(_kern, OID_AUTO, pmap_iommu_disconnect_test,
120 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
121 0, 0, sysctl_test_pmap_iommu_disconnect, "I", "");
122
123 static int
sysctl_test_pmap_extended(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)124 sysctl_test_pmap_extended(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
125 {
126 unsigned int run = 0;
127 int error, changed;
128 error = sysctl_io_number(req, 0, sizeof(run), &run, &changed);
129 if (error || !changed) {
130 return error;
131 }
132 return test_pmap_extended();
133 }
134
135 SYSCTL_PROC(_kern, OID_AUTO, pmap_extended_test,
136 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
137 0, 0, sysctl_test_pmap_extended, "I", "");
138
139 static int
sysctl_test_pmap_call_overhead(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)140 sysctl_test_pmap_call_overhead(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
141 {
142 unsigned int num_loops;
143 int error, changed;
144 error = sysctl_io_number(req, 0, sizeof(num_loops), &num_loops, &changed);
145 if (error || !changed) {
146 return error;
147 }
148 test_pmap_call_overhead(num_loops);
149 return 0;
150 }
151
152 SYSCTL_PROC(_kern, OID_AUTO, pmap_call_overhead_test,
153 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
154 0, 0, sysctl_test_pmap_call_overhead, "I", "");
155
156 static int
sysctl_test_pmap_page_protect_overhead(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)157 sysctl_test_pmap_page_protect_overhead(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
158 {
159 struct {
160 unsigned int num_loops;
161 unsigned int num_aliases;
162 } ppo_in;
163
164 int error;
165 uint64_t duration;
166
167 error = SYSCTL_IN(req, &ppo_in, sizeof(ppo_in));
168 if (error) {
169 return error;
170 }
171
172 duration = test_pmap_page_protect_overhead(ppo_in.num_loops, ppo_in.num_aliases);
173 error = SYSCTL_OUT(req, &duration, sizeof(duration));
174 return error;
175 }
176
177 SYSCTL_PROC(_kern, OID_AUTO, pmap_page_protect_overhead_test,
178 CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0, sysctl_test_pmap_page_protect_overhead, "-", "");
179
180 #if CONFIG_SPTM
181
182 static int
sysctl_test_pmap_huge_pv_list(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)183 sysctl_test_pmap_huge_pv_list(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
184 {
185 struct {
186 unsigned int num_loops;
187 unsigned int num_mappings;
188 } hugepv_in;
189
190 int error = SYSCTL_IN(req, &hugepv_in, sizeof(hugepv_in));
191 if (error) {
192 return error;
193 }
194 return test_pmap_huge_pv_list(hugepv_in.num_loops, hugepv_in.num_mappings);
195 }
196
197 SYSCTL_PROC(_kern, OID_AUTO, pmap_huge_pv_list_test,
198 CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0, sysctl_test_pmap_huge_pv_list, "-", "");
199
200 static int
sysctl_test_pmap_reentrance(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)201 sysctl_test_pmap_reentrance(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
202 {
203 unsigned int num_loops;
204 int error, changed;
205 error = sysctl_io_number(req, 0, sizeof(num_loops), &num_loops, &changed);
206 if (error || !changed) {
207 return error;
208 }
209 return test_pmap_reentrance(num_loops);
210 }
211
212 SYSCTL_PROC(_kern, OID_AUTO, pmap_reentrance_test,
213 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
214 0, 0, sysctl_test_pmap_reentrance, "I", "");
215
216 #endif
217