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