From: Eric Auger <eric.auger@redhat.com>
To: eric.auger.pro@gmail.com, eric.auger@redhat.com,
qemu-devel@nongnu.org, qemu-arm@nongnu.org,
peter.maydell@linaro.org, peterx@redhat.com
Cc: jean-philippe@linaro.org, robh@kernel.org, robin.murphy@arm.com,
mst@redhat.com, zhangfei.gao@foxmail.com,
shameerali.kolothum.thodi@huawei.com, will@kernel.org
Subject: [PATCH for-5.2 v4 07/11] hw/arm/smmuv3: Get prepared for range invalidation
Date: Tue, 28 Jul 2020 17:08:11 +0200 [thread overview]
Message-ID: <20200728150815.11446-8-eric.auger@redhat.com> (raw)
In-Reply-To: <20200728150815.11446-1-eric.auger@redhat.com>
Enhance the smmu_iotlb_inv_iova() helper with range invalidation.
This uses the new fields passed in the NH_VA and NH_VAA commands:
the size of the range, the level and the granule.
As NH_VA and NH_VAA both use those fields, their decoding and
handling is factorized in a new smmuv3_s1_range_inval() helper.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
v3 -> v4:
- Fixed over identation
- added Peter's R-b
---
hw/arm/smmuv3-internal.h | 4 +++
include/hw/arm/smmu-common.h | 3 +-
hw/arm/smmu-common.c | 25 +++++++++++---
hw/arm/smmuv3.c | 64 +++++++++++++++++++++++-------------
hw/arm/trace-events | 4 +--
5 files changed, 69 insertions(+), 31 deletions(-)
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
index 4112394129..5babf72f7d 100644
--- a/hw/arm/smmuv3-internal.h
+++ b/hw/arm/smmuv3-internal.h
@@ -298,6 +298,8 @@ enum { /* Command completion notification */
};
#define CMD_TYPE(x) extract32((x)->word[0], 0 , 8)
+#define CMD_NUM(x) extract32((x)->word[0], 12 , 5)
+#define CMD_SCALE(x) extract32((x)->word[0], 20 , 5)
#define CMD_SSEC(x) extract32((x)->word[0], 10, 1)
#define CMD_SSV(x) extract32((x)->word[0], 11, 1)
#define CMD_RESUME_AC(x) extract32((x)->word[0], 12, 1)
@@ -310,6 +312,8 @@ enum { /* Command completion notification */
#define CMD_RESUME_STAG(x) extract32((x)->word[2], 0 , 16)
#define CMD_RESP(x) extract32((x)->word[2], 11, 2)
#define CMD_LEAF(x) extract32((x)->word[2], 0 , 1)
+#define CMD_TTL(x) extract32((x)->word[2], 8 , 2)
+#define CMD_TG(x) extract32((x)->word[2], 10, 2)
#define CMD_STE_RANGE(x) extract32((x)->word[2], 0 , 5)
#define CMD_ADDR(x) ({ \
uint64_t high = (uint64_t)(x)->word[3]; \
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
index ece62c3652..4f6acf634c 100644
--- a/include/hw/arm/smmu-common.h
+++ b/include/hw/arm/smmu-common.h
@@ -168,7 +168,8 @@ SMMUIOTLBKey smmu_get_iotlb_key(uint16_t asid, uint64_t iova,
uint8_t tg, uint8_t level);
void smmu_iotlb_inv_all(SMMUState *s);
void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid);
-void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova);
+void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
+ uint8_t tg, uint64_t num_pages, uint8_t ttl);
/* Unmap the range of all the notifiers registered to any IOMMU mr */
void smmu_inv_notifiers_all(SMMUState *s);
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index 2922deec6f..8d89a86699 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -143,15 +143,30 @@ static gboolean smmu_hash_remove_by_asid_iova(gpointer key, gpointer value,
if (info->asid >= 0 && info->asid != SMMU_IOTLB_ASID(iotlb_key)) {
return false;
}
- return (info->iova & ~entry->addr_mask) == entry->iova;
+ return ((info->iova & ~entry->addr_mask) == entry->iova) ||
+ ((entry->iova & ~info->mask) == info->iova);
}
-inline void smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova)
+inline void
+smmu_iotlb_inv_iova(SMMUState *s, int asid, dma_addr_t iova,
+ uint8_t tg, uint64_t num_pages, uint8_t ttl)
{
- SMMUIOTLBPageInvInfo info = {.asid = asid, .iova = iova};
+ if (ttl && (num_pages == 1)) {
+ SMMUIOTLBKey key = smmu_get_iotlb_key(asid, iova, tg, ttl);
- trace_smmu_iotlb_inv_iova(asid, iova);
- g_hash_table_foreach_remove(s->iotlb, smmu_hash_remove_by_asid_iova, &info);
+ g_hash_table_remove(s->iotlb, &key);
+ } else {
+ /* if tg is not set we use 4KB range invalidation */
+ uint8_t granule = tg ? tg * 2 + 10 : 12;
+
+ SMMUIOTLBPageInvInfo info = {
+ .asid = asid, .iova = iova,
+ .mask = (num_pages * 1 << granule) - 1};
+
+ g_hash_table_foreach_remove(s->iotlb,
+ smmu_hash_remove_by_asid_iova,
+ &info);
+ }
}
inline void smmu_iotlb_inv_asid(SMMUState *s, uint16_t asid)
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index e4a2cea7ad..89ab11fc36 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -785,42 +785,49 @@ epilogue:
* @n: notifier to be called
* @asid: address space ID or negative value if we don't care
* @iova: iova
+ * @tg: translation granule (if communicated through range invalidation)
+ * @num_pages: number of @granule sized pages (if tg != 0), otherwise 1
*/
static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
IOMMUNotifier *n,
- int asid,
- dma_addr_t iova)
+ int asid, dma_addr_t iova,
+ uint8_t tg, uint64_t num_pages)
{
SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
- SMMUEventInfo event = {.inval_ste_allowed = true};
- SMMUTransTableInfo *tt;
- SMMUTransCfg *cfg;
IOMMUTLBEntry entry;
+ uint8_t granule = tg;
- cfg = smmuv3_get_config(sdev, &event);
- if (!cfg) {
- return;
- }
+ if (!tg) {
+ SMMUEventInfo event = {.inval_ste_allowed = true};
+ SMMUTransCfg *cfg = smmuv3_get_config(sdev, &event);
+ SMMUTransTableInfo *tt;
- if (asid >= 0 && cfg->asid != asid) {
- return;
- }
+ if (!cfg) {
+ return;
+ }
- tt = select_tt(cfg, iova);
- if (!tt) {
- return;
+ if (asid >= 0 && cfg->asid != asid) {
+ return;
+ }
+
+ tt = select_tt(cfg, iova);
+ if (!tt) {
+ return;
+ }
+ granule = tt->granule_sz;
}
entry.target_as = &address_space_memory;
entry.iova = iova;
- entry.addr_mask = (1 << tt->granule_sz) - 1;
+ entry.addr_mask = num_pages * (1 << granule) - 1;
entry.perm = IOMMU_NONE;
memory_region_notify_one(n, &entry);
}
-/* invalidate an asid/iova tuple in all mr's */
-static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
+/* invalidate an asid/iova range tuple in all mr's */
+static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova,
+ uint8_t tg, uint64_t num_pages)
{
SMMUDevice *sdev;
@@ -828,28 +835,39 @@ static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
IOMMUMemoryRegion *mr = &sdev->iommu;
IOMMUNotifier *n;
- trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova);
+ trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova,
+ tg, num_pages);
IOMMU_NOTIFIER_FOREACH(n, mr) {
- smmuv3_notify_iova(mr, n, asid, iova);
+ smmuv3_notify_iova(mr, n, asid, iova, tg, num_pages);
}
}
}
static void smmuv3_s1_range_inval(SMMUState *s, Cmd *cmd)
{
+ uint8_t scale = 0, num = 0, ttl = 0;
dma_addr_t addr = CMD_ADDR(cmd);
uint8_t type = CMD_TYPE(cmd);
uint16_t vmid = CMD_VMID(cmd);
bool leaf = CMD_LEAF(cmd);
+ uint8_t tg = CMD_TG(cmd);
+ hwaddr num_pages = 1;
int asid = -1;
+ if (tg) {
+ scale = CMD_SCALE(cmd);
+ num = CMD_NUM(cmd);
+ ttl = CMD_TTL(cmd);
+ num_pages = (num + 1) * (1 << (scale));
+ }
+
if (type == SMMU_CMD_TLBI_NH_VA) {
asid = CMD_ASID(cmd);
}
- trace_smmuv3_s1_range_inval(vmid, asid, addr, leaf);
- smmuv3_inv_notifiers_iova(s, asid, addr);
- smmu_iotlb_inv_iova(s, asid, addr);
+ trace_smmuv3_s1_range_inval(vmid, asid, addr, tg, num_pages, ttl, leaf);
+ smmuv3_inv_notifiers_iova(s, asid, addr, tg, num_pages);
+ smmu_iotlb_inv_iova(s, asid, addr, tg, num_pages, ttl);
}
static int smmuv3_cmdq_consume(SMMUv3State *s)
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
index c219fe9e82..3d905e0f7d 100644
--- a/hw/arm/trace-events
+++ b/hw/arm/trace-events
@@ -45,11 +45,11 @@ smmuv3_cmdq_cfgi_ste_range(int start, int end) "start=0x%d - end=0x%d"
smmuv3_cmdq_cfgi_cd(uint32_t sid) "streamid = %d"
smmuv3_config_cache_hit(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache HIT for sid %d (hits=%d, misses=%d, hit rate=%d)"
smmuv3_config_cache_miss(uint32_t sid, uint32_t hits, uint32_t misses, uint32_t perc) "Config cache MISS for sid %d (hits=%d, misses=%d, hit rate=%d)"
-smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" leaf=%d"
+smmuv3_s1_range_inval(int vmid, int asid, uint64_t addr, uint8_t tg, uint64_t num_pages, uint8_t ttl, bool leaf) "vmid =%d asid =%d addr=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" ttl=%d leaf=%d"
smmuv3_cmdq_tlbi_nh(void) ""
smmuv3_cmdq_tlbi_nh_asid(uint16_t asid) "asid=%d"
smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid %d"
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
-smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova) "iommu mr=%s asid=%d iova=0x%"PRIx64
+smmuv3_inv_notifiers_iova(const char *name, uint16_t asid, uint64_t iova, uint8_t tg, uint64_t num_pages) "iommu mr=%s asid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64
--
2.21.3
next prev parent reply other threads:[~2020-07-28 15:14 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-28 15:08 [PATCH for-5.2 v4 00/11] SMMUv3.2 Range-based TLB Invalidation Support Eric Auger
2020-07-28 15:08 ` [PATCH for-5.2 v4 01/11] hw/arm/smmu-common: Factorize some code in smmu_ptw_64() Eric Auger
2020-07-28 15:08 ` [PATCH for-5.2 v4 02/11] hw/arm/smmu-common: Add IOTLB helpers Eric Auger
2020-07-28 15:08 ` [PATCH for-5.2 v4 03/11] hw/arm/smmu: Introduce smmu_get_iotlb_key() Eric Auger
2020-07-28 15:08 ` [PATCH for-5.2 v4 04/11] hw/arm/smmu: Introduce SMMUTLBEntry for PTW and IOTLB value Eric Auger
2020-07-28 15:08 ` [PATCH for-5.2 v4 05/11] hw/arm/smmu-common: Manage IOTLB block entries Eric Auger
2020-07-30 13:38 ` Peter Maydell
2020-07-31 9:35 ` Auger Eric
2020-07-28 15:08 ` [PATCH for-5.2 v4 06/11] hw/arm/smmuv3: Introduce smmuv3_s1_range_inval() helper Eric Auger
2020-07-28 15:08 ` Eric Auger [this message]
2020-07-28 15:08 ` [PATCH for-5.2 v4 08/11] hw/arm/smmuv3: Fix IIDR offset Eric Auger
2020-07-28 15:08 ` [PATCH for-5.2 v4 09/11] hw/arm/smmuv3: Let AIDR advertise SMMUv3.0 support Eric Auger
2020-07-28 15:08 ` [PATCH for-5.2 v4 10/11] hw/arm/smmuv3: Support HAD and advertise SMMUv3.1 support Eric Auger
2020-07-28 15:08 ` [PATCH for-5.2 v4 11/11] hw/arm/smmuv3: Advertise SMMUv3.2 range invalidation Eric Auger
2020-07-30 13:39 ` [PATCH for-5.2 v4 00/11] SMMUv3.2 Range-based TLB Invalidation Support Peter Maydell
2020-08-06 12:55 ` Peter Maydell
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=20200728150815.11446-8-eric.auger@redhat.com \
--to=eric.auger@redhat.com \
--cc=eric.auger.pro@gmail.com \
--cc=jean-philippe@linaro.org \
--cc=mst@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=peterx@redhat.com \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=robh@kernel.org \
--cc=robin.murphy@arm.com \
--cc=shameerali.kolothum.thodi@huawei.com \
--cc=will@kernel.org \
--cc=zhangfei.gao@foxmail.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 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.