Lines 628-633
linux_set_thread_area(struct thread *td,
Link Here
|
628 |
struct linux_set_thread_area_args *args) |
628 |
struct linux_set_thread_area_args *args) |
629 |
{ |
629 |
{ |
630 |
struct l_user_desc info; |
630 |
struct l_user_desc info; |
|
|
631 |
struct linux_emuldata *em; |
631 |
struct pcb *pcb; |
632 |
struct pcb *pcb; |
632 |
int error; |
633 |
int error; |
633 |
|
634 |
|
Lines 635-689
linux_set_thread_area(struct thread *td,
Link Here
|
635 |
if (error) |
636 |
if (error) |
636 |
return (error); |
637 |
return (error); |
637 |
|
638 |
|
638 |
/* |
639 |
/* Linux keeps 3 GDT entries for TLS: glibc uses the first one, |
639 |
* Semantics of Linux version: every thread in the system has array |
640 |
* Wine uses the second and nobody seems to be using the third. |
640 |
* of three TLS descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. |
641 |
* We only maintain 2 such entries, so that suits us just fine. |
641 |
* This syscall loads one of the selected TLS decriptors with a value |
|
|
642 |
* and also loads GDT descriptors 6, 7 and 8 with the content of |
643 |
* the per-thread descriptors. |
644 |
* |
645 |
* Semantics of FreeBSD version: I think we can ignore that Linux has |
646 |
* three per-thread descriptors and use just the first one. |
647 |
* The tls_array[] is used only in [gs]et_thread_area() syscalls and |
648 |
* for loading the GDT descriptors. We use just one GDT descriptor |
649 |
* for TLS, so we will load just one. |
650 |
* |
651 |
* XXX: This doesn't work when a user space process tries to use more |
652 |
* than one TLS segment. Comment in the Linux source says wine might |
653 |
* do this. |
654 |
*/ |
642 |
*/ |
|
|
643 |
if (info.entry_number == -1) { |
644 |
em = em_find(td); |
645 |
switch (em->tls_slots_used) { |
646 |
case 0: |
647 |
info.entry_number = GUGS32_SEL; |
648 |
em->tls_slots_used++; |
649 |
break; |
650 |
case 1: |
651 |
info.entry_number = GUFS32_SEL; |
652 |
em->tls_slots_used++; |
653 |
break; |
654 |
default: |
655 |
return (ESRCH); |
656 |
} |
657 |
|
658 |
/* We have to copy out entry_number. */ |
659 |
error = copyout(&info, args->desc, sizeof(struct l_user_desc)); |
660 |
if (error) |
661 |
return (error); |
662 |
} |
655 |
|
663 |
|
656 |
/* |
|
|
657 |
* GLIBC reads current %gs and call set_thread_area() with it. |
658 |
* We should let GUDATA_SEL and GUGS32_SEL proceed as well because |
659 |
* we use these segments. |
660 |
*/ |
661 |
switch (info.entry_number) { |
664 |
switch (info.entry_number) { |
662 |
case GUGS32_SEL: |
665 |
case GUGS32_SEL: |
663 |
case GUDATA_SEL: |
666 |
pcb = td->td_pcb; |
664 |
case 6: |
667 |
update_pcb_bases(pcb); |
665 |
case -1: |
668 |
pcb->pcb_gsbase = (register_t)info.base_addr; |
666 |
info.entry_number = GUGS32_SEL; |
669 |
update_gdt_gsbase(td, info.base_addr); |
|
|
670 |
break; |
671 |
case GUFS32_SEL: |
672 |
pcb = td->td_pcb; |
673 |
update_pcb_bases(pcb); |
674 |
pcb->pcb_fsbase = (register_t)info.base_addr; |
675 |
update_gdt_fsbase(td, info.base_addr); |
667 |
break; |
676 |
break; |
668 |
default: |
677 |
default: |
669 |
return (EINVAL); |
678 |
return (EINVAL); |
670 |
} |
679 |
} |
671 |
|
680 |
|
672 |
/* |
|
|
673 |
* We have to copy out the GDT entry we use. |
674 |
* |
675 |
* XXX: What if a user space program does not check the return value |
676 |
* and tries to use 6, 7 or 8? |
677 |
*/ |
678 |
error = copyout(&info, args->desc, sizeof(struct l_user_desc)); |
679 |
if (error) |
680 |
return (error); |
681 |
|
682 |
pcb = td->td_pcb; |
683 |
update_pcb_bases(pcb); |
684 |
pcb->pcb_gsbase = (register_t)info.base_addr; |
685 |
update_gdt_gsbase(td, info.base_addr); |
686 |
|
687 |
return (0); |
681 |
return (0); |
688 |
} |
682 |
} |
689 |
|
683 |
|