mirror of https://github.com/xemu-project/xemu.git
hw/riscv/riscv-iommu: add DBG support
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 <tjeznach@rivosinc.com> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20241016204038.649340-11-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
69a9ae4836
commit
a7aa525b93
hw/riscv
|
@ -82,6 +82,7 @@ struct riscv_iommu_pq_record {
|
||||||
#define RISCV_IOMMU_CAP_ATS BIT_ULL(25)
|
#define RISCV_IOMMU_CAP_ATS BIT_ULL(25)
|
||||||
#define RISCV_IOMMU_CAP_T2GPA BIT_ULL(26)
|
#define RISCV_IOMMU_CAP_T2GPA BIT_ULL(26)
|
||||||
#define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28)
|
#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_PAS GENMASK_ULL(37, 32)
|
||||||
#define RISCV_IOMMU_CAP_PD8 BIT_ULL(38)
|
#define RISCV_IOMMU_CAP_PD8 BIT_ULL(38)
|
||||||
#define RISCV_IOMMU_CAP_PD17 BIT_ULL(39)
|
#define RISCV_IOMMU_CAP_PD17 BIT_ULL(39)
|
||||||
|
@ -184,6 +185,22 @@ enum {
|
||||||
RISCV_IOMMU_INTR_COUNT
|
RISCV_IOMMU_INTR_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* 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_NW BIT_ULL(3)
|
||||||
|
#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_S BIT_ULL(9)
|
||||||
|
#define RISCV_IOMMU_TR_RESPONSE_PPN RISCV_IOMMU_PPN_FIELD
|
||||||
|
|
||||||
/* 5.27 Interrupt cause to vector (64bits) */
|
/* 5.27 Interrupt cause to vector (64bits) */
|
||||||
#define RISCV_IOMMU_REG_ICVEC 0x02F8
|
#define RISCV_IOMMU_REG_ICVEC 0x02F8
|
||||||
#define RISCV_IOMMU_ICVEC_CIV GENMASK_ULL(3, 0)
|
#define RISCV_IOMMU_ICVEC_CIV GENMASK_ULL(3, 0)
|
||||||
|
|
|
@ -1764,6 +1764,50 @@ static void riscv_iommu_process_pq_control(RISCVIOMMUState *s)
|
||||||
riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_PQCSR, ctrl_set, ctrl_clr);
|
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 = ctrl & RISCV_IOMMU_TR_REQ_CTL_NW ? IOMMU_RO : IOMMU_RW,
|
||||||
|
.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;
|
||||||
|
iova >>= TARGET_PAGE_BITS;
|
||||||
|
iova &= RISCV_IOMMU_TR_RESPONSE_PPN;
|
||||||
|
|
||||||
|
/* We do not support superpages (> 4kbs) for now */
|
||||||
|
iova &= ~RISCV_IOMMU_TR_RESPONSE_S;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
typedef void riscv_iommu_process_fn(RISCVIOMMUState *s);
|
typedef void riscv_iommu_process_fn(RISCVIOMMUState *s);
|
||||||
|
|
||||||
static void riscv_iommu_update_icvec(RISCVIOMMUState *s, uint64_t data)
|
static void riscv_iommu_update_icvec(RISCVIOMMUState *s, uint64_t data)
|
||||||
|
@ -1928,6 +1972,12 @@ static MemTxResult riscv_iommu_mmio_write(void *opaque, hwaddr addr,
|
||||||
|
|
||||||
return MEMTX_OK;
|
return MEMTX_OK;
|
||||||
|
|
||||||
|
case RISCV_IOMMU_REG_TR_REQ_CTL:
|
||||||
|
process_fn = riscv_iommu_process_dbg;
|
||||||
|
regb = RISCV_IOMMU_REG_TR_REQ_CTL;
|
||||||
|
busy = RISCV_IOMMU_TR_REQ_CTL_GO_BUSY;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2065,6 +2115,9 @@ static void riscv_iommu_realize(DeviceState *dev, Error **errp)
|
||||||
s->cap |= RISCV_IOMMU_CAP_SV32X4 | RISCV_IOMMU_CAP_SV39X4 |
|
s->cap |= RISCV_IOMMU_CAP_SV32X4 | RISCV_IOMMU_CAP_SV39X4 |
|
||||||
RISCV_IOMMU_CAP_SV48X4 | RISCV_IOMMU_CAP_SV57X4;
|
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 */
|
/* Report QEMU target physical address space limits */
|
||||||
s->cap = set_field(s->cap, RISCV_IOMMU_CAP_PAS,
|
s->cap = set_field(s->cap, RISCV_IOMMU_CAP_PAS,
|
||||||
TARGET_PHYS_ADDR_SPACE_BITS);
|
TARGET_PHYS_ADDR_SPACE_BITS);
|
||||||
|
@ -2121,6 +2174,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_wc[RISCV_IOMMU_REG_IPSR], ~0);
|
||||||
stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_ICVEC], 0);
|
stl_le_p(&s->regs_ro[RISCV_IOMMU_REG_ICVEC], 0);
|
||||||
stq_le_p(&s->regs_rw[RISCV_IOMMU_REG_DDTP], s->ddtp);
|
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. */
|
/* Memory region for downstream access, if specified. */
|
||||||
if (s->target_mr) {
|
if (s->target_mr) {
|
||||||
|
|
Loading…
Reference in New Issue