@@ -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
31893204static 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-
42424240static 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