Hi Daniel, Daniel Henrique Barboza <dbarb...@ventanamicro.com> 於 2024年3月8日 週五 上午12:05寫道: > > From: Tomasz Jeznach <tjezn...@rivosinc.com> > > DBG support adds three additional registers: tr_req_iova, tr_req_ctl and > tr_response. > > The DBG cap is always enabled. No on/off toggle is provided for it. > > Signed-off-by: Tomasz Jeznach <tjezn...@rivosinc.com> > Signed-off-by: Daniel Henrique Barboza <dbarb...@ventanamicro.com> > --- > hw/riscv/riscv-iommu-bits.h | 20 +++++++++++++ > hw/riscv/riscv-iommu.c | 57 ++++++++++++++++++++++++++++++++++++- > 2 files changed, 76 insertions(+), 1 deletion(-) > > diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h > index 0994f5ce48..b3f92411bb 100644 > --- a/hw/riscv/riscv-iommu-bits.h > +++ b/hw/riscv/riscv-iommu-bits.h > @@ -83,6 +83,7 @@ struct riscv_iommu_pq_record { > #define RISCV_IOMMU_CAP_MSI_MRIF BIT_ULL(23) > #define RISCV_IOMMU_CAP_ATS BIT_ULL(25) > #define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28) > +#define RISCV_IOMMU_CAP_DBG BIT_ULL(31) > #define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32) > #define RISCV_IOMMU_CAP_PD8 BIT_ULL(38) > > @@ -177,6 +178,25 @@ enum { > RISCV_IOMMU_INTR_COUNT > }; > > +#define RISCV_IOMMU_IPSR_CIP BIT(RISCV_IOMMU_INTR_CQ) > +#define RISCV_IOMMU_IPSR_FIP BIT(RISCV_IOMMU_INTR_FQ) > +#define RISCV_IOMMU_IPSR_PMIP BIT(RISCV_IOMMU_INTR_PM) > +#define RISCV_IOMMU_IPSR_PIP BIT(RISCV_IOMMU_INTR_PQ)
These are not related to the DBG. > + > +/* 5.24 Translation request IOVA (64bits) */ > +#define RISCV_IOMMU_REG_TR_REQ_IOVA 0x0258 > + > +/* 5.25 Translation request control (64bits) */ > +#define RISCV_IOMMU_REG_TR_REQ_CTL 0x0260 > +#define RISCV_IOMMU_TR_REQ_CTL_GO_BUSY BIT_ULL(0) > +#define RISCV_IOMMU_TR_REQ_CTL_PID GENMASK_ULL(31, 12) > +#define RISCV_IOMMU_TR_REQ_CTL_DID GENMASK_ULL(63, 40) > + > +/* 5.26 Translation request response (64bits) */ > +#define RISCV_IOMMU_REG_TR_RESPONSE 0x0268 > +#define RISCV_IOMMU_TR_RESPONSE_FAULT BIT_ULL(0) > +#define RISCV_IOMMU_TR_RESPONSE_PPN RISCV_IOMMU_PPN_FIELD > + > /* 5.27 Interrupt cause to vector (64bits) */ > #define RISCV_IOMMU_REG_IVEC 0x02F8 > > diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c > index 7af5929b10..1fa1286d07 100644 > --- a/hw/riscv/riscv-iommu.c > +++ b/hw/riscv/riscv-iommu.c > @@ -1457,6 +1457,46 @@ static void > riscv_iommu_process_pq_control(RISCVIOMMUState *s) > riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_PQCSR, ctrl_set, ctrl_clr); > } > > +static void riscv_iommu_process_dbg(RISCVIOMMUState *s) > +{ > + uint64_t iova = riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_TR_REQ_IOVA); > + uint64_t ctrl = riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_TR_REQ_CTL); > + unsigned devid = get_field(ctrl, RISCV_IOMMU_TR_REQ_CTL_DID); > + unsigned pid = get_field(ctrl, RISCV_IOMMU_TR_REQ_CTL_PID); > + RISCVIOMMUContext *ctx; > + void *ref; > + > + if (!(ctrl & RISCV_IOMMU_TR_REQ_CTL_GO_BUSY)) { > + return; > + } > + > + ctx = riscv_iommu_ctx(s, devid, pid, &ref); > + if (ctx == NULL) { > + riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_TR_RESPONSE, > + RISCV_IOMMU_TR_RESPONSE_FAULT | > + (RISCV_IOMMU_FQ_CAUSE_DMA_DISABLED << 10)); > + } else { > + IOMMUTLBEntry iotlb = { > + .iova = iova, > + .perm = IOMMU_NONE, .perm should honor tr_req_ctl.[Exe|Nw] > + .addr_mask = ~0, > + .target_as = NULL, > + }; > + int fault = riscv_iommu_translate(s, ctx, &iotlb, false); > + if (fault) { > + iova = RISCV_IOMMU_TR_RESPONSE_FAULT | (((uint64_t) fault) << > 10); > + } else { > + iova = ((iotlb.translated_addr & ~iotlb.addr_mask) >> 2) & For 4-KB page, we should right-shift 12 bits. > + RISCV_IOMMU_TR_RESPONSE_PPN; It's possible that the translation is not 4-KB page (i.e. superpage), which we should set tr_response.S and encode translation range size in tr_response.PPN. Regards, Frank Chang > + } > + riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_TR_RESPONSE, iova); > + } > + > + riscv_iommu_reg_mod64(s, RISCV_IOMMU_REG_TR_REQ_CTL, 0, > + RISCV_IOMMU_TR_REQ_CTL_GO_BUSY); > + riscv_iommu_ctx_put(s, ref); > +} > + > /* Core IOMMU execution activation */ > enum { > RISCV_IOMMU_EXEC_DDTP, > @@ -1502,7 +1542,7 @@ static void *riscv_iommu_core_proc(void* arg) > /* NOP */ > break; > case BIT(RISCV_IOMMU_EXEC_TR_REQUEST): > - /* DBG support not implemented yet */ > + riscv_iommu_process_dbg(s); > break; > } > exec &= ~mask; > @@ -1574,6 +1614,12 @@ static MemTxResult riscv_iommu_mmio_write(void > *opaque, hwaddr addr, > exec = BIT(RISCV_IOMMU_EXEC_PQCSR); > busy = RISCV_IOMMU_PQCSR_BUSY; > break; > + > + case RISCV_IOMMU_REG_TR_REQ_CTL: > + exec = BIT(RISCV_IOMMU_EXEC_TR_REQUEST); > + regb = RISCV_IOMMU_REG_TR_REQ_CTL; > + busy = RISCV_IOMMU_TR_REQ_CTL_GO_BUSY; > + break; > } > > /* > @@ -1746,6 +1792,9 @@ static void riscv_iommu_realize(DeviceState *dev, Error > **errp) > s->cap |= RISCV_IOMMU_CAP_SV32X4 | RISCV_IOMMU_CAP_SV39X4 | > RISCV_IOMMU_CAP_SV48X4 | RISCV_IOMMU_CAP_SV57X4; > } > + /* Enable translation debug interface */ > + s->cap |= RISCV_IOMMU_CAP_DBG; > + > /* Report QEMU target physical address space limits */ > s->cap = set_field(s->cap, RISCV_IOMMU_CAP_PAS, > TARGET_PHYS_ADDR_SPACE_BITS); > @@ -1800,6 +1849,12 @@ static void riscv_iommu_realize(DeviceState *dev, > Error **errp) > stl_le_p(&s->regs_wc[RISCV_IOMMU_REG_IPSR], ~0); > stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_IVEC], 0); > stq_le_p(&s->regs_rw[RISCV_IOMMU_REG_DDTP], s->ddtp); > + /* If debug registers enabled. */ > + if (s->cap & RISCV_IOMMU_CAP_DBG) { > + stq_le_p(&s->regs_ro[RISCV_IOMMU_REG_TR_REQ_IOVA], 0); > + stq_le_p(&s->regs_ro[RISCV_IOMMU_REG_TR_REQ_CTL], > + RISCV_IOMMU_TR_REQ_CTL_GO_BUSY); > + } > > /* Memory region for downstream access, if specified. */ > if (s->target_mr) { > -- > 2.43.2 > >