linux/arch/sh/kernel/kgdb.c
<<
>>
Prefs
   1/*
   2 * SuperH KGDB support
   3 *
   4 * Copyright (C) 2008 - 2012  Paul Mundt
   5 *
   6 * Single stepping taken from the old stub by Henry Bell and Jeremy Siegel.
   7 *
   8 * This file is subject to the terms and conditions of the GNU General Public
   9 * License.  See the file "COPYING" in the main directory of this archive
  10 * for more details.
  11 */
  12#include <linux/kgdb.h>
  13#include <linux/kdebug.h>
  14#include <linux/irq.h>
  15#include <linux/io.h>
  16#include <linux/sched.h>
  17#include <asm/cacheflush.h>
  18#include <asm/traps.h>
  19
  20/* Macros for single step instruction identification */
  21#define OPCODE_BT(op)           (((op) & 0xff00) == 0x8900)
  22#define OPCODE_BF(op)           (((op) & 0xff00) == 0x8b00)
  23#define OPCODE_BTF_DISP(op)     (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
  24                                 (((op) & 0x7f ) << 1))
  25#define OPCODE_BFS(op)          (((op) & 0xff00) == 0x8f00)
  26#define OPCODE_BTS(op)          (((op) & 0xff00) == 0x8d00)
  27#define OPCODE_BRA(op)          (((op) & 0xf000) == 0xa000)
  28#define OPCODE_BRA_DISP(op)     (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
  29                                 (((op) & 0x7ff) << 1))
  30#define OPCODE_BRAF(op)         (((op) & 0xf0ff) == 0x0023)
  31#define OPCODE_BRAF_REG(op)     (((op) & 0x0f00) >> 8)
  32#define OPCODE_BSR(op)          (((op) & 0xf000) == 0xb000)
  33#define OPCODE_BSR_DISP(op)     (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
  34                                 (((op) & 0x7ff) << 1))
  35#define OPCODE_BSRF(op)         (((op) & 0xf0ff) == 0x0003)
  36#define OPCODE_BSRF_REG(op)     (((op) >> 8) & 0xf)
  37#define OPCODE_JMP(op)          (((op) & 0xf0ff) == 0x402b)
  38#define OPCODE_JMP_REG(op)      (((op) >> 8) & 0xf)
  39#define OPCODE_JSR(op)          (((op) & 0xf0ff) == 0x400b)
  40#define OPCODE_JSR_REG(op)      (((op) >> 8) & 0xf)
  41#define OPCODE_RTS(op)          ((op) == 0xb)
  42#define OPCODE_RTE(op)          ((op) == 0x2b)
  43
  44#define SR_T_BIT_MASK           0x1
  45#define STEP_OPCODE             0xc33d
  46
  47/* Calculate the new address for after a step */
  48static short *get_step_address(struct pt_regs *linux_regs)
  49{
  50        insn_size_t op = __raw_readw(linux_regs->pc);
  51        long addr;
  52
  53        /* BT */
  54        if (OPCODE_BT(op)) {
  55                if (linux_regs->sr & SR_T_BIT_MASK)
  56                        addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op);
  57                else
  58                        addr = linux_regs->pc + 2;
  59        }
  60
  61        /* BTS */
  62        else if (OPCODE_BTS(op)) {
  63                if (linux_regs->sr & SR_T_BIT_MASK)
  64                        addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op);
  65                else
  66                        addr = linux_regs->pc + 4;      /* Not in delay slot */
  67        }
  68
  69        /* BF */
  70        else if (OPCODE_BF(op)) {
  71                if (!(linux_regs->sr & SR_T_BIT_MASK))
  72                        addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op);
  73                else
  74                        addr = linux_regs->pc + 2;
  75        }
  76
  77        /* BFS */
  78        else if (OPCODE_BFS(op)) {
  79                if (!(linux_regs->sr & SR_T_BIT_MASK))
  80                        addr = linux_regs->pc + 4 + OPCODE_BTF_DISP(op);
  81                else
  82                        addr = linux_regs->pc + 4;      /* Not in delay slot */
  83        }
  84
  85        /* BRA */
  86        else if (OPCODE_BRA(op))
  87                addr = linux_regs->pc + 4 + OPCODE_BRA_DISP(op);
  88
  89        /* BRAF */
  90        else if (OPCODE_BRAF(op))
  91                addr = linux_regs->pc + 4
  92                    + linux_regs->regs[OPCODE_BRAF_REG(op)];
  93
  94        /* BSR */
  95        else if (OPCODE_BSR(op))
  96                addr = linux_regs->pc + 4 + OPCODE_BSR_DISP(op);
  97
  98        /* BSRF */
  99        else if (OPCODE_BSRF(op))
 100                addr = linux_regs->pc + 4
 101                    + linux_regs->regs[OPCODE_BSRF_REG(op)];
 102
 103        /* JMP */
 104        else if (OPCODE_JMP(op))
 105                addr = linux_regs->regs[OPCODE_JMP_REG(op)];
 106
 107        /* JSR */
 108        else if (OPCODE_JSR(op))
 109                addr = linux_regs->regs[OPCODE_JSR_REG(op)];
 110
 111        /* RTS */
 112        else if (OPCODE_RTS(op))
 113                addr = linux_regs->pr;
 114
 115        /* RTE */
 116        else if (OPCODE_RTE(op))
 117                addr = linux_regs->regs[15];
 118
 119        /* Other */
 120        else
 121                addr = linux_regs->pc + instruction_size(op);
 122
 123        flush_icache_range(addr, addr + instruction_size(op));
 124        return (short *)addr;
 125}
 126
 127/*
 128 * Replace the instruction immediately after the current instruction
 129 * (i.e. next in the expected flow of control) with a trap instruction,
 130 * so that returning will cause only a single instruction to be executed.
 131 * Note that this model is slightly broken for instructions with delay
 132 * slots (e.g. B[TF]S, BSR, BRA etc), where both the branch and the
 133 * instruction in the delay slot will be executed.
 134 */
 135
 136static unsigned long stepped_address;
 137static insn_size_t stepped_opcode;
 138
 139static void do_single_step(struct pt_regs *linux_regs)
 140{
 141        /* Determine where the target instruction will send us to */
 142        unsigned short *addr = get_step_address(linux_regs);
 143
 144        stepped_address = (int)addr;
 145
 146        /* Replace it */
 147        stepped_opcode = __raw_readw((long)addr);
 148        *addr = STEP_OPCODE;
 149
 150        /* Flush and return */
 151        flush_icache_range((long)addr, (long)addr +
 152                           instruction_size(stepped_opcode));
 153}
 154
 155/* Undo a single step */
 156static void undo_single_step(struct pt_regs *linux_regs)
 157{
 158        /* If we have stepped, put back the old instruction */
 159        /* Use stepped_address in case we stopped elsewhere */
 160        if (stepped_opcode != 0) {
 161                __raw_writew(stepped_opcode, stepped_address);
 162                flush_icache_range(stepped_address, stepped_address + 2);
 163        }
 164
 165        stepped_opcode = 0;
 166}
 167
 168struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
 169        { "r0",         GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[0]) },
 170        { "r1",         GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[1]) },
 171        { "r2",         GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[2]) },
 172        { "r3",         GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[3]) },
 173        { "r4",         GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[4]) },
 174        { "r5",         GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[5]) },
 175        { "r6",         GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[6]) },
 176        { "r7",         GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[7]) },
 177        { "r8",         GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[8]) },
 178        { "r9",         GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[9]) },
 179        { "r10",        GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[10]) },
 180        { "r11",        GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[11]) },
 181        { "r12",        GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[12]) },
 182        { "r13",        GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[13]) },
 183        { "r14",        GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[14]) },
 184        { "r15",        GDB_SIZEOF_REG, offsetof(struct pt_regs, regs[15]) },
 185        { "pc",         GDB_SIZEOF_REG, offsetof(struct pt_regs, pc) },
 186        { "pr",         GDB_SIZEOF_REG, offsetof(struct pt_regs, pr) },
 187        { "sr",         GDB_SIZEOF_REG, offsetof(struct pt_regs, sr) },
 188        { "gbr",        GDB_SIZEOF_REG, offsetof(struct pt_regs, gbr) },
 189        { "mach",       GDB_SIZEOF_REG, offsetof(struct pt_regs, mach) },
 190        { "macl",       GDB_SIZEOF_REG, offsetof(struct pt_regs, macl) },
 191        { "vbr",        GDB_SIZEOF_REG, -1 },
 192};
 193
 194int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
 195{
 196        if (regno < 0 || regno >= DBG_MAX_REG_NUM)
 197                return -EINVAL;
 198
 199        if (dbg_reg_def[regno].offset != -1)
 200                memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
 201                       dbg_reg_def[regno].size);
 202
 203        return 0;
 204}
 205
 206char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
 207{
 208        if (regno >= DBG_MAX_REG_NUM || regno < 0)
 209                return NULL;
 210
 211        if (dbg_reg_def[regno].size != -1)
 212                memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
 213                       dbg_reg_def[regno].size);
 214
 215        switch (regno) {
 216        case GDB_VBR:
 217                __asm__ __volatile__ ("stc vbr, %0" : "=r" (mem));
 218                break;
 219        }
 220
 221        return dbg_reg_def[regno].name;
 222}
 223
 224void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
 225{
 226        struct pt_regs *thread_regs = task_pt_regs(p);
 227        int reg;
 228
 229        /* Initialize to zero */
 230        for (reg = 0; reg < DBG_MAX_REG_NUM; reg++)
 231                gdb_regs[reg] = 0;
 232
 233        /*
 234         * Copy out GP regs 8 to 14.
 235         *
 236         * switch_to() relies on SR.RB toggling, so regs 0->7 are banked
 237         * and need privileged instructions to get to. The r15 value we
 238         * fetch from the thread info directly.
 239         */
 240        for (reg = GDB_R8; reg < GDB_R15; reg++)
 241                gdb_regs[reg] = thread_regs->regs[reg];
 242
 243        gdb_regs[GDB_R15] = p->thread.sp;
 244        gdb_regs[GDB_PC] = p->thread.pc;
 245
 246        /*
 247         * Additional registers we have context for
 248         */
 249        gdb_regs[GDB_PR] = thread_regs->pr;
 250        gdb_regs[GDB_GBR] = thread_regs->gbr;
 251}
 252
 253int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
 254                               char *remcomInBuffer, char *remcomOutBuffer,
 255                               struct pt_regs *linux_regs)
 256{
 257        unsigned long addr;
 258        char *ptr;
 259
 260        /* Undo any stepping we may have done */
 261        undo_single_step(linux_regs);
 262
 263        switch (remcomInBuffer[0]) {
 264        case 'c':
 265        case 's':
 266                /* try to read optional parameter, pc unchanged if no parm */
 267                ptr = &remcomInBuffer[1];
 268                if (kgdb_hex2long(&ptr, &addr))
 269                        linux_regs->pc = addr;
 270        case 'D':
 271        case 'k':
 272                atomic_set(&kgdb_cpu_doing_single_step, -1);
 273
 274                if (remcomInBuffer[0] == 's') {
 275                        do_single_step(linux_regs);
 276                        kgdb_single_step = 1;
 277
 278                        atomic_set(&kgdb_cpu_doing_single_step,
 279                                   raw_smp_processor_id());
 280                }
 281
 282                return 0;
 283        }
 284
 285        /* this means that we do not want to exit from the handler: */
 286        return -1;
 287}
 288
 289unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs)
 290{
 291        if (exception == 60)
 292                return instruction_pointer(regs) - 2;
 293        return instruction_pointer(regs);
 294}
 295
 296void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 297{
 298        regs->pc = ip;
 299}
 300
 301/*
 302 * The primary entry points for the kgdb debug trap table entries.
 303 */
 304BUILD_TRAP_HANDLER(singlestep)
 305{
 306        unsigned long flags;
 307        TRAP_HANDLER_DECL;
 308
 309        local_irq_save(flags);
 310        regs->pc -= instruction_size(__raw_readw(regs->pc - 4));
 311        kgdb_handle_exception(0, SIGTRAP, 0, regs);
 312        local_irq_restore(flags);
 313}
 314
 315static void kgdb_call_nmi_hook(void *ignored)
 316{
 317        kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
 318}
 319
 320void kgdb_roundup_cpus(unsigned long flags)
 321{
 322        local_irq_enable();
 323        smp_call_function(kgdb_call_nmi_hook, NULL, 0);
 324        local_irq_disable();
 325}
 326
 327static int __kgdb_notify(struct die_args *args, unsigned long cmd)
 328{
 329        int ret;
 330
 331        switch (cmd) {
 332        case DIE_BREAKPOINT:
 333                /*
 334                 * This means a user thread is single stepping
 335                 * a system call which should be ignored
 336                 */
 337                if (test_thread_flag(TIF_SINGLESTEP))
 338                        return NOTIFY_DONE;
 339
 340                ret = kgdb_handle_exception(args->trapnr & 0xff, args->signr,
 341                                            args->err, args->regs);
 342                if (ret)
 343                        return NOTIFY_DONE;
 344
 345                break;
 346        }
 347
 348        return NOTIFY_STOP;
 349}
 350
 351static int
 352kgdb_notify(struct notifier_block *self, unsigned long cmd, void *ptr)
 353{
 354        unsigned long flags;
 355        int ret;
 356
 357        local_irq_save(flags);
 358        ret = __kgdb_notify(ptr, cmd);
 359        local_irq_restore(flags);
 360
 361        return ret;
 362}
 363
 364static struct notifier_block kgdb_notifier = {
 365        .notifier_call  = kgdb_notify,
 366
 367        /*
 368         * Lowest-prio notifier priority, we want to be notified last:
 369         */
 370        .priority       = -INT_MAX,
 371};
 372
 373int kgdb_arch_init(void)
 374{
 375        return register_die_notifier(&kgdb_notifier);
 376}
 377
 378void kgdb_arch_exit(void)
 379{
 380        unregister_die_notifier(&kgdb_notifier);
 381}
 382
 383struct kgdb_arch arch_kgdb_ops = {
 384        /* Breakpoint instruction: trapa #0x3c */
 385#ifdef CONFIG_CPU_LITTLE_ENDIAN
 386        .gdb_bpt_instr          = { 0x3c, 0xc3 },
 387#else
 388        .gdb_bpt_instr          = { 0xc3, 0x3c },
 389#endif
 390};
 391