linux/arch/h8300/kernel/kgdb.c
<<
>>
Prefs
   1/*
   2 * H8/300 KGDB support
   3 *
   4 * Copyright (C) 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
   5 *
   6 * This file is subject to the terms and conditions of the GNU General Public
   7 * License.  See the file "COPYING" in the main directory of this archive
   8 * for more details.
   9 */
  10
  11#include <linux/ptrace.h>
  12#include <linux/kgdb.h>
  13#include <linux/kdebug.h>
  14#include <linux/io.h>
  15
  16struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
  17        { "er0", GDB_SIZEOF_REG, offsetof(struct pt_regs, er0) },
  18        { "er1", GDB_SIZEOF_REG, offsetof(struct pt_regs, er1) },
  19        { "er2", GDB_SIZEOF_REG, offsetof(struct pt_regs, er2) },
  20        { "er3", GDB_SIZEOF_REG, offsetof(struct pt_regs, er3) },
  21        { "er4", GDB_SIZEOF_REG, offsetof(struct pt_regs, er4) },
  22        { "er5", GDB_SIZEOF_REG, offsetof(struct pt_regs, er5) },
  23        { "er6", GDB_SIZEOF_REG, offsetof(struct pt_regs, er6) },
  24        { "sp", GDB_SIZEOF_REG, offsetof(struct pt_regs, sp) },
  25        { "ccr", GDB_SIZEOF_REG, offsetof(struct pt_regs, ccr) },
  26        { "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, pc) },
  27        { "cycles", GDB_SIZEOF_REG, -1 },
  28#if defined(CONFIG_CPU_H8S)
  29        { "exr", GDB_SIZEOF_REG, offsetof(struct pt_regs, exr) },
  30#endif
  31        { "tick", GDB_SIZEOF_REG, -1 },
  32        { "inst", GDB_SIZEOF_REG, -1 },
  33};
  34
  35char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
  36{
  37        if (regno >= DBG_MAX_REG_NUM || regno < 0)
  38                return NULL;
  39
  40        switch (regno) {
  41        case GDB_CCR:
  42#if defined(CONFIG_CPU_H8S)
  43        case GDB_EXR:
  44#endif
  45                *(u32 *)mem = *(u16 *)((void *)regs +
  46                                       dbg_reg_def[regno].offset);
  47                break;
  48        default:
  49                if (dbg_reg_def[regno].offset >= 0)
  50                        memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
  51                               dbg_reg_def[regno].size);
  52                else
  53                        memset(mem, 0, dbg_reg_def[regno].size);
  54                break;
  55        }
  56        return dbg_reg_def[regno].name;
  57}
  58
  59int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
  60{
  61        if (regno >= DBG_MAX_REG_NUM || regno < 0)
  62                return -EINVAL;
  63
  64        switch (regno) {
  65        case GDB_CCR:
  66#if defined(CONFIG_CPU_H8S)
  67        case GDB_EXR:
  68#endif
  69                *(u16 *)((void *)regs +
  70                         dbg_reg_def[regno].offset) = *(u32 *)mem;
  71                break;
  72        default:
  73                memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
  74                       dbg_reg_def[regno].size);
  75        }
  76        return 0;
  77}
  78
  79asmlinkage void h8300_kgdb_trap(struct pt_regs *regs)
  80{
  81        regs->pc &= 0x00ffffff;
  82        if (kgdb_handle_exception(10, SIGTRAP, 0, regs))
  83                return;
  84        if (*(u16 *)(regs->pc) == *(u16 *)&arch_kgdb_ops.gdb_bpt_instr)
  85                regs->pc += BREAK_INSTR_SIZE;
  86        regs->pc |= regs->ccr << 24;
  87}
  88
  89void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
  90{
  91        memset((char *)gdb_regs, 0, NUMREGBYTES);
  92        gdb_regs[GDB_SP] = p->thread.ksp;
  93        gdb_regs[GDB_PC] = KSTK_EIP(p);
  94}
  95
  96void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
  97{
  98        regs->pc = pc;
  99}
 100
 101int kgdb_arch_handle_exception(int vector, int signo, int err_code,
 102                                char *remcom_in_buffer, char *remcom_out_buffer,
 103                                struct pt_regs *regs)
 104{
 105        char *ptr;
 106        unsigned long addr;
 107
 108        switch (remcom_in_buffer[0]) {
 109        case 's':
 110        case 'c':
 111                /* handle the optional parameters */
 112                ptr = &remcom_in_buffer[1];
 113                if (kgdb_hex2long(&ptr, &addr))
 114                        regs->pc = addr;
 115
 116                return 0;
 117        }
 118
 119        return -1; /* this means that we do not want to exit from the handler */
 120}
 121
 122int kgdb_arch_init(void)
 123{
 124        return 0;
 125}
 126
 127void kgdb_arch_exit(void)
 128{
 129        /* Nothing to do */
 130}
 131
 132struct kgdb_arch arch_kgdb_ops = {
 133        /* Breakpoint instruction: trapa #2 */
 134        .gdb_bpt_instr = { 0x57, 0x20 },
 135};
 136