forked from riscv/riscv-debug-spec
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdebug_module.tex
324 lines (265 loc) · 13.9 KB
/
debug_module.tex
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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
\chapter{Debug Module (DM)} \label{dm}
\begin{steps}{The Debug Module implements a translation interface between abstract debug
operations and their specific implementation. It might support the following
operations:}
\item Give the debugger necessary information about the implementation. (Required)
\item Allow any individual hart to be halted and resumed. (Required)
\item Provide status on which harts are halted. (Required)
\item Provide read and write access to a halted hart's GPRs. (Required)
\item Provide access to a reset signal that allows debugging out of reset.(Required)
\item Provide access to other hart registers. (Optional)
\item Provide an interface to force the hart to execute arbitrary instructions. (Optional)
\item Allow multiple harts to be halted, resumed, and/or reset at the same time. (Optional)
\item Allow system memory accesses. (Optional)
\end{steps}
A single DM can debug up to 1024 harts.
\section{Debug Module Interface (DMI)} \label{dmi}
The Debug Module is a slave to a bus called the Debug Module Interface (DMI). The
master of the bus is the Debug Transport Module(s).
The Debug Module Interface can be a trivial bus with one master and one slave,
or use a more full-featured bus like TileLink or the AMBA Advanced Peripheral
Bus. The details are left to the system designer.
The DMI uses between 7 and 32 address bits. It supports read and write
operations, which may return an error. (Errors are only returned by the optional
System Bus Access and Serial Port blocks). The bottom of the address space is
used for the DM. Extra space can be used for custom debug devices, other cores,
additional DMs, etc.
The Debug Module is controlled via register accesses to its DMI address space.
\begin{table}[htp]
\centering
\caption{Debug Module Interface Address Space}
\label{tab:header}
\begin{tabulary}{\textwidth}{|r|L|}
\hline
0x00 -- 0x3f & Registers described in Section~\ref{dmdebbus}. \\
\hline
0x40 -- 0x5f & There are 1024 bits here, one for each hart controlled
by this debug module. If the hart is halted, the bit is 1. Otherwise
the bit is 0. The bit for hart 0 is the LSB in the 32-bit word at 0x40.
The bit for hart 1023 is the MSB in the 32-bit word at 0x5f. \\
\hline
\end{tabulary}
\end{table}
\section{Reset Control} \label{reset}
The Debug Module controls a global reset signal, which can
reset, or hold in reset, every component in the platform,
except for the Debug Module and Debug
Transport Modules. The purpose of this feature is to allow debugging
programs from the first instruction executed, so exactly what is affected
by this reset is implementation dependent. The Debug Module's own state and registers are
generally reset at power-up and if and only if
\Fdmactive in \Rdmcontrol is 0. This means that the halt state of all harts is
maintained provided that \Fdmactive is 1, although trigger CSRs may be cleared.
Due to clock and power domain crossing issues,
it may not be possible to perform arbitrary DMI accesses across reset,
even if the Debug Module state is maintained. It must always be possible to access
the \Rdmcontrol register regardless of the system's reset state.
\section{Selecting Harts} \label{selectingharts}
Up to 1024 harts can be connected to a single DM. The debugger
selects a hart, and then subsequent halt, resume, reset, and debugging
commands are specific to that hart.
A debugger can enumerate all the harts
attached to the DM by selecting each hart starting from 0
until \Fanynonexistent is 1.
The debugger can discover the mapping between hart indices and
\Rmhartid by using the interface to read \Rmhartid, or by
reading the system's Configuration String.
\subsection {Selecting a Single Hart}
All debug modules must support selecting a single hart.
The debugger can select a hart by writing its index to \Fhartsel.
Hart indexes start at 0 and are continuous until the final index.
\subsection {Selecting Multiple Harts}
Debug Modules may optionally implement a Hart Array Mask register to allow
selecting multiple harts at once. The debugger can set bits in the hart array mask register
using \Rhawindowsel and \Rhawindow, then apply actions to all selected harts
by setting \Fhasel. If this feature is supported, multiple harts can be
halted, resumed, and reset simultaneously.
Only the actions initiated by \Rdmcontrol can apply to multiple harts
at once, Abstract Commands apply only to the hart selected by
\Fhartsel.
\section{Halt Control} \label{haltcontrol}
The Debug Module can halt harts and allow them to run again using
the \Rdmcontrol register.
When a debugger wants to halt a single hart it selects it in \Fhartsel
and sets \Fhaltreq, then waits
for \Fallhalted to indicate the hart is halted before clearing \Fhaltreq
to 0. Setting \Fhaltreq has no effect on a hart which is already halted.
To resume, the debugger selects the hart with \Fhartsel,
and sets \Fresumereq. This action sets the hart's
{\tt resumeack} bit to 0. Once the hart has resumed, it
sets its {\tt resumeack} bit to 1. Thus, the
debugger should wait for \Fallresumeack to indicate the
hart has resumed before clearing \Fresumereq to 0.
If a debugger reads \Fallresumeack
and \Fallhalted in the same cycle, the hart must have resumed
and then halted again.
\begin{commentary}
When waiting for a hart to resume, a debugger should
examine \Fallresumeack, not \Fallrunning
or \Fallhalted,
because the hart may immediately halt again due to
trigger or step conditions.
\end{commentary}
Setting \Fresumereq on hart which is running
clears {\tt resumeack} but
may cause a hart which halts in the future to immediately
resume. Debuggers should not depend on this behavior and should not
set \Fresumereq for running harts.
To halt or resume multiple harts at the same time, the debugger first
sets the hart's bits in the hart array mask register, then
follows the same procedure but with \Fhasel set to 1.
Depending on the desired operation, the debugger might consider the {\tt any*}
versions of the status instead of {\tt all*}.
When halt or resume is requested, a hart must respond in
less than one second, unless it is unavailable.
(How this is implemented is not further specified. A few
clock cycles will be a more typical latency).
\section{Abstract Commands} \label{abstractcommands}
The DM supports a set of abstract commands, most of which
are optional. Depending on the implementation, the debugger may
be able to perform
some abstract commands even when the selected hart is not halted.
Debuggers can only determine which abstract commands
are supported by a given hart in a given state by attempting them
and then looking at \Fcmderr in \Rabstractcs to see if they were successful.
Debuggers execute abstract commands by writing them to \Rcommand.
Debuggers can determine whether an abstract command is complete by
reading \Fbusy in \Rabstractcs.
If the command takes arguments, the debugger
must write them to the {\tt data} registers before writing to \Rcommand. If a
command returns results, the Debug Module must ensure they are placed
in the {\tt data} registers when the
command is complete. Which {\tt data} registers are used for the arguments is
described in Table~\ref{tab:datareg}. In all cases the least-significant word
is placed in the lowest-numbered {\tt data} register.
\begin{table}[htp]
\centering
\caption{Use of Data Registers}
\label{tab:datareg}
\begin{tabulary}{\textwidth}{|r|l|l|l|}
\hline
XLEN & arg0/return value & arg1 & arg2 \\
\hline
32 & \Rdatazero & {\tt data1} & {\tt data2} \\
\hline
64 & \Rdatazero, {\tt data1} & {\tt data2} , {\tt data3} & {\tt data4}, {\tt data5} \\
\hline
128 & \Rdatazero-- {\tt data3} & {\tt data4} -- {\tt data7} & {\tt data8} -- {\tt data11} \\
\hline
\end{tabulary}
\end{table}
\begin{table}[htp]
\centering
\caption{Abstract Register Numbers}
\label{tab:regno}
\begin{tabulary}{\textwidth}{|r|l|}
\hline
0x0000 -- 0x0fff & CSRs \\
\hline
0x1000 -- 0x101f & GPRs \\
\hline
0x1020 -- 0x103f & Floating point registers \\
\hline
0xc000 -- 0xffff & Reserved for non-standard extensions and internal
use. \\
\hline
\end{tabulary}
\end{table}
\subsection{Abstract Command Listing}
This section describes each of the different abstract commands
and how their fields should be interpreted when
they are written to \Rcommand.
\input{abstract_commands.tex}
\begin{figure}
\centering
\includegraphics[width=\textwidth]{fig/abstract_commands.pdf}
\caption[Run/Halt Debug State Machine]{Run/Halt Debug State Machine.
As only a small amount of state is visibile to the debugger,
the states and transitions are conceptual.}
\label{fig:abstract_sm}
\end{figure}
Figure~\ref{fig:abstract_sm} shows a conceptual view of the states
passed through by a hart during run/halt debugging as influenced
by the different fields of \Rdmcontrol, \Rabstractcs, \Rabstractauto, and
\Rcommand.
\section{Program Buffer} \label{programbuffer}
To support executing arbitrary instructions on a halted hart,
a Debug Module can include a
Program Buffer that a debugger can write small programs to. Systems
that support all necessary functionality using abstract commands
only may choose to omit the Program Buffer.
A debugger can write a small program to the Program Buffer, and then
execute it exactly once with the Access Register Abstract Command,
setting the \Fpostexec bit in \Rcommand.
If \Fprogsize is 1, the Program Buffer may only hold a single instruction.
This can be a 32-bit
instruction, or a compressed instruction in the lower 16 bits accompanied by a
compressed {\tt nop} in the upper 16 bits. If \Fprogsize is greater than 1,
the debugger can write whatever program it likes, but the program must end with
{\tt ebreak} or {\tt ebreak.c}.
While these programs are executed, the hart does not leave Debug Mode (see
Section~\ref{debugmode}). If an exception is encountered during execution of
the Program Buffer, no more instructions are executed, the hart remains in Debug
Mode, and \Fcmderr is set to 3({\tt exception error}).
Executing the Program Buffer may clobber \Rdpc. If that is the case, it must be
possible to read/write \Rdpc using an abstract command with \Fpostexec not set.
The debugger must attempt to save \Rdpc between halting and
executing a Program Buffer, and then restore \Rdpc before leaving Debug Mode.
\begin{commentary}
Allowing Program Buffer execution to clobber \Rdpc allows for direct
implementations that don't have a separate PC register, and do need to use
the PC when executing the Program Buffer.
\end{commentary}
The Program Buffer may be implemented as RAM which is accessible to the
hart as RAM memory. A debugger can determine if this is the case by executing small
programs that attempt to write relative to \Rpc while executing from the Program Buffer.
If so, the debugger has more flexibility in what it can do with the program buffer.
\section{System Bus Access} \label{systembusaccess}
When a Program Buffer is present, a debugger can access the system bus by having a
RISC-V hart perform the accesses it requires.
A Debug Module may include a System Bus Access block to provide memory access without
involving a hart, regardless of whether Program Buffer is implemented.
The System Bus Access block uses physical addresses.
\begin{commentary}
Implementing a System Bus Access block has several benefits even
when a Debug Module also implements a Program Buffer.
First, it is possible to
access memory in a running system with minimal impact. Second, it may improve
performance when accessing memory.
Third, it may provide
access to devices that a hart does not have access to.
\end{commentary}
\section{Quick Access}
Depending on the task it is performing, some harts can only be halted very briefly.
There are several mechanisms that allow accessing resources in such a running system
with a minimal impact on the running hart.
First, an implementation may allow some abstract commands to execute without halting the hart.
Second, the Quick Access abstract command can be used to halt a hart, quickly
execute the contents of the Program Buffer, and let the hart run again.
Combined with instructions that allow Program Buffer code to access the
{\tt data} registers, as described in \ref{hartinfo}, this can be used to quickly
perform a memory or register access. For some systems this will be too
intrusive, but many systems that can't be halted can bear an occasional hiccup
of a hundred or less cycles.
Third, if the System Bus Access block is implemented, it can be used while a
hart is running to access system memory.
\section{Security}
To protect intellectual property it may be desirable to lock access to the
Debug Module. To allow access during a manufacturing process and not
afterwards, a reasonable solution could be to add a fuse bit to the Debug
Module that can be used to be permanently disable it. Since this is technology
specific, it is not further addressed in this spec.
Another option is to allow the DM to be unlocked only by users who have an
access key. A few bits in \Rdmstatus and \Rauthdata can support an arbitrarily
complex authentication mechanism. When \Fauthenticated is clear, the DM must
not interact with the rest of the platform in any way.
\section{Serial Ports}
The Debug Module may implement up to 8 serial ports. They support basic flow
control and full duplex data transfer between a component and the debugger,
essentially allowing the Debug Transport to be used to communicate
with a debug monitor running on a hart, or more generally emulate devices which
aren't present. All these uses require software support, and are not further specified here.
Only the DMI side of the Debug Module serial registers are defined in this
specification as the core side interface should look like a peripheral device.
\section{Debug Module DMI Registers} \label{dmdebbus}
\input{dm_registers.tex}