2020-07-07 00:06:46

by Jacob Pan

[permalink] [raw]
Subject: [PATCH v4 0/7] iommu/vt-d: Misc tweaks and fixes for vSVA

Hi Baolu and all,

This is a series to address some of the issues we found in vSVA support.
Most of the patches deal with exception handling, we also removed some bits
that are not currently supported.

Many thanks to Kevin Tian's review.

Jacob & Yi


Changelog:
v4 Address reviews from Eric Auger
- Additional warning for unaligned mask and address in guest IOTLB
invalidation
- Comments rewrite and code simplification
v3
- Use pr_err instead of WARN() for invalid user address range (6/7)
- Fix logic in PASID selective devTLB flush (3/7)

v2 Address reviews from Baolu
- Fixed addr field in devTLB flush (5/7)
- Assign address for single page devTLB invalidation (4/7)
- Coding style tweaks


Jacob Pan (4):
iommu/vt-d: Remove global page support in devTLB flush
iommu/vt-d: Fix PASID devTLB invalidation
iommu/vt-d: Warn on out-of-range invalidation address
iommu/vt-d: Disable multiple GPASID-dev bind

Liu Yi L (3):
iommu/vt-d: Enforce PASID devTLB field mask
iommu/vt-d: Handle non-page aligned address
iommu/vt-d: Fix devTLB flush for vSVA

drivers/iommu/intel/dmar.c | 24 +++++++++++++++++++-----
drivers/iommu/intel/iommu.c | 39 ++++++++++++++++++++++++---------------
drivers/iommu/intel/pasid.c | 11 ++++++++++-
drivers/iommu/intel/svm.c | 22 +++++++++-------------
include/linux/intel-iommu.h | 5 ++---
5 files changed, 64 insertions(+), 37 deletions(-)

--
2.7.4


2020-07-07 00:06:50

by Jacob Pan

[permalink] [raw]
Subject: [PATCH v4 4/7] iommu/vt-d: Handle non-page aligned address

From: Liu Yi L <[email protected]>

Address information for device TLB invalidation comes from userspace
when device is directly assigned to a guest with vIOMMU support.
VT-d requires page aligned address. This patch checks and enforce
address to be page aligned, otherwise reserved bits can be set in the
invalidation descriptor. Unrecoverable fault will be reported due to
non-zero value in the reserved bits.

Fixes: 61a06a16e36d8 ("iommu/vt-d: Support flushing more translation
cache types")
Acked-by: Lu Baolu <[email protected]>
Signed-off-by: Liu Yi L <[email protected]>
Signed-off-by: Jacob Pan <[email protected]>

---
drivers/iommu/intel/dmar.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index d9f973fa1190..b2c53bada905 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -1455,9 +1455,25 @@ void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
* Max Invs Pending (MIP) is set to 0 for now until we have DIT in
* ECAP.
*/
- desc.qw1 |= addr & ~mask;
- if (size_order)
+ if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
+ pr_warn_ratelimited("Invalidate non-aligned address %llx, order %d\n", addr, size_order);
+
+ /* Take page address */
+ desc.qw1 = QI_DEV_EIOTLB_ADDR(addr);
+
+ if (size_order) {
+ /*
+ * Existing 0s in address below size_order may be the least
+ * significant bit, we must set them to 1s to avoid having
+ * smaller size than desired.
+ */
+ desc.qw1 |= GENMASK_ULL(size_order + VTD_PAGE_SHIFT,
+ VTD_PAGE_SHIFT);
+ /* Clear size_order bit to indicate size */
+ desc.qw1 &= ~mask;
+ /* Set the S bit to indicate flushing more than 1 page */
desc.qw1 |= QI_DEV_EIOTLB_SIZE;
+ }

qi_submit_sync(iommu, &desc, 1, 0);
}
--
2.7.4

2020-07-07 00:06:55

by Jacob Pan

[permalink] [raw]
Subject: [PATCH v4 2/7] iommu/vt-d: Remove global page support in devTLB flush

Global pages support is removed from VT-d spec 3.0 for dev TLB
invalidation. This patch is to remove the bits for vSVA. Similar change
already made for the native SVA. See the link below.

