hw/riscv/riscv-iommu: add ATS support
Add PCIe Address Translation Services (ATS) capabilities to the IOMMU. This will add support for ATS translation requests in Fault/Event queues, Page-request queue and IOATC invalidations. 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> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20241016204038.649340-10-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
9d085a1c3c
commit
69a9ae4836
@ -79,6 +79,7 @@ struct riscv_iommu_pq_record {
|
|||||||
#define RISCV_IOMMU_CAP_SV57X4 BIT_ULL(19)
|
#define RISCV_IOMMU_CAP_SV57X4 BIT_ULL(19)
|
||||||
#define RISCV_IOMMU_CAP_MSI_FLAT BIT_ULL(22)
|
#define RISCV_IOMMU_CAP_MSI_FLAT BIT_ULL(22)
|
||||||
#define RISCV_IOMMU_CAP_MSI_MRIF BIT_ULL(23)
|
#define RISCV_IOMMU_CAP_MSI_MRIF BIT_ULL(23)
|
||||||
|
#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_PAS GENMASK_ULL(37, 32)
|
#define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32)
|
||||||
@ -212,6 +213,7 @@ struct riscv_iommu_dc {
|
|||||||
|
|
||||||
/* Translation control fields */
|
/* Translation control fields */
|
||||||
#define RISCV_IOMMU_DC_TC_V BIT_ULL(0)
|
#define RISCV_IOMMU_DC_TC_V BIT_ULL(0)
|
||||||
|
#define RISCV_IOMMU_DC_TC_EN_ATS BIT_ULL(1)
|
||||||
#define RISCV_IOMMU_DC_TC_EN_PRI BIT_ULL(2)
|
#define RISCV_IOMMU_DC_TC_EN_PRI BIT_ULL(2)
|
||||||
#define RISCV_IOMMU_DC_TC_T2GPA BIT_ULL(3)
|
#define RISCV_IOMMU_DC_TC_T2GPA BIT_ULL(3)
|
||||||
#define RISCV_IOMMU_DC_TC_DTF BIT_ULL(4)
|
#define RISCV_IOMMU_DC_TC_DTF BIT_ULL(4)
|
||||||
@ -273,6 +275,20 @@ struct riscv_iommu_command {
|
|||||||
#define RISCV_IOMMU_CMD_IODIR_DV BIT_ULL(33)
|
#define RISCV_IOMMU_CMD_IODIR_DV BIT_ULL(33)
|
||||||
#define RISCV_IOMMU_CMD_IODIR_DID GENMASK_ULL(63, 40)
|
#define RISCV_IOMMU_CMD_IODIR_DID GENMASK_ULL(63, 40)
|
||||||
|
|
||||||
|
/* 3.1.4 I/O MMU PCIe ATS */
|
||||||
|
#define RISCV_IOMMU_CMD_ATS_OPCODE 4
|
||||||
|
#define RISCV_IOMMU_CMD_ATS_FUNC_INVAL 0
|
||||||
|
#define RISCV_IOMMU_CMD_ATS_FUNC_PRGR 1
|
||||||
|
#define RISCV_IOMMU_CMD_ATS_PID GENMASK_ULL(31, 12)
|
||||||
|
#define RISCV_IOMMU_CMD_ATS_PV BIT_ULL(32)
|
||||||
|
#define RISCV_IOMMU_CMD_ATS_DSV BIT_ULL(33)
|
||||||
|
#define RISCV_IOMMU_CMD_ATS_RID GENMASK_ULL(55, 40)
|
||||||
|
#define RISCV_IOMMU_CMD_ATS_DSEG GENMASK_ULL(63, 56)
|
||||||
|
/* dword1 is the ATS payload, two different payload types for INVAL and PRGR */
|
||||||
|
|
||||||
|
/* ATS.PRGR payload */
|
||||||
|
#define RISCV_IOMMU_CMD_ATS_PRGR_RESP_CODE GENMASK_ULL(47, 44)
|
||||||
|
|
||||||
enum riscv_iommu_dc_fsc_atp_modes {
|
enum riscv_iommu_dc_fsc_atp_modes {
|
||||||
RISCV_IOMMU_DC_FSC_MODE_BARE = 0,
|
RISCV_IOMMU_DC_FSC_MODE_BARE = 0,
|
||||||
RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32 = 8,
|
RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32 = 8,
|
||||||
@ -339,7 +355,32 @@ enum riscv_iommu_fq_ttypes {
|
|||||||
RISCV_IOMMU_FQ_TTYPE_TADDR_INST_FETCH = 5,
|
RISCV_IOMMU_FQ_TTYPE_TADDR_INST_FETCH = 5,
|
||||||
RISCV_IOMMU_FQ_TTYPE_TADDR_RD = 6,
|
RISCV_IOMMU_FQ_TTYPE_TADDR_RD = 6,
|
||||||
RISCV_IOMMU_FQ_TTYPE_TADDR_WR = 7,
|
RISCV_IOMMU_FQ_TTYPE_TADDR_WR = 7,
|
||||||
RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ = 8,
|
RISCV_IOMMU_FQ_TTYPE_PCIE_ATS_REQ = 8,
|
||||||
|
RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ = 9,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Header fields */
|
||||||
|
#define RISCV_IOMMU_PREQ_HDR_PID GENMASK_ULL(31, 12)
|
||||||
|
#define RISCV_IOMMU_PREQ_HDR_PV BIT_ULL(32)
|
||||||
|
#define RISCV_IOMMU_PREQ_HDR_PRIV BIT_ULL(33)
|
||||||
|
#define RISCV_IOMMU_PREQ_HDR_EXEC BIT_ULL(34)
|
||||||
|
#define RISCV_IOMMU_PREQ_HDR_DID GENMASK_ULL(63, 40)
|
||||||
|
|
||||||
|
/* Payload fields */
|
||||||
|
#define RISCV_IOMMU_PREQ_PAYLOAD_R BIT_ULL(0)
|
||||||
|
#define RISCV_IOMMU_PREQ_PAYLOAD_W BIT_ULL(1)
|
||||||
|
#define RISCV_IOMMU_PREQ_PAYLOAD_L BIT_ULL(2)
|
||||||
|
#define RISCV_IOMMU_PREQ_PAYLOAD_M GENMASK_ULL(2, 0)
|
||||||
|
#define RISCV_IOMMU_PREQ_PRG_INDEX GENMASK_ULL(11, 3)
|
||||||
|
#define RISCV_IOMMU_PREQ_UADDR GENMASK_ULL(63, 12)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* struct riscv_iommu_msi_pte - MSI Page Table Entry
|
||||||
|
*/
|
||||||
|
struct riscv_iommu_msi_pte {
|
||||||
|
uint64_t pte;
|
||||||
|
uint64_t mrif_info;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Fields on pte */
|
/* Fields on pte */
|
||||||
|
@ -669,6 +669,20 @@ static bool riscv_iommu_validate_device_ctx(RISCVIOMMUState *s,
|
|||||||
RISCVIOMMUContext *ctx)
|
RISCVIOMMUContext *ctx)
|
||||||
{
|
{
|
||||||
uint32_t fsc_mode, msi_mode;
|
uint32_t fsc_mode, msi_mode;
|
||||||
|
uint64_t gatp;
|
||||||
|
|
||||||
|
if (!(s->cap & RISCV_IOMMU_CAP_ATS) &&
|
||||||
|
(ctx->tc & RISCV_IOMMU_DC_TC_EN_ATS ||
|
||||||
|
ctx->tc & RISCV_IOMMU_DC_TC_EN_PRI ||
|
||||||
|
ctx->tc & RISCV_IOMMU_DC_TC_PRPR)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ctx->tc & RISCV_IOMMU_DC_TC_EN_ATS) &&
|
||||||
|
(ctx->tc & RISCV_IOMMU_DC_TC_T2GPA ||
|
||||||
|
ctx->tc & RISCV_IOMMU_DC_TC_EN_PRI)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(ctx->tc & RISCV_IOMMU_DC_TC_EN_PRI) &&
|
if (!(ctx->tc & RISCV_IOMMU_DC_TC_EN_PRI) &&
|
||||||
ctx->tc & RISCV_IOMMU_DC_TC_PRPR) {
|
ctx->tc & RISCV_IOMMU_DC_TC_PRPR) {
|
||||||
@ -689,6 +703,12 @@ static bool riscv_iommu_validate_device_ctx(RISCVIOMMUState *s,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gatp = get_field(ctx->gatp, RISCV_IOMMU_ATP_MODE_FIELD);
|
||||||
|
if (ctx->tc & RISCV_IOMMU_DC_TC_T2GPA &&
|
||||||
|
gatp == RISCV_IOMMU_DC_IOHGATP_MODE_BARE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
fsc_mode = get_field(ctx->satp, RISCV_IOMMU_DC_FSC_MODE);
|
fsc_mode = get_field(ctx->satp, RISCV_IOMMU_DC_FSC_MODE);
|
||||||
|
|
||||||
if (ctx->tc & RISCV_IOMMU_DC_TC_PDTV) {
|
if (ctx->tc & RISCV_IOMMU_DC_TC_PDTV) {
|
||||||
@ -839,7 +859,12 @@ static int riscv_iommu_ctx_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx)
|
|||||||
RISCV_IOMMU_DC_IOHGATP_MODE_BARE);
|
RISCV_IOMMU_DC_IOHGATP_MODE_BARE);
|
||||||
ctx->satp = set_field(0, RISCV_IOMMU_ATP_MODE_FIELD,
|
ctx->satp = set_field(0, RISCV_IOMMU_ATP_MODE_FIELD,
|
||||||
RISCV_IOMMU_DC_FSC_MODE_BARE);
|
RISCV_IOMMU_DC_FSC_MODE_BARE);
|
||||||
|
|
||||||
ctx->tc = RISCV_IOMMU_DC_TC_V;
|
ctx->tc = RISCV_IOMMU_DC_TC_V;
|
||||||
|
if (s->enable_ats) {
|
||||||
|
ctx->tc |= RISCV_IOMMU_DC_TC_EN_ATS;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->ta = 0;
|
ctx->ta = 0;
|
||||||
ctx->msiptp = 0;
|
ctx->msiptp = 0;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1296,6 +1321,16 @@ static int riscv_iommu_translate(RISCVIOMMUState *s, RISCVIOMMUContext *ctx,
|
|||||||
enable_pri = (iotlb->perm == IOMMU_NONE) && (ctx->tc & BIT_ULL(32));
|
enable_pri = (iotlb->perm == IOMMU_NONE) && (ctx->tc & BIT_ULL(32));
|
||||||
enable_pid = (ctx->tc & RISCV_IOMMU_DC_TC_PDTV);
|
enable_pid = (ctx->tc & RISCV_IOMMU_DC_TC_PDTV);
|
||||||
|
|
||||||
|
/* Check for ATS request. */
|
||||||
|
if (iotlb->perm == IOMMU_NONE) {
|
||||||
|
/* Check if ATS is disabled. */
|
||||||
|
if (!(ctx->tc & RISCV_IOMMU_DC_TC_EN_ATS)) {
|
||||||
|
enable_pri = false;
|
||||||
|
fault = RISCV_IOMMU_FQ_CAUSE_TTYPE_BLOCKED;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
iot = riscv_iommu_iot_lookup(ctx, iot_cache, iotlb->iova);
|
iot = riscv_iommu_iot_lookup(ctx, iot_cache, iotlb->iova);
|
||||||
perm = iot ? iot->perm : IOMMU_NONE;
|
perm = iot ? iot->perm : IOMMU_NONE;
|
||||||
if (perm != IOMMU_NONE) {
|
if (perm != IOMMU_NONE) {
|
||||||
@ -1347,11 +1382,11 @@ done:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fault) {
|
if (fault) {
|
||||||
unsigned ttype;
|
unsigned ttype = RISCV_IOMMU_FQ_TTYPE_PCIE_ATS_REQ;
|
||||||
|
|
||||||
if (iotlb->perm & IOMMU_RW) {
|
if (iotlb->perm & IOMMU_RW) {
|
||||||
ttype = RISCV_IOMMU_FQ_TTYPE_UADDR_WR;
|
ttype = RISCV_IOMMU_FQ_TTYPE_UADDR_WR;
|
||||||
} else {
|
} else if (iotlb->perm & IOMMU_RO) {
|
||||||
ttype = RISCV_IOMMU_FQ_TTYPE_UADDR_RD;
|
ttype = RISCV_IOMMU_FQ_TTYPE_UADDR_RD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1379,6 +1414,71 @@ static MemTxResult riscv_iommu_iofence(RISCVIOMMUState *s, bool notify,
|
|||||||
MEMTXATTRS_UNSPECIFIED);
|
MEMTXATTRS_UNSPECIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void riscv_iommu_ats(RISCVIOMMUState *s,
|
||||||
|
struct riscv_iommu_command *cmd, IOMMUNotifierFlag flag,
|
||||||
|
IOMMUAccessFlags perm,
|
||||||
|
void (*trace_fn)(const char *id))
|
||||||
|
{
|
||||||
|
RISCVIOMMUSpace *as = NULL;
|
||||||
|
IOMMUNotifier *n;
|
||||||
|
IOMMUTLBEvent event;
|
||||||
|
uint32_t pid;
|
||||||
|
uint32_t devid;
|
||||||
|
const bool pv = cmd->dword0 & RISCV_IOMMU_CMD_ATS_PV;
|
||||||
|
|
||||||
|
if (cmd->dword0 & RISCV_IOMMU_CMD_ATS_DSV) {
|
||||||
|
/* Use device segment and requester id */
|
||||||
|
devid = get_field(cmd->dword0,
|
||||||
|
RISCV_IOMMU_CMD_ATS_DSEG | RISCV_IOMMU_CMD_ATS_RID);
|
||||||
|
} else {
|
||||||
|
devid = get_field(cmd->dword0, RISCV_IOMMU_CMD_ATS_RID);
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = get_field(cmd->dword0, RISCV_IOMMU_CMD_ATS_PID);
|
||||||
|
|
||||||
|
QLIST_FOREACH(as, &s->spaces, list) {
|
||||||
|
if (as->devid == devid) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!as || !as->notifier) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.type = flag;
|
||||||
|
event.entry.perm = perm;
|
||||||
|
event.entry.target_as = s->target_as;
|
||||||
|
|
||||||
|
IOMMU_NOTIFIER_FOREACH(n, &as->iova_mr) {
|
||||||
|
if (!pv || n->iommu_idx == pid) {
|
||||||
|
event.entry.iova = n->start;
|
||||||
|
event.entry.addr_mask = n->end - n->start;
|
||||||
|
trace_fn(as->iova_mr.parent_obj.name);
|
||||||
|
memory_region_notify_iommu_one(n, &event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void riscv_iommu_ats_inval(RISCVIOMMUState *s,
|
||||||
|
struct riscv_iommu_command *cmd)
|
||||||
|
{
|
||||||
|
return riscv_iommu_ats(s, cmd, IOMMU_NOTIFIER_DEVIOTLB_UNMAP, IOMMU_NONE,
|
||||||
|
trace_riscv_iommu_ats_inval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void riscv_iommu_ats_prgr(RISCVIOMMUState *s,
|
||||||
|
struct riscv_iommu_command *cmd)
|
||||||
|
{
|
||||||
|
unsigned resp_code = get_field(cmd->dword1,
|
||||||
|
RISCV_IOMMU_CMD_ATS_PRGR_RESP_CODE);
|
||||||
|
|
||||||
|
/* Using the access flag to carry response code information */
|
||||||
|
IOMMUAccessFlags perm = resp_code ? IOMMU_NONE : IOMMU_RW;
|
||||||
|
return riscv_iommu_ats(s, cmd, IOMMU_NOTIFIER_MAP, perm,
|
||||||
|
trace_riscv_iommu_ats_prgr);
|
||||||
|
}
|
||||||
|
|
||||||
static void riscv_iommu_process_ddtp(RISCVIOMMUState *s)
|
static void riscv_iommu_process_ddtp(RISCVIOMMUState *s)
|
||||||
{
|
{
|
||||||
uint64_t old_ddtp = s->ddtp;
|
uint64_t old_ddtp = s->ddtp;
|
||||||
@ -1534,6 +1634,25 @@ static void riscv_iommu_process_cq_tail(RISCVIOMMUState *s)
|
|||||||
get_field(cmd.dword0, RISCV_IOMMU_CMD_IODIR_PID));
|
get_field(cmd.dword0, RISCV_IOMMU_CMD_IODIR_PID));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* ATS commands */
|
||||||
|
case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_ATS_FUNC_INVAL,
|
||||||
|
RISCV_IOMMU_CMD_ATS_OPCODE):
|
||||||
|
if (!s->enable_ats) {
|
||||||
|
goto cmd_ill;
|
||||||
|
}
|
||||||
|
|
||||||
|
riscv_iommu_ats_inval(s, &cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_ATS_FUNC_PRGR,
|
||||||
|
RISCV_IOMMU_CMD_ATS_OPCODE):
|
||||||
|
if (!s->enable_ats) {
|
||||||
|
goto cmd_ill;
|
||||||
|
}
|
||||||
|
|
||||||
|
riscv_iommu_ats_prgr(s, &cmd);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cmd_ill:
|
cmd_ill:
|
||||||
/* Invalid instruction, do not advance instruction index. */
|
/* Invalid instruction, do not advance instruction index. */
|
||||||
@ -1935,6 +2054,9 @@ static void riscv_iommu_realize(DeviceState *dev, Error **errp)
|
|||||||
if (s->enable_msi) {
|
if (s->enable_msi) {
|
||||||
s->cap |= RISCV_IOMMU_CAP_MSI_FLAT | RISCV_IOMMU_CAP_MSI_MRIF;
|
s->cap |= RISCV_IOMMU_CAP_MSI_FLAT | RISCV_IOMMU_CAP_MSI_MRIF;
|
||||||
}
|
}
|
||||||
|
if (s->enable_ats) {
|
||||||
|
s->cap |= RISCV_IOMMU_CAP_ATS;
|
||||||
|
}
|
||||||
if (s->enable_s_stage) {
|
if (s->enable_s_stage) {
|
||||||
s->cap |= RISCV_IOMMU_CAP_SV32 | RISCV_IOMMU_CAP_SV39 |
|
s->cap |= RISCV_IOMMU_CAP_SV32 | RISCV_IOMMU_CAP_SV39 |
|
||||||
RISCV_IOMMU_CAP_SV48 | RISCV_IOMMU_CAP_SV57;
|
RISCV_IOMMU_CAP_SV48 | RISCV_IOMMU_CAP_SV57;
|
||||||
@ -2044,6 +2166,7 @@ static Property riscv_iommu_properties[] = {
|
|||||||
DEFINE_PROP_UINT32("ioatc-limit", RISCVIOMMUState, iot_limit,
|
DEFINE_PROP_UINT32("ioatc-limit", RISCVIOMMUState, iot_limit,
|
||||||
LIMIT_CACHE_IOT),
|
LIMIT_CACHE_IOT),
|
||||||
DEFINE_PROP_BOOL("intremap", RISCVIOMMUState, enable_msi, TRUE),
|
DEFINE_PROP_BOOL("intremap", RISCVIOMMUState, enable_msi, TRUE),
|
||||||
|
DEFINE_PROP_BOOL("ats", RISCVIOMMUState, enable_ats, TRUE),
|
||||||
DEFINE_PROP_BOOL("off", RISCVIOMMUState, enable_off, TRUE),
|
DEFINE_PROP_BOOL("off", RISCVIOMMUState, enable_off, TRUE),
|
||||||
DEFINE_PROP_BOOL("s-stage", RISCVIOMMUState, enable_s_stage, TRUE),
|
DEFINE_PROP_BOOL("s-stage", RISCVIOMMUState, enable_s_stage, TRUE),
|
||||||
DEFINE_PROP_BOOL("g-stage", RISCVIOMMUState, enable_g_stage, TRUE),
|
DEFINE_PROP_BOOL("g-stage", RISCVIOMMUState, enable_g_stage, TRUE),
|
||||||
|
@ -37,6 +37,7 @@ struct RISCVIOMMUState {
|
|||||||
|
|
||||||
bool enable_off; /* Enable out-of-reset OFF mode (DMA disabled) */
|
bool enable_off; /* Enable out-of-reset OFF mode (DMA disabled) */
|
||||||
bool enable_msi; /* Enable MSI remapping */
|
bool enable_msi; /* Enable MSI remapping */
|
||||||
|
bool enable_ats; /* Enable ATS support */
|
||||||
bool enable_s_stage; /* Enable S/VS-Stage translation */
|
bool enable_s_stage; /* Enable S/VS-Stage translation */
|
||||||
bool enable_g_stage; /* Enable G-Stage translation */
|
bool enable_g_stage; /* Enable G-Stage translation */
|
||||||
|
|
||||||
|
@ -12,3 +12,6 @@ riscv_iommu_notifier_add(const char *id) "%s: dev-iotlb notifier added"
|
|||||||
riscv_iommu_notifier_del(const char *id) "%s: dev-iotlb notifier removed"
|
riscv_iommu_notifier_del(const char *id) "%s: dev-iotlb notifier removed"
|
||||||
riscv_iommu_notify_int_vector(uint32_t cause, uint32_t vector) "Interrupt cause 0x%x sent via vector 0x%x"
|
riscv_iommu_notify_int_vector(uint32_t cause, uint32_t vector) "Interrupt cause 0x%x sent via vector 0x%x"
|
||||||
riscv_iommu_icvec_write(uint32_t orig, uint32_t actual) "ICVEC write: incoming 0x%x actual 0x%x"
|
riscv_iommu_icvec_write(uint32_t orig, uint32_t actual) "ICVEC write: incoming 0x%x actual 0x%x"
|
||||||
|
riscv_iommu_ats(const char *id, unsigned b, unsigned d, unsigned f, uint64_t iova) "%s: translate request %04x:%02x.%u iova: 0x%"PRIx64
|
||||||
|
riscv_iommu_ats_inval(const char *id) "%s: dev-iotlb invalidate"
|
||||||
|
riscv_iommu_ats_prgr(const char *id) "%s: dev-iotlb page request group response"
|
||||||
|
Loading…
Reference in New Issue
Block a user