Signed-off-by: Ethan Chen <ethan84@andestech.com>
---
target/riscv/cpu_cfg.h | 2 ++
target/riscv/cpu_helper.c | 18 +++++++++++++++---
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index fb7eebde52..2946fec20c 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -164,6 +164,8 @@ struct RISCVCPUConfig {
bool pmp;
bool debug;
bool misa_w;
+ bool iopmp;
+ uint32_t iopmp_rrid;
bool short_isa_string;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6709622dd3..c2d6a874da 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1418,9 +1418,21 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
}
if (ret == TRANSLATE_SUCCESS) {
- tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
- prot, mmu_idx, tlb_size);
- return true;
+ if (cpu->cfg.iopmp) {
+ /*
+ * Do not align address on early stage because IOPMP needs origin
+ * address for permission check.
+ */
+ tlb_set_page_with_attrs(cs, address, pa,
+ (MemTxAttrs)
+ {
+ .requester_id = cpu->cfg.iopmp_rrid,
+ },
+ prot, mmu_idx, tlb_size);
+ } else {
+ tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
+ prot, mmu_idx, tlb_size);
+ }
} else if (probe) {
return false;
} else {
--
2.34.1