Index: sys/amd64/cloudabi64/cloudabi64_sysvec.c =================================================================== --- /dev/null +++ sys/amd64/cloudabi64/cloudabi64_sysvec.c @@ -0,0 +1,230 @@ +/*- + * 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 = rounddown2(USRSTACK - len, 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) +{ + char canarybuf[64]; + Elf64_Auxargs *args; + void *argdata, *canary; + size_t argdatalen; + int error; + + /* Store canary for stack smashing protection. */ + argdata = *stack_base; + arc4rand(canarybuf, sizeof(canarybuf), 0); + *stack_base -= howmany(sizeof(canarybuf), sizeof(register_t)); + canary = *stack_base; + error = copyout(canarybuf, canary, sizeof(canarybuf)); + if (error != 0) + return (error); + + /* + * 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; + argdatalen = imgp->args->begin_envv - imgp->args->begin_argv; + if (argdatalen > 0) + --argdatalen; + + /* Write out an auxiliary vector. */ + cloudabi64_auxv_t auxv[] = { +#define VAL(type, val) { .a_type = (type), .a_val = (val) } +#define PTR(type, ptr) { .a_type = (type), .a_ptr = (uintptr_t)(ptr) } + PTR(CLOUDABI_AT_ARGDATA, argdata), + VAL(CLOUDABI_AT_ARGDATALEN, argdatalen), + PTR(CLOUDABI_AT_CANARY, canary), + VAL(CLOUDABI_AT_CANARYLEN, sizeof(canarybuf)), + VAL(CLOUDABI_AT_NCPUS, mp_ncpus), + VAL(CLOUDABI_AT_PAGESZ, args->pagesz), + PTR(CLOUDABI_AT_PHDR, args->phdr), + VAL(CLOUDABI_AT_PHNUM, args->phnum), + VAL(CLOUDABI_AT_TID, curthread->td_tid), +#undef VAL +#undef PTR + { .a_type = CLOUDABI_AT_NULL }, + }; + *stack_base -= howmany(sizeof(auxv), sizeof(register_t)); + return (copyout(auxv, *stack_base, sizeof(auxv))); +} + +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 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_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) +{ + static 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/contrib/cloudabi/syscalldefs_md.h =================================================================== --- sys/contrib/cloudabi/syscalldefs_md.h +++ sys/contrib/cloudabi/syscalldefs_md.h @@ -43,6 +43,19 @@ typedef void IDENT(threadentry_t)(cloudabi_tid_t, PTR(void)); +// Auxiliary vector entry, used to provide paramters on startup. +typedef struct { + uint32_t a_type; + union { + MEMBER(IDENT(size_t)) a_val; + MEMBER(PTR(void)) a_ptr; + }; +} IDENT(auxv_t); +ASSERT_OFFSET(auxv_t, a_type, 0, 0); +ASSERT_OFFSET(auxv_t, a_val, 4, 8); +ASSERT_OFFSET(auxv_t, a_ptr, 4, 8); +ASSERT_SIZE(auxv_t, 8, 16); + typedef struct { MEMBER(PTR(const void)) iov_base; MEMBER(IDENT(size_t)) iov_len; @@ -162,29 +175,6 @@ ASSERT_SIZE(send_out_t, 4, 8); typedef struct { - MEMBER(PTR(const void)) sd_arg; // Program argument data. - MEMBER(IDENT(size_t)) sd_arglen; // Program argument data size. - - MEMBER(PTR(void)) sd_elf_phdr; // ELF program header. - MEMBER(IDENT(size_t)) sd_elf_phdrlen; // ELF program header length. - - MEMBER(cloudabi_tid_t) sd_thread_id; // Thread ID. - MEMBER(uint64_t) sd_random_seed; // Random seed, used for SSP. - - MEMBER(uint32_t) sd_ncpus; // Number of CPUs. - MEMBER(uint32_t) sd_pagesize; // Page size. -} IDENT(startup_data_t); -ASSERT_OFFSET(startup_data_t, sd_arg, 0, 0); -ASSERT_OFFSET(startup_data_t, sd_arglen, 4, 8); -ASSERT_OFFSET(startup_data_t, sd_elf_phdr, 8, 16); -ASSERT_OFFSET(startup_data_t, sd_elf_phdrlen, 12, 24); -ASSERT_OFFSET(startup_data_t, sd_thread_id, 16, 32); -ASSERT_OFFSET(startup_data_t, sd_random_seed, 24, 40); -ASSERT_OFFSET(startup_data_t, sd_ncpus, 32, 48); -ASSERT_OFFSET(startup_data_t, sd_pagesize, 36, 52); -ASSERT_SIZE(startup_data_t, 40, 56); - -typedef struct { MEMBER(cloudabi_userdata_t) userdata; MEMBER(uint16_t) flags; MEMBER(cloudabi_eventtype_t) type; Index: sys/contrib/cloudabi/syscalldefs_mi.h =================================================================== --- sys/contrib/cloudabi/syscalldefs_mi.h +++ sys/contrib/cloudabi/syscalldefs_mi.h @@ -40,6 +40,19 @@ #define CLOUDABI_ADVICE_SEQUENTIAL 5 #define CLOUDABI_ADVICE_WILLNEED 6 +// Auxiliary vector entries. All entries that are also part of the +// x86-64 ABI use the same number. All extensions start at 256. +#define CLOUDABI_AT_ARGDATA 256 +#define CLOUDABI_AT_ARGDATALEN 257 +#define CLOUDABI_AT_CANARY 258 +#define CLOUDABI_AT_CANARYLEN 259 +#define CLOUDABI_AT_NCPUS 260 +#define CLOUDABI_AT_NULL 0 +#define CLOUDABI_AT_PAGESZ 6 +#define CLOUDABI_AT_PHDR 3 +#define CLOUDABI_AT_PHNUM 4 +#define CLOUDABI_AT_TID 261 + // Clocks. #define CLOUDABI_CLOCK_MONOTONIC 1 #define CLOUDABI_CLOCK_PROCESS_CPUTIME_ID 2 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