Index: sys/amd64/cloudabi64/cloudabi64_sysvec.c =================================================================== --- /dev/null +++ sys/amd64/cloudabi64/cloudabi64_sysvec.c @@ -0,0 +1,234 @@ +/*- + * Copyright (c) 2015 Nuxi, https://nuxi.nl/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +extern const char *cloudabi64_syscallnames[]; +extern struct sysent cloudabi64_sysent[]; + +static register_t * +cloudabi64_copyout_strings(struct image_params *imgp) +{ + uintptr_t begin; + size_t len; + + /* Copy out program arguments. */ + len = imgp->args->begin_envv - imgp->args->begin_argv; + begin = (USRSTACK - len) / sizeof(register_t) * sizeof(register_t); + copyout(imgp->args->begin_argv, (void *)begin, len); + return ((register_t *)begin); +} + +static int +cloudabi64_fixup(register_t **stack_base, struct image_params *imgp) +{ + cloudabi64_startup_data_t sd; + Elf64_Auxargs *args; + size_t arglen; + + /* + * Compute length of program arguments. As the argument data is + * binary safe, we had to add a trailing null byte in + * exec_copyin_data_fds(). Undo this by reducing the length. + */ + args = (Elf64_Auxargs *)imgp->auxargs; + arglen = imgp->args->begin_envv - imgp->args->begin_argv; + if (arglen > 0) + --arglen; + + /* Fill the program startup data structure. */ + memset(&sd, '\0', sizeof(sd)); + sd.sd_arg = (uintptr_t)*stack_base; + sd.sd_arglen = arglen; + sd.sd_elf_phdr = args->phdr; + sd.sd_elf_phdrlen = args->phnum; + sd.sd_thread_id = curthread->td_tid; + arc4rand(&sd.sd_random_seed, sizeof(sd.sd_random_seed), 0); + sd.sd_ncpus = mp_ncpus; + sd.sd_pagesize = PAGE_SIZE; + + /* Copy it out to the stack of the process. */ + *stack_base -= howmany(sizeof(sd), sizeof(register_t)); + return (copyout(&sd, *stack_base, sizeof(sd))); +} + +static int +cloudabi64_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +{ + struct trapframe *frame = td->td_frame; + + /* Obtain system call number. */ + sa->code = frame->tf_rax; + if (sa->code >= CLOUDABI64_SYS_MAXSYSCALL) + return (ENOSYS); + sa->callp = &cloudabi64_sysent[sa->code]; + + /* Fetch system call arguments. */ + sa->args[0] = frame->tf_rdi; + sa->args[1] = frame->tf_rsi; + sa->args[2] = frame->tf_rdx; + sa->args[3] = frame->tf_rcx; /* Actually %r10. */ + sa->args[4] = frame->tf_r8; + sa->args[5] = frame->tf_r9; + + /* Default system call return values. */ + td->td_retval[0] = 0; + td->td_retval[1] = frame->tf_rdx; + return (0); +} + +static void +cloudabi64_set_syscall_retval(struct thread *td, int error) +{ + struct trapframe *frame = td->td_frame; + + switch (error) { + case 0: + /* System call succeeded. */ + frame->tf_rax = td->td_retval[0]; + frame->tf_rdx = td->td_retval[1]; + frame->tf_rflags &= ~PSL_C; + break; + case ERESTART: + /* Restart system call. */ + frame->tf_rip -= frame->tf_err; + frame->tf_r10 = frame->tf_rcx; + set_pcb_flags(td->td_pcb, PCB_FULL_IRET); + break; + case EJUSTRETURN: + break; + default: + /* System call returned an error. */ + frame->tf_rax = cloudabi_convert_errno(error); + frame->tf_rflags |= PSL_C; + break; + } +} + +static void +cloudabi64_exec_setregs(struct thread *td, struct image_params *imgp, + u_long stack) +{ + + /* + * Set registers to their initial values. + * + * The entry point has to be called with two arguments: the + * address of the startup data structure and the size of this + * structure. + * + * exec_setregs() for setting the former. The latter is provided + * for forward compatibility and is set in this function. + */ + exec_setregs(td, imgp, stack); + td->td_frame->tf_rsi = sizeof(cloudabi64_startup_data_t); +} + +static struct sysentvec cloudabi64_elf_sysvec = { + .sv_size = CLOUDABI64_SYS_MAXSYSCALL, + .sv_table = cloudabi64_sysent, + .sv_fixup = cloudabi64_fixup, + .sv_name = "CloudABI ELF64", + .sv_coredump = elf64_coredump, + .sv_pagesize = PAGE_SIZE, + .sv_minuser = VM_MIN_ADDRESS, + .sv_maxuser = VM_MAXUSER_ADDRESS, + .sv_usrstack = USRSTACK, + .sv_stackprot = VM_PROT_READ | VM_PROT_WRITE, + .sv_copyout_strings = cloudabi64_copyout_strings, + .sv_setregs = cloudabi64_exec_setregs, + .sv_flags = SV_ABI_CLOUDABI, + .sv_set_syscall_retval = cloudabi64_set_syscall_retval, + .sv_fetch_syscall_args = cloudabi64_fetch_syscall_args, + .sv_syscallnames = cloudabi64_syscallnames, +}; + +INIT_SYSENTVEC(elf_sysvec, &cloudabi64_elf_sysvec); + +static Elf64_Brandinfo cloudabi64_brand = { + .brand = ELFOSABI_CLOUDABI, + .machine = EM_X86_64, + .sysvec = &cloudabi64_elf_sysvec, + .compat_3_brand = "CloudABI", +}; + +static int +cloudabi64_modevent(module_t mod, int type, void *data) +{ + + switch (type) { + case MOD_LOAD: + if (elf64_insert_brand_entry(&cloudabi64_brand) < 0) { + printf("Failed to add CloudABI ELF brand handler\n"); + return (EINVAL); + } + return (0); + case MOD_UNLOAD: + if (elf64_brand_inuse(&cloudabi64_brand)) + return (EBUSY); + if (elf64_remove_brand_entry(&cloudabi64_brand) < 0) { + printf("Failed to remove CloudABI ELF brand handler\n"); + return (EINVAL); + } + return (0); + default: + return (EOPNOTSUPP); + } +} + +static moduledata_t cloudabi64_module = { + "cloudabi64", + cloudabi64_modevent, + NULL +}; + +DECLARE_MODULE_TIED(cloudabi64, cloudabi64_module, SI_SUB_EXEC, SI_ORDER_ANY); +MODULE_DEPEND(cloudabi64, cloudabi, 1, 1, 1); Index: sys/compat/cloudabi/cloudabi_errno.c =================================================================== --- /dev/null +++ sys/compat/cloudabi/cloudabi_errno.c @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2015 Nuxi, https://nuxi.nl/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include + +#include +#include + +/* Converts a FreeBSD errno to a CloudABI errno. */ +cloudabi_errno_t +cloudabi_convert_errno(int error) +{ + const int table[] = { + [E2BIG] = CLOUDABI_E2BIG, + [EACCES] = CLOUDABI_EACCES, + [EADDRINUSE] = CLOUDABI_EADDRINUSE, + [EADDRNOTAVAIL] = CLOUDABI_EADDRNOTAVAIL, + [EAFNOSUPPORT] = CLOUDABI_EAFNOSUPPORT, + [EAGAIN] = CLOUDABI_EAGAIN, + [EALREADY] = CLOUDABI_EALREADY, + [EBADF] = CLOUDABI_EBADF, + [EBADMSG] = CLOUDABI_EBADMSG, + [EBUSY] = CLOUDABI_EBUSY, + [ECANCELED] = CLOUDABI_ECANCELED, + [ECHILD] = CLOUDABI_ECHILD, + [ECONNABORTED] = CLOUDABI_ECONNABORTED, + [ECONNREFUSED] = CLOUDABI_ECONNREFUSED, + [ECONNRESET] = CLOUDABI_ECONNRESET, + [EDEADLK] = CLOUDABI_EDEADLK, + [EDESTADDRREQ] = CLOUDABI_EDESTADDRREQ, + [EDOM] = CLOUDABI_EDOM, + [EDQUOT] = CLOUDABI_EDQUOT, + [EEXIST] = CLOUDABI_EEXIST, + [EFAULT] = CLOUDABI_EFAULT, + [EFBIG] = CLOUDABI_EFBIG, + [EHOSTUNREACH] = CLOUDABI_EHOSTUNREACH, + [EIDRM] = CLOUDABI_EIDRM, + [EILSEQ] = CLOUDABI_EILSEQ, + [EINPROGRESS] = CLOUDABI_EINPROGRESS, + [EINTR] = CLOUDABI_EINTR, + [EINVAL] = CLOUDABI_EINVAL, + [EIO] = CLOUDABI_EIO, + [EISCONN] = CLOUDABI_EISCONN, + [EISDIR] = CLOUDABI_EISDIR, + [ELOOP] = CLOUDABI_ELOOP, + [EMFILE] = CLOUDABI_EMFILE, + [EMLINK] = CLOUDABI_EMLINK, + [EMSGSIZE] = CLOUDABI_EMSGSIZE, + [EMULTIHOP] = CLOUDABI_EMULTIHOP, + [ENAMETOOLONG] = CLOUDABI_ENAMETOOLONG, + [ENETDOWN] = CLOUDABI_ENETDOWN, + [ENETRESET] = CLOUDABI_ENETRESET, + [ENETUNREACH] = CLOUDABI_ENETUNREACH, + [ENFILE] = CLOUDABI_ENFILE, + [ENOBUFS] = CLOUDABI_ENOBUFS, + [ENODEV] = CLOUDABI_ENODEV, + [ENOENT] = CLOUDABI_ENOENT, + [ENOEXEC] = CLOUDABI_ENOEXEC, + [ENOLCK] = CLOUDABI_ENOLCK, + [ENOLINK] = CLOUDABI_ENOLINK, + [ENOMEM] = CLOUDABI_ENOMEM, + [ENOMSG] = CLOUDABI_ENOMSG, + [ENOPROTOOPT] = CLOUDABI_ENOPROTOOPT, + [ENOSPC] = CLOUDABI_ENOSPC, + [ENOSYS] = CLOUDABI_ENOSYS, + [ENOTCONN] = CLOUDABI_ENOTCONN, + [ENOTDIR] = CLOUDABI_ENOTDIR, + [ENOTEMPTY] = CLOUDABI_ENOTEMPTY, + [ENOTRECOVERABLE] = CLOUDABI_ENOTRECOVERABLE, + [ENOTSOCK] = CLOUDABI_ENOTSOCK, + [ENOTSUP] = CLOUDABI_ENOTSUP, + [ENOTTY] = CLOUDABI_ENOTTY, + [ENXIO] = CLOUDABI_ENXIO, + [EOVERFLOW] = CLOUDABI_EOVERFLOW, + [EOWNERDEAD] = CLOUDABI_EOWNERDEAD, + [EPERM] = CLOUDABI_EPERM, + [EPIPE] = CLOUDABI_EPIPE, + [EPROTO] = CLOUDABI_EPROTO, + [EPROTONOSUPPORT] = CLOUDABI_EPROTONOSUPPORT, + [EPROTOTYPE] = CLOUDABI_EPROTOTYPE, + [ERANGE] = CLOUDABI_ERANGE, + [EROFS] = CLOUDABI_EROFS, + [ESPIPE] = CLOUDABI_ESPIPE, + [ESRCH] = CLOUDABI_ESRCH, + [ESTALE] = CLOUDABI_ESTALE, + [ETIMEDOUT] = CLOUDABI_ETIMEDOUT, + [ETXTBSY] = CLOUDABI_ETXTBSY, + [EXDEV] = CLOUDABI_EXDEV, + [ENOTCAPABLE] = CLOUDABI_ENOTCAPABLE, + }; + + /* Unknown error: fall back to returning ENOSYS. */ + if (error < 0 || error >= nitems(table) || table[error] == 0) + return (error == 0 ? 0 : CLOUDABI_ENOSYS); + return (table[error]); +} Index: sys/compat/cloudabi/cloudabi_util.h =================================================================== --- /dev/null +++ sys/compat/cloudabi/cloudabi_util.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2015 Nuxi, https://nuxi.nl/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _CLOUDABI_UTIL_H_ +#define _CLOUDABI_UTIL_H_ + +#include + +/* Converts a FreeBSD errno to a CloudABI errno. */ +cloudabi_errno_t cloudabi_convert_errno(int); + +#endif Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -254,6 +254,7 @@ cddl/dev/prototype.c optional dtrace_prototype | dtraceall compile-with "${CDDL_C}" fs/nfsclient/nfs_clkdtrace.c optional dtnfscl nfscl | dtraceall nfscl compile-with "${CDDL_C}" compat/cloudabi/cloudabi_clock.c optional compat_cloudabi64 +compat/cloudabi/cloudabi_errno.c optional compat_cloudabi64 compat/cloudabi/cloudabi_fd.c optional compat_cloudabi64 compat/cloudabi/cloudabi_file.c optional compat_cloudabi64 compat/cloudabi/cloudabi_futex.c optional compat_cloudabi64 Index: sys/conf/files.amd64 =================================================================== --- sys/conf/files.amd64 +++ sys/conf/files.amd64 @@ -137,6 +137,7 @@ amd64/amd64/uio_machdep.c standard amd64/amd64/uma_machdep.c standard amd64/amd64/vm_machdep.c standard +amd64/cloudabi64/cloudabi64_sysvec.c optional compat_cloudabi64 amd64/pci/pci_cfgreg.c optional pci cddl/contrib/opensolaris/common/atomic/amd64/opensolaris_atomic.S optional zfs | dtrace compile-with "${ZFS_S}" cddl/dev/dtrace/amd64/dtrace_asm.S optional dtrace compile-with "${DTRACE_S}" Index: sys/sys/sysent.h =================================================================== --- sys/sys/sysent.h +++ sys/sys/sysent.h @@ -153,6 +153,7 @@ /* same as ELFOSABI_XXX, to prevent header pollution */ #define SV_ABI_LINUX 3 #define SV_ABI_FREEBSD 9 +#define SV_ABI_CLOUDABI 17 #define SV_ABI_UNDEF 255 #ifdef _KERNEL