| 566 | } |
| 567 | |
| 568 | int |
| 569 | linux_set_thread_area(struct thread *td, struct linux_set_thread_area_args *args) |
| 570 | { |
| 571 | struct l_user_desc info; |
| 572 | int error; |
| 573 | int idx; |
| 574 | int a[2]; |
| 575 | struct segment_descriptor sd; |
| 576 | |
| 577 | error = copyin(args->desc, &info, sizeof(struct l_user_desc)); |
| 578 | if (error) |
| 579 | return (error); |
| 580 | |
| 581 | idx = info.entry_number; |
| 582 | /* |
| 583 | * Semantics of Linux version: every thread in the system has array of |
| 584 | * 3 tls descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. This |
| 585 | * syscall loads one of the selected tls decriptors with a value and |
| 586 | * also loads GDT descriptors 6, 7 and 8 with the content of the |
| 587 | * per-thread descriptors. |
| 588 | * |
| 589 | * Semantics of FreeBSD version: I think we can ignore that Linux has 3 |
| 590 | * per-thread descriptors and use just the 1st one. The tls_array[] |
| 591 | * is used only in set/get-thread_area() syscalls and for loading the |
| 592 | * GDT descriptors. In FreeBSD we use just one GDT descriptor for TLS |
| 593 | * so we will load just one. |
| 594 | * |
| 595 | * XXX: this doesn't work when a user space process tries to use more |
| 596 | * than 1 TLS segment. Comment in the Linux sources says wine might do |
| 597 | * this. |
| 598 | */ |
| 599 | |
| 600 | /* |
| 601 | * we support just GLIBC TLS now |
| 602 | * we should let 3 proceed as well because we use this segment so |
| 603 | * if code does two subsequent calls it should succeed |
| 604 | */ |
| 605 | if (idx != 6 && idx != -1 && idx != 3) |
| 606 | return (EINVAL); |
| 607 | |
| 608 | /* |
| 609 | * we have to copy out the GDT entry we use |
| 610 | * FreeBSD uses GDT entry #3 for storing %gs so load that |
| 611 | * |
| 612 | * XXX: what if a user space program doesn't check this value and tries |
| 613 | * to use 6, 7 or 8? |
| 614 | */ |
| 615 | idx = info.entry_number = 3; |
| 616 | error = copyout(&info, args->desc, sizeof(struct l_user_desc)); |
| 617 | if (error) |
| 618 | return (error); |
| 619 | |
| 620 | if (LINUX_LDT_empty(&info)) { |
| 621 | a[0] = 0; |
| 622 | a[1] = 0; |
| 623 | } else { |
| 624 | a[0] = LINUX_LDT_entry_a(&info); |
| 625 | a[1] = LINUX_LDT_entry_b(&info); |
nothing calls this directly
no test coverage detected