Pull up following revision(s) (requested by rin in ticket #1172): sys/arch/aarch64/aarch64/trap.c: revision 1.30 sys/arch/aarch64/include/ptrace.h: revision 1.10 sys/arch/aarch64/include/netbsd32_machdep.h: revision 1.4 (patch) sys/arch/aarch64/aarch64/netbsd32_machdep.c: revision 1.14 sys/arch/aarch64/aarch64/netbsd32_machdep.c: revision 1.15 Add support of ptrace(2) for COMPAT_NETBSD32. Now, GDB for arm32 is usable for debugging 32bit applications. OK ryo@ For rev 1.14 and before, netbsd32_process_write_regs() returns EINVAL if non-modifiable bits are set in CPSR. Instead, mask out non-modifiable bits and make this function success regardless of value in CPSR. New behavior matches that of arm: https://nxr.netbsd.org/xref/src/sys/arch/arm/arm/process_machdep.c#187 This fixes lib/libc/sys/t_ptrace_wait*:access_regs6 tests, in which register contents retrieved by PT_GETREGS are set back by PT_SETREGS. No new regression is observed in full ATF run. OK ryodiff -r1.7.2.1 -r1.7.2.2 src/sys/arch/aarch64/aarch64/netbsd32_machdep.c
(martin)
--- src/sys/arch/aarch64/aarch64/netbsd32_machdep.c 2020/05/02 16:26:04 1.7.2.1
+++ src/sys/arch/aarch64/aarch64/netbsd32_machdep.c 2021/01/01 12:58:35 1.7.2.2
@@ -1,559 +1,646 @@ | @@ -1,559 +1,646 @@ | |||
1 | /* $NetBSD: netbsd32_machdep.c,v 1.7.2.1 2020/05/02 16:26:04 martin Exp $ */ | 1 | /* $NetBSD: netbsd32_machdep.c,v 1.7.2.2 2021/01/01 12:58:35 martin Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2018 Ryo Shimizu <ryo@nerv.org> | 4 | * Copyright (c) 2018 Ryo Shimizu <ryo@nerv.org> | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
15 | * | 15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | 19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | |
20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 22 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
24 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | 24 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
25 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 25 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
26 | * POSSIBILITY OF SUCH DAMAGE. | 26 | * POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | 27 | */ | |
28 | 28 | |||
29 | #include <sys/cdefs.h> | 29 | #include <sys/cdefs.h> | |
30 | __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.7.2.1 2020/05/02 16:26:04 martin Exp $"); | 30 | __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.7.2.2 2021/01/01 12:58:35 martin Exp $"); | |
31 | 31 | |||
32 | #if defined(_KERNEL_OPT) | 32 | #if defined(_KERNEL_OPT) | |
33 | #include "opt_compat_netbsd.h" | 33 | #include "opt_compat_netbsd.h" | |
34 | #endif | 34 | #endif | |
35 | 35 | |||
36 | #include <sys/param.h> | 36 | #include <sys/param.h> | |
37 | #include <sys/core.h> | 37 | #include <sys/core.h> | |
38 | #include <sys/exec.h> | 38 | #include <sys/exec.h> | |
39 | #include <sys/lwp.h> | 39 | #include <sys/lwp.h> | |
40 | #include <sys/ptrace.h> | |||
40 | #include <sys/ras.h> | 41 | #include <sys/ras.h> | |
41 | #include <sys/signalvar.h> | 42 | #include <sys/signalvar.h> | |
42 | #include <sys/syscallargs.h> | 43 | #include <sys/syscallargs.h> | |
43 | 44 | |||
44 | #include <uvm/uvm_extern.h> | 45 | #include <uvm/uvm_extern.h> | |
45 | 46 | |||
46 | #include <compat/netbsd32/netbsd32.h> | 47 | #include <compat/netbsd32/netbsd32.h> | |
47 | #include <compat/netbsd32/netbsd32_exec.h> | 48 | #include <compat/netbsd32/netbsd32_exec.h> | |
48 | #include <compat/netbsd32/netbsd32_syscallargs.h> | 49 | #include <compat/netbsd32/netbsd32_syscallargs.h> | |
49 | 50 | |||
50 | #include <aarch64/armreg.h> | 51 | #include <aarch64/armreg.h> | |
51 | #include <aarch64/cpufunc.h> | 52 | #include <aarch64/cpufunc.h> | |
52 | #include <aarch64/frame.h> | 53 | #include <aarch64/frame.h> | |
53 | #include <aarch64/machdep.h> | 54 | #include <aarch64/machdep.h> | |
54 | #include <aarch64/userret.h> | 55 | #include <aarch64/userret.h> | |
55 | 56 | |||
56 | const char machine32[] = MACHINE; | 57 | const char machine32[] = MACHINE; | |
57 | #ifdef __AARCH64EB__ | 58 | #ifdef __AARCH64EB__ | |
58 | const char machine_arch32[] = "earmv7hfeb"; | 59 | const char machine_arch32[] = "earmv7hfeb"; | |
59 | #else | 60 | #else | |
60 | const char machine_arch32[] = "earmv7hf"; | 61 | const char machine_arch32[] = "earmv7hf"; | |
61 | #endif | 62 | #endif | |
62 | 63 | |||
63 | void | 64 | void | |
64 | netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) | 65 | netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) | |
65 | { | 66 | { | |
66 | struct proc * const p = l->l_proc; | 67 | struct proc * const p = l->l_proc; | |
67 | struct trapframe * const tf = l->l_md.md_utf; | 68 | struct trapframe * const tf = l->l_md.md_utf; | |
68 | 69 | |||
69 | p->p_flag |= PK_32; | 70 | p->p_flag |= PK_32; | |
70 | 71 | |||
71 | /* | 72 | /* | |
72 | * void __start(struct ps_strings *ps_strings, const Obj_Entry *obj, | 73 | * void __start(struct ps_strings *ps_strings, const Obj_Entry *obj, | |
73 | * void (*cleanup)(void)); | 74 | * void (*cleanup)(void)); | |
74 | */ | 75 | */ | |
75 | memset(tf, 0, sizeof(*tf)); | 76 | memset(tf, 0, sizeof(*tf)); | |
76 | tf->tf_reg[0] = (uint32_t)p->p_psstrp; | 77 | tf->tf_reg[0] = (uint32_t)p->p_psstrp; | |
77 | tf->tf_reg[12] = stack; /* r12 needed by pre 1.4 crt0.c */ | 78 | tf->tf_reg[12] = stack; /* r12 needed by pre 1.4 crt0.c */ | |
78 | tf->tf_reg[13] = stack; /* sp */ | 79 | tf->tf_reg[13] = stack; /* sp */ | |
79 | tf->tf_reg[14] = pack->ep_entry;/* lr */ | 80 | tf->tf_reg[14] = pack->ep_entry;/* lr */ | |
80 | tf->tf_reg[18] = 0x77777777; /* svc_lr. adjust to arm_machdep.c */ | 81 | tf->tf_reg[18] = 0x77777777; /* svc_lr. adjust to arm_machdep.c */ | |
81 | tf->tf_pc = pack->ep_entry; | 82 | tf->tf_pc = pack->ep_entry; | |
82 | 83 | |||
83 | 84 | |||
84 | /* set 32bit mode, and same endian as 64bit's */ | 85 | /* set 32bit mode, and same endian as 64bit's */ | |
85 | #ifdef __AARCH64EB__ | 86 | #ifdef __AARCH64EB__ | |
86 | tf->tf_spsr = SPSR_M_USR32 | SPSR_A32_E; | 87 | tf->tf_spsr = SPSR_M_USR32 | SPSR_A32_E; | |
87 | #else | 88 | #else | |
88 | tf->tf_spsr = SPSR_M_USR32; | 89 | tf->tf_spsr = SPSR_M_USR32; | |
89 | #endif | 90 | #endif | |
90 | 91 | |||
91 | /* THUMB CODE? */ | 92 | /* THUMB CODE? */ | |
92 | if (pack->ep_entry & 1) | 93 | if (pack->ep_entry & 1) | |
93 | tf->tf_spsr |= SPSR_A32_T; | 94 | tf->tf_spsr |= SPSR_A32_T; | |
94 | } | 95 | } | |
95 | 96 | |||
97 | int | |||
98 | netbsd32_ptrace_translate_request(int req) | |||
99 | { | |||
100 | ||||
101 | switch (req) { | |||
102 | case 0 ... PT_FIRSTMACH - 1: | |||
103 | return req; | |||
104 | case PT32_GETREGS: | |||
105 | return PT_GETREGS; | |||
106 | case PT32_SETREGS: | |||
107 | return PT_SETREGS; | |||
108 | case PT32_GETFPREGS: | |||
109 | return PT_GETFPREGS; | |||
110 | case PT32_SETFPREGS: | |||
111 | return PT_SETFPREGS; | |||
112 | /* not implemented for arm32 */ | |||
113 | case PT32_STEP: | |||
114 | case PT32_SETSTEP: | |||
115 | case PT32_CLEARSTEP: | |||
116 | default: | |||
117 | return -1; | |||
118 | } | |||
119 | } | |||
120 | ||||
96 | /* aarch32 fpscr register is assigned to two registers fpsr/fpcr on aarch64 */ | 121 | /* aarch32 fpscr register is assigned to two registers fpsr/fpcr on aarch64 */ | |
97 | #define FPSR_BITS \ | 122 | #define FPSR_BITS \ | |
98 | (FPSR_N32|FPSR_Z32|FPSR_C32|FPSR_V32|FPSR_QC| \ | 123 | (FPSR_N32|FPSR_Z32|FPSR_C32|FPSR_V32|FPSR_QC| \ | |
99 | FPSR_IDC|FPSR_IXC|FPSR_UFC|FPSR_OFC|FPSR_DZC|FPSR_IOC) | 124 | FPSR_IDC|FPSR_IXC|FPSR_UFC|FPSR_OFC|FPSR_DZC|FPSR_IOC) | |
100 | #define FPCR_BITS \ | 125 | #define FPCR_BITS \ | |
101 | (FPCR_AHP|FPCR_DN|FPCR_FZ|FPCR_RMODE|FPCR_STRIDE|FPCR_LEN| \ | 126 | (FPCR_AHP|FPCR_DN|FPCR_FZ|FPCR_RMODE|FPCR_STRIDE|FPCR_LEN| \ | |
102 | FPCR_IDE|FPCR_IXE|FPCR_UFE|FPCR_OFE|FPCR_DZE|FPCR_IOE) | 127 | FPCR_IDE|FPCR_IXE|FPCR_UFE|FPCR_OFE|FPCR_DZE|FPCR_IOE) | |
103 | 128 | |||
104 | static int | 129 | int | |
105 | netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs) | 130 | netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs) | |
106 | { | 131 | { | |
107 | struct proc * const p = l->l_proc; | 132 | struct proc * const p = l->l_proc; | |
108 | struct trapframe *tf = l->l_md.md_utf; | 133 | struct trapframe *tf = l->l_md.md_utf; | |
109 | int i; | 134 | int i; | |
110 | 135 | |||
111 | if ((p->p_flag & PK_32) == 0) | 136 | if ((p->p_flag & PK_32) == 0) | |
112 | return EINVAL; | 137 | return EINVAL; | |
113 | 138 | |||
114 | for (i = 0; i < 13; i++) | 139 | for (i = 0; i < 13; i++) | |
115 | regs->r[i] = tf->tf_reg[i]; /* r0-r12 */ | 140 | regs->r[i] = tf->tf_reg[i]; /* r0-r12 */ | |
116 | regs->r_sp = tf->tf_reg[13]; /* r13 = sp */ | 141 | regs->r_sp = tf->tf_reg[13]; /* r13 = sp */ | |
117 | regs->r_lr = tf->tf_reg[14]; /* r14 = lr */ | 142 | regs->r_lr = tf->tf_reg[14]; /* r14 = lr */ | |
118 | regs->r_pc = tf->tf_pc; /* r15 = pc */ | 143 | regs->r_pc = tf->tf_pc; /* r15 = pc */ | |
119 | regs->r_cpsr = tf->tf_spsr; | 144 | regs->r_cpsr = tf->tf_spsr; | |
120 | 145 | |||
121 | /* THUMB CODE? */ | 146 | /* THUMB CODE? */ | |
122 | if (tf->tf_spsr & SPSR_A32_T) | 147 | if (tf->tf_spsr & SPSR_A32_T) | |
123 | regs->r_pc |= 1; | 148 | regs->r_pc |= 1; | |
124 | 149 | |||
125 | return 0; | 150 | return 0; | |
126 | } | 151 | } | |
127 | 152 | |||
128 | static int | 153 | int | |
129 | netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *fpregs, | 154 | netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *fpregs, | |
130 | size_t *lenp) | 155 | size_t *lenp) | |
131 | { | 156 | { | |
132 | struct proc * const p = l->l_proc; | 157 | struct proc * const p = l->l_proc; | |
133 | struct pcb * const pcb = lwp_getpcb(l); | 158 | struct pcb * const pcb = lwp_getpcb(l); | |
134 | int i; | 159 | int i; | |
135 | 160 | |||
136 | if ((p->p_flag & PK_32) == 0) | 161 | if ((p->p_flag & PK_32) == 0) | |
137 | return EINVAL; | 162 | return EINVAL; | |
138 | 163 | |||
139 | KASSERT(*lenp <= sizeof(*fpregs)); | 164 | KASSERT(*lenp <= sizeof(*fpregs)); | |
140 | fpu_save(l); | 165 | fpu_save(l); | |
141 | 166 | |||
142 | /* | 167 | /* | |
143 | * convert from aarch64's struct fpreg to arm's struct fpreg32 | 168 | * convert from aarch64's struct fpreg to arm's struct fpreg32 | |
144 | */ | 169 | */ | |
145 | #define VFP_FPEXC_EN 0x40000000 /* VFP Enable bit */ | 170 | #define VFP_FPEXC_EN 0x40000000 /* VFP Enable bit */ | |
146 | #define VFP_FPEXC_VECITR 0x00000700 /* VECtor ITeRation count */ | 171 | #define VFP_FPEXC_VECITR 0x00000700 /* VECtor ITeRation count */ | |
147 | fpregs->fpr_vfp.vfp_fpexc = VFP_FPEXC_EN | VFP_FPEXC_VECITR; | 172 | fpregs->fpr_vfp.vfp_fpexc = VFP_FPEXC_EN | VFP_FPEXC_VECITR; | |
148 | 173 | |||
149 | fpregs->fpr_vfp.vfp_fpscr = | 174 | fpregs->fpr_vfp.vfp_fpscr = | |
150 | (pcb->pcb_fpregs.fpsr & FPSR_BITS) | | 175 | (pcb->pcb_fpregs.fpsr & FPSR_BITS) | | |
151 | (pcb->pcb_fpregs.fpcr & FPCR_BITS); | 176 | (pcb->pcb_fpregs.fpcr & FPCR_BITS); | |
152 | 177 | |||
153 | fpregs->fpr_vfp.vfp_fpinst = 0; | 178 | fpregs->fpr_vfp.vfp_fpinst = 0; | |
154 | fpregs->fpr_vfp.vfp_fpinst2 = 0; | 179 | fpregs->fpr_vfp.vfp_fpinst2 = 0; | |
155 | 180 | |||
156 | for (i = 0; i < 32; i++) { | 181 | for (i = 0; i < 32; i++) { | |
157 | #ifdef __AARCH64EB__ | 182 | #ifdef __AARCH64EB__ | |
158 | fpregs->fpr_vfp.vfp_regs[i] = pcb->pcb_fpregs.fp_reg[i].u64[1]; | 183 | fpregs->fpr_vfp.vfp_regs[i] = pcb->pcb_fpregs.fp_reg[i].u64[1]; | |
159 | #else | 184 | #else | |
160 | fpregs->fpr_vfp.vfp_regs[i] = pcb->pcb_fpregs.fp_reg[i].u64[0]; | 185 | fpregs->fpr_vfp.vfp_regs[i] = pcb->pcb_fpregs.fp_reg[i].u64[0]; | |
161 | #endif | 186 | #endif | |
162 | } | 187 | } | |
163 | 188 | |||
164 | return 0; | 189 | return 0; | |
165 | } | 190 | } | |
166 | 191 | |||
167 | int | 192 | int | |
193 | netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs) | |||
194 | { | |||
195 | struct proc * const p = l->l_proc; | |||
196 | struct trapframe *tf = l->l_md.md_utf; | |||
197 | int i; | |||
198 | ||||
199 | if ((p->p_flag & PK_32) == 0) | |||
200 | return EINVAL; | |||
201 | ||||
202 | if (regs->r_pc >= VM_MAXUSER_ADDRESS32 || | |||
203 | regs->r_sp >= VM_MAXUSER_ADDRESS32) | |||
204 | return EINVAL; | |||
205 | ||||
206 | for (i = 0; i < 13; i++) | |||
207 | tf->tf_reg[i] = regs->r[i]; /* r0-r12 */ | |||
208 | tf->tf_reg[13] = regs->r_sp; /* r13 = sp */ | |||
209 | tf->tf_reg[14] = regs->r_lr; /* r14 = lr */ | |||
210 | tf->tf_pc = regs->r_pc; /* r15 = pc */ | |||
211 | tf->tf_spsr &= ~(SPSR_NZCV | SPSR_A32_T); | |||
212 | tf->tf_spsr |= regs->r_cpsr & (SPSR_NZCV | SPSR_A32_T); | |||
213 | ||||
214 | /* THUMB CODE? */ | |||
215 | if (regs->r_pc & 1) | |||
216 | tf->tf_spsr |= SPSR_A32_T; | |||
217 | ||||
218 | return 0; | |||
219 | } | |||
220 | ||||
221 | int | |||
222 | netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *fpregs, | |||
223 | size_t len) | |||
224 | { | |||
225 | struct proc * const p = l->l_proc; | |||
226 | struct pcb * const pcb = lwp_getpcb(l); | |||
227 | int i; | |||
228 | ||||
229 | if ((p->p_flag & PK_32) == 0) | |||
230 | return EINVAL; | |||
231 | ||||
232 | KASSERT(len <= sizeof(*fpregs)); | |||
233 | fpu_discard(l, true); // set used flag | |||
234 | ||||
235 | pcb->pcb_fpregs.fpsr = fpregs->fpr_vfp.vfp_fpscr & FPSR_BITS; | |||
236 | pcb->pcb_fpregs.fpcr = fpregs->fpr_vfp.vfp_fpscr & FPCR_BITS; | |||
237 | ||||
238 | CTASSERT(__arraycount(fpregs->fpr_vfp.vfp_regs) == | |||
239 | __arraycount(pcb->pcb_fpregs.fp_reg) + 1); | |||
240 | for (i = 0; i < __arraycount(pcb->pcb_fpregs.fp_reg); i++) { | |||
241 | #ifdef __AARCH64EB__ | |||
242 | pcb->pcb_fpregs.fp_reg[i].u64[0] = 0; | |||
243 | pcb->pcb_fpregs.fp_reg[i].u64[1] = | |||
244 | #else | |||
245 | pcb->pcb_fpregs.fp_reg[i].u64[1] = 0; | |||
246 | pcb->pcb_fpregs.fp_reg[i].u64[0] = | |||
247 | #endif | |||
248 | fpregs->fpr_vfp.vfp_regs[i]; | |||
249 | } | |||
250 | ||||
251 | return 0; | |||
252 | } | |||
253 | ||||
254 | int | |||
168 | cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie, | 255 | cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie, | |
169 | struct core32 *chdr) | 256 | struct core32 *chdr) | |
170 | { | 257 | { | |
171 | struct netbsd32_cpustate md_core32; | 258 | struct netbsd32_cpustate md_core32; | |
172 | struct coreseg32 cseg; | 259 | struct coreseg32 cseg; | |
173 | int error; | 260 | int error; | |
174 | 261 | |||
175 | if (iocookie == NULL) { | 262 | if (iocookie == NULL) { | |
176 | CORE_SETMAGIC(*chdr, COREMAGIC, MID_ARM6, 0); | 263 | CORE_SETMAGIC(*chdr, COREMAGIC, MID_ARM6, 0); | |
177 | chdr->c_hdrsize = ALIGN32(sizeof(*chdr)); | 264 | chdr->c_hdrsize = ALIGN32(sizeof(*chdr)); | |
178 | chdr->c_seghdrsize = ALIGN32(sizeof(cseg)); | 265 | chdr->c_seghdrsize = ALIGN32(sizeof(cseg)); | |
179 | chdr->c_cpusize = sizeof(md_core32); | 266 | chdr->c_cpusize = sizeof(md_core32); | |
180 | chdr->c_nseg++; | 267 | chdr->c_nseg++; | |
181 | return 0; | 268 | return 0; | |
182 | } | 269 | } | |
183 | 270 | |||
184 | error = netbsd32_process_read_regs(l, &md_core32.regs); | 271 | error = netbsd32_process_read_regs(l, &md_core32.regs); | |
185 | if (error) | 272 | if (error) | |
186 | return error; | 273 | return error; | |
187 | 274 | |||
188 | error = netbsd32_process_read_fpregs(l, &md_core32.fpregs, NULL); | 275 | error = netbsd32_process_read_fpregs(l, &md_core32.fpregs, NULL); | |
189 | if (error) | 276 | if (error) | |
190 | return error; | 277 | return error; | |
191 | 278 | |||
192 | CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_ARM6, CORE_CPU); | 279 | CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_ARM6, CORE_CPU); | |
193 | cseg.c_addr = 0; | 280 | cseg.c_addr = 0; | |
194 | cseg.c_size = chdr->c_cpusize; | 281 | cseg.c_size = chdr->c_cpusize; | |
195 | 282 | |||
196 | error = coredump_write(iocookie, UIO_SYSSPACE, | 283 | error = coredump_write(iocookie, UIO_SYSSPACE, | |
197 | &cseg, chdr->c_seghdrsize); | 284 | &cseg, chdr->c_seghdrsize); | |
198 | if (error) | 285 | if (error) | |
199 | return error; | 286 | return error; | |
200 | 287 | |||
201 | return coredump_write(iocookie, UIO_SYSSPACE, | 288 | return coredump_write(iocookie, UIO_SYSSPACE, | |
202 | &md_core32, sizeof(md_core32)); | 289 | &md_core32, sizeof(md_core32)); | |
203 | } | 290 | } | |
204 | 291 | |||
205 | static void | 292 | static void | |
206 | netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) | 293 | netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) | |
207 | { | 294 | { | |
208 | struct lwp * const l = curlwp; | 295 | struct lwp * const l = curlwp; | |
209 | struct proc * const p = l->l_proc; | 296 | struct proc * const p = l->l_proc; | |
210 | struct trapframe * const tf = l->l_md.md_utf; | 297 | struct trapframe * const tf = l->l_md.md_utf; | |
211 | struct sigaltstack * const ss = &l->l_sigstk; | 298 | struct sigaltstack * const ss = &l->l_sigstk; | |
212 | const int signo = ksi->ksi_signo; | 299 | const int signo = ksi->ksi_signo; | |
213 | const struct sigaction * const sa = &SIGACTION(p, signo); | 300 | const struct sigaction * const sa = &SIGACTION(p, signo); | |
214 | const struct sigact_sigdesc * const sdesc = | 301 | const struct sigact_sigdesc * const sdesc = | |
215 | &p->p_sigacts->sa_sigdesc[signo]; | 302 | &p->p_sigacts->sa_sigdesc[signo]; | |
216 | const sig_t handler = sa->sa_handler; | 303 | const sig_t handler = sa->sa_handler; | |
217 | struct netbsd32_sigframe_siginfo *fp, frame; | 304 | struct netbsd32_sigframe_siginfo *fp, frame; | |
218 | int error; | 305 | int error; | |
219 | 306 | |||
220 | const bool onstack_p = | 307 | const bool onstack_p = | |
221 | (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && | 308 | (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && | |
222 | (sa->sa_flags & SA_ONSTACK); | 309 | (sa->sa_flags & SA_ONSTACK); | |
223 | 310 | |||
224 | vaddr_t sp = onstack_p ? | 311 | vaddr_t sp = onstack_p ? | |
225 | ((vaddr_t)ss->ss_sp + ss->ss_size) : | 312 | ((vaddr_t)ss->ss_sp + ss->ss_size) : | |
226 | tf->tf_reg[13]; /* r13 = sp on aarch32 */ | 313 | tf->tf_reg[13]; /* r13 = sp on aarch32 */ | |
227 | 314 | |||
228 | fp = (struct netbsd32_sigframe_siginfo *)sp; | 315 | fp = (struct netbsd32_sigframe_siginfo *)sp; | |
229 | fp = (struct netbsd32_sigframe_siginfo *)STACK_ALIGN(fp - 1, (8 - 1)); | 316 | fp = (struct netbsd32_sigframe_siginfo *)STACK_ALIGN(fp - 1, (8 - 1)); | |
230 | 317 | |||
231 | memset(&frame, 0, sizeof(frame)); | 318 | memset(&frame, 0, sizeof(frame)); | |
232 | 319 | |||
233 | /* XXX: netbsd32_ksi_to_si32 */ | 320 | /* XXX: netbsd32_ksi_to_si32 */ | |
234 | netbsd32_si_to_si32(&frame.sf_si, (const siginfo_t *)&ksi->ksi_info); | 321 | netbsd32_si_to_si32(&frame.sf_si, (const siginfo_t *)&ksi->ksi_info); | |
235 | 322 | |||
236 | frame.sf_uc.uc_flags = _UC_SIGMASK; | 323 | frame.sf_uc.uc_flags = _UC_SIGMASK; | |
237 | frame.sf_uc.uc_sigmask = *mask; | 324 | frame.sf_uc.uc_sigmask = *mask; | |
238 | frame.sf_uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink; | 325 | frame.sf_uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink; | |
239 | frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) ? | 326 | frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) ? | |
240 | _UC_SETSTACK : _UC_CLRSTACK; | 327 | _UC_SETSTACK : _UC_CLRSTACK; | |
241 | sendsig_reset(l, signo); | 328 | sendsig_reset(l, signo); | |
242 | 329 | |||
243 | mutex_exit(p->p_lock); | 330 | mutex_exit(p->p_lock); | |
244 | cpu_getmcontext32(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); | 331 | cpu_getmcontext32(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); | |
245 | error = copyout(&frame, fp, sizeof(frame)); | 332 | error = copyout(&frame, fp, sizeof(frame)); | |
246 | mutex_enter(p->p_lock); | 333 | mutex_enter(p->p_lock); | |
247 | 334 | |||
248 | if (error != 0) { | 335 | if (error != 0) { | |
249 | /* | 336 | /* | |
250 | * Process has trashed its stack; | 337 | * Process has trashed its stack; | |
251 | * give it an illegal instruction to halt it in its tracks. | 338 | * give it an illegal instruction to halt it in its tracks. | |
252 | */ | 339 | */ | |
253 | sigexit(l, SIGILL); | 340 | sigexit(l, SIGILL); | |
254 | /* NOTREACHED */ | 341 | /* NOTREACHED */ | |
255 | } | 342 | } | |
256 | 343 | |||
257 | tf->tf_reg[0] = signo; | 344 | tf->tf_reg[0] = signo; | |
258 | tf->tf_reg[1] = (uint32_t)(uintptr_t)&fp->sf_si; | 345 | tf->tf_reg[1] = (uint32_t)(uintptr_t)&fp->sf_si; | |
259 | tf->tf_reg[2] = (uint32_t)(uintptr_t)&fp->sf_uc; | 346 | tf->tf_reg[2] = (uint32_t)(uintptr_t)&fp->sf_uc; | |
260 | 347 | |||
261 | /* the trampoline uses r5 as the uc address */ | 348 | /* the trampoline uses r5 as the uc address */ | |
262 | tf->tf_reg[5] = (uint32_t)(uintptr_t)&fp->sf_uc; | 349 | tf->tf_reg[5] = (uint32_t)(uintptr_t)&fp->sf_uc; | |
263 | tf->tf_pc = (uint32_t)(uintptr_t)handler; | 350 | tf->tf_pc = (uint32_t)(uintptr_t)handler; | |
264 | 351 | |||
265 | /* THUMB CODE? */ | 352 | /* THUMB CODE? */ | |
266 | if (((uintptr_t)handler) & 1) | 353 | if (((uintptr_t)handler) & 1) | |
267 | tf->tf_spsr |= SPSR_A32_T; | 354 | tf->tf_spsr |= SPSR_A32_T; | |
268 | else | 355 | else | |
269 | tf->tf_spsr &= ~SPSR_A32_T; | 356 | tf->tf_spsr &= ~SPSR_A32_T; | |
270 | 357 | |||
271 | tf->tf_reg[13] = (uint32_t)(uintptr_t)fp; /* sp */ | 358 | tf->tf_reg[13] = (uint32_t)(uintptr_t)fp; /* sp */ | |
272 | tf->tf_reg[14] = (uint32_t)(uintptr_t)sdesc->sd_tramp; /* lr */ | 359 | tf->tf_reg[14] = (uint32_t)(uintptr_t)sdesc->sd_tramp; /* lr */ | |
273 | 360 | |||
274 | /* Remember if we'ere now on the signal stack */ | 361 | /* Remember if we'ere now on the signal stack */ | |
275 | if (onstack_p) | 362 | if (onstack_p) | |
276 | ss->ss_flags |= SS_ONSTACK; | 363 | ss->ss_flags |= SS_ONSTACK; | |
277 | } | 364 | } | |
278 | 365 | |||
279 | void | 366 | void | |
280 | netbsd32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) | 367 | netbsd32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) | |
281 | { | 368 | { | |
282 | #ifdef COMPAT_16 | 369 | #ifdef COMPAT_16 | |
283 | #error non EABI generation binaries are not supported | 370 | #error non EABI generation binaries are not supported | |
284 | if (curproc->p_sigacts->sa_sigdesc[ksi->ksi_signo].sd_vers < 2) | 371 | if (curproc->p_sigacts->sa_sigdesc[ksi->ksi_signo].sd_vers < 2) | |
285 | netbsd32_sendsig_sigcontext(ksi, mask); | 372 | netbsd32_sendsig_sigcontext(ksi, mask); | |
286 | else | 373 | else | |
287 | #endif | 374 | #endif | |
288 | netbsd32_sendsig_siginfo(ksi, mask); | 375 | netbsd32_sendsig_siginfo(ksi, mask); | |
289 | } | 376 | } | |
290 | 377 | |||
291 | void | 378 | void | |
292 | startlwp32(void *arg) | 379 | startlwp32(void *arg) | |
293 | { | 380 | { | |
294 | ucontext32_t *uc = arg; | 381 | ucontext32_t *uc = arg; | |
295 | lwp_t *l = curlwp; | 382 | lwp_t *l = curlwp; | |
296 | int error __diagused; | 383 | int error __diagused; | |
297 | 384 | |||
298 | /* | 385 | /* | |
299 | * entity of *uc is ucontext_t. therefore | 386 | * entity of *uc is ucontext_t. therefore | |
300 | * ucontext_t must be greater than ucontext32_t | 387 | * ucontext_t must be greater than ucontext32_t | |
301 | */ | 388 | */ | |
302 | CTASSERT(sizeof(ucontext_t) >= sizeof(ucontext32_t)); | 389 | CTASSERT(sizeof(ucontext_t) >= sizeof(ucontext32_t)); | |
303 | 390 | |||
304 | error = cpu_setmcontext32(l, &uc->uc_mcontext, uc->uc_flags); | 391 | error = cpu_setmcontext32(l, &uc->uc_mcontext, uc->uc_flags); | |
305 | KASSERT(error == 0); | 392 | KASSERT(error == 0); | |
306 | 393 | |||
307 | /* Note: we are freeing ucontext_t, not ucontext32_t. */ | 394 | /* Note: we are freeing ucontext_t, not ucontext32_t. */ | |
308 | kmem_free(uc, sizeof(ucontext_t)); | 395 | kmem_free(uc, sizeof(ucontext_t)); | |
309 | userret(l); | 396 | userret(l); | |
310 | } | 397 | } | |
311 | 398 | |||
312 | int | 399 | int | |
313 | cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mcp) | 400 | cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mcp) | |
314 | { | 401 | { | |
315 | struct proc * const p __diagused = l->l_proc; | 402 | struct proc * const p __diagused = l->l_proc; | |
316 | const uint32_t spsr = mcp->__gregs[_REG_CPSR]; | 403 | const uint32_t spsr = mcp->__gregs[_REG_CPSR]; | |
317 | 404 | |||
318 | KASSERT(p->p_flag & PK_32); | 405 | KASSERT(p->p_flag & PK_32); | |
319 | 406 | |||
320 | if (__SHIFTOUT(spsr, SPSR_M) != SPSR_M_USR32) | 407 | if (__SHIFTOUT(spsr, SPSR_M) != SPSR_M_USR32) | |
321 | return EINVAL; | 408 | return EINVAL; | |
322 | if ((spsr & (SPSR_A64_D|SPSR_A|SPSR_I|SPSR_F)) != 0) | 409 | if ((spsr & (SPSR_A64_D|SPSR_A|SPSR_I|SPSR_F)) != 0) | |
323 | return EINVAL; | 410 | return EINVAL; | |
324 | 411 | |||
325 | #ifdef __AARCH64EB__ | 412 | #ifdef __AARCH64EB__ | |
326 | if ((spsr & SPSR_A32_E) == 0) | 413 | if ((spsr & SPSR_A32_E) == 0) | |
327 | return EINVAL; | 414 | return EINVAL; | |
328 | #else | 415 | #else | |
329 | if ((spsr & SPSR_A32_E) != 0) | 416 | if ((spsr & SPSR_A32_E) != 0) | |
330 | return EINVAL; | 417 | return EINVAL; | |
331 | #endif | 418 | #endif | |
332 | 419 | |||
333 | if ((spsr & (SPSR_A|SPSR_I|SPSR_F)) != 0) | 420 | if ((spsr & (SPSR_A|SPSR_I|SPSR_F)) != 0) | |
334 | return EINVAL; | 421 | return EINVAL; | |
335 | 422 | |||
336 | return 0; | 423 | return 0; | |
337 | } | 424 | } | |
338 | void | 425 | void | |
339 | cpu_getmcontext32(struct lwp *l, mcontext32_t *mcp, unsigned int *flagsp) | 426 | cpu_getmcontext32(struct lwp *l, mcontext32_t *mcp, unsigned int *flagsp) | |
340 | { | 427 | { | |
341 | struct trapframe * const tf = l->l_md.md_utf; | 428 | struct trapframe * const tf = l->l_md.md_utf; | |
342 | __greg32_t *gr = mcp->__gregs; | 429 | __greg32_t *gr = mcp->__gregs; | |
343 | __greg32_t ras_pc; | 430 | __greg32_t ras_pc; | |
344 | 431 | |||
345 | gr[_REG_R0] = tf->tf_reg[0]; | 432 | gr[_REG_R0] = tf->tf_reg[0]; | |
346 | gr[_REG_R1] = tf->tf_reg[1]; | 433 | gr[_REG_R1] = tf->tf_reg[1]; | |
347 | gr[_REG_R2] = tf->tf_reg[2]; | 434 | gr[_REG_R2] = tf->tf_reg[2]; | |
348 | gr[_REG_R3] = tf->tf_reg[3]; | 435 | gr[_REG_R3] = tf->tf_reg[3]; | |
349 | gr[_REG_R4] = tf->tf_reg[4]; | 436 | gr[_REG_R4] = tf->tf_reg[4]; | |
350 | gr[_REG_R5] = tf->tf_reg[5]; | 437 | gr[_REG_R5] = tf->tf_reg[5]; | |
351 | gr[_REG_R6] = tf->tf_reg[6]; | 438 | gr[_REG_R6] = tf->tf_reg[6]; | |
352 | gr[_REG_R7] = tf->tf_reg[7]; | 439 | gr[_REG_R7] = tf->tf_reg[7]; | |
353 | gr[_REG_R8] = tf->tf_reg[8]; | 440 | gr[_REG_R8] = tf->tf_reg[8]; | |
354 | gr[_REG_R9] = tf->tf_reg[9]; | 441 | gr[_REG_R9] = tf->tf_reg[9]; | |
355 | gr[_REG_R10] = tf->tf_reg[10]; | 442 | gr[_REG_R10] = tf->tf_reg[10]; | |
356 | gr[_REG_R11] = tf->tf_reg[11]; | 443 | gr[_REG_R11] = tf->tf_reg[11]; | |
357 | gr[_REG_R12] = tf->tf_reg[12]; | 444 | gr[_REG_R12] = tf->tf_reg[12]; | |
358 | gr[_REG_R13] = tf->tf_reg[13]; | 445 | gr[_REG_R13] = tf->tf_reg[13]; | |
359 | gr[_REG_R14] = tf->tf_reg[14]; | 446 | gr[_REG_R14] = tf->tf_reg[14]; | |
360 | gr[_REG_R15] = tf->tf_pc; | 447 | gr[_REG_R15] = tf->tf_pc; | |
361 | gr[_REG_CPSR] = tf->tf_spsr; | 448 | gr[_REG_CPSR] = tf->tf_spsr; | |
362 | 449 | |||
363 | if ((ras_pc = (__greg32_t)(uintptr_t)ras_lookup(l->l_proc, | 450 | if ((ras_pc = (__greg32_t)(uintptr_t)ras_lookup(l->l_proc, | |
364 | (void *)(uintptr_t)gr[_REG_R15])) != -1) { | 451 | (void *)(uintptr_t)gr[_REG_R15])) != -1) { | |
365 | gr[_REG_R15] = ras_pc; | 452 | gr[_REG_R15] = ras_pc; | |
366 | } | 453 | } | |
367 | *flagsp |= _UC_CPU; | 454 | *flagsp |= _UC_CPU; | |
368 | 455 | |||
369 | /* fpu context */ | 456 | /* fpu context */ | |
370 | if (fpu_used_p(l)) { | 457 | if (fpu_used_p(l)) { | |
371 | const struct pcb * const pcb = lwp_getpcb(l); | 458 | const struct pcb * const pcb = lwp_getpcb(l); | |
372 | int i; | 459 | int i; | |
373 | 460 | |||
374 | fpu_save(l); | 461 | fpu_save(l); | |
375 | 462 | |||
376 | CTASSERT(__arraycount(mcp->__vfpregs.__vfp_fstmx) == | 463 | CTASSERT(__arraycount(mcp->__vfpregs.__vfp_fstmx) == | |
377 | __arraycount(pcb->pcb_fpregs.fp_reg)); | 464 | __arraycount(pcb->pcb_fpregs.fp_reg)); | |
378 | for (i = 0; i < __arraycount(pcb->pcb_fpregs.fp_reg); i++) { | 465 | for (i = 0; i < __arraycount(pcb->pcb_fpregs.fp_reg); i++) { | |
379 | mcp->__vfpregs.__vfp_fstmx[i] = | 466 | mcp->__vfpregs.__vfp_fstmx[i] = | |
380 | #ifdef __AARCH64EB__ | 467 | #ifdef __AARCH64EB__ | |
381 | pcb->pcb_fpregs.fp_reg[i].u64[1]; | 468 | pcb->pcb_fpregs.fp_reg[i].u64[1]; | |
382 | #else | 469 | #else | |
383 | pcb->pcb_fpregs.fp_reg[i].u64[0]; | 470 | pcb->pcb_fpregs.fp_reg[i].u64[0]; | |
384 | #endif | 471 | #endif | |
385 | } | 472 | } | |
386 | 473 | |||
387 | mcp->__vfpregs.__vfp_fpscr = | 474 | mcp->__vfpregs.__vfp_fpscr = | |
388 | (pcb->pcb_fpregs.fpsr & FPSR_BITS) | | 475 | (pcb->pcb_fpregs.fpsr & FPSR_BITS) | | |
389 | (pcb->pcb_fpregs.fpcr & FPCR_BITS); | 476 | (pcb->pcb_fpregs.fpcr & FPCR_BITS); | |
390 | mcp->__vfpregs.__vfp_fpsid = 0; /* XXX: build FPSID from MIDR */ | 477 | mcp->__vfpregs.__vfp_fpsid = 0; /* XXX: build FPSID from MIDR */ | |
391 | 478 | |||
392 | *flagsp |= _UC_FPU; | 479 | *flagsp |= _UC_FPU; | |
393 | } | 480 | } | |
394 | 481 | |||
395 | mcp->_mc_tlsbase = (uint32_t)(uintptr_t)l->l_private; | 482 | mcp->_mc_tlsbase = (uint32_t)(uintptr_t)l->l_private; | |
396 | *flagsp |= _UC_TLSBASE; | 483 | *flagsp |= _UC_TLSBASE; | |
397 | } | 484 | } | |
398 | 485 | |||
399 | int | 486 | int | |
400 | cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags) | 487 | cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags) | |
401 | { | 488 | { | |
402 | struct trapframe * const tf = l->l_md.md_utf; | 489 | struct trapframe * const tf = l->l_md.md_utf; | |
403 | const __greg32_t * const gr = mcp->__gregs; | 490 | const __greg32_t * const gr = mcp->__gregs; | |
404 | struct proc * const p = l->l_proc; | 491 | struct proc * const p = l->l_proc; | |
405 | int error, i; | 492 | int error, i; | |
406 | 493 | |||
407 | if (flags & _UC_CPU) { | 494 | if (flags & _UC_CPU) { | |
408 | error = cpu_mcontext32_validate(l, mcp); | 495 | error = cpu_mcontext32_validate(l, mcp); | |
409 | if (error != 0) | 496 | if (error != 0) | |
410 | return error; | 497 | return error; | |
411 | 498 | |||
412 | tf->tf_reg[0] = gr[_REG_R0]; | 499 | tf->tf_reg[0] = gr[_REG_R0]; | |
413 | tf->tf_reg[1] = gr[_REG_R1]; | 500 | tf->tf_reg[1] = gr[_REG_R1]; | |
414 | tf->tf_reg[2] = gr[_REG_R2]; | 501 | tf->tf_reg[2] = gr[_REG_R2]; | |
415 | tf->tf_reg[3] = gr[_REG_R3]; | 502 | tf->tf_reg[3] = gr[_REG_R3]; | |
416 | tf->tf_reg[4] = gr[_REG_R4]; | 503 | tf->tf_reg[4] = gr[_REG_R4]; | |
417 | tf->tf_reg[5] = gr[_REG_R5]; | 504 | tf->tf_reg[5] = gr[_REG_R5]; | |
418 | tf->tf_reg[6] = gr[_REG_R6]; | 505 | tf->tf_reg[6] = gr[_REG_R6]; | |
419 | tf->tf_reg[7] = gr[_REG_R7]; | 506 | tf->tf_reg[7] = gr[_REG_R7]; | |
420 | tf->tf_reg[8] = gr[_REG_R8]; | 507 | tf->tf_reg[8] = gr[_REG_R8]; | |
421 | tf->tf_reg[9] = gr[_REG_R9]; | 508 | tf->tf_reg[9] = gr[_REG_R9]; | |
422 | tf->tf_reg[10] = gr[_REG_R10]; | 509 | tf->tf_reg[10] = gr[_REG_R10]; | |
423 | tf->tf_reg[11] = gr[_REG_R11]; | 510 | tf->tf_reg[11] = gr[_REG_R11]; | |
424 | tf->tf_reg[12] = gr[_REG_R12]; | 511 | tf->tf_reg[12] = gr[_REG_R12]; | |
425 | tf->tf_reg[13] = gr[_REG_R13]; | 512 | tf->tf_reg[13] = gr[_REG_R13]; | |
426 | tf->tf_reg[14] = gr[_REG_R14]; | 513 | tf->tf_reg[14] = gr[_REG_R14]; | |
427 | tf->tf_pc = gr[_REG_R15]; | 514 | tf->tf_pc = gr[_REG_R15]; | |
428 | tf->tf_spsr = gr[_REG_CPSR]; | 515 | tf->tf_spsr = gr[_REG_CPSR]; | |
429 | } | 516 | } | |
430 | 517 | |||
431 | if (flags & _UC_FPU) { | 518 | if (flags & _UC_FPU) { | |
432 | struct pcb * const pcb = lwp_getpcb(l); | 519 | struct pcb * const pcb = lwp_getpcb(l); | |
433 | fpu_discard(l, true); | 520 | fpu_discard(l, true); | |
434 | 521 | |||
435 | CTASSERT(__arraycount(mcp->__vfpregs.__vfp_fstmx) == | 522 | CTASSERT(__arraycount(mcp->__vfpregs.__vfp_fstmx) == | |
436 | __arraycount(pcb->pcb_fpregs.fp_reg)); | 523 | __arraycount(pcb->pcb_fpregs.fp_reg)); | |
437 | for (i = 0; i < __arraycount(pcb->pcb_fpregs.fp_reg); i++) { | 524 | for (i = 0; i < __arraycount(pcb->pcb_fpregs.fp_reg); i++) { | |
438 | #ifdef __AARCH64EB__ | 525 | #ifdef __AARCH64EB__ | |
439 | pcb->pcb_fpregs.fp_reg[i].u64[0] = 0; | 526 | pcb->pcb_fpregs.fp_reg[i].u64[0] = 0; | |
440 | pcb->pcb_fpregs.fp_reg[i].u64[1] = | 527 | pcb->pcb_fpregs.fp_reg[i].u64[1] = | |
441 | #else | 528 | #else | |
442 | pcb->pcb_fpregs.fp_reg[i].u64[1] = 0; | 529 | pcb->pcb_fpregs.fp_reg[i].u64[1] = 0; | |
443 | pcb->pcb_fpregs.fp_reg[i].u64[0] = | 530 | pcb->pcb_fpregs.fp_reg[i].u64[0] = | |
444 | #endif | 531 | #endif | |
445 | mcp->__vfpregs.__vfp_fstmx[i]; | 532 | mcp->__vfpregs.__vfp_fstmx[i]; | |
446 | } | 533 | } | |
447 | pcb->pcb_fpregs.fpsr = | 534 | pcb->pcb_fpregs.fpsr = | |
448 | mcp->__vfpregs.__vfp_fpscr & FPSR_BITS; | 535 | mcp->__vfpregs.__vfp_fpscr & FPSR_BITS; | |
449 | pcb->pcb_fpregs.fpcr = | 536 | pcb->pcb_fpregs.fpcr = | |
450 | mcp->__vfpregs.__vfp_fpscr & FPCR_BITS; | 537 | mcp->__vfpregs.__vfp_fpscr & FPCR_BITS; | |
451 | } | 538 | } | |
452 | 539 | |||
453 | if (flags &_UC_TLSBASE) | 540 | if (flags &_UC_TLSBASE) | |
454 | l->l_private = (void *)(uintptr_t)mcp->_mc_tlsbase; | 541 | l->l_private = (void *)(uintptr_t)mcp->_mc_tlsbase; | |
455 | 542 | |||
456 | mutex_enter(p->p_lock); | 543 | mutex_enter(p->p_lock); | |
457 | if (flags & _UC_SETSTACK) | 544 | if (flags & _UC_SETSTACK) | |
458 | l->l_sigstk.ss_flags |= SS_ONSTACK; | 545 | l->l_sigstk.ss_flags |= SS_ONSTACK; | |
459 | if (flags & _UC_CLRSTACK) | 546 | if (flags & _UC_CLRSTACK) | |
460 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; | 547 | l->l_sigstk.ss_flags &= ~SS_ONSTACK; | |
461 | mutex_exit(p->p_lock); | 548 | mutex_exit(p->p_lock); | |
462 | 549 | |||
463 | return 0; | 550 | return 0; | |
464 | } | 551 | } | |
465 | 552 | |||
466 | static int | 553 | static int | |
467 | arm32_sync_icache(struct lwp *l, const void *args, register_t *retval) | 554 | arm32_sync_icache(struct lwp *l, const void *args, register_t *retval) | |
468 | { | 555 | { | |
469 | struct netbsd32_arm_sync_icache_args ua; | 556 | struct netbsd32_arm_sync_icache_args ua; | |
470 | struct faultbuf fb; | 557 | struct faultbuf fb; | |
471 | int error; | 558 | int error; | |
472 | 559 | |||
473 | error = copyin(args, &ua, sizeof(ua)); | 560 | error = copyin(args, &ua, sizeof(ua)); | |
474 | if (error != 0) | 561 | if (error != 0) | |
475 | return error; | 562 | return error; | |
476 | 563 | |||
477 | if ((vaddr_t)ua.addr + ua.len > VM_MAXUSER_ADDRESS32) | 564 | if ((vaddr_t)ua.addr + ua.len > VM_MAXUSER_ADDRESS32) | |
478 | return EINVAL; | 565 | return EINVAL; | |
479 | 566 | |||
480 | /* use cpu_set_onfault() by way of precaution */ | 567 | /* use cpu_set_onfault() by way of precaution */ | |
481 | if ((error = cpu_set_onfault(&fb)) == 0) { | 568 | if ((error = cpu_set_onfault(&fb)) == 0) { | |
482 | pmap_icache_sync_range( | 569 | pmap_icache_sync_range( | |
483 | vm_map_pmap(&l->l_proc->p_vmspace->vm_map), | 570 | vm_map_pmap(&l->l_proc->p_vmspace->vm_map), | |
484 | (vaddr_t)ua.addr, (vaddr_t)ua.addr + ua.len); | 571 | (vaddr_t)ua.addr, (vaddr_t)ua.addr + ua.len); | |
485 | cpu_unset_onfault(); | 572 | cpu_unset_onfault(); | |
486 | } | 573 | } | |
487 | 574 | |||
488 | *retval = 0; | 575 | *retval = 0; | |
489 | return error; | 576 | return error; | |
490 | } | 577 | } | |
491 | 578 | |||
492 | static int | 579 | static int | |
493 | arm32_drain_writebuf(struct lwp *l, const void *args, register_t *retval) | 580 | arm32_drain_writebuf(struct lwp *l, const void *args, register_t *retval) | |
494 | { | 581 | { | |
495 | aarch64_drain_writebuf(); | 582 | aarch64_drain_writebuf(); | |
496 | 583 | |||
497 | *retval = 0; | 584 | *retval = 0; | |
498 | return 0; | 585 | return 0; | |
499 | } | 586 | } | |
500 | 587 | |||
501 | int | 588 | int | |
502 | netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, | 589 | netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, | |
503 | register_t *retval) | 590 | register_t *retval) | |
504 | { | 591 | { | |
505 | /* { | 592 | /* { | |
506 | syscallarg(int) op; | 593 | syscallarg(int) op; | |
507 | syscallarg(netbsd32_voidp) parms; | 594 | syscallarg(netbsd32_voidp) parms; | |
508 | } */ | 595 | } */ | |
509 | int error; | 596 | int error; | |
510 | 597 | |||
511 | switch (SCARG(uap, op)) { | 598 | switch (SCARG(uap, op)) { | |
512 | case ARM_SYNC_ICACHE: | 599 | case ARM_SYNC_ICACHE: | |
513 | error = arm32_sync_icache(l, | 600 | error = arm32_sync_icache(l, | |
514 | NETBSD32PTR64(SCARG(uap, parms)), retval); | 601 | NETBSD32PTR64(SCARG(uap, parms)), retval); | |
515 | break; | 602 | break; | |
516 | case ARM_DRAIN_WRITEBUF: | 603 | case ARM_DRAIN_WRITEBUF: | |
517 | error = arm32_drain_writebuf(l, | 604 | error = arm32_drain_writebuf(l, | |
518 | NETBSD32PTR64(SCARG(uap, parms)), retval); | 605 | NETBSD32PTR64(SCARG(uap, parms)), retval); | |
519 | break; | 606 | break; | |
520 | case ARM_VFP_FPSCR: | 607 | case ARM_VFP_FPSCR: | |
521 | printf("%s: ARM_VFP_FPSCR not implemented\n", __func__); | 608 | printf("%s: ARM_VFP_FPSCR not implemented\n", __func__); | |
522 | error = EINVAL; | 609 | error = EINVAL; | |
523 | break; | 610 | break; | |
524 | case ARM_FPU_USED: | 611 | case ARM_FPU_USED: | |
525 | printf("%s: ARM_FPU_USED not implemented\n", __func__); | 612 | printf("%s: ARM_FPU_USED not implemented\n", __func__); | |
526 | error = EINVAL; | 613 | error = EINVAL; | |
527 | break; | 614 | break; | |
528 | default: | 615 | default: | |
529 | printf("%s: op=%d: not implemented\n", __func__, | 616 | printf("%s: op=%d: not implemented\n", __func__, | |
530 | SCARG(uap, op)); | 617 | SCARG(uap, op)); | |
531 | error = EINVAL; | 618 | error = EINVAL; | |
532 | break; | 619 | break; | |
533 | } | 620 | } | |
534 | return error; | 621 | return error; | |
535 | } | 622 | } | |
536 | 623 | |||
537 | vaddr_t | 624 | vaddr_t | |
538 | netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t sz, | 625 | netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t sz, | |
539 | int topdown) | 626 | int topdown) | |
540 | { | 627 | { | |
541 | if (topdown) | 628 | if (topdown) | |
542 | return VM_DEFAULT_ADDRESS32_TOPDOWN(base, sz); | 629 | return VM_DEFAULT_ADDRESS32_TOPDOWN(base, sz); | |
543 | else | 630 | else | |
544 | return VM_DEFAULT_ADDRESS32_BOTTOMUP(base, sz); | 631 | return VM_DEFAULT_ADDRESS32_BOTTOMUP(base, sz); | |
545 | } | 632 | } | |
546 | 633 | |||
547 | void | 634 | void | |
548 | netbsd32_machdep_md_init(void) | 635 | netbsd32_machdep_md_init(void) | |
549 | { | 636 | { | |
550 | 637 | |||
551 | /* nothing to do */ | 638 | /* nothing to do */ | |
552 | } | 639 | } | |
553 | 640 | |||
554 | void | 641 | void | |
555 | netbsd32_machdep_md_fini(void) | 642 | netbsd32_machdep_md_fini(void) | |
556 | { | 643 | { | |
557 | 644 | |||
558 | /* nothing to do */ | 645 | /* nothing to do */ | |
559 | } | 646 | } |
--- src/sys/arch/aarch64/aarch64/trap.c 2021/01/01 12:31:19 1.17.4.3
+++ src/sys/arch/aarch64/aarch64/trap.c 2021/01/01 12:58:35 1.17.4.4
@@ -1,638 +1,655 @@ | @@ -1,638 +1,655 @@ | |||
1 | /* $NetBSD: trap.c,v 1.17.4.3 2021/01/01 12:31:19 martin Exp $ */ | 1 | /* $NetBSD: trap.c,v 1.17.4.4 2021/01/01 12:58:35 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Matt Thomas of 3am Software Foundry. | 8 | * by Matt Thomas of 3am Software Foundry. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | 33 | |||
34 | __KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.17.4.3 2021/01/01 12:31:19 martin Exp $"); | 34 | __KERNEL_RCSID(1, "$NetBSD: trap.c,v 1.17.4.4 2021/01/01 12:58:35 martin Exp $"); | |
35 | 35 | |||
36 | #include "opt_arm_intr_impl.h" | 36 | #include "opt_arm_intr_impl.h" | |
37 | #include "opt_compat_netbsd32.h" | 37 | #include "opt_compat_netbsd32.h" | |
38 | #include "opt_dtrace.h" | 38 | #include "opt_dtrace.h" | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/kauth.h> | 41 | #include <sys/kauth.h> | |
42 | #include <sys/types.h> | 42 | #include <sys/types.h> | |
43 | #include <sys/atomic.h> | 43 | #include <sys/atomic.h> | |
44 | #include <sys/cpu.h> | 44 | #include <sys/cpu.h> | |
45 | #ifdef KDB | 45 | #ifdef KDB | |
46 | #include <sys/kdb.h> | 46 | #include <sys/kdb.h> | |
47 | #endif | 47 | #endif | |
48 | #include <sys/proc.h> | 48 | #include <sys/proc.h> | |
49 | #include <sys/systm.h> | 49 | #include <sys/systm.h> | |
50 | #include <sys/signal.h> | 50 | #include <sys/signal.h> | |
51 | #include <sys/signalvar.h> | 51 | #include <sys/signalvar.h> | |
52 | #include <sys/siginfo.h> | 52 | #include <sys/siginfo.h> | |
53 | 53 | |||
54 | #ifdef ARM_INTR_IMPL | 54 | #ifdef ARM_INTR_IMPL | |
55 | #include ARM_INTR_IMPL | 55 | #include ARM_INTR_IMPL | |
56 | #else | 56 | #else | |
57 | #error ARM_INTR_IMPL not defined | 57 | #error ARM_INTR_IMPL not defined | |
58 | #endif | 58 | #endif | |
59 | 59 | |||
60 | #ifndef ARM_IRQ_HANDLER | 60 | #ifndef ARM_IRQ_HANDLER | |
61 | #error ARM_IRQ_HANDLER not defined | 61 | #error ARM_IRQ_HANDLER not defined | |
62 | #endif | 62 | #endif | |
63 | 63 | |||
64 | #include <aarch64/userret.h> | 64 | #include <aarch64/userret.h> | |
65 | #include <aarch64/frame.h> | 65 | #include <aarch64/frame.h> | |
66 | #include <aarch64/machdep.h> | 66 | #include <aarch64/machdep.h> | |
67 | #include <aarch64/armreg.h> | 67 | #include <aarch64/armreg.h> | |
68 | #include <aarch64/locore.h> | 68 | #include <aarch64/locore.h> | |
69 | 69 | |||
70 | #ifdef KDB | 70 | #ifdef KDB | |
71 | #include <machine/db_machdep.h> | 71 | #include <machine/db_machdep.h> | |
72 | #endif | 72 | #endif | |
73 | #ifdef DDB | 73 | #ifdef DDB | |
74 | #include <ddb/db_output.h> | 74 | #include <ddb/db_output.h> | |
75 | #include <machine/db_machdep.h> | 75 | #include <machine/db_machdep.h> | |
76 | #endif | 76 | #endif | |
77 | #ifdef KDTRACE_HOOKS | 77 | #ifdef KDTRACE_HOOKS | |
78 | #include <sys/dtrace_bsd.h> | 78 | #include <sys/dtrace_bsd.h> | |
79 | #endif | 79 | #endif | |
80 | 80 | |||
81 | #ifdef DDB | 81 | #ifdef DDB | |
82 | int sigill_debug = 0; | 82 | int sigill_debug = 0; | |
83 | #endif | 83 | #endif | |
84 | 84 | |||
85 | #ifdef KDTRACE_HOOKS | 85 | #ifdef KDTRACE_HOOKS | |
86 | dtrace_doubletrap_func_t dtrace_doubletrap_func = NULL; | 86 | dtrace_doubletrap_func_t dtrace_doubletrap_func = NULL; | |
87 | dtrace_trap_func_t dtrace_trap_func = NULL; | 87 | dtrace_trap_func_t dtrace_trap_func = NULL; | |
88 | int (*dtrace_invop_jump_addr)(struct trapframe *); | 88 | int (*dtrace_invop_jump_addr)(struct trapframe *); | |
89 | #endif | 89 | #endif | |
90 | 90 | |||
91 | const char * const trap_names[] = { | 91 | const char * const trap_names[] = { | |
92 | [ESR_EC_UNKNOWN] = "Unknown Reason (Illegal Instruction)", | 92 | [ESR_EC_UNKNOWN] = "Unknown Reason (Illegal Instruction)", | |
93 | [ESR_EC_SERROR] = "SError Interrupt", | 93 | [ESR_EC_SERROR] = "SError Interrupt", | |
94 | [ESR_EC_WFX] = "WFI or WFE instruction execution", | 94 | [ESR_EC_WFX] = "WFI or WFE instruction execution", | |
95 | [ESR_EC_ILL_STATE] = "Illegal Execution State", | 95 | [ESR_EC_ILL_STATE] = "Illegal Execution State", | |
96 | 96 | |||
97 | [ESR_EC_SYS_REG] = "MSR/MRS/SYS instruction", | 97 | [ESR_EC_SYS_REG] = "MSR/MRS/SYS instruction", | |
98 | [ESR_EC_SVC_A64] = "SVC Instruction Execution", | 98 | [ESR_EC_SVC_A64] = "SVC Instruction Execution", | |
99 | [ESR_EC_HVC_A64] = "HVC Instruction Execution", | 99 | [ESR_EC_HVC_A64] = "HVC Instruction Execution", | |
100 | [ESR_EC_SMC_A64] = "SMC Instruction Execution", | 100 | [ESR_EC_SMC_A64] = "SMC Instruction Execution", | |
101 | 101 | |||
102 | [ESR_EC_INSN_ABT_EL0] = "Instruction Abort (EL0)", | 102 | [ESR_EC_INSN_ABT_EL0] = "Instruction Abort (EL0)", | |
103 | [ESR_EC_INSN_ABT_EL1] = "Instruction Abort (EL1)", | 103 | [ESR_EC_INSN_ABT_EL1] = "Instruction Abort (EL1)", | |
104 | [ESR_EC_DATA_ABT_EL0] = "Data Abort (EL0)", | 104 | [ESR_EC_DATA_ABT_EL0] = "Data Abort (EL0)", | |
105 | [ESR_EC_DATA_ABT_EL1] = "Data Abort (EL1)", | 105 | [ESR_EC_DATA_ABT_EL1] = "Data Abort (EL1)", | |
106 | 106 | |||
107 | [ESR_EC_PC_ALIGNMENT] = "Misaligned PC", | 107 | [ESR_EC_PC_ALIGNMENT] = "Misaligned PC", | |
108 | [ESR_EC_SP_ALIGNMENT] = "Misaligned SP", | 108 | [ESR_EC_SP_ALIGNMENT] = "Misaligned SP", | |
109 | 109 | |||
110 | [ESR_EC_FP_ACCESS] = "Access to SIMD/FP Registers", | 110 | [ESR_EC_FP_ACCESS] = "Access to SIMD/FP Registers", | |
111 | [ESR_EC_FP_TRAP_A64] = "FP Exception", | 111 | [ESR_EC_FP_TRAP_A64] = "FP Exception", | |
112 | 112 | |||
113 | [ESR_EC_BRKPNT_EL0] = "Breakpoint Exception (EL0)", | 113 | [ESR_EC_BRKPNT_EL0] = "Breakpoint Exception (EL0)", | |
114 | [ESR_EC_BRKPNT_EL1] = "Breakpoint Exception (EL1)", | 114 | [ESR_EC_BRKPNT_EL1] = "Breakpoint Exception (EL1)", | |
115 | [ESR_EC_SW_STEP_EL0] = "Software Step (EL0)", | 115 | [ESR_EC_SW_STEP_EL0] = "Software Step (EL0)", | |
116 | [ESR_EC_SW_STEP_EL1] = "Software Step (EL1)", | 116 | [ESR_EC_SW_STEP_EL1] = "Software Step (EL1)", | |
117 | [ESR_EC_WTCHPNT_EL0] = "Watchpoint (EL0)", | 117 | [ESR_EC_WTCHPNT_EL0] = "Watchpoint (EL0)", | |
118 | [ESR_EC_WTCHPNT_EL1] = "Watchpoint (EL1)", | 118 | [ESR_EC_WTCHPNT_EL1] = "Watchpoint (EL1)", | |
119 | [ESR_EC_BKPT_INSN_A64] = "BKPT Instruction Execution", | 119 | [ESR_EC_BKPT_INSN_A64] = "BKPT Instruction Execution", | |
120 | 120 | |||
121 | [ESR_EC_CP15_RT] = "A32: MCR/MRC access to CP15", | 121 | [ESR_EC_CP15_RT] = "A32: MCR/MRC access to CP15", | |
122 | [ESR_EC_CP15_RRT] = "A32: MCRR/MRRC access to CP15", | 122 | [ESR_EC_CP15_RRT] = "A32: MCRR/MRRC access to CP15", | |
123 | [ESR_EC_CP14_RT] = "A32: MCR/MRC access to CP14", | 123 | [ESR_EC_CP14_RT] = "A32: MCR/MRC access to CP14", | |
124 | [ESR_EC_CP14_DT] = "A32: LDC/STC access to CP14", | 124 | [ESR_EC_CP14_DT] = "A32: LDC/STC access to CP14", | |
125 | [ESR_EC_CP14_RRT] = "A32: MRRC access to CP14", | 125 | [ESR_EC_CP14_RRT] = "A32: MRRC access to CP14", | |
126 | [ESR_EC_SVC_A32] = "A32: SVC Instruction Execution", | 126 | [ESR_EC_SVC_A32] = "A32: SVC Instruction Execution", | |
127 | [ESR_EC_HVC_A32] = "A32: HVC Instruction Execution", | 127 | [ESR_EC_HVC_A32] = "A32: HVC Instruction Execution", | |
128 | [ESR_EC_SMC_A32] = "A32: SMC Instruction Execution", | 128 | [ESR_EC_SMC_A32] = "A32: SMC Instruction Execution", | |
129 | [ESR_EC_FPID] = "A32: MCR/MRC access to CP10", | 129 | [ESR_EC_FPID] = "A32: MCR/MRC access to CP10", | |
130 | [ESR_EC_FP_TRAP_A32] = "A32: FP Exception", | 130 | [ESR_EC_FP_TRAP_A32] = "A32: FP Exception", | |
131 | [ESR_EC_BKPT_INSN_A32] = "A32: BKPT Instruction Execution", | 131 | [ESR_EC_BKPT_INSN_A32] = "A32: BKPT Instruction Execution", | |
132 | [ESR_EC_VECTOR_CATCH] = "A32: Vector Catch Exception" | 132 | [ESR_EC_VECTOR_CATCH] = "A32: Vector Catch Exception" | |
133 | }; | 133 | }; | |
134 | 134 | |||
135 | const char * | 135 | const char * | |
136 | eclass_trapname(uint32_t eclass) | 136 | eclass_trapname(uint32_t eclass) | |
137 | { | 137 | { | |
138 | static char trapnamebuf[sizeof("Unknown trap 0x????????")]; | 138 | static char trapnamebuf[sizeof("Unknown trap 0x????????")]; | |
139 | 139 | |||
140 | if (eclass >= __arraycount(trap_names) || trap_names[eclass] == NULL) { | 140 | if (eclass >= __arraycount(trap_names) || trap_names[eclass] == NULL) { | |
141 | snprintf(trapnamebuf, sizeof(trapnamebuf), | 141 | snprintf(trapnamebuf, sizeof(trapnamebuf), | |
142 | "Unknown trap %#02x", eclass); | 142 | "Unknown trap %#02x", eclass); | |
143 | return trapnamebuf; | 143 | return trapnamebuf; | |
144 | } | 144 | } | |
145 | return trap_names[eclass]; | 145 | return trap_names[eclass]; | |
146 | } | 146 | } | |
147 | 147 | |||
148 | void | 148 | void | |
149 | userret(struct lwp *l) | 149 | userret(struct lwp *l) | |
150 | { | 150 | { | |
151 | mi_userret(l); | 151 | mi_userret(l); | |
152 | } | 152 | } | |
153 | 153 | |||
154 | void | 154 | void | |
155 | trap_doast(struct trapframe *tf) | 155 | trap_doast(struct trapframe *tf) | |
156 | { | 156 | { | |
157 | struct lwp * const l = curlwp; | 157 | struct lwp * const l = curlwp; | |
158 | 158 | |||
159 | /* | 159 | /* | |
160 | * allow to have a chance of context switch just prior to user | 160 | * allow to have a chance of context switch just prior to user | |
161 | * exception return. | 161 | * exception return. | |
162 | */ | 162 | */ | |
163 | #ifdef __HAVE_PREEMPTION | 163 | #ifdef __HAVE_PREEMPTION | |
164 | kpreempt_disable(); | 164 | kpreempt_disable(); | |
165 | #endif | 165 | #endif | |
166 | struct cpu_info * const ci = curcpu(); | 166 | struct cpu_info * const ci = curcpu(); | |
167 | 167 | |||
168 | ci->ci_data.cpu_ntrap++; | 168 | ci->ci_data.cpu_ntrap++; | |
169 | 169 | |||
170 | KDASSERT(ci->ci_cpl == IPL_NONE); | 170 | KDASSERT(ci->ci_cpl == IPL_NONE); | |
171 | const int want_resched = ci->ci_want_resched; | 171 | const int want_resched = ci->ci_want_resched; | |
172 | #ifdef __HAVE_PREEMPTION | 172 | #ifdef __HAVE_PREEMPTION | |
173 | kpreempt_enable(); | 173 | kpreempt_enable(); | |
174 | #endif | 174 | #endif | |
175 | 175 | |||
176 | if (l->l_pflag & LP_OWEUPC) { | 176 | if (l->l_pflag & LP_OWEUPC) { | |
177 | l->l_pflag &= ~LP_OWEUPC; | 177 | l->l_pflag &= ~LP_OWEUPC; | |
178 | ADDUPROF(l); | 178 | ADDUPROF(l); | |
179 | } | 179 | } | |
180 | 180 | |||
181 | /* Allow a forced task switch. */ | 181 | /* Allow a forced task switch. */ | |
182 | if (want_resched) | 182 | if (want_resched) | |
183 | preempt(); | 183 | preempt(); | |
184 | userret(l); | 184 | userret(l); | |
185 | } | 185 | } | |
186 | 186 | |||
187 | void | 187 | void | |
188 | trap_el1h_sync(struct trapframe *tf) | 188 | trap_el1h_sync(struct trapframe *tf) | |
189 | { | 189 | { | |
190 | const uint32_t esr = tf->tf_esr; | 190 | const uint32_t esr = tf->tf_esr; | |
191 | const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */ | 191 | const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */ | |
192 | 192 | |||
193 | /* re-enable traps and interrupts */ | 193 | /* re-enable traps and interrupts */ | |
194 | if (!(tf->tf_spsr & SPSR_I)) | 194 | if (!(tf->tf_spsr & SPSR_I)) | |
195 | daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F); | 195 | daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F); | |
196 | else | 196 | else | |
197 | daif_enable(DAIF_D|DAIF_A); | 197 | daif_enable(DAIF_D|DAIF_A); | |
198 | 198 | |||
199 | #ifdef KDTRACE_HOOKS | 199 | #ifdef KDTRACE_HOOKS | |
200 | if (dtrace_trap_func != NULL && (*dtrace_trap_func)(tf, eclass)) | 200 | if (dtrace_trap_func != NULL && (*dtrace_trap_func)(tf, eclass)) | |
201 | return; | 201 | return; | |
202 | #endif | 202 | #endif | |
203 | 203 | |||
204 | switch (eclass) { | 204 | switch (eclass) { | |
205 | case ESR_EC_INSN_ABT_EL1: | 205 | case ESR_EC_INSN_ABT_EL1: | |
206 | case ESR_EC_DATA_ABT_EL1: | 206 | case ESR_EC_DATA_ABT_EL1: | |
207 | data_abort_handler(tf, eclass); | 207 | data_abort_handler(tf, eclass); | |
208 | break; | 208 | break; | |
209 | 209 | |||
210 | case ESR_EC_BKPT_INSN_A64: | 210 | case ESR_EC_BKPT_INSN_A64: | |
211 | #ifdef KDTRACE_HOOKS | 211 | #ifdef KDTRACE_HOOKS | |
212 | if (__SHIFTOUT(esr, ESR_ISS) == 0x40d && | 212 | if (__SHIFTOUT(esr, ESR_ISS) == 0x40d && | |
213 | dtrace_invop_jump_addr != 0) { | 213 | dtrace_invop_jump_addr != 0) { | |
214 | (*dtrace_invop_jump_addr)(tf); | 214 | (*dtrace_invop_jump_addr)(tf); | |
215 | break; | 215 | break; | |
216 | } | 216 | } | |
217 | /* FALLTHROUGH */ | 217 | /* FALLTHROUGH */ | |
218 | #endif | 218 | #endif | |
219 | case ESR_EC_BRKPNT_EL1: | 219 | case ESR_EC_BRKPNT_EL1: | |
220 | case ESR_EC_SW_STEP_EL1: | 220 | case ESR_EC_SW_STEP_EL1: | |
221 | case ESR_EC_WTCHPNT_EL1: | 221 | case ESR_EC_WTCHPNT_EL1: | |
222 | #ifdef DDB | 222 | #ifdef DDB | |
223 | if (eclass == ESR_EC_BRKPNT_EL1) | 223 | if (eclass == ESR_EC_BRKPNT_EL1) | |
224 | kdb_trap(DB_TRAP_BREAKPOINT, tf); | 224 | kdb_trap(DB_TRAP_BREAKPOINT, tf); | |
225 | else if (eclass == ESR_EC_BKPT_INSN_A64) | 225 | else if (eclass == ESR_EC_BKPT_INSN_A64) | |
226 | kdb_trap(DB_TRAP_BKPT_INSN, tf); | 226 | kdb_trap(DB_TRAP_BKPT_INSN, tf); | |
227 | else if (eclass == ESR_EC_WTCHPNT_EL1) | 227 | else if (eclass == ESR_EC_WTCHPNT_EL1) | |
228 | kdb_trap(DB_TRAP_WATCHPOINT, tf); | 228 | kdb_trap(DB_TRAP_WATCHPOINT, tf); | |
229 | else if (eclass == ESR_EC_SW_STEP_EL1) | 229 | else if (eclass == ESR_EC_SW_STEP_EL1) | |
230 | kdb_trap(DB_TRAP_SW_STEP, tf); | 230 | kdb_trap(DB_TRAP_SW_STEP, tf); | |
231 | else | 231 | else | |
232 | kdb_trap(DB_TRAP_UNKNOWN, tf); | 232 | kdb_trap(DB_TRAP_UNKNOWN, tf); | |
233 | #else | 233 | #else | |
234 | panic("No debugger in kernel"); | 234 | panic("No debugger in kernel"); | |
235 | #endif | 235 | #endif | |
236 | break; | 236 | break; | |
237 | 237 | |||
238 | case ESR_EC_FP_ACCESS: | 238 | case ESR_EC_FP_ACCESS: | |
239 | case ESR_EC_FP_TRAP_A64: | 239 | case ESR_EC_FP_TRAP_A64: | |
240 | case ESR_EC_PC_ALIGNMENT: | 240 | case ESR_EC_PC_ALIGNMENT: | |
241 | case ESR_EC_SP_ALIGNMENT: | 241 | case ESR_EC_SP_ALIGNMENT: | |
242 | case ESR_EC_ILL_STATE: | 242 | case ESR_EC_ILL_STATE: | |
243 | default: | 243 | default: | |
244 | panic("Trap: fatal %s: pc=%016" PRIx64 " sp=%016" PRIx64 | 244 | panic("Trap: fatal %s: pc=%016" PRIx64 " sp=%016" PRIx64 | |
245 | " esr=%08x", eclass_trapname(eclass), tf->tf_pc, tf->tf_sp, | 245 | " esr=%08x", eclass_trapname(eclass), tf->tf_pc, tf->tf_sp, | |
246 | esr); | 246 | esr); | |
247 | break; | 247 | break; | |
248 | } | 248 | } | |
249 | } | 249 | } | |
250 | 250 | |||
251 | void | 251 | void | |
252 | trap_el0_sync(struct trapframe *tf) | 252 | trap_el0_sync(struct trapframe *tf) | |
253 | { | 253 | { | |
254 | struct lwp * const l = curlwp; | 254 | struct lwp * const l = curlwp; | |
255 | const uint32_t esr = tf->tf_esr; | 255 | const uint32_t esr = tf->tf_esr; | |
256 | const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */ | 256 | const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */ | |
257 | 257 | |||
258 | /* disable trace */ | 258 | /* disable trace */ | |
259 | reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS); | 259 | reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS); | |
260 | /* enable traps and interrupts */ | 260 | /* enable traps and interrupts */ | |
261 | daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F); | 261 | daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F); | |
262 | 262 | |||
263 | switch (eclass) { | 263 | switch (eclass) { | |
264 | case ESR_EC_INSN_ABT_EL0: | 264 | case ESR_EC_INSN_ABT_EL0: | |
265 | case ESR_EC_DATA_ABT_EL0: | 265 | case ESR_EC_DATA_ABT_EL0: | |
266 | data_abort_handler(tf, eclass); | 266 | data_abort_handler(tf, eclass); | |
267 | userret(l); | 267 | userret(l); | |
268 | break; | 268 | break; | |
269 | 269 | |||
270 | case ESR_EC_SVC_A64: | 270 | case ESR_EC_SVC_A64: | |
271 | (*l->l_proc->p_md.md_syscall)(tf); | 271 | (*l->l_proc->p_md.md_syscall)(tf); | |
272 | break; | 272 | break; | |
273 | case ESR_EC_FP_ACCESS: | 273 | case ESR_EC_FP_ACCESS: | |
274 | fpu_load(l); | 274 | fpu_load(l); | |
275 | userret(l); | 275 | userret(l); | |
276 | break; | 276 | break; | |
277 | case ESR_EC_FP_TRAP_A64: | 277 | case ESR_EC_FP_TRAP_A64: | |
278 | do_trapsignal(l, SIGFPE, FPE_FLTUND, NULL, esr); /* XXX */ | 278 | do_trapsignal(l, SIGFPE, FPE_FLTUND, NULL, esr); /* XXX */ | |
279 | userret(l); | 279 | userret(l); | |
280 | break; | 280 | break; | |
281 | 281 | |||
282 | case ESR_EC_PC_ALIGNMENT: | 282 | case ESR_EC_PC_ALIGNMENT: | |
283 | do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_pc, esr); | 283 | do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_pc, esr); | |
284 | userret(l); | 284 | userret(l); | |
285 | break; | 285 | break; | |
286 | case ESR_EC_SP_ALIGNMENT: | 286 | case ESR_EC_SP_ALIGNMENT: | |
287 | do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_sp, esr); | 287 | do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_sp, esr); | |
288 | userret(l); | 288 | userret(l); | |
289 | break; | 289 | break; | |
290 | 290 | |||
291 | case ESR_EC_BKPT_INSN_A64: | 291 | case ESR_EC_BKPT_INSN_A64: | |
292 | case ESR_EC_BRKPNT_EL0: | 292 | case ESR_EC_BRKPNT_EL0: | |
293 | case ESR_EC_WTCHPNT_EL0: | 293 | case ESR_EC_WTCHPNT_EL0: | |
294 | do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr); | 294 | do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr); | |
295 | userret(l); | 295 | userret(l); | |
296 | break; | 296 | break; | |
297 | case ESR_EC_SW_STEP_EL0: | 297 | case ESR_EC_SW_STEP_EL0: | |
298 | /* disable trace, and send trace trap */ | 298 | /* disable trace, and send trace trap */ | |
299 | tf->tf_spsr &= ~SPSR_SS; | 299 | tf->tf_spsr &= ~SPSR_SS; | |
300 | do_trapsignal(l, SIGTRAP, TRAP_TRACE, (void *)tf->tf_pc, esr); | 300 | do_trapsignal(l, SIGTRAP, TRAP_TRACE, (void *)tf->tf_pc, esr); | |
301 | userret(l); | 301 | userret(l); | |
302 | break; | 302 | break; | |
303 | 303 | |||
304 | default: | 304 | default: | |
305 | case ESR_EC_UNKNOWN: | 305 | case ESR_EC_UNKNOWN: | |
306 | #ifdef DDB | 306 | #ifdef DDB | |
307 | if (sigill_debug) { | 307 | if (sigill_debug) { | |
308 | /* show illegal instruction */ | 308 | /* show illegal instruction */ | |
309 | printf("TRAP: pid %d (%s), uid %d: %s:" | 309 | printf("TRAP: pid %d (%s), uid %d: %s:" | |
310 | " esr=0x%lx: pc=0x%lx: %s\n", | 310 | " esr=0x%lx: pc=0x%lx: %s\n", | |
311 | curlwp->l_proc->p_pid, curlwp->l_proc->p_comm, | 311 | curlwp->l_proc->p_pid, curlwp->l_proc->p_comm, | |
312 | l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1, | 312 | l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1, | |
313 | eclass_trapname(eclass), tf->tf_esr, tf->tf_pc, | 313 | eclass_trapname(eclass), tf->tf_esr, tf->tf_pc, | |
314 | strdisasm(tf->tf_pc)); | 314 | strdisasm(tf->tf_pc)); | |
315 | } | 315 | } | |
316 | #endif | 316 | #endif | |
317 | /* illegal or not implemented instruction */ | 317 | /* illegal or not implemented instruction */ | |
318 | do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr); | 318 | do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr); | |
319 | userret(l); | 319 | userret(l); | |
320 | break; | 320 | break; | |
321 | } | 321 | } | |
322 | } | 322 | } | |
323 | 323 | |||
324 | void | 324 | void | |
325 | interrupt(struct trapframe *tf) | 325 | interrupt(struct trapframe *tf) | |
326 | { | 326 | { | |
327 | struct cpu_info * const ci = curcpu(); | 327 | struct cpu_info * const ci = curcpu(); | |
328 | 328 | |||
329 | #ifdef STACKCHECKS | 329 | #ifdef STACKCHECKS | |
330 | struct lwp *l = curlwp; | 330 | struct lwp *l = curlwp; | |
331 | void *sp = (void *)reg_sp_read(); | 331 | void *sp = (void *)reg_sp_read(); | |
332 | if (l->l_addr >= sp) { | 332 | if (l->l_addr >= sp) { | |
333 | panic("lwp/interrupt stack overflow detected." | 333 | panic("lwp/interrupt stack overflow detected." | |
334 | " lwp=%p, sp=%p, l_addr=%p", l, sp, l->l_addr); | 334 | " lwp=%p, sp=%p, l_addr=%p", l, sp, l->l_addr); | |
335 | } | 335 | } | |
336 | #endif | 336 | #endif | |
337 | 337 | |||
338 | /* disable trace */ | 338 | /* disable trace */ | |
339 | reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS); | 339 | reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS); | |
340 | 340 | |||
341 | /* enable traps */ | 341 | /* enable traps */ | |
342 | daif_enable(DAIF_D|DAIF_A); | 342 | daif_enable(DAIF_D|DAIF_A); | |
343 | 343 | |||
344 | ci->ci_intr_depth++; | 344 | ci->ci_intr_depth++; | |
345 | ARM_IRQ_HANDLER(tf); | 345 | ARM_IRQ_HANDLER(tf); | |
346 | ci->ci_intr_depth--; | 346 | ci->ci_intr_depth--; | |
347 | 347 | |||
348 | cpu_dosoftints(); | 348 | cpu_dosoftints(); | |
349 | } | 349 | } | |
350 | 350 | |||
351 | #ifdef COMPAT_NETBSD32 | 351 | #ifdef COMPAT_NETBSD32 | |
352 | 352 | |||
353 | /* | 353 | /* | |
354 | * 32-bit length Thumb instruction. See ARMv7 DDI0406A A6.3. | 354 | * 32-bit length Thumb instruction. See ARMv7 DDI0406A A6.3. | |
355 | */ | 355 | */ | |
356 | #define THUMB_32BIT(hi) (((hi) & 0xe000) == 0xe000 && ((hi) & 0x1800)) | 356 | #define THUMB_32BIT(hi) (((hi) & 0xe000) == 0xe000 && ((hi) & 0x1800)) | |
357 | 357 | |||
358 | static int | 358 | static int | |
359 | fetch_arm_insn(struct trapframe *tf, uint32_t *insn) | 359 | fetch_arm_insn(struct trapframe *tf, uint32_t *insn) | |
360 | { | 360 | { | |
361 | 361 | |||
362 | /* THUMB? */ | 362 | /* THUMB? */ | |
363 | if (tf->tf_spsr & SPSR_A32_T) { | 363 | if (tf->tf_spsr & SPSR_A32_T) { | |
364 | uint16_t *pc = (uint16_t *)(tf->tf_pc & ~1UL); /* XXX */ | 364 | uint16_t *pc = (uint16_t *)(tf->tf_pc & ~1UL); /* XXX */ | |
365 | uint16_t hi, lo; | 365 | uint16_t hi, lo; | |
366 | 366 | |||
367 | if (ufetch_16(pc, &hi)) | 367 | if (ufetch_16(pc, &hi)) | |
368 | return -1; | 368 | return -1; | |
369 | 369 | |||
370 | if (!THUMB_32BIT(hi)) { | 370 | if (!THUMB_32BIT(hi)) { | |
371 | /* 16-bit Thumb instruction */ | 371 | /* 16-bit Thumb instruction */ | |
372 | *insn = hi; | 372 | *insn = hi; | |
373 | return 2; | 373 | return 2; | |
374 | } | 374 | } | |
375 | 375 | |||
376 | /* 32-bit Thumb instruction */ | 376 | /* 32-bit Thumb instruction */ | |
377 | if (ufetch_16(pc + 1, &lo)) | 377 | if (ufetch_16(pc + 1, &lo)) | |
378 | return -1; | 378 | return -1; | |
379 | 379 | |||
380 | *insn = ((uint32_t)hi << 16) | lo; | 380 | *insn = ((uint32_t)hi << 16) | lo; | |
381 | return 4; | 381 | return 4; | |
382 | } | 382 | } | |
383 | 383 | |||
384 | if (ufetch_32((uint32_t *)tf->tf_pc, insn)) | 384 | if (ufetch_32((uint32_t *)tf->tf_pc, insn)) | |
385 | return -1; | 385 | return -1; | |
386 | 386 | |||
387 | return 4; | 387 | return 4; | |
388 | } | 388 | } | |
389 | 389 | |||
390 | enum emul_arm_result { | 390 | enum emul_arm_result { | |
391 | EMUL_ARM_SUCCESS = 0, | 391 | EMUL_ARM_SUCCESS = 0, | |
392 | EMUL_ARM_UNKNOWN, | 392 | EMUL_ARM_UNKNOWN, | |
393 | EMUL_ARM_FAULT, | 393 | EMUL_ARM_FAULT, | |
394 | }; | 394 | }; | |
395 | 395 | |||
396 | static enum emul_arm_result | 396 | static enum emul_arm_result | |
397 | emul_arm_insn(struct trapframe *tf) | 397 | emul_arm_insn(struct trapframe *tf) | |
398 | { | 398 | { | |
399 | struct lwp * const l = curlwp; | |||
399 | uint32_t insn; | 400 | uint32_t insn; | |
400 | int insn_size; | 401 | int insn_size; | |
401 | 402 | |||
402 | insn_size = fetch_arm_insn(tf, &insn); | 403 | insn_size = fetch_arm_insn(tf, &insn); | |
403 | 404 | |||
404 | switch (insn_size) { | 405 | switch (insn_size) { | |
405 | case 2: | 406 | case 2: | |
406 | /* T32-16bit instruction */ | 407 | /* T32-16bit instruction */ | |
407 | 408 | |||
409 | /* | |||
410 | * Breakpoint used by GDB. | |||
411 | */ | |||
412 | if (insn == 0xdefe) | |||
413 | goto trap; | |||
414 | ||||
408 | /* XXX: some T32 IT instruction deprecated should be emulated */ | 415 | /* XXX: some T32 IT instruction deprecated should be emulated */ | |
409 | break; | 416 | break; | |
410 | case 4: | 417 | case 4: | |
411 | /* T32-32bit instruction, or A32 instruction */ | 418 | /* T32-32bit instruction, or A32 instruction */ | |
412 | 419 | |||
413 | /* | 420 | /* | |
421 | * Breakpoint used by GDB. | |||
422 | */ | |||
423 | if (insn == 0xe6000011 || insn == 0xe7ffdefe) { | |||
424 | trap: | |||
425 | do_trapsignal(l, SIGTRAP, TRAP_BRKPT, | |||
426 | (void *)tf->tf_pc, 0); | |||
427 | return 0; | |||
428 | } | |||
429 | ||||
430 | /* | |||
414 | * Emulate ARMv6 instructions with cache operations | 431 | * Emulate ARMv6 instructions with cache operations | |
415 | * register (c7), that can be used in user mode. | 432 | * register (c7), that can be used in user mode. | |
416 | */ | 433 | */ | |
417 | switch (insn & 0x0fff0fff) { | 434 | switch (insn & 0x0fff0fff) { | |
418 | case 0x0e070f95: | 435 | case 0x0e070f95: | |
419 | /* | 436 | /* | |
420 | * mcr p15, 0, <Rd>, c7, c5, 4 | 437 | * mcr p15, 0, <Rd>, c7, c5, 4 | |
421 | * (flush prefetch buffer) | 438 | * (flush prefetch buffer) | |
422 | */ | 439 | */ | |
423 | __asm __volatile("isb sy" ::: "memory"); | 440 | __asm __volatile("isb sy" ::: "memory"); | |
424 | goto emulated; | 441 | goto emulated; | |
425 | case 0x0e070f9a: | 442 | case 0x0e070f9a: | |
426 | /* | 443 | /* | |
427 | * mcr p15, 0, <Rd>, c7, c10, 4 | 444 | * mcr p15, 0, <Rd>, c7, c10, 4 | |
428 | * (data synchronization barrier) | 445 | * (data synchronization barrier) | |
429 | */ | 446 | */ | |
430 | __asm __volatile("dsb sy" ::: "memory"); | 447 | __asm __volatile("dsb sy" ::: "memory"); | |
431 | goto emulated; | 448 | goto emulated; | |
432 | case 0x0e070fba: | 449 | case 0x0e070fba: | |
433 | /* | 450 | /* | |
434 | * mcr p15, 0, <Rd>, c7, c10, 5 | 451 | * mcr p15, 0, <Rd>, c7, c10, 5 | |
435 | * (data memory barrier) | 452 | * (data memory barrier) | |
436 | */ | 453 | */ | |
437 | __asm __volatile("dmb sy" ::: "memory"); | 454 | __asm __volatile("dmb sy" ::: "memory"); | |
438 | goto emulated; | 455 | goto emulated; | |
439 | default: | 456 | default: | |
440 | break; | 457 | break; | |
441 | } | 458 | } | |
442 | break; | 459 | break; | |
443 | default: | 460 | default: | |
444 | return EMUL_ARM_FAULT; | 461 | return EMUL_ARM_FAULT; | |
445 | } | 462 | } | |
446 | 463 | |||
447 | /* unknown, or unsupported instruction */ | 464 | /* unknown, or unsupported instruction */ | |
448 | return EMUL_ARM_UNKNOWN; | 465 | return EMUL_ARM_UNKNOWN; | |
449 | 466 | |||
450 | emulated: | 467 | emulated: | |
451 | tf->tf_pc += insn_size; | 468 | tf->tf_pc += insn_size; | |
452 | return EMUL_ARM_SUCCESS; | 469 | return EMUL_ARM_SUCCESS; | |
453 | } | 470 | } | |
454 | #endif /* COMPAT_NETBSD32 */ | 471 | #endif /* COMPAT_NETBSD32 */ | |
455 | 472 | |||
456 | void | 473 | void | |
457 | trap_el0_32sync(struct trapframe *tf) | 474 | trap_el0_32sync(struct trapframe *tf) | |
458 | { | 475 | { | |
459 | struct lwp * const l = curlwp; | 476 | struct lwp * const l = curlwp; | |
460 | const uint32_t esr = tf->tf_esr; | 477 | const uint32_t esr = tf->tf_esr; | |
461 | const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */ | 478 | const uint32_t eclass = __SHIFTOUT(esr, ESR_EC); /* exception class */ | |
462 | 479 | |||
463 | /* disable trace */ | 480 | /* disable trace */ | |
464 | reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS); | 481 | reg_mdscr_el1_write(reg_mdscr_el1_read() & ~MDSCR_SS); | |
465 | /* enable traps and interrupts */ | 482 | /* enable traps and interrupts */ | |
466 | daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F); | 483 | daif_enable(DAIF_D|DAIF_A|DAIF_I|DAIF_F); | |
467 | 484 | |||
468 | switch (eclass) { | 485 | switch (eclass) { | |
469 | #ifdef COMPAT_NETBSD32 | 486 | #ifdef COMPAT_NETBSD32 | |
470 | case ESR_EC_INSN_ABT_EL0: | 487 | case ESR_EC_INSN_ABT_EL0: | |
471 | case ESR_EC_DATA_ABT_EL0: | 488 | case ESR_EC_DATA_ABT_EL0: | |
472 | data_abort_handler(tf, eclass); | 489 | data_abort_handler(tf, eclass); | |
473 | userret(l); | 490 | userret(l); | |
474 | break; | 491 | break; | |
475 | 492 | |||
476 | case ESR_EC_SVC_A32: | 493 | case ESR_EC_SVC_A32: | |
477 | (*l->l_proc->p_md.md_syscall)(tf); | 494 | (*l->l_proc->p_md.md_syscall)(tf); | |
478 | break; | 495 | break; | |
479 | case ESR_EC_FP_ACCESS: | 496 | case ESR_EC_FP_ACCESS: | |
480 | fpu_load(l); | 497 | fpu_load(l); | |
481 | userret(l); | 498 | userret(l); | |
482 | break; | 499 | break; | |
483 | case ESR_EC_FP_TRAP_A32: | 500 | case ESR_EC_FP_TRAP_A32: | |
484 | do_trapsignal(l, SIGFPE, FPE_FLTUND, NULL, esr); /* XXX */ | 501 | do_trapsignal(l, SIGFPE, FPE_FLTUND, NULL, esr); /* XXX */ | |
485 | userret(l); | 502 | userret(l); | |
486 | break; | 503 | break; | |
487 | 504 | |||
488 | case ESR_EC_PC_ALIGNMENT: | 505 | case ESR_EC_PC_ALIGNMENT: | |
489 | do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_pc, esr); | 506 | do_trapsignal(l, SIGBUS, BUS_ADRALN, (void *)tf->tf_pc, esr); | |
490 | userret(l); | 507 | userret(l); | |
491 | break; | 508 | break; | |
492 | case ESR_EC_SP_ALIGNMENT: | 509 | case ESR_EC_SP_ALIGNMENT: | |
493 | do_trapsignal(l, SIGBUS, BUS_ADRALN, | 510 | do_trapsignal(l, SIGBUS, BUS_ADRALN, | |
494 | (void *)tf->tf_reg[13], esr); /* sp is r13 on AArch32 */ | 511 | (void *)tf->tf_reg[13], esr); /* sp is r13 on AArch32 */ | |
495 | userret(l); | 512 | userret(l); | |
496 | break; | 513 | break; | |
497 | 514 | |||
498 | case ESR_EC_BKPT_INSN_A32: | 515 | case ESR_EC_BKPT_INSN_A32: | |
499 | do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr); | 516 | do_trapsignal(l, SIGTRAP, TRAP_BRKPT, (void *)tf->tf_pc, esr); | |
500 | userret(l); | 517 | userret(l); | |
501 | break; | 518 | break; | |
502 | 519 | |||
503 | case ESR_EC_UNKNOWN: | 520 | case ESR_EC_UNKNOWN: | |
504 | switch (emul_arm_insn(tf)) { | 521 | switch (emul_arm_insn(tf)) { | |
505 | case EMUL_ARM_SUCCESS: | 522 | case EMUL_ARM_SUCCESS: | |
506 | break; | 523 | break; | |
507 | case EMUL_ARM_UNKNOWN: | 524 | case EMUL_ARM_UNKNOWN: | |
508 | goto unknown; | 525 | goto unknown; | |
509 | case EMUL_ARM_FAULT: | 526 | case EMUL_ARM_FAULT: | |
510 | do_trapsignal(l, SIGSEGV, SEGV_MAPERR, | 527 | do_trapsignal(l, SIGSEGV, SEGV_MAPERR, | |
511 | (void *)tf->tf_pc, esr); | 528 | (void *)tf->tf_pc, esr); | |
512 | break; | 529 | break; | |
513 | } | 530 | } | |
514 | userret(l); | 531 | userret(l); | |
515 | break; | 532 | break; | |
516 | 533 | |||
517 | case ESR_EC_CP15_RT: | 534 | case ESR_EC_CP15_RT: | |
518 | case ESR_EC_CP15_RRT: | 535 | case ESR_EC_CP15_RRT: | |
519 | case ESR_EC_CP14_RT: | 536 | case ESR_EC_CP14_RT: | |
520 | case ESR_EC_CP14_DT: | 537 | case ESR_EC_CP14_DT: | |
521 | case ESR_EC_CP14_RRT: | 538 | case ESR_EC_CP14_RRT: | |
522 | unknown: | 539 | unknown: | |
523 | #endif /* COMPAT_NETBSD32 */ | 540 | #endif /* COMPAT_NETBSD32 */ | |
524 | default: | 541 | default: | |
525 | #ifdef DDB | 542 | #ifdef DDB | |
526 | if (sigill_debug) { | 543 | if (sigill_debug) { | |
527 | /* show illegal instruction */ | 544 | /* show illegal instruction */ | |
528 | printf("TRAP: pid %d (%s), uid %d: %s:" | 545 | printf("TRAP: pid %d (%s), uid %d: %s:" | |
529 | " esr=0x%lx: pc=0x%lx: %s\n", | 546 | " esr=0x%lx: pc=0x%lx: %s\n", | |
530 | curlwp->l_proc->p_pid, curlwp->l_proc->p_comm, | 547 | curlwp->l_proc->p_pid, curlwp->l_proc->p_comm, | |
531 | l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1, | 548 | l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1, | |
532 | eclass_trapname(eclass), tf->tf_esr, tf->tf_pc, | 549 | eclass_trapname(eclass), tf->tf_esr, tf->tf_pc, | |
533 | strdisasm_aarch32(tf->tf_pc)); | 550 | strdisasm_aarch32(tf->tf_pc)); | |
534 | } | 551 | } | |
535 | #endif | 552 | #endif | |
536 | /* illegal or not implemented instruction */ | 553 | /* illegal or not implemented instruction */ | |
537 | do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr); | 554 | do_trapsignal(l, SIGILL, ILL_ILLTRP, (void *)tf->tf_pc, esr); | |
538 | userret(l); | 555 | userret(l); | |
539 | break; | 556 | break; | |
540 | } | 557 | } | |
541 | } | 558 | } | |
542 | 559 | |||
543 | #define bad_trap_panic(trapfunc) \ | 560 | #define bad_trap_panic(trapfunc) \ | |
544 | void \ | 561 | void \ | |
545 | trapfunc(struct trapframe *tf) \ | 562 | trapfunc(struct trapframe *tf) \ | |
546 | { \ | 563 | { \ | |
547 | panic("%s", __func__); \ | 564 | panic("%s", __func__); \ | |
548 | } | 565 | } | |
549 | bad_trap_panic(trap_el1t_sync) | 566 | bad_trap_panic(trap_el1t_sync) | |
550 | bad_trap_panic(trap_el1t_irq) | 567 | bad_trap_panic(trap_el1t_irq) | |
551 | bad_trap_panic(trap_el1t_fiq) | 568 | bad_trap_panic(trap_el1t_fiq) | |
552 | bad_trap_panic(trap_el1t_error) | 569 | bad_trap_panic(trap_el1t_error) | |
553 | bad_trap_panic(trap_el1h_fiq) | 570 | bad_trap_panic(trap_el1h_fiq) | |
554 | bad_trap_panic(trap_el1h_error) | 571 | bad_trap_panic(trap_el1h_error) | |
555 | bad_trap_panic(trap_el0_fiq) | 572 | bad_trap_panic(trap_el0_fiq) | |
556 | bad_trap_panic(trap_el0_error) | 573 | bad_trap_panic(trap_el0_error) | |
557 | bad_trap_panic(trap_el0_32fiq) | 574 | bad_trap_panic(trap_el0_32fiq) | |
558 | bad_trap_panic(trap_el0_32error) | 575 | bad_trap_panic(trap_el0_32error) | |
559 | 576 | |||
560 | void | 577 | void | |
561 | cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb, int val) | 578 | cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb, int val) | |
562 | { | 579 | { | |
563 | tf->tf_reg[19] = fb->fb_reg[FB_X19]; | 580 | tf->tf_reg[19] = fb->fb_reg[FB_X19]; | |
564 | tf->tf_reg[20] = fb->fb_reg[FB_X20]; | 581 | tf->tf_reg[20] = fb->fb_reg[FB_X20]; | |
565 | tf->tf_reg[21] = fb->fb_reg[FB_X21]; | 582 | tf->tf_reg[21] = fb->fb_reg[FB_X21]; | |
566 | tf->tf_reg[22] = fb->fb_reg[FB_X22]; | 583 | tf->tf_reg[22] = fb->fb_reg[FB_X22]; | |
567 | tf->tf_reg[23] = fb->fb_reg[FB_X23]; | 584 | tf->tf_reg[23] = fb->fb_reg[FB_X23]; | |
568 | tf->tf_reg[24] = fb->fb_reg[FB_X24]; | 585 | tf->tf_reg[24] = fb->fb_reg[FB_X24]; | |
569 | tf->tf_reg[25] = fb->fb_reg[FB_X25]; | 586 | tf->tf_reg[25] = fb->fb_reg[FB_X25]; | |
570 | tf->tf_reg[26] = fb->fb_reg[FB_X26]; | 587 | tf->tf_reg[26] = fb->fb_reg[FB_X26]; | |
571 | tf->tf_reg[27] = fb->fb_reg[FB_X27]; | 588 | tf->tf_reg[27] = fb->fb_reg[FB_X27]; | |
572 | tf->tf_reg[28] = fb->fb_reg[FB_X28]; | 589 | tf->tf_reg[28] = fb->fb_reg[FB_X28]; | |
573 | tf->tf_reg[29] = fb->fb_reg[FB_X29]; | 590 | tf->tf_reg[29] = fb->fb_reg[FB_X29]; | |
574 | tf->tf_sp = fb->fb_reg[FB_SP]; | 591 | tf->tf_sp = fb->fb_reg[FB_SP]; | |
575 | tf->tf_pc = fb->fb_reg[FB_LR]; | 592 | tf->tf_pc = fb->fb_reg[FB_LR]; | |
576 | tf->tf_reg[0] = val; | 593 | tf->tf_reg[0] = val; | |
577 | } | 594 | } | |
578 | 595 | |||
579 | #ifdef TRAP_SIGDEBUG | 596 | #ifdef TRAP_SIGDEBUG | |
580 | static void | 597 | static void | |
581 | frame_dump(const struct trapframe *tf) | 598 | frame_dump(const struct trapframe *tf) | |
582 | { | 599 | { | |
583 | const struct reg *r = &tf->tf_regs; | 600 | const struct reg *r = &tf->tf_regs; | |
584 | 601 | |||
585 | printf("trapframe %p\n", tf); | 602 | printf("trapframe %p\n", tf); | |
586 | for (size_t i = 0; i < __arraycount(r->r_reg); i++) { | 603 | for (size_t i = 0; i < __arraycount(r->r_reg); i++) { | |
587 | printf(" r%.2zu %#018" PRIx64 "%c", i, r->r_reg[i], | 604 | printf(" r%.2zu %#018" PRIx64 "%c", i, r->r_reg[i], | |
588 | " \n"[i && (i & 1) == 0]); | 605 | " \n"[i && (i & 1) == 0]); | |
589 | } | 606 | } | |
590 | 607 | |||
591 | printf("\n"); | 608 | printf("\n"); | |
592 | printf(" sp %#018" PRIx64 " pc %#018" PRIx64 "\n", | 609 | printf(" sp %#018" PRIx64 " pc %#018" PRIx64 "\n", | |
593 | r->r_sp, r->r_pc); | 610 | r->r_sp, r->r_pc); | |
594 | printf(" spsr %#018" PRIx64 " tpidr %#018" PRIx64 "\n", | 611 | printf(" spsr %#018" PRIx64 " tpidr %#018" PRIx64 "\n", | |
595 | r->r_spsr, r->r_tpidr); | 612 | r->r_spsr, r->r_tpidr); | |
596 | printf(" esr %#018" PRIx64 " far %#018" PRIx64 "\n", | 613 | printf(" esr %#018" PRIx64 " far %#018" PRIx64 "\n", | |
597 | tf->tf_esr, tf->tf_far); | 614 | tf->tf_esr, tf->tf_far); | |
598 | 615 | |||
599 | printf("\n"); | 616 | printf("\n"); | |
600 | hexdump(printf, "Stack dump", tf, 256); | 617 | hexdump(printf, "Stack dump", tf, 256); | |
601 | } | 618 | } | |
602 | 619 | |||
603 | static void | 620 | static void | |
604 | sigdebug(const struct trapframe *tf, const ksiginfo_t *ksi) | 621 | sigdebug(const struct trapframe *tf, const ksiginfo_t *ksi) | |
605 | { | 622 | { | |
606 | struct lwp *l = curlwp; | 623 | struct lwp *l = curlwp; | |
607 | struct proc *p = l->l_proc; | 624 | struct proc *p = l->l_proc; | |
608 | const uint32_t eclass = __SHIFTOUT(ksi->ksi_trap, ESR_EC); | 625 | const uint32_t eclass = __SHIFTOUT(ksi->ksi_trap, ESR_EC); | |
609 | 626 | |||
610 | printf("pid %d.%d (%s): signal %d (trap %#x) " | 627 | printf("pid %d.%d (%s): signal %d (trap %#x) " | |
611 | "@pc %#" PRIx64 ", addr %p, error=%s\n", | 628 | "@pc %#" PRIx64 ", addr %p, error=%s\n", | |
612 | p->p_pid, l->l_lid, p->p_comm, ksi->ksi_signo, ksi->ksi_trap, | 629 | p->p_pid, l->l_lid, p->p_comm, ksi->ksi_signo, ksi->ksi_trap, | |
613 | tf->tf_regs.r_pc, ksi->ksi_addr, eclass_trapname(eclass)); | 630 | tf->tf_regs.r_pc, ksi->ksi_addr, eclass_trapname(eclass)); | |
614 | frame_dump(tf); | 631 | frame_dump(tf); | |
615 | } | 632 | } | |
616 | #endif | 633 | #endif | |
617 | 634 | |||
618 | void do_trapsignal1( | 635 | void do_trapsignal1( | |
619 | #ifdef TRAP_SIGDEBUG | 636 | #ifdef TRAP_SIGDEBUG | |
620 | const char *func, | 637 | const char *func, | |
621 | size_t line, | 638 | size_t line, | |
622 | struct trapframe *tf, | 639 | struct trapframe *tf, | |
623 | #endif | 640 | #endif | |
624 | struct lwp *l, int signo, int code, void *addr, int trap) | 641 | struct lwp *l, int signo, int code, void *addr, int trap) | |
625 | { | 642 | { | |
626 | ksiginfo_t ksi; | 643 | ksiginfo_t ksi; | |
627 | 644 | |||
628 | KSI_INIT_TRAP(&ksi); | 645 | KSI_INIT_TRAP(&ksi); | |
629 | ksi.ksi_signo = signo; | 646 | ksi.ksi_signo = signo; | |
630 | ksi.ksi_code = code; | 647 | ksi.ksi_code = code; | |
631 | ksi.ksi_addr = addr; | 648 | ksi.ksi_addr = addr; | |
632 | ksi.ksi_trap = trap; | 649 | ksi.ksi_trap = trap; | |
633 | #ifdef TRAP_SIGDEBUG | 650 | #ifdef TRAP_SIGDEBUG | |
634 | printf("%s, %zu: ", func, line); | 651 | printf("%s, %zu: ", func, line); | |
635 | sigdebug(tf, &ksi); | 652 | sigdebug(tf, &ksi); | |
636 | #endif | 653 | #endif | |
637 | (*l->l_proc->p_emul->e_trapsignal)(l, &ksi); | 654 | (*l->l_proc->p_emul->e_trapsignal)(l, &ksi); | |
638 | } | 655 | } |
--- src/sys/arch/aarch64/include/netbsd32_machdep.h 2018/10/12 01:28:58 1.2
+++ src/sys/arch/aarch64/include/netbsd32_machdep.h 2021/01/01 12:58:35 1.2.4.1
@@ -1,110 +1,131 @@ | @@ -1,110 +1,131 @@ | |||
1 | /* $NetBSD: netbsd32_machdep.h,v 1.2 2018/10/12 01:28:58 ryo Exp $ */ | 1 | /* $NetBSD: netbsd32_machdep.h,v 1.2.4.1 2021/01/01 12:58:35 martin Exp $ */ | |
2 | 2 | |||
3 | #ifndef _MACHINE_NETBSD32_H_ | 3 | #ifndef _MACHINE_NETBSD32_H_ | |
4 | #define _MACHINE_NETBSD32_H_ | 4 | #define _MACHINE_NETBSD32_H_ | |
5 | 5 | |||
6 | #include <sys/ucontext.h> | 6 | #include <sys/ucontext.h> | |
7 | #include <compat/sys/ucontext.h> | 7 | #include <compat/sys/ucontext.h> | |
8 | #include <compat/sys/siginfo.h> | 8 | #include <compat/sys/siginfo.h> | |
9 | 9 | |||
10 | /* | |||
11 | * arm ptrace constants | |||
12 | * Please keep in sync with sys/arch/arm/include/ptrace.h. | |||
13 | */ | |||
14 | #define PT32_STEP (PT_FIRSTMACH + 0) /* Not implemented */ | |||
15 | #define PT32_GETREGS (PT_FIRSTMACH + 1) | |||
16 | #define PT32_SETREGS (PT_FIRSTMACH + 2) | |||
17 | #define PT32_GETFPREGS (PT_FIRSTMACH + 5) | |||
18 | #define PT32_SETFPREGS (PT_FIRSTMACH + 6) | |||
19 | #define PT32_SETSTEP (PT_FIRSTMACH + 7) /* Not implemented */ | |||
20 | #define PT32_CLEARSTEP (PT_FIRSTMACH + 8) /* Not implemented */ | |||
21 | ||||
10 | #define NETBSD32_POINTER_TYPE uint32_t | 22 | #define NETBSD32_POINTER_TYPE uint32_t | |
11 | typedef struct { NETBSD32_POINTER_TYPE i32; } netbsd32_pointer_t; | 23 | typedef struct { NETBSD32_POINTER_TYPE i32; } netbsd32_pointer_t; | |
12 | 24 | |||
13 | /* earm has 64bit aligned 64bit integers */ | 25 | /* earm has 64bit aligned 64bit integers */ | |
14 | #define NETBSD32_INT64_ALIGN __attribute__((__aligned__(8))) | 26 | #define NETBSD32_INT64_ALIGN __attribute__((__aligned__(8))) | |
15 | 27 | |||
16 | typedef netbsd32_pointer_t netbsd32_sigcontextp_t; | 28 | typedef netbsd32_pointer_t netbsd32_sigcontextp_t; | |
17 | 29 | |||
18 | struct netbsd32_sigcontext13 { | 30 | struct netbsd32_sigcontext13 { | |
19 | int32_t sc_onstack; /* sigstack state to restore */ | 31 | int32_t sc_onstack; /* sigstack state to restore */ | |
20 | int32_t __sc_mask13; /* signal mask to restore (old style) */ | 32 | int32_t __sc_mask13; /* signal mask to restore (old style) */ | |
21 | 33 | |||
22 | uint32_t sc_spsr; | 34 | uint32_t sc_spsr; | |
23 | uint32_t sc_r0; | 35 | uint32_t sc_r0; | |
24 | uint32_t sc_r1; | 36 | uint32_t sc_r1; | |
25 | uint32_t sc_r2; | 37 | uint32_t sc_r2; | |
26 | uint32_t sc_r3; | 38 | uint32_t sc_r3; | |
27 | uint32_t sc_r4; | 39 | uint32_t sc_r4; | |
28 | uint32_t sc_r5; | 40 | uint32_t sc_r5; | |
29 | uint32_t sc_r6; | 41 | uint32_t sc_r6; | |
30 | uint32_t sc_r7; | 42 | uint32_t sc_r7; | |
31 | uint32_t sc_r8; | 43 | uint32_t sc_r8; | |
32 | uint32_t sc_r9; | 44 | uint32_t sc_r9; | |
33 | uint32_t sc_r10; | 45 | uint32_t sc_r10; | |
34 | uint32_t sc_r11; | 46 | uint32_t sc_r11; | |
35 | uint32_t sc_r12; | 47 | uint32_t sc_r12; | |
36 | uint32_t sc_usr_sp; | 48 | uint32_t sc_usr_sp; | |
37 | uint32_t sc_usr_lr; | 49 | uint32_t sc_usr_lr; | |
38 | uint32_t sc_svc_lr; | 50 | uint32_t sc_svc_lr; | |
39 | uint32_t sc_pc; | 51 | uint32_t sc_pc; | |
40 | }; | 52 | }; | |
41 | 53 | |||
42 | struct netbsd32_sigcontext { | 54 | struct netbsd32_sigcontext { | |
43 | int32_t sc_onstack; /* sigstack state to restore */ | 55 | int32_t sc_onstack; /* sigstack state to restore */ | |
44 | int32_t __sc_mask13; /* signal mask to restore (old style) */ | 56 | int32_t __sc_mask13; /* signal mask to restore (old style) */ | |
45 | 57 | |||
46 | uint32_t sc_spsr; | 58 | uint32_t sc_spsr; | |
47 | uint32_t sc_r0; | 59 | uint32_t sc_r0; | |
48 | uint32_t sc_r1; | 60 | uint32_t sc_r1; | |
49 | uint32_t sc_r2; | 61 | uint32_t sc_r2; | |
50 | uint32_t sc_r3; | 62 | uint32_t sc_r3; | |
51 | uint32_t sc_r4; | 63 | uint32_t sc_r4; | |
52 | uint32_t sc_r5; | 64 | uint32_t sc_r5; | |
53 | uint32_t sc_r6; | 65 | uint32_t sc_r6; | |
54 | uint32_t sc_r7; | 66 | uint32_t sc_r7; | |
55 | uint32_t sc_r8; | 67 | uint32_t sc_r8; | |
56 | uint32_t sc_r9; | 68 | uint32_t sc_r9; | |
57 | uint32_t sc_r10; | 69 | uint32_t sc_r10; | |
58 | uint32_t sc_r11; | 70 | uint32_t sc_r11; | |
59 | uint32_t sc_r12; | 71 | uint32_t sc_r12; | |
60 | uint32_t sc_usr_sp; | 72 | uint32_t sc_usr_sp; | |
61 | uint32_t sc_usr_lr; | 73 | uint32_t sc_usr_lr; | |
62 | uint32_t sc_svc_lr; | 74 | uint32_t sc_svc_lr; | |
63 | uint32_t sc_pc; | 75 | uint32_t sc_pc; | |
64 | 76 | |||
65 | sigset_t sc_mask; /* signal mask to restore (new style) */ | 77 | sigset_t sc_mask; /* signal mask to restore (new style) */ | |
66 | }; | 78 | }; | |
67 | 79 | |||
68 | struct netbsd32_sigframe_siginfo { | 80 | struct netbsd32_sigframe_siginfo { | |
69 | siginfo32_t sf_si; | 81 | siginfo32_t sf_si; | |
70 | ucontext32_t sf_uc; | 82 | ucontext32_t sf_uc; | |
71 | }; | 83 | }; | |
72 | 84 | |||
73 | struct reg32 { | 85 | struct reg32 { | |
74 | uint32_t r[13]; | 86 | uint32_t r[13]; | |
75 | uint32_t r_sp; | 87 | uint32_t r_sp; | |
76 | uint32_t r_lr; | 88 | uint32_t r_lr; | |
77 | uint32_t r_pc; | 89 | uint32_t r_pc; | |
78 | uint32_t r_cpsr; | 90 | uint32_t r_cpsr; | |
79 | }; | 91 | }; | |
80 | 92 | |||
81 | struct vfpreg32 { | 93 | struct vfpreg32 { | |
82 | uint32_t vfp_fpexc; | 94 | uint32_t vfp_fpexc; | |
83 | uint32_t vfp_fpscr; | 95 | uint32_t vfp_fpscr; | |
84 | uint32_t vfp_fpinst; | 96 | uint32_t vfp_fpinst; | |
85 | uint32_t vfp_fpinst2; | 97 | uint32_t vfp_fpinst2; | |
86 | uint64_t vfp_regs[33]; /* In case we need fstmx format. */ | 98 | uint64_t vfp_regs[33]; /* In case we need fstmx format. */ | |
87 | }; | 99 | }; | |
88 | 100 | |||
89 | struct fpreg32 { | 101 | struct fpreg32 { | |
90 | struct vfpreg32 fpr_vfp; | 102 | struct vfpreg32 fpr_vfp; | |
91 | }; | 103 | }; | |
92 | 104 | |||
93 | /* same as cpustate in arm/arm/core_machdep.c */ | 105 | /* same as cpustate in arm/arm/core_machdep.c */ | |
94 | struct netbsd32_cpustate { | 106 | struct netbsd32_cpustate { | |
95 | struct reg32 regs; | 107 | struct reg32 regs; | |
96 | struct fpreg32 fpregs; | 108 | struct fpreg32 fpregs; | |
97 | }; | 109 | }; | |
98 | 110 | |||
99 | /* compat netbsd/arm sysarch(2) */ | 111 | /* compat netbsd/arm sysarch(2) */ | |
100 | #define ARM_SYNC_ICACHE 0 | 112 | #define ARM_SYNC_ICACHE 0 | |
101 | #define ARM_DRAIN_WRITEBUF 1 | 113 | #define ARM_DRAIN_WRITEBUF 1 | |
102 | #define ARM_VFP_FPSCR 2 | 114 | #define ARM_VFP_FPSCR 2 | |
103 | #define ARM_FPU_USED 3 | 115 | #define ARM_FPU_USED 3 | |
104 | 116 | |||
105 | struct netbsd32_arm_sync_icache_args { | 117 | struct netbsd32_arm_sync_icache_args { | |
106 | netbsd32_uintptr_t addr; /* Virtual start address */ | 118 | uint32_t addr; /* Virtual start address */ | |
107 | netbsd32_size_t len; /* Region size */ | 119 | uint32_t len; /* Region size */ | |
108 | }; | 120 | }; | |
109 | 121 | |||
122 | /* Translate ptrace() PT_* request from 32-bit userland to kernel. */ | |||
123 | int netbsd32_ptrace_translate_request(int); | |||
124 | ||||
125 | int netbsd32_process_read_regs(struct lwp *, struct reg32 *); | |||
126 | int netbsd32_process_read_fpregs(struct lwp *, struct fpreg32 *, size_t *); | |||
127 | ||||
128 | int netbsd32_process_write_regs(struct lwp *, const struct reg32 *); | |||
129 | int netbsd32_process_write_fpregs(struct lwp *, const struct fpreg32 *, size_t); | |||
130 | ||||
110 | #endif /* _MACHINE_NETBSD32_H_ */ | 131 | #endif /* _MACHINE_NETBSD32_H_ */ |
--- src/sys/arch/aarch64/include/ptrace.h 2019/06/18 21:18:11 1.9
+++ src/sys/arch/aarch64/include/ptrace.h 2021/01/01 12:58:35 1.9.2.1
@@ -1,75 +1,94 @@ | @@ -1,75 +1,94 @@ | |||
1 | /* $NetBSD: ptrace.h,v 1.9 2019/06/18 21:18:11 kamil Exp $ */ | 1 | /* $NetBSD: ptrace.h,v 1.9.2.1 2021/01/01 12:58:35 martin Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Matt Thomas of 3am Software Foundry. | 8 | * by Matt Thomas of 3am Software Foundry. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
15 | * 2. Redistributions in binary form must reproduce the above copyright | 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
16 | * notice, this list of conditions and the following disclaimer in the | 16 | * notice, this list of conditions and the following disclaimer in the | |
17 | * documentation and/or other materials provided with the distribution. | 17 | * documentation and/or other materials provided with the distribution. | |
18 | * | 18 | * | |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #ifndef _AARCH64_PTRACE_H_ | 32 | #ifndef _AARCH64_PTRACE_H_ | |
33 | #define _AARCH64_PTRACE_H_ | 33 | #define _AARCH64_PTRACE_H_ | |
34 | 34 | |||
35 | #ifdef __aarch64__ | 35 | #ifdef __aarch64__ | |
36 | 36 | |||
37 | /* | 37 | /* | |
38 | * AARCH64-dependent ptrace definitions. | 38 | * AARCH64-dependent ptrace definitions. | |
39 | */ | 39 | */ | |
40 | #define PT_GETREGS (PT_FIRSTMACH + 0) | 40 | #define PT_GETREGS (PT_FIRSTMACH + 0) | |
41 | #define PT_SETREGS (PT_FIRSTMACH + 1) | 41 | #define PT_SETREGS (PT_FIRSTMACH + 1) | |
42 | #define PT_GETFPREGS (PT_FIRSTMACH + 2) | 42 | #define PT_GETFPREGS (PT_FIRSTMACH + 2) | |
43 | #define PT_SETFPREGS (PT_FIRSTMACH + 3) | 43 | #define PT_SETFPREGS (PT_FIRSTMACH + 3) | |
44 | #define PT_STEP (PT_FIRSTMACH + 4) | 44 | #define PT_STEP (PT_FIRSTMACH + 4) | |
45 | #define PT_SETSTEP (PT_FIRSTMACH + 5) | 45 | #define PT_SETSTEP (PT_FIRSTMACH + 5) | |
46 | #define PT_CLEARSTEP (PT_FIRSTMACH + 6) | 46 | #define PT_CLEARSTEP (PT_FIRSTMACH + 6) | |
47 | 47 | |||
48 | #define PT_MACHDEP_STRINGS \ | 48 | #define PT_MACHDEP_STRINGS \ | |
49 | "PT_GETREGS", \ | 49 | "PT_GETREGS", \ | |
50 | "PT_SETREGS", \ | 50 | "PT_SETREGS", \ | |
51 | "PT_GETFPREGS", \ | 51 | "PT_GETFPREGS", \ | |
52 | "PT_SETFPREGS", \ | 52 | "PT_SETFPREGS", \ | |
53 | "PT_STEP", \ | 53 | "PT_STEP", \ | |
54 | "PT_SETSTEP", \ | 54 | "PT_SETSTEP", \ | |
55 | "PT_CLEARSTEP", | 55 | "PT_CLEARSTEP", | |
56 | 56 | |||
57 | 57 | |||
58 | #include <machine/reg.h> | 58 | #include <machine/reg.h> | |
59 | #define PTRACE_REG_PC(r) (r)->r_pc | 59 | #define PTRACE_REG_PC(r) (r)->r_pc | |
60 | #define PTRACE_REG_FP(r) (r)->r_reg[29] | 60 | #define PTRACE_REG_FP(r) (r)->r_reg[29] | |
61 | #define PTRACE_REG_SET_PC(r, v) (r)->r_pc = (v) | 61 | #define PTRACE_REG_SET_PC(r, v) (r)->r_pc = (v) | |
62 | #define PTRACE_REG_SP(r) (r)->r_sp | 62 | #define PTRACE_REG_SP(r) (r)->r_sp | |
63 | #define PTRACE_REG_INTRV(r) (r)->r_reg[0] | 63 | #define PTRACE_REG_INTRV(r) (r)->r_reg[0] | |
64 | 64 | |||
65 | #define PTRACE_BREAKPOINT ((const uint8_t[]) { 0xa0, 0x01, 0x20, 0xd4 }) | 65 | #define PTRACE_BREAKPOINT ((const uint8_t[]) { 0xa0, 0x01, 0x20, 0xd4 }) | |
66 | #define PTRACE_BREAKPOINT_ASM __asm __volatile("brk #13" ::: "memory") | 66 | #define PTRACE_BREAKPOINT_ASM __asm __volatile("brk #13" ::: "memory") | |
67 | #define PTRACE_BREAKPOINT_SIZE 4 | 67 | #define PTRACE_BREAKPOINT_SIZE 4 | |
68 | 68 | |||
69 | #ifdef _KERNEL_OPT | |||
70 | #include "opt_compat_netbsd32.h" | |||
71 | #endif | |||
72 | ||||
73 | #ifdef COMPAT_NETBSD32 | |||
74 | #include <machine/netbsd32_machdep.h> | |||
75 | ||||
76 | #define process_read_regs32 netbsd32_process_read_regs | |||
77 | #define process_read_fpregs32 netbsd32_process_read_fpregs | |||
78 | ||||
79 | #define process_write_regs32 netbsd32_process_write_regs | |||
80 | #define process_write_fpregs32 netbsd32_process_write_fpregs | |||
81 | ||||
82 | #define process_reg32 struct reg32 | |||
83 | #define process_fpreg32 struct fpreg32 | |||
84 | ||||
85 | #define PTRACE_TRANSLATE_REQUEST32(x) netbsd32_ptrace_translate_request(x) | |||
86 | #endif /* COMPAT_NETBSD32 */ | |||
87 | ||||
69 | #elif defined(__arm__) | 88 | #elif defined(__arm__) | |
70 | 89 | |||
71 | #include <arm/ptrace.h> | 90 | #include <arm/ptrace.h> | |
72 | 91 | |||
73 | #endif | 92 | #endif | |
74 | 93 | |||
75 | #endif /* _AARCH64_PTRACE_H_ */ | 94 | #endif /* _AARCH64_PTRACE_H_ */ |