From 2c7660ba3e67c64161b4c77b403534028f0faf6f Mon Sep 17 00:00:00 2001 From: Dmitry Chagin Date: Sat, 12 Feb 2011 15:50:21 +0000 Subject: [PATCH] In preparation for moving linux_clone () to a MI path move the TLS code in a separate function. Use function parameter instead of direct using register. --- sys/amd64/linux32/linux32_machdep.c | 86 +++++++++++---------- sys/i386/linux/linux_machdep.c | 112 ++++++++++++++-------------- 2 files changed, 104 insertions(+), 94 deletions(-) diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c index 986322e9fa7a..d24b7b6e3ea6 100644 --- a/sys/amd64/linux32/linux32_machdep.c +++ b/sys/amd64/linux32/linux32_machdep.c @@ -496,6 +496,50 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args) return (0); } +static int +linux_set_cloned_tls(struct thread *td, void *desc) +{ + struct user_segment_descriptor sd; + struct l_user_desc info; + struct pcb *pcb; + int error; + int a[2]; + + error = copyin(desc, &info, sizeof(struct l_user_desc)); + if (error) { + printf(LMSG("copyin failed!")); + } else { + /* We might copy out the entry_number as GUGS32_SEL. */ + info.entry_number = GUGS32_SEL; + error = copyout(&info, desc, sizeof(struct l_user_desc)); + if (error) + printf(LMSG("copyout failed!")); + + a[0] = LINUX_LDT_entry_a(&info); + a[1] = LINUX_LDT_entry_b(&info); + + memcpy(&sd, &a, sizeof(a)); +#ifdef DEBUG + if (ldebug(clone)) + printf("Segment created in clone with " + "CLONE_SETTLS: lobase: %x, hibase: %x, " + "lolimit: %x, hilimit: %x, type: %i, " + "dpl: %i, p: %i, xx: %i, long: %i, " + "def32: %i, gran: %i\n", sd.sd_lobase, + sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, + sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, + sd.sd_long, sd.sd_def32, sd.sd_gran); +#endif + pcb = td->td_pcb; + pcb->pcb_gsbase = (register_t)info.base_addr; +/* XXXKIB pcb->pcb_gs32sd = sd; */ + td->td_frame->tf_gs = GSEL(GUGS32_SEL, SEL_UPL); + set_pcb_flags(pcb, PCB_GS32BIT | PCB_32BIT); + } + + return (error); +} + int linux_clone(struct thread *td, struct linux_clone_args *args) { @@ -613,46 +657,8 @@ linux_clone(struct thread *td, struct linux_clone_args *args) if (args->stack) td2->td_frame->tf_rsp = PTROUT(args->stack); - if (args->flags & LINUX_CLONE_SETTLS) { - struct user_segment_descriptor sd; - struct l_user_desc info; - struct pcb *pcb; - int a[2]; - - error = copyin((void *)td->td_frame->tf_rsi, &info, - sizeof(struct l_user_desc)); - if (error) { - printf(LMSG("copyin failed!")); - } else { - /* We might copy out the entry_number as GUGS32_SEL. */ - info.entry_number = GUGS32_SEL; - error = copyout(&info, (void *)td->td_frame->tf_rsi, - sizeof(struct l_user_desc)); - if (error) - printf(LMSG("copyout failed!")); - - a[0] = LINUX_LDT_entry_a(&info); - a[1] = LINUX_LDT_entry_b(&info); - - memcpy(&sd, &a, sizeof(a)); -#ifdef DEBUG - if (ldebug(clone)) - printf("Segment created in clone with " - "CLONE_SETTLS: lobase: %x, hibase: %x, " - "lolimit: %x, hilimit: %x, type: %i, " - "dpl: %i, p: %i, xx: %i, long: %i, " - "def32: %i, gran: %i\n", sd.sd_lobase, - sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, - sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, - sd.sd_long, sd.sd_def32, sd.sd_gran); -#endif - pcb = td2->td_pcb; - pcb->pcb_gsbase = (register_t)info.base_addr; -/* XXXKIB pcb->pcb_gs32sd = sd; */ - td2->td_frame->tf_gs = GSEL(GUGS32_SEL, SEL_UPL); - set_pcb_flags(pcb, PCB_GS32BIT | PCB_32BIT); - } - } + if (args->flags & LINUX_CLONE_SETTLS) + linux_set_cloned_tls(td2, args->tls); #ifdef DEBUG if (ldebug(clone)) diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c index af2665b7aa92..b8e18eff1947 100644 --- a/sys/i386/linux/linux_machdep.c +++ b/sys/i386/linux/linux_machdep.c @@ -387,6 +387,62 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args) return (0); } +static int +linux_set_cloned_tls(struct thread *td, void *desc) +{ + struct segment_descriptor sd; + struct l_user_desc info; + int idx, error; + int a[2]; + + error = copyin(desc, &info, sizeof(struct l_user_desc)); + if (error) { + printf(LMSG("copyin failed!")); + } else { + idx = info.entry_number; + + /* + * looks like we're getting the idx we returned + * in the set_thread_area() syscall + */ + if (idx != 6 && idx != 3) { + printf(LMSG("resetting idx!")); + idx = 3; + } + + /* this doesnt happen in practice */ + if (idx == 6) { + /* we might copy out the entry_number as 3 */ + info.entry_number = 3; + error = copyout(&info, desc, sizeof(struct l_user_desc)); + if (error) + printf(LMSG("copyout failed!")); + } + + a[0] = LINUX_LDT_entry_a(&info); + a[1] = LINUX_LDT_entry_b(&info); + + memcpy(&sd, &a, sizeof(a)); +#ifdef DEBUG + if (ldebug(clone)) + printf("Segment created in clone with " + "CLONE_SETTLS: lobase: %x, hibase: %x, " + "lolimit: %x, hilimit: %x, type: %i, " + "dpl: %i, p: %i, xx: %i, def32: %i, " + "gran: %i\n", sd.sd_lobase, sd.sd_hibase, + sd.sd_lolimit, sd.sd_hilimit, sd.sd_type, + sd.sd_dpl, sd.sd_p, sd.sd_xx, + sd.sd_def32, sd.sd_gran); +#endif + + /* set %gs */ + td->td_pcb->pcb_gsd = sd; + td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL); + } + + return (error); +} + int linux_clone(struct thread *td, struct linux_clone_args *args) { @@ -505,60 +561,8 @@ linux_clone(struct thread *td, struct linux_clone_args *args) if (args->stack) td2->td_frame->tf_esp = (unsigned int)args->stack; - if (args->flags & LINUX_CLONE_SETTLS) { - struct l_user_desc info; - int idx; - int a[2]; - struct segment_descriptor sd; - - error = copyin((void *)td->td_frame->tf_esi, &info, sizeof(struct l_user_desc)); - if (error) { - printf(LMSG("copyin failed!")); - } else { - - idx = info.entry_number; - - /* - * looks like we're getting the idx we returned - * in the set_thread_area() syscall - */ - if (idx != 6 && idx != 3) { - printf(LMSG("resetting idx!")); - idx = 3; - } - - /* this doesnt happen in practice */ - if (idx == 6) { - /* we might copy out the entry_number as 3 */ - info.entry_number = 3; - error = copyout(&info, (void *) td->td_frame->tf_esi, sizeof(struct l_user_desc)); - if (error) - printf(LMSG("copyout failed!")); - } - - a[0] = LINUX_LDT_entry_a(&info); - a[1] = LINUX_LDT_entry_b(&info); - - memcpy(&sd, &a, sizeof(a)); -#ifdef DEBUG - if (ldebug(clone)) - printf("Segment created in clone with CLONE_SETTLS: lobase: %x, hibase: %x, lolimit: %x, hilimit: %x, type: %i, dpl: %i, p: %i, xx: %i, def32: %i, gran: %i\n", sd.sd_lobase, - sd.sd_hibase, - sd.sd_lolimit, - sd.sd_hilimit, - sd.sd_type, - sd.sd_dpl, - sd.sd_p, - sd.sd_xx, - sd.sd_def32, - sd.sd_gran); -#endif - - /* set %gs */ - td2->td_pcb->pcb_gsd = sd; - td2->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL); - } - } + if (args->flags & LINUX_CLONE_SETTLS) + linux_set_cloned_tls(td2, args->tls); #ifdef DEBUG if (ldebug(clone))