Merge pull request #177 from riscv/debug_auth
[riscv-isa-sim.git] / riscv / debug_module.cc
1 #include <cassert>
2
3 #include "debug_module.h"
4 #include "debug_defines.h"
5 #include "opcodes.h"
6 #include "mmu.h"
7
8 #include "debug_rom/debug_rom.h"
9 #include "debug_rom_defines.h"
10
11 #if 0
12 # define D(x) x
13 #else
14 # define D(x)
15 #endif
16
17 ///////////////////////// debug_module_t
18
19 debug_module_t::debug_module_t(sim_t *sim, unsigned progbufsize, unsigned max_bus_master_bits,
20 bool require_authentication) :
21 progbufsize(progbufsize),
22 program_buffer_bytes(4 + 4*progbufsize),
23 max_bus_master_bits(max_bus_master_bits),
24 require_authentication(require_authentication),
25 debug_progbuf_start(debug_data_start - program_buffer_bytes),
26 debug_abstract_start(debug_progbuf_start - debug_abstract_size*4),
27 sim(sim)
28 {
29 D(fprintf(stderr, "debug_data_start=0x%x\n", debug_data_start));
30 D(fprintf(stderr, "debug_progbuf_start=0x%x\n", debug_progbuf_start));
31 D(fprintf(stderr, "debug_abstract_start=0x%x\n", debug_abstract_start));
32
33 program_buffer = new uint8_t[program_buffer_bytes];
34
35 memset(halted, 0, sizeof(halted));
36 memset(debug_rom_flags, 0, sizeof(debug_rom_flags));
37 memset(resumeack, 0, sizeof(resumeack));
38 memset(program_buffer, 0, program_buffer_bytes);
39 program_buffer[4*progbufsize] = ebreak();
40 program_buffer[4*progbufsize+1] = ebreak() >> 8;
41 program_buffer[4*progbufsize+2] = ebreak() >> 16;
42 program_buffer[4*progbufsize+3] = ebreak() >> 24;
43 memset(dmdata, 0, sizeof(dmdata));
44
45 write32(debug_rom_whereto, 0,
46 jal(ZERO, debug_abstract_start - DEBUG_ROM_WHERETO));
47
48 memset(debug_abstract, 0, sizeof(debug_abstract));
49
50 reset();
51 }
52
53 debug_module_t::~debug_module_t()
54 {
55 delete[] program_buffer;
56 }
57
58 void debug_module_t::reset()
59 {
60 for (unsigned i = 0; i < sim->nprocs(); i++) {
61 processor_t *proc = sim->get_core(i);
62 if (proc)
63 proc->halt_request = false;
64 }
65
66 dmcontrol = {0};
67
68 dmstatus = {0};
69 dmstatus.impebreak = true;
70 dmstatus.authenticated = !require_authentication;
71 dmstatus.version = 2;
72
73 abstractcs = {0};
74 abstractcs.datacount = sizeof(dmdata) / 4;
75 abstractcs.progbufsize = progbufsize;
76
77 abstractauto = {0};
78
79 sbcs = {0};
80 if (max_bus_master_bits > 0) {
81 sbcs.version = 1;
82 sbcs.asize = sizeof(reg_t) * 8;
83 }
84 if (max_bus_master_bits >= 64)
85 sbcs.access64 = true;
86 if (max_bus_master_bits >= 32)
87 sbcs.access32 = true;
88 if (max_bus_master_bits >= 16)
89 sbcs.access16 = true;
90 if (max_bus_master_bits >= 8)
91 sbcs.access8 = true;
92
93 challenge = random();
94 }
95
96 void debug_module_t::add_device(bus_t *bus) {
97 bus->add_device(DEBUG_START, this);
98 }
99
100 bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
101 {
102 addr = DEBUG_START + addr;
103
104 if (addr >= DEBUG_ROM_ENTRY &&
105 (addr + len) <= (DEBUG_ROM_ENTRY + debug_rom_raw_len)) {
106 memcpy(bytes, debug_rom_raw + addr - DEBUG_ROM_ENTRY, len);
107 return true;
108 }
109
110 if (addr >= DEBUG_ROM_WHERETO && (addr + len) <= (DEBUG_ROM_WHERETO + 4)) {
111 memcpy(bytes, debug_rom_whereto + addr - DEBUG_ROM_WHERETO, len);
112 return true;
113 }
114
115 if (addr >= DEBUG_ROM_FLAGS && ((addr + len) <= DEBUG_ROM_FLAGS + 1024)) {
116 memcpy(bytes, debug_rom_flags + addr - DEBUG_ROM_FLAGS, len);
117 return true;
118 }
119
120 if (addr >= debug_abstract_start && ((addr + len) <= (debug_abstract_start + sizeof(debug_abstract)))) {
121 memcpy(bytes, debug_abstract + addr - debug_abstract_start, len);
122 return true;
123 }
124
125 if (addr >= debug_data_start && (addr + len) <= (debug_data_start + sizeof(dmdata))) {
126 memcpy(bytes, dmdata + addr - debug_data_start, len);
127 return true;
128 }
129
130 if (addr >= debug_progbuf_start && ((addr + len) <= (debug_progbuf_start + program_buffer_bytes))) {
131 memcpy(bytes, program_buffer + addr - debug_progbuf_start, len);
132 return true;
133 }
134
135 fprintf(stderr, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
136 PRIx64 "\n", len, addr);
137
138 return false;
139 }
140
141 bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
142 {
143 D(
144 switch (len) {
145 case 4:
146 fprintf(stderr, "store(addr=0x%lx, len=%d, bytes=0x%08x); "
147 "hartsel=0x%x\n", addr, (unsigned) len, *(uint32_t *) bytes,
148 dmcontrol.hartsel);
149 break;
150 default:
151 fprintf(stderr, "store(addr=0x%lx, len=%d, bytes=...); "
152 "hartsel=0x%x\n", addr, (unsigned) len, dmcontrol.hartsel);
153 break;
154 }
155 );
156
157 uint8_t id_bytes[4];
158 uint32_t id = 0;
159 if (len == 4) {
160 memcpy(id_bytes, bytes, 4);
161 id = read32(id_bytes, 0);
162 }
163
164 addr = DEBUG_START + addr;
165
166 if (addr >= debug_data_start && (addr + len) <= (debug_data_start + sizeof(dmdata))) {
167 memcpy(dmdata + addr - debug_data_start, bytes, len);
168 return true;
169 }
170
171 if (addr >= debug_progbuf_start && ((addr + len) <= (debug_progbuf_start + program_buffer_bytes))) {
172 memcpy(program_buffer + addr - debug_progbuf_start, bytes, len);
173
174 return true;
175 }
176
177 if (addr == DEBUG_ROM_HALTED) {
178 assert (len == 4);
179 halted[id] = true;
180 if (dmcontrol.hartsel == id) {
181 if (0 == (debug_rom_flags[id] & (1 << DEBUG_ROM_FLAG_GO))){
182 if (dmcontrol.hartsel == id) {
183 abstractcs.busy = false;
184 }
185 }
186 }
187 return true;
188 }
189
190 if (addr == DEBUG_ROM_GOING) {
191 debug_rom_flags[dmcontrol.hartsel] &= ~(1 << DEBUG_ROM_FLAG_GO);
192 return true;
193 }
194
195 if (addr == DEBUG_ROM_RESUMING) {
196 assert (len == 4);
197 halted[id] = false;
198 resumeack[id] = true;
199 debug_rom_flags[id] &= ~(1 << DEBUG_ROM_FLAG_RESUME);
200 return true;
201 }
202
203 if (addr == DEBUG_ROM_EXCEPTION) {
204 if (abstractcs.cmderr == CMDERR_NONE) {
205 abstractcs.cmderr = CMDERR_EXCEPTION;
206 }
207 return true;
208 }
209
210 fprintf(stderr, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
211 PRIx64 "\n", len, addr);
212 return false;
213 }
214
215 void debug_module_t::write32(uint8_t *memory, unsigned int index, uint32_t value)
216 {
217 uint8_t* base = memory + index * 4;
218 base[0] = value & 0xff;
219 base[1] = (value >> 8) & 0xff;
220 base[2] = (value >> 16) & 0xff;
221 base[3] = (value >> 24) & 0xff;
222 }
223
224 uint32_t debug_module_t::read32(uint8_t *memory, unsigned int index)
225 {
226 uint8_t* base = memory + index * 4;
227 uint32_t value = ((uint32_t) base[0]) |
228 (((uint32_t) base[1]) << 8) |
229 (((uint32_t) base[2]) << 16) |
230 (((uint32_t) base[3]) << 24);
231 return value;
232 }
233
234 processor_t *debug_module_t::current_proc() const
235 {
236 processor_t *proc = NULL;
237 try {
238 proc = sim->get_core(dmcontrol.hartsel);
239 } catch (const std::out_of_range&) {
240 }
241 return proc;
242 }
243
244 unsigned debug_module_t::sb_access_bits()
245 {
246 return 8 << sbcs.sbaccess;
247 }
248
249 void debug_module_t::sb_autoincrement()
250 {
251 if (!sbcs.autoincrement || !max_bus_master_bits)
252 return;
253
254 uint64_t value = sbaddress[0] + sb_access_bits() / 8;
255 sbaddress[0] = value;
256 uint32_t carry = value >> 32;
257
258 value = sbaddress[1] + carry;
259 sbaddress[1] = value;
260 carry = value >> 32;
261
262 value = sbaddress[2] + carry;
263 sbaddress[2] = value;
264 carry = value >> 32;
265
266 sbaddress[3] += carry;
267 }
268
269 void debug_module_t::sb_read()
270 {
271 reg_t address = ((uint64_t) sbaddress[1] << 32) | sbaddress[0];
272 try {
273 if (sbcs.sbaccess == 0 && max_bus_master_bits >= 8) {
274 sbdata[0] = sim->debug_mmu->load_uint8(address);
275 } else if (sbcs.sbaccess == 1 && max_bus_master_bits >= 16) {
276 sbdata[0] = sim->debug_mmu->load_uint16(address);
277 } else if (sbcs.sbaccess == 2 && max_bus_master_bits >= 32) {
278 sbdata[0] = sim->debug_mmu->load_uint32(address);
279 } else if (sbcs.sbaccess == 3 && max_bus_master_bits >= 64) {
280 uint64_t value = sim->debug_mmu->load_uint32(address);
281 sbdata[0] = value;
282 sbdata[1] = value >> 32;
283 } else {
284 sbcs.error = 3;
285 }
286 } catch (trap_load_access_fault& t) {
287 sbcs.error = 2;
288 }
289 }
290
291 void debug_module_t::sb_write()
292 {
293 reg_t address = ((uint64_t) sbaddress[1] << 32) | sbaddress[0];
294 D(fprintf(stderr, "sb_write() 0x%x @ 0x%lx\n", sbdata[0], address));
295 if (sbcs.sbaccess == 0 && max_bus_master_bits >= 8) {
296 sim->debug_mmu->store_uint8(address, sbdata[0]);
297 } else if (sbcs.sbaccess == 1 && max_bus_master_bits >= 16) {
298 sim->debug_mmu->store_uint16(address, sbdata[0]);
299 } else if (sbcs.sbaccess == 2 && max_bus_master_bits >= 32) {
300 sim->debug_mmu->store_uint32(address, sbdata[0]);
301 } else if (sbcs.sbaccess == 3 && max_bus_master_bits >= 64) {
302 sim->debug_mmu->store_uint64(address,
303 (((uint64_t) sbdata[1]) << 32) | sbdata[0]);
304 } else {
305 sbcs.error = 3;
306 }
307 }
308
309 bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
310 {
311 uint32_t result = 0;
312 D(fprintf(stderr, "dmi_read(0x%x) -> ", address));
313 if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
314 unsigned i = address - DMI_DATA0;
315 result = read32(dmdata, i);
316 if (abstractcs.busy) {
317 result = -1;
318 fprintf(stderr, "\ndmi_read(0x%02x (data[%d]) -> -1 because abstractcs.busy==true\n", address, i);
319 }
320
321 if (abstractcs.busy && abstractcs.cmderr == CMDERR_NONE) {
322 abstractcs.cmderr = CMDERR_BUSY;
323 }
324
325 if (!abstractcs.busy && ((abstractauto.autoexecdata >> i) & 1)) {
326 perform_abstract_command();
327 }
328 } else if (address >= DMI_PROGBUF0 && address < DMI_PROGBUF0 + progbufsize) {
329 unsigned i = address - DMI_PROGBUF0;
330 result = read32(program_buffer, i);
331 if (abstractcs.busy) {
332 result = -1;
333 fprintf(stderr, "\ndmi_read(0x%02x (progbuf[%d]) -> -1 because abstractcs.busy==true\n", address, i);
334 }
335 if (!abstractcs.busy && ((abstractauto.autoexecprogbuf >> i) & 1)) {
336 perform_abstract_command();
337 }
338
339 } else {
340 switch (address) {
341 case DMI_DMCONTROL:
342 {
343 processor_t *proc = current_proc();
344 if (proc)
345 dmcontrol.haltreq = proc->halt_request;
346
347 result = set_field(result, DMI_DMCONTROL_HALTREQ, dmcontrol.haltreq);
348 result = set_field(result, DMI_DMCONTROL_RESUMEREQ, dmcontrol.resumereq);
349 result = set_field(result, ((1L<<hartsellen)-1) <<
350 DMI_DMCONTROL_HARTSEL_OFFSET, dmcontrol.hartsel);
351 result = set_field(result, DMI_DMCONTROL_HARTRESET, dmcontrol.hartreset);
352 result = set_field(result, DMI_DMCONTROL_NDMRESET, dmcontrol.ndmreset);
353 result = set_field(result, DMI_DMCONTROL_DMACTIVE, dmcontrol.dmactive);
354 }
355 break;
356 case DMI_DMSTATUS:
357 {
358 processor_t *proc = current_proc();
359
360 dmstatus.allnonexistant = false;
361 dmstatus.allunavail = false;
362 dmstatus.allrunning = false;
363 dmstatus.allhalted = false;
364 dmstatus.allresumeack = false;
365 if (proc) {
366 if (halted[dmcontrol.hartsel]) {
367 dmstatus.allhalted = true;
368 } else {
369 dmstatus.allrunning = true;
370 }
371 } else {
372 dmstatus.allnonexistant = true;
373 }
374 dmstatus.anynonexistant = dmstatus.allnonexistant;
375 dmstatus.anyunavail = dmstatus.allunavail;
376 dmstatus.anyrunning = dmstatus.allrunning;
377 dmstatus.anyhalted = dmstatus.allhalted;
378 if (proc) {
379 if (resumeack[dmcontrol.hartsel]) {
380 dmstatus.allresumeack = true;
381 } else {
382 dmstatus.allresumeack = false;
383 }
384 } else {
385 dmstatus.allresumeack = false;
386 }
387
388 result = set_field(result, DMI_DMSTATUS_IMPEBREAK,
389 dmstatus.impebreak);
390 result = set_field(result, DMI_DMSTATUS_ALLNONEXISTENT, dmstatus.allnonexistant);
391 result = set_field(result, DMI_DMSTATUS_ALLUNAVAIL, dmstatus.allunavail);
392 result = set_field(result, DMI_DMSTATUS_ALLRUNNING, dmstatus.allrunning);
393 result = set_field(result, DMI_DMSTATUS_ALLHALTED, dmstatus.allhalted);
394 result = set_field(result, DMI_DMSTATUS_ALLRESUMEACK, dmstatus.allresumeack);
395 result = set_field(result, DMI_DMSTATUS_ANYNONEXISTENT, dmstatus.anynonexistant);
396 result = set_field(result, DMI_DMSTATUS_ANYUNAVAIL, dmstatus.anyunavail);
397 result = set_field(result, DMI_DMSTATUS_ANYRUNNING, dmstatus.anyrunning);
398 result = set_field(result, DMI_DMSTATUS_ANYHALTED, dmstatus.anyhalted);
399 result = set_field(result, DMI_DMSTATUS_ANYRESUMEACK, dmstatus.anyresumeack);
400 result = set_field(result, DMI_DMSTATUS_AUTHENTICATED, dmstatus.authenticated);
401 result = set_field(result, DMI_DMSTATUS_AUTHBUSY, dmstatus.authbusy);
402 result = set_field(result, DMI_DMSTATUS_VERSION, dmstatus.version);
403 }
404 break;
405 case DMI_ABSTRACTCS:
406 result = set_field(result, DMI_ABSTRACTCS_CMDERR, abstractcs.cmderr);
407 result = set_field(result, DMI_ABSTRACTCS_BUSY, abstractcs.busy);
408 result = set_field(result, DMI_ABSTRACTCS_DATACOUNT, abstractcs.datacount);
409 result = set_field(result, DMI_ABSTRACTCS_PROGBUFSIZE,
410 abstractcs.progbufsize);
411 break;
412 case DMI_ABSTRACTAUTO:
413 result = set_field(result, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF, abstractauto.autoexecprogbuf);
414 result = set_field(result, DMI_ABSTRACTAUTO_AUTOEXECDATA, abstractauto.autoexecdata);
415 break;
416 case DMI_COMMAND:
417 result = 0;
418 break;
419 case DMI_HARTINFO:
420 result = set_field(result, DMI_HARTINFO_NSCRATCH, 1);
421 result = set_field(result, DMI_HARTINFO_DATAACCESS, 1);
422 result = set_field(result, DMI_HARTINFO_DATASIZE, abstractcs.datacount);
423 result = set_field(result, DMI_HARTINFO_DATAADDR, debug_data_start);
424 break;
425 case DMI_SBCS:
426 result = set_field(result, DMI_SBCS_SBVERSION, sbcs.version);
427 result = set_field(result, DMI_SBCS_SBREADONADDR, sbcs.readonaddr);
428 result = set_field(result, DMI_SBCS_SBACCESS, sbcs.sbaccess);
429 result = set_field(result, DMI_SBCS_SBAUTOINCREMENT, sbcs.autoincrement);
430 result = set_field(result, DMI_SBCS_SBREADONDATA, sbcs.readondata);
431 result = set_field(result, DMI_SBCS_SBERROR, sbcs.error);
432 result = set_field(result, DMI_SBCS_SBASIZE, sbcs.asize);
433 result = set_field(result, DMI_SBCS_SBACCESS128, sbcs.access128);
434 result = set_field(result, DMI_SBCS_SBACCESS64, sbcs.access64);
435 result = set_field(result, DMI_SBCS_SBACCESS32, sbcs.access32);
436 result = set_field(result, DMI_SBCS_SBACCESS16, sbcs.access16);
437 result = set_field(result, DMI_SBCS_SBACCESS8, sbcs.access8);
438 break;
439 case DMI_SBADDRESS0:
440 result = sbaddress[0];
441 break;
442 case DMI_SBADDRESS1:
443 result = sbaddress[1];
444 break;
445 case DMI_SBADDRESS2:
446 result = sbaddress[2];
447 break;
448 case DMI_SBADDRESS3:
449 result = sbaddress[3];
450 break;
451 case DMI_SBDATA0:
452 result = sbdata[0];
453 if (sbcs.error == 0) {
454 sb_autoincrement();
455 if (sbcs.readondata) {
456 sb_read();
457 }
458 }
459 break;
460 case DMI_SBDATA1:
461 result = sbdata[1];
462 break;
463 case DMI_SBDATA2:
464 result = sbdata[2];
465 break;
466 case DMI_SBDATA3:
467 result = sbdata[3];
468 break;
469 case DMI_AUTHDATA:
470 result = challenge;
471 break;
472 default:
473 result = 0;
474 D(fprintf(stderr, "Unexpected. Returning Error."));
475 return false;
476 }
477 }
478 D(fprintf(stderr, "0x%x\n", result));
479 *value = result;
480 return true;
481 }
482
483 bool debug_module_t::perform_abstract_command()
484 {
485 if (abstractcs.cmderr != CMDERR_NONE)
486 return true;
487 if (abstractcs.busy) {
488 abstractcs.cmderr = CMDERR_BUSY;
489 return true;
490 }
491
492 if ((command >> 24) == 0) {
493 // register access
494 unsigned size = get_field(command, AC_ACCESS_REGISTER_SIZE);
495 bool write = get_field(command, AC_ACCESS_REGISTER_WRITE);
496 unsigned regno = get_field(command, AC_ACCESS_REGISTER_REGNO);
497
498 if (!halted[dmcontrol.hartsel]) {
499 abstractcs.cmderr = CMDERR_HALTRESUME;
500 return true;
501 }
502
503 unsigned i = 0;
504 if (get_field(command, AC_ACCESS_REGISTER_TRANSFER)) {
505
506 if (regno < 0x1000 && progbufsize < 2) {
507 // Make the debugger use the program buffer if it's available, so it
508 // can test both use cases.
509 write32(debug_abstract, i++, csrw(S0, CSR_DSCRATCH));
510
511 if (write) {
512 switch (size) {
513 case 2:
514 write32(debug_abstract, i++, lw(S0, ZERO, debug_data_start));
515 break;
516 case 3:
517 write32(debug_abstract, i++, ld(S0, ZERO, debug_data_start));
518 break;
519 default:
520 abstractcs.cmderr = CMDERR_NOTSUP;
521 return true;
522 }
523 write32(debug_abstract, i++, csrw(S0, regno));
524
525 } else {
526 write32(debug_abstract, i++, csrr(S0, regno));
527 switch (size) {
528 case 2:
529 write32(debug_abstract, i++, sw(S0, ZERO, debug_data_start));
530 break;
531 case 3:
532 write32(debug_abstract, i++, sd(S0, ZERO, debug_data_start));
533 break;
534 default:
535 abstractcs.cmderr = CMDERR_NOTSUP;
536 return true;
537 }
538 }
539 write32(debug_abstract, i++, csrr(S0, CSR_DSCRATCH));
540
541 } else if (regno >= 0x1000 && regno < 0x1020) {
542 unsigned regnum = regno - 0x1000;
543
544 switch (size) {
545 case 2:
546 if (write)
547 write32(debug_abstract, i++, lw(regnum, ZERO, debug_data_start));
548 else
549 write32(debug_abstract, i++, sw(regnum, ZERO, debug_data_start));
550 break;
551 case 3:
552 if (write)
553 write32(debug_abstract, i++, ld(regnum, ZERO, debug_data_start));
554 else
555 write32(debug_abstract, i++, sd(regnum, ZERO, debug_data_start));
556 break;
557 default:
558 abstractcs.cmderr = CMDERR_NOTSUP;
559 return true;
560 }
561
562 } else if (regno >= 0x1020 && regno < 0x1040) {
563 // Don't force the debugger to use progbuf if it exists, so the
564 // debugger has to make the decision not to use abstract commands to
565 // access 64-bit FPRs on 32-bit targets.
566 unsigned fprnum = regno - 0x1020;
567
568 if (write) {
569 switch (size) {
570 case 2:
571 write32(debug_abstract, i++, flw(fprnum, ZERO, debug_data_start));
572 break;
573 case 3:
574 write32(debug_abstract, i++, fld(fprnum, ZERO, debug_data_start));
575 break;
576 default:
577 abstractcs.cmderr = CMDERR_NOTSUP;
578 return true;
579 }
580
581 } else {
582 switch (size) {
583 case 2:
584 write32(debug_abstract, i++, fsw(fprnum, ZERO, debug_data_start));
585 break;
586 case 3:
587 write32(debug_abstract, i++, fsd(fprnum, ZERO, debug_data_start));
588 break;
589 default:
590 abstractcs.cmderr = CMDERR_NOTSUP;
591 return true;
592 }
593 }
594
595 } else {
596 abstractcs.cmderr = CMDERR_NOTSUP;
597 return true;
598 }
599 }
600
601 if (get_field(command, AC_ACCESS_REGISTER_POSTEXEC)) {
602 write32(debug_abstract, i,
603 jal(ZERO, debug_progbuf_start - debug_abstract_start - 4 * i));
604 i++;
605 } else {
606 write32(debug_abstract, i++, ebreak());
607 }
608
609 debug_rom_flags[dmcontrol.hartsel] |= 1 << DEBUG_ROM_FLAG_GO;
610
611 abstractcs.busy = true;
612 } else {
613 abstractcs.cmderr = CMDERR_NOTSUP;
614 }
615 return true;
616 }
617
618 bool debug_module_t::dmi_write(unsigned address, uint32_t value)
619 {
620 D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
621
622 if (!dmstatus.authenticated && address != DMI_AUTHDATA &&
623 address != DMI_DMCONTROL)
624 return false;
625
626 if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
627 unsigned i = address - DMI_DATA0;
628 if (!abstractcs.busy)
629 write32(dmdata, address - DMI_DATA0, value);
630
631 if (abstractcs.busy && abstractcs.cmderr == CMDERR_NONE) {
632 abstractcs.cmderr = CMDERR_BUSY;
633 }
634
635 if (!abstractcs.busy && ((abstractauto.autoexecdata >> i) & 1)) {
636 perform_abstract_command();
637 }
638 return true;
639
640 } else if (address >= DMI_PROGBUF0 && address < DMI_PROGBUF0 + progbufsize) {
641 unsigned i = address - DMI_PROGBUF0;
642
643 if (!abstractcs.busy)
644 write32(program_buffer, i, value);
645
646 if (!abstractcs.busy && ((abstractauto.autoexecprogbuf >> i) & 1)) {
647 perform_abstract_command();
648 }
649 return true;
650
651 } else {
652 switch (address) {
653 case DMI_DMCONTROL:
654 {
655 if (!dmcontrol.dmactive && get_field(value, DMI_DMCONTROL_DMACTIVE))
656 reset();
657 dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE);
658 if (!dmstatus.authenticated)
659 return true;
660 if (dmcontrol.dmactive) {
661 dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ);
662 dmcontrol.resumereq = get_field(value, DMI_DMCONTROL_RESUMEREQ);
663 dmcontrol.hartreset = get_field(value, DMI_DMCONTROL_HARTRESET);
664 dmcontrol.ndmreset = get_field(value, DMI_DMCONTROL_NDMRESET);
665 dmcontrol.hartsel = get_field(value, ((1L<<hartsellen)-1) <<
666 DMI_DMCONTROL_HARTSEL_OFFSET);
667 }
668 processor_t *proc = current_proc();
669 if (proc) {
670 proc->halt_request = dmcontrol.haltreq;
671 if (dmcontrol.resumereq) {
672 debug_rom_flags[dmcontrol.hartsel] |= (1 << DEBUG_ROM_FLAG_RESUME);
673 resumeack[dmcontrol.hartsel] = false;
674 }
675 if (dmcontrol.hartreset) {
676 proc->reset();
677 }
678 }
679 if (dmcontrol.ndmreset) {
680 for (size_t i = 0; i < sim->nprocs(); i++) {
681 proc = sim->get_core(i);
682 proc->reset();
683 }
684 }
685 }
686 return true;
687
688 case DMI_COMMAND:
689 command = value;
690 return perform_abstract_command();
691
692 case DMI_ABSTRACTCS:
693 abstractcs.cmderr = (cmderr_t) (((uint32_t) (abstractcs.cmderr)) & (~(uint32_t)(get_field(value, DMI_ABSTRACTCS_CMDERR))));
694 return true;
695
696 case DMI_ABSTRACTAUTO:
697 abstractauto.autoexecprogbuf = get_field(value,
698 DMI_ABSTRACTAUTO_AUTOEXECPROGBUF);
699 abstractauto.autoexecdata = get_field(value,
700 DMI_ABSTRACTAUTO_AUTOEXECDATA);
701 return true;
702 case DMI_SBCS:
703 sbcs.readonaddr = get_field(value, DMI_SBCS_SBREADONADDR);
704 sbcs.sbaccess = get_field(value, DMI_SBCS_SBACCESS);
705 sbcs.autoincrement = get_field(value, DMI_SBCS_SBAUTOINCREMENT);
706 sbcs.readondata = get_field(value, DMI_SBCS_SBREADONDATA);
707 sbcs.error &= ~get_field(value, DMI_SBCS_SBERROR);
708 return true;
709 case DMI_SBADDRESS0:
710 sbaddress[0] = value;
711 if (sbcs.error == 0 && sbcs.readonaddr) {
712 sb_read();
713 }
714 return true;
715 case DMI_SBADDRESS1:
716 sbaddress[1] = value;
717 return true;
718 case DMI_SBADDRESS2:
719 sbaddress[2] = value;
720 return true;
721 case DMI_SBADDRESS3:
722 sbaddress[3] = value;
723 return true;
724 case DMI_SBDATA0:
725 sbdata[0] = value;
726 if (sbcs.error == 0) {
727 sb_write();
728 if (sbcs.autoincrement && sbcs.error == 0) {
729 sb_autoincrement();
730 }
731 }
732 return true;
733 case DMI_SBDATA1:
734 sbdata[1] = value;
735 return true;
736 case DMI_SBDATA2:
737 sbdata[2] = value;
738 return true;
739 case DMI_SBDATA3:
740 sbdata[3] = value;
741 return true;
742 case DMI_AUTHDATA:
743 D(fprintf(stderr, "debug authentication: got 0x%x; 0x%x unlocks\n", value,
744 challenge + secret));
745 if (require_authentication) {
746 if (value == challenge + secret) {
747 dmstatus.authenticated = true;
748 } else {
749 dmstatus.authenticated = false;
750 challenge = random();
751 }
752 }
753 return true;
754 }
755 }
756 return false;
757 }