3 #include "debug_module.h"
4 #include "debug_defines.h"
8 #include "debug_rom/debug_rom.h"
16 ///////////////////////// debug_module_data_t
18 debug_module_data_t::debug_module_data_t()
20 memset(data
, 0, sizeof(data
));
23 bool debug_module_data_t::load(reg_t addr
, size_t len
, uint8_t* bytes
)
25 if (addr
+ len
< sizeof(data
)) {
26 memcpy(bytes
, data
+ addr
, len
);
30 fprintf(stderr
, "ERROR: invalid load from debug_module_data_t: %zd bytes at 0x%016"
31 PRIx64
"\n", len
, addr
);
36 bool debug_module_data_t::store(reg_t addr
, size_t len
, const uint8_t* bytes
)
38 D(fprintf(stderr
, "debug_module_data_t store 0x%lx bytes at 0x%lx\n", len
,
41 if (addr
+ len
< sizeof(data
)) {
42 memcpy(data
+ addr
, bytes
, len
);
46 fprintf(stderr
, "ERROR: invalid store to debug_module_data_t: %zd bytes at 0x%016"
47 PRIx64
"\n", len
, addr
);
51 uint32_t debug_module_data_t::read32(reg_t addr
) const
53 assert(addr
+ 4 <= sizeof(data
));
55 (data
[addr
+ 1] << 8) |
56 (data
[addr
+ 2] << 16) |
57 (data
[addr
+ 3] << 24);
60 void debug_module_data_t::write32(reg_t addr
, uint32_t value
)
62 fprintf(stderr
, "debug_module_data_t::write32(0x%lx, 0x%x)\n", addr
, value
);
63 assert(addr
+ 4 <= sizeof(data
));
64 data
[addr
] = value
& 0xff;
65 data
[addr
+ 1] = (value
>> 8) & 0xff;
66 data
[addr
+ 2] = (value
>> 16) & 0xff;
67 data
[addr
+ 3] = (value
>> 24) & 0xff;
70 ///////////////////////// debug_module_t
72 debug_module_t::debug_module_t(sim_t
*sim
) : sim(sim
),
73 next_action(jal(ZERO
, 0)),
74 action_executed(false)
79 dmstatus
.authenticated
= 1;
80 dmstatus
.versionlo
= 2;
83 abstractcs
.progsize
= progsize
;
87 for (unsigned i
= 0; i
< DEBUG_ROM_ENTRY_SIZE
/ 4; i
++) {
88 write32(debug_rom_entry
, i
, jal(ZERO
, 0));
92 memset(program_buffer
, 0, sizeof(program_buffer
));
95 void debug_module_t::reset()
97 for (unsigned i
= 0; i
< sim
->nprocs(); i
++) {
98 processor_t
*proc
= sim
->get_core(i
);
100 proc
->halt_request
= false;
106 dmstatus
.authenticated
= 1;
107 dmstatus
.versionlo
= 2;
110 abstractcs
.datacount
= sizeof(dmdata
.data
) / 4;
111 abstractcs
.progsize
= progsize
;
116 void debug_module_t::add_device(bus_t
*bus
) {
117 bus
->add_device(DEBUG_START
, this);
118 bus
->add_device(DEBUG_EXCHANGE
, &dmdata
);
121 bool debug_module_t::load(reg_t addr
, size_t len
, uint8_t* bytes
)
123 addr
= DEBUG_START
+ addr
;
125 if (addr
>= DEBUG_ROM_ENTRY
&&
126 addr
< DEBUG_ROM_ENTRY
+ DEBUG_ROM_ENTRY_SIZE
) {
128 if (read32(debug_rom_entry
, dmcontrol
.hartsel
) == jal(ZERO
, 0)) {
129 // We're here in an infinite loop. That means that whatever abstract
130 // command has complete.
131 abstractcs
.busy
= false;
134 action_executed
= true;
136 halted
[(addr
- DEBUG_ROM_ENTRY
) / 4] = true;
137 memcpy(bytes
, debug_rom_entry
+ addr
- DEBUG_ROM_ENTRY
, len
);
141 if (action_executed
) {
142 // Restore the jump-to-self loop.
143 write32(debug_rom_entry
, dmcontrol
.hartsel
, next_action
);
144 next_action
= jal(ZERO
, 0);
145 action_executed
= false;
148 if (addr
>= DEBUG_ROM_CODE
&&
149 addr
< DEBUG_ROM_CODE
+ DEBUG_ROM_CODE_SIZE
) {
151 if (read32(debug_rom_code
, 0) == dret()) {
152 abstractcs
.busy
= false;
153 halted
[dmcontrol
.hartsel
] = false;
156 memcpy(bytes
, debug_rom_code
+ addr
- DEBUG_ROM_CODE
, len
);
160 if (addr
>= DEBUG_RAM_START
&& addr
< DEBUG_RAM_END
) {
161 memcpy(bytes
, program_buffer
+ addr
- DEBUG_RAM_START
, len
);
165 if (addr
>= DEBUG_ROM_EXCEPTION
&&
166 addr
< DEBUG_ROM_EXCEPTION
+ DEBUG_ROM_EXCEPTION_SIZE
) {
167 memcpy(bytes
, debug_rom_exception
+ addr
- DEBUG_ROM_EXCEPTION
, len
);
168 if (abstractcs
.cmderr
== abstractcs
.CMDERR_NONE
) {
169 abstractcs
.cmderr
= abstractcs
.CMDERR_EXCEPTION
;
174 fprintf(stderr
, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
175 PRIx64
"\n", len
, addr
);
180 bool debug_module_t::store(reg_t addr
, size_t len
, const uint8_t* bytes
)
182 addr
= DEBUG_START
+ addr
;
184 if (addr
>= DEBUG_RAM_START
&& addr
< DEBUG_RAM_END
) {
185 memcpy(program_buffer
+ addr
- DEBUG_RAM_START
, bytes
, len
);
189 fprintf(stderr
, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
190 PRIx64
"\n", len
, addr
);
194 void debug_module_t::write32(uint8_t *memory
, unsigned int index
, uint32_t value
)
196 uint8_t* base
= memory
+ index
* 4;
197 base
[0] = value
& 0xff;
198 base
[1] = (value
>> 8) & 0xff;
199 base
[2] = (value
>> 16) & 0xff;
200 base
[3] = (value
>> 24) & 0xff;
203 uint32_t debug_module_t::read32(uint8_t *memory
, unsigned int index
)
205 uint8_t* base
= memory
+ index
* 4;
206 uint32_t value
= ((uint32_t) base
[0]) |
207 (((uint32_t) base
[1]) << 8) |
208 (((uint32_t) base
[2]) << 16) |
209 (((uint32_t) base
[3]) << 24);
213 processor_t
*debug_module_t::current_proc() const
215 processor_t
*proc
= NULL
;
217 proc
= sim
->get_core(dmcontrol
.hartsel
);
218 } catch (const std::out_of_range
&) {
223 bool debug_module_t::dmi_read(unsigned address
, uint32_t *value
)
226 D(fprintf(stderr
, "dmi_read(0x%x) -> ", address
));
227 if (address
>= DMI_DATA0
&& address
< DMI_DATA0
+ abstractcs
.datacount
) {
228 unsigned i
= address
- DMI_DATA0
;
229 result
= dmdata
.read32(4 * i
);
231 if (abstractcs
.busy
&& abstractcs
.cmderr
== abstractcs
.CMDERR_NONE
) {
232 abstractcs
.cmderr
= abstractcs
.CMDERR_BUSY
;
235 if ((abstractauto
.autoexecdata
>> i
) & 1)
236 perform_abstract_command();
237 } else if (address
>= DMI_PROGBUF0
&& address
< DMI_PROGBUF0
+ progsize
) {
238 // TODO : Autoexec progbuf.
239 result
= read32(program_buffer
, address
- DMI_PROGBUF0
);
244 processor_t
*proc
= current_proc();
246 dmcontrol
.haltreq
= proc
->halt_request
;
248 result
= set_field(result
, DMI_DMCONTROL_HALTREQ
, dmcontrol
.haltreq
);
249 result
= set_field(result
, DMI_DMCONTROL_RESUMEREQ
, dmcontrol
.resumereq
);
250 result
= set_field(result
, DMI_DMCONTROL_HARTSEL
, dmcontrol
.hartsel
);
251 result
= set_field(result
, DMI_DMCONTROL_HARTRESET
, dmcontrol
.hartreset
);
252 result
= set_field(result
, DMI_DMCONTROL_NDMRESET
, dmcontrol
.ndmreset
);
253 result
= set_field(result
, DMI_DMCONTROL_DMACTIVE
, dmcontrol
.dmactive
);
258 processor_t
*proc
= current_proc();
260 dmstatus
.allnonexistant
= false;
261 dmstatus
.allunavail
= false;
262 dmstatus
.allrunning
= false;
263 dmstatus
.allhalted
= false;
265 if (halted
[dmcontrol
.hartsel
]) {
266 dmstatus
.allhalted
= true;
268 dmstatus
.allrunning
= true;
271 dmstatus
.allnonexistant
= true;
273 dmstatus
.anynonexistant
= dmstatus
.allnonexistant
;
274 dmstatus
.anyunavail
= dmstatus
.allunavail
;
275 dmstatus
.anyrunning
= dmstatus
.allrunning
;
276 dmstatus
.anyhalted
= dmstatus
.allhalted
;
278 result
= set_field(result
, DMI_DMSTATUS_ALLNONEXISTENT
, dmstatus
.allnonexistant
);
279 result
= set_field(result
, DMI_DMSTATUS_ALLUNAVAIL
, dmstatus
.allunavail
);
280 result
= set_field(result
, DMI_DMSTATUS_ALLRUNNING
, dmstatus
.allrunning
);
281 result
= set_field(result
, DMI_DMSTATUS_ALLHALTED
, dmstatus
.allhalted
);
282 result
= set_field(result
, DMI_DMSTATUS_ANYNONEXISTENT
, dmstatus
.anynonexistant
);
283 result
= set_field(result
, DMI_DMSTATUS_ANYUNAVAIL
, dmstatus
.anyunavail
);
284 result
= set_field(result
, DMI_DMSTATUS_ANYRUNNING
, dmstatus
.anyrunning
);
285 result
= set_field(result
, DMI_DMSTATUS_ANYHALTED
, dmstatus
.anyhalted
);
286 result
= set_field(result
, DMI_DMSTATUS_AUTHENTICATED
, dmstatus
.authenticated
);
287 result
= set_field(result
, DMI_DMSTATUS_AUTHBUSY
, dmstatus
.authbusy
);
288 result
= set_field(result
, DMI_DMSTATUS_VERSIONHI
, dmstatus
.versionhi
);
289 result
= set_field(result
, DMI_DMSTATUS_VERSIONLO
, dmstatus
.versionlo
);
293 result
= set_field(result
, DMI_ABSTRACTCS_CMDERR
, abstractcs
.cmderr
);
294 result
= set_field(result
, DMI_ABSTRACTCS_BUSY
, abstractcs
.busy
);
295 result
= set_field(result
, DMI_ABSTRACTCS_DATACOUNT
, abstractcs
.datacount
);
296 result
= set_field(result
, DMI_ABSTRACTCS_PROGSIZE
, abstractcs
.progsize
);
298 case DMI_ABSTRACTAUTO
:
299 result
= set_field(result
, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF
, abstractauto
.autoexecprogbuf
);
300 result
= set_field(result
, DMI_ABSTRACTAUTO_AUTOEXECDATA
, abstractauto
.autoexecdata
);
306 result
= set_field(result
, DMI_HARTINFO_NSCRATCH
, 1);
307 result
= set_field(result
, DMI_HARTINFO_DATAACCESS
, 1);
308 result
= set_field(result
, DMI_HARTINFO_DATASIZE
, abstractcs
.datacount
);
309 result
= set_field(result
, DMI_HARTINFO_DATAADDR
, DEBUG_EXCHANGE
);
315 D(fprintf(stderr
, "0x%x\n", result
));
320 bool debug_module_t::perform_abstract_command()
322 if (abstractcs
.cmderr
!= abstractcs
.CMDERR_NONE
)
324 if (abstractcs
.busy
) {
325 abstractcs
.cmderr
= abstractcs
.CMDERR_BUSY
;
329 if ((command
>> 24) == 0) {
331 unsigned size
= get_field(command
, AC_ACCESS_REGISTER_SIZE
);
332 bool write
= get_field(command
, AC_ACCESS_REGISTER_WRITE
);
333 unsigned regno
= get_field(command
, AC_ACCESS_REGISTER_REGNO
);
335 if (regno
< 0x1000 || regno
>= 0x1020) {
336 abstractcs
.cmderr
= abstractcs
.CMDERR_NOTSUP
;
340 unsigned regnum
= regno
- 0x1000;
342 if (!halted
[dmcontrol
.hartsel
]) {
343 abstractcs
.cmderr
= abstractcs
.CMDERR_HALTRESUME
;
347 if (get_field(command
, AC_ACCESS_REGISTER_TRANSFER
)) {
351 write32(debug_rom_code
, 0, lw(regnum
, ZERO
, DEBUG_EXCHANGE
));
353 write32(debug_rom_code
, 0, sw(regnum
, ZERO
, DEBUG_EXCHANGE
));
357 write32(debug_rom_code
, 0, ld(regnum
, ZERO
, DEBUG_EXCHANGE
));
359 write32(debug_rom_code
, 0, sd(regnum
, ZERO
, DEBUG_EXCHANGE
));
364 write32(debug_rom_code, 0, lq(regnum, ZERO, DEBUG_EXCHANGE));
366 write32(debug_rom_code, 0, sq(regnum, ZERO, DEBUG_EXCHANGE));
370 abstractcs
.cmderr
= abstractcs
.CMDERR_NOTSUP
;
374 // Should be a NOP. Store DEBUG_EXCHANGE to x0.
375 write32(debug_rom_code
, 0, sw(ZERO
, ZERO
, DEBUG_EXCHANGE
));
378 if (get_field(command
, AC_ACCESS_REGISTER_POSTEXEC
)) {
379 write32(debug_rom_code
, 1, jal(ZERO
, DEBUG_RAM_START
- DEBUG_ROM_CODE
- 4));
381 write32(debug_rom_code
, 1, ebreak());
384 write32(debug_rom_entry
, dmcontrol
.hartsel
,
385 jal(ZERO
, DEBUG_ROM_CODE
- (DEBUG_ROM_ENTRY
+ 4 * dmcontrol
.hartsel
)));
387 write32(debug_rom_exception
, dmcontrol
.hartsel
,
388 jal(ZERO
, (DEBUG_ROM_ENTRY
+ 4 * dmcontrol
.hartsel
) - DEBUG_ROM_EXCEPTION
));
389 abstractcs
.busy
= true;
391 abstractcs
.cmderr
= abstractcs
.CMDERR_NOTSUP
;
396 bool debug_module_t::dmi_write(unsigned address
, uint32_t value
)
398 D(fprintf(stderr
, "dmi_write(0x%x, 0x%x)\n", address
, value
));
399 if (address
>= DMI_DATA0
&& address
< DMI_DATA0
+ abstractcs
.datacount
) {
400 unsigned i
= address
- DMI_DATA0
;
401 dmdata
.write32(4 * i
, value
);
403 if (abstractcs
.busy
&& abstractcs
.cmderr
== abstractcs
.CMDERR_NONE
) {
404 abstractcs
.cmderr
= abstractcs
.CMDERR_BUSY
;
407 if ((abstractauto
.autoexecdata
>> i
) & 1)
408 perform_abstract_command();
411 } else if (address
>= DMI_PROGBUF0
&& address
< DMI_PROGBUF0
+ progsize
) {
412 write32(program_buffer
, address
- DMI_PROGBUF0
, value
);
418 dmcontrol
.dmactive
= get_field(value
, DMI_DMCONTROL_DMACTIVE
);
419 if (dmcontrol
.dmactive
) {
420 dmcontrol
.haltreq
= get_field(value
, DMI_DMCONTROL_HALTREQ
);
421 dmcontrol
.resumereq
= get_field(value
, DMI_DMCONTROL_RESUMEREQ
);
422 dmcontrol
.ndmreset
= get_field(value
, DMI_DMCONTROL_NDMRESET
);
423 dmcontrol
.hartsel
= get_field(value
, DMI_DMCONTROL_HARTSEL
);
427 processor_t
*proc
= current_proc();
429 proc
->halt_request
= dmcontrol
.haltreq
;
430 if (dmcontrol
.resumereq
) {
431 write32(debug_rom_code
, 0, dret());
432 write32(debug_rom_entry
, dmcontrol
.hartsel
,
433 jal(ZERO
, DEBUG_ROM_CODE
- (DEBUG_ROM_ENTRY
+ 4 * dmcontrol
.hartsel
)));
434 abstractcs
.busy
= true;
442 return perform_abstract_command();
445 if (get_field(value
, DMI_ABSTRACTCS_CMDERR
) == abstractcs
.CMDERR_NONE
) {
446 abstractcs
.cmderr
= abstractcs
.CMDERR_NONE
;
450 case DMI_ABSTRACTAUTO
:
451 abstractauto
.autoexecprogbuf
= get_field(value
, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF
);
452 abstractauto
.autoexecdata
= get_field(value
, DMI_ABSTRACTAUTO_AUTOEXECDATA
);