From: Frank Chang <[email protected]> According to the RISC-V IOMMU specification:
* When ddtp.iommu_mode is set to Off, there is no DDT look-up, and an "All inbound transactions disallowed" fault (cause = 256) is reported for any inbound transaction. * When ddtp.iommu_mode is set to Bare, there is no DDT look-up, and the translated address is the same as the IOVA, unless the transaction type is disallowed (cause = 260). In the current implementation, the DDT cache is incorrectly looked up even when ddtp.iommu_mode is set to Off or Bare. This may result in unintended cache hits. Therefore, the DDT cache must not be looked up when ddtp.iommu_mode is set to Off or Bare. For other modes, software is required to issue cache invalidation commands before any inbound transactions. Signed-off-by: Frank Chang <[email protected]> --- hw/riscv/riscv-iommu.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index b33c7fe3259..95db811f125 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -1290,13 +1290,18 @@ static RISCVIOMMUContext *riscv_iommu_ctx(RISCVIOMMUState *s, .devid = devid, .process_id = process_id, }; + unsigned mode = get_field(s->ddtp, RISCV_IOMMU_DDTP_MODE); ctx_cache = g_hash_table_ref(s->ctx_cache); - ctx = g_hash_table_lookup(ctx_cache, &key); - if (ctx && (ctx->tc & RISCV_IOMMU_DC_TC_V)) { - *ref = ctx_cache; - return ctx; + if (mode != RISCV_IOMMU_DDTP_MODE_OFF && + mode != RISCV_IOMMU_DDTP_MODE_BARE) { + ctx = g_hash_table_lookup(ctx_cache, &key); + + if (ctx && (ctx->tc & RISCV_IOMMU_DC_TC_V)) { + *ref = ctx_cache; + return ctx; + } } ctx = g_new0(RISCVIOMMUContext, 1); -- 2.43.0