Link: https://lkml.org/lkml/2019/8/26/651
Acked-by: Lu Baolu <[email protected]>
Reviewed-by: Eric Auger <[email protected]>
Signed-off-by: Jacob Pan <[email protected]>
---
drivers/iommu/intel/dmar.c | 4 +---
drivers/iommu/intel/iommu.c | 4 ++--
include/linux/intel-iommu.h | 3 +--
3 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index cc46dff98fa0..d9f973fa1190 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -1437,8 +1437,7 @@ void qi_flush_piotlb(struct intel_iommu *iommu, u16 did, u32 pasid, u64 addr,

/* PASID-based device IOTLB Invalidate */
void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
- u32 pasid, u16 qdep, u64 addr,
- unsigned int size_order, u64 granu)
+ u32 pasid, u16 qdep, u64 addr, unsigned int size_order)
{
unsigned long mask = 1UL << (VTD_PAGE_SHIFT + size_order - 1);
struct qi_desc desc = {.qw1 = 0, .qw2 = 0, .qw3 = 0};
@@ -1446,7 +1445,6 @@ void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
desc.qw0 = QI_DEV_EIOTLB_PASID(pasid) | QI_DEV_EIOTLB_SID(sid) |
QI_DEV_EIOTLB_QDEP(qdep) | QI_DEIOTLB_TYPE |
QI_DEV_IOTLB_PFSID(pfsid);
- desc.qw1 = QI_DEV_EIOTLB_GLOB(granu);

/*
* If S bit is 0, we only flush a single page. If S bit is set,
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 9129663a7406..96340da57075 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -5466,7 +5466,7 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev,
info->pfsid, pasid,
info->ats_qdep,
inv_info->addr_info.addr,
- size, granu);
+ size);
break;
case IOMMU_CACHE_INV_TYPE_DEV_IOTLB:
if (info->ats_enabled)
@@ -5474,7 +5474,7 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev,
info->pfsid, pasid,
info->ats_qdep,
inv_info->addr_info.addr,
- size, granu);
+ size);
else
pr_warn_ratelimited("Passdown device IOTLB flush w/o ATS!\n");
break;
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 729386ca8122..9a6614880773 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -380,7 +380,6 @@ enum {

#define QI_DEV_EIOTLB_ADDR(a) ((u64)(a) & VTD_PAGE_MASK)
#define QI_DEV_EIOTLB_SIZE (((u64)1) << 11)
-#define QI_DEV_EIOTLB_GLOB(g) ((u64)(g) & 0x1)
#define QI_DEV_EIOTLB_PASID(p) ((u64)((p) & 0xfffff) << 32)
#define QI_DEV_EIOTLB_SID(sid) ((u64)((sid) & 0xffff) << 16)
#define QI_DEV_EIOTLB_QDEP(qd) ((u64)((qd) & 0x1f) << 4)
@@ -704,7 +703,7 @@ void qi_flush_piotlb(struct intel_iommu *iommu, u16 did, u32 pasid, u64 addr,

void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
u32 pasid, u16 qdep, u64 addr,
- unsigned int size_order, u64 granu);
+ unsigned int size_order);
void qi_flush_pasid_cache(struct intel_iommu *iommu, u16 did, u64 granu,
int pasid);

--
2.7.4

2020-07-07 00:07:00

by Jacob Pan

[permalink] [raw]
Subject: [PATCH v4 7/7] iommu/vt-d: Disable multiple GPASID-dev bind

For the unlikely use case where multiple aux domains from the same pdev
are attached to a single guest and then bound to a single process
(thus same PASID) within that guest, we cannot easily support this case
by refcounting the number of users. As there is only one SL page table
per PASID while we have multiple aux domains thus multiple SL page tables
for the same PASID.

Extra unbinding guest PASID can happen due to race between normal and
exception cases. Termination of one aux domain may affect others unless
we actively track and switch aux domains to ensure the validity of SL
page tables and TLB states in the shared PASID entry.

Support for sharing second level PGDs across domains can reduce the
complexity but this is not available due to the limitations on VFIO
container architecture. We can revisit this decision once sharing PGDs
are available.

Overall, the complexity and potential glitch do not warrant this unlikely
use case thereby removed by this patch.

Fixes: 56722a4398a30 ("iommu/vt-d: Add bind guest PASID support")
Acked-by: Lu Baolu <[email protected]>
Cc: Kevin Tian <[email protected]>
Cc: Lu Baolu <[email protected]>
Reviewed-by: Eric Auger <[email protected]>
Signed-off-by: Liu Yi L <[email protected]>
Signed-off-by: Jacob Pan <[email protected]>
---
drivers/iommu/intel/svm.c | 22 +++++++++-------------
1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 6c87c807a0ab..d386853121a2 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -277,20 +277,16 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, struct device *dev,
goto out;
}

+ /*
+ * Do not allow multiple bindings of the same device-PASID since
+ * there is only one SL page tables per PASID. We may revisit
+ * once sharing PGD across domains are supported.
+ */
for_each_svm_dev(sdev, svm, dev) {
- /*
- * For devices with aux domains, we should allow
- * multiple bind calls with the same PASID and pdev.
- */
- if (iommu_dev_feature_enabled(dev,
- IOMMU_DEV_FEAT_AUX)) {
- sdev->users++;
- } else {
- dev_warn_ratelimited(dev,
- "Already bound with PASID %u\n",
- svm->pasid);
- ret = -EBUSY;
- }
+ dev_warn_ratelimited(dev,
+ "Already bound with PASID %u\n",
+ svm->pasid);
+ ret = -EBUSY;
goto out;
}
} else {
--
2.7.4

2020-07-07 00:07:06

by Jacob Pan

[permalink] [raw]
Subject: [PATCH v4 5/7] iommu/vt-d: Fix devTLB flush for vSVA

From: Liu Yi L <[email protected]>

For guest SVA usage, in order to optimize for less VMEXIT, guest request
of IOTLB flush also includes device TLB.

On the host side, IOMMU driver performs IOTLB and implicit devTLB
invalidation. When PASID-selective granularity is requested by the guest
we need to derive the equivalent address range for devTLB instead of
using the address information in the UAPI data. The reason for that is, unlike
IOTLB flush, devTLB flush does not support PASID-selective granularity.
This is to say, we need to set the following in the PASID based devTLB
invalidation descriptor:
- entire 64 bit range in address ~(0x1 << 63)
- S bit = 1 (VT-d CH 6.5.2.6).

Without this fix, device TLB flush range is not set properly for PASID
selective granularity. This patch also merged devTLB flush code for both
implicit and explicit cases.

Fixes: 6ee1b77ba3ac ("iommu/vt-d: Add svm/sva invalidate function")
Acked-by: Lu Baolu <[email protected]>
Reviewed-by: Eric Auger <[email protected]>
Signed-off-by: Liu Yi L <[email protected]>
Signed-off-by: Jacob Pan <[email protected]>
---
drivers/iommu/intel/iommu.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 96340da57075..3bf03c6cd15f 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -5408,7 +5408,7 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev,
sid = PCI_DEVID(bus, devfn);

/* Size is only valid in address selective invalidation */
- if (inv_info->granularity != IOMMU_INV_GRANU_PASID)
+ if (inv_info->granularity == IOMMU_INV_GRANU_ADDR)
size = to_vtd_size(inv_info->addr_info.granule_size,
inv_info->addr_info.nb_granules);

@@ -5417,6 +5417,7 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev,
IOMMU_CACHE_INV_TYPE_NR) {
int granu = 0;
u64 pasid = 0;
+ u64 addr = 0;

granu = to_vtd_granularity(cache_type, inv_info->granularity);
if (granu == -EINVAL) {
@@ -5456,24 +5457,33 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev,
(granu == QI_GRAN_NONG_PASID) ? -1 : 1 << size,
inv_info->addr_info.flags & IOMMU_INV_ADDR_FLAGS_LEAF);

+ if (!info->ats_enabled)
+ break;
/*
* Always flush device IOTLB if ATS is enabled. vIOMMU
* in the guest may assume IOTLB flush is inclusive,
* which is more efficient.
*/
- if (info->ats_enabled)
- qi_flush_dev_iotlb_pasid(iommu, sid,
- info->pfsid, pasid,
- info->ats_qdep,
- inv_info->addr_info.addr,
- size);
- break;
+ fallthrough;
case IOMMU_CACHE_INV_TYPE_DEV_IOTLB:
+ /*
+ * PASID based device TLB invalidation does not support
+ * IOMMU_INV_GRANU_PASID granularity but only supports
+ * IOMMU_INV_GRANU_ADDR.
+ * The equivalent of that is we set the size to be the
+ * entire range of 64 bit. User only provides PASID info
+ * without address info. So we set addr to 0.
+ */
+ if (inv_info->granularity == IOMMU_INV_GRANU_PASID) {
+ size = 64 - VTD_PAGE_SHIFT;
+ addr = 0;
+ } else if (inv_info->granularity == IOMMU_INV_GRANU_ADDR)
+ addr = inv_info->addr_info.addr;
+
if (info->ats_enabled)
qi_flush_dev_iotlb_pasid(iommu, sid,
info->pfsid, pasid,
- info->ats_qdep,
- inv_info->addr_info.addr,
+ info->ats_qdep, addr,
size);
else
pr_warn_ratelimited("Passdown device IOTLB flush w/o ATS!\n");
--
2.7.4

2020-07-07 00:08:38

by Jacob Pan

[permalink] [raw]
Subject: [PATCH v4 6/7] iommu/vt-d: Warn on out-of-range invalidation address

For guest requested IOTLB invalidation, address and mask are provided as
part of the invalidation data. VT-d HW silently ignores any address bits
below the mask. SW shall also allow such case but give warning if
address does not align with the mask. This patch relax the fault
handling from error to warning and proceed with invalidation request
with the given mask.

Fixes: 6ee1b77ba3ac0 ("iommu/vt-d: Add svm/sva invalidate function")
Acked-by: Lu Baolu <[email protected]>
Signed-off-by: Jacob Pan <[email protected]>
---
drivers/iommu/intel/iommu.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 3bf03c6cd15f..c3a9a85a3c3f 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -5439,13 +5439,12 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev,

switch (BIT(cache_type)) {
case IOMMU_CACHE_INV_TYPE_IOTLB:
+ /* HW will ignore LSB bits based on address mask */
if (inv_info->granularity == IOMMU_INV_GRANU_ADDR &&
size &&
(inv_info->addr_info.addr & ((BIT(VTD_PAGE_SHIFT + size)) - 1))) {
- pr_err_ratelimited("Address out of range, 0x%llx, size order %llu\n",
- inv_info->addr_info.addr, size);
- ret = -ERANGE;
- goto out_unlock;
+ pr_err_ratelimited("User address not aligned, 0x%llx, size order %llu\n",
+ inv_info->addr_info.addr, size);
}

/*
--
2.7.4

2020-07-07 00:10:01

by Jacob Pan

[permalink] [raw]
Subject: [PATCH v4 3/7] iommu/vt-d: Fix PASID devTLB invalidation

DevTLB flush can be used for both DMA request with and without PASIDs.
The former uses PASID#0 (RID2PASID), latter uses non-zero PASID for SVA
usage.

This patch adds a check for PASID value such that devTLB flush with
PASID is used for SVA case. This is more efficient in that multiple
PASIDs can be used by a single device, when tearing down a PASID entry
we shall flush only the devTLB specific to a PASID.

Fixes: 6f7db75e1c46 ("iommu/vt-d: Add second level page table")
Acked-by: Lu Baolu <[email protected]>
Signed-off-by: Jacob Pan <[email protected]>
---
drivers/iommu/intel/pasid.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
index c81f0f17c6ba..fa0154cce537 100644
--- a/drivers/iommu/intel/pasid.c
+++ b/drivers/iommu/intel/pasid.c
@@ -486,7 +486,16 @@ devtlb_invalidation_with_pasid(struct intel_iommu *iommu,
qdep = info->ats_qdep;
pfsid = info->pfsid;

- qi_flush_dev_iotlb(iommu, sid, pfsid, qdep, 0, 64 - VTD_PAGE_SHIFT);
+ /*
+ * When PASID 0 is used, it indicates RID2PASID(DMA request w/o PASID),
+ * devTLB flush w/o PASID should be used. For non-zero PASID under
+ * SVA usage, device could do DMA with multiple PASIDs. It is more
+ * efficient to flush devTLB specific to the PASID.
+ */
+ if (pasid == PASID_RID2PASID)
+ qi_flush_dev_iotlb(iommu, sid, pfsid, qdep, 0, 64 - VTD_PAGE_SHIFT);
+ else
+ qi_flush_dev_iotlb_pasid(iommu, sid, pfsid, pasid, qdep, 0, 64 - VTD_PAGE_SHIFT);
}

void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
--
2.7.4

2020-07-07 00:10:42

by Jacob Pan

[permalink] [raw]
Subject: [PATCH v4 1/7] iommu/vt-d: Enforce PASID devTLB field mask

From: Liu Yi L <[email protected]>

Set proper masks to avoid invalid input spillover to reserved bits.

Acked-by: Lu Baolu <[email protected]>
Reviewed-by: Eric Auger <[email protected]>
Signed-off-by: Liu Yi L <[email protected]>
Signed-off-by: Jacob Pan <[email protected]>
---
include/linux/intel-iommu.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 4100bd224f5c..729386ca8122 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -380,8 +380,8 @@ enum {

#define QI_DEV_EIOTLB_ADDR(a) ((u64)(a) & VTD_PAGE_MASK)
#define QI_DEV_EIOTLB_SIZE (((u64)1) << 11)
-#define QI_DEV_EIOTLB_GLOB(g) ((u64)g)
-#define QI_DEV_EIOTLB_PASID(p) (((u64)p) << 32)
+#define QI_DEV_EIOTLB_GLOB(g) ((u64)(g) & 0x1)
+#define QI_DEV_EIOTLB_PASID(p) ((u64)((p) & 0xfffff) << 32)
#define QI_DEV_EIOTLB_SID(sid) ((u64)((sid) & 0xffff) << 16)
#define QI_DEV_EIOTLB_QDEP(qd) ((u64)((qd) & 0x1f) << 4)
#define QI_DEV_EIOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | \
--
2.7.4

2020-07-07 13:55:00

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v4 4/7] iommu/vt-d: Handle non-page aligned address

Hi Jacob,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on iommu/next]
[also build test WARNING on linux/master linus/master v5.8-rc4 next-20200707]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/Jacob-Pan/iommu-vt-d-Misc-tweaks-and-fixes-for-vSVA/20200707-081026
base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
config: x86_64-randconfig-m031-20200707 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-14) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All warnings (new ones prefixed by >>):

