Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
hexagon
kernel
kgdb.c
Go to the documentation of this file.
1
/*
2
* arch/hexagon/kernel/kgdb.c - Hexagon KGDB Support
3
*
4
* Copyright (c) 2011, The Linux Foundation. All rights reserved.
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 and
8
* only version 2 as published by the Free Software Foundation.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
* 02110-1301, USA.
19
*/
20
21
#include <
linux/kdebug.h
>
22
#include <
linux/kgdb.h
>
23
24
/* All registers are 4 bytes, for now */
25
#define GDB_SIZEOF_REG 4
26
27
/* The register names are used during printing of the regs;
28
* Keep these at three letters to pretty-print. */
29
struct
dbg_reg_def_t
dbg_reg_def
[
DBG_MAX_REG_NUM
] = {
30
{
" r0"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, r00)},
31
{
" r1"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, r01)},
32
{
" r2"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, r02)},
33
{
" r3"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, r03)},
34
{
" r4"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, r04)},
35
{
" r5"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, r05)},
36
{
" r6"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, r06)},
37
{
" r7"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, r07)},
38
{
" r8"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, r08)},
39
{
" r9"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, r09)},
40
{
"r10"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r10
)},
41
{
"r11"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r11
)},
42
{
"r12"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r12
)},
43
{
"r13"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r13
)},
44
{
"r14"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r14
)},
45
{
"r15"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r15
)},
46
{
"r16"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r16
)},
47
{
"r17"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r17
)},
48
{
"r18"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r18
)},
49
{
"r19"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r19
)},
50
{
"r20"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r20
)},
51
{
"r21"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r21
)},
52
{
"r22"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r22
)},
53
{
"r23"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r23
)},
54
{
"r24"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r24
)},
55
{
"r25"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r25
)},
56
{
"r26"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r26
)},
57
{
"r27"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r27
)},
58
{
"r28"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r28
)},
59
{
"r29"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r29
)},
60
{
"r30"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r30
)},
61
{
"r31"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
r31
)},
62
63
{
"usr"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, usr)},
64
{
"preds"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, preds)},
65
{
" m0"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, m0)},
66
{
" m1"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, m1)},
67
{
"sa0"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, sa0)},
68
{
"sa1"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, sa1)},
69
{
"lc0"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, lc0)},
70
{
"lc1"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, lc1)},
71
{
" gp"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
,
gp
)},
72
{
"ugp"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, ugp)},
73
{
"psp"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, hvmer.vmpsp)},
74
{
"elr"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, hvmer.vmel)},
75
{
"est"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, hvmer.vmest)},
76
{
"badva"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, hvmer.vmbadva)},
77
{
"restart_r0"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, restart_r0)},
78
{
"syscall_nr"
,
GDB_SIZEOF_REG
,
offsetof
(
struct
pt_regs
, syscall_nr)},
79
};
80
81
struct
kgdb_arch
arch_kgdb_ops
= {
82
/* trap0(#0xDB) 0x0cdb0054 */
83
.gdb_bpt_instr = {0x54, 0x00, 0xdb, 0x0c},
84
};
85
86
char
*
dbg_get_reg
(
int
regno,
void
*
mem
,
struct
pt_regs
*
regs
)
87
{
88
if
(regno >=
DBG_MAX_REG_NUM
|| regno < 0)
89
return
NULL
;
90
91
*((
unsigned
long
*) mem) = *((
unsigned
long
*) ((
void
*)regs +
92
dbg_reg_def
[regno].offset));
93
94
return
dbg_reg_def
[regno].name;
95
}
96
97
int
dbg_set_reg
(
int
regno,
void
*
mem
,
struct
pt_regs
*
regs
)
98
{
99
if
(regno >=
DBG_MAX_REG_NUM
|| regno < 0)
100
return
-
EINVAL
;
101
102
*((
unsigned
long
*) ((
void
*)regs +
dbg_reg_def
[regno].offset)) =
103
*((
unsigned
long
*) mem);
104
105
return
0;
106
}
107
108
void
kgdb_arch_set_pc
(
struct
pt_regs
*
regs
,
unsigned
long
pc
)
109
{
110
instruction_pointer
(regs) =
pc
;
111
}
112
113
#ifdef CONFIG_SMP
114
132
static
void
hexagon_kgdb_nmi_hook(
void
*
ignored
)
133
{
134
kgdb_nmicallback
(
raw_smp_processor_id
(),
get_irq_regs
());
135
}
136
137
void
kgdb_roundup_cpus
(
unsigned
long
flags
)
138
{
139
local_irq_enable
();
140
smp_call_function
(hexagon_kgdb_nmi_hook,
NULL
, 0);
141
local_irq_disable
();
142
}
143
#endif
144
145
146
/* Not yet working */
147
void
sleeping_thread_to_gdb_regs
(
unsigned
long
*
gdb_regs
,
148
struct
task_struct
*
task
)
149
{
150
struct
pt_regs
*thread_regs;
151
152
if
(task ==
NULL
)
153
return
;
154
155
/* Initialize to zero */
156
memset
(gdb_regs, 0,
NUMREGBYTES
);
157
158
/* Otherwise, we have only some registers from switch_to() */
159
thread_regs =
task_pt_regs
(task);
160
gdb_regs[0] = thread_regs->
r00
;
161
}
162
181
int
kgdb_arch_handle_exception
(
int
vector
,
int
signo,
int
err_code
,
182
char
*remcom_in_buffer,
char
*remcom_out_buffer,
183
struct
pt_regs
*linux_regs)
184
{
185
switch
(remcom_in_buffer[0]) {
186
case
's'
:
187
case
'c'
:
188
return
0;
189
}
190
/* Stay in the debugger. */
191
return
-1;
192
}
193
194
static
int
__kgdb_notify(
struct
die_args
*
args
,
unsigned
long
cmd
)
195
{
196
/* cpu roundup */
197
if
(
atomic_read
(&
kgdb_active
) != -1) {
198
kgdb_nmicallback
(
smp_processor_id
(), args->
regs
);
199
return
NOTIFY_STOP;
200
}
201
202
if
(
user_mode
(args->
regs
))
203
return
NOTIFY_DONE;
204
205
if
(
kgdb_handle_exception
(args->
trapnr
& 0xff, args->
signr
, args->
err
,
206
args->
regs
))
207
return
NOTIFY_DONE;
208
209
return
NOTIFY_STOP;
210
}
211
212
static
int
213
kgdb_notify(
struct
notifier_block
*
self
,
unsigned
long
cmd,
void
*
ptr
)
214
{
215
unsigned
long
flags
;
216
int
ret
;
217
218
local_irq_save
(flags);
219
ret = __kgdb_notify(ptr, cmd);
220
local_irq_restore
(flags);
221
222
return
ret
;
223
}
224
225
static
struct
notifier_block
kgdb_notifier = {
226
.notifier_call = kgdb_notify,
227
228
/*
229
* Lowest-prio notifier priority, we want to be notified last:
230
*/
231
.priority = -
INT_MAX
,
232
};
233
240
int
kgdb_arch_init
(
void
)
241
{
242
return
register_die_notifier
(&kgdb_notifier);
243
}
244
251
void
kgdb_arch_exit
(
void
)
252
{
253
unregister_die_notifier
(&kgdb_notifier);
254
}
Generated on Thu Jan 10 2013 12:56:11 for Linux Kernel by
1.8.2