linux/arch/arc/kernel/kgdb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * kgdb support for ARC
   4 *
   5 * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
   6 */
   7
   8#include <linux/kgdb.h>
   9#include <linux/sched.h>
  10#include <linux/sched/task_stack.h>
  11#include <asm/disasm.h>
  12#include <asm/cacheflush.h>
  13
  14static void to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs,
  15                        struct callee_regs *cregs)
  16{
  17        int regno;
  18
  19        for (regno = 0; regno <= 26; regno++)
  20                gdb_regs[_R0 + regno] = get_reg(regno, kernel_regs, cregs);
  21
  22        for (regno = 27; regno < GDB_MAX_REGS; regno++)
  23                gdb_regs[regno] = 0;
  24
  25        gdb_regs[_FP]           = kernel_regs->fp;
  26        gdb_regs[__SP]          = kernel_regs->sp;
  27        gdb_regs[_BLINK]        = kernel_regs->blink;
  28        gdb_regs[_RET]          = kernel_regs->ret;
  29        gdb_regs[_STATUS32]     = kernel_regs->status32;
  30        gdb_regs[_LP_COUNT]     = kernel_regs->lp_count;
  31        gdb_regs[_LP_END]       = kernel_regs->lp_end;
  32        gdb_regs[_LP_START]     = kernel_regs->lp_start;
  33        gdb_regs[_BTA]          = kernel_regs->bta;
  34        gdb_regs[_STOP_PC]      = kernel_regs->ret;
  35}
  36
  37static void from_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs,
  38                        struct callee_regs *cregs)
  39{
  40        int regno;
  41
  42        for (regno = 0; regno <= 26; regno++)
  43                set_reg(regno, gdb_regs[regno + _R0], kernel_regs, cregs);
  44
  45        kernel_regs->fp         = gdb_regs[_FP];
  46        kernel_regs->sp         = gdb_regs[__SP];
  47        kernel_regs->blink      = gdb_regs[_BLINK];
  48        kernel_regs->ret        = gdb_regs[_RET];
  49        kernel_regs->status32   = gdb_regs[_STATUS32];
  50        kernel_regs->lp_count   = gdb_regs[_LP_COUNT];
  51        kernel_regs->lp_end     = gdb_regs[_LP_END];
  52        kernel_regs->lp_start   = gdb_regs[_LP_START];
  53        kernel_regs->bta        = gdb_regs[_BTA];
  54}
  55
  56
  57void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
  58{
  59        to_gdb_regs(gdb_regs, kernel_regs, (struct callee_regs *)
  60                current->thread.callee_reg);
  61}
  62
  63void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *kernel_regs)
  64{
  65        from_gdb_regs(gdb_regs, kernel_regs, (struct callee_regs *)
  66                current->thread.callee_reg);
  67}
  68
  69void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs,
  70                                 struct task_struct *task)
  71{
  72        if (task)
  73                to_gdb_regs(gdb_regs, task_pt_regs(task),
  74                        (struct callee_regs *) task->thread.callee_reg);
  75}
  76
  77struct single_step_data_t {
  78        uint16_t opcode[2];
  79        unsigned long address[2];
  80        int is_branch;
  81        int armed;
  82} single_step_data;
  83
  84static void undo_single_step(struct pt_regs *regs)
  85{
  86        if (single_step_data.armed) {
  87                int i;
  88
  89                for (i = 0; i < (single_step_data.is_branch ? 2 : 1); i++) {
  90                        memcpy((void *) single_step_data.address[i],
  91                                &single_step_data.opcode[i],
  92                                BREAK_INSTR_SIZE);
  93
  94                        flush_icache_range(single_step_data.address[i],
  95                                single_step_data.address[i] +
  96                                BREAK_INSTR_SIZE);
  97                }
  98                single_step_data.armed = 0;
  99        }
 100}
 101
 102static void place_trap(unsigned long address, void *save)
 103{
 104        memcpy(save, (void *) address, BREAK_INSTR_SIZE);
 105        memcpy((void *) address, &arch_kgdb_ops.gdb_bpt_instr,
 106                BREAK_INSTR_SIZE);
 107        flush_icache_range(address, address + BREAK_INSTR_SIZE);
 108}
 109
 110static void do_single_step(struct pt_regs *regs)
 111{
 112        single_step_data.is_branch = disasm_next_pc((unsigned long)
 113                regs->ret, regs, (struct callee_regs *)
 114                current->thread.callee_reg,
 115                &single_step_data.address[0],
 116                &single_step_data.address[1]);
 117
 118        place_trap(single_step_data.address[0], &single_step_data.opcode[0]);
 119
 120        if (single_step_data.is_branch) {
 121                place_trap(single_step_data.address[1],
 122                        &single_step_data.opcode[1]);
 123        }
 124
 125        single_step_data.armed++;
 126}
 127
 128int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
 129                               char *remcomInBuffer, char *remcomOutBuffer,
 130                               struct pt_regs *regs)
 131{
 132        unsigned long addr;
 133        char *ptr;
 134
 135        undo_single_step(regs);
 136
 137        switch (remcomInBuffer[0]) {
 138        case 's':
 139        case 'c':
 140                ptr = &remcomInBuffer[1];
 141                if (kgdb_hex2long(&ptr, &addr))
 142                        regs->ret = addr;
 143                fallthrough;
 144
 145        case 'D':
 146        case 'k':
 147                atomic_set(&kgdb_cpu_doing_single_step, -1);
 148
 149                if (remcomInBuffer[0] == 's') {
 150                        do_single_step(regs);
 151                        atomic_set(&kgdb_cpu_doing_single_step,
 152                                   smp_processor_id());
 153                }
 154
 155                return 0;
 156        }
 157        return -1;
 158}
 159
 160int kgdb_arch_init(void)
 161{
 162        single_step_data.armed = 0;
 163        return 0;
 164}
 165
 166void kgdb_trap(struct pt_regs *regs)
 167{
 168        /* trap_s 3 is used for breakpoints that overwrite existing
 169         * instructions, while trap_s 4 is used for compiled breakpoints.
 170         *
 171         * with trap_s 3 breakpoints the original instruction needs to be
 172         * restored and continuation needs to start at the location of the
 173         * breakpoint.
 174         *
 175         * with trap_s 4 (compiled) breakpoints, continuation needs to
 176         * start after the breakpoint.
 177         */
 178        if (regs->ecr_param == 3)
 179                instruction_pointer(regs) -= BREAK_INSTR_SIZE;
 180
 181        kgdb_handle_exception(1, SIGTRAP, 0, regs);
 182}
 183
 184void kgdb_arch_exit(void)
 185{
 186}
 187
 188void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 189{
 190        instruction_pointer(regs) = ip;
 191}
 192
 193void kgdb_call_nmi_hook(void *ignored)
 194{
 195        /* Default implementation passes get_irq_regs() but we don't */
 196        kgdb_nmicallback(raw_smp_processor_id(), NULL);
 197}
 198
 199const struct kgdb_arch arch_kgdb_ops = {
 200        /* breakpoint instruction: TRAP_S 0x3 */
 201#ifdef CONFIG_CPU_BIG_ENDIAN
 202        .gdb_bpt_instr          = {0x78, 0x7e},
 203#else
 204        .gdb_bpt_instr          = {0x7e, 0x78},
 205#endif
 206};
 207