aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/cloudabi64/cloudabi64_sysvec.c64
-rw-r--r--sys/arm64/cloudabi64/cloudabi64_sysvec.c28
-rw-r--r--sys/compat/cloudabi64/cloudabi64_module.c8
-rw-r--r--sys/compat/cloudabi64/cloudabi64_thread.c10
-rw-r--r--sys/compat/cloudabi64/cloudabi64_util.h4
-rw-r--r--sys/contrib/cloudabi/cloudabi64_types.h7
6 files changed, 110 insertions, 11 deletions
diff --git a/sys/amd64/cloudabi64/cloudabi64_sysvec.c b/sys/amd64/cloudabi64/cloudabi64_sysvec.c
index 16d3ef9f45e7..b94c0efbb5ea 100644
--- a/sys/amd64/cloudabi64/cloudabi64_sysvec.c
+++ b/sys/amd64/cloudabi64/cloudabi64_sysvec.c
@@ -27,6 +27,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/imgact.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/sysent.h>
@@ -47,6 +48,45 @@ extern const char *cloudabi64_syscallnames[];
extern struct sysent cloudabi64_sysent[];
static int
+cloudabi64_fixup_tcb(register_t **stack_base, struct image_params *imgp)
+{
+ int error;
+ register_t tcbptr;
+
+ /* Place auxiliary vector and TCB on the stack. */
+ error = cloudabi64_fixup(stack_base, imgp);
+ if (error != 0)
+ return (error);
+
+ /*
+ * On x86-64, the TCB is referred to by %fs:0. Take some space
+ * from the top of the stack to store a single element array,
+ * containing a pointer to the TCB. %fs base will point to this.
+ */
+ tcbptr = (register_t)*stack_base;
+ return (copyout(&tcbptr, --*stack_base, sizeof(tcbptr)));
+}
+
+static void
+cloudabi64_proc_setregs(struct thread *td, struct image_params *imgp,
+ unsigned long stack)
+{
+ struct trapframe *regs;
+
+ exec_setregs(td, imgp, stack);
+
+ /*
+ * The stack now contains a pointer to the TCB, the TCB itself,
+ * and the auxiliary vector. Let %rdx point to the auxiliary
+ * vector, and set %fs base to the address of the TCB.
+ */
+ regs = td->td_frame;
+ regs->tf_rdi = stack + sizeof(register_t) +
+ roundup(sizeof(cloudabi64_tcb_t), sizeof(register_t));
+ (void)cpu_set_user_tls(td, (void *)stack);
+}
+
+static int
cloudabi64_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
struct trapframe *frame = td->td_frame;
@@ -109,16 +149,29 @@ cloudabi64_schedtail(struct thread *td)
frame->tf_rdx = td->td_tid;
}
-void
+int
cloudabi64_thread_setregs(struct thread *td,
- const cloudabi64_threadattr_t *attr)
+ const cloudabi64_threadattr_t *attr, uint64_t tcb)
{
struct trapframe *frame;
stack_t stack;
+ uint64_t tcbptr;
+ int error;
+
+ /*
+ * On x86-64, the TCB is referred to by %fs:0. Take some space
+ * from the top of the stack to store a single element array,
+ * containing a pointer to the TCB. %fs base will point to this.
+ */
+ tcbptr = rounddown(attr->stack + attr->stack_size - sizeof(tcbptr),
+ _Alignof(tcbptr));
+ error = copyout(&tcb, (void *)tcbptr, sizeof(tcb));
+ if (error != 0)
+ return (error);
/* Perform standard register initialization. */
stack.ss_sp = (void *)attr->stack;
- stack.ss_size = attr->stack_size;
+ stack.ss_size = tcbptr - attr->stack;
cpu_set_upcall_kse(td, (void *)attr->entry_point, NULL, &stack);
/*
@@ -129,12 +182,14 @@ cloudabi64_thread_setregs(struct thread *td,
frame = td->td_frame;
frame->tf_rdi = td->td_tid;
frame->tf_rsi = attr->argument;
+
+ return (cpu_set_user_tls(td, (void *)tcbptr));
}
static struct sysentvec cloudabi64_elf_sysvec = {
.sv_size = CLOUDABI64_SYS_MAXSYSCALL,
.sv_table = cloudabi64_sysent,
- .sv_fixup = cloudabi64_fixup,
+ .sv_fixup = cloudabi64_fixup_tcb,
.sv_name = "CloudABI ELF64",
.sv_coredump = elf64_coredump,
.sv_pagesize = PAGE_SIZE,
@@ -143,6 +198,7 @@ static struct sysentvec cloudabi64_elf_sysvec = {
.sv_usrstack = USRSTACK,
.sv_stackprot = VM_PROT_READ | VM_PROT_WRITE,
.sv_copyout_strings = cloudabi64_copyout_strings,
+ .sv_setregs = cloudabi64_proc_setregs,
.sv_flags = SV_ABI_CLOUDABI | SV_CAPSICUM | SV_LP64,
.sv_set_syscall_retval = cloudabi64_set_syscall_retval,
.sv_fetch_syscall_args = cloudabi64_fetch_syscall_args,
diff --git a/sys/arm64/cloudabi64/cloudabi64_sysvec.c b/sys/arm64/cloudabi64/cloudabi64_sysvec.c
index a26007a254c4..fd13db89ce76 100644
--- a/sys/arm64/cloudabi64/cloudabi64_sysvec.c
+++ b/sys/arm64/cloudabi64/cloudabi64_sysvec.c
@@ -27,6 +27,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/imgact.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/sysent.h>
@@ -46,6 +47,25 @@ __FBSDID("$FreeBSD$");
extern const char *cloudabi64_syscallnames[];
extern struct sysent cloudabi64_sysent[];
+static void
+cloudabi64_proc_setregs(struct thread *td, struct image_params *imgp,
+ unsigned long stack)
+{
+ struct trapframe *regs;
+
+ exec_setregs(td, imgp, stack);
+
+ /*
+ * The stack now contains a pointer to the TCB and the auxiliary
+ * vector. Let x0 point to the auxiliary vector, and set
+ * tpidr_el0 to the TCB.
+ */
+ regs = td->td_frame;
+ regs->tf_x[0] = td->td_retval[0] =
+ stack + roundup(sizeof(cloudabi64_tcb_t), sizeof(register_t));
+ (void)cpu_set_user_tls(td, (void *)stack);
+}
+
static int
cloudabi64_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
@@ -110,9 +130,9 @@ cloudabi64_schedtail(struct thread *td)
}
}
-void
+int
cloudabi64_thread_setregs(struct thread *td,
- const cloudabi64_threadattr_t *attr)
+ const cloudabi64_threadattr_t *attr, uint64_t tcb)
{
struct trapframe *frame;
stack_t stack;
@@ -130,6 +150,9 @@ cloudabi64_thread_setregs(struct thread *td,
frame = td->td_frame;
frame->tf_x[0] = td->td_tid;
frame->tf_x[1] = attr->argument;
+
+ /* Set up TLS. */
+ return (cpu_set_user_tls(td, (void *)tcb));
}
static struct sysentvec cloudabi64_elf_sysvec = {
@@ -144,6 +167,7 @@ static struct sysentvec cloudabi64_elf_sysvec = {
.sv_usrstack = USRSTACK,
.sv_stackprot = VM_PROT_READ | VM_PROT_WRITE,
.sv_copyout_strings = cloudabi64_copyout_strings,
+ .sv_setregs = cloudabi64_proc_setregs,
.sv_flags = SV_ABI_CLOUDABI | SV_CAPSICUM | SV_LP64,
.sv_set_syscall_retval = cloudabi64_set_syscall_retval,
.sv_fetch_syscall_args = cloudabi64_fetch_syscall_args,
diff --git a/sys/compat/cloudabi64/cloudabi64_module.c b/sys/compat/cloudabi64/cloudabi64_module.c
index de890bc5c652..246a887105cb 100644
--- a/sys/compat/cloudabi64/cloudabi64_module.c
+++ b/sys/compat/cloudabi64/cloudabi64_module.c
@@ -112,7 +112,13 @@ cloudabi64_fixup(register_t **stack_base, struct image_params *imgp)
{ .a_type = CLOUDABI_AT_NULL },
};
*stack_base -= howmany(sizeof(auxv), sizeof(register_t));
- return (copyout(auxv, *stack_base, sizeof(auxv)));
+ error = copyout(auxv, *stack_base, sizeof(auxv));
+ if (error != 0)
+ return (error);
+
+ /* Reserve space for storing the TCB. */
+ *stack_base -= howmany(sizeof(cloudabi64_tcb_t), sizeof(register_t));
+ return (0);
}
static int
diff --git a/sys/compat/cloudabi64/cloudabi64_thread.c b/sys/compat/cloudabi64/cloudabi64_thread.c
index 51961f8ad29b..429ad3398be6 100644
--- a/sys/compat/cloudabi64/cloudabi64_thread.c
+++ b/sys/compat/cloudabi64/cloudabi64_thread.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
struct thread_create_args {
cloudabi64_threadattr_t attr;
+ uint64_t tcb;
lwpid_t tid;
};
@@ -49,8 +50,7 @@ initialize_thread(struct thread *td, void *thunk)
args->tid = td->td_tid;
/* Set up initial register contents. */
- cloudabi64_thread_setregs(td, &args->attr);
- return (0);
+ return (cloudabi64_thread_setregs(td, &args->attr, args->tcb));
}
int
@@ -63,6 +63,12 @@ cloudabi64_sys_thread_create(struct thread *td,
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(cloudabi64_tcb_t), _Alignof(cloudabi64_tcb_t));
+ args.attr.stack_size = args.tcb - args.attr.stack;
+
error = thread_create(td, NULL, initialize_thread, &args);
if (error != 0)
return (error);
diff --git a/sys/compat/cloudabi64/cloudabi64_util.h b/sys/compat/cloudabi64/cloudabi64_util.h
index dcec70ece5f4..29a90d779821 100644
--- a/sys/compat/cloudabi64/cloudabi64_util.h
+++ b/sys/compat/cloudabi64/cloudabi64_util.h
@@ -42,7 +42,7 @@ extern Elf64_Brandinfo cloudabi64_brand;
register_t *cloudabi64_copyout_strings(struct image_params *);
int cloudabi64_fixup(register_t **, struct image_params *);
-void cloudabi64_thread_setregs(struct thread *,
- const cloudabi64_threadattr_t *);
+int cloudabi64_thread_setregs(struct thread *,
+ const cloudabi64_threadattr_t *, uint64_t);
#endif
diff --git a/sys/contrib/cloudabi/cloudabi64_types.h b/sys/contrib/cloudabi/cloudabi64_types.h
index 88babaaa3178..cb354d46bc55 100644
--- a/sys/contrib/cloudabi/cloudabi64_types.h
+++ b/sys/contrib/cloudabi/cloudabi64_types.h
@@ -192,6 +192,13 @@ _Static_assert(offsetof(cloudabi64_subscription_t, proc_terminate.fd) == 16, "In
_Static_assert(sizeof(cloudabi64_subscription_t) == 56, "Incorrect layout");
_Static_assert(_Alignof(cloudabi64_subscription_t) == 8, "Incorrect layout");
+typedef struct {
+ _Alignas(8) uint64_t parent;
+} cloudabi64_tcb_t;
+_Static_assert(offsetof(cloudabi64_tcb_t, parent) == 0, "Incorrect layout");
+_Static_assert(sizeof(cloudabi64_tcb_t) == 8, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi64_tcb_t) == 8, "Incorrect layout");
+
typedef void cloudabi64_threadentry_t(cloudabi_tid_t tid, uint64_t aux);
typedef struct {