cloudabi64_sysvec.c revision 316574
1244769Sglebius/*- 2126258Smlaier * Copyright (c) 2015 Nuxi, https://nuxi.nl/ 3244769Sglebius * 4126258Smlaier * Redistribution and use in source and binary forms, with or without 5126258Smlaier * modification, are permitted provided that the following conditions 6126258Smlaier * are met: 7126258Smlaier * 1. Redistributions of source code must retain the above copyright 8126258Smlaier * notice, this list of conditions and the following disclaimer. 9126258Smlaier * 2. Redistributions in binary form must reproduce the above copyright 10126258Smlaier * notice, this list of conditions and the following disclaimer in the 11126258Smlaier * documentation and/or other materials provided with the distribution. 12126258Smlaier * 13126258Smlaier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14126258Smlaier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15126258Smlaier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16126258Smlaier * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17126258Smlaier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18126258Smlaier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19126258Smlaier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20126258Smlaier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21126258Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22126258Smlaier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23126258Smlaier * SUCH DAMAGE. 24126258Smlaier */ 25126258Smlaier 26126258Smlaier#include <sys/cdefs.h> 27126258Smlaier__FBSDID("$FreeBSD: stable/11/sys/arm64/cloudabi64/cloudabi64_sysvec.c 316574 2017-04-06 15:10:36Z ed $"); 28244769Sglebius 29223637Sbz#include <sys/param.h> 30223637Sbz#include <sys/imgact.h> 31223637Sbz#include <sys/kernel.h> 32223637Sbz#include <sys/proc.h> 33223637Sbz#include <sys/sysent.h> 34223637Sbz 35223637Sbz#include <vm/vm.h> 36223637Sbz#include <vm/pmap.h> 37223637Sbz 38223637Sbz#include <machine/frame.h> 39223637Sbz#include <machine/pcb.h> 40223637Sbz#include <machine/vmparam.h> 41223637Sbz 42223637Sbz#include <compat/cloudabi/cloudabi_util.h> 43223637Sbz 44228814Sglebius#include <compat/cloudabi64/cloudabi64_syscall.h> 45244769Sglebius#include <compat/cloudabi64/cloudabi64_util.h> 46244769Sglebius 47228814Sglebiusextern const char *cloudabi64_syscallnames[]; 48244185Sglebiusextern struct sysent cloudabi64_sysent[]; 49228814Sglebius 50228815Sglebiusstatic void 51228816Sglebiuscloudabi64_proc_setregs(struct thread *td, struct image_params *imgp, 52244113Sglebius unsigned long stack) 53229961Sglebius{ 54232685Sglebius struct trapframe *regs; 55229777Sglebius 56233846Sglebius exec_setregs(td, imgp, stack); 57233874Sglebius 58228814Sglebius /* 59228814Sglebius * The stack now contains a pointer to the TCB and the auxiliary 60240233Sglebius * vector. Let x0 point to the auxiliary vector, and set 61240233Sglebius * tpidr_el0 to the TCB. 62240233Sglebius */ 63126261Smlaier regs = td->td_frame; 64126261Smlaier regs->tf_x[0] = td->td_retval[0] = 65126261Smlaier stack + roundup(sizeof(cloudabi64_tcb_t), sizeof(register_t)); 66153110Sru (void)cpu_set_user_tls(td, (void *)stack); 67126258Smlaier} 68223637Sbz 69240233Sglebiusstatic int 70223637Sbzcloudabi64_fetch_syscall_args(struct thread *td, struct syscall_args *sa) 71240233Sglebius{ 72240233Sglebius struct trapframe *frame = td->td_frame; 73126258Smlaier int i; 74129907Smlaier 75130613Smlaier /* Obtain system call number. */ 76240233Sglebius sa->code = frame->tf_x[8]; 77229850Sglebius if (sa->code >= CLOUDABI64_SYS_MAXSYSCALL) 78240233Sglebius return (ENOSYS); 79240233Sglebius sa->callp = &cloudabi64_sysent[sa->code]; 80223637Sbz sa->narg = sa->callp->sy_narg; 81126258Smlaier 82240233Sglebius /* Fetch system call arguments. */ 83126258Smlaier for (i = 0; i < MAXARGS; i++) 84130933Sbrooks sa->args[i] = frame->tf_x[i]; 85126258Smlaier 86240233Sglebius /* Default system call return values. */ 87240233Sglebius td->td_retval[0] = 0; 88223637Sbz td->td_retval[1] = frame->tf_x[1]; 89240233Sglebius return (0); 90171168Smlaier} 91126258Smlaier 92130613Smlaierstatic void 93240233Sglebiuscloudabi64_set_syscall_retval(struct thread *td, int error) 94130613Smlaier{ 95240233Sglebius struct trapframe *frame = td->td_frame; 96240233Sglebius 97240233Sglebius switch (error) { 98126258Smlaier case 0: 99223637Sbz /* System call succeeded. */ 100223637Sbz frame->tf_x[0] = td->td_retval[0]; 101223637Sbz frame->tf_x[1] = td->td_retval[1]; 102246822Sglebius frame->tf_spsr &= ~PSR_C; 103126258Smlaier break; 104223637Sbz case ERESTART: 105223637Sbz /* Restart system call. */ 106223637Sbz frame->tf_elr -= 4; 107223637Sbz break; 108223637Sbz case EJUSTRETURN: 109223637Sbz break; 110240233Sglebius default: 111240233Sglebius /* System call returned an error. */ 112240233Sglebius frame->tf_x[0] = cloudabi_convert_errno(error); 113240233Sglebius frame->tf_spsr |= PSR_C; 114240233Sglebius break; 115240233Sglebius } 116240233Sglebius} 117240233Sglebius 118240233Sglebiusstatic void 119240233Sglebiuscloudabi64_schedtail(struct thread *td) 120240233Sglebius{ 121240233Sglebius struct trapframe *frame = td->td_frame; 122240233Sglebius 123240233Sglebius /* 124223637Sbz * Initial register values for processes returning from fork. 125240233Sglebius * Make sure that we only set these values when forking, not 126223637Sbz * when creating a new thread. 127223637Sbz */ 128223637Sbz if ((td->td_pflags & TDP_FORKING) != 0) { 129223637Sbz frame->tf_x[0] = CLOUDABI_PROCESS_CHILD; 130223637Sbz frame->tf_x[1] = td->td_tid; 131223637Sbz } 132223637Sbz} 133223637Sbz 134223637Sbzint 135223637Sbzcloudabi64_thread_setregs(struct thread *td, 136223637Sbz const cloudabi64_threadattr_t *attr, uint64_t tcb) 137223637Sbz{ 138223637Sbz struct trapframe *frame; 139223637Sbz stack_t stack; 140223637Sbz 141223637Sbz /* Perform standard register initialization. */ 142241056Sglebius stack.ss_sp = TO_PTR(attr->stack); 143223637Sbz stack.ss_size = attr->stack_len; 144223637Sbz cpu_set_upcall(td, TO_PTR(attr->entry_point), NULL, &stack); 145223637Sbz 146223637Sbz /* 147223637Sbz * Pass in the thread ID of the new thread and the argument 148241056Sglebius * pointer provided by the parent thread in as arguments to the 149241056Sglebius * entry point. 150241056Sglebius */ 151241056Sglebius frame = td->td_frame; 152223637Sbz frame->tf_x[0] = td->td_tid; 153240233Sglebius frame->tf_x[1] = attr->argument; 154223637Sbz 155223637Sbz /* Set up TLS. */ 156223637Sbz return (cpu_set_user_tls(td, (void *)tcb)); 157223637Sbz} 158223637Sbz 159223637Sbzstatic struct sysentvec cloudabi64_elf_sysvec = { 160223637Sbz .sv_size = CLOUDABI64_SYS_MAXSYSCALL, 161240233Sglebius .sv_table = cloudabi64_sysent, 162240233Sglebius .sv_fixup = cloudabi64_fixup, 163223637Sbz .sv_name = "CloudABI ELF64", 164240233Sglebius .sv_coredump = elf64_coredump, 165240233Sglebius .sv_pagesize = PAGE_SIZE, 166223637Sbz .sv_minuser = VM_MIN_ADDRESS, 167223637Sbz .sv_maxuser = VM_MAXUSER_ADDRESS, 168223637Sbz .sv_stackprot = VM_PROT_READ | VM_PROT_WRITE, 169223637Sbz .sv_copyout_strings = cloudabi64_copyout_strings, 170223637Sbz .sv_setregs = cloudabi64_proc_setregs, 171223637Sbz .sv_flags = SV_ABI_CLOUDABI | SV_CAPSICUM | SV_LP64, 172240233Sglebius .sv_set_syscall_retval = cloudabi64_set_syscall_retval, 173240233Sglebius .sv_fetch_syscall_args = cloudabi64_fetch_syscall_args, 174240233Sglebius .sv_syscallnames = cloudabi64_syscallnames, 175240233Sglebius .sv_schedtail = cloudabi64_schedtail, 176240233Sglebius}; 177240233Sglebius 178240233SglebiusINIT_SYSENTVEC(elf_sysvec, &cloudabi64_elf_sysvec); 179223637Sbz 180126258SmlaierElf64_Brandinfo cloudabi64_brand = { 181223637Sbz .brand = ELFOSABI_CLOUDABI, 182240233Sglebius .machine = EM_AARCH64, 183223637Sbz .sysvec = &cloudabi64_elf_sysvec, 184223637Sbz .flags = BI_CAN_EXEC_DYN, 185240233Sglebius}; 186240233Sglebius