Skip to content

Commit 5de7310

Browse files
authored
Merge pull request #1190 from lz-bro/enable-hardware-translation
target/riscv: move the dcsr modification out of program buffer
2 parents 550df16 + 05d377a commit 5de7310

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
@@ -2036,13 +2036,6 @@ static int examine(struct target *target)
20362036
info->impebreak);
20372037
}
20382038

2039-
if (info->progbufsize < 4 && riscv_virt2phys_mode_is_hw(target)) {
2040-
LOG_TARGET_ERROR(target, "software address translation "
2041-
"is not available on this target. It requires a "
2042-
"program buffer size of at least 4. (progbufsize=%d) "
2043-
"Use `riscv set_enable_virtual off` to continue.", info->progbufsize);
2044-
}
2045-
20462039
/* Don't call any riscv_* functions until after we've counted the number of
20472040
* cores and initialized registers. */
20482041

@@ -3143,47 +3136,69 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
31433136
}
31443137

31453138
/* TODO: return mem_access_result_t */
3146-
static int modify_privilege(struct target *target, uint64_t *mstatus, uint64_t *mstatus_old)
3139+
static int modify_privilege_for_virt2phys_mode(struct target *target, riscv_reg_t *mstatus, riscv_reg_t *mstatus_old,
3140+
riscv_reg_t *dcsr, riscv_reg_t *dcsr_old)
31473141
{
31483142
assert(mstatus);
31493143
assert(mstatus_old);
3144+
assert(dcsr);
3145+
assert(dcsr_old);
31503146
if (!riscv_virt2phys_mode_is_hw(target))
31513147
return ERROR_OK;
31523148

3153-
/* TODO: handle error in this case
3154-
* modify_privilege function used only for program buffer memory access.
3155-
* Privilege modification requires progbuf size to be at least 5 */
3156-
if (!has_sufficient_progbuf(target, 5)) {
3157-
LOG_TARGET_WARNING(target, "Can't modify privilege to provide "
3158-
"hardware translation: program buffer too small.");
3159-
return ERROR_OK;
3160-
}
3161-
3162-
/* Read DCSR */
3163-
riscv_reg_t dcsr;
3164-
if (register_read_direct(target, &dcsr, GDB_REGNO_DCSR) != ERROR_OK)
3149+
/* Read and save DCSR */
3150+
if (riscv_reg_get(target, dcsr, GDB_REGNO_DCSR) != ERROR_OK)
31653151
return ERROR_FAIL;
3152+
*dcsr_old = *dcsr;
31663153

31673154
/* Read and save MSTATUS */
3168-
if (register_read_direct(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
3155+
if (riscv_reg_get(target, mstatus, GDB_REGNO_MSTATUS) != ERROR_OK)
31693156
return ERROR_FAIL;
31703157
*mstatus_old = *mstatus;
31713158

31723159
/* If we come from m-mode with mprv set, we want to keep mpp */
3173-
if (get_field(dcsr, CSR_DCSR_PRV) == PRV_M)
3160+
if (get_field(*dcsr, CSR_DCSR_PRV) == PRV_M)
31743161
return ERROR_OK;
31753162

31763163
/* mstatus.mpp <- dcsr.prv */
3177-
*mstatus = set_field(*mstatus, MSTATUS_MPP, get_field(dcsr, CSR_DCSR_PRV));
3164+
*mstatus = set_field(*mstatus, MSTATUS_MPP, get_field(*dcsr, CSR_DCSR_PRV));
31783165

31793166
/* mstatus.mprv <- 1 */
31803167
*mstatus = set_field(*mstatus, MSTATUS_MPRV, 1);
31813168

31823169
/* Write MSTATUS */
3183-
if (*mstatus == *mstatus_old)
3170+
if (*mstatus != *mstatus_old &&
3171+
riscv_reg_set(target, GDB_REGNO_MSTATUS, *mstatus) != ERROR_OK)
3172+
return ERROR_FAIL;
3173+
3174+
/* dcsr.mprven <- 1 */
3175+
*dcsr = set_field(*dcsr, CSR_DCSR_MPRVEN, CSR_DCSR_MPRVEN_ENABLED);
3176+
3177+
/* Write DCSR */
3178+
if (*dcsr != *dcsr_old &&
3179+
riscv_reg_set(target, GDB_REGNO_DCSR, *dcsr) != ERROR_OK)
3180+
return ERROR_FAIL;
3181+
3182+
return ERROR_OK;
3183+
}
3184+
3185+
static int restore_privilege_from_virt2phys_mode(struct target *target, riscv_reg_t mstatus, riscv_reg_t mstatus_old,
3186+
riscv_reg_t dcsr, riscv_reg_t dcsr_old)
3187+
{
3188+
if (!riscv_virt2phys_mode_is_hw(target))
31843189
return ERROR_OK;
31853190

3186-
return register_write_direct(target, GDB_REGNO_MSTATUS, *mstatus);
3191+
/* Restore MSTATUS */
3192+
if (mstatus != mstatus_old &&
3193+
riscv_reg_set(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK)
3194+
return ERROR_FAIL;
3195+
3196+
/* Restore DCSR */
3197+
if (dcsr != dcsr_old &&
3198+
riscv_reg_set(target, GDB_REGNO_DCSR, dcsr_old) != ERROR_OK)
3199+
return ERROR_FAIL;
3200+
3201+
return ERROR_OK;
31873202
}
31883203

31893204
static int read_memory_bus_v0(struct target *target, const riscv_mem_access_args_t args)
@@ -4222,25 +4237,8 @@ static int read_word_from_s1(struct target *target,
42224237
return ERROR_OK;
42234238
}
42244239

4225-
static int riscv_program_load_mprv(struct riscv_program *p, enum gdb_regno d,
4226-
enum gdb_regno b, int offset, unsigned int size, bool mprven)
4227-
{
4228-
if (mprven && riscv_program_csrrsi(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN,
4229-
GDB_REGNO_DCSR) != ERROR_OK)
4230-
return ERROR_FAIL;
4231-
4232-
if (riscv_program_load(p, d, b, offset, size) != ERROR_OK)
4233-
return ERROR_FAIL;
4234-
4235-
if (mprven && riscv_program_csrrci(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN,
4236-
GDB_REGNO_DCSR) != ERROR_OK)
4237-
return ERROR_FAIL;
4238-
4239-
return ERROR_OK;
4240-
}
4241-
42424240
static int read_memory_progbuf_inner_fill_progbuf(struct target *target,
4243-
uint32_t increment, uint32_t size, bool mprven)
4241+
uint32_t increment, uint32_t size)
42444242
{
42454243
const bool is_repeated_read = increment == 0;
42464244

@@ -4254,8 +4252,7 @@ static int read_memory_progbuf_inner_fill_progbuf(struct target *target,
42544252
struct riscv_program program;
42554253

42564254
riscv_program_init(&program, target);
4257-
if (riscv_program_load_mprv(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size,
4258-
mprven) != ERROR_OK)
4255+
if (riscv_program_load(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size) != ERROR_OK)
42594256
return ERROR_FAIL;
42604257
if (is_repeated_read) {
42614258
if (riscv_program_addi(&program, GDB_REGNO_A0, GDB_REGNO_A0, 1)
@@ -4280,14 +4277,12 @@ static int read_memory_progbuf_inner_fill_progbuf(struct target *target,
42804277
* re-read the data only if `abstract command busy` or `DMI busy`
42814278
* is encountered in the process.
42824279
*/
4283-
static int read_memory_progbuf_inner(struct target *target,
4284-
const riscv_mem_access_args_t args, bool mprven)
4280+
static int read_memory_progbuf_inner(struct target *target, const riscv_mem_access_args_t args)
42854281
{
42864282
assert(riscv_mem_access_is_read(args));
42874283
assert(args.count > 1 && "If count == 1, read_memory_progbuf_inner_one must be called");
42884284

4289-
if (read_memory_progbuf_inner_fill_progbuf(target, args.increment,
4290-
args.size, mprven) != ERROR_OK)
4285+
if (read_memory_progbuf_inner_fill_progbuf(target, args.increment, args.size) != ERROR_OK)
42914286
return ERROR_FAIL;
42924287

42934288
if (read_memory_progbuf_inner_startup(target, args.address,
@@ -4339,8 +4334,7 @@ static int read_memory_progbuf_inner(struct target *target,
43394334
* Only need to save/restore one GPR to read a single word, and the progbuf
43404335
* program doesn't need to increment.
43414336
*/
4342-
static int read_memory_progbuf_inner_one(struct target *target,
4343-
const riscv_mem_access_args_t args, bool mprven)
4337+
static int read_memory_progbuf_inner_one(struct target *target, const riscv_mem_access_args_t args)
43444338
{
43454339
assert(riscv_mem_access_is_read(args));
43464340

@@ -4350,8 +4344,7 @@ static int read_memory_progbuf_inner_one(struct target *target,
43504344
struct riscv_program program;
43514345

43524346
riscv_program_init(&program, target);
4353-
if (riscv_program_load_mprv(&program, GDB_REGNO_S1, GDB_REGNO_S1, 0,
4354-
args.size, mprven) != ERROR_OK)
4347+
if (riscv_program_load(&program, GDB_REGNO_S1, GDB_REGNO_S1, 0, args.size) != ERROR_OK)
43554348
return ERROR_FAIL;
43564349
if (riscv_program_ebreak(&program) != ERROR_OK)
43574350
return ERROR_FAIL;
@@ -4397,19 +4390,18 @@ read_memory_progbuf(struct target *target, const riscv_mem_access_args_t args)
43974390
if (execute_autofence(target) != ERROR_OK)
43984391
return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;
43994392

4400-
uint64_t mstatus = 0;
4401-
uint64_t mstatus_old = 0;
4402-
if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK)
4393+
riscv_reg_t mstatus = 0;
4394+
riscv_reg_t mstatus_old = 0;
4395+
riscv_reg_t dcsr = 0;
4396+
riscv_reg_t dcsr_old = 0;
4397+
if (modify_privilege_for_virt2phys_mode(target, &mstatus, &mstatus_old, &dcsr, &dcsr_old) != ERROR_OK)
44034398
return MEM_ACCESS_FAILED_PRIV_MOD_FAILED;
44044399

4405-
const bool mprven = riscv_virt2phys_mode_is_hw(target)
4406-
&& get_field(mstatus, MSTATUS_MPRV);
44074400
int result = (args.count == 1) ?
4408-
read_memory_progbuf_inner_one(target, args, mprven) :
4409-
read_memory_progbuf_inner(target, args, mprven);
4401+
read_memory_progbuf_inner_one(target, args) :
4402+
read_memory_progbuf_inner(target, args);
44104403

4411-
if (mstatus != mstatus_old &&
4412-
register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old) != ERROR_OK)
4404+
if (restore_privilege_from_virt2phys_mode(target, mstatus, mstatus_old, dcsr, dcsr_old) != ERROR_OK)
44134405
return MEM_ACCESS_FAILED;
44144406

44154407
return (result == ERROR_OK) ? MEM_ACCESS_OK : MEM_ACCESS_FAILED;
@@ -4867,25 +4859,7 @@ static int write_memory_progbuf_try_to_write(struct target *target,
48674859
return result;
48684860
}
48694861

4870-
static int riscv_program_store_mprv(struct riscv_program *p, enum gdb_regno d,
4871-
enum gdb_regno b, int offset, unsigned int size, bool mprven)
4872-
{
4873-
if (mprven && riscv_program_csrrsi(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN,
4874-
GDB_REGNO_DCSR) != ERROR_OK)
4875-
return ERROR_FAIL;
4876-
4877-
if (riscv_program_store(p, d, b, offset, size) != ERROR_OK)
4878-
return ERROR_FAIL;
4879-
4880-
if (mprven && riscv_program_csrrci(p, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN,
4881-
GDB_REGNO_DCSR) != ERROR_OK)
4882-
return ERROR_FAIL;
4883-
4884-
return ERROR_OK;
4885-
}
4886-
4887-
static int write_memory_progbuf_fill_progbuf(struct target *target,
4888-
uint32_t size, bool mprven)
4862+
static int write_memory_progbuf_fill_progbuf(struct target *target, uint32_t size)
48894863
{
48904864
if (riscv013_reg_save(target, GDB_REGNO_S0) != ERROR_OK)
48914865
return ERROR_FAIL;
@@ -4895,8 +4869,7 @@ static int write_memory_progbuf_fill_progbuf(struct target *target,
48954869
struct riscv_program program;
48964870

48974871
riscv_program_init(&program, target);
4898-
if (riscv_program_store_mprv(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size,
4899-
mprven) != ERROR_OK)
4872+
if (riscv_program_store(&program, GDB_REGNO_S1, GDB_REGNO_S0, 0, size) != ERROR_OK)
49004873
return ERROR_FAIL;
49014874

49024875
if (riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, size) != ERROR_OK)
@@ -4908,12 +4881,11 @@ static int write_memory_progbuf_fill_progbuf(struct target *target,
49084881
return riscv_program_write(&program);
49094882
}
49104883

4911-
static int write_memory_progbuf_inner(struct target *target, const riscv_mem_access_args_t args, bool mprven)
4884+
static int write_memory_progbuf_inner(struct target *target, const riscv_mem_access_args_t args)
49124885
{
49134886
assert(riscv_mem_access_is_write(args));
49144887

4915-
if (write_memory_progbuf_fill_progbuf(target, args.size,
4916-
mprven) != ERROR_OK)
4888+
if (write_memory_progbuf_fill_progbuf(target, args.size) != ERROR_OK)
49174889
return ERROR_FAIL;
49184890

49194891
target_addr_t addr_on_target = args.address;
@@ -4957,18 +4929,15 @@ write_memory_progbuf(struct target *target, const riscv_mem_access_args_t args)
49574929

49584930
uint64_t mstatus = 0;
49594931
uint64_t mstatus_old = 0;
4960-
if (modify_privilege(target, &mstatus, &mstatus_old) != ERROR_OK)
4932+
uint64_t dcsr = 0;
4933+
uint64_t dcsr_old = 0;
4934+
if (modify_privilege_for_virt2phys_mode(target, &mstatus, &mstatus_old, &dcsr, &dcsr_old) != ERROR_OK)
49614935
return MEM_ACCESS_FAILED_PRIV_MOD_FAILED;
49624936

4963-
const bool mprven = riscv_virt2phys_mode_is_hw(target)
4964-
&& get_field(mstatus, MSTATUS_MPRV);
4937+
int result = write_memory_progbuf_inner(target, args);
49654938

4966-
int result = write_memory_progbuf_inner(target, args, mprven);
4967-
4968-
/* Restore MSTATUS */
4969-
if (mstatus != mstatus_old)
4970-
if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old))
4971-
return MEM_ACCESS_FAILED;
4939+
if (restore_privilege_from_virt2phys_mode(target, mstatus, mstatus_old, dcsr, dcsr_old) != ERROR_OK)
4940+
return MEM_ACCESS_FAILED;
49724941

49734942
if (execute_autofence(target) != ERROR_OK)
49744943
return MEM_ACCESS_SKIPPED_FENCE_EXEC_FAILED;

0 commit comments

Comments
 (0)