View | Details | Raw Unified | Return to bug 247327 | Differences between
and this patch

Collapse All | Expand All

(-)b/sys/amd64/linux32/linux32_machdep.c (-40 / +34 lines)
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
(-)b/sys/compat/linux/linux_emul.c (-1 / +5 lines)
Lines 141-152 linux_set_default_stacksize(struct thread *td, struct proc *p) Link Here
141
void
141
void
142
linux_proc_init(struct thread *td, struct thread *newtd, bool init_thread)
142
linux_proc_init(struct thread *td, struct thread *newtd, bool init_thread)
143
{
143
{
144
	struct linux_emuldata *em;
144
	struct linux_emuldata *em, *old_em;
145
	struct linux_pemuldata *pem;
145
	struct linux_pemuldata *pem;
146
	struct proc *p;
146
	struct proc *p;
147
147
148
	if (newtd != NULL) {
148
	if (newtd != NULL) {
149
		p = newtd->td_proc;
149
		p = newtd->td_proc;
150
		old_em = em_find(td);
150
151
151
		/* non-exec call */
152
		/* non-exec call */
152
		em = malloc(sizeof(*em), M_TEMP, M_WAITOK | M_ZERO);
153
		em = malloc(sizeof(*em), M_TEMP, M_WAITOK | M_ZERO);
Lines 155-164 linux_proc_init(struct thread *td, struct thread *newtd, bool init_thread) Link Here
155
			    newtd->td_tid);
156
			    newtd->td_tid);
156
157
157
			em->em_tid = newtd->td_tid;
158
			em->em_tid = newtd->td_tid;
159
			em->tls_slots_used = old_em != NULL ? old_em->tls_slots_used : 0;
158
		} else {
160
		} else {
159
			LINUX_CTR1(proc_init, "fork newtd(%d)", p->p_pid);
161
			LINUX_CTR1(proc_init, "fork newtd(%d)", p->p_pid);
160
162
161
			em->em_tid = p->p_pid;
163
			em->em_tid = p->p_pid;
164
			em->tls_slots_used = old_em != NULL ? old_em->tls_slots_used : 0;
162
165
163
			pem = malloc(sizeof(*pem), M_LINUX, M_WAITOK | M_ZERO);
166
			pem = malloc(sizeof(*pem), M_LINUX, M_WAITOK | M_ZERO);
164
			sx_init(&pem->pem_sx, "lpemlk");
167
			sx_init(&pem->pem_sx, "lpemlk");
Lines 183-188 linux_proc_init(struct thread *td, struct thread *newtd, bool init_thread) Link Here
183
		em->robust_futexes = NULL;
186
		em->robust_futexes = NULL;
184
		em->child_clear_tid = NULL;
187
		em->child_clear_tid = NULL;
185
		em->child_set_tid = NULL;
188
		em->child_set_tid = NULL;
189
		em->tls_slots_used = 0;
186
190
187
		pem = pem_find(p);
191
		pem = pem_find(p);
188
		KASSERT(pem != NULL, ("proc_init: proc emuldata not found.\n"));
192
		KASSERT(pem != NULL, ("proc_init: proc emuldata not found.\n"));
(-)b/sys/compat/linux/linux_emul.h (-1 / +2 lines)
Lines 46-51 struct linux_emuldata { Link Here
46
	int	em_tid;			/* thread id */
46
	int	em_tid;			/* thread id */
47
47
48
	struct	linux_robust_list_head	*robust_futexes;
48
	struct	linux_robust_list_head	*robust_futexes;
49
50
	int tls_slots_used; /* GDT descriptor count for set_thread_area() on i386/amd64 */
49
};
51
};
50
52
51
struct linux_emuldata	*em_find(struct thread *);
53
struct linux_emuldata	*em_find(struct thread *);
52
- 

Return to bug 247327