lkml.org 
[lkml]   [2007]   [Feb]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [patch 08/13] syslets: x86, add move_user_context() method
    On Wed, 21 Feb 2007, Ingo Molnar wrote:

    > From: Ingo Molnar <mingo@elte.hu>
    >
    > add the move_user_context() method to move the user-space
    > context of one kernel thread to another kernel thread.
    > User-space might notice the changed TID, but execution,
    > stack and register contents (general purpose and FPU) are
    > still the same.

    Also signal handling should/must be maintained, on top of TID.
    You don't want the user to be presented with a different signal handling
    after an sys_async_exec call.




    > Signed-off-by: Ingo Molnar <mingo@elte.hu>
    > Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
    > ---
    > arch/i386/kernel/process.c | 21 +++++++++++++++++++++
    > include/asm-i386/system.h | 7 +++++++
    > 2 files changed, 28 insertions(+)
    >
    > Index: linux/arch/i386/kernel/process.c
    > ===================================================================
    > --- linux.orig/arch/i386/kernel/process.c
    > +++ linux/arch/i386/kernel/process.c
    > @@ -820,6 +820,27 @@ unsigned long get_wchan(struct task_stru
    > }
    >
    > /*
    > + * Move user-space context from one kernel thread to another.
    > + * This includes registers and FPU state. Callers must make
    > + * sure that neither task is running user context at the moment:
    > + */
    > +void
    > +move_user_context(struct task_struct *new_task, struct task_struct *old_task)
    > +{
    > + struct pt_regs *old_regs = task_pt_regs(old_task);
    > + struct pt_regs *new_regs = task_pt_regs(new_task);
    > + union i387_union *tmp;
    > +
    > + *new_regs = *old_regs;
    > + /*
    > + * Flip around the FPU state too:
    > + */
    > + tmp = new_task->thread.i387;
    > + new_task->thread.i387 = old_task->thread.i387;
    > + old_task->thread.i387 = tmp;
    > +}

    This is not going to work in this case (already posted twice in other
    emails):

    ---
    Given TS_USEDFPU set (NTSK == new_task, OTSK == old_task), before
    move_user_context():

    CPU => FPUc
    NTSK => FPUn
    OTSK => FPUo

    After move_user_context():

    CPU => FPUc
    NTSK => FPUo
    OTSK => FPUn

    After the incoming __unlazy_fpu() in __switch_to():

    CPU => FPUc
    NTSK => FPUo
    OTSK => FPUc

    After the first fault in NTSK:

    CPU => FPUo
    NTSK => FPUo
    OTSK => FPUc

    So NTSK loads a non up2date FPUo, instead of the FPUc that was the "dirty"
    context to migrate (since TS_USEDFPU was set). I think you need an early
    __unlazy_fpu() in that case, that would turn the above into:

    Before move_user_context():

    CPU => FPUc
    NTSK => FPUn
    OTSK => FPUo

    After an early __unlazy_fpu() before FPU member swap:

    CPU => FPUc
    NTSK => FPUn
    OTSK => FPUc

    After move_user_context():

    CPU => FPUc
    NTSK => FPUc
    OTSK => FPUn

    After the first fault in NTSK:

    CPU => FPUc
    NTSK => FPUc
    OTSK => FPUn

    So, NTSK (the return-to-userspace task) will get the correct FPUc after a
    fault. But the OTSK (now becoming service thread) will load FPUn after a
    fault, that is not what expected. You may need a copy in that case.
    I think correct FPU context handling is not going to be as easy as
    swapping FPU pointers.



    - Davide


    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-02-22 00:07    [W:0.025 / U:31.052 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site