2 * Copyright (c) 2014, 2015 The FreeBSD Foundation.
3 * Copyright (c) 2014, 2017 Andrew Turner.
4 * Copyright (c) 2018 Olivier Houchard
7 * This software was developed by Andrew Turner under
8 * sponsorship from the FreeBSD Foundation.
10 * Portions of this software were developed by Konstantin Belousov
11 * under sponsorship from the FreeBSD Foundation.
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
36 #define __ELF_WORD_SIZE 32
38 #include <sys/param.h>
39 #include <sys/kernel.h>
40 #include <sys/systm.h>
42 #include <sys/imgact.h>
43 #include <sys/linker.h>
46 #include <sys/sysctl.h>
47 #include <sys/sysent.h>
48 #include <sys/imgact_elf.h>
49 #include <sys/syscall.h>
50 #include <sys/signalvar.h>
51 #include <sys/vnode.h>
53 #include <machine/elf.h>
54 #include <machine/pcb.h>
56 #include <machine/vfp.h>
59 #include <compat/freebsd32/freebsd32_util.h>
61 #define FREEBSD32_MINUSER 0x00001000
62 #define FREEBSD32_MAXUSER ((1ul << 32) - PAGE_SIZE)
63 #define FREEBSD32_SHAREDPAGE (FREEBSD32_MAXUSER - PAGE_SIZE)
64 #define FREEBSD32_USRSTACK FREEBSD32_SHAREDPAGE
65 #define AARCH32_MAXDSIZ (512 * 1024 * 1024)
66 #define AARCH32_MAXSSIZ (64 * 1024 * 1024)
67 #define AARCH32_MAXVMEM 0
69 extern const char *freebsd32_syscallnames[];
71 extern char aarch32_sigcode[];
72 extern int sz_aarch32_sigcode;
74 static int freebsd32_fetch_syscall_args(struct thread *td);
75 static void freebsd32_setregs(struct thread *td, struct image_params *imgp,
77 static void freebsd32_set_syscall_retval(struct thread *, int);
79 static bool elf32_arm_abi_supported(struct image_params *, int32_t *,
81 static void elf32_fixlimit(struct rlimit *rl, int which);
83 extern void freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
85 u_long __read_frequently elf32_hwcap;
86 u_long __read_frequently elf32_hwcap2;
88 static SYSCTL_NODE(_compat, OID_AUTO, aarch32, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
91 static u_long aarch32_maxdsiz = AARCH32_MAXDSIZ;
92 SYSCTL_ULONG(_compat_aarch32, OID_AUTO, maxdsiz, CTLFLAG_RWTUN,
93 &aarch32_maxdsiz, 0, "");
94 u_long aarch32_maxssiz = AARCH32_MAXSSIZ;
95 SYSCTL_ULONG(_compat_aarch32, OID_AUTO, maxssiz, CTLFLAG_RWTUN,
96 &aarch32_maxssiz, 0, "");
97 static u_long aarch32_maxvmem = AARCH32_MAXVMEM;
98 SYSCTL_ULONG(_compat_aarch32, OID_AUTO, maxvmem, CTLFLAG_RWTUN,
99 &aarch32_maxvmem, 0, "");
101 static struct sysentvec elf32_freebsd_sysvec = {
102 .sv_size = SYS_MAXSYSCALL,
103 .sv_table = freebsd32_sysent,
104 .sv_fixup = elf32_freebsd_fixup,
105 .sv_sendsig = freebsd32_sendsig,
106 .sv_sigcode = aarch32_sigcode,
107 .sv_szsigcode = &sz_aarch32_sigcode,
108 .sv_name = "FreeBSD ELF32",
109 .sv_coredump = elf32_coredump,
110 .sv_elf_core_osabi = ELFOSABI_FREEBSD,
111 .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR,
112 .sv_elf_core_prepare_notes = elf32_prepare_notes,
113 .sv_minsigstksz = MINSIGSTKSZ,
114 .sv_minuser = FREEBSD32_MINUSER,
115 .sv_maxuser = FREEBSD32_MAXUSER,
116 .sv_usrstack = FREEBSD32_USRSTACK,
117 .sv_psstrings = FREEBSD32_PS_STRINGS,
118 .sv_psstringssz = sizeof(struct freebsd32_ps_strings),
119 .sv_stackprot = VM_PROT_READ | VM_PROT_WRITE,
120 .sv_copyout_auxargs = elf32_freebsd_copyout_auxargs,
121 .sv_copyout_strings = freebsd32_copyout_strings,
122 .sv_setregs = freebsd32_setregs,
123 .sv_fixlimit = elf32_fixlimit,
124 .sv_maxssiz = &aarch32_maxssiz,
125 .sv_flags = SV_ABI_FREEBSD | SV_ILP32 | SV_SHP | SV_TIMEKEEP |
126 SV_RNG_SEED_VER | SV_SIGSYS,
127 .sv_set_syscall_retval = freebsd32_set_syscall_retval,
128 .sv_fetch_syscall_args = freebsd32_fetch_syscall_args,
129 .sv_syscallnames = freebsd32_syscallnames,
130 .sv_shared_page_base = FREEBSD32_SHAREDPAGE,
131 .sv_shared_page_len = PAGE_SIZE,
132 .sv_schedtail = NULL,
133 .sv_thread_detach = NULL,
135 .sv_hwcap = &elf32_hwcap,
136 .sv_hwcap2 = &elf32_hwcap2,
137 .sv_onexec_old = exec_onexec_old,
138 .sv_onexit = exit_onexit,
139 .sv_regset_begin = SET_BEGIN(__elfN(regset)),
140 .sv_regset_end = SET_LIMIT(__elfN(regset)),
142 INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
144 static Elf32_Brandinfo freebsd32_brand_info = {
145 .brand = ELFOSABI_FREEBSD,
147 .compat_3_brand = "FreeBSD",
148 .interp_path = "/libexec/ld-elf.so.1",
149 .sysvec = &elf32_freebsd_sysvec,
150 .interp_newpath = "/libexec/ld-elf32.so.1",
151 .brand_note = &elf32_freebsd_brandnote,
152 .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE,
153 .header_supported= elf32_arm_abi_supported,
157 register_elf32_brand(void *arg)
159 /* Check if we support AArch32 */
160 if (ID_AA64PFR0_EL0_VAL(READ_SPECIALREG(id_aa64pfr0_el1)) ==
161 ID_AA64PFR0_EL0_64_32) {
162 elf32_insert_brand_entry(&freebsd32_brand_info);
164 compat_freebsd_32bit = 0;
167 SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST, register_elf32_brand, NULL);
170 elf32_arm_abi_supported(struct image_params *imgp, int32_t *osrel __unused,
171 uint32_t *fctl0 __unused)
173 const Elf32_Ehdr *hdr;
175 #define EF_ARM_EABI_FREEBSD_MIN EF_ARM_EABI_VER4
176 hdr = (const Elf32_Ehdr *)imgp->image_header;
177 if (EF_ARM_EABI_VERSION(hdr->e_flags) < EF_ARM_EABI_FREEBSD_MIN) {
179 uprintf("Attempting to execute non EABI binary "
181 EF_ARM_EABI_VERSION(hdr->e_flags),
190 freebsd32_fetch_syscall_args(struct thread *td)
194 struct syscall_args *sa;
195 int error, i, nap, narg;
196 unsigned int args[4];
200 ap = td->td_frame->tf_x;
203 /* r7 is the syscall id */
204 sa->code = td->td_frame->tf_x[7];
205 sa->original_code = sa->code;
207 if (sa->code == SYS_syscall) {
210 } else if (sa->code == SYS___syscall) {
216 if (sa->code >= p->p_sysent->sv_size)
217 sa->callp = &nosys_sysent;
219 sa->callp = &p->p_sysent->sv_table[sa->code];
221 narg = sa->callp->sy_narg;
222 for (i = 0; i < nap; i++)
225 if (narg - nap > nitems(args))
226 panic("Too many system call arguiments");
227 error = copyin((void *)td->td_frame->tf_x[13], args,
228 (narg - nap) * sizeof(int));
231 for (i = 0; i < (narg - nap); i++)
232 sa->args[i + nap] = args[i];
235 td->td_retval[0] = 0;
236 td->td_retval[1] = 0;
242 freebsd32_set_syscall_retval(struct thread *td, int error)
244 struct trapframe *frame;
246 frame = td->td_frame;
249 frame->tf_x[0] = td->td_retval[0];
250 frame->tf_x[1] = td->td_retval[1];
251 frame->tf_spsr &= ~PSR_C;
255 * Reconstruct the pc to point at the swi.
257 if ((frame->tf_spsr & PSR_T) != 0)
258 frame->tf_elr -= 2; //THUMB_INSN_SIZE;
260 frame->tf_elr -= 4; //INSN_SIZE;
266 frame->tf_x[0] = error;
267 frame->tf_spsr |= PSR_C;
273 freebsd32_setregs(struct thread *td, struct image_params *imgp,
276 struct trapframe *tf = td->td_frame;
277 struct pcb *pcb = td->td_pcb;
279 memset(tf, 0, sizeof(struct trapframe));
282 * We need to set x0 for init as it doesn't call
283 * cpu_set_syscall_retval to copy the value. We also
284 * need to set td_retval for the cases where we do.
287 /* SP_usr is mapped to x13 */
288 tf->tf_x[13] = stack;
289 /* LR_usr is mapped to x14 */
290 tf->tf_x[14] = imgp->entry_addr;
291 tf->tf_elr = imgp->entry_addr;
292 tf->tf_spsr = PSR_M_32;
293 if ((uint32_t)imgp->entry_addr & 1)
294 tf->tf_spsr |= PSR_T;
297 vfp_reset_state(td, pcb);
301 * Clear debug register state. It is not applicable to the new process.
303 bzero(&pcb->pcb_dbg_regs, sizeof(pcb->pcb_dbg_regs));
307 elf32_dump_thread(struct thread *td, void *dst, size_t *off)
312 elf32_fixlimit(struct rlimit *rl, int which)
317 if (aarch32_maxdsiz != 0) {
318 if (rl->rlim_cur > aarch32_maxdsiz)
319 rl->rlim_cur = aarch32_maxdsiz;
320 if (rl->rlim_max > aarch32_maxdsiz)
321 rl->rlim_max = aarch32_maxdsiz;
325 if (aarch32_maxssiz != 0) {
326 if (rl->rlim_cur > aarch32_maxssiz)
327 rl->rlim_cur = aarch32_maxssiz;
328 if (rl->rlim_max > aarch32_maxssiz)
329 rl->rlim_max = aarch32_maxssiz;
333 if (aarch32_maxvmem != 0) {
334 if (rl->rlim_cur > aarch32_maxvmem)
335 rl->rlim_cur = aarch32_maxvmem;
336 if (rl->rlim_max > aarch32_maxvmem)
337 rl->rlim_max = aarch32_maxvmem;