xref: /freebsd/sys/arm/arm/sys_machdep.c (revision 05296a0ff615566d25c77c5e6619b08724d2eecb)
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