1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * from: @(#)sys_machdep.c 5.5 (Berkeley) 1/19/91
32 */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include "opt_capsicum.h"
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/capsicum.h>
42 #include <sys/proc.h>
43 #include <sys/sysproto.h>
44 #include <sys/syscall.h>
45 #include <sys/sysent.h>
46 #include <vm/vm.h>
47 #include <vm/vm_extern.h>
48
49 #include <machine/cpu.h>
50 #include <machine/sysarch.h>
51 #include <machine/machdep.h>
52 #include <machine/vmparam.h>
53
54 #ifndef _SYS_SYSPROTO_H_
55 struct sysarch_args {
56 int op;
57 char *parms;
58 };
59 #endif
60
61 /* Prototypes */
62 static int arm32_sync_icache (struct thread *, void *);
63 static int arm32_drain_writebuf(struct thread *, void *);
64
65 static int
66 sync_icache(uintptr_t addr, size_t len)
67 {
68 size_t size;
69 vm_offset_t rv;
70
71 /* Align starting address to cacheline size */
72 len += addr & cpuinfo.dcache_line_mask;
73 addr &= ~cpuinfo.dcache_line_mask;
74
75 /* Break whole range to pages. */
76 do {
77 size = PAGE_SIZE - (addr & PAGE_MASK);
78 size = min(size, len);
79 rv = dcache_wb_pou_checked(addr, size);
80 if (rv == 1) /* see dcache_wb_pou_checked() */
81 rv = icache_inv_pou_checked(addr, size);
82 if (rv != 1) {
83 if (!useracc((void *)addr, size, VM_PROT_READ)) {
84 /* Invalid access */
85 return (rv);
86 }
87 /* Valid but unmapped page - skip it. */
88 }
89 len -= size;
90 addr += size;
91 } while (len > 0);
92
93 /* Invalidate branch predictor buffer. */
94 bpb_inv_all();
95 return (1);
96 }
97
98 static int
99 arm32_sync_icache(struct thread *td, void *args)
100 {
101 struct arm_sync_icache_args ua;
102 int error;
103 ksiginfo_t ksi;
104 vm_offset_t rv;
105
106 if ((error = copyin(args, &ua, sizeof(ua))) != 0)
107 return (error);
108
109 if (ua.len == 0) {
110 td->td_retval[0] = 0;
111 return (0);
112 }
113
114 /*
115 * Validate arguments. Address and length are unsigned,
116 * so we can use wrapped overflow check.
117 */
118 if (((ua.addr + ua.len) < ua.addr) ||
119 ((ua.addr + ua.len) > VM_MAXUSER_ADDRESS)) {
120 ksiginfo_init_trap(&ksi);
121 ksi.ksi_signo = SIGSEGV;
122 ksi.ksi_code = SEGV_ACCERR;
123 ksi.ksi_addr = (void *)max(ua.addr, VM_MAXUSER_ADDRESS);
124 trapsignal(td, &ksi);
125 return (EINVAL);
126 }
127
128 rv = sync_icache(ua.addr, ua.len);
129 if (rv != 1) {
130 ksiginfo_init_trap(&ksi);
131 ksi.ksi_signo = SIGSEGV;
132 ksi.ksi_code = SEGV_MAPERR;
133 ksi.ksi_addr = (void *)rv;
134 trapsignal(td, &ksi);
135 return (EINVAL);
136 }
137
138 td->td_retval[0] = 0;
139 return (0);
140 }
141
142 static int
143 arm32_drain_writebuf(struct thread *td, void *args)
144 {
145 /* No args. */
146
147 dsb();
148 cpu_l2cache_drain_writebuf();
149 td->td_retval[0] = 0;
150 return (0);
151 }
152
153 static int
154 arm32_set_tp(struct thread *td, void *args)
155 {
156
157 set_tls(args);
158 return (0);
159 }
160
161 static int
162 arm32_get_tp(struct thread *td, void *args)
163 {
164
165 td->td_retval[0] = (register_t)get_tls();
166 return (0);
167 }
168
169 int
170 sysarch(struct thread *td, struct sysarch_args *uap)
171 {
172 int error;
173
174 #ifdef CAPABILITY_MODE
175 /*
176 * When adding new operations, add a new case statement here to
177 * explicitly indicate whether or not the operation is safe to
178 * perform in capability mode.
179 */
180 if (IN_CAPABILITY_MODE(td)) {
181 switch (uap->op) {
182 case ARM_SYNC_ICACHE:
183 case ARM_DRAIN_WRITEBUF:
184 case ARM_SET_TP:
185 case ARM_GET_TP:
186 case ARM_GET_VFPSTATE:
187 break;
188
189 default:
190 #ifdef KTRACE
191 if (KTRPOINT(td, KTR_CAPFAIL))
192 ktrcapfail(CAPFAIL_SYSCALL, NULL, NULL);
193 #endif
194 return (ECAPMODE);
195 }
196 }
197 #endif
198
199 switch (uap->op) {
200 case ARM_SYNC_ICACHE:
201 error = arm32_sync_icache(td, uap->parms);
202 break;
203 case ARM_DRAIN_WRITEBUF:
204 error = arm32_drain_writebuf(td, uap->parms);
205 break;
206 case ARM_SET_TP:
207 error = arm32_set_tp(td, uap->parms);
208 break;
209 case ARM_GET_TP:
210 error = arm32_get_tp(td, uap->parms);
211 break;
212 case ARM_GET_VFPSTATE:
213 error = arm_get_vfpstate(td, uap->parms);
214 break;
215 default:
216 error = EINVAL;
217 break;
218 }
219 return (error);
220 }
Cache object: 020b7a998cd8922aceabea17508058d5
|