diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 58df51a0c..3ea324260 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -390,7 +390,7 @@ static int gdb_put_packet_inner(struct connection *connection, break; } - LOG_WARNING("Discard unexpected char %c", reply); + LOG_DEBUG("Discard unexpected char %c", reply); } #endif diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 11a7c3cdd..8919d4a06 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -2040,53 +2040,13 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address, * Read the requested memory, taking care to execute every read exactly once, * even if cmderr=busy is encountered. */ -static int read_memory_progbuf(struct target *target, target_addr_t address, +static int read_memory_progbuf_inner(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { RISCV013_INFO(info); int result = ERROR_OK; - LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count, - size, address); - - select_dmi(target); - - /* s0 holds the next address to write to - * s1 holds the next data value to write - */ - uint64_t s0, s1; - if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) - return ERROR_FAIL; - if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK) - return ERROR_FAIL; - - if (execute_fence(target) != ERROR_OK) - return ERROR_FAIL; - - /* Write the program (load, increment) */ - struct riscv_program program; - riscv_program_init(&program, target); - switch (size) { - case 1: - riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0); - break; - case 2: - riscv_program_lhr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0); - break; - case 4: - riscv_program_lwr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0); - break; - default: - LOG_ERROR("Unsupported size: %d", size); - return ERROR_FAIL; - } - riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size); - - if (riscv_program_ebreak(&program) != ERROR_OK) - return ERROR_FAIL; - riscv_program_write(&program); - /* Write address to S0, and execute buffer. */ result = register_write_direct(target, GDB_REGNO_S0, address); if (result != ERROR_OK) @@ -2214,7 +2174,7 @@ static int read_memory_progbuf(struct target *target, target_addr_t address, 1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET); break; default: - LOG_ERROR("error when reading memory, abstractcs=0x%08lx", (long)abstractcs); + LOG_DEBUG("error when reading memory, abstractcs=0x%08lx", (long)abstractcs); riscv013_clear_abstract_error(target); riscv_batch_free(batch); result = ERROR_FAIL; @@ -2272,13 +2232,90 @@ static int read_memory_progbuf(struct target *target, target_addr_t address, write_to_buf(buffer + receive_addr - address, value, size); log_memory_access(receive_addr, value, size, true); - riscv_set_register(target, GDB_REGNO_S0, s0); - riscv_set_register(target, GDB_REGNO_S1, s1); return ERROR_OK; error: dmi_write(target, DMI_ABSTRACTAUTO, 0); + return result; +} + +/** + * Read the requested memory, silently handling memory access errors. + */ +static int read_memory_progbuf(struct target *target, target_addr_t address, + uint32_t size, uint32_t count, uint8_t *buffer) +{ + int result = ERROR_OK; + + LOG_DEBUG("reading %d words of %d bytes from 0x%" TARGET_PRIxADDR, count, + size, address); + + select_dmi(target); + + memset(buffer, 0, count*size); + + /* s0 holds the next address to write to + * s1 holds the next data value to write + */ + uint64_t s0, s1; + if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) + return ERROR_FAIL; + if (register_read(target, &s1, GDB_REGNO_S1) != ERROR_OK) + return ERROR_FAIL; + + if (execute_fence(target) != ERROR_OK) + return ERROR_FAIL; + + /* Write the program (load, increment) */ + struct riscv_program program; + riscv_program_init(&program, target); + switch (size) { + case 1: + riscv_program_lbr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0); + break; + case 2: + riscv_program_lhr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0); + break; + case 4: + riscv_program_lwr(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0); + break; + default: + LOG_ERROR("Unsupported size: %d", size); + return ERROR_FAIL; + } + riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size); + + if (riscv_program_ebreak(&program) != ERROR_OK) + return ERROR_FAIL; + riscv_program_write(&program); + + result = read_memory_progbuf_inner(target, address, size, count, buffer); + + if (result != ERROR_OK) { + /* The full read did not succeed, so we will try to read each word individually. */ + /* This will not be fast, but reading outside actual memory is a special case anyway. */ + /* It will make the toolchain happier, especially Eclipse Memory View as it reads ahead. */ + target_addr_t address_i = address; + uint32_t size_i = size; + uint32_t count_i = 1; + uint8_t *buffer_i = buffer; + + for (uint32_t i = 0; i < count; i++, address_i += size_i, buffer_i += size_i) { + result = read_memory_progbuf_inner(target, address_i, size_i, count_i, buffer_i); + + /* The read of a single word failed, so we will just return 0 for that instead */ + if (result != ERROR_OK) { + LOG_DEBUG("error reading single word of %d bytes from 0x%" TARGET_PRIxADDR, + size_i, address_i); + + uint64_t value_i = 0; + write_to_buf(buffer_i, value_i, size_i); + } + } + result = ERROR_OK; + } + riscv_set_register(target, GDB_REGNO_S0, s0); riscv_set_register(target, GDB_REGNO_S1, s1); return result;