All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mostafa Saleh <smostafa@google.com>
To: qemu-arm@nongnu.org, eric.auger@redhat.com,
	peter.maydell@linaro.org,  qemu-devel@nongnu.org
Cc: jean-philippe@linaro.org, alex.bennee@linaro.org, maz@kernel.org,
	 nicolinc@nvidia.com, julien@xen.org,
	richard.henderson@linaro.org,  marcin.juszkiewicz@linaro.org,
	Mostafa Saleh <smostafa@google.com>
Subject: [PATCH v4 08/19] hw/arm/smmuv3: Translate CD and TT using stage-2 table
Date: Mon,  1 Jul 2024 11:02:30 +0000	[thread overview]
Message-ID: <20240701110241.2005222-9-smostafa@google.com> (raw)
In-Reply-To: <20240701110241.2005222-1-smostafa@google.com>

According to ARM SMMU architecture specification (ARM IHI 0070 F.b),
In "5.2 Stream Table Entry":
 [51:6] S1ContextPtr
 If Config[1] == 1 (stage 2 enabled), this pointer is an IPA translated by
 stage 2 and the programmed value must be within the range of the IAS.

In "5.4.1 CD notes":
 The translation table walks performed from TTB0 or TTB1 are always performed
 in IPA space if stage 2 translations are enabled.

This patch implements translation of the S1 context descriptor pointer and
TTBx base addresses through the S2 stage (IPA -> PA)

smmuv3_do_translate() is updated to have one arg which is translation
class, this is useful to:
 - Decide wether a translation is stage-2 only or use the STE config.
 - Populate the class in case of faults, WALK_EABT is left unchanged,
   as it is always triggered from TT access so no need to use the
   input class.

In case for stage-2 only translation, used in the context of nested
translation, the stage and asid are saved and restored before and
after calling smmu_translate().

Translating CD or TTBx can fail for the following reasons:
1) Large address size: This is described in
   (3.4.3 Address sizes of SMMU-originated accesses)
   - For CD ptr larger than IAS, for SMMUv3.1, it can trigger either
     C_BAD_STE or Translation fault, we implement the latter as it
     requires no extra code.
   - For TTBx, if larger than the effective stage 1 output address size, it
     triggers C_BAD_CD.

2) Faults from PTWs (7.3 Event records)
   - F_ADDR_SIZE: large address size after first level causes stage 2 Address
     Size fault (Also in 3.4.3 Address sizes of SMMU-originated accesses)
   - F_PERMISSION: Same as an address translation. However, when
     CLASS == CD, the access is implicitly Data and a read.
   - F_ACCESS: Same as an address translation.
   - F_TRANSLATION: Same as an address translation.
   - F_WALK_EABT: Same as an address translation.
  These are already implemented in the PTW logic, so no extra handling
  required.

Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
 hw/arm/smmuv3.c | 91 +++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 80 insertions(+), 11 deletions(-)

diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 229b3c388c..86f95c1e40 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -337,14 +337,35 @@ static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf,
 
 }
 
+static SMMUTranslationStatus smmuv3_do_translate(SMMUv3State *s, hwaddr addr,
+                                                 SMMUTransCfg *cfg,
+                                                 SMMUEventInfo *event,
+                                                 IOMMUAccessFlags flag,
+                                                 SMMUTLBEntry **out_entry,
+                                                 SMMUTranslationClass class);
 /* @ssid > 0 not supported yet */
-static int smmu_get_cd(SMMUv3State *s, STE *ste, uint32_t ssid,
-                       CD *buf, SMMUEventInfo *event)
+static int smmu_get_cd(SMMUv3State *s, STE *ste, SMMUTransCfg *cfg,
+                       uint32_t ssid, CD *buf, SMMUEventInfo *event)
 {
     dma_addr_t addr = STE_CTXPTR(ste);
     int ret, i;
+    SMMUTranslationStatus status;
+    SMMUTLBEntry *entry;
 
     trace_smmuv3_get_cd(addr);
+
+    if (cfg->stage == SMMU_NESTED) {
+        status = smmuv3_do_translate(s, addr, cfg, event,
+                                     IOMMU_RO, &entry, SMMU_CLASS_CD);
+
+        /* Same PTW faults are reported but with CLASS = CD. */
+        if (status != SMMU_TRANS_SUCCESS) {
+            return -EINVAL;
+        }
+
+        addr = CACHED_ENTRY_TO_ADDR(entry, addr);
+    }
+
     /* TODO: guarantee 64-bit single-copy atomicity */
     ret = dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf),
                           MEMTXATTRS_UNSPECIFIED);
