The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm64/arm64/elf32_machdep.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2014, 2015 The FreeBSD Foundation.
    3  * Copyright (c) 2014, 2017 Andrew Turner.
    4  * Copyright (c) 2018 Olivier Houchard
    5  * All rights reserved.
    6  *
    7  * This software was developed by Andrew Turner under
    8  * sponsorship from the FreeBSD Foundation.
    9  *
   10  * Portions of this software were developed by Konstantin Belousov
   11  * under sponsorship from the FreeBSD Foundation.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   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.
   21  *
   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
   32  * SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD$");
   37 
   38 #define __ELF_WORD_SIZE 32
   39 
   40 #include <sys/param.h>
   41 #include <sys/kernel.h>
   42 #include <sys/systm.h>
   43 #include <sys/exec.h>
   44 #include <sys/imgact.h>
   45 #include <sys/linker.h>
   46 #include <sys/proc.h>
   47 #include <sys/reg.h>
   48 #include <sys/sysent.h>
   49 #include <sys/imgact_elf.h>
   50 #include <sys/syscall.h>
   51 #include <sys/signalvar.h>
   52 #include <sys/vnode.h>
   53 
   54 #include <machine/elf.h>
   55 #ifdef VFP
   56 #include <machine/vfp.h>
   57 #endif
   58 
   59 #include <compat/freebsd32/freebsd32_util.h>
   60 
   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 
   66 extern const char *freebsd32_syscallnames[];
   67 
   68 extern char aarch32_sigcode[];
   69 extern int sz_aarch32_sigcode;
   70 
   71 static int freebsd32_fetch_syscall_args(struct thread *td);
   72 static void freebsd32_setregs(struct thread *td, struct image_params *imgp,
   73     u_long stack);
   74 static void freebsd32_set_syscall_retval(struct thread *, int);
   75 
   76 static boolean_t elf32_arm_abi_supported(struct image_params *, int32_t *,
   77     uint32_t *);
   78 
   79 extern void freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
   80 
   81 u_long __read_frequently elf32_hwcap;
   82 u_long __read_frequently elf32_hwcap2;
   83 
   84 static struct sysentvec elf32_freebsd_sysvec = {
   85         .sv_size        = SYS_MAXSYSCALL,
   86         .sv_table       = freebsd32_sysent,
   87         .sv_fixup       = elf32_freebsd_fixup,
   88         .sv_sendsig     = freebsd32_sendsig,
   89         .sv_sigcode     = aarch32_sigcode,
   90         .sv_szsigcode   = &sz_aarch32_sigcode,
   91         .sv_name        = "FreeBSD ELF32",
   92         .sv_coredump    = elf32_coredump,
   93         .sv_elf_core_osabi = ELFOSABI_FREEBSD,
   94         .sv_elf_core_abi_vendor = FREEBSD_ABI_VENDOR,
   95         .sv_elf_core_prepare_notes = elf32_prepare_notes,
   96         .sv_imgact_try  = NULL,
   97         .sv_minsigstksz = MINSIGSTKSZ,
   98         .sv_minuser     = FREEBSD32_MINUSER,
   99         .sv_maxuser     = FREEBSD32_MAXUSER,
  100         .sv_usrstack    = FREEBSD32_USRSTACK,
  101         .sv_psstrings   = FREEBSD32_PS_STRINGS,
  102         .sv_psstringssz = sizeof(struct freebsd32_ps_strings),
  103         .sv_stackprot   = VM_PROT_READ | VM_PROT_WRITE,
  104         .sv_copyout_auxargs = elf32_freebsd_copyout_auxargs,
  105         .sv_copyout_strings = freebsd32_copyout_strings,
  106         .sv_setregs     = freebsd32_setregs,
  107         .sv_fixlimit    = NULL, // XXX
  108         .sv_maxssiz     = NULL,
  109         .sv_flags       = SV_ABI_FREEBSD | SV_ILP32 | SV_SHP | SV_TIMEKEEP |
  110             SV_RNG_SEED_VER,
  111         .sv_set_syscall_retval = freebsd32_set_syscall_retval,
  112         .sv_fetch_syscall_args = freebsd32_fetch_syscall_args,
  113         .sv_syscallnames = freebsd32_syscallnames,
  114         .sv_shared_page_base = FREEBSD32_SHAREDPAGE,
  115         .sv_shared_page_len = PAGE_SIZE,
  116         .sv_schedtail   = NULL,
  117         .sv_thread_detach = NULL,
  118         .sv_trap        = NULL,
  119         .sv_hwcap       = &elf32_hwcap,
  120         .sv_hwcap2      = &elf32_hwcap2,
  121         .sv_onexec_old  = exec_onexec_old,
  122         .sv_onexit      = exit_onexit,
  123         .sv_regset_begin = SET_BEGIN(__elfN(regset)),
  124         .sv_regset_end  = SET_LIMIT(__elfN(regset)),
  125 };
  126 INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
  127 
  128 static Elf32_Brandinfo freebsd32_brand_info = {
  129         .brand          = ELFOSABI_FREEBSD,
  130         .machine        = EM_ARM,
  131         .compat_3_brand = "FreeBSD",
  132         .emul_path      = NULL,
  133         .interp_path    = "/libexec/ld-elf.so.1",
  134         .sysvec         = &elf32_freebsd_sysvec,
  135         .interp_newpath = "/libexec/ld-elf32.so.1",
  136         .brand_note     = &elf32_freebsd_brandnote,
  137         .flags          = BI_CAN_EXEC_DYN | BI_BRAND_NOTE,
  138         .header_supported= elf32_arm_abi_supported,
  139 };
  140 
  141 SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
  142     (sysinit_cfunc_t)elf32_insert_brand_entry, &freebsd32_brand_info);
  143 
  144 static boolean_t
  145 elf32_arm_abi_supported(struct image_params *imgp, int32_t *osrel __unused,
  146     uint32_t *fctl0 __unused)
  147 {
  148         const Elf32_Ehdr *hdr;
  149 
  150         /* Check if we support AArch32 */
  151         if (ID_AA64PFR0_EL0_VAL(READ_SPECIALREG(id_aa64pfr0_el1)) !=
  152             ID_AA64PFR0_EL0_64_32)
  153                 return (FALSE);
  154 
  155 #define EF_ARM_EABI_FREEBSD_MIN EF_ARM_EABI_VER4
  156         hdr = (const Elf32_Ehdr *)imgp->image_header;
  157         if (EF_ARM_EABI_VERSION(hdr->e_flags) < EF_ARM_EABI_FREEBSD_MIN) {
  158                 if (bootverbose)
  159                         uprintf("Attempting to execute non EABI binary "
  160                             "(rev %d) image %s",
  161                             EF_ARM_EABI_VERSION(hdr->e_flags),
  162                             imgp->args->fname);
  163                 return (FALSE);
  164         }
  165 
  166         return (TRUE);
  167 }
  168 
  169 static int
  170 freebsd32_fetch_syscall_args(struct thread *td)
  171 {
  172         struct proc *p;
  173         register_t *ap;
  174         struct syscall_args *sa;
  175         int error, i, nap, narg;
  176         unsigned int args[4];
  177 
  178         nap = 4;
  179         p = td->td_proc;
  180         ap = td->td_frame->tf_x;
  181         sa = &td->td_sa;
  182 
  183         /* r7 is the syscall id */
  184         sa->code = td->td_frame->tf_x[7];
  185         sa->original_code = sa->code;
  186 
  187         if (sa->code == SYS_syscall) {
  188                 sa->code = *ap++;
  189                 nap--;
  190         } else if (sa->code == SYS___syscall) {
  191                 sa->code = ap[1];
  192                 nap -= 2;
  193                 ap += 2;
  194         }
  195 
  196         if (sa->code >= p->p_sysent->sv_size)
  197                 sa->callp = &p->p_sysent->sv_table[0];
  198         else
  199                 sa->callp = &p->p_sysent->sv_table[sa->code];
  200 
  201         narg = sa->callp->sy_narg;
  202         for (i = 0; i < nap; i++)
  203                 sa->args[i] = ap[i];
  204         if (narg > nap) {
  205                 if (narg - nap > nitems(args))
  206                         panic("Too many system call arguiments");
  207                 error = copyin((void *)td->td_frame->tf_x[13], args,
  208                     (narg - nap) * sizeof(int));
  209                 if (error != 0)
  210                         return (error);
  211                 for (i = 0; i < (narg - nap); i++)
  212                         sa->args[i + nap] = args[i];
  213         }
  214 
  215         td->td_retval[0] = 0;
  216         td->td_retval[1] = 0;
  217 
  218         return (0);
  219 }
  220 
  221 static void
  222 freebsd32_set_syscall_retval(struct thread *td, int error)
  223 {
  224         struct trapframe *frame;
  225 
  226         frame = td->td_frame;
  227         switch (error) {
  228         case 0:
  229                 frame->tf_x[0] = td->td_retval[0];
  230                 frame->tf_x[1] = td->td_retval[1];
  231                 frame->tf_spsr &= ~PSR_C;
  232                 break;
  233         case ERESTART:
  234                 /*
  235                  * Reconstruct the pc to point at the swi.
  236                  */
  237                 if ((frame->tf_spsr & PSR_T) != 0)
  238                         frame->tf_elr -= 2; //THUMB_INSN_SIZE;
  239                 else
  240                         frame->tf_elr -= 4; //INSN_SIZE;
  241                 break;
  242         case EJUSTRETURN:
  243                 /* nothing to do */
  244                 break;
  245         default:
  246                 frame->tf_x[0] = error;
  247                 frame->tf_spsr |= PSR_C;
  248                 break;
  249         }
  250 }
  251 
  252 static void
  253 freebsd32_setregs(struct thread *td, struct image_params *imgp,
  254    uintptr_t stack)
  255 {
  256         struct trapframe *tf = td->td_frame;
  257         struct pcb *pcb = td->td_pcb;
  258 
  259         memset(tf, 0, sizeof(struct trapframe));
  260 
  261         /*
  262          * We need to set x0 for init as it doesn't call
  263          * cpu_set_syscall_retval to copy the value. We also
  264          * need to set td_retval for the cases where we do.
  265          */
  266         tf->tf_x[0] = stack;
  267         /* SP_usr is mapped to x13 */
  268         tf->tf_x[13] = stack;
  269         /* LR_usr is mapped to x14 */
  270         tf->tf_x[14] = imgp->entry_addr;
  271         tf->tf_elr = imgp->entry_addr;
  272         tf->tf_spsr = PSR_M_32;
  273         if ((uint32_t)imgp->entry_addr & 1)
  274                 tf->tf_spsr |= PSR_T;
  275 
  276 #ifdef VFP
  277         vfp_reset_state(td, pcb);
  278 #endif
  279 
  280         /*
  281          * Clear debug register state. It is not applicable to the new process.
  282          */
  283         bzero(&pcb->pcb_dbg_regs, sizeof(pcb->pcb_dbg_regs));
  284 }
  285 
  286 void
  287 elf32_dump_thread(struct thread *td, void *dst, size_t *off)
  288 {
  289 }

Cache object: 4240e5582dd93c0742fcf91f390ec32e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.