Skip to content

Commit 05d377a

Browse files
committed
target/riscv: move the dcsr modification out of program buffer
when riscv virt2phys_mode is hw, reduce the use of unnecessary program buffers.
1 parent f82c5a7 commit 05d377a

File tree

1 file changed

+64
-95
lines changed

1 file changed

+64
-95
lines changed

src/target/riscv/riscv-013.c

Lines changed: 64 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -2005,13 +2005,6 @@ static int examine(struct target *target)
20052005
info->impebreak);
20062006
}
20072007

2008-
if (info->progbufsize < 4 && riscv_virt2phys_mode_is_hw(target)) {
2009-
LOG_TARGET_ERROR(target, "software address translation "
2010-
"is not available on this target. It requires a "
2011-
"program buffer size of at least 4. (progbufsize=%d) "
2012-
"Use `riscv set_enable_virtual off` to continue.", info->progbufsize);
2013-
}
2014-
20152008
/* Don't call any riscv_* functions until after we've counted the number of
20162009
* cores and initialized registers. */
20172010

@@ -3109,47 +3102,69 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
31093102
}
31103103

31113104
/* TODO: return mem_access_result_t */
3112-
static int modify_privilege(struct target *target, uint64_t *mstatus, uint64_t *mstatus_old)
3105+
static int modify_privilege_for_virt2phys_mode(struct target *target, riscv_reg_t *mstatus, riscv_reg_t *mstatus_old,
3106+
riscv_reg_t *dcsr, riscv_reg_t *dcsr_old)
31133107
{
31143108
assert(mstatus);
31153109
assert(mstatus_old);
3110+
assert(dcsr);
3111+
assert(dcsr_old);
31163112
if (!riscv_virt2phys_mode_is_hw(target))
31173113
return ERROR_OK;
31183114

3119-
/* TODO: handle error in this case
3120-
* modify_privilege function used only for program buffer memory access.
3121-
* Privilege modification requires progbuf size to be at least 5 */
3122-
if (!has_sufficient_progbuf(target, 5)) {
3123-
LOG_TARGET_WARNING(target, "Can't modify privilege to provide "
3124-
"hardware translation: program buffer too small.");
3125-
return ERROR_OK;
3126-
}
3127-
3128-
/* Read DCSR */
3129-
riscv_reg_t dcsr;
3130-
if (register_read_direct(target, &dcsr, GDB_REGNO_DCSR) != ERROR_OK)
3115+
/* Read and save DCSR */
3116+
if (riscv_reg_get(target, dcsr, GDB_REGNO_DCSR) != ERROR_OK)
31313117
return ERROR_FAIL;
3118+
*dcsr_old = *dcsr;
31323119

31333120
/* Read and save MSTATUS */
3134-
if (register_read_direct(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
3121+
if (riscv_reg_get(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
31353122
return ERROR_FAIL;
31363123
*mstatus_old = *mstatus;
31373124

31383125
/* If we come from m-mode with mprv set, we want to keep mpp */
3139-
if (get_field(dcsr, CSR_DCSR_PRV) == PRV_M)
3126+
if (get_field(*dcsr, CSR_DCSR_PRV) == PRV_M)
31403127
return ERROR_OK;
31413128

31423129
/* mstatus.mpp <- dcsr.prv */
3143-
*mstatus = set_field(*mstatus, MSTATUS_MPP, get_field(dcsr, CSR_DCSR_PRV));
3130+
*mstatus = set_field(*mstatus, MSTATUS_MPP, get_field(*dcsr, CSR_DCSR_PRV));
31443131

31453132
/* mstatus.mprv <- 1 */
31463133
*mstatus = set_field(*mstatus, MSTATUS_MPRV, 1);
31473134

31483135
/* Write MSTATUS */
3149-
if (*mstatus == *mstatus_old)
3136+
if (*mstatus != *mstatus_old &&
3137+
riscv_reg_set(target, GDB_REGNO_MSTATUS, *mstatus) != ERROR_OK)
3138+
return ERROR_FAIL;
3139+
3140+
/* dcsr.mprven <- 1 */
3141+
*dcsr = set_field(*dcsr, CSR_DCSR_MPRVEN, CSR_DCSR_MPRVEN_ENABLED);
3142+
3143+
/* Write DCSR */
3144+
if (*dcsr != *dcsr_old &&
3145+
riscv_reg_set(target, GDB_REGNO_DCSR, *dcsr) != ERROR_OK)
3146+
return ERROR_FAIL;
3147+
3148+
return ERROR_OK;
3149+
}
3150+
3151+
static int restore_privilege_from_virt2phys_mode(struct target *target, riscv_reg_t mstatus, riscv_reg_t mstatus_old,
3152+
riscv_reg_t dcsr, riscv_reg_t dcsr_old)
3153+
{
3154+
if (!riscv_virt2phys_mode_is_hw(target))
31503155
return ERROR_OK;
31513156

3152-
return register_write_direct(target, GDB_REGNO_MSTATUS, *mstatus);
3157+
/* Restore MSTATUS */
3158+
if (mstatus != mstatus_old &&
3159+
riscv_reg_set(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK)
3160+
return ERROR_FAIL;
3161+
3162+
/* Restore DCSR */
3163+
if (dcsr != dcsr_old &&
3164+
riscv_reg_set(target, GDB_REGNO_DCSR, dcsr_old) != ERROR_OK)
3165+
return ERROR_FAIL;
3166+
3167+
return ERROR_OK;
31533168
}
31543169

31553170
static int read_memory_bus_v0(struct target *target, const riscv_mem_access_args_t args)
@@ -4188,25 +4203,8 @@ static int read_word_from_s1(struct target *target,
41884203
return ERROR_OK;
41894204
}
41904205

4191-
static int riscv_program_load_mprv(struct riscv_program *p, enum gdb_regno d,
4192-
enum gdb_regno b, int offset, unsigned int size, bool mprven)
4193-
{
4194-
if (mprven && riscv_program_csrrsi(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN,
4195-
GDB_REGNO_DCSR) != ERROR_OK)
4196-
return ERROR_FAIL;
4197-
4198-
if (riscv_program_load(p, d, b, offset, size) != ERROR_OK)
4199-
return ERROR_FAIL;
4200-
4201-
if (mprven && riscv_program_csrrci(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN,
4202-
GDB_REGNO_DCSR) != ERROR_OK)
4203-
return ERROR_FAIL;
4204-
4205-
return ERROR_OK;
4206-
}
4207-
42084206
static int read_memory_progbuf_inner_fill_progbuf(struct target *target,
4209-
uint32_t increment, uint32_t size, bool mprven)
4207+
uint32_t increment, uint32_t size)
42104208
{
42114209
const bool is_repeated_read = increment == 0;
42124210

@@ -4220,8 +4218,7 @@ static int read_memory_progbuf_inner_fill_progbuf(struct target *target,
42204218
struct riscv_program program;
42214219

42224220
riscv_program_init(&program, target);
4223-
if (riscv_program_load_mprv(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size,
4224-
mprven) != ERROR_OK)
4221+
if (riscv_program_load(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size) != ERROR_OK)
42254222
return ERROR_FAIL;
42264223
if (is_repeated_read) {
42274224
if (riscv_program_addi(&program, GDB_REGNO_A0, GDB_REGNO_A0, 1)
@@ -4246,14 +4243,12 @@ static int read_memory_progbuf_inner_fill_progbuf(struct target *target,
42464243
* re-read the data only if `abstract command busy` or `DMI busy`
42474244
* is encountered in the process.
42484245
*/
4249-
static int read_memory_progbuf_inner(struct target *target,
4250-
const riscv_mem_access_args_t args, bool mprven)
4246+
static int read_memory_progbuf_inner(struct target *target, const riscv_mem_access_args_t args)
42514247
{
42524248
assert(riscv_mem_access_is_read(args));
42534249
assert(args.count > 1 && "If count == 1, read_memory_progbuf_inner_one must be called");
42544250

4255-
if (read_memory_progbuf_inner_fill_progbuf(target, args.increment,
4256-
args.size, mprven) != ERROR_OK)
4251+
if (read_memory_progbuf_inner_fill_progbuf(target, args.increment, args.size) != ERROR_OK)
42574252
return ERROR_FAIL;
42584253

42594254
if (read_memory_progbuf_inner_startup(target, args.address,
@@ -4305,8 +4300,7 @@ static int read_memory_progbuf_inner(struct target *target,
43054300
* Only need to save/restore one GPR to read a single word, and the progbuf
43064301
* program doesn't need to increment.
43074302
*/
4308-
static int read_memory_progbuf_inner_one(struct target *target,
4309-
const riscv_mem_access_args_t args, bool mprven)
4303+
static int read_memory_progbuf_inner_one(struct target *target, const riscv_mem_access_args_t args)
43104304
{
43114305
assert(riscv_mem_access_is_read(args));
43124306

@@ -4316,8 +4310,7 @@ static int read_memory_progbuf_inner_one(struct target *target,
43164310
struct riscv_program program;
43174311

43184312
riscv_program_init(&program, target);
4319-
if (riscv_program_load_mprv(&program, GDB_REGNO_S1, GDB_REGNO_S1, 0,
4320-
args.size, mprven) != ERROR_OK)
4313+
if (riscv_program_load(&program, GDB_REGNO_S1, GDB_REGNO_S1, 0, args.size) != ERROR_OK)
43214314
return ERROR_FAIL;
43224315
if (riscv_program_ebreak(&program) != ERROR_OK)
43234316
return ERROR_FAIL;
@@ -4363,19 +4356,18 @@ read_memory_progbuf(struct target *target, const riscv_mem_access_args_t args)
43634356
if (execute_autofence(target) != ERROR_OK)
43644357
return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;
43654358

4366-
uint64_t mstatus = 0;
4367-
uint64_t mstatus_old = 0;
4368-
if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK)
4359+
riscv_reg_t mstatus = 0;
4360+
riscv_reg_t mstatus_old = 0;
4361+
riscv_reg_t dcsr = 0;
4362+
riscv_reg_t dcsr_old = 0;
4363+
if (modify_privilege_for_virt2phys_mode(target, &mstatus, &mstatus_old, &dcsr, &dcsr_old) != ERROR_OK)
43694364
return MEM_ACCESS_FAILED_PRIV_MOD_FAILED;
43704365

4371-
const bool mprven = riscv_virt2phys_mode_is_hw(target)
4372-
&& get_field(mstatus, MSTATUS_MPRV);
43734366
int result = (args.count == 1) ?
4374-
read_memory_progbuf_inner_one(target, args, mprven) :
4375-
read_memory_progbuf_inner(target, args, mprven);
4367+
read_memory_progbuf_inner_one(target, args) :
4368+
read_memory_progbuf_inner(target, args);
43764369

4377-
if (mstatus != mstatus_old &&
4378-
register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK)
4370+
if (restore_privilege_from_virt2phys_mode(target, mstatus, mstatus_old, dcsr, dcsr_old) != ERROR_OK)
43794371
return MEM_ACCESS_FAILED;
43804372

43814373
return (result == ERROR_OK) ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
@@ -4833,25 +4825,7 @@ static int write_memory_progbuf_try_to_write(struct target *target,
48334825
return result;
48344826
}
48354827

4836-
static int riscv_program_store_mprv(struct riscv_program *p, enum gdb_regno d,
4837-
enum gdb_regno b, int offset, unsigned int size, bool mprven)
4838-
{
4839-
if (mprven && riscv_program_csrrsi(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN,
4840-
GDB_REGNO_DCSR) != ERROR_OK)
4841-
return ERROR_FAIL;
4842-
4843-
if (riscv_program_store(p, d, b, offset, size) != ERROR_OK)
4844-
return ERROR_FAIL;
4845-
4846-
if (mprven && riscv_program_csrrci(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN,
4847-
GDB_REGNO_DCSR) != ERROR_OK)
4848-
return ERROR_FAIL;
4849-
4850-
return ERROR_OK;
4851-
}
4852-
4853-
static int write_memory_progbuf_fill_progbuf(struct target *target,
4854-
uint32_t size, bool mprven)
4828+
static int write_memory_progbuf_fill_progbuf(struct target *target, uint32_t size)
48554829
{
48564830
if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
48574831
return ERROR_FAIL;
@@ -4861,8 +4835,7 @@ static int write_memory_progbuf_fill_progbuf(struct target *target,
48614835
struct riscv_program program;
48624836

48634837
riscv_program_init(&program, target);
4864-
if (riscv_program_store_mprv(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size,
4865-
mprven) != ERROR_OK)
4838+
if (riscv_program_store(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size) != ERROR_OK)
48664839
return ERROR_FAIL;
48674840

48684841
if (riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size) != ERROR_OK)
@@ -4874,12 +4847,11 @@ static int write_memory_progbuf_fill_progbuf(struct target *target,
48744847
return riscv_program_write(&program);
48754848
}
48764849

4877-
static int write_memory_progbuf_inner(struct target *target, const riscv_mem_access_args_t args, bool mprven)
4850+
static int write_memory_progbuf_inner(struct target *target, const riscv_mem_access_args_t args)
48784851
{
48794852
assert(riscv_mem_access_is_write(args));
48804853

4881-
if (write_memory_progbuf_fill_progbuf(target, args.size,
4882-
mprven) != ERROR_OK)
4854+
if (write_memory_progbuf_fill_progbuf(target, args.size) != ERROR_OK)
48834855
return ERROR_FAIL;
48844856

48854857
target_addr_t addr_on_target = args.address;
@@ -4923,18 +4895,15 @@ write_memory_progbuf(struct target *target, const riscv_mem_access_args_t args)
49234895

49244896
uint64_t mstatus = 0;
49254897
uint64_t mstatus_old = 0;
4926-
if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK)
4898+
uint64_t dcsr = 0;
4899+
uint64_t dcsr_old = 0;
4900+
if (modify_privilege_for_virt2phys_mode(target, &mstatus, &mstatus_old, &dcsr, &dcsr_old) != ERROR_OK)
49274901
return MEM_ACCESS_FAILED_PRIV_MOD_FAILED;
49284902

4929-
const bool mprven = riscv_virt2phys_mode_is_hw(target)
4930-
&& get_field(mstatus, MSTATUS_MPRV);
4903+
int result = write_memory_progbuf_inner(target, args);
49314904

4932-
int result = write_memory_progbuf_inner(target, args, mprven);
4933-
4934-
/* Restore MSTATUS */
4935-
if (mstatus != mstatus_old)
4936-
if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old))
4937-
return MEM_ACCESS_FAILED;
4905+
if (restore_privilege_from_virt2phys_mode(target, mstatus, mstatus_old, dcsr, dcsr_old) != ERROR_OK)
4906+
return MEM_ACCESS_FAILED;
49384907

49394908
if (execute_autofence(target) != ERROR_OK)
49404909
return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;

0 commit comments

Comments
 (0)