History

Merge tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd

Pull iommufd updates from Jason Gunthorpe: "This brings three new iommufd capabilities: - Dirty tracking for DMA. AMD/ARM/Intel CPUs can now record if a DMA writes to a page in the IOPTEs within the IO page table. This can be used to generate a record of what memory is being dirtied by DMA activities during a VM migration process. A VMM like qemu will combine the IOMMU dirty bits with the CPU's dirty log to determine what memory to transfer. VFIO already has a DMA dirty tracking framework that requires PCI devices to implement tracking HW internally. The iommufd version provides an alternative that the VMM can select, if available. The two are designed to have very similar APIs. - Userspace controlled attributes for hardware page tables (HWPT/iommu_domain). There are currently a few generic attributes for HWPTs (support dirty tracking, and parent of a nest). This is an entry point for the userspace iommu driver to control the HW in detail. - Nested translation support for HWPTs. This is a 2D translation scheme similar to the CPU where a DMA goes through a first stage to determine an intermediate address which is then translated trough a second stage to a physical address. Like for CPU translation the first stage table would exist in VM controlled memory and the second stage is in the kernel and matches the VM's guest to physical map. As every IOMMU has a unique set of parameter to describe the S1 IO page table and its associated parameters the userspace IOMMU driver has to marshal the information into the correct format. This is 1/3 of the feature, it allows creating the nested translation and binding it to VFIO devices, however the API to support IOTLB and ATC invalidation of the stage 1 io page table, and forwarding of IO faults are still in progress. The series includes AMD and Intel support for dirty tracking. Intel support for nested translation. Along the way are a number of internal items: - New iommu core items: ops->domain_alloc_user(), ops->set_dirty_tracking, ops->read_and_clear_dirty(), IOMMU_DOMAIN_NESTED, and iommu_copy_struct_from_user - UAF fix in iopt_area_split() - Spelling fixes and some test suite improvement" * tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd: (52 commits) iommufd: Organize the mock domain alloc functions closer to Joerg's tree iommufd/selftest: Fix page-size check in iommufd_test_dirty() iommufd: Add iopt_area_alloc() iommufd: Fix missing update of domains_itree after splitting iopt_area iommu/vt-d: Disallow read-only mappings to nest parent domain iommu/vt-d: Add nested domain allocation iommu/vt-d: Set the nested domain to a device iommu/vt-d: Make domain attach helpers to be extern iommu/vt-d: Add helper to setup pasid nested translation iommu/vt-d: Add helper for nested domain allocation iommu/vt-d: Extend dmar_domain to support nested domain iommufd: Add data structure for Intel VT-d stage-1 domain allocation iommu/vt-d: Enhance capability check for nested parent domain allocation iommufd/selftest: Add coverage for IOMMU_HWPT_ALLOC with nested HWPTs iommufd/selftest: Add nested domain allocation for mock domain iommu: Add iommu_copy_struct_from_user helper iommufd: Add a nested HW pagetable object iommu: Pass in parent domain with user_data to domain_alloc_user op iommufd: Share iommufd_hwpt_alloc with IOMMUFD_OBJ_HWPT_NESTED iommufd: Derive iommufd_hwpt_paging from iommufd_hw_pagetable ...

Linus Torvalds committed 3 years ago

Commit 463f46e2 parents ff269e2 b2b67c936 files · +2722 −218Browse files

Showing the changes to include/uapi/linux (1 of 36 files). Show all

Unified · Split

