3 #include "debug_module.h"
4 #include "debug_defines.h"
8 #include "debug_rom/debug_rom.h"
9 #include "debug_rom/debug_rom_defines.h"
17 ///////////////////////// debug_module_t
19 debug_module_t::debug_module_t(sim_t
*sim
, unsigned progbufsize
, unsigned max_bus_master_bits
) :
20 progbufsize(progbufsize
),
21 program_buffer_bytes(4 + 4*progbufsize
),
22 max_bus_master_bits(max_bus_master_bits
),
23 debug_progbuf_start(debug_data_start
- program_buffer_bytes
),
24 debug_abstract_start(debug_progbuf_start
- debug_abstract_size
*4),
27 program_buffer
= new uint8_t[program_buffer_bytes
];
29 memset(halted
, 0, sizeof(halted
));
30 memset(debug_rom_flags
, 0, sizeof(debug_rom_flags
));
31 memset(resumeack
, 0, sizeof(resumeack
));
32 memset(program_buffer
, 0, program_buffer_bytes
);
33 program_buffer
[4*progbufsize
] = ebreak();
34 program_buffer
[4*progbufsize
+1] = ebreak() >> 8;
35 program_buffer
[4*progbufsize
+2] = ebreak() >> 16;
36 program_buffer
[4*progbufsize
+3] = ebreak() >> 24;
37 memset(dmdata
, 0, sizeof(dmdata
));
39 write32(debug_rom_whereto
, 0,
40 jal(ZERO
, debug_abstract_start
- DEBUG_ROM_WHERETO
));
42 memset(debug_abstract
, 0, sizeof(debug_abstract
));
47 debug_module_t::~debug_module_t()
49 delete[] program_buffer
;
52 void debug_module_t::reset()
54 for (unsigned i
= 0; i
< sim
->nprocs(); i
++) {
55 processor_t
*proc
= sim
->get_core(i
);
57 proc
->halt_request
= false;
63 dmstatus
.impebreak
= true;
64 dmstatus
.authenticated
= 1;
68 abstractcs
.datacount
= sizeof(dmdata
) / 4;
69 abstractcs
.progbufsize
= progbufsize
;
74 if (max_bus_master_bits
> 0) {
76 sbcs
.asize
= sizeof(reg_t
) * 8;
78 if (max_bus_master_bits
>= 64)
80 if (max_bus_master_bits
>= 32)
82 if (max_bus_master_bits
>= 16)
84 if (max_bus_master_bits
>= 8)
88 void debug_module_t::add_device(bus_t
*bus
) {
89 bus
->add_device(DEBUG_START
, this);
92 bool debug_module_t::load(reg_t addr
, size_t len
, uint8_t* bytes
)
94 addr
= DEBUG_START
+ addr
;
96 if (addr
>= DEBUG_ROM_ENTRY
&&
97 (addr
+ len
) <= (DEBUG_ROM_ENTRY
+ debug_rom_raw_len
)) {
98 memcpy(bytes
, debug_rom_raw
+ addr
- DEBUG_ROM_ENTRY
, len
);
102 if (addr
>= DEBUG_ROM_WHERETO
&& (addr
+ len
) <= (DEBUG_ROM_WHERETO
+ 4)) {
103 memcpy(bytes
, debug_rom_whereto
+ addr
- DEBUG_ROM_WHERETO
, len
);
107 if (addr
>= DEBUG_ROM_FLAGS
&& ((addr
+ len
) <= DEBUG_ROM_FLAGS
+ 1024)) {
108 memcpy(bytes
, debug_rom_flags
+ addr
- DEBUG_ROM_FLAGS
, len
);
112 if (addr
>= debug_abstract_start
&& ((addr
+ len
) <= (debug_abstract_start
+ sizeof(debug_abstract
)))) {
113 memcpy(bytes
, debug_abstract
+ addr
- debug_abstract_start
, len
);
117 if (addr
>= debug_data_start
&& (addr
+ len
) <= (debug_data_start
+ sizeof(dmdata
))) {
118 memcpy(bytes
, dmdata
+ addr
- debug_data_start
, len
);
122 if (addr
>= debug_progbuf_start
&& ((addr
+ len
) <= (debug_progbuf_start
+ program_buffer_bytes
))) {
123 memcpy(bytes
, program_buffer
+ addr
- debug_progbuf_start
, len
);
127 fprintf(stderr
, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
128 PRIx64
"\n", len
, addr
);
133 bool debug_module_t::store(reg_t addr
, size_t len
, const uint8_t* bytes
)
138 fprintf(stderr
, "store(addr=0x%lx, len=%d, bytes=0x%08x); "
139 "hartsel=0x%x\n", addr
, (unsigned) len
, *(uint32_t *) bytes
,
143 fprintf(stderr
, "store(addr=0x%lx, len=%d, bytes=...); "
144 "hartsel=0x%x\n", addr
, (unsigned) len
, dmcontrol
.hartsel
);
152 memcpy(id_bytes
, bytes
, 4);
153 id
= read32(id_bytes
, 0);
156 addr
= DEBUG_START
+ addr
;
158 if (addr
>= debug_data_start
&& (addr
+ len
) <= (debug_data_start
+ sizeof(dmdata
))) {
159 memcpy(dmdata
+ addr
- debug_data_start
, bytes
, len
);
163 if (addr
>= debug_progbuf_start
&& ((addr
+ len
) <= (debug_progbuf_start
+ program_buffer_bytes
))) {
164 memcpy(program_buffer
+ addr
- debug_progbuf_start
, bytes
, len
);
169 if (addr
== DEBUG_ROM_HALTED
) {
172 if (dmcontrol
.hartsel
== id
) {
173 if (0 == (debug_rom_flags
[id
] & (1 << DEBUG_ROM_FLAG_GO
))){
174 if (dmcontrol
.hartsel
== id
) {
175 abstractcs
.busy
= false;
182 if (addr
== DEBUG_ROM_GOING
) {
183 debug_rom_flags
[dmcontrol
.hartsel
] &= ~(1 << DEBUG_ROM_FLAG_GO
);
187 if (addr
== DEBUG_ROM_RESUMING
) {
190 resumeack
[id
] = true;
191 debug_rom_flags
[id
] &= ~(1 << DEBUG_ROM_FLAG_RESUME
);
195 if (addr
== DEBUG_ROM_EXCEPTION
) {
196 if (abstractcs
.cmderr
== CMDERR_NONE
) {
197 abstractcs
.cmderr
= CMDERR_EXCEPTION
;
202 fprintf(stderr
, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
203 PRIx64
"\n", len
, addr
);
207 void debug_module_t::write32(uint8_t *memory
, unsigned int index
, uint32_t value
)
209 uint8_t* base
= memory
+ index
* 4;
210 base
[0] = value
& 0xff;
211 base
[1] = (value
>> 8) & 0xff;
212 base
[2] = (value
>> 16) & 0xff;
213 base
[3] = (value
>> 24) & 0xff;
216 uint32_t debug_module_t::read32(uint8_t *memory
, unsigned int index
)
218 uint8_t* base
= memory
+ index
* 4;
219 uint32_t value
= ((uint32_t) base
[0]) |
220 (((uint32_t) base
[1]) << 8) |
221 (((uint32_t) base
[2]) << 16) |
222 (((uint32_t) base
[3]) << 24);
226 processor_t
*debug_module_t::current_proc() const
228 processor_t
*proc
= NULL
;
230 proc
= sim
->get_core(dmcontrol
.hartsel
);
231 } catch (const std::out_of_range
&) {
236 unsigned debug_module_t::sb_access_bits()
238 return 8 << sbcs
.sbaccess
;
241 void debug_module_t::sb_autoincrement()
243 if (!sbcs
.autoincrement
|| !max_bus_master_bits
)
246 uint64_t value
= sbaddress
[0] + sb_access_bits() / 8;
247 sbaddress
[0] = value
;
248 uint32_t carry
= value
>> 32;
250 value
= sbaddress
[1] + carry
;
251 sbaddress
[1] = value
;
254 value
= sbaddress
[2] + carry
;
255 sbaddress
[2] = value
;
258 sbaddress
[3] += carry
;
261 void debug_module_t::sb_read()
263 reg_t address
= ((uint64_t) sbaddress
[1] << 32) | sbaddress
[0];
265 if (sbcs
.sbaccess
== 0 && max_bus_master_bits
>= 8) {
266 sbdata
[0] = sim
->debug_mmu
->load_uint8(address
);
267 } else if (sbcs
.sbaccess
== 1 && max_bus_master_bits
>= 16) {
268 sbdata
[0] = sim
->debug_mmu
->load_uint16(address
);
269 } else if (sbcs
.sbaccess
== 2 && max_bus_master_bits
>= 32) {
270 sbdata
[0] = sim
->debug_mmu
->load_uint32(address
);
271 } else if (sbcs
.sbaccess
== 3 && max_bus_master_bits
>= 64) {
272 uint64_t value
= sim
->debug_mmu
->load_uint32(address
);
274 sbdata
[1] = value
>> 32;
278 } catch (trap_load_access_fault
& t
) {
283 void debug_module_t::sb_write()
285 reg_t address
= ((uint64_t) sbaddress
[1] << 32) | sbaddress
[0];
286 D(fprintf(stderr
, "sb_write() 0x%x @ 0x%lx\n", sbdata
[0], address
));
287 if (sbcs
.sbaccess
== 0 && max_bus_master_bits
>= 8) {
288 sim
->debug_mmu
->store_uint8(address
, sbdata
[0]);
289 } else if (sbcs
.sbaccess
== 1 && max_bus_master_bits
>= 16) {
290 sim
->debug_mmu
->store_uint16(address
, sbdata
[0]);
291 } else if (sbcs
.sbaccess
== 2 && max_bus_master_bits
>= 32) {
292 sim
->debug_mmu
->store_uint32(address
, sbdata
[0]);
293 } else if (sbcs
.sbaccess
== 3 && max_bus_master_bits
>= 64) {
294 sim
->debug_mmu
->store_uint64(address
,
295 (((uint64_t) sbdata
[1]) << 32) | sbdata
[0]);
301 bool debug_module_t::dmi_read(unsigned address
, uint32_t *value
)
304 D(fprintf(stderr
, "dmi_read(0x%x) -> ", address
));
305 if (address
>= DMI_DATA0
&& address
< DMI_DATA0
+ abstractcs
.datacount
) {
306 unsigned i
= address
- DMI_DATA0
;
307 result
= read32(dmdata
, i
);
308 if (abstractcs
.busy
) {
310 fprintf(stderr
, "\ndmi_read(0x%02x (data[%d]) -> -1 because abstractcs.busy==true\n", address
, i
);
313 if (abstractcs
.busy
&& abstractcs
.cmderr
== CMDERR_NONE
) {
314 abstractcs
.cmderr
= CMDERR_BUSY
;
317 if (!abstractcs
.busy
&& ((abstractauto
.autoexecdata
>> i
) & 1)) {
318 perform_abstract_command();
320 } else if (address
>= DMI_PROGBUF0
&& address
< DMI_PROGBUF0
+ progbufsize
) {
321 unsigned i
= address
- DMI_PROGBUF0
;
322 result
= read32(program_buffer
, i
);
323 if (abstractcs
.busy
) {
325 fprintf(stderr
, "\ndmi_read(0x%02x (progbuf[%d]) -> -1 because abstractcs.busy==true\n", address
, i
);
327 if (!abstractcs
.busy
&& ((abstractauto
.autoexecprogbuf
>> i
) & 1)) {
328 perform_abstract_command();
335 processor_t
*proc
= current_proc();
337 dmcontrol
.haltreq
= proc
->halt_request
;
339 result
= set_field(result
, DMI_DMCONTROL_HALTREQ
, dmcontrol
.haltreq
);
340 result
= set_field(result
, DMI_DMCONTROL_RESUMEREQ
, dmcontrol
.resumereq
);
341 result
= set_field(result
, ((1L<<hartsellen
)-1) <<
342 DMI_DMCONTROL_HARTSEL_OFFSET
, dmcontrol
.hartsel
);
343 result
= set_field(result
, DMI_DMCONTROL_HARTRESET
, dmcontrol
.hartreset
);
344 result
= set_field(result
, DMI_DMCONTROL_NDMRESET
, dmcontrol
.ndmreset
);
345 result
= set_field(result
, DMI_DMCONTROL_DMACTIVE
, dmcontrol
.dmactive
);
350 processor_t
*proc
= current_proc();
352 dmstatus
.allnonexistant
= false;
353 dmstatus
.allunavail
= false;
354 dmstatus
.allrunning
= false;
355 dmstatus
.allhalted
= false;
356 dmstatus
.allresumeack
= false;
358 if (halted
[dmcontrol
.hartsel
]) {
359 dmstatus
.allhalted
= true;
361 dmstatus
.allrunning
= true;
364 dmstatus
.allnonexistant
= true;
366 dmstatus
.anynonexistant
= dmstatus
.allnonexistant
;
367 dmstatus
.anyunavail
= dmstatus
.allunavail
;
368 dmstatus
.anyrunning
= dmstatus
.allrunning
;
369 dmstatus
.anyhalted
= dmstatus
.allhalted
;
371 if (resumeack
[dmcontrol
.hartsel
]) {
372 dmstatus
.allresumeack
= true;
374 dmstatus
.allresumeack
= false;
377 dmstatus
.allresumeack
= false;
380 result
= set_field(result
, DMI_DMSTATUS_IMPEBREAK
,
382 result
= set_field(result
, DMI_DMSTATUS_ALLNONEXISTENT
, dmstatus
.allnonexistant
);
383 result
= set_field(result
, DMI_DMSTATUS_ALLUNAVAIL
, dmstatus
.allunavail
);
384 result
= set_field(result
, DMI_DMSTATUS_ALLRUNNING
, dmstatus
.allrunning
);
385 result
= set_field(result
, DMI_DMSTATUS_ALLHALTED
, dmstatus
.allhalted
);
386 result
= set_field(result
, DMI_DMSTATUS_ALLRESUMEACK
, dmstatus
.allresumeack
);
387 result
= set_field(result
, DMI_DMSTATUS_ANYNONEXISTENT
, dmstatus
.anynonexistant
);
388 result
= set_field(result
, DMI_DMSTATUS_ANYUNAVAIL
, dmstatus
.anyunavail
);
389 result
= set_field(result
, DMI_DMSTATUS_ANYRUNNING
, dmstatus
.anyrunning
);
390 result
= set_field(result
, DMI_DMSTATUS_ANYHALTED
, dmstatus
.anyhalted
);
391 result
= set_field(result
, DMI_DMSTATUS_ANYRESUMEACK
, dmstatus
.anyresumeack
);
392 result
= set_field(result
, DMI_DMSTATUS_AUTHENTICATED
, dmstatus
.authenticated
);
393 result
= set_field(result
, DMI_DMSTATUS_AUTHBUSY
, dmstatus
.authbusy
);
394 result
= set_field(result
, DMI_DMSTATUS_VERSION
, dmstatus
.version
);
398 result
= set_field(result
, DMI_ABSTRACTCS_CMDERR
, abstractcs
.cmderr
);
399 result
= set_field(result
, DMI_ABSTRACTCS_BUSY
, abstractcs
.busy
);
400 result
= set_field(result
, DMI_ABSTRACTCS_DATACOUNT
, abstractcs
.datacount
);
401 result
= set_field(result
, DMI_ABSTRACTCS_PROGBUFSIZE
,
402 abstractcs
.progbufsize
);
404 case DMI_ABSTRACTAUTO
:
405 result
= set_field(result
, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF
, abstractauto
.autoexecprogbuf
);
406 result
= set_field(result
, DMI_ABSTRACTAUTO_AUTOEXECDATA
, abstractauto
.autoexecdata
);
412 result
= set_field(result
, DMI_HARTINFO_NSCRATCH
, 1);
413 result
= set_field(result
, DMI_HARTINFO_DATAACCESS
, 1);
414 result
= set_field(result
, DMI_HARTINFO_DATASIZE
, abstractcs
.datacount
);
415 result
= set_field(result
, DMI_HARTINFO_DATAADDR
, debug_data_start
);
418 result
= set_field(result
, DMI_SBCS_SBVERSION
, sbcs
.version
);
419 result
= set_field(result
, DMI_SBCS_SBREADONADDR
, sbcs
.readonaddr
);
420 result
= set_field(result
, DMI_SBCS_SBACCESS
, sbcs
.sbaccess
);
421 result
= set_field(result
, DMI_SBCS_SBAUTOINCREMENT
, sbcs
.autoincrement
);
422 result
= set_field(result
, DMI_SBCS_SBREADONDATA
, sbcs
.readondata
);
423 result
= set_field(result
, DMI_SBCS_SBERROR
, sbcs
.error
);
424 result
= set_field(result
, DMI_SBCS_SBASIZE
, sbcs
.asize
);
425 result
= set_field(result
, DMI_SBCS_SBACCESS128
, sbcs
.access128
);
426 result
= set_field(result
, DMI_SBCS_SBACCESS64
, sbcs
.access64
);
427 result
= set_field(result
, DMI_SBCS_SBACCESS32
, sbcs
.access32
);
428 result
= set_field(result
, DMI_SBCS_SBACCESS16
, sbcs
.access16
);
429 result
= set_field(result
, DMI_SBCS_SBACCESS8
, sbcs
.access8
);
432 result
= sbaddress
[0];
435 result
= sbaddress
[1];
438 result
= sbaddress
[2];
441 result
= sbaddress
[3];
445 if (sbcs
.error
== 0) {
447 if (sbcs
.readondata
) {
463 D(fprintf(stderr
, "Unexpected. Returning Error."));
467 D(fprintf(stderr
, "0x%x\n", result
));
472 bool debug_module_t::perform_abstract_command()
474 if (abstractcs
.cmderr
!= CMDERR_NONE
)
476 if (abstractcs
.busy
) {
477 abstractcs
.cmderr
= CMDERR_BUSY
;
481 if ((command
>> 24) == 0) {
483 unsigned size
= get_field(command
, AC_ACCESS_REGISTER_SIZE
);
484 bool write
= get_field(command
, AC_ACCESS_REGISTER_WRITE
);
485 unsigned regno
= get_field(command
, AC_ACCESS_REGISTER_REGNO
);
487 if (!halted
[dmcontrol
.hartsel
]) {
488 abstractcs
.cmderr
= CMDERR_HALTRESUME
;
492 if (get_field(command
, AC_ACCESS_REGISTER_TRANSFER
)) {
494 if (regno
< 0x1000 || regno
>= 0x1020) {
495 abstractcs
.cmderr
= CMDERR_NOTSUP
;
499 unsigned regnum
= regno
- 0x1000;
504 write32(debug_abstract
, 0, lw(regnum
, ZERO
, debug_data_start
));
506 write32(debug_abstract
, 0, sw(regnum
, ZERO
, debug_data_start
));
510 write32(debug_abstract
, 0, ld(regnum
, ZERO
, debug_data_start
));
512 write32(debug_abstract
, 0, sd(regnum
, ZERO
, debug_data_start
));
517 write32(debug_rom_code, 0, lq(regnum, ZERO, debug_data_start));
519 write32(debug_rom_code, 0, sq(regnum, ZERO, debug_data_start));
523 abstractcs
.cmderr
= CMDERR_NOTSUP
;
528 write32(debug_abstract
, 0, addi(ZERO
, ZERO
, 0));
531 if (get_field(command
, AC_ACCESS_REGISTER_POSTEXEC
)) {
532 // Since the next instruction is what we will use, just use nother NOP
534 write32(debug_abstract
, 1, addi(ZERO
, ZERO
, 0));
536 write32(debug_abstract
, 1, ebreak());
539 debug_rom_flags
[dmcontrol
.hartsel
] |= 1 << DEBUG_ROM_FLAG_GO
;
541 abstractcs
.busy
= true;
543 abstractcs
.cmderr
= CMDERR_NOTSUP
;
548 bool debug_module_t::dmi_write(unsigned address
, uint32_t value
)
550 D(fprintf(stderr
, "dmi_write(0x%x, 0x%x)\n", address
, value
));
551 if (address
>= DMI_DATA0
&& address
< DMI_DATA0
+ abstractcs
.datacount
) {
552 unsigned i
= address
- DMI_DATA0
;
553 if (!abstractcs
.busy
)
554 write32(dmdata
, address
- DMI_DATA0
, value
);
556 if (abstractcs
.busy
&& abstractcs
.cmderr
== CMDERR_NONE
) {
557 abstractcs
.cmderr
= CMDERR_BUSY
;
560 if (!abstractcs
.busy
&& ((abstractauto
.autoexecdata
>> i
) & 1)) {
561 perform_abstract_command();
565 } else if (address
>= DMI_PROGBUF0
&& address
< DMI_PROGBUF0
+ progbufsize
) {
566 unsigned i
= address
- DMI_PROGBUF0
;
568 if (!abstractcs
.busy
)
569 write32(program_buffer
, i
, value
);
571 if (!abstractcs
.busy
&& ((abstractauto
.autoexecprogbuf
>> i
) & 1)) {
572 perform_abstract_command();
580 if (!dmcontrol
.dmactive
&& get_field(value
, DMI_DMCONTROL_DMACTIVE
))
582 dmcontrol
.dmactive
= get_field(value
, DMI_DMCONTROL_DMACTIVE
);
583 if (dmcontrol
.dmactive
) {
584 dmcontrol
.haltreq
= get_field(value
, DMI_DMCONTROL_HALTREQ
);
585 dmcontrol
.resumereq
= get_field(value
, DMI_DMCONTROL_RESUMEREQ
);
586 dmcontrol
.hartreset
= get_field(value
, DMI_DMCONTROL_HARTRESET
);
587 dmcontrol
.ndmreset
= get_field(value
, DMI_DMCONTROL_NDMRESET
);
588 dmcontrol
.hartsel
= get_field(value
, ((1L<<hartsellen
)-1) <<
589 DMI_DMCONTROL_HARTSEL_OFFSET
);
591 processor_t
*proc
= current_proc();
593 proc
->halt_request
= dmcontrol
.haltreq
;
594 if (dmcontrol
.resumereq
) {
595 debug_rom_flags
[dmcontrol
.hartsel
] |= (1 << DEBUG_ROM_FLAG_RESUME
);
596 resumeack
[dmcontrol
.hartsel
] = false;
598 if (dmcontrol
.hartreset
) {
602 if (dmcontrol
.ndmreset
) {
603 for (size_t i
= 0; i
< sim
->nprocs(); i
++) {
604 proc
= sim
->get_core(i
);
613 return perform_abstract_command();
616 abstractcs
.cmderr
= (cmderr_t
) (((uint32_t) (abstractcs
.cmderr
)) & (~(uint32_t)(get_field(value
, DMI_ABSTRACTCS_CMDERR
))));
619 case DMI_ABSTRACTAUTO
:
620 abstractauto
.autoexecprogbuf
= get_field(value
,
621 DMI_ABSTRACTAUTO_AUTOEXECPROGBUF
);
622 abstractauto
.autoexecdata
= get_field(value
,
623 DMI_ABSTRACTAUTO_AUTOEXECDATA
);
626 sbcs
.readonaddr
= get_field(value
, DMI_SBCS_SBREADONADDR
);
627 sbcs
.sbaccess
= get_field(value
, DMI_SBCS_SBACCESS
);
628 sbcs
.autoincrement
= get_field(value
, DMI_SBCS_SBAUTOINCREMENT
);
629 sbcs
.readondata
= get_field(value
, DMI_SBCS_SBREADONDATA
);
630 sbcs
.error
&= ~get_field(value
, DMI_SBCS_SBERROR
);
633 sbaddress
[0] = value
;
634 if (sbcs
.error
== 0 && sbcs
.readonaddr
) {
639 sbaddress
[1] = value
;
642 sbaddress
[2] = value
;
645 sbaddress
[3] = value
;
649 if (sbcs
.error
== 0) {
651 if (sbcs
.autoincrement
&& sbcs
.error
== 0) {