In file included from include/linux/string.h:6,
from include/linux/uuid.h:12,
from include/linux/mod_devicetable.h:13,
from include/linux/pci.h:27,
from drivers/iommu/intel/dmar.c:19:
drivers/iommu/intel/dmar.c: In function 'qi_flush_dev_iotlb_pasid':
include/linux/bits.h:26:28: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
| ^
include/linux/compiler.h:58:52: note: in definition of macro '__trace_if_var'
58 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
| ^~~~
>> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~
include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
| ^~~~~~~~~~~~~~~~~
include/linux/bits.h:45:3: note: in expansion of macro 'GENMASK_INPUT_CHECK'
45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
| ^~~~~~~~~~~~~~~~~~~
drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro 'GENMASK_ULL'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~~~~~~~~~~
include/linux/bits.h:26:40: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
| ^
include/linux/compiler.h:58:52: note: in definition of macro '__trace_if_var'
58 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
| ^~~~
>> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~
include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
| ^~~~~~~~~~~~~~~~~
include/linux/bits.h:45:3: note: in expansion of macro 'GENMASK_INPUT_CHECK'
45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
| ^~~~~~~~~~~~~~~~~~~
drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro 'GENMASK_ULL'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~~~~~~~~~~
include/linux/bits.h:26:28: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
| ^
include/linux/compiler.h:58:61: note: in definition of macro '__trace_if_var'
58 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
| ^~~~
>> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~
include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
| ^~~~~~~~~~~~~~~~~
include/linux/bits.h:45:3: note: in expansion of macro 'GENMASK_INPUT_CHECK'
45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
| ^~~~~~~~~~~~~~~~~~~
drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro 'GENMASK_ULL'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~~~~~~~~~~
include/linux/bits.h:26:40: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
| ^
include/linux/compiler.h:58:61: note: in definition of macro '__trace_if_var'
58 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
| ^~~~
>> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~
include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
| ^~~~~~~~~~~~~~~~~
include/linux/bits.h:45:3: note: in expansion of macro 'GENMASK_INPUT_CHECK'
45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
| ^~~~~~~~~~~~~~~~~~~
drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro 'GENMASK_ULL'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~~~~~~~~~~
include/linux/bits.h:26:28: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
| ^
include/linux/compiler.h:69:3: note: in definition of macro '__trace_if_value'
69 | (cond) ? \
| ^~~~
include/linux/compiler.h:56:28: note: in expansion of macro '__trace_if_var'
56 | #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
| ^~~~~~~~~~~~~~
>> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~
include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
| ^~~~~~~~~~~~~~~~~
include/linux/bits.h:45:3: note: in expansion of macro 'GENMASK_INPUT_CHECK'
45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
| ^~~~~~~~~~~~~~~~~~~
drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro 'GENMASK_ULL'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~~~~~~~~~~
include/linux/bits.h:26:40: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits]
26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
| ^
include/linux/compiler.h:69:3: note: in definition of macro '__trace_if_value'
69 | (cond) ? \
| ^~~~
include/linux/compiler.h:56:28: note: in expansion of macro '__trace_if_var'
56 | #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
| ^~~~~~~~~~~~~~
>> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~
include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
| ^~~~~~~~~~~~~~~~~
include/linux/bits.h:45:3: note: in expansion of macro 'GENMASK_INPUT_CHECK'
45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
| ^~~~~~~~~~~~~~~~~~~
drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro 'GENMASK_ULL'
1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
| ^~~~~~~~~~~

