Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/frv/kernel/debug-stub.c
10817 views
1
/* debug-stub.c: debug-mode stub
2
*
3
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4
* Written by David Howells ([email protected])
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version
9
* 2 of the License, or (at your option) any later version.
10
*/
11
12
#include <linux/string.h>
13
#include <linux/kernel.h>
14
#include <linux/signal.h>
15
#include <linux/sched.h>
16
#include <linux/init.h>
17
#include <linux/serial_reg.h>
18
#include <linux/start_kernel.h>
19
20
#include <asm/system.h>
21
#include <asm/serial-regs.h>
22
#include <asm/timer-regs.h>
23
#include <asm/irc-regs.h>
24
#include <asm/gdb-stub.h>
25
#include "gdb-io.h"
26
27
/* CPU board CON5 */
28
#define __UART0(X) (*(volatile uint8_t *)(UART0_BASE + (UART_##X)))
29
30
#define LSR_WAIT_FOR0(STATE) \
31
do { \
32
} while (!(__UART0(LSR) & UART_LSR_##STATE))
33
34
#define FLOWCTL_QUERY0(LINE) ({ __UART0(MSR) & UART_MSR_##LINE; })
35
#define FLOWCTL_CLEAR0(LINE) do { __UART0(MCR) &= ~UART_MCR_##LINE; } while (0)
36
#define FLOWCTL_SET0(LINE) do { __UART0(MCR) |= UART_MCR_##LINE; } while (0)
37
38
#define FLOWCTL_WAIT_FOR0(LINE) \
39
do { \
40
gdbstub_do_rx(); \
41
} while(!FLOWCTL_QUERY(LINE))
42
43
struct frv_debug_status __debug_status;
44
45
static void __init debug_stub_init(void);
46
47
/*****************************************************************************/
48
/*
49
* debug mode handler stub
50
* - we come here with the CPU in debug mode and with exceptions disabled
51
* - handle debugging services for userspace
52
*/
53
asmlinkage void debug_stub(void)
54
{
55
unsigned long hsr0;
56
int type = 0;
57
58
static u8 inited = 0;
59
if (!inited) {
60
debug_stub_init();
61
type = -1;
62
inited = 1;
63
}
64
65
hsr0 = __get_HSR(0);
66
if (hsr0 & HSR0_ETMD)
67
__set_HSR(0, hsr0 & ~HSR0_ETMD);
68
69
/* disable single stepping */
70
__debug_status.dcr &= ~DCR_SE;
71
72
/* kernel mode can propose an exception be handled in debug mode by jumping to a special
73
* location */
74
if (__debug_frame->pc == (unsigned long) __break_hijack_kernel_event_breaks_here) {
75
/* replace the debug frame with the kernel frame and discard
76
* the top kernel context */
77
*__debug_frame = *__frame;
78
__frame = __debug_frame->next_frame;
79
__debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12;
80
__debug_status.brr |= BRR_EB;
81
}
82
83
if (__debug_frame->pc == (unsigned long) __debug_bug_trap + 4) {
84
__debug_frame->pc = __debug_frame->lr;
85
type = __debug_frame->gr8;
86
}
87
88
#ifdef CONFIG_GDBSTUB
89
gdbstub(type);
90
#endif
91
92
if (hsr0 & HSR0_ETMD)
93
__set_HSR(0, __get_HSR(0) | HSR0_ETMD);
94
95
} /* end debug_stub() */
96
97
/*****************************************************************************/
98
/*
99
* debug stub initialisation
100
*/
101
static void __init debug_stub_init(void)
102
{
103
__set_IRR(6, 0xff000000); /* map ERRs to NMI */
104
__set_IITMR(1, 0x20000000); /* ERR0/1, UART0/1 IRQ detect levels */
105
106
asm volatile(" movgs gr0,ibar0 \n"
107
" movgs gr0,ibar1 \n"
108
" movgs gr0,ibar2 \n"
109
" movgs gr0,ibar3 \n"
110
" movgs gr0,dbar0 \n"
111
" movgs gr0,dbmr00 \n"
112
" movgs gr0,dbmr01 \n"
113
" movgs gr0,dbdr00 \n"
114
" movgs gr0,dbdr01 \n"
115
" movgs gr0,dbar1 \n"
116
" movgs gr0,dbmr10 \n"
117
" movgs gr0,dbmr11 \n"
118
" movgs gr0,dbdr10 \n"
119
" movgs gr0,dbdr11 \n"
120
);
121
122
/* deal with debugging stub initialisation and initial pause */
123
if (__debug_frame->pc == (unsigned long) __debug_stub_init_break)
124
__debug_frame->pc = (unsigned long) start_kernel;
125
126
/* enable the debug events we want to trap */
127
__debug_status.dcr = DCR_EBE;
128
129
#ifdef CONFIG_GDBSTUB
130
gdbstub_init();
131
#endif
132
133
__clr_MASK_all();
134
__clr_MASK(15);
135
__clr_RC(15);
136
137
} /* end debug_stub_init() */
138
139
/*****************************************************************************/
140
/*
141
* kernel "exit" trap for gdb stub
142
*/
143
void debug_stub_exit(int status)
144
{
145
146
#ifdef CONFIG_GDBSTUB
147
gdbstub_exit(status);
148
#endif
149
150
} /* end debug_stub_exit() */
151
152
/*****************************************************************************/
153
/*
154
* send string to serial port
155
*/
156
void debug_to_serial(const char *p, int n)
157
{
158
char ch;
159
160
for (; n > 0; n--) {
161
ch = *p++;
162
FLOWCTL_SET0(DTR);
163
LSR_WAIT_FOR0(THRE);
164
// FLOWCTL_WAIT_FOR(CTS);
165
166
if (ch == 0x0a) {
167
__UART0(TX) = 0x0d;
168
mb();
169
LSR_WAIT_FOR0(THRE);
170
// FLOWCTL_WAIT_FOR(CTS);
171
}
172
__UART0(TX) = ch;
173
mb();
174
175
FLOWCTL_CLEAR0(DTR);
176
}
177
178
} /* end debug_to_serial() */
179
180
/*****************************************************************************/
181
/*
182
* send string to serial port
183
*/
184
void debug_to_serial2(const char *fmt, ...)
185
{
186
va_list va;
187
char buf[64];
188
int n;
189
190
va_start(va, fmt);
191
n = vsprintf(buf, fmt, va);
192
va_end(va);
193
194
debug_to_serial(buf, n);
195
196
} /* end debug_to_serial2() */
197
198
/*****************************************************************************/
199
/*
200
* set up the ttyS0 serial port baud rate timers
201
*/
202
void __init console_set_baud(unsigned baud)
203
{
204
unsigned value, high, low;
205
u8 lcr;
206
207
/* work out the divisor to give us the nearest higher baud rate */
208
value = __serial_clock_speed_HZ / 16 / baud;
209
210
/* determine the baud rate range */
211
high = __serial_clock_speed_HZ / 16 / value;
212
low = __serial_clock_speed_HZ / 16 / (value + 1);
213
214
/* pick the nearest bound */
215
if (low + (high - low) / 2 > baud)
216
value++;
217
218
lcr = __UART0(LCR);
219
__UART0(LCR) |= UART_LCR_DLAB;
220
mb();
221
__UART0(DLL) = value & 0xff;
222
__UART0(DLM) = (value >> 8) & 0xff;
223
mb();
224
__UART0(LCR) = lcr;
225
mb();
226
227
} /* end console_set_baud() */
228
229
/*****************************************************************************/
230
/*
231
*
232
*/
233
int __init console_get_baud(void)
234
{
235
unsigned value;
236
u8 lcr;
237
238
lcr = __UART0(LCR);
239
__UART0(LCR) |= UART_LCR_DLAB;
240
mb();
241
value = __UART0(DLM) << 8;
242
value |= __UART0(DLL);
243
__UART0(LCR) = lcr;
244
mb();
245
246
return value;
247
} /* end console_get_baud() */
248
249
/*****************************************************************************/
250
/*
251
* display BUG() info
252
*/
253
#ifndef CONFIG_NO_KERNEL_MSG
254
void __debug_bug_printk(const char *file, unsigned line)
255
{
256
printk("kernel BUG at %s:%d!\n", file, line);
257
258
} /* end __debug_bug_printk() */
259
#endif
260
261