cloudabi32_sysvec.c revision 326743
138451Smsmith/*- 238451Smsmith * Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/ 338451Smsmith * 438451Smsmith * Redistribution and use in source and binary forms, with or without 538451Smsmith * modification, are permitted provided that the following conditions 638451Smsmith * are met: 738451Smsmith * 1. Redistributions of source code must retain the above copyright 838451Smsmith * notice, this list of conditions and the following disclaimer. 938451Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1038451Smsmith * notice, this list of conditions and the following disclaimer in the 1138451Smsmith * documentation and/or other materials provided with the distribution. 1238451Smsmith * 1338451Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1438451Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1538451Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1638451Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1738451Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1838451Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1938451Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2038451Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2138451Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2238451Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2338451Smsmith * SUCH DAMAGE. 2438451Smsmith */ 2538451Smsmith 2638451Smsmith#include <sys/cdefs.h> 2738451Smsmith__FBSDID("$FreeBSD: stable/11/sys/arm/cloudabi32/cloudabi32_sysvec.c 326743 2017-12-10 12:25:32Z ed $"); 2838451Smsmith 2938451Smsmith#include <sys/param.h> 3038451Smsmith#include <sys/imgact.h> 3138451Smsmith#include <sys/kernel.h> 3238451Smsmith#include <sys/proc.h> 3338451Smsmith#include <sys/sysent.h> 3438451Smsmith 3538451Smsmith#include <vm/vm.h> 3638451Smsmith#include <vm/pmap.h> 3738451Smsmith 3838451Smsmith#include <machine/frame.h> 3938451Smsmith#include <machine/pcb.h> 4038451Smsmith#include <machine/vmparam.h> 4138451Smsmith 4284221Sdillon#include <compat/cloudabi/cloudabi_util.h> 4384221Sdillon 4484221Sdillon#include <compat/cloudabi32/cloudabi32_syscall.h> 4538451Smsmith#include <compat/cloudabi32/cloudabi32_util.h> 4638451Smsmith 4738451Smsmithextern const char *cloudabi32_syscallnames[]; 4838451Smsmithextern struct sysent cloudabi32_sysent[]; 4938451Smsmith 5038451Smsmithstatic void 5138451Smsmithcloudabi32_proc_setregs(struct thread *td, struct image_params *imgp, 5238451Smsmith unsigned long stack) 5338451Smsmith{ 5438451Smsmith struct trapframe *regs; 5538451Smsmith 5638451Smsmith exec_setregs(td, imgp, stack); 5738451Smsmith 5838451Smsmith /* 5938451Smsmith * The stack now contains a pointer to the TCB and the auxiliary 6038451Smsmith * vector. Let r0 point to the auxiliary vector, and set 6138451Smsmith * tpidrurw to the TCB. 6238451Smsmith */ 6338451Smsmith regs = td->td_frame; 6438451Smsmith regs->tf_r0 = td->td_retval[0] = 6538451Smsmith stack + roundup(sizeof(cloudabi32_tcb_t), sizeof(register_t)); 6638451Smsmith (void)cpu_set_user_tls(td, TO_PTR(stack)); 6738451Smsmith} 6838451Smsmith 6938451Smsmithstatic int 7038451Smsmithcloudabi32_fetch_syscall_args(struct thread *td) 7138451Smsmith{ 7238451Smsmith struct trapframe *frame; 7338451Smsmith struct syscall_args *sa; 7438451Smsmith int error; 7538451Smsmith 7638451Smsmith frame = td->td_frame; 7738451Smsmith sa = &td->td_sa; 7838451Smsmith 7938451Smsmith /* Obtain system call number. */ 8038451Smsmith sa->code = frame->tf_r12; 8138451Smsmith if (sa->code >= CLOUDABI32_SYS_MAXSYSCALL) 8238451Smsmith return (ENOSYS); 8338451Smsmith sa->callp = &cloudabi32_sysent[sa->code]; 8438451Smsmith sa->narg = sa->callp->sy_narg; 8538451Smsmith 8638451Smsmith /* Fetch system call arguments from registers and the stack. */ 8738451Smsmith sa->args[0] = frame->tf_r0; 8838451Smsmith sa->args[1] = frame->tf_r1; 8938451Smsmith sa->args[2] = frame->tf_r2; 9038451Smsmith sa->args[3] = frame->tf_r3; 9138451Smsmith if (sa->narg > 4) { 9238451Smsmith error = copyin((void *)td->td_frame->tf_usr_sp, &sa->args[4], 9338451Smsmith (sa->narg - 4) * sizeof(register_t)); 9438451Smsmith if (error != 0) 9538451Smsmith return (error); 9638451Smsmith } 9738451Smsmith 9838451Smsmith /* Default system call return values. */ 9938451Smsmith td->td_retval[0] = 0; 10038451Smsmith td->td_retval[1] = frame->tf_r1; 10138451Smsmith return (0); 10238451Smsmith} 10338451Smsmith 10438451Smsmithstatic void 10538451Smsmithcloudabi32_set_syscall_retval(struct thread *td, int error) 10638451Smsmith{ 10738451Smsmith struct trapframe *frame = td->td_frame; 10838451Smsmith 10938451Smsmith switch (error) { 11038451Smsmith case 0: 11138451Smsmith /* System call succeeded. */ 11238451Smsmith frame->tf_r0 = td->td_retval[0]; 11338451Smsmith frame->tf_r1 = td->td_retval[1]; 11438451Smsmith frame->tf_spsr &= ~PSR_C; 11538451Smsmith break; 11638451Smsmith case ERESTART: 11738451Smsmith /* Restart system call. */ 11838451Smsmith frame->tf_pc -= 4; 11938451Smsmith break; 12038451Smsmith case EJUSTRETURN: 12138451Smsmith break; 12238451Smsmith default: 12338451Smsmith /* System call returned an error. */ 12438451Smsmith frame->tf_r0 = cloudabi_convert_errno(error); 12538451Smsmith frame->tf_spsr |= PSR_C; 12638451Smsmith break; 12738451Smsmith } 12838451Smsmith} 12938451Smsmith 13038451Smsmithstatic void 13138451Smsmithcloudabi32_schedtail(struct thread *td) 13238451Smsmith{ 13338451Smsmith struct trapframe *frame = td->td_frame; 13438451Smsmith 13538451Smsmith /* 13638451Smsmith * Initial register values for processes returning from fork. 13738451Smsmith * Make sure that we only set these values when forking, not 13838451Smsmith * when creating a new thread. 13938451Smsmith */ 14038451Smsmith if ((td->td_pflags & TDP_FORKING) != 0) { 14138451Smsmith frame->tf_r0 = CLOUDABI_PROCESS_CHILD; 14238451Smsmith frame->tf_r1 = td->td_tid; 14338451Smsmith } 14438451Smsmith} 14538451Smsmith 14638451Smsmithint 14738451Smsmithcloudabi32_thread_setregs(struct thread *td, 14838451Smsmith const cloudabi32_threadattr_t *attr, uint32_t tcb) 14938451Smsmith{ 15038451Smsmith struct trapframe *frame; 15138451Smsmith stack_t stack; 15238451Smsmith 15338451Smsmith /* Perform standard register initialization. */ 15438451Smsmith stack.ss_sp = TO_PTR(attr->stack); 15538451Smsmith stack.ss_size = attr->stack_len; 15638451Smsmith cpu_set_upcall(td, TO_PTR(attr->entry_point), NULL, &stack); 15738451Smsmith 15838451Smsmith /* 15938451Smsmith * Pass in the thread ID of the new thread and the argument 16038451Smsmith * pointer provided by the parent thread in as arguments to the 16138451Smsmith * entry point. 16238451Smsmith */ 16338451Smsmith frame = td->td_frame; 16438451Smsmith frame->tf_r0 = td->td_tid; 16538451Smsmith frame->tf_r1 = attr->argument; 16638451Smsmith 16738451Smsmith /* Set up TLS. */ 16838451Smsmith return (cpu_set_user_tls(td, TO_PTR(tcb))); 16938451Smsmith} 17038451Smsmith 17138451Smsmithstatic struct sysentvec cloudabi32_elf_sysvec = { 17238451Smsmith .sv_size = CLOUDABI32_SYS_MAXSYSCALL, 17338451Smsmith .sv_table = cloudabi32_sysent, 17438451Smsmith .sv_fixup = cloudabi32_fixup, 17538451Smsmith .sv_name = "CloudABI ELF32", 17638451Smsmith .sv_coredump = elf32_coredump, 17738451Smsmith .sv_pagesize = PAGE_SIZE, 17838451Smsmith .sv_minuser = VM_MIN_ADDRESS, 17938451Smsmith .sv_maxuser = VM_MAXUSER_ADDRESS, 18038451Smsmith .sv_stackprot = VM_PROT_READ | VM_PROT_WRITE, 18138451Smsmith .sv_copyout_strings = cloudabi32_copyout_strings, 18238451Smsmith .sv_setregs = cloudabi32_proc_setregs, 18338451Smsmith .sv_flags = SV_ABI_CLOUDABI | SV_CAPSICUM | SV_ILP32, 18438451Smsmith .sv_set_syscall_retval = cloudabi32_set_syscall_retval, 18538451Smsmith .sv_fetch_syscall_args = cloudabi32_fetch_syscall_args, 18638451Smsmith .sv_syscallnames = cloudabi32_syscallnames, 18738451Smsmith .sv_schedtail = cloudabi32_schedtail, 18838451Smsmith}; 18938451Smsmith 19038451SmsmithINIT_SYSENTVEC(elf_sysvec, &cloudabi32_elf_sysvec); 19138451Smsmith 19238451SmsmithElf32_Brandinfo cloudabi32_brand = { 19338451Smsmith .brand = ELFOSABI_CLOUDABI, 19438451Smsmith .machine = EM_ARM, 19538451Smsmith .sysvec = &cloudabi32_elf_sysvec, 19638451Smsmith .flags = BI_BRAND_ONLY_STATIC, 19738451Smsmith}; 19838451Smsmith