vim +/if +1459 drivers/iommu/intel/dmar.c

1438
1439 /* PASID-based device IOTLB Invalidate */
1440 void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
1441 u32 pasid, u16 qdep, u64 addr, unsigned int size_order)
1442 {
1443 unsigned long mask = 1UL << (VTD_PAGE_SHIFT + size_order - 1);
1444 struct qi_desc desc = {.qw1 = 0, .qw2 = 0, .qw3 = 0};
1445
1446 desc.qw0 = QI_DEV_EIOTLB_PASID(pasid) | QI_DEV_EIOTLB_SID(sid) |
1447 QI_DEV_EIOTLB_QDEP(qdep) | QI_DEIOTLB_TYPE |
1448 QI_DEV_IOTLB_PFSID(pfsid);
1449
1450 /*
1451 * If S bit is 0, we only flush a single page. If S bit is set,
1452 * The least significant zero bit indicates the invalidation address
1453 * range. VT-d spec 6.5.2.6.
1454 * e.g. address bit 12[0] indicates 8KB, 13[0] indicates 16KB.
1455 * size order = 0 is PAGE_SIZE 4KB
1456 * Max Invs Pending (MIP) is set to 0 for now until we have DIT in
1457 * ECAP.
1458 */
> 1459 if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
1460 pr_warn_ratelimited("Invalidate non-aligned address %llx, order %d\n", addr, size_order);
1461
1462 /* Take page address */
1463 desc.qw1 = QI_DEV_EIOTLB_ADDR(addr);
1464
1465 if (size_order) {
1466 /*
1467 * Existing 0s in address below size_order may be the least
1468 * significant bit, we must set them to 1s to avoid having
1469 * smaller size than desired.
1470 */
1471 desc.qw1 |= GENMASK_ULL(size_order + VTD_PAGE_SHIFT,
1472 VTD_PAGE_SHIFT);
1473 /* Clear size_order bit to indicate size */
1474 desc.qw1 &= ~mask;
1475 /* Set the S bit to indicate flushing more than 1 page */
1476 desc.qw1 |= QI_DEV_EIOTLB_SIZE;
1477 }
1478
1479 qi_submit_sync(iommu, &desc, 1, 0);
1480 }
1481

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (10.13 kB)
.config.gz (31.52 kB)
Download all attachments

