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