@@ -659,10 +680,13 @@ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste,
     return 0;
 }
 
-static int decode_cd(SMMUTransCfg *cfg, CD *cd, SMMUEventInfo *event)
+static int decode_cd(SMMUv3State *s, SMMUTransCfg *cfg,
+                     CD *cd, SMMUEventInfo *event)
 {
     int ret = -EINVAL;
     int i;
+    SMMUTranslationStatus status;
+    SMMUTLBEntry *entry;
 
     if (!CD_VALID(cd) || !CD_AARCH64(cd)) {
         goto bad_cd;
@@ -713,9 +737,26 @@ static int decode_cd(SMMUTransCfg *cfg, CD *cd, SMMUEventInfo *event)
 
         tt->tsz = tsz;
         tt->ttb = CD_TTB(cd, i);
+
         if (tt->ttb & ~(MAKE_64BIT_MASK(0, cfg->oas))) {
             goto bad_cd;
         }
+
+        /* Translate the TTBx, from IPA to PA if nesting is enabled. */
+        if (cfg->stage == SMMU_NESTED) {
+            status = smmuv3_do_translate(s, tt->ttb, cfg, event, IOMMU_RO,
+                                         &entry, SMMU_CLASS_TT);
+            /*
+             * Same PTW faults are reported but with CLASS = TT.
+             * If TTBx is larger than the effective stage 1 output addres
+             * size, it reports C_BAD_CD, which is handled by the above case.
+             */
+            if (status != SMMU_TRANS_SUCCESS) {
+                return -EINVAL;
+            }
+            tt->ttb = CACHED_ENTRY_TO_ADDR(entry, tt->ttb);
+        }
+
         tt->had = CD_HAD(cd, i);
         trace_smmuv3_decode_cd_tt(i, tt->tsz, tt->ttb, tt->granule_sz, tt->had);
     }
@@ -767,12 +808,12 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg,
         return 0;
     }
 
-    ret = smmu_get_cd(s, &ste, 0 /* ssid */, &cd, event);
+    ret = smmu_get_cd(s, &ste, cfg, 0 /* ssid */, &cd, event);
     if (ret) {
         return ret;
     }
 
-    return decode_cd(cfg, &cd, event);
+    return decode_cd(s, cfg, &cd, event);
 }
 
 /**
@@ -832,13 +873,40 @@ static SMMUTranslationStatus smmuv3_do_translate(SMMUv3State *s, hwaddr addr,
                                                  SMMUTransCfg *cfg,
                                                  SMMUEventInfo *event,
                                                  IOMMUAccessFlags flag,
-                                                 SMMUTLBEntry **out_entry)
+                                                 SMMUTLBEntry **out_entry,
+                                                 SMMUTranslationClass class)
 {
     SMMUPTWEventInfo ptw_info = {};
     SMMUState *bs = ARM_SMMU(s);
     SMMUTLBEntry *cached_entry = NULL;
+    int asid, stage;
+    bool S2_only = class != SMMU_CLASS_IN;
+
+    /*
+     * The function uses the argument class to indentify which stage is used:
+     * - CLASS = IN: Means an input translation, determine the stage from STE.
+     * - CLASS = CD: Means the addr is an IPA of the CD, and it would be
+     *   tranlsated using the stage-2.
+     * - CLASS = TT: Means the addr is an IPA of the stage-1 translation table
+     *   and it would be tranlsated using the stage-2.
+     * For the last 2 cases instead of having intrusive changes in the common
+     * logic, we modify the cfg to be a stage-2 translation only in case of
+     * nested, and then restore it after.
+     */
+    if (S2_only) {
+        asid = cfg->asid;
+        stage = cfg->stage;
+        cfg->asid = -1;
+        cfg->stage = SMMU_STAGE_2;
+    }
 
     cached_entry = smmu_translate(bs, cfg, addr, flag, &ptw_info);
