]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/amd64/cloudabi32/cloudabi32_sysvec.c
Flowtables were removed in r321618, remove stray reference here.
[FreeBSD/FreeBSD.git] / sys / amd64 / cloudabi32 / cloudabi32_sysvec.c
1 /*-
2  * Copyright (c) 2015-2016 Nuxi, https://nuxi.nl/
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include <sys/param.h>
30 #include <sys/imgact.h>
31 #include <sys/kernel.h>
32 #include <sys/proc.h>
33 #include <sys/sysent.h>
34
35 #include <vm/vm.h>
36 #include <vm/pmap.h>
37
38 #include <machine/frame.h>
39 #include <machine/pcb.h>
40 #include <machine/vmparam.h>
41
42 #include <compat/cloudabi/cloudabi_util.h>
43
44 #include <compat/cloudabi32/cloudabi32_syscall.h>
45 #include <compat/cloudabi32/cloudabi32_util.h>
46
47 #include <compat/ia32/ia32_signal.h>
48 #include <compat/ia32/ia32_util.h>
49
50 extern const char *cloudabi32_syscallnames[];
51 extern struct sysent cloudabi32_sysent[];
52
53 extern unsigned long ia32_maxssiz;
54
55 static int
56 cloudabi32_fixup_tcb(register_t **stack_base, struct image_params *imgp)
57 {
58         int error;
59         uint32_t args[2];
60
61         /* Place auxiliary vector and TCB on the stack. */
62         error = cloudabi32_fixup(stack_base, imgp);
63         if (error != 0)
64                 return (error);
65
66         /*
67          * On i386, the TCB is referred to by %gs:0. Reuse the empty
68          * space normally used by the return address (args[0]) to store
69          * a single element array, containing a pointer to the TCB. %gs
70          * base will point to this.
71          *
72          * Also let the first argument of the entry point (args[1])
73          * refer to the auxiliary vector, which is stored right after
74          * the TCB.
75          */
76         args[0] = (uintptr_t)*stack_base;
77         args[1] = (uintptr_t)*stack_base +
78             roundup(sizeof(cloudabi32_tcb_t), sizeof(register_t));
79         *stack_base -= howmany(sizeof(args), sizeof(register_t));
80         return (copyout(args, *stack_base, sizeof(args)));
81 }
82
83 static void
84 cloudabi32_proc_setregs(struct thread *td, struct image_params *imgp,
85     unsigned long stack)
86 {
87
88         ia32_setregs(td, imgp, stack);
89         (void)cpu_set_user_tls(td, TO_PTR(stack));
90 }
91
92 static int
93 cloudabi32_fetch_syscall_args(struct thread *td)
94 {
95         struct trapframe *frame;
96         struct syscall_args *sa;
97         int error;
98
99         frame = td->td_frame;
100         sa = &td->td_sa;
101
102         /* Obtain system call number. */
103         sa->code = frame->tf_rax;
104         if (sa->code >= CLOUDABI32_SYS_MAXSYSCALL)
105                 return (ENOSYS);
106         sa->callp = &cloudabi32_sysent[sa->code];
107         sa->narg = sa->callp->sy_narg;
108
109         /*
110          * Fetch system call arguments.
111          *
112          * The vDSO has already made sure that the arguments are
113          * eight-byte aligned. Pointers and size_t parameters are
114          * zero-extended. This makes it possible to copy in the
115          * arguments directly. As long as the call doesn't use 32-bit
116          * data structures, we can just invoke the same system call
117          * implementation used by 64-bit processes.
118          */
119         error = copyin((void *)frame->tf_rcx, sa->args,
120             sa->narg * sizeof(sa->args[0]));
121         if (error != 0)
122                 return (error);
123
124         /* Default system call return values. */
125         td->td_retval[0] = 0;
126         td->td_retval[1] = 0;
127         return (0);
128 }
129
130 static void
131 cloudabi32_set_syscall_retval(struct thread *td, int error)
132 {
133         struct trapframe *frame = td->td_frame;
134
135         switch (error) {
136         case 0:
137                 /*
138                  * System call succeeded.
139                  *
140                  * Simply copy out the 64-bit return values into the
141                  * same buffer provided for system call arguments. The
142                  * vDSO will copy them to the right spot, truncating
143                  * pointers and size_t values to 32 bits.
144                  */
145                 frame->tf_rax = copyout(td->td_retval, (void *)frame->tf_rcx,
146                     sizeof(td->td_retval)) == 0 ? 0 : CLOUDABI_EFAULT;
147                 break;
148         case ERESTART:
149                 /* Restart system call. */
150                 frame->tf_rip -= frame->tf_err;
151                 frame->tf_r10 = frame->tf_rcx;
152                 set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
153                 break;
154         case EJUSTRETURN:
155                 break;
156         default:
157                 /* System call returned an error. */
158                 frame->tf_rax = cloudabi_convert_errno(error);
159                 break;
160         }
161 }
162
163 static void
164 cloudabi32_schedtail(struct thread *td)
165 {
166         struct trapframe *frame = td->td_frame;
167         register_t retval[2];
168
169         /* Return values for processes returning from fork. */
170         if ((td->td_pflags & TDP_FORKING) != 0) {
171                 retval[0] = CLOUDABI_PROCESS_CHILD;
172                 retval[1] = td->td_tid;
173                 copyout(retval, (void *)frame->tf_rcx, sizeof(retval));
174         }
175 }
176
177 int
178 cloudabi32_thread_setregs(struct thread *td,
179     const cloudabi32_threadattr_t *attr, uint32_t tcb)
180 {
181         stack_t stack;
182         uint32_t args[3];
183         void *frameptr;
184         int error;
185
186         /* Perform standard register initialization. */
187         stack.ss_sp = TO_PTR(attr->stack);
188         stack.ss_size = attr->stack_len - sizeof(args);
189         cpu_set_upcall(td, TO_PTR(attr->entry_point), NULL, &stack);
190
191         /*
192          * Copy the arguments for the thread entry point onto the stack
193          * (args[1] and args[2]). Similar to process startup, use the
194          * otherwise unused return address (args[0]) for TLS.
195          */
196         args[0] = tcb;
197         args[1] = td->td_tid;
198         args[2] = attr->argument;
199         frameptr = (void *)td->td_frame->tf_rsp;
200         error = copyout(args, frameptr, sizeof(args));
201         if (error != 0)
202                 return (error);
203
204         return (cpu_set_user_tls(td, frameptr));
205 }
206
207 static struct sysentvec cloudabi32_elf_sysvec = {
208         .sv_size                = CLOUDABI32_SYS_MAXSYSCALL,
209         .sv_table               = cloudabi32_sysent,
210         .sv_fixup               = cloudabi32_fixup_tcb,
211         .sv_name                = "CloudABI ELF32",
212         .sv_coredump            = elf32_coredump,
213         .sv_minuser             = FREEBSD32_MINUSER,
214         .sv_maxuser             = FREEBSD32_MAXUSER,
215         .sv_stackprot           = VM_PROT_READ | VM_PROT_WRITE,
216         .sv_copyout_strings     = cloudabi32_copyout_strings,
217         .sv_setregs             = cloudabi32_proc_setregs,
218         .sv_fixlimit            = ia32_fixlimit,
219         .sv_maxssiz             = &ia32_maxssiz,
220         .sv_flags               = SV_ABI_CLOUDABI | SV_CAPSICUM | SV_IA32 | SV_ILP32,
221         .sv_set_syscall_retval  = cloudabi32_set_syscall_retval,
222         .sv_fetch_syscall_args  = cloudabi32_fetch_syscall_args,
223         .sv_syscallnames        = cloudabi32_syscallnames,
224         .sv_schedtail           = cloudabi32_schedtail,
225 };
226
227 INIT_SYSENTVEC(elf_sysvec, &cloudabi32_elf_sysvec);
228
229 Elf32_Brandinfo cloudabi32_brand = {
230         .brand          = ELFOSABI_CLOUDABI,
231         .machine        = EM_386,
232         .sysvec         = &cloudabi32_elf_sysvec,
233         .flags          = BI_BRAND_ONLY_STATIC,
234 };