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