FreeBSD Bugzilla – Attachment 248191 Details for
Bug 247327
i386 linuxulator doesn't support more than one LDT
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
comment cleanup
0001-linux-4-use-GUFS32_SEL-for-the-second-GDT-descriptor.patch (text/plain), 4.57 KB, created by
Alex S
on 2024-02-04 23:19:19 UTC
(
hide
)
Description:
comment cleanup
Filename:
MIME Type:
Creator:
Alex S
Created:
2024-02-04 23:19:19 UTC
Size:
4.57 KB
patch
obsolete
>From a5ed94198cfef4bfccf138dd232d6edb2f07512e Mon Sep 17 00:00:00 2001 >From: Alex S <iwtcex@gmail.com> >Date: Sun, 4 Feb 2024 03:09:03 +0300 >Subject: [PATCH] linux(4): use GUFS32_SEL for the second GDT descriptor in > linux_set_thread_area > >We maintain 2 descriptors entries that are suitable for TLS on AMD64, >not just one. This partially unbreaks i386 Wine. >--- > sys/amd64/linux32/linux32_machdep.c | 75 ++++++++++++++--------------- > sys/compat/linux/linux_emul.c | 1 + > sys/compat/linux/linux_emul.h | 2 + > 3 files changed, 38 insertions(+), 40 deletions(-) > >diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c >index 9746c4bd7..cee845826 100644 >--- a/sys/amd64/linux32/linux32_machdep.c >+++ b/sys/amd64/linux32/linux32_machdep.c >@@ -623,11 +623,13 @@ linux_getrusage(struct thread *td, struct linux_getrusage_args *uap) > return (error); > } > >+//TODO: adjust linux_set_cloned_tls? > int > linux_set_thread_area(struct thread *td, > struct linux_set_thread_area_args *args) > { > struct l_user_desc info; >+ struct linux_emuldata *em; > struct pcb *pcb; > int error; > >@@ -635,55 +637,48 @@ linux_set_thread_area(struct thread *td, > if (error) > return (error); > >- /* >- * Semantics of Linux version: every thread in the system has array >- * of three TLS descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. >- * This syscall loads one of the selected TLS decriptors with a value >- * and also loads GDT descriptors 6, 7 and 8 with the content of >- * the per-thread descriptors. >- * >- * Semantics of FreeBSD version: I think we can ignore that Linux has >- * three per-thread descriptors and use just the first one. >- * The tls_array[] is used only in [gs]et_thread_area() syscalls and >- * for loading the GDT descriptors. We use just one GDT descriptor >- * for TLS, so we will load just one. >- * >- * XXX: This doesn't work when a user space process tries to use more >- * than one TLS segment. Comment in the Linux source says wine might >- * do this. >+ /* Linux keeps 3 GDT entries for TLS: glibc uses the first one, >+ * Wine uses the second and nobody seems to be using the third. >+ * We only maintain 2 such entries, so that suits us just fine. > */ >+ if (info.entry_number == -1) { >+ em = em_find(td); >+ switch (em->tls_slots_used) { >+ case 0: >+ info.entry_number = GUGS32_SEL; >+ em->tls_slots_used++; >+ break; >+ case 1: >+ info.entry_number = GUFS32_SEL; >+ em->tls_slots_used++; >+ break; >+ default: >+ return (ESRCH); >+ } >+ >+ /* We have to copy out entry_number. */ >+ error = copyout(&info, args->desc, sizeof(struct l_user_desc)); >+ if (error) >+ return (error); >+ } > >- /* >- * GLIBC reads current %gs and call set_thread_area() with it. >- * We should let GUDATA_SEL and GUGS32_SEL proceed as well because >- * we use these segments. >- */ > switch (info.entry_number) { > case GUGS32_SEL: >- case GUDATA_SEL: >- case 6: >- case -1: >- info.entry_number = GUGS32_SEL; >+ pcb = td->td_pcb; >+ update_pcb_bases(pcb); >+ pcb->pcb_gsbase = (register_t)info.base_addr; >+ update_gdt_gsbase(td, info.base_addr); >+ break; >+ case GUFS32_SEL: >+ pcb = td->td_pcb; >+ update_pcb_bases(pcb); >+ pcb->pcb_fsbase = (register_t)info.base_addr; >+ update_gdt_fsbase(td, info.base_addr); > break; > default: > return (EINVAL); > } > >- /* >- * We have to copy out the GDT entry we use. >- * >- * XXX: What if a user space program does not check the return value >- * and tries to use 6, 7 or 8? >- */ >- error = copyout(&info, args->desc, sizeof(struct l_user_desc)); >- if (error) >- return (error); >- >- pcb = td->td_pcb; >- update_pcb_bases(pcb); >- pcb->pcb_gsbase = (register_t)info.base_addr; >- update_gdt_gsbase(td, info.base_addr); >- > return (0); > } > >diff --git a/sys/compat/linux/linux_emul.c b/sys/compat/linux/linux_emul.c >index 08510fc29..511e0535c 100644 >--- a/sys/compat/linux/linux_emul.c >+++ b/sys/compat/linux/linux_emul.c >@@ -183,6 +183,7 @@ linux_proc_init(struct thread *td, struct thread *newtd, bool init_thread) > em->robust_futexes = NULL; > em->child_clear_tid = NULL; > em->child_set_tid = NULL; >+ em->tls_slots_used = 0; > > pem = pem_find(p); > KASSERT(pem != NULL, ("proc_init: proc emuldata not found.\n")); >diff --git a/sys/compat/linux/linux_emul.h b/sys/compat/linux/linux_emul.h >index fde97c018..0b2b8c71e 100644 >--- a/sys/compat/linux/linux_emul.h >+++ b/sys/compat/linux/linux_emul.h >@@ -46,6 +46,8 @@ struct linux_emuldata { > int em_tid; /* thread id */ > > struct linux_robust_list_head *robust_futexes; >+ >+ int tls_slots_used; /* GDT descriptor count for set_thread_area() on i386/amd64 */ > }; > > struct linux_emuldata *em_find(struct thread *); >-- >2.42.0 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 247327
:
248191
|
248228
|
248297
|
248298
|
248299