Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sparc/kernel/kgdb_64.c
10818 views
1
/* kgdb.c: KGDB support for 64-bit sparc.
2
*
3
* Copyright (C) 2008 David S. Miller <[email protected]>
4
*/
5
6
#include <linux/kgdb.h>
7
#include <linux/kdebug.h>
8
#include <linux/ftrace.h>
9
10
#include <asm/kdebug.h>
11
#include <asm/ptrace.h>
12
#include <asm/irq.h>
13
14
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
15
{
16
struct reg_window *win;
17
int i;
18
19
gdb_regs[GDB_G0] = 0;
20
for (i = 0; i < 15; i++)
21
gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
22
23
win = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS);
24
for (i = 0; i < 8; i++)
25
gdb_regs[GDB_L0 + i] = win->locals[i];
26
for (i = 0; i < 8; i++)
27
gdb_regs[GDB_I0 + i] = win->ins[i];
28
29
for (i = GDB_F0; i <= GDB_F62; i++)
30
gdb_regs[i] = 0;
31
32
gdb_regs[GDB_PC] = regs->tpc;
33
gdb_regs[GDB_NPC] = regs->tnpc;
34
gdb_regs[GDB_STATE] = regs->tstate;
35
gdb_regs[GDB_FSR] = 0;
36
gdb_regs[GDB_FPRS] = 0;
37
gdb_regs[GDB_Y] = regs->y;
38
}
39
40
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
41
{
42
struct thread_info *t = task_thread_info(p);
43
extern unsigned int switch_to_pc;
44
extern unsigned int ret_from_syscall;
45
struct reg_window *win;
46
unsigned long pc, cwp;
47
int i;
48
49
for (i = GDB_G0; i < GDB_G6; i++)
50
gdb_regs[i] = 0;
51
gdb_regs[GDB_G6] = (unsigned long) t;
52
gdb_regs[GDB_G7] = (unsigned long) p;
53
for (i = GDB_O0; i < GDB_SP; i++)
54
gdb_regs[i] = 0;
55
gdb_regs[GDB_SP] = t->ksp;
56
gdb_regs[GDB_O7] = 0;
57
58
win = (struct reg_window *) (t->ksp + STACK_BIAS);
59
for (i = 0; i < 8; i++)
60
gdb_regs[GDB_L0 + i] = win->locals[i];
61
for (i = 0; i < 8; i++)
62
gdb_regs[GDB_I0 + i] = win->ins[i];
63
64
for (i = GDB_F0; i <= GDB_F62; i++)
65
gdb_regs[i] = 0;
66
67
if (t->new_child)
68
pc = (unsigned long) &ret_from_syscall;
69
else
70
pc = (unsigned long) &switch_to_pc;
71
72
gdb_regs[GDB_PC] = pc;
73
gdb_regs[GDB_NPC] = pc + 4;
74
75
cwp = __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP];
76
77
gdb_regs[GDB_STATE] = (TSTATE_PRIV | TSTATE_IE | cwp);
78
gdb_regs[GDB_FSR] = 0;
79
gdb_regs[GDB_FPRS] = 0;
80
gdb_regs[GDB_Y] = 0;
81
}
82
83
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
84
{
85
struct reg_window *win;
86
int i;
87
88
for (i = 0; i < 15; i++)
89
regs->u_regs[UREG_G1 + i] = gdb_regs[GDB_G1 + i];
90
91
/* If the TSTATE register is changing, we have to preserve
92
* the CWP field, otherwise window save/restore explodes.
93
*/
94
if (regs->tstate != gdb_regs[GDB_STATE]) {
95
unsigned long cwp = regs->tstate & TSTATE_CWP;
96
97
regs->tstate = (gdb_regs[GDB_STATE] & ~TSTATE_CWP) | cwp;
98
}
99
100
regs->tpc = gdb_regs[GDB_PC];
101
regs->tnpc = gdb_regs[GDB_NPC];
102
regs->y = gdb_regs[GDB_Y];
103
104
win = (struct reg_window *) (regs->u_regs[UREG_FP] + STACK_BIAS);
105
for (i = 0; i < 8; i++)
106
win->locals[i] = gdb_regs[GDB_L0 + i];
107
for (i = 0; i < 8; i++)
108
win->ins[i] = gdb_regs[GDB_I0 + i];
109
}
110
111
#ifdef CONFIG_SMP
112
void __irq_entry smp_kgdb_capture_client(int irq, struct pt_regs *regs)
113
{
114
unsigned long flags;
115
116
__asm__ __volatile__("rdpr %%pstate, %0\n\t"
117
"wrpr %0, %1, %%pstate"
118
: "=r" (flags)
119
: "i" (PSTATE_IE));
120
121
flushw_all();
122
123
if (atomic_read(&kgdb_active) != -1)
124
kgdb_nmicallback(raw_smp_processor_id(), regs);
125
126
__asm__ __volatile__("wrpr %0, 0, %%pstate"
127
: : "r" (flags));
128
}
129
#endif
130
131
int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
132
char *remcomInBuffer, char *remcomOutBuffer,
133
struct pt_regs *linux_regs)
134
{
135
unsigned long addr;
136
char *ptr;
137
138
switch (remcomInBuffer[0]) {
139
case 'c':
140
/* try to read optional parameter, pc unchanged if no parm */
141
ptr = &remcomInBuffer[1];
142
if (kgdb_hex2long(&ptr, &addr)) {
143
linux_regs->tpc = addr;
144
linux_regs->tnpc = addr + 4;
145
}
146
/* fallthru */
147
148
case 'D':
149
case 'k':
150
if (linux_regs->tpc == (unsigned long) arch_kgdb_breakpoint) {
151
linux_regs->tpc = linux_regs->tnpc;
152
linux_regs->tnpc += 4;
153
}
154
return 0;
155
}
156
return -1;
157
}
158
159
asmlinkage void kgdb_trap(unsigned long trap_level, struct pt_regs *regs)
160
{
161
unsigned long flags;
162
163
if (user_mode(regs)) {
164
bad_trap(regs, trap_level);
165
return;
166
}
167
168
flushw_all();
169
170
local_irq_save(flags);
171
kgdb_handle_exception(0x172, SIGTRAP, 0, regs);
172
local_irq_restore(flags);
173
}
174
175
int kgdb_arch_init(void)
176
{
177
return 0;
178
}
179
180
void kgdb_arch_exit(void)
181
{
182
}
183
184
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
185
{
186
regs->tpc = ip;
187
regs->tnpc = regs->tpc + 4;
188
}
189
190
struct kgdb_arch arch_kgdb_ops = {
191
/* Breakpoint instruction: ta 0x72 */
192
.gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x72 },
193
};
194
195