gdbmain.c
6.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*---------------------------------------------------------------------*
* Copyright (C) 2004 BroadOn Communications Corp.
*
* $RCSfile: gdbmain.c,v $ (derived from rmonmain.c)
* $Revision: 1.4 $
* $Date: 2004/02/18 02:59:00 $
*---------------------------------------------------------------------*/
/*
* The GDB stub for the BBPlayer provides a mechanism for GDB to talk
* to and debug programs on the BBPlayer. The GDB stub is composed of
* two threads: a main thread responsible to monitoring and handling
* CPU break and fault, and a second thread responsible for communicating
* with GDB using the GDB Remote Serial Protocol via RDB and USB.
*/
#include "ultragdb.h"
#include "osint.h"
#include "os_bb.h"
#ifndef _FINALROM
char *gdb_module_name = "GDB Handler";
int gdbDebug = 0; /* GDB_DEBUG_SHOW_INFO | GDB_DEBUG_SHOW_ERROR */
int gdbShowAllThreadsFlag = 1;
int gdbStopUserThreadsFlag = 1;
int gdbWaitToSendBreakFlag = 1;
int gdbReplaceEventMQs = 0;
int __gdbActive = 0; /* flag so others can know if gdb is alive */
static vu32 __gdbToDo;
/* GDB Main Message Queue */
static OSMesgQueue __gdbMQ;
static OSMesg gdbMsgs[8];
/* GDB IO Thread and stack */
static OSThread gdbIOThread;
static double gdbIOStack[0x800];
/* GDB Main Thread and stack */
static OSThread gdbThread;
static u64 gdbStack[GDB_STACKSIZE/sizeof(u64)] __attribute__ ((aligned (8)));
static OSMesg gdbPiMsgs[8];
static OSMesgQueue gdbPiMQ;
extern __OSEventState __osEventStateTab[];
void gdbMain(void);
void gdbInit()
{
/* If GDB is already running, simply return */
if (__gdbActive)
return;
/* Create and start GDB Main Thread */
osCreateThread(&gdbThread, OS_TID_GDBMAIN, (VFUNPTR) gdbMain, (void *)0,
(void *)(gdbStack+GDB_STACKSIZE/sizeof(u64)),
(OSPri) OS_PRIORITY_GDB );
osStartThread(&gdbThread);
}
/************************************************************************
Function: __gdbSetEventMesg
Args: OSEvent e - Event
OSMesgQueue mq - Message Queue to associate with event
OSMesg m - Message to associate with event
int replaceMQ - Whether to replace the existing message queue if
there is already a message queue associated with
the event.
Purpose: This function associates a event with a message queue (like
osSetEventMesg) but also has an option of checking to see if the
event already has an message queue associated with it.
************************************************************************/
void __gdbSetEventMesg(OSEvent e, OSMesgQueue *mq, OSMesg m, int replaceMQ)
{
u32 saveMask;
/* Disable interrupts */
saveMask = __osDisableInt();
if (!replaceMQ)
{
/* We don't want to replace the message queue for this event if
it has already be set */
/* Make sure we have a valid event */
if (e < OS_NUM_EVENTS)
{
__OSEventState *es = &__osEventStateTab[e];
/* If the event already has a message queue subscribed to it,
let's just return */
if (es->messageQueue) {
/* Restore interrupts */
__osRestoreInt(saveMask);
return;
}
}
}
/* We do want to set the event */
osSetEventMesg(e, mq, m);
/* Restore interrupts */
__osRestoreInt(saveMask);
}
/************************************************************************
Function: __gdbInitRest
Args: none
Type: void
Purpose: This function does the rest of the initialization for GDB
************************************************************************/
static void __gdbInitRest(void)
{
/* Set up message queues */
osCreateMesgQueue( &__gdbMQ, gdbMsgs, 8 );
__gdbSetEventMesg( OS_EVENT_CPU_BREAK, &__gdbMQ, (OSMesg) MSG_BREAKPOINT, gdbReplaceEventMQs );
__gdbSetEventMesg( OS_EVENT_SP_BREAK, &__gdbMQ, (OSMesg) MSG_SPBREAKPOINT, gdbReplaceEventMQs );
__gdbSetEventMesg( OS_EVENT_FAULT, &__gdbMQ, (OSMesg) MSG_CPUFAULT, gdbReplaceEventMQs );
__gdbSetEventMesg( OS_EVENT_THREADSTATUS, &__gdbMQ, (OSMesg) 0, gdbReplaceEventMQs );
/* Create GDB IO Thread */
osCreateThread( &gdbIOThread, OS_TID_GDBIO, (VFUNPTR) __gdbIOhandler, 0,
&gdbIOStack[0x800], (OSPri) 255 );
/*
Note that Pi manager must start before IO manager, since the
latter requests the former's command queue address at startup.
It should be legal to start one, even if one is already
running (will just fail).
*/
osCreatePiManager( (OSPri) OS_PRIORITY_PIMGR, &gdbPiMQ, gdbPiMsgs, 8 );
osStartThread( &gdbIOThread );
}
/************************************************************************
Function: gdbMain
Args: none
Type: void
Purpose: This is the main loop of the gdb debugger.
It waits for and handles CPU breaks and faults.
************************************************************************/
void gdbMain( void )
{
/* Check to see if a GDB thread is already active - if so just return */
if (__gdbActive) return;
__gdbActive = 1;
__gdbInitRest();
/*
* Loop forever acquiring commands
*/
__gdbToDo = 0;
while (1)
{
OSMesg work;
if (gdbDebug & GDB_DEBUG_SHOW_INFO)
GDB_PRINTF("%s: Waiting for break.\n", gdb_module_name);
osRecvMesg( &__gdbMQ, &work, OS_MESG_BLOCK );
__gdbToDo |= (u32) work;
if ( __gdbToDo & MSG_BREAKPOINT )
{
if (gdbDebug & GDB_DEBUG_SHOW_INFO)
GDB_PRINTF("%s: CPU Breakpoint\n", gdb_module_name);
__gdbToDo &= ~MSG_BREAKPOINT;
__gdbHitBreak();
}
if ( __gdbToDo & MSG_SPBREAKPOINT )
{
if (gdbDebug & GDB_DEBUG_SHOW_INFO)
GDB_PRINTF("%s: RCP Breakpoint\n", gdb_module_name);
__gdbToDo &= ~MSG_SPBREAKPOINT;
/* NOT supported */
/* __rmonHitSpBreak(); */
}
if ( __gdbToDo & MSG_CPUFAULT )
{
if (gdbDebug & GDB_DEBUG_SHOW_INFO)
GDB_PRINTF("%s: CPU Fault\n", gdb_module_name);
__gdbToDo &= ~MSG_CPUFAULT;
__gdbHitCpuFault();
}
if ( __gdbToDo & MSG_THREADCREATE )
{
if (gdbDebug & GDB_DEBUG_SHOW_INFO)
GDB_PRINTF("%s: Thread %d created\n",
gdb_module_name, __gdbToDo >> 8);
__gdbToDo &= ~(MSG_THREADCREATE | 0xffffff00);
}
if ( __gdbToDo & MSG_THREADDESTROY )
{
if (gdbDebug & GDB_DEBUG_SHOW_INFO)
GDB_PRINTF("%s: Thread %d destroyed\n",
gdb_module_name, __gdbToDo >> 8);
__gdbToDo &= ~(MSG_THREADDESTROY | 0xffffff00);
}
}
}
#endif /* #ifndef _FINALROM */