2020-07-09 01:13:09

by Philip Li

[permalink] [raw]
Subject: RE: [kbuild-all] Re: [PATCH v4 4/7] iommu/vt-d: Handle non-page aligned address

> Subject: [kbuild-all] Re: [PATCH v4 4/7] iommu/vt-d: Handle non-page aligned
> address
>
> Hi Jacob,
>
> Thank you for the patch! Perhaps something to improve:
>
> [auto build test WARNING on iommu/next]
> [also build test WARNING on linux/master linus/master v5.8-rc4 next-20200707]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use as documented in
> https://git-scm.com/docs/git-format-patch]
>
> url: https://github.com/0day-ci/linux/commits/Jacob-Pan/iommu-vt-d-Misc-
> tweaks-and-fixes-for-vSVA/20200707-081026
> base: https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git next
> config: x86_64-randconfig-m031-20200707 (attached as .config)
> compiler: gcc-9 (Debian 9.3.0-14) 9.3.0
>
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot <[email protected]>
>
> All warnings (new ones prefixed by >>):
Kindly ignore this, which is related to [-Wtype-limits], and is under
discussion to move such warning from W=1 to W=2 as it may not
suitable to fix which can hurt code readability.

Refer to https://lore.kernel.org/lkml/CAHk-=wiKCXEWKJ9dWUimGbrVRo_N2RosESUw8E7m9AEtyZcu=w@mail.gmail.com/
for the discussion.


