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
//! Debug Triggers Extension (EID #0x44425452 "DBTR")
//!
//! The RISC-V Sdtrig extension allows machine-mode software to directly
//! configure debug triggers which in-turn allows native (or hosted) debugging in machine-mode
//! without any external debugger. Unfortunately, the debug triggers are only accessible to
//! machine-mode.
//!
//! The SBI debug trigger extension defines a SBI based abstraction to provide native debugging
//! for supervisor-mode software such that it is:
//! 1. Suitable for the rich operating systems and hypervisors running in supervisor-mode.
//! 2. Allows Guest (VS-mode) and Hypervisor (HS-mode) to share debug triggers on a hart.
//!
//! Each hart on a RISC-V platform has a fixed number of debug triggers which is referred
//! to as `trig_max` in this SBI extension. Each debug trigger is assigned a logical index
//! called `trig_idx` by the SBI implementation where `-1 < trig_idx < trig_max`.
use crate;
use ;
use *;
/// Get the number of debug triggers on the calling hart which can support the trigger
/// configuration specified by `trig_tdata1` parameter.
///
/// This function always returns `SbiRet::success()` in `SbiRet.error`. It will return `trig_max`
/// in `SbiRet.value` when `trig_tdata1 == 0` otherwise it will return the number of matching
/// debug triggers in `SbiRet.value`.
/// Set and enable the shared memory for debug trigger configuration on the calling hart.
///
/// If `shmem` is not all-ones bitwise then `shmem` specifies the bits of the shared memory physical base address.
/// The `shmem` MUST be `(XLEN / 8)` bytes aligned and the size of shared
/// memory is assumed to be `trig_max * (XLEN / 2)` bytes.
///
/// If `shmem` is all-ones bitwise then shared memory for debug trigger configuration is disabled
///
/// The `flags` parameter is reserved for future use and MUST be zero.
///
/// # Return value
///
/// | Error code | Description
/// |:------------------------------|:---------------------------------
/// | `SbiRet::success()` | Shared memory was set or cleared successfully.
/// | `SbiRet::invalid_param()` | The `flags` parameter is not zero or the `shmem` parameter is not `(XLEN / 8)` bytes aligned.
/// | `SbiRet::invalid_address()` | The shared memory pointed to by the `shmem` parameter does not satisfy the requirements.
/// | `SbiRet::failed()` | The request failed for unspecified or unknown other reasons.
/// Read the debug trigger state and configuration into shared memory for a range of
/// debug triggers specified by the `trig_idx_base` and `trig_count` parameters on the calling hart.
///
/// For each debug trigger with index `trig_idx_base + i` where `-1 < i < trig_count`, the
/// debug trigger state and configuration consisting of four XLEN-bit words are written in
/// little-endian format at `offset = i * (XLEN / 2)` of the shared memory as follows:
///
/// ```text
/// word[0] = `trig_state` written by the SBI implementation
/// word[1] = `trig_tdata1` written by the SBI implementation
/// word[2] = `trig_tdata2` written by the SBI implementation
/// word[3] = `trig_tdata3` written by the SBI implementation
/// ```
/// # Return value
///
/// | Error code | Description
/// |:------------------------|:---------------------------------
/// | `SbiRet::success()` | State and configuration of triggers read successfully.
/// | `SbiRet::no_shmem()` | Shared memory for debug triggers is disabled.
/// | `SbiRet::bad_range()` | Either `trig_idx_base >= trig_max` or `trig_idx_base + trig_count >= trig_max`.
/// Install debug triggers based on an array of trigger configurations in the shared memory
/// of the calling hart. The `trig_idx` assigned to each installed trigger configuration is
/// written back in the shared memory.
///
/// The `trig_count` parameter represents the number of trigger configuration entries in
/// the shared memory at offset `0x0`.
///
/// The i'th trigger configuration at `offset = i * (XLEN / 2)` in the shared memory
/// consists of four consecutive XLEN-bit words in little-endian format which are
/// organized as follows:
///
/// ```text
/// word[0] = `trig_idx` written back by the SBI implementation
/// word[1] = `trig_tdata1` read by the SBI implementation
/// word[2] = `trig_tdata2` read by the SBI implementation
/// word[3] = `trig_tdata3` read by the SBI implementation
/// ```
///
/// Upon success, `SbiRet.value` is set to zero. Upon failure, `SbiRet.value` is set to the
/// array index of the failing trigger configuration.
///
/// # Return value
///
/// | Error code | Description
/// |:----------------------------|:---------------------------------
/// | `SbiRet::success()` | Triggers installed successfully.
/// | `SbiRet::no_shmem()` | Shared memory for debug triggers is disabled.
/// | `SbiRet::bad_range()` | `trig_count >= trig_max`.
/// | `SbiRet::invalid_param()` | One of the trigger configuration words `trig_tdata1`, `trig_tdata2`, or `trig_tdata3` has an invalid value.
/// | `SbiRet::failed()` | Failed to assign `trig_idx` or HW debug trigger for one of the trigger configurations.
/// | `SbiRet::not_supported()` | One of the trigger configuration can't be programmed due to unimplemented optional bits in `tdata1`, `tdata2`, or `tdata3` CSRs.
/// Update already installed debug triggers based on a trigger configuration array in the
/// shared memory of the calling hart.
///
/// The `trig_count` parameter represents the number of trigger configuration entries in
/// the shared memory at offset `0x0`.
///
/// The i'th trigger configuration at `offset = i * (XLEN / 2)` in the shared memory
/// consists of four consecutive XLEN-bit words in little-endian format as follows:
///
/// ```text
/// word[0] = `trig_idx` read by the SBI implementation
/// word[1] = `trig_tdata1` read by the SBI implementation
/// word[2] = `trig_tdata2` read by the SBI implementation
/// word[3] = `trig_tdata3` read by the SBI implementation
/// ```
/// The SBI implementation MUST consider trigger configurations in the increasing order of
/// the array index and starting with array index `0`. To install a debug trigger for the
/// trigger configuration at array index `i` in the shared memory, the SBI implementation
/// MUST do the following:
///
/// - Map an unused HW debug trigger which matches the trigger configuration to an
/// an unused `trig_idx`.
/// - Save a copy of the `trig_tdata1.vs`, `trig_tdata1.vu`, `trig_tdata1.s`, and
/// `trig_tdata.u` bits in `trig_state`.
/// - Update the `tdata1`, `tdata2`, and `tdata3` CSRs of the HW debug trigger.
/// - Write `trig_idx` at `offset = i * (XLEN / 2)` in the shared memory.
///
/// Additionally for each trigger configuration chain in the shared memory, the SBI
/// implementation MUST assign contiguous `trig_idx` values and contiguous HW debug
/// triggers when installing the trigger configuration chain.
///
/// The last trigger configuration in the shared memory MUST not have `trig_tdata1.chain == 1`
/// for `trig_tdata1.type = 2 or 6` to prevent incomplete trigger configuration chain
/// in the shared memory.
///
/// The `SbiRet.value` is set to zero upon success or if shared memory is disabled whereas
/// `SbiRet.value` is set to the array index `i` of the failing trigger configuration upon
/// other failures.
///
/// # Return value
///
/// | Error code | Description
/// |:----------------------------|:---------------------------------
/// | `SbiRet::success()` | Triggers updated successfully.
/// | `SbiRet::no_shmem()` | Shared memory for debug triggers is disabled.
/// | `SbiRet::bad_range()` | `trig_count >= trig_max`.
/// | `SbiRet::invalid_param()` | One of the trigger configuration in the shared memory has an invalid of `trig_idx` (i.e. `trig_idx >= trig_max`), `trig_tdata1`, `trig_tdata2`, or `trig_tdata3`.
/// | `SbiRet::failed()` | One of the trigger configurations has valid `trig_idx` but the corresponding debug trigger is not mapped to any HW debug trigger.
/// | `SbiRet::not_supported()` | One of the trigger configuration can't be programmed due to unimplemented optional bits in `tdata1`, `tdata2`, or `tdata3` CSRs.
/// Uninstall a set of debug triggers specified by the `triggers` mask parameter on the calling hart.
///
/// The `triggers` specifies which triggers are to be uninstalled.
/// Each bit in the mask corresponds to a specific trigger, allowing for batch operations
/// on multiple triggers simultaneously.
///
/// For each debug trigger in the specified set of debug triggers, the SBI implementation MUST:
/// 1. Clear the `tdata1`, `tdata2`, and `tdata3` CSRs of the mapped HW debug trigger.
/// 2. Clear the `trig_state` of the debug trigger.
/// 3. Unmap and free the HW debug trigger and corresponding `trig_idx` for re-use in
/// the future trigger installations.
///
/// # Return value
///
/// | Error code | Description
/// |:----------------------------|:---------------------------------
/// | `SbiRet::success()` | Triggers uninstalled successfully.
/// | `SbiRet::invalid_param()` | One of the debug triggers with index `trig_idx` in the specified set of debug triggers either not mapped to any HW debug trigger OR has `trig_idx >= trig_max`.
/// Enable a set of debug triggers specified by the `triggers` mask parameter on the calling hart.
///
/// The `triggers` specifies which triggers are to be enabled.
/// Each bit in the mask corresponds to a specific trigger, allowing for batch operations
/// on multiple triggers simultaneously.
///
/// To enable a debug trigger in the specified set of debug triggers, the SBI implementation
/// MUST restore the `vs`, `vu`, `s`, and `u` bits of the mapped HW debug trigger from their
/// saved copy in `trig_state`.
///
/// # Return value
///
/// | Error code | Description
/// |:----------------------------|:---------------------------------
/// | `SbiRet::success()` | Triggers enabled successfully.
/// | `SbiRet::invalid_param()` | One of the debug triggers with index `trig_idx` in the specified set of debug triggers either not mapped to any HW debug trigger OR has `trig_idx >= trig_max`.
/// Disable a set of debug triggers specified by the `triggers` mask parameter on the calling hart.
///
/// The `triggers` specifies which triggers are to be disabled.
/// Each bit in the mask corresponds to a specific trigger, allowing for batch operations
/// on multiple triggers simultaneously.
///
/// To disable a debug trigger in the specified set of debug triggers, the SBI implementation
/// MUST clear the `vs`, `vu`, `s`, and `u` bits of the mapped HW debug trigger.
///
/// # Return value
///
/// | Error code | Description
/// |:----------------------------|:---------------------------------
/// | `SbiRet::success()` | Triggers disabled successfully.
/// | `SbiRet::invalid_param()` | One of the debug triggers with index `trig_idx` in the specified set of debug triggers either not mapped to any HW debug trigger OR has `trig_idx >= trig_max`.