xref: /freebsd/sys/amd64/linux32/linux32_machdep.c (revision 73577bf01de5c4677dc54d97f93310286c254780)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2004 Tim J. Robbins
5  * Copyright (c) 2002 Doug Rabson
6  * Copyright (c) 2000 Marcel Moolenaar
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer
14  *    in this position and unchanged.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include "opt_compat.h"
37 
38 #include <sys/param.h>
39 #include <sys/capsicum.h>
40 #include <sys/clock.h>
41 #include <sys/fcntl.h>
42 #include <sys/file.h>
43 #include <sys/imgact.h>
44 #include <sys/kernel.h>
45 #include <sys/limits.h>
46 #include <sys/lock.h>
47 #include <sys/malloc.h>
48 #include <sys/mman.h>
49 #include <sys/mutex.h>
50 #include <sys/priv.h>
51 #include <sys/proc.h>
52 #include <sys/resource.h>
53 #include <sys/resourcevar.h>
54 #include <sys/syscallsubr.h>
55 #include <sys/sysproto.h>
56 #include <sys/systm.h>
57 #include <sys/unistd.h>
58 #include <sys/wait.h>
59 
60 #include <machine/frame.h>
61 #include <machine/md_var.h>
62 #include <machine/pcb.h>
63 #include <machine/psl.h>
64 #include <machine/segments.h>
65 #include <machine/specialreg.h>
66 #include <x86/ifunc.h>
67 
68 #include <vm/pmap.h>
69 #include <vm/vm.h>
70 #include <vm/vm_map.h>
71 
72 #include <compat/freebsd32/freebsd32_util.h>
73 #include <amd64/linux32/linux.h>
74 #include <amd64/linux32/linux32_proto.h>
75 #include <compat/linux/linux_emul.h>
76 #include <compat/linux/linux_ipc.h>
77 #include <compat/linux/linux_misc.h>
78 #include <compat/linux/linux_mmap.h>
79 #include <compat/linux/linux_signal.h>
80 #include <compat/linux/linux_util.h>
81 
82 static void	bsd_to_linux_rusage(struct rusage *ru, struct l_rusage *lru);
83 
84 struct l_old_select_argv {
85 	l_int		nfds;
86 	l_uintptr_t	readfds;
87 	l_uintptr_t	writefds;
88 	l_uintptr_t	exceptfds;
89 	l_uintptr_t	timeout;
90 } __packed;
91 
92 static void
93 bsd_to_linux_rusage(struct rusage *ru, struct l_rusage *lru)
94 {
95 
96 	lru->ru_utime.tv_sec = ru->ru_utime.tv_sec;
97 	lru->ru_utime.tv_usec = ru->ru_utime.tv_usec;
98 	lru->ru_stime.tv_sec = ru->ru_stime.tv_sec;
99 	lru->ru_stime.tv_usec = ru->ru_stime.tv_usec;
100 	lru->ru_maxrss = ru->ru_maxrss;
101 	lru->ru_ixrss = ru->ru_ixrss;
102 	lru->ru_idrss = ru->ru_idrss;
103 	lru->ru_isrss = ru->ru_isrss;
104 	lru->ru_minflt = ru->ru_minflt;
105 	lru->ru_majflt = ru->ru_majflt;
106 	lru->ru_nswap = ru->ru_nswap;
107 	lru->ru_inblock = ru->ru_inblock;
108 	lru->ru_oublock = ru->ru_oublock;
109 	lru->ru_msgsnd = ru->ru_msgsnd;
110 	lru->ru_msgrcv = ru->ru_msgrcv;
111 	lru->ru_nsignals = ru->ru_nsignals;
112 	lru->ru_nvcsw = ru->ru_nvcsw;
113 	lru->ru_nivcsw = ru->ru_nivcsw;
114 }
115 
116 int
117 linux_copyout_rusage(struct rusage *ru, void *uaddr)
118 {
119 	struct l_rusage lru;
120 
121 	bsd_to_linux_rusage(ru, &lru);
122 
123 	return (copyout(&lru, uaddr, sizeof(struct l_rusage)));
124 }
125 
126 int
127 linux_execve(struct thread *td, struct linux_execve_args *args)
128 {
129 	struct image_args eargs;
130 	char *path;
131 	int error;
132 
133 	LCONVPATHEXIST(td, args->path, &path);
134 
135 	error = freebsd32_exec_copyin_args(&eargs, path, UIO_SYSSPACE,
136 	    args->argp, args->envp);
137 	free(path, M_TEMP);
138 	if (error == 0)
139 		error = linux_common_execve(td, &eargs);
140 	return (error);
141 }
142 
143 CTASSERT(sizeof(struct l_iovec32) == 8);
144 
145 int
146 linux32_copyinuio(struct l_iovec32 *iovp, l_ulong iovcnt, struct uio **uiop)
147 {
148 	struct l_iovec32 iov32;
149 	struct iovec *iov;
150 	struct uio *uio;
151 	uint32_t iovlen;
152 	int error, i;
153 
154 	*uiop = NULL;
155 	if (iovcnt > UIO_MAXIOV)
156 		return (EINVAL);
157 	iovlen = iovcnt * sizeof(struct iovec);
158 	uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK);
159 	iov = (struct iovec *)(uio + 1);
160 	for (i = 0; i < iovcnt; i++) {
161 		error = copyin(&iovp[i], &iov32, sizeof(struct l_iovec32));
162 		if (error) {
163 			free(uio, M_IOV);
164 			return (error);
165 		}
166 		iov[i].iov_base = PTRIN(iov32.iov_base);
167 		iov[i].iov_len = iov32.iov_len;
168 	}
169 	uio->uio_iov = iov;
170 	uio->uio_iovcnt = iovcnt;
171 	uio->uio_segflg = UIO_USERSPACE;
172 	uio->uio_offset = -1;
173 	uio->uio_resid = 0;
174 	for (i = 0; i < iovcnt; i++) {
175 		if (iov->iov_len > INT_MAX - uio->uio_resid) {
176 			free(uio, M_IOV);
177 			return (EINVAL);
178 		}
179 		uio->uio_resid += iov->iov_len;
180 		iov++;
181 	}
182 	*uiop = uio;
183 	return (0);
184 }
185 
186 int
187 linux32_copyiniov(struct l_iovec32 *iovp32, l_ulong iovcnt, struct iovec **iovp,
188     int error)
189 {
190 	struct l_iovec32 iov32;
191 	struct iovec *iov;
192 	uint32_t iovlen;
193 	int i;
194 
195 	*iovp = NULL;
196 	if (iovcnt > UIO_MAXIOV)
197 		return (error);
198 	iovlen = iovcnt * sizeof(struct iovec);
199 	iov = malloc(iovlen, M_IOV, M_WAITOK);
200 	for (i = 0; i < iovcnt; i++) {
201 		error = copyin(&iovp32[i], &iov32, sizeof(struct l_iovec32));
202 		if (error) {
203 			free(iov, M_IOV);
204 			return (error);
205 		}
206 		iov[i].iov_base = PTRIN(iov32.iov_base);
207 		iov[i].iov_len = iov32.iov_len;
208 	}
209 	*iovp = iov;
210 	return(0);
211 
212 }
213 
214 int
215 linux_readv(struct thread *td, struct linux_readv_args *uap)
216 {
217 	struct uio *auio;
218 	int error;
219 
220 	error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio);
221 	if (error)
222 		return (error);
223 	error = kern_readv(td, uap->fd, auio);
224 	free(auio, M_IOV);
225 	return (error);
226 }
227 
228 int
229 linux_writev(struct thread *td, struct linux_writev_args *uap)
230 {
231 	struct uio *auio;
232 	int error;
233 
234 	error = linux32_copyinuio(uap->iovp, uap->iovcnt, &auio);
235 	if (error)
236 		return (error);
237 	error = kern_writev(td, uap->fd, auio);
238 	free(auio, M_IOV);
239 	return (error);
240 }
241 
242 struct l_ipc_kludge {
243 	l_uintptr_t msgp;
244 	l_long msgtyp;
245 } __packed;
246 
247 int
248 linux_ipc(struct thread *td, struct linux_ipc_args *args)
249 {
250 
251 	switch (args->what & 0xFFFF) {
252 	case LINUX_SEMOP: {
253 		struct linux_semop_args a;
254 
255 		a.semid = args->arg1;
256 		a.tsops = PTRIN(args->ptr);
257 		a.nsops = args->arg2;
258 		return (linux_semop(td, &a));
259 	}
260 	case LINUX_SEMGET: {
261 		struct linux_semget_args a;
262 
263 		a.key = args->arg1;
264 		a.nsems = args->arg2;
265 		a.semflg = args->arg3;
266 		return (linux_semget(td, &a));
267 	}
268 	case LINUX_SEMCTL: {
269 		struct linux_semctl_args a;
270 		int error;
271 
272 		a.semid = args->arg1;
273 		a.semnum = args->arg2;
274 		a.cmd = args->arg3;
275 		error = copyin(PTRIN(args->ptr), &a.arg, sizeof(a.arg));
276 		if (error)
277 			return (error);
278 		return (linux_semctl(td, &a));
279 	}
280 	case LINUX_MSGSND: {
281 		struct linux_msgsnd_args a;
282 
283 		a.msqid = args->arg1;
284 		a.msgp = PTRIN(args->ptr);
285 		a.msgsz = args->arg2;
286 		a.msgflg = args->arg3;
287 		return (linux_msgsnd(td, &a));
288 	}
289 	case LINUX_MSGRCV: {
290 		struct linux_msgrcv_args a;
291 
292 		a.msqid = args->arg1;
293 		a.msgsz = args->arg2;
294 		a.msgflg = args->arg3;
295 		if ((args->what >> 16) == 0) {
296 			struct l_ipc_kludge tmp;
297 			int error;
298 
299 			if (args->ptr == 0)
300 				return (EINVAL);
301 			error = copyin(PTRIN(args->ptr), &tmp, sizeof(tmp));
302 			if (error)
303 				return (error);
304 			a.msgp = PTRIN(tmp.msgp);
305 			a.msgtyp = tmp.msgtyp;
306 		} else {
307 			a.msgp = PTRIN(args->ptr);
308 			a.msgtyp = args->arg5;
309 		}
310 		return (linux_msgrcv(td, &a));
311 	}
312 	case LINUX_MSGGET: {
313 		struct linux_msgget_args a;
314 
315 		a.key = args->arg1;
316 		a.msgflg = args->arg2;
317 		return (linux_msgget(td, &a));
318 	}
319 	case LINUX_MSGCTL: {
320 		struct linux_msgctl_args a;
321 
322 		a.msqid = args->arg1;
323 		a.cmd = args->arg2;
324 		a.buf = PTRIN(args->ptr);
325 		return (linux_msgctl(td, &a));
326 	}
327 	case LINUX_SHMAT: {
328 		struct linux_shmat_args a;
329 		l_uintptr_t addr;
330 		int error;
331 
332 		a.shmid = args->arg1;
333 		a.shmaddr = PTRIN(args->ptr);
334 		a.shmflg = args->arg2;
335 		error = linux_shmat(td, &a);
336 		if (error != 0)
337 			return (error);
338 		addr = td->td_retval[0];
339 		error = copyout(&addr, PTRIN(args->arg3), sizeof(addr));
340 		td->td_retval[0] = 0;
341 		return (error);
342 	}
343 	case LINUX_SHMDT: {
344 		struct linux_shmdt_args a;
345 
346 		a.shmaddr = PTRIN(args->ptr);
347 		return (linux_shmdt(td, &a));
348 	}
349 	case LINUX_SHMGET: {
350 		struct linux_shmget_args a;
351 
352 		a.key = args->arg1;
353 		a.size = args->arg2;
354 		a.shmflg = args->arg3;
355 		return (linux_shmget(td, &a));
356 	}
357 	case LINUX_SHMCTL: {
358 		struct linux_shmctl_args a;
359 
360 		a.shmid = args->arg1;
361 		a.cmd = args->arg2;
362 		a.buf = PTRIN(args->ptr);
363 		return (linux_shmctl(td, &a));
364 	}
365 	default:
366 		break;
367 	}
368 
369 	return (EINVAL);
370 }
371 
372 int
373 linux_old_select(struct thread *td, struct linux_old_select_args *args)
374 {
375 	struct l_old_select_argv linux_args;
376 	struct linux_select_args newsel;
377 	int error;
378 
379 	error = copyin(args->ptr, &linux_args, sizeof(linux_args));
380 	if (error)
381 		return (error);
382 
383 	newsel.nfds = linux_args.nfds;
384 	newsel.readfds = PTRIN(linux_args.readfds);
385 	newsel.writefds = PTRIN(linux_args.writefds);
386 	newsel.exceptfds = PTRIN(linux_args.exceptfds);
387 	newsel.timeout = PTRIN(linux_args.timeout);
388 	return (linux_select(td, &newsel));
389 }
390 
391 int
392 linux_set_cloned_tls(struct thread *td, void *desc)
393 {
394 	struct user_segment_descriptor sd;
395 	struct l_user_desc info;
396 	struct pcb *pcb;
397 	int error;
398 	int a[2];
399 
400 	error = copyin(desc, &info, sizeof(struct l_user_desc));
401 	if (error) {
402 		linux_msg(td, "set_cloned_tls copyin info failed!");
403 	} else {
404 		/* We might copy out the entry_number as GUGS32_SEL. */
405 		info.entry_number = GUGS32_SEL;
406 		error = copyout(&info, desc, sizeof(struct l_user_desc));
407 		if (error)
408 			linux_msg(td, "set_cloned_tls copyout info failed!");
409 
410 		a[0] = LINUX_LDT_entry_a(&info);
411 		a[1] = LINUX_LDT_entry_b(&info);
412 
413 		memcpy(&sd, &a, sizeof(a));
414 		pcb = td->td_pcb;
415 		pcb->pcb_gsbase = (register_t)info.base_addr;
416 		td->td_frame->tf_gs = GSEL(GUGS32_SEL, SEL_UPL);
417 		set_pcb_flags(pcb, PCB_32BIT);
418 	}
419 
420 	return (error);
421 }
422 
423 int
424 linux_set_upcall_kse(struct thread *td, register_t stack)
425 {
426 
427 	if (stack)
428 		td->td_frame->tf_rsp = stack;
429 
430 	/*
431 	 * The newly created Linux thread returns
432 	 * to the user space by the same path that a parent do.
433 	 */
434 	td->td_frame->tf_rax = 0;
435 	return (0);
436 }
437 
438 int
439 linux_mmap2(struct thread *td, struct linux_mmap2_args *args)
440 {
441 
442 	return (linux_mmap_common(td, PTROUT(args->addr), args->len, args->prot,
443 		args->flags, args->fd, (uint64_t)(uint32_t)args->pgoff *
444 		PAGE_SIZE));
445 }
446 
447 int
448 linux_mmap(struct thread *td, struct linux_mmap_args *args)
449 {
450 	int error;
451 	struct l_mmap_argv linux_args;
452 
453 	error = copyin(args->ptr, &linux_args, sizeof(linux_args));
454 	if (error)
455 		return (error);
456 
457 	return (linux_mmap_common(td, linux_args.addr, linux_args.len,
458 	    linux_args.prot, linux_args.flags, linux_args.fd,
459 	    (uint32_t)linux_args.pgoff));
460 }
461 
462 int
463 linux_mprotect(struct thread *td, struct linux_mprotect_args *uap)
464 {
465 
466 	return (linux_mprotect_common(td, PTROUT(uap->addr), uap->len, uap->prot));
467 }
468 
469 int
470 linux_madvise(struct thread *td, struct linux_madvise_args *uap)
471 {
472 
473 	return (linux_madvise_common(td, PTROUT(uap->addr), uap->len, uap->behav));
474 }
475 
476 int
477 linux_iopl(struct thread *td, struct linux_iopl_args *args)
478 {
479 	int error;
480 
481 	if (args->level < 0 || args->level > 3)
482 		return (EINVAL);
483 	if ((error = priv_check(td, PRIV_IO)) != 0)
484 		return (error);
485 	if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
486 		return (error);
487 	td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) |
488 	    (args->level * (PSL_IOPL / 3));
489 
490 	return (0);
491 }
492 
493 int
494 linux_sigaction(struct thread *td, struct linux_sigaction_args *args)
495 {
496 	l_osigaction_t osa;
497 	l_sigaction_t act, oact;
498 	int error;
499 
500 	if (args->nsa != NULL) {
501 		error = copyin(args->nsa, &osa, sizeof(l_osigaction_t));
502 		if (error)
503 			return (error);
504 		act.lsa_handler = osa.lsa_handler;
505 		act.lsa_flags = osa.lsa_flags;
506 		act.lsa_restorer = osa.lsa_restorer;
507 		LINUX_SIGEMPTYSET(act.lsa_mask);
508 		act.lsa_mask.__mask = osa.lsa_mask;
509 	}
510 
511 	error = linux_do_sigaction(td, args->sig, args->nsa ? &act : NULL,
512 	    args->osa ? &oact : NULL);
513 
514 	if (args->osa != NULL && !error) {
515 		osa.lsa_handler = oact.lsa_handler;
516 		osa.lsa_flags = oact.lsa_flags;
517 		osa.lsa_restorer = oact.lsa_restorer;
518 		osa.lsa_mask = oact.lsa_mask.__mask;
519 		error = copyout(&osa, args->osa, sizeof(l_osigaction_t));
520 	}
521 
522 	return (error);
523 }
524 
525 /*
526  * Linux has two extra args, restart and oldmask.  We don't use these,
527  * but it seems that "restart" is actually a context pointer that
528  * enables the signal to happen with a different register set.
529  */
530 int
531 linux_sigsuspend(struct thread *td, struct linux_sigsuspend_args *args)
532 {
533 	sigset_t sigmask;
534 	l_sigset_t mask;
535 
536 	LINUX_SIGEMPTYSET(mask);
537 	mask.__mask = args->mask;
538 	linux_to_bsd_sigset(&mask, &sigmask);
539 	return (kern_sigsuspend(td, sigmask));
540 }
541 
542 int
543 linux_rt_sigsuspend(struct thread *td, struct linux_rt_sigsuspend_args *uap)
544 {
545 	l_sigset_t lmask;
546 	sigset_t sigmask;
547 	int error;
548 
549 	if (uap->sigsetsize != sizeof(l_sigset_t))
550 		return (EINVAL);
551 
552 	error = copyin(uap->newset, &lmask, sizeof(l_sigset_t));
553 	if (error)
554 		return (error);
555 
556 	linux_to_bsd_sigset(&lmask, &sigmask);
557 	return (kern_sigsuspend(td, sigmask));
558 }
559 
560 int
561 linux_pause(struct thread *td, struct linux_pause_args *args)
562 {
563 	struct proc *p = td->td_proc;
564 	sigset_t sigmask;
565 
566 	PROC_LOCK(p);
567 	sigmask = td->td_sigmask;
568 	PROC_UNLOCK(p);
569 	return (kern_sigsuspend(td, sigmask));
570 }
571 
572 int
573 linux_sigaltstack(struct thread *td, struct linux_sigaltstack_args *uap)
574 {
575 	stack_t ss, oss;
576 	l_stack_t lss;
577 	int error;
578 
579 	if (uap->uss != NULL) {
580 		error = copyin(uap->uss, &lss, sizeof(l_stack_t));
581 		if (error)
582 			return (error);
583 
584 		ss.ss_sp = PTRIN(lss.ss_sp);
585 		ss.ss_size = lss.ss_size;
586 		ss.ss_flags = linux_to_bsd_sigaltstack(lss.ss_flags);
587 	}
588 	error = kern_sigaltstack(td, (uap->uss != NULL) ? &ss : NULL,
589 	    (uap->uoss != NULL) ? &oss : NULL);
590 	if (!error && uap->uoss != NULL) {
591 		lss.ss_sp = PTROUT(oss.ss_sp);
592 		lss.ss_size = oss.ss_size;
593 		lss.ss_flags = bsd_to_linux_sigaltstack(oss.ss_flags);
594 		error = copyout(&lss, uap->uoss, sizeof(l_stack_t));
595 	}
596 
597 	return (error);
598 }
599 
600 int
601 linux_gettimeofday(struct thread *td, struct linux_gettimeofday_args *uap)
602 {
603 	struct timeval atv;
604 	l_timeval atv32;
605 	struct timezone rtz;
606 	int error = 0;
607 
608 	if (uap->tp) {
609 		microtime(&atv);
610 		atv32.tv_sec = atv.tv_sec;
611 		atv32.tv_usec = atv.tv_usec;
612 		error = copyout(&atv32, uap->tp, sizeof(atv32));
613 	}
614 	if (error == 0 && uap->tzp != NULL) {
615 		rtz.tz_minuteswest = 0;
616 		rtz.tz_dsttime = 0;
617 		error = copyout(&rtz, uap->tzp, sizeof(rtz));
618 	}
619 	return (error);
620 }
621 
622 int
623 linux_settimeofday(struct thread *td, struct linux_settimeofday_args *uap)
624 {
625 	l_timeval atv32;
626 	struct timeval atv, *tvp;
627 	struct timezone atz, *tzp;
628 	int error;
629 
630 	if (uap->tp) {
631 		error = copyin(uap->tp, &atv32, sizeof(atv32));
632 		if (error)
633 			return (error);
634 		atv.tv_sec = atv32.tv_sec;
635 		atv.tv_usec = atv32.tv_usec;
636 		tvp = &atv;
637 	} else
638 		tvp = NULL;
639 	if (uap->tzp) {
640 		error = copyin(uap->tzp, &atz, sizeof(atz));
641 		if (error)
642 			return (error);
643 		tzp = &atz;
644 	} else
645 		tzp = NULL;
646 	return (kern_settimeofday(td, tvp, tzp));
647 }
648 
649 int
650 linux_getrusage(struct thread *td, struct linux_getrusage_args *uap)
651 {
652 	struct rusage s;
653 	int error;
654 
655 	error = kern_getrusage(td, uap->who, &s);
656 	if (error != 0)
657 		return (error);
658 	if (uap->rusage != NULL)
659 		error = linux_copyout_rusage(&s, uap->rusage);
660 	return (error);
661 }
662 
663 int
664 linux_set_thread_area(struct thread *td,
665     struct linux_set_thread_area_args *args)
666 {
667 	struct l_user_desc info;
668 	struct user_segment_descriptor sd;
669 	struct pcb *pcb;
670 	int a[2];
671 	int error;
672 
673 	error = copyin(args->desc, &info, sizeof(struct l_user_desc));
674 	if (error)
675 		return (error);
676 
677 	/*
678 	 * Semantics of Linux version: every thread in the system has array
679 	 * of three TLS descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown.
680 	 * This syscall loads one of the selected TLS decriptors with a value
681 	 * and also loads GDT descriptors 6, 7 and 8 with the content of
682 	 * the per-thread descriptors.
683 	 *
684 	 * Semantics of FreeBSD version: I think we can ignore that Linux has
685 	 * three per-thread descriptors and use just the first one.
686 	 * The tls_array[] is used only in [gs]et_thread_area() syscalls and
687 	 * for loading the GDT descriptors. We use just one GDT descriptor
688 	 * for TLS, so we will load just one.
689 	 *
690 	 * XXX: This doesn't work when a user space process tries to use more
691 	 * than one TLS segment. Comment in the Linux source says wine might
692 	 * do this.
693 	 */
694 
695 	/*
696 	 * GLIBC reads current %gs and call set_thread_area() with it.
697 	 * We should let GUDATA_SEL and GUGS32_SEL proceed as well because
698 	 * we use these segments.
699 	 */
700 	switch (info.entry_number) {
701 	case GUGS32_SEL:
702 	case GUDATA_SEL:
703 	case 6:
704 	case -1:
705 		info.entry_number = GUGS32_SEL;
706 		break;
707 	default:
708 		return (EINVAL);
709 	}
710 
711 	/*
712 	 * We have to copy out the GDT entry we use.
713 	 *
714 	 * XXX: What if a user space program does not check the return value
715 	 * and tries to use 6, 7 or 8?
716 	 */
717 	error = copyout(&info, args->desc, sizeof(struct l_user_desc));
718 	if (error)
719 		return (error);
720 
721 	if (LINUX_LDT_empty(&info)) {
722 		a[0] = 0;
723 		a[1] = 0;
724 	} else {
725 		a[0] = LINUX_LDT_entry_a(&info);
726 		a[1] = LINUX_LDT_entry_b(&info);
727 	}
728 
729 	memcpy(&sd, &a, sizeof(a));
730 	pcb = td->td_pcb;
731 	pcb->pcb_gsbase = (register_t)info.base_addr;
732 	set_pcb_flags(pcb, PCB_32BIT);
733 	update_gdt_gsbase(td, info.base_addr);
734 
735 	return (0);
736 }
737 
738 int futex_xchgl_nosmap(int oparg, uint32_t *uaddr, int *oldval);
739 int futex_xchgl_smap(int oparg, uint32_t *uaddr, int *oldval);
740 DEFINE_IFUNC(, int, futex_xchgl, (int, uint32_t *, int *))
741 {
742 
743 	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
744 	    futex_xchgl_smap : futex_xchgl_nosmap);
745 }
746 
747 int futex_addl_nosmap(int oparg, uint32_t *uaddr, int *oldval);
748 int futex_addl_smap(int oparg, uint32_t *uaddr, int *oldval);
749 DEFINE_IFUNC(, int, futex_addl, (int, uint32_t *, int *))
750 {
751 
752 	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
753 	    futex_addl_smap : futex_addl_nosmap);
754 }
755 
756 int futex_orl_nosmap(int oparg, uint32_t *uaddr, int *oldval);
757 int futex_orl_smap(int oparg, uint32_t *uaddr, int *oldval);
758 DEFINE_IFUNC(, int, futex_orl, (int, uint32_t *, int *))
759 {
760 
761 	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
762 	    futex_orl_smap : futex_orl_nosmap);
763 }
764 
765 int futex_andl_nosmap(int oparg, uint32_t *uaddr, int *oldval);
766 int futex_andl_smap(int oparg, uint32_t *uaddr, int *oldval);
767 DEFINE_IFUNC(, int, futex_andl, (int, uint32_t *, int *))
768 {
769 
770 	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
771 	    futex_andl_smap : futex_andl_nosmap);
772 }
773 
774 int futex_xorl_nosmap(int oparg, uint32_t *uaddr, int *oldval);
775 int futex_xorl_smap(int oparg, uint32_t *uaddr, int *oldval);
776 DEFINE_IFUNC(, int, futex_xorl, (int, uint32_t *, int *))
777 {
778 
779 	return ((cpu_stdext_feature & CPUID_STDEXT_SMAP) != 0 ?
780 	    futex_xorl_smap : futex_xorl_nosmap);
781 }
782