+
+    if (S2_only) {
+        cfg->asid = asid;
+        cfg->stage = stage;
+    }
+
     if (!cached_entry) {
         /* All faults from PTW has S2 field. */
         event->u.f_walk_eabt.s2 = (ptw_info.stage == SMMU_STAGE_2);
@@ -855,7 +923,7 @@ static SMMUTranslationStatus smmuv3_do_translate(SMMUv3State *s, hwaddr addr,
                 event->type = SMMU_EVT_F_TRANSLATION;
                 event->u.f_translation.addr = addr;
                 event->u.f_translation.addr2 = ptw_info.addr;
-                event->u.f_translation.class = SMMU_CLASS_IN;
+                event->u.f_translation.class = class;
                 event->u.f_translation.rnw = flag & 0x1;
             }
             break;
@@ -864,7 +932,7 @@ static SMMUTranslationStatus smmuv3_do_translate(SMMUv3State *s, hwaddr addr,
                 event->type = SMMU_EVT_F_ADDR_SIZE;
                 event->u.f_addr_size.addr = addr;
                 event->u.f_addr_size.addr2 = ptw_info.addr;
-                event->u.f_addr_size.class = SMMU_CLASS_IN;
+                event->u.f_addr_size.class = class;
                 event->u.f_addr_size.rnw = flag & 0x1;
             }
             break;
@@ -873,7 +941,7 @@ static SMMUTranslationStatus smmuv3_do_translate(SMMUv3State *s, hwaddr addr,
                 event->type = SMMU_EVT_F_ACCESS;
                 event->u.f_access.addr = addr;
                 event->u.f_access.addr2 = ptw_info.addr;
-                event->u.f_access.class = SMMU_CLASS_IN;
+                event->u.f_access.class = class;
                 event->u.f_access.rnw = flag & 0x1;
             }
             break;
@@ -882,7 +950,7 @@ static SMMUTranslationStatus smmuv3_do_translate(SMMUv3State *s, hwaddr addr,
                 event->type = SMMU_EVT_F_PERMISSION;
                 event->u.f_permission.addr = addr;
                 event->u.f_permission.addr2 = ptw_info.addr;
-                event->u.f_permission.class = SMMU_CLASS_IN;
+                event->u.f_permission.class = class;
                 event->u.f_permission.rnw = flag & 0x1;
             }
             break;
@@ -943,7 +1011,8 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
         goto epilogue;
     }
 
-    status = smmuv3_do_translate(s, addr, cfg, &event, flag, &cached_entry);
+    status = smmuv3_do_translate(s, addr, cfg, &event, flag,
+                                 &cached_entry, SMMU_CLASS_IN);
 
 epilogue:
     qemu_mutex_unlock(&s->mutex);
