Skip to content

Commit 61a06a1

Browse files
Jacob Panjoergroedel
authored andcommitted
iommu/vt-d: Support flushing more translation cache types
When Shared Virtual Memory is exposed to a guest via vIOMMU, scalable IOTLB invalidation may be passed down from outside IOMMU subsystems. This patch adds invalidation functions that can be used for additional translation cache types. Signed-off-by: Jacob Pan <[email protected]> Signed-off-by: Lu Baolu <[email protected]> Reviewed-by: Eric Auger <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 56722a4 commit 61a06a1

File tree

3 files changed

+58
-5
lines changed

3 files changed

+58
-5
lines changed

drivers/iommu/dmar.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,6 +1421,45 @@ void qi_flush_piotlb(struct intel_iommu *iommu, u16 did, u32 pasid, u64 addr,
14211421
qi_submit_sync(&desc, iommu);
14221422
}
14231423

1424+
/* PASID-based device IOTLB Invalidate */
1425+
void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
1426+
u32 pasid, u16 qdep, u64 addr,
1427+
unsigned int size_order, u64 granu)
1428+
{
1429+
unsigned long mask = 1UL << (VTD_PAGE_SHIFT + size_order - 1);
1430+
struct qi_desc desc = {.qw1 = 0, .qw2 = 0, .qw3 = 0};
1431+
1432+
desc.qw0 = QI_DEV_EIOTLB_PASID(pasid) | QI_DEV_EIOTLB_SID(sid) |
1433+
QI_DEV_EIOTLB_QDEP(qdep) | QI_DEIOTLB_TYPE |
1434+
QI_DEV_IOTLB_PFSID(pfsid);
1435+
desc.qw1 = QI_DEV_EIOTLB_GLOB(granu);
1436+
1437+
/*
1438+
* If S bit is 0, we only flush a single page. If S bit is set,
1439+
* The least significant zero bit indicates the invalidation address
1440+
* range. VT-d spec 6.5.2.6.
1441+
* e.g. address bit 12[0] indicates 8KB, 13[0] indicates 16KB.
1442+
* size order = 0 is PAGE_SIZE 4KB
1443+
* Max Invs Pending (MIP) is set to 0 for now until we have DIT in
1444+
* ECAP.
1445+
*/
1446+
desc.qw1 |= addr & ~mask;
1447+
if (size_order)
1448+
desc.qw1 |= QI_DEV_EIOTLB_SIZE;
1449+
1450+
qi_submit_sync(&desc, iommu);
1451+
}
1452+
1453+
void qi_flush_pasid_cache(struct intel_iommu *iommu, u16 did,
1454+
u64 granu, int pasid)
1455+
{
1456+
struct qi_desc desc = {.qw1 = 0, .qw2 = 0, .qw3 = 0};
1457+
1458+
desc.qw0 = QI_PC_PASID(pasid) | QI_PC_DID(did) |
1459+
QI_PC_GRAN(granu) | QI_PC_TYPE;
1460+
qi_submit_sync(&desc, iommu);
1461+
}
1462+
14241463
/*
14251464
* Disable Queued Invalidation interface.
14261465
*/

drivers/iommu/intel-pasid.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,8 @@ pasid_cache_invalidation_with_pasid(struct intel_iommu *iommu,
375375
{
376376
struct qi_desc desc;
377377

378-
desc.qw0 = QI_PC_DID(did) | QI_PC_PASID_SEL | QI_PC_PASID(pasid);
378+
desc.qw0 = QI_PC_DID(did) | QI_PC_GRAN(QI_PC_PASID_SEL) |
379+
QI_PC_PASID(pasid) | QI_PC_TYPE;
379380
desc.qw1 = 0;
380381
desc.qw2 = 0;
381382
desc.qw3 = 0;

include/linux/intel-iommu.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ enum {
334334
#define QI_IOTLB_GRAN(gran) (((u64)gran) >> (DMA_TLB_FLUSH_GRANU_OFFSET-4))
335335
#define QI_IOTLB_ADDR(addr) (((u64)addr) & VTD_PAGE_MASK)
336336
#define QI_IOTLB_IH(ih) (((u64)ih) << 6)
337-
#define QI_IOTLB_AM(am) (((u8)am))
337+
#define QI_IOTLB_AM(am) (((u8)am) & 0x3f)
338338

339339
#define QI_CC_FM(fm) (((u64)fm) << 48)
340340
#define QI_CC_SID(sid) (((u64)sid) << 32)
@@ -353,16 +353,21 @@ enum {
353353
#define QI_PC_DID(did) (((u64)did) << 16)
354354
#define QI_PC_GRAN(gran) (((u64)gran) << 4)
355355

356-
#define QI_PC_ALL_PASIDS (QI_PC_TYPE | QI_PC_GRAN(0))
357-
#define QI_PC_PASID_SEL (QI_PC_TYPE | QI_PC_GRAN(1))
356+
/* PASID cache invalidation granu */
357+
#define QI_PC_ALL_PASIDS 0
358+
#define QI_PC_PASID_SEL 1
358359

359360
#define QI_EIOTLB_ADDR(addr) ((u64)(addr) & VTD_PAGE_MASK)
360361
#define QI_EIOTLB_IH(ih) (((u64)ih) << 6)
361-
#define QI_EIOTLB_AM(am) (((u64)am))
362+
#define QI_EIOTLB_AM(am) (((u64)am) & 0x3f)
362363
#define QI_EIOTLB_PASID(pasid) (((u64)pasid) << 32)
363364
#define QI_EIOTLB_DID(did) (((u64)did) << 16)
364365
#define QI_EIOTLB_GRAN(gran) (((u64)gran) << 4)
365366

367+
/* QI Dev-IOTLB inv granu */
368+
#define QI_DEV_IOTLB_GRAN_ALL 1
369+
#define QI_DEV_IOTLB_GRAN_PASID_SEL 0
370+
366371
#define QI_DEV_EIOTLB_ADDR(a) ((u64)(a) & VTD_PAGE_MASK)
367372
#define QI_DEV_EIOTLB_SIZE (((u64)1) << 11)
368373
#define QI_DEV_EIOTLB_GLOB(g) ((u64)g)
@@ -679,8 +684,16 @@ extern void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
679684
unsigned int size_order, u64 type);
680685
extern void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 pfsid,
681686
u16 qdep, u64 addr, unsigned mask);
687+
682688
void qi_flush_piotlb(struct intel_iommu *iommu, u16 did, u32 pasid, u64 addr,
683689
unsigned long npages, bool ih);
690+
691+
void qi_flush_dev_iotlb_pasid(struct intel_iommu *iommu, u16 sid, u16 pfsid,
692+
u32 pasid, u16 qdep, u64 addr,
693+
unsigned int size_order, u64 granu);
694+
void qi_flush_pasid_cache(struct intel_iommu *iommu, u16 did, u64 granu,
695+
int pasid);
696+
684697
extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
685698

686699
extern int dmar_ir_support(void);

0 commit comments

Comments
 (0)