Add CPU independent code for running 32-bits CloudABI executables.
Essentially, this is a literal copy of the code in sys/compat/cloudabi64, except that it now makes use of 32-bits datatypes and limits. In sys/conf/files, we now need to take care to build the code in sys/compat/cloudabi if either COMPAT_CLOUDABI32 or COMPAT_CLOUDABI64 is turned on. This change does not yet include any of the CPU dependent bits. Right now I have implementations for running i386 binaries both on i386 and x86-64, which I will send out for review separately.
This commit is contained in:
parent
258ff8a811
commit
d46ddfcd43
14
sys/compat/cloudabi32/Makefile
Normal file
14
sys/compat/cloudabi32/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
# $FreeBSD$
|
||||
|
||||
all:
|
||||
@echo "make sysent only"
|
||||
|
||||
sysent: cloudabi32_sysent.c cloudabi32_syscall.h cloudabi32_proto.h \
|
||||
cloudabi32_syscalls.c cloudabi32_systrace_args.c
|
||||
|
||||
cloudabi32_sysent.c cloudabi32_syscall.h cloudabi32_proto.h \
|
||||
cloudabi32_syscalls.c cloudabi32_systrace_args.c: \
|
||||
../../kern/makesyscalls.sh ../../contrib/cloudabi/syscalls32.master \
|
||||
syscalls.conf
|
||||
sh ../../kern/makesyscalls.sh ../../contrib/cloudabi/syscalls32.master \
|
||||
syscalls.conf
|
145
sys/compat/cloudabi32/cloudabi32_fd.c
Normal file
145
sys/compat/cloudabi32/cloudabi32_fd.c
Normal file
@ -0,0 +1,145 @@
|
||||
/*-
|
||||
* 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/limits.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <contrib/cloudabi/cloudabi32_types.h>
|
||||
|
||||
#include <compat/cloudabi32/cloudabi32_proto.h>
|
||||
#include <compat/cloudabi32/cloudabi32_util.h>
|
||||
|
||||
/* Copies in 32-bit iovec structures from userspace. */
|
||||
static int
|
||||
cloudabi32_copyinuio(const cloudabi32_iovec_t *iovp, size_t iovcnt,
|
||||
struct uio **uiop)
|
||||
{
|
||||
cloudabi32_iovec_t iovobj;
|
||||
struct uio *uio;
|
||||
struct iovec *iov;
|
||||
size_t i;
|
||||
int error;
|
||||
|
||||
/* Allocate uio and iovecs. */
|
||||
if (iovcnt > UIO_MAXIOV)
|
||||
return (EINVAL);
|
||||
uio = malloc(sizeof(struct uio) + iovcnt * sizeof(struct iovec),
|
||||
M_IOV, M_WAITOK);
|
||||
iov = (struct iovec *)(uio + 1);
|
||||
|
||||
/* Initialize uio. */
|
||||
uio->uio_iov = iov;
|
||||
uio->uio_iovcnt = iovcnt;
|
||||
uio->uio_segflg = UIO_USERSPACE;
|
||||
uio->uio_offset = -1;
|
||||
uio->uio_resid = 0;
|
||||
|
||||
/* Copy in iovecs. */
|
||||
for (i = 0; i < iovcnt; i++) {
|
||||
error = copyin(&iovp[i], &iovobj, sizeof(iovobj));
|
||||
if (error != 0) {
|
||||
free(uio, M_IOV);
|
||||
return (error);
|
||||
}
|
||||
iov[i].iov_base = TO_PTR(iovobj.iov_base);
|
||||
iov[i].iov_len = iovobj.iov_len;
|
||||
if (iov[i].iov_len > INT32_MAX - uio->uio_resid) {
|
||||
free(uio, M_IOV);
|
||||
return (EINVAL);
|
||||
}
|
||||
uio->uio_resid += iov[i].iov_len;
|
||||
}
|
||||
|
||||
*uiop = uio;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
cloudabi32_sys_fd_pread(struct thread *td,
|
||||
struct cloudabi32_sys_fd_pread_args *uap)
|
||||
{
|
||||
struct uio *uio;
|
||||
int error;
|
||||
|
||||
error = cloudabi32_copyinuio(uap->iov, uap->iovcnt, &uio);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = kern_preadv(td, uap->fd, uio, uap->offset);
|
||||
free(uio, M_IOV);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
cloudabi32_sys_fd_pwrite(struct thread *td,
|
||||
struct cloudabi32_sys_fd_pwrite_args *uap)
|
||||
{
|
||||
struct uio *uio;
|
||||
int error;
|
||||
|
||||
error = cloudabi32_copyinuio(TO_PTR(uap->iov), uap->iovcnt, &uio);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = kern_pwritev(td, uap->fd, uio, uap->offset);
|
||||
free(uio, M_IOV);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
cloudabi32_sys_fd_read(struct thread *td,
|
||||
struct cloudabi32_sys_fd_read_args *uap)
|
||||
{
|
||||
struct uio *uio;
|
||||
int error;
|
||||
|
||||
error = cloudabi32_copyinuio(uap->iov, uap->iovcnt, &uio);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = kern_readv(td, uap->fd, uio);
|
||||
free(uio, M_IOV);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
cloudabi32_sys_fd_write(struct thread *td,
|
||||
struct cloudabi32_sys_fd_write_args *uap)
|
||||
{
|
||||
struct uio *uio;
|
||||
int error;
|
||||
|
||||
error = cloudabi32_copyinuio(TO_PTR(uap->iov), uap->iovcnt, &uio);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = kern_writev(td, uap->fd, uio);
|
||||
free(uio, M_IOV);
|
||||
return (error);
|
||||
}
|
167
sys/compat/cloudabi32/cloudabi32_module.c
Normal file
167
sys/compat/cloudabi32/cloudabi32_module.c
Normal file
@ -0,0 +1,167 @@
|
||||
/*-
|
||||
* 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/imgact.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/smp.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <contrib/cloudabi/cloudabi32_types.h>
|
||||
|
||||
#include <compat/cloudabi/cloudabi_util.h>
|
||||
|
||||
#include <compat/cloudabi32/cloudabi32_util.h>
|
||||
|
||||
extern char _binary_cloudabi32_vdso_o_start[];
|
||||
extern char _binary_cloudabi32_vdso_o_end[];
|
||||
|
||||
register_t *
|
||||
cloudabi32_copyout_strings(struct image_params *imgp)
|
||||
{
|
||||
struct image_args *args;
|
||||
uintptr_t begin;
|
||||
size_t len;
|
||||
|
||||
/* Copy out program arguments. */
|
||||
args = imgp->args;
|
||||
len = args->begin_envv - args->begin_argv;
|
||||
begin = rounddown2(imgp->sysent->sv_usrstack - len, sizeof(register_t));
|
||||
copyout(args->begin_argv, (void *)begin, len);
|
||||
return ((register_t *)begin);
|
||||
}
|
||||
|
||||
int
|
||||
cloudabi32_fixup(register_t **stack_base, struct image_params *imgp)
|
||||
{
|
||||
char canarybuf[64];
|
||||
Elf32_Auxargs *args;
|
||||
struct thread *td;
|
||||
void *argdata, *canary;
|
||||
size_t argdatalen;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* CloudABI executables do not store the FreeBSD OS release
|
||||
* number in their header. Set the OS release number to the
|
||||
* latest version of FreeBSD, so that system calls behave as if
|
||||
* called natively.
|
||||
*/
|
||||
td = curthread;
|
||||
td->td_proc->p_osrel = __FreeBSD_version;
|
||||
|
||||
/* 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 = (Elf32_Auxargs *)imgp->auxargs;
|
||||
argdatalen = imgp->args->begin_envv - imgp->args->begin_argv;
|
||||
if (argdatalen > 0)
|
||||
--argdatalen;
|
||||
|
||||
/* Write out an auxiliary vector. */
|
||||
cloudabi32_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),
|
||||
VAL(CLOUDABI_AT_BASE, args->base),
|
||||
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, td->td_tid),
|
||||
PTR(CLOUDABI_AT_SYSINFO_EHDR,
|
||||
imgp->proc->p_sysent->sv_shared_page_base),
|
||||
#undef VAL
|
||||
#undef PTR
|
||||
{ .a_type = CLOUDABI_AT_NULL },
|
||||
};
|
||||
*stack_base -= howmany(sizeof(auxv), sizeof(register_t));
|
||||
error = copyout(auxv, *stack_base, sizeof(auxv));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/* Reserve space for storing the TCB. */
|
||||
*stack_base -= howmany(sizeof(cloudabi32_tcb_t), sizeof(register_t));
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cloudabi32_modevent(module_t mod, int type, void *data)
|
||||
{
|
||||
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
cloudabi_vdso_init(cloudabi32_brand.sysvec,
|
||||
_binary_cloudabi32_vdso_o_start,
|
||||
_binary_cloudabi32_vdso_o_end);
|
||||
if (elf32_insert_brand_entry(&cloudabi32_brand) < 0) {
|
||||
printf("Failed to add CloudABI ELF brand handler\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
return (0);
|
||||
case MOD_UNLOAD:
|
||||
if (elf32_brand_inuse(&cloudabi32_brand))
|
||||
return (EBUSY);
|
||||
if (elf32_remove_brand_entry(&cloudabi32_brand) < 0) {
|
||||
printf("Failed to remove CloudABI ELF brand handler\n");
|
||||
return (EINVAL);
|
||||
}
|
||||
cloudabi_vdso_destroy(cloudabi32_brand.sysvec);
|
||||
return (0);
|
||||
default:
|
||||
return (EOPNOTSUPP);
|
||||
}
|
||||
}
|
||||
|
||||
static moduledata_t cloudabi32_module = {
|
||||
"cloudabi32",
|
||||
cloudabi32_modevent,
|
||||
NULL
|
||||
};
|
||||
|
||||
DECLARE_MODULE_TIED(cloudabi32, cloudabi32_module, SI_SUB_EXEC, SI_ORDER_ANY);
|
||||
MODULE_DEPEND(cloudabi32, cloudabi, 1, 1, 1);
|
||||
FEATURE(cloudabi32, "CloudABI 32bit support");
|
408
sys/compat/cloudabi32/cloudabi32_poll.c
Normal file
408
sys/compat/cloudabi32/cloudabi32_poll.c
Normal file
@ -0,0 +1,408 @@
|
||||
/*-
|
||||
* 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
|
||||
#include <contrib/cloudabi/cloudabi32_types.h>
|
||||
|
||||
#include <compat/cloudabi/cloudabi_util.h>
|
||||
|
||||
#include <compat/cloudabi32/cloudabi32_proto.h>
|
||||
#include <compat/cloudabi32/cloudabi32_util.h>
|
||||
|
||||
/* Converts a FreeBSD signal number to a CloudABI signal number. */
|
||||
static cloudabi_signal_t
|
||||
convert_signal(int sig)
|
||||
{
|
||||
static const cloudabi_signal_t signals[] = {
|
||||
[SIGABRT] = CLOUDABI_SIGABRT,
|
||||
[SIGALRM] = CLOUDABI_SIGALRM,
|
||||
[SIGBUS] = CLOUDABI_SIGBUS,
|
||||
[SIGCHLD] = CLOUDABI_SIGCHLD,
|
||||
[SIGCONT] = CLOUDABI_SIGCONT,
|
||||
[SIGFPE] = CLOUDABI_SIGFPE,
|
||||
[SIGHUP] = CLOUDABI_SIGHUP,
|
||||
[SIGILL] = CLOUDABI_SIGILL,
|
||||
[SIGINT] = CLOUDABI_SIGINT,
|
||||
[SIGKILL] = CLOUDABI_SIGKILL,
|
||||
[SIGPIPE] = CLOUDABI_SIGPIPE,
|
||||
[SIGQUIT] = CLOUDABI_SIGQUIT,
|
||||
[SIGSEGV] = CLOUDABI_SIGSEGV,
|
||||
[SIGSTOP] = CLOUDABI_SIGSTOP,
|
||||
[SIGSYS] = CLOUDABI_SIGSYS,
|
||||
[SIGTERM] = CLOUDABI_SIGTERM,
|
||||
[SIGTRAP] = CLOUDABI_SIGTRAP,
|
||||
[SIGTSTP] = CLOUDABI_SIGTSTP,
|
||||
[SIGTTIN] = CLOUDABI_SIGTTIN,
|
||||
[SIGTTOU] = CLOUDABI_SIGTTOU,
|
||||
[SIGURG] = CLOUDABI_SIGURG,
|
||||
[SIGUSR1] = CLOUDABI_SIGUSR1,
|
||||
[SIGUSR2] = CLOUDABI_SIGUSR2,
|
||||
[SIGVTALRM] = CLOUDABI_SIGVTALRM,
|
||||
[SIGXCPU] = CLOUDABI_SIGXCPU,
|
||||
[SIGXFSZ] = CLOUDABI_SIGXFSZ,
|
||||
};
|
||||
|
||||
/* Convert unknown signals to SIGABRT. */
|
||||
if (sig < 0 || sig >= nitems(signals) || signals[sig] == 0)
|
||||
return (SIGABRT);
|
||||
return (signals[sig]);
|
||||
}
|
||||
|
||||
struct cloudabi32_kevent_args {
|
||||
const cloudabi32_subscription_t *in;
|
||||
cloudabi32_event_t *out;
|
||||
bool once;
|
||||
};
|
||||
|
||||
/* Converts CloudABI's subscription objects to FreeBSD's struct kevent. */
|
||||
static int
|
||||
cloudabi32_kevent_copyin(void *arg, struct kevent *kevp, int count)
|
||||
{
|
||||
cloudabi32_subscription_t sub;
|
||||
struct cloudabi32_kevent_args *args;
|
||||
cloudabi_timestamp_t ts;
|
||||
int error;
|
||||
|
||||
args = arg;
|
||||
while (count-- > 0) {
|
||||
/* TODO(ed): Copy in multiple entries at once. */
|
||||
error = copyin(args->in++, &sub, sizeof(sub));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
memset(kevp, 0, sizeof(*kevp));
|
||||
kevp->udata = TO_PTR(sub.userdata);
|
||||
switch (sub.type) {
|
||||
case CLOUDABI_EVENTTYPE_CLOCK:
|
||||
kevp->filter = EVFILT_TIMER;
|
||||
kevp->ident = sub.clock.identifier;
|
||||
kevp->fflags = NOTE_NSECONDS;
|
||||
if ((sub.clock.flags &
|
||||
CLOUDABI_SUBSCRIPTION_CLOCK_ABSTIME) != 0 &&
|
||||
sub.clock.timeout > 0) {
|
||||
/* Convert absolute timestamp to a relative. */
|
||||
error = cloudabi_clock_time_get(curthread,
|
||||
sub.clock.clock_id, &ts);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
ts = ts > sub.clock.timeout ? 0 :
|
||||
sub.clock.timeout - ts;
|
||||
} else {
|
||||
/* Relative timestamp. */
|
||||
ts = sub.clock.timeout;
|
||||
}
|
||||
kevp->data = ts > INTPTR_MAX ? INTPTR_MAX : ts;
|
||||
break;
|
||||
case CLOUDABI_EVENTTYPE_FD_READ:
|
||||
kevp->filter = EVFILT_READ;
|
||||
kevp->ident = sub.fd_readwrite.fd;
|
||||
if ((sub.fd_readwrite.flags &
|
||||
CLOUDABI_SUBSCRIPTION_FD_READWRITE_POLL) != 0)
|
||||
kevp->fflags = NOTE_FILE_POLL;
|
||||
break;
|
||||
case CLOUDABI_EVENTTYPE_FD_WRITE:
|
||||
kevp->filter = EVFILT_WRITE;
|
||||
kevp->ident = sub.fd_readwrite.fd;
|
||||
break;
|
||||
case CLOUDABI_EVENTTYPE_PROC_TERMINATE:
|
||||
kevp->filter = EVFILT_PROCDESC;
|
||||
kevp->ident = sub.proc_terminate.fd;
|
||||
kevp->fflags = NOTE_EXIT;
|
||||
break;
|
||||
}
|
||||
if (args->once) {
|
||||
/* Ignore flags. Simply use oneshot mode. */
|
||||
kevp->flags = EV_ADD | EV_ONESHOT;
|
||||
} else {
|
||||
/* Translate flags. */
|
||||
if ((sub.flags & CLOUDABI_SUBSCRIPTION_ADD) != 0)
|
||||
kevp->flags |= EV_ADD;
|
||||
if ((sub.flags & CLOUDABI_SUBSCRIPTION_CLEAR) != 0)
|
||||
kevp->flags |= EV_CLEAR;
|
||||
if ((sub.flags & CLOUDABI_SUBSCRIPTION_DELETE) != 0)
|
||||
kevp->flags |= EV_DELETE;
|
||||
if ((sub.flags & CLOUDABI_SUBSCRIPTION_DISABLE) != 0)
|
||||
kevp->flags |= EV_DISABLE;
|
||||
if ((sub.flags & CLOUDABI_SUBSCRIPTION_ENABLE) != 0)
|
||||
kevp->flags |= EV_ENABLE;
|
||||
if ((sub.flags & CLOUDABI_SUBSCRIPTION_ONESHOT) != 0)
|
||||
kevp->flags |= EV_ONESHOT;
|
||||
}
|
||||
++kevp;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Converts FreeBSD's struct kevent to CloudABI's event objects. */
|
||||
static int
|
||||
cloudabi32_kevent_copyout(void *arg, struct kevent *kevp, int count)
|
||||
{
|
||||
cloudabi32_event_t ev;
|
||||
struct cloudabi32_kevent_args *args;
|
||||
int error;
|
||||
|
||||
args = arg;
|
||||
while (count-- > 0) {
|
||||
/* Convert fields that should always be present. */
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
ev.userdata = (uintptr_t)kevp->udata;
|
||||
switch (kevp->filter) {
|
||||
case EVFILT_TIMER:
|
||||
ev.type = CLOUDABI_EVENTTYPE_CLOCK;
|
||||
ev.clock.identifier = kevp->ident;
|
||||
break;
|
||||
case EVFILT_READ:
|
||||
ev.type = CLOUDABI_EVENTTYPE_FD_READ;
|
||||
ev.fd_readwrite.fd = kevp->ident;
|
||||
break;
|
||||
case EVFILT_WRITE:
|
||||
ev.type = CLOUDABI_EVENTTYPE_FD_WRITE;
|
||||
ev.fd_readwrite.fd = kevp->ident;
|
||||
break;
|
||||
case EVFILT_PROCDESC:
|
||||
ev.type = CLOUDABI_EVENTTYPE_PROC_TERMINATE;
|
||||
ev.proc_terminate.fd = kevp->ident;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((kevp->flags & EV_ERROR) == 0) {
|
||||
/* Success. */
|
||||
switch (kevp->filter) {
|
||||
case EVFILT_READ:
|
||||
case EVFILT_WRITE:
|
||||
ev.fd_readwrite.nbytes = kevp->data;
|
||||
if ((kevp->flags & EV_EOF) != 0) {
|
||||
ev.fd_readwrite.flags |=
|
||||
CLOUDABI_EVENT_FD_READWRITE_HANGUP;
|
||||
}
|
||||
break;
|
||||
case EVFILT_PROCDESC:
|
||||
if (WIFSIGNALED(kevp->data)) {
|
||||
/* Process got signalled. */
|
||||
ev.proc_terminate.signal =
|
||||
convert_signal(WTERMSIG(kevp->data));
|
||||
ev.proc_terminate.exitcode = 0;
|
||||
} else {
|
||||
/* Process exited. */
|
||||
ev.proc_terminate.signal = 0;
|
||||
ev.proc_terminate.exitcode =
|
||||
WEXITSTATUS(kevp->data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Error. */
|
||||
ev.error = cloudabi_convert_errno(kevp->data);
|
||||
}
|
||||
++kevp;
|
||||
|
||||
/* TODO(ed): Copy out multiple entries at once. */
|
||||
error = copyout(&ev, args->out++, sizeof(ev));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
cloudabi32_sys_poll(struct thread *td, struct cloudabi32_sys_poll_args *uap)
|
||||
{
|
||||
struct cloudabi32_kevent_args args = {
|
||||
.in = uap->in,
|
||||
.out = uap->out,
|
||||
.once = true,
|
||||
};
|
||||
struct kevent_copyops copyops = {
|
||||
.k_copyin = cloudabi32_kevent_copyin,
|
||||
.k_copyout = cloudabi32_kevent_copyout,
|
||||
.arg = &args,
|
||||
};
|
||||
|
||||
/*
|
||||
* Bandaid to support CloudABI futex constructs that are not
|
||||
* implemented through FreeBSD's kqueue().
|
||||
*/
|
||||
if (uap->nsubscriptions == 1) {
|
||||
cloudabi32_subscription_t sub;
|
||||
cloudabi32_event_t ev = {};
|
||||
int error;
|
||||
|
||||
error = copyin(uap->in, &sub, sizeof(sub));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
ev.userdata = sub.userdata;
|
||||
ev.type = sub.type;
|
||||
if (sub.type == CLOUDABI_EVENTTYPE_CONDVAR) {
|
||||
/* Wait on a condition variable. */
|
||||
ev.condvar.condvar = sub.condvar.condvar;
|
||||
ev.error = cloudabi_convert_errno(
|
||||
cloudabi_futex_condvar_wait(
|
||||
td, TO_PTR(sub.condvar.condvar),
|
||||
sub.condvar.condvar_scope,
|
||||
TO_PTR(sub.condvar.lock),
|
||||
sub.condvar.lock_scope,
|
||||
CLOUDABI_CLOCK_MONOTONIC, UINT64_MAX, 0));
|
||||
td->td_retval[0] = 1;
|
||||
return (copyout(&ev, uap->out, sizeof(ev)));
|
||||
} else if (sub.type == CLOUDABI_EVENTTYPE_LOCK_RDLOCK) {
|
||||
/* Acquire a read lock. */
|
||||
ev.lock.lock = sub.lock.lock;
|
||||
ev.error = cloudabi_convert_errno(
|
||||
cloudabi_futex_lock_rdlock(
|
||||
td, TO_PTR(sub.lock.lock),
|
||||
sub.lock.lock_scope, CLOUDABI_CLOCK_MONOTONIC,
|
||||
UINT64_MAX, 0));
|
||||
td->td_retval[0] = 1;
|
||||
return (copyout(&ev, uap->out, sizeof(ev)));
|
||||
} else if (sub.type == CLOUDABI_EVENTTYPE_LOCK_WRLOCK) {
|
||||
/* Acquire a write lock. */
|
||||
ev.lock.lock = sub.lock.lock;
|
||||
ev.error = cloudabi_convert_errno(
|
||||
cloudabi_futex_lock_wrlock(
|
||||
td, TO_PTR(sub.lock.lock),
|
||||
sub.lock.lock_scope, CLOUDABI_CLOCK_MONOTONIC,
|
||||
UINT64_MAX, 0));
|
||||
td->td_retval[0] = 1;
|
||||
return (copyout(&ev, uap->out, sizeof(ev)));
|
||||
}
|
||||
} else if (uap->nsubscriptions == 2) {
|
||||
cloudabi32_subscription_t sub[2];
|
||||
cloudabi32_event_t ev[2] = {};
|
||||
int error;
|
||||
|
||||
error = copyin(uap->in, &sub, sizeof(sub));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
ev[0].userdata = sub[0].userdata;
|
||||
ev[0].type = sub[0].type;
|
||||
ev[1].userdata = sub[1].userdata;
|
||||
ev[1].type = sub[1].type;
|
||||
if (sub[0].type == CLOUDABI_EVENTTYPE_CONDVAR &&
|
||||
sub[1].type == CLOUDABI_EVENTTYPE_CLOCK &&
|
||||
sub[1].clock.flags == CLOUDABI_SUBSCRIPTION_CLOCK_ABSTIME) {
|
||||
/* Wait for a condition variable with timeout. */
|
||||
ev[0].condvar.condvar = sub[0].condvar.condvar;
|
||||
ev[1].clock.identifier = sub[1].clock.identifier;
|
||||
error = cloudabi_futex_condvar_wait(
|
||||
td, TO_PTR(sub[0].condvar.condvar),
|
||||
sub[0].condvar.condvar_scope,
|
||||
TO_PTR(sub[0].condvar.lock),
|
||||
sub[0].condvar.lock_scope, sub[1].clock.clock_id,
|
||||
sub[1].clock.timeout, sub[1].clock.precision);
|
||||
if (error == ETIMEDOUT) {
|
||||
td->td_retval[0] = 1;
|
||||
return (copyout(&ev[1], uap->out,
|
||||
sizeof(ev[1])));
|
||||
}
|
||||
|
||||
ev[0].error = cloudabi_convert_errno(error);
|
||||
td->td_retval[0] = 1;
|
||||
return (copyout(&ev[0], uap->out, sizeof(ev[0])));
|
||||
} else if (sub[0].type == CLOUDABI_EVENTTYPE_LOCK_RDLOCK &&
|
||||
sub[1].type == CLOUDABI_EVENTTYPE_CLOCK &&
|
||||
sub[1].clock.flags == CLOUDABI_SUBSCRIPTION_CLOCK_ABSTIME) {
|
||||
/* Acquire a read lock with a timeout. */
|
||||
ev[0].lock.lock = sub[0].lock.lock;
|
||||
ev[1].clock.identifier = sub[1].clock.identifier;
|
||||
error = cloudabi_futex_lock_rdlock(
|
||||
td, TO_PTR(sub[0].lock.lock),
|
||||
sub[0].lock.lock_scope, sub[1].clock.clock_id,
|
||||
sub[1].clock.timeout, sub[1].clock.precision);
|
||||
if (error == ETIMEDOUT) {
|
||||
td->td_retval[0] = 1;
|
||||
return (copyout(&ev[1], uap->out,
|
||||
sizeof(ev[1])));
|
||||
}
|
||||
|
||||
ev[0].error = cloudabi_convert_errno(error);
|
||||
td->td_retval[0] = 1;
|
||||
return (copyout(&ev[0], uap->out, sizeof(ev[0])));
|
||||
} else if (sub[0].type == CLOUDABI_EVENTTYPE_LOCK_WRLOCK &&
|
||||
sub[1].type == CLOUDABI_EVENTTYPE_CLOCK &&
|
||||
sub[1].clock.flags == CLOUDABI_SUBSCRIPTION_CLOCK_ABSTIME) {
|
||||
/* Acquire a write lock with a timeout. */
|
||||
ev[0].lock.lock = sub[0].lock.lock;
|
||||
ev[1].clock.identifier = sub[1].clock.identifier;
|
||||
error = cloudabi_futex_lock_wrlock(
|
||||
td, TO_PTR(sub[0].lock.lock),
|
||||
sub[0].lock.lock_scope, sub[1].clock.clock_id,
|
||||
sub[1].clock.timeout, sub[1].clock.precision);
|
||||
if (error == ETIMEDOUT) {
|
||||
td->td_retval[0] = 1;
|
||||
return (copyout(&ev[1], uap->out,
|
||||
sizeof(ev[1])));
|
||||
}
|
||||
|
||||
ev[0].error = cloudabi_convert_errno(error);
|
||||
td->td_retval[0] = 1;
|
||||
return (copyout(&ev[0], uap->out, sizeof(ev[0])));
|
||||
}
|
||||
}
|
||||
|
||||
return (kern_kevent_anonymous(td, uap->nsubscriptions, ©ops));
|
||||
}
|
||||
|
||||
int
|
||||
cloudabi32_sys_poll_fd(struct thread *td,
|
||||
struct cloudabi32_sys_poll_fd_args *uap)
|
||||
{
|
||||
struct cloudabi32_kevent_args args = {
|
||||
.in = uap->in,
|
||||
.out = uap->out,
|
||||
.once = false,
|
||||
};
|
||||
struct kevent_copyops copyops = {
|
||||
.k_copyin = cloudabi32_kevent_copyin,
|
||||
.k_copyout = cloudabi32_kevent_copyout,
|
||||
.arg = &args,
|
||||
};
|
||||
cloudabi32_subscription_t subtimo;
|
||||
struct timespec timeout;
|
||||
int error;
|
||||
|
||||
if (uap->timeout != NULL) {
|
||||
/* Poll with a timeout. */
|
||||
error = copyin(uap->timeout, &subtimo, sizeof(subtimo));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (subtimo.type != CLOUDABI_EVENTTYPE_CLOCK ||
|
||||
subtimo.clock.flags != 0)
|
||||
return (EINVAL);
|
||||
timeout.tv_sec = subtimo.clock.timeout / 1000000000;
|
||||
timeout.tv_nsec = subtimo.clock.timeout % 1000000000;
|
||||
return (kern_kevent(td, uap->fd, uap->nin, uap->nout, ©ops,
|
||||
&timeout));
|
||||
} else {
|
||||
/* Poll without a timeout. */
|
||||
return (kern_kevent(td, uap->fd, uap->nin, uap->nout, ©ops,
|
||||
NULL));
|
||||
}
|
||||
}
|
148
sys/compat/cloudabi32/cloudabi32_sock.c
Normal file
148
sys/compat/cloudabi32/cloudabi32_sock.c
Normal file
@ -0,0 +1,148 @@
|
||||
/*-
|
||||
* 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/syscallsubr.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <contrib/cloudabi/cloudabi32_types.h>
|
||||
|
||||
#include <compat/cloudabi/cloudabi_util.h>
|
||||
|
||||
#include <compat/cloudabi32/cloudabi32_proto.h>
|
||||
#include <compat/cloudabi32/cloudabi32_util.h>
|
||||
|
||||
static MALLOC_DEFINE(M_SOCKET, "socket", "CloudABI socket");
|
||||
|
||||
int
|
||||
cloudabi32_sys_sock_recv(struct thread *td,
|
||||
struct cloudabi32_sys_sock_recv_args *uap)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
cloudabi32_recv_in_t ri;
|
||||
cloudabi32_recv_out_t ro = {};
|
||||
cloudabi32_iovec_t iovobj;
|
||||
struct msghdr msghdr = {};
|
||||
const cloudabi32_iovec_t *user_iov;
|
||||
size_t i;
|
||||
int error;
|
||||
|
||||
error = copyin(uap->in, &ri, sizeof(ri));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/* Convert results in cloudabi_recv_in_t to struct msghdr. */
|
||||
if (ri.ri_datalen > UIO_MAXIOV)
|
||||
return (EINVAL);
|
||||
msghdr.msg_iovlen = ri.ri_datalen;
|
||||
msghdr.msg_iov = malloc(msghdr.msg_iovlen * sizeof(struct iovec),
|
||||
M_SOCKET, M_WAITOK);
|
||||
user_iov = TO_PTR(ri.ri_data);
|
||||
for (i = 0; i < msghdr.msg_iovlen; i++) {
|
||||
error = copyin(&user_iov[i], &iovobj, sizeof(iovobj));
|
||||
if (error != 0) {
|
||||
free(msghdr.msg_iov, M_SOCKET);
|
||||
return (error);
|
||||
}
|
||||
msghdr.msg_iov[i].iov_base = TO_PTR(iovobj.iov_base);
|
||||
msghdr.msg_iov[i].iov_len = iovobj.iov_len;
|
||||
}
|
||||
msghdr.msg_name = &ss;
|
||||
msghdr.msg_namelen = sizeof(ss);
|
||||
if (ri.ri_flags & CLOUDABI_MSG_PEEK)
|
||||
msghdr.msg_flags |= MSG_PEEK;
|
||||
if (ri.ri_flags & CLOUDABI_MSG_WAITALL)
|
||||
msghdr.msg_flags |= MSG_WAITALL;
|
||||
|
||||
/* TODO(ed): Add file descriptor passing. */
|
||||
error = kern_recvit(td, uap->sock, &msghdr, UIO_SYSSPACE, NULL);
|
||||
free(msghdr.msg_iov, M_SOCKET);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/* Convert results in msghdr to cloudabi_recv_out_t. */
|
||||
ro.ro_datalen = td->td_retval[0];
|
||||
cloudabi_convert_sockaddr((struct sockaddr *)&ss,
|
||||
MIN(msghdr.msg_namelen, sizeof(ss)), &ro.ro_peername);
|
||||
td->td_retval[0] = 0;
|
||||
return (copyout(&ro, uap->out, sizeof(ro)));
|
||||
}
|
||||
|
||||
int
|
||||
cloudabi32_sys_sock_send(struct thread *td,
|
||||
struct cloudabi32_sys_sock_send_args *uap)
|
||||
{
|
||||
cloudabi32_send_in_t si;
|
||||
cloudabi32_send_out_t so = {};
|
||||
cloudabi32_ciovec_t iovobj;
|
||||
struct msghdr msghdr = {};
|
||||
const cloudabi32_ciovec_t *user_iov;
|
||||
size_t i;
|
||||
int error, flags;
|
||||
|
||||
error = copyin(uap->in, &si, sizeof(si));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/* Convert results in cloudabi_send_in_t to struct msghdr. */
|
||||
if (si.si_datalen > UIO_MAXIOV)
|
||||
return (EINVAL);
|
||||
msghdr.msg_iovlen = si.si_datalen;
|
||||
msghdr.msg_iov = malloc(msghdr.msg_iovlen * sizeof(struct iovec),
|
||||
M_SOCKET, M_WAITOK);
|
||||
user_iov = TO_PTR(si.si_data);
|
||||
for (i = 0; i < msghdr.msg_iovlen; i++) {
|
||||
error = copyin(&user_iov[i], &iovobj, sizeof(iovobj));
|
||||
if (error != 0) {
|
||||
free(msghdr.msg_iov, M_SOCKET);
|
||||
return (error);
|
||||
}
|
||||
msghdr.msg_iov[i].iov_base = TO_PTR(iovobj.iov_base);
|
||||
msghdr.msg_iov[i].iov_len = iovobj.iov_len;
|
||||
}
|
||||
|
||||
flags = MSG_NOSIGNAL;
|
||||
if (si.si_flags & CLOUDABI_MSG_EOR)
|
||||
flags |= MSG_EOR;
|
||||
|
||||
/* TODO(ed): Add file descriptor passing. */
|
||||
error = kern_sendit(td, uap->sock, &msghdr, flags, NULL, UIO_USERSPACE);
|
||||
free(msghdr.msg_iov, M_SOCKET);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/* Convert results in msghdr to cloudabi_send_out_t. */
|
||||
so.so_datalen = td->td_retval[0];
|
||||
td->td_retval[0] = 0;
|
||||
return (copyout(&so, uap->out, sizeof(so)));
|
||||
}
|
77
sys/compat/cloudabi32/cloudabi32_thread.c
Normal file
77
sys/compat/cloudabi32/cloudabi32_thread.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*-
|
||||
* 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <contrib/cloudabi/cloudabi32_types.h>
|
||||
|
||||
#include <compat/cloudabi32/cloudabi32_proto.h>
|
||||
#include <compat/cloudabi32/cloudabi32_util.h>
|
||||
|
||||
struct thread_create_args {
|
||||
cloudabi32_threadattr_t attr;
|
||||
uint32_t tcb;
|
||||
lwpid_t tid;
|
||||
};
|
||||
|
||||
static int
|
||||
initialize_thread(struct thread *td, void *thunk)
|
||||
{
|
||||
struct thread_create_args *args = thunk;
|
||||
|
||||
/* Save the thread ID, so it can be returned. */
|
||||
args->tid = td->td_tid;
|
||||
|
||||
/* Set up initial register contents. */
|
||||
return (cloudabi32_thread_setregs(td, &args->attr, args->tcb));
|
||||
}
|
||||
|
||||
int
|
||||
cloudabi32_sys_thread_create(struct thread *td,
|
||||
struct cloudabi32_sys_thread_create_args *uap)
|
||||
{
|
||||
struct thread_create_args args;
|
||||
int error;
|
||||
|
||||
error = copyin(uap->attr, &args.attr, sizeof(args.attr));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/* Remove some space on the top of the stack for the TCB. */
|
||||
args.tcb = rounddown(args.attr.stack + args.attr.stack_size -
|
||||
sizeof(cloudabi32_tcb_t), _Alignof(cloudabi32_tcb_t));
|
||||
args.attr.stack_size = args.tcb - args.attr.stack;
|
||||
|
||||
error = thread_create(td, NULL, initialize_thread, &args);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
td->td_retval[0] = args.tid;
|
||||
return (0);
|
||||
}
|
51
sys/compat/cloudabi32/cloudabi32_util.h
Normal file
51
sys/compat/cloudabi32/cloudabi32_util.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*-
|
||||
* 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 _CLOUDABI32_UTIL_H_
|
||||
#define _CLOUDABI32_UTIL_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#define __ELF_WORD_SIZE 32
|
||||
#include <sys/imgact_elf.h>
|
||||
|
||||
#include <contrib/cloudabi/cloudabi32_types.h>
|
||||
|
||||
struct image_params;
|
||||
struct thread;
|
||||
|
||||
extern Elf32_Brandinfo cloudabi32_brand;
|
||||
|
||||
#define TO_PTR(x) ((void *)(uintptr_t)(x))
|
||||
|
||||
/* Stack initialization during process execution. */
|
||||
register_t *cloudabi32_copyout_strings(struct image_params *);
|
||||
int cloudabi32_fixup(register_t **, struct image_params *);
|
||||
|
||||
int cloudabi32_thread_setregs(struct thread *,
|
||||
const cloudabi32_threadattr_t *, uint32_t);
|
||||
|
||||
#endif
|
15
sys/compat/cloudabi32/syscalls.conf
Normal file
15
sys/compat/cloudabi32/syscalls.conf
Normal file
@ -0,0 +1,15 @@
|
||||
# $FreeBSD$
|
||||
sysnames="cloudabi32_syscalls.c"
|
||||
sysproto="cloudabi32_proto.h"
|
||||
sysproto_h=_CLOUDABI32_SYSPROTO_H_
|
||||
syshdr="cloudabi32_syscall.h"
|
||||
syssw="cloudabi32_sysent.c"
|
||||
sysmk="/dev/null"
|
||||
syscallprefix="CLOUDABI32_SYS_"
|
||||
switchname="cloudabi32_sysent"
|
||||
namesname="cloudabi32_syscallnames"
|
||||
systrace="cloudabi32_systrace_args.c"
|
||||
|
||||
# Allow all system calls in capabilities mode. Extract the names of the
|
||||
# system calls from syscalls.master.
|
||||
capenabled=`sed -n -e 's/.*\<\(cloudabi[0-9]*_sys_[a-z0-9_]*\)\>.*/\1/p' $1 | tr '\n' ','`
|
@ -274,17 +274,24 @@ cddl/dev/fbt/fbt.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}
|
||||
cddl/dev/systrace/systrace.c optional dtrace_systrace | dtraceall compile-with "${CDDL_C}"
|
||||
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
|
||||
compat/cloudabi/cloudabi_mem.c optional compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_proc.c optional compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_random.c optional compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_sock.c optional compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_thread.c optional compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_vdso.c optional compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_clock.c optional compat_cloudabi32 | compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_errno.c optional compat_cloudabi32 | compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_fd.c optional compat_cloudabi32 | compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_file.c optional compat_cloudabi32 | compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_futex.c optional compat_cloudabi32 | compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_mem.c optional compat_cloudabi32 | compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_proc.c optional compat_cloudabi32 | compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_random.c optional compat_cloudabi32 | compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_sock.c optional compat_cloudabi32 | compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_thread.c optional compat_cloudabi32 | compat_cloudabi64
|
||||
compat/cloudabi/cloudabi_vdso.c optional compat_cloudabi32 | compat_cloudabi64
|
||||
compat/cloudabi32/cloudabi32_fd.c optional compat_cloudabi32
|
||||
compat/cloudabi32/cloudabi32_module.c optional compat_cloudabi32
|
||||
compat/cloudabi32/cloudabi32_poll.c optional compat_cloudabi32
|
||||
compat/cloudabi32/cloudabi32_sock.c optional compat_cloudabi32
|
||||
compat/cloudabi32/cloudabi32_syscalls.c optional compat_cloudabi32
|
||||
compat/cloudabi32/cloudabi32_sysent.c optional compat_cloudabi32
|
||||
compat/cloudabi32/cloudabi32_thread.c optional compat_cloudabi32
|
||||
compat/cloudabi64/cloudabi64_fd.c optional compat_cloudabi64
|
||||
compat/cloudabi64/cloudabi64_module.c optional compat_cloudabi64
|
||||
compat/cloudabi64/cloudabi64_poll.c optional compat_cloudabi64
|
||||
|
@ -86,6 +86,7 @@ COMPAT_FREEBSD6 opt_compat.h
|
||||
COMPAT_FREEBSD7 opt_compat.h
|
||||
COMPAT_FREEBSD9 opt_compat.h
|
||||
COMPAT_FREEBSD10 opt_compat.h
|
||||
COMPAT_CLOUDABI32 opt_dontuse.h
|
||||
COMPAT_CLOUDABI64 opt_dontuse.h
|
||||
COMPAT_LINUXKPI opt_compat.h
|
||||
COMPILING_LINT opt_global.h
|
||||
|
Loading…
Reference in New Issue
Block a user