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;
|
riscv_addr_t hart_address;
|
||||||
/* Memory address to access the scratch memory from the debugger. */
|
/* Memory address to access the scratch memory from the debugger. */
|
||||||
riscv_addr_t debug_address;
|
riscv_addr_t debug_address;
|
||||||
|
struct working_area *area;
|
||||||
} scratch_mem_t;
|
} scratch_mem_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find some scratch memory to be used with the given program.
|
* 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,
|
scratch_mem_t *scratch,
|
||||||
struct riscv_program *program,
|
struct riscv_program *program,
|
||||||
unsigned size_bytes)
|
unsigned size_bytes)
|
||||||
{
|
{
|
||||||
riscv013_info_t *info = get_info(target);
|
|
||||||
|
|
||||||
riscv_addr_t alignment = 1;
|
riscv_addr_t alignment = 1;
|
||||||
while (alignment < size_bytes)
|
while (alignment < size_bytes)
|
||||||
alignment *= 2;
|
alignment *= 2;
|
||||||
|
|
||||||
|
scratch->area = NULL;
|
||||||
|
|
||||||
|
riscv013_info_t *info = get_info(target);
|
||||||
|
|
||||||
if (info->dataaccess == 1) {
|
if (info->dataaccess == 1) {
|
||||||
/* Sign extend dataaddr. */
|
/* Sign extend dataaddr. */
|
||||||
scratch->hart_address = info->dataaddr;
|
scratch->hart_address = info->dataaddr;
|
||||||
|
@ -969,8 +972,9 @@ static int scratch_find(struct target *target,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (riscv_use_scratch_ram) {
|
if (target_alloc_working_area(target, size_bytes + alignment - 1,
|
||||||
scratch->hart_address = (riscv_scratch_ram_address + alignment - 1) &
|
&scratch->area) == ERROR_OK) {
|
||||||
|
scratch->hart_address = (scratch->area->address + alignment - 1) &
|
||||||
~(alignment - 1);
|
~(alignment - 1);
|
||||||
scratch->memory_space = SPACE_DMI_RAM;
|
scratch->memory_space = SPACE_DMI_RAM;
|
||||||
scratch->debug_address = scratch->hart_address;
|
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 "
|
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;
|
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,
|
static int scratch_read64(struct target *target, scratch_mem_t *scratch,
|
||||||
uint64_t *value)
|
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)
|
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
scratch_mem_t scratch;
|
||||||
|
bool use_scratch = false;
|
||||||
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
|
if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 &&
|
||||||
riscv_supports_extension(target, riscv_current_hartid(target), 'D') &&
|
riscv_supports_extension(target, riscv_current_hartid(target), 'D') &&
|
||||||
riscv_xlen(target) < 64) {
|
riscv_xlen(target) < 64) {
|
||||||
/* There are no instructions to move all the bits from a register, so
|
/* There are no instructions to move all the bits from a register, so
|
||||||
* we need to use some scratch RAM. */
|
* we need to use some scratch RAM. */
|
||||||
|
use_scratch = true;
|
||||||
riscv_program_insert(&program, fld(number - GDB_REGNO_FPR0, S0, 0));
|
riscv_program_insert(&program, fld(number - GDB_REGNO_FPR0, S0, 0));
|
||||||
|
|
||||||
scratch_mem_t scratch;
|
if (scratch_reserve(target, &scratch, &program, 8) != ERROR_OK)
|
||||||
if (scratch_find(target, &scratch, &program, 8) != ERROR_OK)
|
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
if (register_write_direct(target, GDB_REGNO_S0, scratch.hart_address)
|
if (register_write_direct(target, GDB_REGNO_S0, scratch.hart_address)
|
||||||
!= ERROR_OK)
|
!= ERROR_OK) {
|
||||||
|
scratch_release(target, &scratch);
|
||||||
return ERROR_FAIL;
|
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;
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (register_write_direct(target, GDB_REGNO_S0, value) != ERROR_OK)
|
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;
|
reg->valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_scratch)
|
||||||
|
scratch_release(target, &scratch);
|
||||||
|
|
||||||
/* Restore S0. */
|
/* Restore S0. */
|
||||||
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK)
|
if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
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,
|
riscv_program_insert(&program, fsd(number - GDB_REGNO_FPR0, S0,
|
||||||
0));
|
0));
|
||||||
|
|
||||||
if (scratch_find(target, &scratch, &program, 8) != ERROR_OK)
|
if (scratch_reserve(target, &scratch, &program, 8) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
use_scratch = true;
|
use_scratch = true;
|
||||||
|
|
||||||
if (register_write_direct(target, GDB_REGNO_S0,
|
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;
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
} else if (riscv_supports_extension(target,
|
} else if (riscv_supports_extension(target,
|
||||||
riscv_current_hartid(target), 'D')) {
|
riscv_current_hartid(target), 'D')) {
|
||||||
riscv_program_insert(&program, fmv_x_d(S0, number - GDB_REGNO_FPR0));
|
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. */
|
/* Don't message on error. Probably the register doesn't exist. */
|
||||||
|
|
||||||
if (use_scratch) {
|
if (use_scratch) {
|
||||||
if (scratch_read64(target, &scratch, value) != ERROR_OK)
|
result = scratch_read64(target, &scratch, value);
|
||||||
return ERROR_FAIL;
|
scratch_release(target, &scratch);
|
||||||
|
if (result != ERROR_OK)
|
||||||
|
return result;
|
||||||
} else {
|
} else {
|
||||||
/* Read S0 */
|
/* Read S0 */
|
||||||
if (register_read_direct(target, value, GDB_REGNO_S0) != ERROR_OK)
|
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.*/
|
/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
|
||||||
int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC;
|
int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC;
|
||||||
|
|
||||||
bool riscv_use_scratch_ram;
|
|
||||||
uint64_t riscv_scratch_ram_address;
|
|
||||||
|
|
||||||
bool riscv_prefer_sba;
|
bool riscv_prefer_sba;
|
||||||
|
|
||||||
/* In addition to the ones in the standard spec, we'll also expose additional
|
/* 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;
|
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)
|
COMMAND_HANDLER(riscv_set_prefer_sba)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 1) {
|
if (CMD_ARGC != 1) {
|
||||||
|
@ -1469,13 +1441,6 @@ static const struct command_registration riscv_exec_command_handlers[] = {
|
||||||
.usage = "riscv set_reset_timeout_sec [sec]",
|
.usage = "riscv set_reset_timeout_sec [sec]",
|
||||||
.help = "Set the wall-clock timeout (in seconds) after reset is deasserted"
|
.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",
|
.name = "set_prefer_sba",
|
||||||
.handler = riscv_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.*/
|
/* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/
|
||||||
extern int riscv_reset_timeout_sec;
|
extern int riscv_reset_timeout_sec;
|
||||||
|
|
||||||
extern bool riscv_use_scratch_ram;
|
|
||||||
extern uint64_t riscv_scratch_ram_address;
|
|
||||||
|
|
||||||
extern bool riscv_prefer_sba;
|
extern bool riscv_prefer_sba;
|
||||||
|
|
||||||
/* Everything needs the RISC-V specific info structure, so here's a nice macro
|
/* Everything needs the RISC-V specific info structure, so here's a nice macro
|
||||||
|
|
Loading…
Reference in New Issue