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 D(fprintf(stderr
, "debug_module_data_t load 0x%lx bytes at 0x%lx\n", len
,
28 if (addr
+ len
< sizeof(data
)) {
29 memcpy(bytes
, data
+ addr
, len
);
33 fprintf(stderr
, "ERROR: invalid load from debug_module_data_t: %zd bytes at 0x%016"
34 PRIx64
"\n", len
, addr
);
39 bool debug_module_data_t::store(reg_t addr
, size_t len
, const uint8_t* bytes
)
41 D(fprintf(stderr
, "debug_module_data_t store 0x%lx bytes at 0x%lx\n", len
,
44 if (addr
+ len
< sizeof(data
)) {
45 memcpy(data
+ addr
, bytes
, len
);
49 fprintf(stderr
, "ERROR: invalid store to debug_module_data_t: %zd bytes at 0x%016"
50 PRIx64
"\n", len
, addr
);
54 uint32_t debug_module_data_t::read32(reg_t addr
) const
56 assert(addr
+ 4 <= sizeof(data
));
58 (data
[addr
+ 1] << 8) |
59 (data
[addr
+ 2] << 16) |
60 (data
[addr
+ 3] << 24);
63 void debug_module_data_t::write32(reg_t addr
, uint32_t value
)
65 fprintf(stderr
, "debug_module_data_t::write32(0x%lx, 0x%x)\n", addr
, value
);
66 assert(addr
+ 4 <= sizeof(data
));
67 data
[addr
] = value
& 0xff;
68 data
[addr
+ 1] = (value
>> 8) & 0xff;
69 data
[addr
+ 2] = (value
>> 16) & 0xff;
70 data
[addr
+ 3] = (value
>> 24) & 0xff;
73 ///////////////////////// debug_module_t
75 debug_module_t::debug_module_t(sim_t
*sim
) : sim(sim
),
76 next_action(jal(ZERO
, 0)),
77 action_executed(false)
80 dmcontrol
.version
= 1;
82 for (unsigned i
= 0; i
< DEBUG_ROM_ENTRY_SIZE
/ 4; i
++) {
83 write32(debug_rom_entry
, i
, jal(ZERO
, 0));
87 memset(program_buffer
, 0, sizeof(program_buffer
));
90 void debug_module_t::reset()
92 for (unsigned i
= 0; i
< sim
->nprocs(); i
++) {
93 processor_t
*proc
= sim
->get_core(i
);
95 proc
->halt_request
= false;
99 dmcontrol
.authenticated
= 1;
100 dmcontrol
.version
= 1;
101 dmcontrol
.authtype
= dmcontrol
.AUTHTYPE_NOAUTH
;
104 abstractcs
.datacount
= sizeof(dmdata
.data
) / 4;
107 void debug_module_t::add_device(bus_t
*bus
) {
108 bus
->add_device(DEBUG_START
, this);
109 bus
->add_device(DEBUG_EXCHANGE
, &dmdata
);
112 bool debug_module_t::load(reg_t addr
, size_t len
, uint8_t* bytes
)
114 D(fprintf(stderr
, "debug_module_t load 0x%lx bytes at 0x%lx\n",
116 addr
= DEBUG_START
+ addr
;
118 if (addr
>= DEBUG_ROM_ENTRY
&&
119 addr
< DEBUG_ROM_ENTRY
+ DEBUG_ROM_ENTRY_SIZE
) {
121 if (read32(debug_rom_entry
, dmcontrol
.hartsel
) == jal(ZERO
, 0)) {
122 // We're here in an infinite loop. That means that whatever abstract
123 // command has complete.
124 abstractcs
.busy
= false;
127 action_executed
= true;
129 halted
[(addr
- DEBUG_ROM_ENTRY
) / 4] = true;
130 memcpy(bytes
, debug_rom_entry
+ addr
- DEBUG_ROM_ENTRY
, len
);
134 if (action_executed
) {
135 // Restore the jump-to-self loop.
136 write32(debug_rom_entry
, dmcontrol
.hartsel
, next_action
);
137 next_action
= jal(ZERO
, 0);
138 action_executed
= false;
141 if (addr
>= DEBUG_ROM_CODE
&&
142 addr
< DEBUG_ROM_CODE
+ DEBUG_ROM_CODE_SIZE
) {
144 if (read32(debug_rom_code
, 0) == dret()) {
145 abstractcs
.busy
= false;
146 halted
[dmcontrol
.hartsel
] = false;
149 memcpy(bytes
, debug_rom_code
+ addr
- DEBUG_ROM_CODE
, len
);
153 if (addr
>= DEBUG_RAM_START
&& addr
< DEBUG_RAM_END
) {
154 memcpy(bytes
, program_buffer
+ addr
- DEBUG_RAM_START
, len
);
158 if (addr
>= DEBUG_ROM_EXCEPTION
&&
159 addr
< DEBUG_ROM_EXCEPTION
+ DEBUG_ROM_EXCEPTION_SIZE
) {
160 memcpy(bytes
, debug_rom_exception
+ addr
- DEBUG_ROM_EXCEPTION
, len
);
161 if (abstractcs
.cmderr
== abstractcs
.CMDERR_NONE
) {
162 abstractcs
.cmderr
= abstractcs
.CMDERR_EXCEPTION
;
167 fprintf(stderr
, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
168 PRIx64
"\n", len
, addr
);
173 bool debug_module_t::store(reg_t addr
, size_t len
, const uint8_t* bytes
)
175 addr
= DEBUG_START
+ addr
;
177 if (addr
>= DEBUG_RAM_START
&& addr
< DEBUG_RAM_END
) {
178 memcpy(program_buffer
+ addr
- DEBUG_RAM_START
, bytes
, len
);
182 fprintf(stderr
, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
183 PRIx64
"\n", len
, addr
);
187 void debug_module_t::write32(uint8_t *memory
, unsigned int index
, uint32_t value
)
189 uint8_t* base
= memory
+ index
* 4;
190 base
[0] = value
& 0xff;
191 base
[1] = (value
>> 8) & 0xff;
192 base
[2] = (value
>> 16) & 0xff;
193 base
[3] = (value
>> 24) & 0xff;
196 uint32_t debug_module_t::read32(uint8_t *memory
, unsigned int index
)
198 uint8_t* base
= memory
+ index
* 4;
199 uint32_t value
= ((uint32_t) base
[0]) |
200 (((uint32_t) base
[1]) << 8) |
201 (((uint32_t) base
[2]) << 16) |
202 (((uint32_t) base
[3]) << 24);
206 processor_t
*debug_module_t::current_proc() const
208 processor_t
*proc
= NULL
;
210 proc
= sim
->get_core(dmcontrol
.hartsel
);
211 } catch (const std::out_of_range
&) {
216 bool debug_module_t::dmi_read(unsigned address
, uint32_t *value
)
219 D(fprintf(stderr
, "dmi_read(0x%x) -> ", address
));
220 if (address
>= DMI_DATA0
&& address
< DMI_DATA0
+ abstractcs
.datacount
) {
221 unsigned i
= address
- DMI_DATA0
;
222 result
= dmdata
.read32(4 * i
);
224 if (abstractcs
.busy
&& abstractcs
.cmderr
== abstractcs
.CMDERR_NONE
) {
225 abstractcs
.cmderr
= abstractcs
.CMDERR_BUSY
;
228 bool autoexec
= false;
230 case 0: autoexec
= abstractcs
.autoexec0
; break;
231 case 1: autoexec
= abstractcs
.autoexec1
; break;
232 case 2: autoexec
= abstractcs
.autoexec2
; break;
233 case 3: autoexec
= abstractcs
.autoexec3
; break;
234 case 4: autoexec
= abstractcs
.autoexec4
; break;
235 case 5: autoexec
= abstractcs
.autoexec5
; break;
236 case 6: autoexec
= abstractcs
.autoexec6
; break;
237 case 7: autoexec
= abstractcs
.autoexec7
; break;
240 perform_abstract_command();
242 } else if (address
>= DMI_IBUF0
&& address
< DMI_IBUF0
+ progsize
) {
243 result
= read32(program_buffer
, address
- DMI_IBUF0
);
248 processor_t
*proc
= current_proc();
250 if (halted
[dmcontrol
.hartsel
]) {
251 dmcontrol
.hartstatus
= dmcontrol
.HARTSTATUS_HALTED
;
253 dmcontrol
.hartstatus
= dmcontrol
.HARTSTATUS_RUNNING
;
255 dmcontrol
.haltreq
= proc
->halt_request
;
257 dmcontrol
.hartstatus
= dmcontrol
.HARTSTATUS_NOTEXIST
;
259 result
= set_field(result
, DMI_DMCONTROL_HALTREQ
, dmcontrol
.haltreq
);
260 result
= set_field(result
, DMI_DMCONTROL_RESET
, dmcontrol
.reset
);
261 result
= set_field(result
, DMI_DMCONTROL_DMACTIVE
, dmcontrol
.dmactive
);
262 result
= set_field(result
, DMI_DMCONTROL_HARTSTATUS
, dmcontrol
.hartstatus
);
263 result
= set_field(result
, DMI_DMCONTROL_HARTSEL
, dmcontrol
.hartsel
);
264 result
= set_field(result
, DMI_DMCONTROL_AUTHENTICATED
, dmcontrol
.authenticated
);
265 result
= set_field(result
, DMI_DMCONTROL_AUTHBUSY
, dmcontrol
.authbusy
);
266 result
= set_field(result
, DMI_DMCONTROL_AUTHTYPE
, dmcontrol
.authtype
);
267 result
= set_field(result
, DMI_DMCONTROL_VERSION
, dmcontrol
.version
);
271 result
= set_field(result
, DMI_ABSTRACTCS_AUTOEXEC7
, abstractcs
.autoexec7
);
272 result
= set_field(result
, DMI_ABSTRACTCS_AUTOEXEC6
, abstractcs
.autoexec6
);
273 result
= set_field(result
, DMI_ABSTRACTCS_AUTOEXEC5
, abstractcs
.autoexec5
);
274 result
= set_field(result
, DMI_ABSTRACTCS_AUTOEXEC4
, abstractcs
.autoexec4
);
275 result
= set_field(result
, DMI_ABSTRACTCS_AUTOEXEC3
, abstractcs
.autoexec3
);
276 result
= set_field(result
, DMI_ABSTRACTCS_AUTOEXEC2
, abstractcs
.autoexec2
);
277 result
= set_field(result
, DMI_ABSTRACTCS_AUTOEXEC1
, abstractcs
.autoexec1
);
278 result
= set_field(result
, DMI_ABSTRACTCS_AUTOEXEC0
, abstractcs
.autoexec0
);
279 result
= set_field(result
, DMI_ABSTRACTCS_CMDERR
, abstractcs
.cmderr
);
280 result
= set_field(result
, DMI_ABSTRACTCS_BUSY
, abstractcs
.busy
);
281 result
= set_field(result
, DMI_ABSTRACTCS_DATACOUNT
, abstractcs
.datacount
);
284 result
= progsize
<< DMI_ACCESSCS_PROGSIZE_OFFSET
;
290 D(fprintf(stderr
, "error\n"));
294 D(fprintf(stderr
, "0x%x\n", result
));
299 bool debug_module_t::perform_abstract_command()
301 if (abstractcs
.cmderr
!= abstractcs
.CMDERR_NONE
)
303 if (abstractcs
.busy
) {
304 abstractcs
.cmderr
= abstractcs
.CMDERR_BUSY
;
308 if ((command
>> 24) == 0) {
310 unsigned size
= get_field(command
, AC_ACCESS_REGISTER_SIZE
);
311 bool write
= get_field(command
, AC_ACCESS_REGISTER_WRITE
);
312 unsigned regno
= get_field(command
, AC_ACCESS_REGISTER_REGNO
);
314 if (regno
< 0x1000 || regno
>= 0x1020) {
315 abstractcs
.cmderr
= abstractcs
.CMDERR_NOTSUP
;
319 unsigned regnum
= regno
- 0x1000;
321 if (!halted
[dmcontrol
.hartsel
]) {
322 abstractcs
.cmderr
= abstractcs
.CMDERR_HALTRESUME
;
329 write32(debug_rom_code
, 0, lw(regnum
, ZERO
, DEBUG_EXCHANGE
));
331 write32(debug_rom_code
, 0, sw(regnum
, ZERO
, DEBUG_EXCHANGE
));
335 write32(debug_rom_code
, 0, ld(regnum
, ZERO
, DEBUG_EXCHANGE
));
337 write32(debug_rom_code
, 0, sd(regnum
, ZERO
, DEBUG_EXCHANGE
));
342 write32(debug_rom_code, 0, lq(regnum, ZERO, DEBUG_EXCHANGE));
344 write32(debug_rom_code, 0, sq(regnum, ZERO, DEBUG_EXCHANGE));
348 abstractcs
.cmderr
= abstractcs
.CMDERR_NOTSUP
;
351 if (get_field(command
, AC_ACCESS_REGISTER_POSTEXEC
)) {
352 write32(debug_rom_code
, 1, jal(ZERO
, DEBUG_RAM_START
- DEBUG_ROM_CODE
- 4));
354 write32(debug_rom_code
, 1, ebreak());
357 if (get_field(command
, AC_ACCESS_REGISTER_PREEXEC
)) {
358 write32(debug_rom_entry
, dmcontrol
.hartsel
,
359 jal(ZERO
, DEBUG_RAM_START
- (DEBUG_ROM_ENTRY
+ 4 * dmcontrol
.hartsel
)));
361 jal(ZERO
, DEBUG_ROM_CODE
- (DEBUG_ROM_ENTRY
+ 4 * dmcontrol
.hartsel
));
363 write32(debug_rom_entry
, dmcontrol
.hartsel
,
364 jal(ZERO
, DEBUG_ROM_CODE
- (DEBUG_ROM_ENTRY
+ 4 * dmcontrol
.hartsel
)));
367 write32(debug_rom_exception
, dmcontrol
.hartsel
,
368 jal(ZERO
, (DEBUG_ROM_ENTRY
+ 4 * dmcontrol
.hartsel
) - DEBUG_ROM_EXCEPTION
));
369 abstractcs
.busy
= true;
371 abstractcs
.cmderr
= abstractcs
.CMDERR_NOTSUP
;
376 bool debug_module_t::dmi_write(unsigned address
, uint32_t value
)
378 D(fprintf(stderr
, "dmi_write(0x%x, 0x%x)\n", address
, value
));
379 if (address
>= DMI_DATA0
&& address
< DMI_DATA0
+ abstractcs
.datacount
) {
380 unsigned i
= address
- DMI_DATA0
;
381 dmdata
.write32(4 * i
, value
);
383 if (abstractcs
.busy
&& abstractcs
.cmderr
== abstractcs
.CMDERR_NONE
) {
384 abstractcs
.cmderr
= abstractcs
.CMDERR_BUSY
;
387 bool autoexec
= false;
389 case 0: autoexec
= abstractcs
.autoexec0
; break;
390 case 1: autoexec
= abstractcs
.autoexec1
; break;
391 case 2: autoexec
= abstractcs
.autoexec2
; break;
392 case 3: autoexec
= abstractcs
.autoexec3
; break;
393 case 4: autoexec
= abstractcs
.autoexec4
; break;
394 case 5: autoexec
= abstractcs
.autoexec5
; break;
395 case 6: autoexec
= abstractcs
.autoexec6
; break;
396 case 7: autoexec
= abstractcs
.autoexec7
; break;
399 perform_abstract_command();
403 } else if (address
>= DMI_IBUF0
&& address
< DMI_IBUF0
+ progsize
) {
404 write32(program_buffer
, address
- DMI_IBUF0
, value
);
410 dmcontrol
.dmactive
= get_field(value
, DMI_DMCONTROL_DMACTIVE
);
411 if (dmcontrol
.dmactive
) {
412 dmcontrol
.haltreq
= get_field(value
, DMI_DMCONTROL_HALTREQ
);
413 dmcontrol
.resumereq
= get_field(value
, DMI_DMCONTROL_RESUMEREQ
);
414 dmcontrol
.reset
= get_field(value
, DMI_DMCONTROL_RESET
);
415 dmcontrol
.hartsel
= get_field(value
, DMI_DMCONTROL_HARTSEL
);
419 processor_t
*proc
= current_proc();
421 proc
->halt_request
= dmcontrol
.haltreq
;
422 if (dmcontrol
.resumereq
) {
423 write32(debug_rom_code
, 0, dret());
424 write32(debug_rom_entry
, dmcontrol
.hartsel
,
425 jal(ZERO
, DEBUG_ROM_CODE
- (DEBUG_ROM_ENTRY
+ 4 * dmcontrol
.hartsel
)));
426 abstractcs
.busy
= true;
434 return perform_abstract_command();
437 abstractcs
.autoexec7
= get_field(value
, DMI_ABSTRACTCS_AUTOEXEC7
);
438 abstractcs
.autoexec6
= get_field(value
, DMI_ABSTRACTCS_AUTOEXEC6
);
439 abstractcs
.autoexec5
= get_field(value
, DMI_ABSTRACTCS_AUTOEXEC5
);
440 abstractcs
.autoexec4
= get_field(value
, DMI_ABSTRACTCS_AUTOEXEC4
);
441 abstractcs
.autoexec3
= get_field(value
, DMI_ABSTRACTCS_AUTOEXEC3
);
442 abstractcs
.autoexec2
= get_field(value
, DMI_ABSTRACTCS_AUTOEXEC2
);
443 abstractcs
.autoexec1
= get_field(value
, DMI_ABSTRACTCS_AUTOEXEC1
);
444 abstractcs
.autoexec0
= get_field(value
, DMI_ABSTRACTCS_AUTOEXEC0
);
445 if (get_field(value
, DMI_ABSTRACTCS_CMDERR
) == abstractcs
.CMDERR_NONE
) {
446 abstractcs
.cmderr
= abstractcs
.CMDERR_NONE
;