lkml.org 
[lkml]   [2009]   [Jan]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[RFC Patch 6/10] Use virtual debug registers in process/thread handling code
    This patch enables the use of abstract/virtual debug registers in
    process-handling routines.

    Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
    Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
    ---
    arch/x86/kernel/process_32.c | 43 +++++++++++++++++++++++++------------------
    arch/x86/kernel/process_64.c | 41 ++++++++++++++++++++++++-----------------
    2 files changed, 49 insertions(+), 35 deletions(-)

    Index: linux-hbkpt-lkml-29-rc2/arch/x86/kernel/process_32.c
    ===================================================================
    --- linux-hbkpt-lkml-29-rc2.orig/arch/x86/kernel/process_32.c
    +++ linux-hbkpt-lkml-29-rc2/arch/x86/kernel/process_32.c
    @@ -60,6 +60,8 @@
    #include <asm/idle.h>
    #include <asm/syscalls.h>
    #include <asm/ds.h>
    +#include <asm/debugreg.h>
    +#include <asm/hw_breakpoint.h>

    asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");

    @@ -231,6 +233,8 @@ EXPORT_SYMBOL(kernel_thread);
    */
    void exit_thread(void)
    {
    + struct task_struct *tsk = current;
    +
    /* The process may have allocated an io port bitmap... nuke it. */
    if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
    struct task_struct *tsk = current;
    @@ -251,6 +255,8 @@ void exit_thread(void)
    tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
    put_cpu();
    }
    + if (unlikely(tsk->thread.hw_breakpoint_info))
    + flush_thread_hw_breakpoint(tsk);

    ds_exit_thread(current);
    }
    @@ -259,14 +265,9 @@ void flush_thread(void)
    {
    struct task_struct *tsk = current;

    - tsk->thread.debugreg0 = 0;
    - tsk->thread.debugreg1 = 0;
    - tsk->thread.debugreg2 = 0;
    - tsk->thread.debugreg3 = 0;
    - tsk->thread.debugreg6 = 0;
    - tsk->thread.debugreg7 = 0;
    memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
    - clear_tsk_thread_flag(tsk, TIF_DEBUG);
    + if (unlikely(tsk->thread.hw_breakpoint_info))
    + flush_thread_hw_breakpoint(tsk);
    /*
    * Forget coprocessor state..
    */
    @@ -310,7 +311,15 @@ int copy_thread(int nr, unsigned long cl

    savesegment(gs, p->thread.gs);

    + p->thread.hw_breakpoint_info = NULL;
    + p->thread.io_bitmap_ptr = NULL;
    +
    tsk = current;
    + err = -ENOMEM;
    + if (unlikely(tsk->thread.hw_breakpoint_info)) {
    + if (copy_thread_hw_breakpoint(tsk, p, clone_flags))
    + goto out;
    + }
    if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) {
    p->thread.io_bitmap_ptr = kmemdup(tsk->thread.io_bitmap_ptr,
    IO_BITMAP_BYTES, GFP_KERNEL);
    @@ -329,11 +338,13 @@ int copy_thread(int nr, unsigned long cl
    if (clone_flags & CLONE_SETTLS)
    err = do_set_thread_area(p, -1,
    (struct user_desc __user *)childregs->si, 0);
    -
    + out:
    if (err && p->thread.io_bitmap_ptr) {
    kfree(p->thread.io_bitmap_ptr);
    p->thread.io_bitmap_max = 0;
    }
    + if (err)
    + flush_thread_hw_breakpoint(p);

    ds_copy_thread(p, current);

    @@ -435,16 +446,6 @@ __switch_to_xtra(struct task_struct *pre
    else if (next->debugctlmsr != prev->debugctlmsr)
    update_debugctlmsr(next->debugctlmsr);

    - if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
    - set_debugreg(next->debugreg0, 0);
    - set_debugreg(next->debugreg1, 1);
    - set_debugreg(next->debugreg2, 2);
    - set_debugreg(next->debugreg3, 3);
    - /* no 4 and 5 */
    - set_debugreg(next->debugreg6, 6);
    - set_debugreg(next->debugreg7, 7);
    - }
    -
    if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
    /* prev and next are different */
    @@ -592,6 +593,12 @@ __switch_to(struct task_struct *prev_p,
    loadsegment(gs, next->gs);

    x86_write_percpu(current_task, next_p);
    + /*
    + * Handle debug registers. This must be done _after_ current
    + * is updated.
    + */
    + if (unlikely(test_tsk_thread_flag(next_p, TIF_DEBUG)))
    + switch_to_thread_hw_breakpoint(next_p);

    return prev_p;
    }
    Index: linux-hbkpt-lkml-29-rc2/arch/x86/kernel/process_64.c
    ===================================================================
    --- linux-hbkpt-lkml-29-rc2.orig/arch/x86/kernel/process_64.c
    +++ linux-hbkpt-lkml-29-rc2/arch/x86/kernel/process_64.c
    @@ -52,6 +52,8 @@
    #include <asm/proto.h>
    #include <asm/ia32.h>
    #include <asm/idle.h>
    +#include <asm/debugreg.h>
    +#include <asm/hw_breakpoint.h>
    #include <asm/syscalls.h>
    #include <asm/ds.h>

    @@ -256,13 +258,9 @@ void flush_thread(void)
    }
    clear_tsk_thread_flag(tsk, TIF_DEBUG);

    - tsk->thread.debugreg0 = 0;
    - tsk->thread.debugreg1 = 0;
    - tsk->thread.debugreg2 = 0;
    - tsk->thread.debugreg3 = 0;
    - tsk->thread.debugreg6 = 0;
    - tsk->thread.debugreg7 = 0;
    memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
    + if (unlikely(tsk->thread.hw_breakpoint_info))
    + flush_thread_hw_breakpoint(tsk);
    /*
    * Forget coprocessor state..
    */
    @@ -282,6 +280,8 @@ void release_thread(struct task_struct *
    BUG();
    }
    }
    + if (unlikely(me->thread.hw_breakpoint_info))
    + flush_thread_hw_breakpoint(me);
    }

    static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
    @@ -337,13 +337,21 @@ int copy_thread(int nr, unsigned long cl

    p->thread.fs = me->thread.fs;
    p->thread.gs = me->thread.gs;
    + p->thread.hw_breakpoint_info = NULL;
    + p->thread.io_bitmap_ptr = NULL;

    savesegment(gs, p->thread.gsindex);
    savesegment(fs, p->thread.fsindex);
    savesegment(es, p->thread.es);
    savesegment(ds, p->thread.ds);

    - if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
    + err = -ENOMEM;
    + if (unlikely(me->thread.hw_breakpoint_info)) {
    + if (copy_thread_hw_breakpoint(me, p, clone_flags))
    + goto out;
    + }
    +
    +if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
    p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
    if (!p->thread.io_bitmap_ptr) {
    p->thread.io_bitmap_max = 0;
    @@ -380,6 +388,9 @@ out:
    kfree(p->thread.io_bitmap_ptr);
    p->thread.io_bitmap_max = 0;
    }
    + if (err)
    + flush_thread_hw_breakpoint(p);
    +
    return err;
    }

    @@ -482,16 +493,6 @@ static inline void __switch_to_xtra(stru
    else if (next->debugctlmsr != prev->debugctlmsr)
    update_debugctlmsr(next->debugctlmsr);

    - if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
    - loaddebug(next, 0);
    - loaddebug(next, 1);
    - loaddebug(next, 2);
    - loaddebug(next, 3);
    - /* no 4 and 5 */
    - loaddebug(next, 6);
    - loaddebug(next, 7);
    - }
    -
    if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
    test_tsk_thread_flag(next_p, TIF_NOTSC)) {
    /* prev and next are different */
    @@ -514,6 +515,12 @@ static inline void __switch_to_xtra(stru
    */
    memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
    }
    + /*
    + * Handle debug registers. This must be done _after_ current
    + * is updated.
    + */
    + if (unlikely(test_tsk_thread_flag(next_p, TIF_DEBUG)))
    + switch_to_thread_hw_breakpoint(next_p);
    }

    /*

    \
     
     \ /
      Last update: 2009-01-22 15:09    [W:0.057 / U:58.816 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site