Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/sparc/kernel/kgdb_32.c
10817 views
1
/* kgdb.c: KGDB support for 32-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
9
#include <asm/kdebug.h>
10
#include <asm/ptrace.h>
11
#include <asm/irq.h>
12
13
extern unsigned long trapbase;
14
15
void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
16
{
17
struct reg_window32 *win;
18
int i;
19
20
gdb_regs[GDB_G0] = 0;
21
for (i = 0; i < 15; i++)
22
gdb_regs[GDB_G1 + i] = regs->u_regs[UREG_G1 + i];
23
24
win = (struct reg_window32 *) regs->u_regs[UREG_FP];
25
for (i = 0; i < 8; i++)
26
gdb_regs[GDB_L0 + i] = win->locals[i];
27
for (i = 0; i < 8; i++)
28
gdb_regs[GDB_I0 + i] = win->ins[i];
29
30
for (i = GDB_F0; i <= GDB_F31; i++)
31
gdb_regs[i] = 0;
32
33
gdb_regs[GDB_Y] = regs->y;
34
gdb_regs[GDB_PSR] = regs->psr;
35
gdb_regs[GDB_WIM] = 0;
36
gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
37
gdb_regs[GDB_PC] = regs->pc;
38
gdb_regs[GDB_NPC] = regs->npc;
39
gdb_regs[GDB_FSR] = 0;
40
gdb_regs[GDB_CSR] = 0;
41
}
42
43
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
44
{
45
struct thread_info *t = task_thread_info(p);
46
struct reg_window32 *win;
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] = 0;
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_window32 *) t->ksp;
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_F31; i++)
65
gdb_regs[i] = 0;
66
67
gdb_regs[GDB_Y] = 0;
68
69
gdb_regs[GDB_PSR] = t->kpsr;
70
gdb_regs[GDB_WIM] = t->kwim;
71
gdb_regs[GDB_TBR] = (unsigned long) &trapbase;
72
gdb_regs[GDB_PC] = t->kpc;
73
gdb_regs[GDB_NPC] = t->kpc + 4;
74
gdb_regs[GDB_FSR] = 0;
75
gdb_regs[GDB_CSR] = 0;
76
}
77
78
void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
79
{
80
struct reg_window32 *win;
81
int i;
82
83
for (i = 0; i < 15; i++)
84
regs->u_regs[UREG_G1 + i] = gdb_regs[GDB_G1 + i];
85
86
/* If the PSR register is changing, we have to preserve
87
* the CWP field, otherwise window save/restore explodes.
88
*/
89
if (regs->psr != gdb_regs[GDB_PSR]) {
90
unsigned long cwp = regs->psr & PSR_CWP;
91
92
regs->psr = (gdb_regs[GDB_PSR] & ~PSR_CWP) | cwp;
93
}
94
95
regs->pc = gdb_regs[GDB_PC];
96
regs->npc = gdb_regs[GDB_NPC];
97
regs->y = gdb_regs[GDB_Y];
98
99
win = (struct reg_window32 *) regs->u_regs[UREG_FP];
100
for (i = 0; i < 8; i++)
101
win->locals[i] = gdb_regs[GDB_L0 + i];
102
for (i = 0; i < 8; i++)
103
win->ins[i] = gdb_regs[GDB_I0 + i];
104
}
105
106
int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
107
char *remcomInBuffer, char *remcomOutBuffer,
108
struct pt_regs *linux_regs)
109
{
110
unsigned long addr;
111
char *ptr;
112
113
switch (remcomInBuffer[0]) {
114
case 'c':
115
/* try to read optional parameter, pc unchanged if no parm */
116
ptr = &remcomInBuffer[1];
117
if (kgdb_hex2long(&ptr, &addr)) {
118
linux_regs->pc = addr;
119
linux_regs->npc = addr + 4;
120
}
121
/* fallthru */
122
123
case 'D':
124
case 'k':
125
if (linux_regs->pc == (unsigned long) arch_kgdb_breakpoint) {
126
linux_regs->pc = linux_regs->npc;
127
linux_regs->npc += 4;
128
}
129
return 0;
130
}
131
return -1;
132
}
133
134
extern void do_hw_interrupt(struct pt_regs *regs, unsigned long type);
135
136
asmlinkage void kgdb_trap(struct pt_regs *regs)
137
{
138
unsigned long flags;
139
140
if (user_mode(regs)) {
141
do_hw_interrupt(regs, 0xfd);
142
return;
143
}
144
145
flushw_all();
146
147
local_irq_save(flags);
148
kgdb_handle_exception(0x172, SIGTRAP, 0, regs);
149
local_irq_restore(flags);
150
}
151
152
int kgdb_arch_init(void)
153
{
154
return 0;
155
}
156
157
void kgdb_arch_exit(void)
158
{
159
}
160
161
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
162
{
163
regs->pc = ip;
164
regs->npc = regs->pc + 4;
165
}
166
167
struct kgdb_arch arch_kgdb_ops = {
168
/* Breakpoint instruction: ta 0x7d */
169
.gdb_bpt_instr = { 0x91, 0xd0, 0x20, 0x7d },
170
};
171
172