include/uapi/linux/iommufd.h+176−4
@@ -47,6 +47,8 @@ enum { · 46 unmodified lines
4747 IOMMUFD_CMD_VFIO_IOAS,
4848 IOMMUFD_CMD_HWPT_ALLOC,
4949 IOMMUFD_CMD_GET_HW_INFO,
50+ IOMMUFD_CMD_HWPT_SET_DIRTY_TRACKING,
51+ IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP,
5052 };
5153
5254 /**
@@ -347,20 +349,86 @@ struct iommu_vfio_ioas { · 294 unmodified lines
347349 };
348350 #define IOMMU_VFIO_IOAS _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VFIO_IOAS)
349351
352+/**
353+ * enum iommufd_hwpt_alloc_flags - Flags for HWPT allocation
354+ * @IOMMU_HWPT_ALLOC_NEST_PARENT: If set, allocate a HWPT that can serve as
355+ * the parent HWPT in a nesting configuration.
356+ * @IOMMU_HWPT_ALLOC_DIRTY_TRACKING: Dirty tracking support for device IOMMU is
357+ * enforced on device attachment
358+ */
359+enum iommufd_hwpt_alloc_flags {
360+ IOMMU_HWPT_ALLOC_NEST_PARENT = 1 << 0,
361+ IOMMU_HWPT_ALLOC_DIRTY_TRACKING = 1 << 1,
362+};
363+
364+/**
365+ * enum iommu_hwpt_vtd_s1_flags - Intel VT-d stage-1 page table
366+ * entry attributes
367+ * @IOMMU_VTD_S1_SRE: Supervisor request
368+ * @IOMMU_VTD_S1_EAFE: Extended access enable
369+ * @IOMMU_VTD_S1_WPE: Write protect enable
370+ */
371+enum iommu_hwpt_vtd_s1_flags {
372+ IOMMU_VTD_S1_SRE = 1 << 0,
373+ IOMMU_VTD_S1_EAFE = 1 << 1,
374+ IOMMU_VTD_S1_WPE = 1 << 2,
375+};
376+
377+/**
378+ * struct iommu_hwpt_vtd_s1 - Intel VT-d stage-1 page table
379+ * info (IOMMU_HWPT_DATA_VTD_S1)
380+ * @flags: Combination of enum iommu_hwpt_vtd_s1_flags
381+ * @pgtbl_addr: The base address of the stage-1 page table.
382+ * @addr_width: The address width of the stage-1 page table
383+ * @__reserved: Must be 0
384+ */
385+struct iommu_hwpt_vtd_s1 {
386+ __aligned_u64 flags;
387+ __aligned_u64 pgtbl_addr;
388+ __u32 addr_width;
389+ __u32 __reserved;
390+};
391+
392+/**
393+ * enum iommu_hwpt_data_type - IOMMU HWPT Data Type
394+ * @IOMMU_HWPT_DATA_NONE: no data
395+ * @IOMMU_HWPT_DATA_VTD_S1: Intel VT-d stage-1 page table
396+ */
397+enum iommu_hwpt_data_type {
398+ IOMMU_HWPT_DATA_NONE,
399+ IOMMU_HWPT_DATA_VTD_S1,
400+};
401+
350402 /**
351403 * struct iommu_hwpt_alloc - ioctl(IOMMU_HWPT_ALLOC)
352404 * @size: sizeof(struct iommu_hwpt_alloc)
353− * @flags: Must be 0
405+ * @flags: Combination of enum iommufd_hwpt_alloc_flags
354406 * @dev_id: The device to allocate this HWPT for
355− * @pt_id: The IOAS to connect this HWPT to
407+ * @pt_id: The IOAS or HWPT to connect this HWPT to
356408 * @out_hwpt_id: The ID of the new HWPT
357409 * @__reserved: Must be 0
410+ * @data_type: One of enum iommu_hwpt_data_type
411+ * @data_len: Length of the type specific data
412+ * @data_uptr: User pointer to the type specific data
358413 *
359414 * Explicitly allocate a hardware page table object. This is the same object
360415 * type that is returned by iommufd_device_attach() and represents the
361416 * underlying iommu driver's iommu_domain kernel object.
362417 *
363− * A HWPT will be created with the IOVA mappings from the given IOAS.
418+ * A kernel-managed HWPT will be created with the mappings from the given
419+ * IOAS via the @pt_id. The @data_type for this allocation must be set to
420+ * IOMMU_HWPT_DATA_NONE. The HWPT can be allocated as a parent HWPT for a
421+ * nesting configuration by passing IOMMU_HWPT_ALLOC_NEST_PARENT via @flags.
422+ *
423+ * A user-managed nested HWPT will be created from a given parent HWPT via
424+ * @pt_id, in which the parent HWPT must be allocated previously via the
425+ * same ioctl from a given IOAS (@pt_id). In this case, the @data_type
426+ * must be set to a pre-defined type corresponding to an I/O page table
427+ * type supported by the underlying IOMMU hardware.
428+ *
429+ * If the @data_type is set to IOMMU_HWPT_DATA_NONE, @data_len and
430+ * @data_uptr should be zero. Otherwise, both @data_len and @data_uptr
431+ * must be given.
364432 */
365433 struct iommu_hwpt_alloc {
366434 __u32 size;
@@ -369,13 +437,26 @@ struct iommu_hwpt_alloc { · 2 unmodified lines
369437 __u32 pt_id;
370438 __u32 out_hwpt_id;
371439 __u32 __reserved;
440+ __u32 data_type;
441+ __u32 data_len;
442+ __aligned_u64 data_uptr;
372443 };
373444 #define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)
374445
446+/**
447+ * enum iommu_hw_info_vtd_flags - Flags for VT-d hw_info
448+ * @IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17: If set, disallow read-only mappings
449+ * on a nested_parent domain.
450+ * https://www.intel.com/content/www/us/en/content-details/772415/content-details.html
451+ */
452+enum iommu_hw_info_vtd_flags {
453+ IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17 = 1 << 0,
454+};
455+
375456 /**
376457 * struct iommu_hw_info_vtd - Intel VT-d hardware information
377458 *
378− * @flags: Must be 0
459+ * @flags: Combination of enum iommu_hw_info_vtd_flags
379460 * @__reserved: Must be 0
380461 *
381462 * @cap_reg: Value of Intel VT-d capability register defined in VT-d spec
@@ -404,6 +485,20 @@ enum iommu_hw_info_type { · 22 unmodified lines
404485 IOMMU_HW_INFO_TYPE_INTEL_VTD,
405486 };
406487
488+/**
489+ * enum iommufd_hw_capabilities
490+ * @IOMMU_HW_CAP_DIRTY_TRACKING: IOMMU hardware support for dirty tracking
491+ * If available, it means the following APIs
492+ * are supported:
493+ *
494+ * IOMMU_HWPT_GET_DIRTY_BITMAP
495+ * IOMMU_HWPT_SET_DIRTY_TRACKING
496+ *
497+ */
498+enum iommufd_hw_capabilities {
499+ IOMMU_HW_CAP_DIRTY_TRACKING = 1 << 0,
500+};
501+
407502 /**
408503 * struct iommu_hw_info - ioctl(IOMMU_GET_HW_INFO)
409504 * @size: sizeof(struct iommu_hw_info)
@@ -415,6 +510,8 @@ enum iommu_hw_info_type { · 5 unmodified lines
415510 * the iommu type specific hardware information data
416511 * @out_data_type: Output the iommu hardware info type as defined in the enum
417512 * iommu_hw_info_type.
513+ * @out_capabilities: Output the generic iommu capability info type as defined
514+ * in the enum iommu_hw_capabilities.
418515 * @__reserved: Must be 0
419516 *
420517 * Query an iommu type specific hardware information data from an iommu behind
@@ -439,6 +536,81 @@ struct iommu_hw_info { · 18 unmodified lines
439536 __aligned_u64 data_uptr;
440537 __u32 out_data_type;
441538 __u32 __reserved;
539+ __aligned_u64 out_capabilities;
442540 };
443541 #define IOMMU_GET_HW_INFO _IO(IOMMUFD_TYPE, IOMMUFD_CMD_GET_HW_INFO)
542+
543+/*
544+ * enum iommufd_hwpt_set_dirty_tracking_flags - Flags for steering dirty
545+ * tracking
546+ * @IOMMU_HWPT_DIRTY_TRACKING_ENABLE: Enable dirty tracking
547+ */
548+enum iommufd_hwpt_set_dirty_tracking_flags {
549+ IOMMU_HWPT_DIRTY_TRACKING_ENABLE = 1,
550+};
551+
552+/**
553+ * struct iommu_hwpt_set_dirty_tracking - ioctl(IOMMU_HWPT_SET_DIRTY_TRACKING)
554+ * @size: sizeof(struct iommu_hwpt_set_dirty_tracking)
555+ * @flags: Combination of enum iommufd_hwpt_set_dirty_tracking_flags
556+ * @hwpt_id: HW pagetable ID that represents the IOMMU domain
557+ * @__reserved: Must be 0
558+ *
559+ * Toggle dirty tracking on an HW pagetable.
560+ */
561+struct iommu_hwpt_set_dirty_tracking {
562+ __u32 size;
563+ __u32 flags;
564+ __u32 hwpt_id;
565+ __u32 __reserved;
566+};
567+#define IOMMU_HWPT_SET_DIRTY_TRACKING _IO(IOMMUFD_TYPE, \
568+ IOMMUFD_CMD_HWPT_SET_DIRTY_TRACKING)
569+
570+/**
571+ * enum iommufd_hwpt_get_dirty_bitmap_flags - Flags for getting dirty bits
572+ * @IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR: Just read the PTEs without clearing
573+ * any dirty bits metadata. This flag
574+ * can be passed in the expectation
575+ * where the next operation is an unmap
576+ * of the same IOVA range.
577+ *
578+ */
579+enum iommufd_hwpt_get_dirty_bitmap_flags {
580+ IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR = 1,
581+};
582+
583+/**
584+ * struct iommu_hwpt_get_dirty_bitmap - ioctl(IOMMU_HWPT_GET_DIRTY_BITMAP)
585+ * @size: sizeof(struct iommu_hwpt_get_dirty_bitmap)
586+ * @hwpt_id: HW pagetable ID that represents the IOMMU domain
587+ * @flags: Combination of enum iommufd_hwpt_get_dirty_bitmap_flags
588+ * @__reserved: Must be 0
589+ * @iova: base IOVA of the bitmap first bit
590+ * @length: IOVA range size
591+ * @page_size: page size granularity of each bit in the bitmap
592+ * @data: bitmap where to set the dirty bits. The bitmap bits each
593+ * represent a page_size which you deviate from an arbitrary iova.
594+ *
595+ * Checking a given IOVA is dirty:
596+ *
597+ * data[(iova / page_size) / 64] & (1ULL << ((iova / page_size) % 64))
598+ *
599+ * Walk the IOMMU pagetables for a given IOVA range to return a bitmap
600+ * with the dirty IOVAs. In doing so it will also by default clear any
601+ * dirty bit metadata set in the IOPTE.
602+ */
603+struct iommu_hwpt_get_dirty_bitmap {
604+ __u32 size;
605+ __u32 hwpt_id;
606+ __u32 flags;
607+ __u32 __reserved;
608+ __aligned_u64 iova;
609+ __aligned_u64 length;
610+ __aligned_u64 page_size;
611+ __aligned_u64 data;
612+};
613+#define IOMMU_HWPT_GET_DIRTY_BITMAP _IO(IOMMUFD_TYPE, \
614+ IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP)
615+
444616 #endif