Merge pull request #279 from riscv/work_area
Use work area instead of riscv-specific config
This commit is contained in:
commit
8b25d2f2ee
|
@ -923,22 +923,25 @@ typedef struct {
|
|||
riscv_addr_t hart_address;
|
||||
/* Memory address to access the scratch memory from the debugger. */
|
||||
riscv_addr_t debug_address;
|
||||
struct working_area *area;
|
||||
} scratch_mem_t;
|
||||
|
||||
/**
|
||||
* Find some scratch memory to be used with the given program.
|
||||
*/
|
||||
static int scratch_find(struct target *target,
|
||||
static int scratch_reserve(struct target *target,
|
||||
scratch_mem_t *scratch,
|
||||
struct riscv_program *program,
|
||||
unsigned size_bytes)
|
||||
{
|
||||
riscv013_info_t *info = get_info(target);
|
||||
|
||||
riscv_addr_t alignment = 1;
|
||||
while (alignment < size_bytes)
|
||||
alignment *= 2;
|
||||
|
||||
scratch->area = NULL;
|
||||
|
||||
riscv013_info_t *info = get_info(target);
|
||||
|
||||
if (info->dataaccess == 1) {
|
||||
/* Sign extend dataaddr. */
|
||||
scratch->hart_address = info->dataaddr;
|
||||
|
@ -969,8 +972,9 @@ static int scratch_find(struct target *target,
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
if (riscv_use_scratch_ram) {
|
||||
scratch->hart_address = (riscv_scratch_ram_address + alignment - 1) &
|
||||
if (target_alloc_working_area(target, size_bytes + alignment - 1,
|
||||
&scratch->area) == ERROR_OK) {
|
||||
scratch->hart_address = (scratch->area->address + alignment - 1) &
|
||||
~(alignment - 1);
|
||||
scratch->memory_space = SPACE_DMI_RAM;
|
||||
scratch->debug_address = scratch->hart_address;
|
||||
|
@ -978,10 +982,19 @@ static int scratch_find(struct target *target,
|
|||
}
|
||||
|
||||
LOG_ERROR("Couldn't find %d bytes of scratch RAM to use. Please configure "
|
||||
"an address with 'riscv set_scratch_ram'.", size_bytes);
|
||||
"a work area with 'configure -work-area-phys'.", size_bytes);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
static int scratch_release(struct target *target,
|
||||
scratch_mem_t *scratch)
|
||||
{
|
||||
if (scratch->area)
|
||||
return target_free_working_area(target, scratch->area);
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
static int scratch_read64(struct target *target, scratch_mem_t *scratch,
|
||||
uint64_t *value)
|
||||
{
|
||||
|
@ -1096,23 +1109,29 @@ static int register_write_direct(struct target *target, unsigned number,
|
|||
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
scratch_mem_t scratch;
|
||||
bool use_scratch = false;
|
||||
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
|
||||
riscv_supports_extension(target, riscv_current_hartid(target), 'D') &&
|
||||
riscv_xlen(target) < 64) {
|
||||
/* There are no instructions to move all the bits from a register, so
|
||||
* we need to use some scratch RAM. */
|
||||
use_scratch = true;
|
||||
riscv_program_insert(&program, fld(number - GDB_REGNO_FPR0, S0, 0));
|
||||
|
||||
scratch_mem_t scratch;
|
||||
if (scratch_find(target, &scratch, &program, 8) != ERROR_OK)
|
||||
if (scratch_reserve(target, &scratch, &program, 8) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
||||
if (register_write_direct(target, GDB_REGNO_S0, scratch.hart_address)
|
||||
!= ERROR_OK)
|
||||
!= ERROR_OK) {
|
||||
scratch_release(target, &scratch);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (scratch_write64(target, &scratch, value) != ERROR_OK)
|
||||
if (scratch_write64(target, &scratch, value) != ERROR_OK) {
|
||||
scratch_release(target, &scratch);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (register_write_direct(target, GDB_REGNO_S0, value) != ERROR_OK)
|
||||
|
@ -1139,6 +1158,9 @@ static int register_write_direct(struct target *target, unsigned number,
|
|||
reg->valid = true;
|
||||
}
|
||||
|
||||
if (use_scratch)
|
||||
scratch_release(target, &scratch);
|
||||
|
||||
/* Restore S0. */
|
||||
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
|
@ -1215,13 +1237,15 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
|
|||
riscv_program_insert(&program, fsd(number - GDB_REGNO_FPR0, S0,
|
||||
0));
|
||||
|
||||
if (scratch_find(target, &scratch, &program, 8) != ERROR_OK)
|
||||
if (scratch_reserve(target, &scratch, &program, 8) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
use_scratch = true;
|
||||
|
||||
if (register_write_direct(target, GDB_REGNO_S0,
|
||||
scratch.hart_address) != ERROR_OK)
|
||||
scratch.hart_address) != ERROR_OK) {
|
||||
scratch_release(target, &scratch);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
} else if (riscv_supports_extension(target,
|
||||
riscv_current_hartid(target), 'D')) {
|
||||
riscv_program_insert(&program, fmv_x_d(S0, number - GDB_REGNO_FPR0));
|
||||
|
@ -1240,8 +1264,10 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
|
|||
/* Don't message on error. Probably the register doesn't exist. */
|
||||
|
||||
if (use_scratch) {
|
||||
if (scratch_read64(target, &scratch, value) != ERROR_OK)
|
||||
return ERROR_FAIL;
|
||||
result = scratch_read64(target, &scratch, value);
|
||||
scratch_release(target, &scratch);
|
||||
if (result != ERROR_OK)
|
||||
return result;
|
||||
} else {
|
||||
/* Read S0 */
|
||||
if (register_read_direct(target, value, GDB_REGNO_S0) != ERROR_OK)
|
||||
|
|
|
@ -185,9 +185,6 @@ int riscv_command_timeout_sec = DEFAULT_COMMAND_TIMEOUT_SEC;
|
|||
/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
|
||||
int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC;
|
||||
|
||||
bool riscv_use_scratch_ram;
|
||||
uint64_t riscv_scratch_ram_address;
|
||||
|
||||
bool riscv_prefer_sba;
|
||||
|
||||
/* In addition to the ones in the standard spec, we'll also expose additional
|
||||
|
@ -1230,31 +1227,6 @@ COMMAND_HANDLER(riscv_set_reset_timeout_sec)
|
|||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(riscv_set_scratch_ram)
|
||||
{
|
||||
if (CMD_ARGC != 1) {
|
||||
LOG_ERROR("Command takes exactly 1 parameter");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
if (!strcmp(CMD_ARGV[0], "none")) {
|
||||
riscv_use_scratch_ram = false;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
/* TODO: use COMMAND_PARSE_NUMBER */
|
||||
long long unsigned int address;
|
||||
int result = sscanf(CMD_ARGV[0], "%llx", &address);
|
||||
if (result != (int) strlen(CMD_ARGV[0])) {
|
||||
LOG_ERROR("%s is not a valid address for command.", CMD_ARGV[0]);
|
||||
riscv_use_scratch_ram = false;
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
riscv_scratch_ram_address = address;
|
||||
riscv_use_scratch_ram = true;
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(riscv_set_prefer_sba)
|
||||
{
|
||||
if (CMD_ARGC != 1) {
|
||||
|
@ -1469,13 +1441,6 @@ static const struct command_registration riscv_exec_command_handlers[] = {
|
|||
.usage = "riscv set_reset_timeout_sec [sec]",
|
||||
.help = "Set the wall-clock timeout (in seconds) after reset is deasserted"
|
||||
},
|
||||
{
|
||||
.name = "set_scratch_ram",
|
||||
.handler = riscv_set_scratch_ram,
|
||||
.mode = COMMAND_ANY,
|
||||
.usage = "riscv set_scratch_ram none|[address]",
|
||||
.help = "Set address of 16 bytes of scratch RAM the debugger can use, or 'none'."
|
||||
},
|
||||
{
|
||||
.name = "set_prefer_sba",
|
||||
.handler = riscv_set_prefer_sba,
|
||||
|
|
|
@ -128,9 +128,6 @@ extern int riscv_command_timeout_sec;
|
|||
/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
|
||||
extern int riscv_reset_timeout_sec;
|
||||
|
||||
extern bool riscv_use_scratch_ram;
|
||||
extern uint64_t riscv_scratch_ram_address;
|
||||
|
||||
extern bool riscv_prefer_sba;
|
||||
|
||||
/* Everything needs the RISC-V specific info structure, so here's a nice macro
|
||||
|
|
Loading…
Reference in New Issue