From: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
To: Frank Chang <frank.chang@sifive.com>
Cc: qemu-devel@nongnu.org, qemu-riscv@nongnu.org,
alistair.francis@wdc.com, bmeng@tinylab.org, liwei1518@gmail.com,
zhiwei_liu@linux.alibaba.com, palmer@rivosinc.com,
ajones@ventanamicro.com, tjeznach@rivosinc.com
Subject: Re: [PATCH v2 08/15] hw/riscv/riscv-iommu: add Address Translation Cache (IOATC)
Date: Thu, 16 May 2024 18:45:41 -0300 [thread overview]
Message-ID: <78d179f3-fe8d-45dc-b779-3310e47cea2c@ventanamicro.com> (raw)
In-Reply-To: <CANzO1D1hKidUTKeLrWoNsr4oCy_D6m0UEWAPYemFo5MzmJGuLQ@mail.gmail.com>
On 5/8/24 04:26, Frank Chang wrote:
> Hi Daniel,
>
> Daniel Henrique Barboza <dbarboza@ventanamicro.com> 於 2024年3月8日 週五 上午12:05寫道:
>>
>> From: Tomasz Jeznach <tjeznach@rivosinc.com>
>>
>> The RISC-V IOMMU spec predicts that the IOMMU can use translation caches
>> to hold entries from the DDT. This includes implementation for all cache
>> commands that are marked as 'not implemented'.
>>
>> There are some artifacts included in the cache that predicts s-stage and
>> g-stage elements, although we don't support it yet. We'll introduce them
>> next.
>>
>> Signed-off-by: Tomasz Jeznach <tjeznach@rivosinc.com>
>> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
>> ---
>> hw/riscv/riscv-iommu.c | 190 ++++++++++++++++++++++++++++++++++++++++-
>> hw/riscv/riscv-iommu.h | 2 +
>> 2 files changed, 188 insertions(+), 4 deletions(-)
>>
>> diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
>> index df534b99b0..0b93146327 100644
>> --- a/hw/riscv/riscv-iommu.c
>> +++ b/hw/riscv/riscv-iommu.c
>> @@ -63,6 +63,16 @@ struct RISCVIOMMUContext {
>> uint64_t msiptp; /* MSI redirection page table pointer */
>> };
>>
>> +/* Address translation cache entry */
>> +struct RISCVIOMMUEntry {
>> + uint64_t iova:44; /* IOVA Page Number */
>> + uint64_t pscid:20; /* Process Soft-Context identifier */
>> + uint64_t phys:44; /* Physical Page Number */
>> + uint64_t gscid:16; /* Guest Soft-Context identifier */
>> + uint64_t perm:2; /* IOMMU_RW flags */
>> + uint64_t __rfu:2;
>> +};
>> +
>> /* IOMMU index for transactions without PASID specified. */
>> #define RISCV_IOMMU_NOPASID 0
>>
>> @@ -629,14 +639,127 @@ static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, uint32_t devid)
>> return &as->iova_as;
>> }
>>
>> +/* Translation Object cache support */
>> +static gboolean __iot_equal(gconstpointer v1, gconstpointer v2)
>> +{
>> + RISCVIOMMUEntry *t1 = (RISCVIOMMUEntry *) v1;
>> + RISCVIOMMUEntry *t2 = (RISCVIOMMUEntry *) v2;
>> + return t1->gscid == t2->gscid && t1->pscid == t2->pscid &&
>> + t1->iova == t2->iova;
>> +}
>> +
>> +static guint __iot_hash(gconstpointer v)
>> +{
>> + RISCVIOMMUEntry *t = (RISCVIOMMUEntry *) v;
>> + return (guint)t->iova;
>> +}
>> +
>> +/* GV: 1 PSCV: 1 AV: 1 */
>> +static void __iot_inval_pscid_iova(gpointer key, gpointer value, gpointer data)
>> +{
>> + RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
>> + RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
>> + if (iot->gscid == arg->gscid &&
>> + iot->pscid == arg->pscid &&
>> + iot->iova == arg->iova) {
>> + iot->perm = 0;
>
> Maybe using IOMMU_NONE would be clearer?
Agree. I changed all relevant "iot->perm = 0" instances to "iot->perm = IOMMU_NONE".
Thanks,
Daniel
>
> Otherwise,
> Reviewed-by: Frank Chang <frank.chang@sifive.com>
>
>> + }
>> +}
>> +
>> +/* GV: 1 PSCV: 1 AV: 0 */
>> +static void __iot_inval_pscid(gpointer key, gpointer value, gpointer data)
>> +{
>> + RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
>> + RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
>> + if (iot->gscid == arg->gscid &&
>> + iot->pscid == arg->pscid) {
>> + iot->perm = 0;
>> + }
>> +}
>> +
>> +/* GV: 1 GVMA: 1 */
>> +static void __iot_inval_gscid_gpa(gpointer key, gpointer value, gpointer data)
>> +{
>> + RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
>> + RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
>> + if (iot->gscid == arg->gscid) {
>> + /* simplified cache, no GPA matching */
>> + iot->perm = 0;
>> + }
>> +}
>> +
>> +/* GV: 1 GVMA: 0 */
>> +static void __iot_inval_gscid(gpointer key, gpointer value, gpointer data)
>> +{
>> + RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
>> + RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
>> + if (iot->gscid == arg->gscid) {
>> + iot->perm = 0;
>> + }
>> +}
>> +
>> +/* GV: 0 */
>> +static void __iot_inval_all(gpointer key, gpointer value, gpointer data)
>> +{
>> + RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
>> + iot->perm = 0;
>> +}
>> +
>> +/* caller should keep ref-count for iot_cache object */
>> +static RISCVIOMMUEntry *riscv_iommu_iot_lookup(RISCVIOMMUContext *ctx,
>> + GHashTable *iot_cache, hwaddr iova)
>> +{
>> + RISCVIOMMUEntry key = {
>> + .pscid = get_field(ctx->ta, RISCV_IOMMU_DC_TA_PSCID),
>> + .iova = PPN_DOWN(iova),
>> + };
>> + return g_hash_table_lookup(iot_cache, &key);
>> +}
>> +
>> +/* caller should keep ref-count for iot_cache object */
>> +static void riscv_iommu_iot_update(RISCVIOMMUState *s,
>> + GHashTable *iot_cache, RISCVIOMMUEntry *iot)
>> +{
>> + if (!s->iot_limit) {
>> + return;
>> + }
>> +
>> + if (g_hash_table_size(s->iot_cache) >= s->iot_limit) {
>> + iot_cache = g_hash_table_new_full(__iot_hash, __iot_equal,
>> + g_free, NULL);
>> + g_hash_table_unref(qatomic_xchg(&s->iot_cache, iot_cache));
>> + }
>> + g_hash_table_add(iot_cache, iot);
>> +}
>> +
>> +static void riscv_iommu_iot_inval(RISCVIOMMUState *s, GHFunc func,
>> + uint32_t gscid, uint32_t pscid, hwaddr iova)
>> +{
>> + GHashTable *iot_cache;
>> + RISCVIOMMUEntry key = {
>> + .gscid = gscid,
>> + .pscid = pscid,
>> + .iova = PPN_DOWN(iova),
>> + };
>> +
>> + iot_cache = g_hash_table_ref(s->iot_cache);
>> + g_hash_table_foreach(iot_cache, func, &key);
>> + g_hash_table_unref(iot_cache);
>> +}
>> +
>> static int riscv_iommu_translate(RISCVIOMMUState *s, RISCVIOMMUContext *ctx,
>> - IOMMUTLBEntry *iotlb)
>> + IOMMUTLBEntry *iotlb, bool enable_cache)
>> {
>> + RISCVIOMMUEntry *iot;
>> + IOMMUAccessFlags perm;
>> bool enable_faults;
>> bool enable_pasid;
>> bool enable_pri;
>> + GHashTable *iot_cache;
>> int fault;
>>
>> + iot_cache = g_hash_table_ref(s->iot_cache);
>> +
>> enable_faults = !(ctx->tc & RISCV_IOMMU_DC_TC_DTF);
>> /*
>> * TC[32] is reserved for custom extensions, used here to temporarily
>> @@ -645,9 +768,36 @@ static int riscv_iommu_translate(RISCVIOMMUState *s, RISCVIOMMUContext *ctx,
>> enable_pri = (iotlb->perm == IOMMU_NONE) && (ctx->tc & BIT_ULL(32));
>> enable_pasid = (ctx->tc & RISCV_IOMMU_DC_TC_PDTV);
>>
>> + iot = riscv_iommu_iot_lookup(ctx, iot_cache, iotlb->iova);
>> + perm = iot ? iot->perm : IOMMU_NONE;
>> + if (perm != IOMMU_NONE) {
>> + iotlb->translated_addr = PPN_PHYS(iot->phys);
>> + iotlb->addr_mask = ~TARGET_PAGE_MASK;
>> + iotlb->perm = perm;
>> + fault = 0;
>> + goto done;
>> + }
>> +
>> /* Translate using device directory / page table information. */
>> fault = riscv_iommu_spa_fetch(s, ctx, iotlb);
>>
>> + if (!fault && iotlb->target_as == &s->trap_as) {
>> + /* Do not cache trapped MSI translations */
>> + goto done;
>> + }
>> +
>> + if (!fault && iotlb->translated_addr != iotlb->iova && enable_cache) {
>> + iot = g_new0(RISCVIOMMUEntry, 1);
>> + iot->iova = PPN_DOWN(iotlb->iova);
>> + iot->phys = PPN_DOWN(iotlb->translated_addr);
>> + iot->pscid = get_field(ctx->ta, RISCV_IOMMU_DC_TA_PSCID);
>> + iot->perm = iotlb->perm;
>> + riscv_iommu_iot_update(s, iot_cache, iot);
>> + }
>> +
>> +done:
>> + g_hash_table_unref(iot_cache);
>> +
>> if (enable_pri && fault) {
>> struct riscv_iommu_pq_record pr = {0};
>> if (enable_pasid) {
>> @@ -794,13 +944,40 @@ static void riscv_iommu_process_cq_tail(RISCVIOMMUState *s)
>> if (cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_PSCV) {
>> /* illegal command arguments IOTINVAL.GVMA & PSCV == 1 */
>> goto cmd_ill;
>> + } else if (!(cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_GV)) {
>> + /* invalidate all cache mappings */
>> + func = __iot_inval_all;
>> + } else if (!(cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_AV)) {
>> + /* invalidate cache matching GSCID */
>> + func = __iot_inval_gscid;
>> + } else {
>> + /* invalidate cache matching GSCID and ADDR (GPA) */
>> + func = __iot_inval_gscid_gpa;
>> }
>> - /* translation cache not implemented yet */
>> + riscv_iommu_iot_inval(s, func,
>> + get_field(cmd.dword0, RISCV_IOMMU_CMD_IOTINVAL_GSCID), 0,
>> + cmd.dword1 & TARGET_PAGE_MASK);
>> break;
>>
>> case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_IOTINVAL_FUNC_VMA,
>> RISCV_IOMMU_CMD_IOTINVAL_OPCODE):
>> - /* translation cache not implemented yet */
>> + if (!(cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_GV)) {
>> + /* invalidate all cache mappings, simplified model */
>> + func = __iot_inval_all;
>> + } else if (!(cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_PSCV)) {
>> + /* invalidate cache matching GSCID, simplified model */
>> + func = __iot_inval_gscid;
>> + } else if (!(cmd.dword0 & RISCV_IOMMU_CMD_IOTINVAL_AV)) {
>> + /* invalidate cache matching GSCID and PSCID */
>> + func = __iot_inval_pscid;
>> + } else {
>> + /* invalidate cache matching GSCID and PSCID and ADDR (IOVA) */
>> + func = __iot_inval_pscid_iova;
>> + }
>> + riscv_iommu_iot_inval(s, func,
>> + get_field(cmd.dword0, RISCV_IOMMU_CMD_IOTINVAL_GSCID),
>> + get_field(cmd.dword0, RISCV_IOMMU_CMD_IOTINVAL_PSCID),
>> + cmd.dword1 & TARGET_PAGE_MASK);
>> break;
>>
>> case RISCV_IOMMU_CMD(RISCV_IOMMU_CMD_IODIR_FUNC_INVAL_DDT,
>> @@ -1290,6 +1467,8 @@ static void riscv_iommu_realize(DeviceState *dev, Error **errp)
>> /* Device translation context cache */
>> s->ctx_cache = g_hash_table_new_full(__ctx_hash, __ctx_equal,
>> g_free, NULL);
>> + s->iot_cache = g_hash_table_new_full(__iot_hash, __iot_equal,
>> + g_free, NULL);
>>
>> s->iommus.le_next = NULL;
>> s->iommus.le_prev = NULL;
>> @@ -1313,6 +1492,7 @@ static void riscv_iommu_unrealize(DeviceState *dev)
>> qemu_thread_join(&s->core_proc);
>> qemu_cond_destroy(&s->core_cond);
>> qemu_mutex_destroy(&s->core_lock);
>> + g_hash_table_unref(s->iot_cache);
>> g_hash_table_unref(s->ctx_cache);
>> }
>>
>> @@ -1320,6 +1500,8 @@ static Property riscv_iommu_properties[] = {
>> DEFINE_PROP_UINT32("version", RISCVIOMMUState, version,
>> RISCV_IOMMU_SPEC_DOT_VER),
>> DEFINE_PROP_UINT32("bus", RISCVIOMMUState, bus, 0x0),
>> + DEFINE_PROP_UINT32("ioatc-limit", RISCVIOMMUState, iot_limit,
>> + LIMIT_CACHE_IOT),
>> DEFINE_PROP_BOOL("intremap", RISCVIOMMUState, enable_msi, TRUE),
>> DEFINE_PROP_BOOL("off", RISCVIOMMUState, enable_off, TRUE),
>> DEFINE_PROP_LINK("downstream-mr", RISCVIOMMUState, target_mr,
>> @@ -1372,7 +1554,7 @@ static IOMMUTLBEntry riscv_iommu_memory_region_translate(
>> /* Translation disabled or invalid. */
>> iotlb.addr_mask = 0;
>> iotlb.perm = IOMMU_NONE;
>> - } else if (riscv_iommu_translate(as->iommu, ctx, &iotlb)) {
>> + } else if (riscv_iommu_translate(as->iommu, ctx, &iotlb, true)) {
>> /* Translation disabled or fault reported. */
>> iotlb.addr_mask = 0;
>> iotlb.perm = IOMMU_NONE;
>> diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h
>> index 6f740de690..eea2123686 100644
>> --- a/hw/riscv/riscv-iommu.h
>> +++ b/hw/riscv/riscv-iommu.h
>> @@ -68,6 +68,8 @@ struct RISCVIOMMUState {
>> MemoryRegion trap_mr;
>>
>> GHashTable *ctx_cache; /* Device translation Context Cache */
>> + GHashTable *iot_cache; /* IO Translated Address Cache */
>> + unsigned iot_limit; /* IO Translation Cache size limit */
>>
>> /* MMIO Hardware Interface */
>> MemoryRegion regs_mr;
>> --
>> 2.43.2
>>
>>
next prev parent reply other threads:[~2024-05-16 21:46 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-07 16:03 [PATCH v2 00/15] riscv: QEMU RISC-V IOMMU Support Daniel Henrique Barboza
2024-03-07 16:03 ` [PATCH v2 01/15] exec/memtxattr: add process identifier to the transaction attributes Daniel Henrique Barboza
2024-04-23 16:33 ` Frank Chang
2024-03-07 16:03 ` [PATCH v2 02/15] hw/riscv: add riscv-iommu-bits.h Daniel Henrique Barboza
2024-05-10 11:01 ` Frank Chang
2024-05-15 10:02 ` Eric Cheng
2024-05-15 14:28 ` Daniel Henrique Barboza
2024-03-07 16:03 ` [PATCH v2 03/15] hw/riscv: add RISC-V IOMMU base emulation Daniel Henrique Barboza
2024-05-01 11:57 ` Jason Chien
2024-05-14 20:06 ` Daniel Henrique Barboza
2024-05-02 11:37 ` Frank Chang
2024-05-08 11:15 ` Daniel Henrique Barboza
2024-05-10 10:58 ` Frank Chang
2024-05-13 12:41 ` Daniel Henrique Barboza
2024-05-13 12:37 ` Daniel Henrique Barboza
2024-05-16 7:13 ` Frank Chang
2024-05-20 16:17 ` Daniel Henrique Barboza
2024-05-21 10:52 ` Frank Chang
2024-05-21 12:28 ` Daniel Henrique Barboza
2024-03-07 16:03 ` [PATCH v2 04/15] hw/riscv: add riscv-iommu-pci device Daniel Henrique Barboza
2024-04-29 7:21 ` Frank Chang
2024-05-02 9:37 ` Daniel Henrique Barboza
2024-03-07 16:03 ` [PATCH v2 05/15] hw/riscv: add riscv-iommu-sys platform device Daniel Henrique Barboza
2024-04-30 1:35 ` Frank Chang
2024-03-07 16:03 ` [PATCH v2 06/15] hw/riscv/virt.c: support for RISC-V IOMMU PCIDevice hotplug Daniel Henrique Barboza
2024-04-30 2:17 ` Frank Chang
2024-05-15 6:25 ` Eric Cheng
2024-05-15 7:16 ` Andrew Jones
2024-03-07 16:03 ` [PATCH v2 07/15] test/qtest: add riscv-iommu-pci tests Daniel Henrique Barboza
2024-04-30 3:33 ` Frank Chang
2024-03-07 16:03 ` [PATCH v2 08/15] hw/riscv/riscv-iommu: add Address Translation Cache (IOATC) Daniel Henrique Barboza
2024-05-08 7:26 ` Frank Chang
2024-05-16 21:45 ` Daniel Henrique Barboza [this message]
2024-03-07 16:03 ` [PATCH v2 09/15] hw/riscv/riscv-iommu: add s-stage and g-stage support Daniel Henrique Barboza
2024-05-10 10:36 ` Frank Chang
2024-05-10 11:14 ` Andrew Jones
2024-05-16 19:41 ` Daniel Henrique Barboza
2024-03-07 16:03 ` [PATCH v2 10/15] hw/riscv/riscv-iommu: add ATS support Daniel Henrique Barboza
2024-05-08 2:57 ` Frank Chang
2024-05-17 9:29 ` Daniel Henrique Barboza
2024-03-07 16:03 ` [PATCH v2 11/15] hw/riscv/riscv-iommu: add DBG support Daniel Henrique Barboza
2024-05-06 4:09 ` Frank Chang
2024-05-06 13:05 ` Daniel Henrique Barboza
2024-05-10 10:59 ` Frank Chang
2024-03-07 16:03 ` [PATCH v2 12/15] hw/riscv/riscv-iommu: Add another irq for mrif notifications Daniel Henrique Barboza
2024-05-06 6:12 ` Frank Chang
2024-03-07 16:03 ` [PATCH v2 13/15] qtest/riscv-iommu-test: add init queues test Daniel Henrique Barboza
2024-05-07 8:01 ` Frank Chang
2024-03-07 16:03 ` [PATCH v2 14/15] hw/misc: EDU: added PASID support Daniel Henrique Barboza
2024-05-07 9:06 ` Frank Chang
2024-03-07 16:03 ` [PATCH v2 15/15] hw/misc: EDU: add ATS/PRI capability Daniel Henrique Barboza
2024-05-07 15:32 ` Frank Chang
2024-05-16 13:59 ` Daniel Henrique Barboza
2024-05-10 11:14 ` [PATCH v2 00/15] riscv: QEMU RISC-V IOMMU Support Frank Chang
2024-05-20 16:26 ` Daniel Henrique Barboza
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=78d179f3-fe8d-45dc-b779-3310e47cea2c@ventanamicro.com \
--to=dbarboza@ventanamicro.com \
--cc=ajones@ventanamicro.com \
--cc=alistair.francis@wdc.com \
--cc=bmeng@tinylab.org \
--cc=frank.chang@sifive.com \
--cc=liwei1518@gmail.com \
--cc=palmer@rivosinc.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-riscv@nongnu.org \
--cc=tjeznach@rivosinc.com \
--cc=zhiwei_liu@linux.alibaba.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).