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