Skip to content

Commit 96eb73c

Browse files
Merge pull request #90 from riscv/FE_402_fix
Fix reads beyond requested memory range
2 parents b132fac + 39b0125 commit 96eb73c

File tree

1 file changed

+60
-37
lines changed

1 file changed

+60
-37
lines changed

src/target/riscv/riscv-013.c

Lines changed: 60 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,8 +1354,9 @@ static int read_memory(struct target *target, target_addr_t address,
13541354
riscv_addr_t fin_addr = address + (count * size);
13551355
riscv_addr_t prev_addr = ((riscv_addr_t) address) - size;
13561356
bool first = true;
1357-
LOG_DEBUG("writing until final address 0x%" PRIx64, fin_addr);
1358-
while (count > 1 && (cur_addr = riscv_read_debug_buffer_x(target, d_addr)) < fin_addr) {
1357+
bool this_is_last_read = false;
1358+
LOG_DEBUG("reading until final address 0x%" PRIx64, fin_addr);
1359+
while (count > 1 && (cur_addr = riscv_read_debug_buffer_x(target, d_addr)) < fin_addr - size) {
13591360
LOG_DEBUG("transferring burst starting at address 0x%" TARGET_PRIxADDR
13601361
" (previous burst was 0x%" TARGET_PRIxADDR ")", cur_addr,
13611362
prev_addr);
@@ -1372,25 +1373,75 @@ static int read_memory(struct target *target, target_addr_t address,
13721373
size_t reads = 0;
13731374
size_t rereads = reads;
13741375
for (riscv_addr_t i = start; i < count; ++i) {
1375-
size_t index =
1376-
riscv_batch_add_dmi_read(
1377-
batch,
1378-
riscv013_debug_buffer_register(target, r_data));
1379-
assert(index == reads);
1376+
1377+
if (i == count - 1) {
1378+
// don't do actual read in this batch,
1379+
// we will do it later after we disable autoexec
1380+
//
1381+
// this is done to avoid reading more memory than requested
1382+
// which in some special cases(like reading stack located
1383+
// at the very top of RAM) may cause an exception
1384+
this_is_last_read = true;
1385+
} else {
1386+
size_t const index =
1387+
riscv_batch_add_dmi_read(
1388+
batch,
1389+
riscv013_debug_buffer_register(target, r_data));
1390+
assert(index == reads);
1391+
}
1392+
13801393
reads++;
13811394
if (riscv_batch_full(batch))
13821395
break;
13831396
}
13841397

13851398
riscv_batch_run(batch);
13861399

1400+
// Note that if the scan resulted in a Busy DMI response, it
1401+
// is this read to abstractcs that will cause the dmi_busy_delay
1402+
// to be incremented if necessary. The loop condition above
1403+
// catches the case where no writes went through at all.
1404+
1405+
bool retry_batch_transaction = false;
1406+
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
1407+
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
1408+
abstractcs = dmi_read(target, DMI_ABSTRACTCS);
1409+
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
1410+
switch (info->cmderr) {
1411+
case CMDERR_NONE:
1412+
LOG_DEBUG("successful (partial?) memory write");
1413+
break;
1414+
case CMDERR_BUSY:
1415+
LOG_DEBUG("memory write resulted in busy response");
1416+
riscv013_clear_abstract_error(target);
1417+
increase_ac_busy_delay(target);
1418+
retry_batch_transaction = true;
1419+
riscv_batch_free(batch);
1420+
break;
1421+
default:
1422+
LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs);
1423+
riscv013_set_autoexec(target, d_data, 0);
1424+
riscv_set_register(target, GDB_REGNO_S0, s0);
1425+
riscv_set_register(target, GDB_REGNO_S1, s1);
1426+
riscv013_clear_abstract_error(target);
1427+
riscv_batch_free(batch);
1428+
return ERROR_FAIL;
1429+
}
1430+
if (retry_batch_transaction) continue;
1431+
13871432
for (size_t i = start; i < start + reads; ++i) {
13881433
riscv_addr_t offset = size*i;
13891434
riscv_addr_t t_addr = address + offset;
13901435
uint8_t *t_buffer = buffer + offset;
13911436

1392-
uint64_t dmi_out = riscv_batch_get_dmi_read(batch, rereads);
1393-
value = get_field(dmi_out, DTM_DMI_DATA);
1437+
if (this_is_last_read && i == start + reads - 1) {
1438+
riscv013_set_autoexec(target, d_data, 0);
1439+
value = riscv_program_read_ram(&program, r_data);
1440+
} else {
1441+
uint64_t dmi_out = riscv_batch_get_dmi_read(batch, rereads);
1442+
value = get_field(dmi_out, DTM_DMI_DATA);
1443+
}
1444+
13941445
rereads++;
13951446

13961447
switch (size) {
@@ -1414,35 +1465,7 @@ static int read_memory(struct target *target, target_addr_t address,
14141465

14151466
LOG_DEBUG("M[0x%08lx] reads 0x%08lx", (long)t_addr, (long)value);
14161467
}
1417-
14181468
riscv_batch_free(batch);
1419-
1420-
// Note that if the scan resulted in a Busy DMI response, it
1421-
// is this read to abstractcs that will cause the dmi_busy_delay
1422-
// to be incremented if necessary. The loop condition above
1423-
// catches the case where no writes went through at all.
1424-
1425-
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
1426-
while (get_field(abstractcs, DMI_ABSTRACTCS_BUSY))
1427-
abstractcs = dmi_read(target, DMI_ABSTRACTCS);
1428-
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
1429-
switch (info->cmderr) {
1430-
case CMDERR_NONE:
1431-
LOG_DEBUG("successful (partial?) memory write");
1432-
break;
1433-
case CMDERR_BUSY:
1434-
LOG_DEBUG("memory write resulted in busy response");
1435-
riscv013_clear_abstract_error(target);
1436-
increase_ac_busy_delay(target);
1437-
break;
1438-
default:
1439-
LOG_ERROR("error when writing memory, abstractcs=0x%08lx", (long)abstractcs);
1440-
riscv013_set_autoexec(target, d_data, 0);
1441-
riscv_set_register(target, GDB_REGNO_S0, s0);
1442-
riscv_set_register(target, GDB_REGNO_S1, s1);
1443-
riscv013_clear_abstract_error(target);
1444-
return ERROR_FAIL;
1445-
}
14461469
}
14471470

14481471
riscv013_set_autoexec(target, d_data, 0);

0 commit comments

Comments
 (0)