target/riscv: fix riscv_mmu behaviour#1256
target/riscv: fix riscv_mmu behaviour#1256fkhaidari wants to merge 1 commit intoriscv-collab:riscvfrom
Conversation
en-sc
left a comment
There was a problem hiding this comment.
LGTM (reviewed internally).
|
@JanMatCodasip, @MarekVCodasip, could you please take a look? |
| if (!riscv_virt2phys_mode_is_sw(target)) | ||
| return ERROR_OK; | ||
|
|
There was a problem hiding this comment.
Access memory would fail while virt2phys_mode is hw.
| if (!riscv_virt2phys_mode_is_sw(target)) | |
| return ERROR_OK; | |
| if (riscv_virt2phys_mode_is_hw(target)) | |
| return ERROR_OK; |
There was a problem hiding this comment.
With this check virt2phys_mode would return incorrect value: virtual address instead of physical
There was a problem hiding this comment.
Access memory would fail without this check virt2phys_mode while virt2phys_mode is hw. It is correct to return a virtual address while virt2phys_mode is hw. Address translation should be done by hardware when set dcsr.mprven, I have tested it. When virt2phys_mode is hw, the virt2phys command returns the physical address, at least the current modification is incorrect, and both the virt2phys command and memory access will report errors.
There was a problem hiding this comment.
Sorry, I've mistaken. I meant that virt2phys would return incorrect value
There was a problem hiding this comment.
I think I understand you now. You are right, here we have double translation. But I think it has to be fixed in riscv_rw_memory function. Something like:
if (riscv_virt2phys_mode_is_hw(target))
return r->access_memory(target, args);before translation.
Sorry for the mess. This change was a part of #1241. Looks like I have extracted this part incorrectly
There was a problem hiding this comment.
When virt2phys_mode is hw, the virt2phys command still report errors. Translate page table accesses failed due to setting dcsr.mprven. I think maybe it could be fixed in riscv_virt2phys function like this:
RISCV_INFO(r);
int mode = r->virt2phys_mode;
if (riscv_virt2phys_mode_is_hw(target))
r->virt2phys_mode = RISCV_VIRT2PHYS_MODE_SW;
int result = riscv_address_translate(target,
satp_info, get_field(satp_value, RISCV_SATP_PPN(xlen)),
NULL, 0,
virtual, physical);
r->virt2phys_mode = mode;
return result;
There was a problem hiding this comment.
IIUC, riscv_address_translate() function should always perform physical accesses - it should work exclusively with physical addresses. @lz-bro, is this the issue that you are trying to point out?
If that's correct understanding, then we should probably create function r->access_memory_phys that will always perform physical accesses, regardless of r->virt2phys_mode. It looks to me as a cleaner solution than temporarily changing the virt2phys_mode flag.
There was a problem hiding this comment.
@JanMatCodasip Yes, that's exactly what I meant.
There was a problem hiding this comment.
@lz-bro, great catch!
If that's correct understanding, then we should probably create function r->access_memory_phys that will always perform physical accesses, regardless of r->virt2phys_mode. It looks to me as a cleaner solution than temporarily changing the virt2phys_mode flag.
@JanMatCodasip, this will not be enough. In case of 2-stage translation, the first PTE is addressed using a virtual address. I'd suggest bailing out with a message that this is not supported for now (AFAIU, mstatus.MPP will need to be modified/restored for proper support).
... create function r->access_memory_phys that will always perform physical accesses.
AFAIU, this is exactly the purpose of #1241.
There was a problem hiding this comment.
AFAIU, this is exactly the purpose of #1241
You are right, yeah
Fixed riscv_mmu behaviour: buggy check was removed. As a result virt2phys command behaviour was fixed: now it returns translated address even while virt2phys_mode is off. Change-Id: Ie2e6d1057024ab794038d5ed3662ef49a4d71e70 Signed-off-by: Farid Khaydari <f.khaydari@syntacore.com>
| if (riscv_virt2phys_mode_is_hw(target)) | ||
| return r->access_memory(target, args); |
There was a problem hiding this comment.
Do I understand correctly that when virt2phys is off, we should also directly call r->access_memory?
| if (riscv_virt2phys_mode_is_hw(target)) | |
| return r->access_memory(target, args); | |
| if (riscv_virt2phys_mode_is_off(target)) | |
| /* No address translation is performed. Virtual == physical is assumed. */ | |
| return r->access_memory(target, args); | |
| if (riscv_virt2phys_mode_is_hw(target)) | |
| /* Address translation virtual -> physical will be performed by the hardware. */ | |
| return r->access_memory(target, args); | |
| /* Otherwise address translation is performed by OpenOCD - for each 4 KiB page separately. | |
| * The memory operation must be split to page-sized chunks. | |
| */ | |
| ... |
There was a problem hiding this comment.
@fk-sc It looks like you have independently came to the same conclusion in this comment.
| if (!riscv_virt2phys_mode_is_sw(target)) | ||
| return ERROR_OK; | ||
|
|
There was a problem hiding this comment.
IIUC, riscv_address_translate() function should always perform physical accesses - it should work exclusively with physical addresses. @lz-bro, is this the issue that you are trying to point out?
If that's correct understanding, then we should probably create function r->access_memory_phys that will always perform physical accesses, regardless of r->virt2phys_mode. It looks to me as a cleaner solution than temporarily changing the virt2phys_mode flag.
|
@JanMatCodasip, @lz-bro, I'd suggest merging this one as-is. It makes the |
|
@JanMatCodasip, @lz-bro, can we continue merging? Maybe with some extra TODO's |
|
Ping |
|
@JanMatCodasip, @lz-bro, ping |
|
@JanMatCodasip, @lz-bro, can we continue merging? Maybe with some extra TODO's |
Fixed riscv_mmu behaviour: buggy check was removed.
As a result virt2phys command behaviour was fixed: now it
returns translated address even while virt2phys_mode is off.
Change-Id: Ie2e6d1057024ab794038d5ed3662ef49a4d71e70