>
> In file included from include/linux/string.h:6,
> from include/linux/uuid.h:12,
> from include/linux/mod_devicetable.h:13,
> from include/linux/pci.h:27,
> from drivers/iommu/intel/dmar.c:19:
> drivers/iommu/intel/dmar.c: In function 'qi_flush_dev_iotlb_pasid':
> include/linux/bits.h:26:28: warning: comparison of unsigned expression < 0 is
> always false [-Wtype-limits]
> 26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
> | ^
> include/linux/compiler.h:58:52: note: in definition of macro '__trace_if_var'
> 58 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) :
> __trace_if_value(cond))
> | ^~~~
> >> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~
> include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
> 25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
> | ^~~~~~~~~~~~~~~~~
> include/linux/bits.h:45:3: note: in expansion of macro
> 'GENMASK_INPUT_CHECK'
> 45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
> | ^~~~~~~~~~~~~~~~~~~
> drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro
> 'GENMASK_ULL'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~~~~~~~~~~
> include/linux/bits.h:26:40: warning: comparison of unsigned expression < 0 is
> always false [-Wtype-limits]
> 26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
> | ^
> include/linux/compiler.h:58:52: note: in definition of macro '__trace_if_var'
> 58 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) :
> __trace_if_value(cond))
> | ^~~~
> >> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~
> include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
> 25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
> | ^~~~~~~~~~~~~~~~~
> include/linux/bits.h:45:3: note: in expansion of macro
> 'GENMASK_INPUT_CHECK'
> 45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
> | ^~~~~~~~~~~~~~~~~~~
> drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro
> 'GENMASK_ULL'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~~~~~~~~~~
> include/linux/bits.h:26:28: warning: comparison of unsigned expression < 0 is
> always false [-Wtype-limits]
> 26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
> | ^
> include/linux/compiler.h:58:61: note: in definition of macro '__trace_if_var'
> 58 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) :
> __trace_if_value(cond))
> | ^~~~
> >> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~
> include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
> 25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
> | ^~~~~~~~~~~~~~~~~
> include/linux/bits.h:45:3: note: in expansion of macro
> 'GENMASK_INPUT_CHECK'
> 45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
> | ^~~~~~~~~~~~~~~~~~~
> drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro
> 'GENMASK_ULL'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~~~~~~~~~~
> include/linux/bits.h:26:40: warning: comparison of unsigned expression < 0 is
> always false [-Wtype-limits]
> 26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
> | ^
> include/linux/compiler.h:58:61: note: in definition of macro '__trace_if_var'
> 58 | #define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) :
> __trace_if_value(cond))
> | ^~~~
> >> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~
> include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
> 25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
> | ^~~~~~~~~~~~~~~~~
> include/linux/bits.h:45:3: note: in expansion of macro
> 'GENMASK_INPUT_CHECK'
> 45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
> | ^~~~~~~~~~~~~~~~~~~
> drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro
> 'GENMASK_ULL'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~~~~~~~~~~
> include/linux/bits.h:26:28: warning: comparison of unsigned expression < 0 is
> always false [-Wtype-limits]
> 26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
> | ^
> include/linux/compiler.h:69:3: note: in definition of macro '__trace_if_value'
> 69 | (cond) ? \
> | ^~~~
> include/linux/compiler.h:56:28: note: in expansion of macro '__trace_if_var'
> 56 | #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
> | ^~~~~~~~~~~~~~
> >> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~
> include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
> 25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
> | ^~~~~~~~~~~~~~~~~
> include/linux/bits.h:45:3: note: in expansion of macro
> 'GENMASK_INPUT_CHECK'
> 45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
> | ^~~~~~~~~~~~~~~~~~~
> drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro
> 'GENMASK_ULL'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~~~~~~~~~~
> include/linux/bits.h:26:40: warning: comparison of unsigned expression < 0 is
> always false [-Wtype-limits]
> 26 | __builtin_constant_p((l) > (h)), (l) > (h), 0)))
> | ^
> include/linux/compiler.h:69:3: note: in definition of macro '__trace_if_value'
> 69 | (cond) ? \
> | ^~~~
> include/linux/compiler.h:56:28: note: in expansion of macro '__trace_if_var'
> 56 | #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
> | ^~~~~~~~~~~~~~
> >> drivers/iommu/intel/dmar.c:1459:2: note: in expansion of macro 'if'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~
> include/linux/bits.h:25:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
> 25 | (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
> | ^~~~~~~~~~~~~~~~~
> include/linux/bits.h:45:3: note: in expansion of macro
> 'GENMASK_INPUT_CHECK'
> 45 | (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))
> | ^~~~~~~~~~~~~~~~~~~
> drivers/iommu/intel/dmar.c:1459:13: note: in expansion of macro
> 'GENMASK_ULL'
> 1459 | if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> | ^~~~~~~~~~~
>
> vim +/if +1459 drivers/iommu/intel/dmar.c
>
> 1438
> 1439 /* PASID-based device IOTLB Invalidate */
> 1440 void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16
> pfsid,
> 1441 u32 pasid, u16 qdep, u64 addr, unsigned int
> size_order)
> 1442 {
> 1443 unsigned long mask = 1UL << (VTD_PAGE_SHIFT + size_order -
> 1);
> 1444 struct qi_desc desc = {.qw1 = 0, .qw2 = 0, .qw3 = 0};
> 1445
> 1446 desc.qw0 = QI_DEV_EIOTLB_PASID(pasid) |
> QI_DEV_EIOTLB_SID(sid) |
> 1447 QI_DEV_EIOTLB_QDEP(qdep) | QI_DEIOTLB_TYPE |
> 1448 QI_DEV_IOTLB_PFSID(pfsid);
> 1449
> 1450 /*
> 1451 * If S bit is 0, we only flush a single page. If S bit is set,
> 1452 * The least significant zero bit indicates the invalidation address
> 1453 * range. VT-d spec 6.5.2.6.
> 1454 * e.g. address bit 12[0] indicates 8KB, 13[0] indicates 16KB.
> 1455 * size order = 0 is PAGE_SIZE 4KB
> 1456 * Max Invs Pending (MIP) is set to 0 for now until we have DIT in
> 1457 * ECAP.
> 1458 */
> > 1459 if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> 1460 pr_warn_ratelimited("Invalidate non-aligned address %llx,
> order %d\n", addr, size_order);
> 1461
> 1462 /* Take page address */
> 1463 desc.qw1 = QI_DEV_EIOTLB_ADDR(addr);
> 1464
> 1465 if (size_order) {
> 1466 /*
> 1467 * Existing 0s in address below size_order may be the
> least
> 1468 * significant bit, we must set them to 1s to avoid having
> 1469 * smaller size than desired.
> 1470 */
> 1471 desc.qw1 |= GENMASK_ULL(size_order +
> VTD_PAGE_SHIFT,
> 1472 VTD_PAGE_SHIFT);
> 1473 /* Clear size_order bit to indicate size */
> 1474 desc.qw1 &= ~mask;
> 1475 /* Set the S bit to indicate flushing more than 1 page */
> 1476 desc.qw1 |= QI_DEV_EIOTLB_SIZE;
> 1477 }
> 1478
> 1479 qi_submit_sync(iommu, &desc, 1, 0);
> 1480 }
> 1481
>
> ---
> 0-DAY CI Kernel Test Service, Intel Corporation
> https://lists.01.org/hyperkitty/list/[email protected]

2020-07-16 07:52:40

by Eric Auger

[permalink] [raw]
Subject: Re: [PATCH v4 4/7] iommu/vt-d: Handle non-page aligned address

Hi Jacob,

On 7/7/20 2:12 AM, Jacob Pan wrote:
> From: Liu Yi L <[email protected]>
>
> Address information for device TLB invalidation comes from userspace
> when device is directly assigned to a guest with vIOMMU support.
> VT-d requires page aligned address. This patch checks and enforce
> address to be page aligned, otherwise reserved bits can be set in the
> invalidation descriptor. Unrecoverable fault will be reported due to
> non-zero value in the reserved bits.
>
> Fixes: 61a06a16e36d8 ("iommu/vt-d: Support flushing more translation
> cache types")
> Acked-by: Lu Baolu <[email protected]>
> Signed-off-by: Liu Yi L <[email protected]>
> Signed-off-by: Jacob Pan <[email protected]>
Reviewed-by: Eric Auger <[email protected]>

Thanks

Eric
>
> ---
> drivers/iommu/intel/dmar.c | 20 ++++++++++++++++++--
> 1 file changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
> index d9f973fa1190..b2c53bada905 100644
> --- a/drivers/iommu/intel/dmar.c
> +++ b/drivers/iommu/intel/dmar.c
> @@ -1455,9 +1455,25 @@ void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
> * Max Invs Pending (MIP) is set to 0 for now until we have DIT in
> * ECAP.
> */
> - desc.qw1 |= addr & ~mask;
> - if (size_order)
> + if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> + pr_warn_ratelimited("Invalidate non-aligned address %llx, order %d\n", addr, size_order);
> +
> + /* Take page address */
> + desc.qw1 = QI_DEV_EIOTLB_ADDR(addr);
> +
> + if (size_order) {
> + /*
> + * Existing 0s in address below size_order may be the least
> + * significant bit, we must set them to 1s to avoid having
> + * smaller size than desired.
> + */
> + desc.qw1 |= GENMASK_ULL(size_order + VTD_PAGE_SHIFT,
> + VTD_PAGE_SHIFT);
> + /* Clear size_order bit to indicate size */
> + desc.qw1 &= ~mask;
> + /* Set the S bit to indicate flushing more than 1 page */
> desc.qw1 |= QI_DEV_EIOTLB_SIZE;
> + }
>
> qi_submit_sync(iommu, &desc, 1, 0);
> }
>

2020-07-16 07:55:16

by Eric Auger

[permalink] [raw]
Subject: Re: [PATCH v4 3/7] iommu/vt-d: Fix PASID devTLB invalidation

Hi Jacob,

On 7/7/20 2:12 AM, Jacob Pan wrote:
> DevTLB flush can be used for both DMA request with and without PASIDs.
> The former uses PASID#0 (RID2PASID), latter uses non-zero PASID for SVA
> usage.
>
> This patch adds a check for PASID value such that devTLB flush with
> PASID is used for SVA case. This is more efficient in that multiple
> PASIDs can be used by a single device, when tearing down a PASID entry
> we shall flush only the devTLB specific to a PASID.
>
> Fixes: 6f7db75e1c46 ("iommu/vt-d: Add second level page table")
> Acked-by: Lu Baolu <[email protected]>
> Signed-off-by: Jacob Pan <[email protected]>
Reviewed-by: Eric Auger <[email protected]>
sent on v3.

Thanks

Eric
> ---
> drivers/iommu/intel/pasid.c | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
> index c81f0f17c6ba..fa0154cce537 100644
> --- a/drivers/iommu/intel/pasid.c
> +++ b/drivers/iommu/intel/pasid.c
> @@ -486,7 +486,16 @@ devtlb_invalidation_with_pasid(struct intel_iommu *iommu,
> qdep = info->ats_qdep;
> pfsid = info->pfsid;
>
> - qi_flush_dev_iotlb(iommu, sid, pfsid, qdep, 0, 64 - VTD_PAGE_SHIFT);
> + /*
> + * When PASID 0 is used, it indicates RID2PASID(DMA request w/o PASID),
> + * devTLB flush w/o PASID should be used. For non-zero PASID under
> + * SVA usage, device could do DMA with multiple PASIDs. It is more
> + * efficient to flush devTLB specific to the PASID.
> + */
> + if (pasid == PASID_RID2PASID)
> + qi_flush_dev_iotlb(iommu, sid, pfsid, qdep, 0, 64 - VTD_PAGE_SHIFT);
> + else
> + qi_flush_dev_iotlb_pasid(iommu, sid, pfsid, pasid, qdep, 0, 64 - VTD_PAGE_SHIFT);
> }
>
> void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
>

2020-07-16 08:43:39

by Eric Auger

[permalink] [raw]
Subject: Re: [PATCH v4 6/7] iommu/vt-d: Warn on out-of-range invalidation address

Hi Jacob,

On 7/7/20 2:12 AM, Jacob Pan wrote:
> For guest requested IOTLB invalidation, address and mask are provided as
> part of the invalidation data. VT-d HW silently ignores any address bits
> below the mask. SW shall also allow such case but give warning if
> address does not align with the mask. This patch relax the fault
> handling from error to warning and proceed with invalidation request
> with the given mask.
>
> Fixes: 6ee1b77ba3ac0 ("iommu/vt-d: Add svm/sva invalidate function")
> Acked-by: Lu Baolu <[email protected]>
> Signed-off-by: Jacob Pan <[email protected]>
following your replies on my v3 comments,

Reviewed-by: Eric Auger <[email protected]>

Thanks

Eric

> ---
> drivers/iommu/intel/iommu.c | 7 +++----
> 1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
> index 3bf03c6cd15f..c3a9a85a3c3f 100644
> --- a/drivers/iommu/intel/iommu.c
> +++ b/drivers/iommu/intel/iommu.c
> @@ -5439,13 +5439,12 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, struct device *dev,
>
> switch (BIT(cache_type)) {
> case IOMMU_CACHE_INV_TYPE_IOTLB:
> + /* HW will ignore LSB bits based on address mask */
> if (inv_info->granularity == IOMMU_INV_GRANU_ADDR &&
> size &&
> (inv_info->addr_info.addr & ((BIT(VTD_PAGE_SHIFT + size)) - 1))) {
> - pr_err_ratelimited("Address out of range, 0x%llx, size order %llu\n",
> - inv_info->addr_info.addr, size);
> - ret = -ERANGE;
> - goto out_unlock;
> + pr_err_ratelimited("User address not aligned, 0x%llx, size order %llu\n",
> + inv_info->addr_info.addr, size);
> }
>
> /*
>

2020-07-21 16:47:25

by Jacob Pan

[permalink] [raw]
Subject: Re: [PATCH v4 4/7] iommu/vt-d: Handle non-page aligned address

Hi Baolu,

Not sure what state is this patch in, there is a bug in this patch
(see below), shall I send out an updated version of this one only? or
another incremental patch.

Thanks,

Jacob

On Mon, 6 Jul 2020 17:12:51 -0700
Jacob Pan <[email protected]> wrote:

> From: Liu Yi L <[email protected]>
>
> Address information for device TLB invalidation comes from userspace
> when device is directly assigned to a guest with vIOMMU support.
> VT-d requires page aligned address. This patch checks and enforce
> address to be page aligned, otherwise reserved bits can be set in the
> invalidation descriptor. Unrecoverable fault will be reported due to
> non-zero value in the reserved bits.
>
> Fixes: 61a06a16e36d8 ("iommu/vt-d: Support flushing more translation
> cache types")
> Acked-by: Lu Baolu <[email protected]>
> Signed-off-by: Liu Yi L <[email protected]>
> Signed-off-by: Jacob Pan <[email protected]>
>
> ---
> drivers/iommu/intel/dmar.c | 20 ++++++++++++++++++--
> 1 file changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
> index d9f973fa1190..b2c53bada905 100644
> --- a/drivers/iommu/intel/dmar.c
> +++ b/drivers/iommu/intel/dmar.c
> @@ -1455,9 +1455,25 @@ void qi_flush_dev_iotlb_pasid(struct
> intel_iommu *iommu, u16 sid, u16 pfsid,
> * Max Invs Pending (MIP) is set to 0 for now until we have
> DIT in
> * ECAP.
> */
> - desc.qw1 |= addr & ~mask;
> - if (size_order)
> + if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
> + pr_warn_ratelimited("Invalidate non-aligned address
> %llx, order %d\n", addr, size_order); +
> + /* Take page address */
> + desc.qw1 = QI_DEV_EIOTLB_ADDR(addr);
> +
> + if (size_order) {
> + /*
> + * Existing 0s in address below size_order may be
> the least
> + * significant bit, we must set them to 1s to avoid
> having
> + * smaller size than desired.
> + */
> + desc.qw1 |= GENMASK_ULL(size_order + VTD_PAGE_SHIFT,
> + VTD_PAGE_SHIFT);
Yi reported the issue, it should be:
desc.qw1 |= GENMASK_ULL(size_order + VTD_PAGE_SHIFT - 1,
VTD_PAGE_SHIFT);

> + /* Clear size_order bit to indicate size */
> + desc.qw1 &= ~mask;
> + /* Set the S bit to indicate flushing more than 1
> page */ desc.qw1 |= QI_DEV_EIOTLB_SIZE;
> + }
>
> qi_submit_sync(iommu, &desc, 1, 0);
> }

[Jacob Pan]

2020-07-22 01:08:51

by Lu Baolu

[permalink] [raw]
Subject: Re: [PATCH v4 4/7] iommu/vt-d: Handle non-page aligned address

Hi Jacob,

On 7/22/20 12:50 AM, Jacob Pan wrote:
> Hi Baolu,
>
> Not sure what state is this patch in, there is a bug in this patch
> (see below), shall I send out an updated version of this one only? or
> another incremental patch.

Please send an updated version. I hope Joerg could pick these as 5.8
fix.

Best regards,
baolu

>
> Thanks,
>
> Jacob
>
> On Mon, 6 Jul 2020 17:12:51 -0700
> Jacob Pan <[email protected]> wrote:
>
>> From: Liu Yi L <[email protected]>
>>
>> Address information for device TLB invalidation comes from userspace
>> when device is directly assigned to a guest with vIOMMU support.
>> VT-d requires page aligned address. This patch checks and enforce
>> address to be page aligned, otherwise reserved bits can be set in the
>> invalidation descriptor. Unrecoverable fault will be reported due to
>> non-zero value in the reserved bits.
>>
>> Fixes: 61a06a16e36d8 ("iommu/vt-d: Support flushing more translation
>> cache types")
>> Acked-by: Lu Baolu <[email protected]>
>> Signed-off-by: Liu Yi L <[email protected]>
>> Signed-off-by: Jacob Pan <[email protected]>
>>
>> ---
>> drivers/iommu/intel/dmar.c | 20 ++++++++++++++++++--
>> 1 file changed, 18 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
>> index d9f973fa1190..b2c53bada905 100644
>> --- a/drivers/iommu/intel/dmar.c
>> +++ b/drivers/iommu/intel/dmar.c
>> @@ -1455,9 +1455,25 @@ void qi_flush_dev_iotlb_pasid(struct
>> intel_iommu *iommu, u16 sid, u16 pfsid,
>> * Max Invs Pending (MIP) is set to 0 for now until we have
>> DIT in
>> * ECAP.
>> */
>> - desc.qw1 |= addr & ~mask;
>> - if (size_order)
>> + if (addr & GENMASK_ULL(size_order + VTD_PAGE_SHIFT, 0))
>> + pr_warn_ratelimited("Invalidate non-aligned address
>> %llx, order %d\n", addr, size_order); +
>> + /* Take page address */
>> + desc.qw1 = QI_DEV_EIOTLB_ADDR(addr);
>> +
>> + if (size_order) {
>> + /*
>> + * Existing 0s in address below size_order may be
>> the least
>> + * significant bit, we must set them to 1s to avoid
>> having
>> + * smaller size than desired.
>> + */
>> + desc.qw1 |= GENMASK_ULL(size_order + VTD_PAGE_SHIFT,
>> + VTD_PAGE_SHIFT);
> Yi reported the issue, it should be:
> desc.qw1 |= GENMASK_ULL(size_order + VTD_PAGE_SHIFT - 1,
> VTD_PAGE_SHIFT);
>
>> + /* Clear size_order bit to indicate size */
>> + desc.qw1 &= ~mask;
>> + /* Set the S bit to indicate flushing more than 1
>> page */ desc.qw1 |= QI_DEV_EIOTLB_SIZE;
>> + }
>>
>> qi_submit_sync(iommu, &desc, 1, 0);
>> }
>
> [Jacob Pan]
>

2020-07-22 18:14:27

by Jacob Pan

[permalink] [raw]
Subject: Re: [PATCH v4 4/7] iommu/vt-d: Handle non-page aligned address

On Wed, 22 Jul 2020 09:01:27 +0800
Lu Baolu <[email protected]> wrote:

> >
> > Not sure what state is this patch in, there is a bug in this patch
> > (see below), shall I send out an updated version of this one only?
> > or another incremental patch.
>
> Please send an updated version. I hope Joerg could pick these as 5.8
> fix.
OK, will do.