MCPcopy Create free account
hub / github.com/F-Stack/f-stack / linux_set_thread_area

Function linux_set_thread_area

freebsd/i386/linux/linux_machdep.c:568–638  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

566}
567
568int
569linux_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);

Callers

nothing calls this directly

Calls 6

copyinFunction · 0.50
copyoutFunction · 0.50
memcpyFunction · 0.50
critical_enterFunction · 0.50
load_gsFunction · 0.50
critical_exitFunction · 0.50

Tested by

no test coverage detected