Skip to content

Commit 750e2e9

Browse files
jpemartinsjgunthorpe
authored andcommitted
iommu: Add iommu_domain ops for dirty tracking
Add to iommu domain operations a set of callbacks to perform dirty tracking, particulary to start and stop tracking and to read and clear the dirty data. Drivers are generally expected to dynamically change its translation structures to toggle the tracking and flush some form of control state structure that stands in the IOVA translation path. Though it's not mandatory, as drivers can also enable dirty tracking at boot, and just clear the dirty bits before setting dirty tracking. For each of the newly added IOMMU core APIs: iommu_cap::IOMMU_CAP_DIRTY_TRACKING: new device iommu_capable value when probing for capabilities of the device. .set_dirty_tracking(): an iommu driver is expected to change its translation structures and enable dirty tracking for the devices in the iommu_domain. For drivers making dirty tracking always-enabled, it should just return 0. .read_and_clear_dirty(): an iommu driver is expected to walk the pagetables for the iova range passed in and use iommu_dirty_bitmap_record() to record dirty info per IOVA. When detecting that a given IOVA is dirty it should also clear its dirty state from the PTE, *unless* the flag IOMMU_DIRTY_NO_CLEAR is passed in -- flushing is steered from the caller of the domain_op via iotlb_gather. The iommu core APIs use the same data structure in use for dirty tracking for VFIO device dirty (struct iova_bitmap) abstracted by iommu_dirty_bitmap_record() helper function. domain::dirty_ops: IOMMU domains will store the dirty ops depending on whether the iommu device supports dirty tracking or not. iommu drivers can then use this field to figure if the dirty tracking is supported+enforced on attach. The enforcement is enable via domain_alloc_user() which is done via IOMMUFD hwpt flag introduced later. Link: https://lore.kernel.org/r/20231024135109.73787-5-joao.m.martins@oracle.com Signed-off-by: Joao Martins <joao.m.martins@oracle.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
1 parent 13578d4 commit 750e2e9

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

include/linux/io-pgtable.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ struct io_pgtable_ops {
166166
struct iommu_iotlb_gather *gather);
167167
phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops,
168168
unsigned long iova);
169+
int (*read_and_clear_dirty)(struct io_pgtable_ops *ops,
170+
unsigned long iova, size_t size,
171+
unsigned long flags,
172+
struct iommu_dirty_bitmap *dirty);
169173
};
170174

171175
/**

include/linux/iommu.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/errno.h>
1414
#include <linux/err.h>
1515
#include <linux/of.h>
16+
#include <linux/iova_bitmap.h>
1617
#include <uapi/linux/iommu.h>
1718

1819
#define IOMMU_READ (1 << 0)
@@ -37,6 +38,7 @@ struct bus_type;
3738
struct device;
3839
struct iommu_domain;
3940
struct iommu_domain_ops;
41+
struct iommu_dirty_ops;
4042
struct notifier_block;
4143
struct iommu_sva;
4244
struct iommu_fault_event;
@@ -95,6 +97,8 @@ struct iommu_domain_geometry {
9597
struct iommu_domain {
9698
unsigned type;
9799
const struct iommu_domain_ops *ops;
100+
const struct iommu_dirty_ops *dirty_ops;
101+
98102
unsigned long pgsize_bitmap; /* Bitmap of page sizes in use */
99103
struct iommu_domain_geometry geometry;
100104
struct iommu_dma_cookie *iova_cookie;
@@ -133,6 +137,7 @@ enum iommu_cap {
133137
* usefully support the non-strict DMA flush queue.
134138
*/
135139
IOMMU_CAP_DEFERRED_FLUSH,
140+
IOMMU_CAP_DIRTY_TRACKING, /* IOMMU supports dirty tracking */
136141
};
137142

138143
/* These are the possible reserved region types */
@@ -227,6 +232,35 @@ struct iommu_iotlb_gather {
227232
bool queued;
228233
};
229234

235+
/**
236+
* struct iommu_dirty_bitmap - Dirty IOVA bitmap state
237+
* @bitmap: IOVA bitmap
238+
* @gather: Range information for a pending IOTLB flush
239+
*/
240+
struct iommu_dirty_bitmap {
241+
struct iova_bitmap *bitmap;
242+
struct iommu_iotlb_gather *gather;
243+
};
244+
245+
/* Read but do not clear any dirty bits */
246+
#define IOMMU_DIRTY_NO_CLEAR (1 << 0)
247+
248+
/**
249+
* struct iommu_dirty_ops - domain specific dirty tracking operations
250+
* @set_dirty_tracking: Enable or Disable dirty tracking on the iommu domain
251+
* @read_and_clear_dirty: Walk IOMMU page tables for dirtied PTEs marshalled
252+
* into a bitmap, with a bit represented as a page.
253+
* Reads the dirty PTE bits and clears it from IO
254+
* pagetables.
255+
*/
256+
struct iommu_dirty_ops {
257+
int (*set_dirty_tracking)(struct iommu_domain *domain, bool enabled);
258+
int (*read_and_clear_dirty)(struct iommu_domain *domain,
259+
unsigned long iova, size_t size,
260+
unsigned long flags,
261+
struct iommu_dirty_bitmap *dirty);
262+
};
263+
230264
/**
231265
* struct iommu_ops - iommu ops and capabilities
232266
* @capable: check capability
@@ -641,6 +675,28 @@ static inline bool iommu_iotlb_gather_queued(struct iommu_iotlb_gather *gather)
641675
return gather && gather->queued;
642676
}
643677

678+
static inline void iommu_dirty_bitmap_init(struct iommu_dirty_bitmap *dirty,
679+
struct iova_bitmap *bitmap,
680+
struct iommu_iotlb_gather *gather)
681+
{
682+
if (gather)
683+
iommu_iotlb_gather_init(gather);
684+
685+
dirty->bitmap = bitmap;
686+
dirty->gather = gather;
687+
}
688+
689+
static inline void iommu_dirty_bitmap_record(struct iommu_dirty_bitmap *dirty,
690+
unsigned long iova,
691+
unsigned long length)
692+
{
693+
if (dirty->bitmap)
694+
iova_bitmap_set(dirty->bitmap, iova, length);
695+
696+
if (dirty->gather)
697+
iommu_iotlb_gather_add_range(dirty->gather, iova, length);
698+
}
699+
644700
/* PCI device grouping function */
645701
extern struct iommu_group *pci_device_group(struct device *dev);
646702
/* Generic device grouping function */
@@ -746,6 +802,8 @@ struct iommu_fwspec {};
746802
struct iommu_device {};
747803
struct iommu_fault_param {};
748804
struct iommu_iotlb_gather {};
805+
struct iommu_dirty_bitmap {};
806+
struct iommu_dirty_ops {};
749807

750808
static inline bool iommu_present(const struct bus_type *bus)
751809
{
@@ -978,6 +1036,18 @@ static inline bool iommu_iotlb_gather_queued(struct iommu_iotlb_gather *gather)
9781036
return false;
9791037
}
9801038

1039+
static inline void iommu_dirty_bitmap_init(struct iommu_dirty_bitmap *dirty,
1040+
struct iova_bitmap *bitmap,
1041+
struct iommu_iotlb_gather *gather)
1042+
{
1043+
}
1044+
1045+
static inline void iommu_dirty_bitmap_record(struct iommu_dirty_bitmap *dirty,
1046+
unsigned long iova,
1047+
unsigned long length)
1048+
{
1049+
}
1050+
9811051
static inline void iommu_device_unregister(struct iommu_device *iommu)
9821052
{
9831053
}

0 commit comments

Comments
 (0)