-- 
2.45.2.803.g4e1b14247a-goog

  parent reply	other threads:[~2024-07-01 11:03 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-01 11:02 [PATCH v4 00/19] SMMUv3 nested translation support Mostafa Saleh
2024-07-01 11:02 ` [PATCH v4 01/19] hw/arm/smmu-common: Add missing size check for stage-1 Mostafa Saleh
2024-07-04 17:55   ` Jean-Philippe Brucker
2024-07-01 11:02 ` [PATCH v4 02/19] hw/arm/smmu: Fix IPA for stage-2 events Mostafa Saleh
2024-07-04 17:56   ` Jean-Philippe Brucker
2024-07-01 11:02 ` [PATCH v4 03/19] hw/arm/smmuv3: Fix encoding of CLASS in events Mostafa Saleh
2024-07-04 18:02   ` Jean-Philippe Brucker
2024-07-09  7:10     ` Mostafa Saleh
2024-07-01 11:02 ` [PATCH v4 04/19] hw/arm/smmu: Use enum for SMMU stage Mostafa Saleh
2024-07-01 11:02 ` [PATCH v4 05/19] hw/arm/smmu: Split smmuv3_translate() Mostafa Saleh
2024-07-01 11:02 ` [PATCH v4 06/19] hw/arm/smmu: Consolidate ASID and VMID types Mostafa Saleh
2024-07-01 11:02 ` [PATCH v4 07/19] hw/arm/smmu: Introduce CACHED_ENTRY_TO_ADDR Mostafa Saleh
2024-07-04 18:04   ` Jean-Philippe Brucker
2024-07-08 13:27     ` Eric Auger
2024-07-01 11:02 ` Mostafa Saleh [this message]
2024-07-04 18:08   ` [PATCH v4 08/19] hw/arm/smmuv3: Translate CD and TT using stage-2 table Jean-Philippe Brucker
2024-07-08 14:54     ` Eric Auger
2024-07-09  7:12     ` Mostafa Saleh
2024-07-09 13:00       ` Jean-Philippe Brucker
2024-07-11 13:03         ` Mostafa Saleh
2024-07-01 11:02 ` [PATCH v4 09/19] hw/arm/smmu-common: Rework TLB lookup for nesting Mostafa Saleh
2024-07-04 18:12   ` Jean-Philippe Brucker
2024-07-09  7:14     ` Mostafa Saleh
2024-07-09 17:13       ` Jean-Philippe Brucker
2024-07-10  8:39         ` Mostafa Saleh
2024-07-01 11:02 ` [PATCH v4 10/19] hw/arm/smmu-common: Add support for nested TLB Mostafa Saleh
2024-07-04 18:13   ` Jean-Philippe Brucker
2024-07-08 15:06   ` Eric Auger
2024-07-01 11:02 ` [PATCH v4 11/19] hw/arm/smmu-common: Support nested translation Mostafa Saleh
2024-07-04 18:31   ` Jean-Philippe Brucker
2024-07-09  7:15     ` Mostafa Saleh
2024-07-08 15:19   ` Eric Auger
2024-07-09  7:18     ` Mostafa Saleh
2024-07-09  7:57       ` Eric Auger
2024-07-01 11:02 ` [PATCH v4 12/19] hw/arm/smmu: Support nesting in smmuv3_range_inval() Mostafa Saleh
2024-07-04 18:32   ` Jean-Philippe Brucker
2024-07-09  7:19     ` Mostafa Saleh
2024-07-01 11:02 ` [PATCH v4 13/19] hw/arm/smmu: Introduce smmu_iotlb_inv_asid_vmid Mostafa Saleh
2024-07-04 18:33   ` Jean-Philippe Brucker
2024-07-08 16:08     ` Eric Auger
2024-07-01 11:02 ` [PATCH v4 14/19] hw/arm/smmu: Support nesting in the rest of commands Mostafa Saleh
2024-07-04 18:34   ` Jean-Philippe Brucker
2024-07-08 16:15   ` Eric Auger
2024-07-01 11:02 ` [PATCH v4 15/19] hw/arm/smmuv3: Support nested SMMUs in smmuv3_notify_iova() Mostafa Saleh
2024-07-04 18:35   ` Jean-Philippe Brucker
2024-07-09  7:20     ` Mostafa Saleh
2024-07-01 11:02 ` [PATCH v4 16/19] hw/arm/smmuv3: Handle translation faults according to SMMUPTWEventInfo Mostafa Saleh
2024-07-04 18:36   ` Jean-Philippe Brucker
2024-07-08 16:30     ` Eric Auger
2024-07-01 11:02 ` [PATCH v4 17/19] hw/arm/smmuv3: Support and advertise nesting Mostafa Saleh
2024-07-04 18:36   ` Jean-Philippe Brucker
2024-07-08 16:51   ` Eric Auger
2024-07-01 11:02 ` [PATCH v4 18/19] hw/arm/smmuv3: Advertise S2FWB Mostafa Saleh
2024-07-04 18:36   ` Jean-Philippe Brucker
2024-07-08 17:09     ` Eric Auger
2024-07-09  7:22       ` Mostafa Saleh
2024-07-09  7:21     ` Mostafa Saleh
2024-07-01 11:02 ` [PATCH v4 19/19] hw/arm/smmu: Refactor SMMU OAS Mostafa Saleh
2024-07-04 18:37   ` Jean-Philippe Brucker
2024-07-08 17:30 ` [PATCH v4 00/19] SMMUv3 nested translation support Eric Auger
2024-07-08 18:13   ` Mostafa Saleh

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=20240701110241.2005222-9-smostafa@google.com \
    --to=smostafa@google.com \
    --cc=alex.bennee@linaro.org \
    --cc=eric.auger@redhat.com \
    --cc=jean-philippe@linaro.org \
    --cc=julien@xen.org \
    --cc=marcin.juszkiewicz@linaro.org \
    --cc=maz@kernel.org \
    --cc=nicolinc@nvidia.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.