MIPS: ptrace: Avoid smp_processor_id() in preemptible code
authorAlex Smith <alex.smith@imgtec.com>
Thu, 1 May 2014 11:51:19 +0000 (12:51 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Wed, 28 May 2014 08:54:41 +0000 (10:54 +0200)
ptrace_{get,set}_watch_regs access current_cpu_data to get the watch
register count/masks, which calls smp_processor_id(). However they are
run in preemptible context and therefore trigger warnings like so:

[ 6340.092000] BUG: using smp_processor_id() in preemptible [00000000] code: gdb/367
[ 6340.092000] caller is ptrace_get_watch_regs+0x44/0x220

Since the watch register count/masks should be the same across all
CPUs, use boot_cpu_data instead. Note that this may need to change in
future should a heterogenous system be supported where the count/masks
are not the same across all CPUs (the current code is also incorrect
for this scenario - current_cpu_data here would not necessarily be
correct for the CPU that the target task will execute on).

Signed-off-by: Alex Smith <alex.smith@imgtec.com>
Reviewed-by: Paul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/6879/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/kernel/ptrace.c

index 71f85f4270341252d046db277aecfd5d3d0ae13d..f639ccd5060c18d85f33a33f2cc4bce81605ae3b 100644 (file)
@@ -163,7 +163,7 @@ int ptrace_get_watch_regs(struct task_struct *child,
        enum pt_watch_style style;
        int i;
 
-       if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0)
+       if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0)
                return -EIO;
        if (!access_ok(VERIFY_WRITE, addr, sizeof(struct pt_watch_regs)))
                return -EIO;
@@ -177,14 +177,14 @@ int ptrace_get_watch_regs(struct task_struct *child,
 #endif
 
        __put_user(style, &addr->style);
-       __put_user(current_cpu_data.watch_reg_use_cnt,
+       __put_user(boot_cpu_data.watch_reg_use_cnt,
                   &addr->WATCH_STYLE.num_valid);
-       for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
+       for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
                __put_user(child->thread.watch.mips3264.watchlo[i],
                           &addr->WATCH_STYLE.watchlo[i]);
                __put_user(child->thread.watch.mips3264.watchhi[i] & 0xfff,
                           &addr->WATCH_STYLE.watchhi[i]);
-               __put_user(current_cpu_data.watch_reg_masks[i],
+               __put_user(boot_cpu_data.watch_reg_masks[i],
                           &addr->WATCH_STYLE.watch_masks[i]);
        }
        for (; i < 8; i++) {
@@ -204,12 +204,12 @@ int ptrace_set_watch_regs(struct task_struct *child,
        unsigned long lt[NUM_WATCH_REGS];
        u16 ht[NUM_WATCH_REGS];
 
-       if (!cpu_has_watch || current_cpu_data.watch_reg_use_cnt == 0)
+       if (!cpu_has_watch || boot_cpu_data.watch_reg_use_cnt == 0)
                return -EIO;
        if (!access_ok(VERIFY_READ, addr, sizeof(struct pt_watch_regs)))
                return -EIO;
        /* Check the values. */
-       for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
+       for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
                __get_user(lt[i], &addr->WATCH_STYLE.watchlo[i]);
 #ifdef CONFIG_32BIT
                if (lt[i] & __UA_LIMIT)
@@ -228,7 +228,7 @@ int ptrace_set_watch_regs(struct task_struct *child,
                        return -EINVAL;
        }
        /* Install them. */
-       for (i = 0; i < current_cpu_data.watch_reg_use_cnt; i++) {
+       for (i = 0; i < boot_cpu_data.watch_reg_use_cnt; i++) {
                if (lt[i] & 7)
                        watch_active = 1;
                child->thread.watch.mips3264.watchlo[i] = lt[i];