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