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
47 IOMMUFD_CMD_VFIO_IOAS,47 IOMMUFD_CMD_VFIO_IOAS,
48 IOMMUFD_CMD_HWPT_ALLOC,48 IOMMUFD_CMD_HWPT_ALLOC,
49 IOMMUFD_CMD_GET_HW_INFO,49 IOMMUFD_CMD_GET_HW_INFO,
50 IOMMUFD_CMD_HWPT_SET_DIRTY_TRACKING,
51 IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP,
50};52};
51 53
52/**54/**
@@ -347,20 +349,86 @@ struct iommu_vfio_ioas { · 294 unmodified lines
347};349};
348#define IOMMU_VFIO_IOAS _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VFIO_IOAS)350#define IOMMU_VFIO_IOAS _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VFIO_IOAS)
349 351
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 */
359enum 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 */
371enum 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 */
385struct 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 */
397enum iommu_hwpt_data_type {
398 IOMMU_HWPT_DATA_NONE,
399 IOMMU_HWPT_DATA_VTD_S1,
400};
401
350/**402/**
351 * struct iommu_hwpt_alloc - ioctl(IOMMU_HWPT_ALLOC)403 * struct iommu_hwpt_alloc - ioctl(IOMMU_HWPT_ALLOC)
352 * @size: sizeof(struct iommu_hwpt_alloc)404 * @size: sizeof(struct iommu_hwpt_alloc)
353 * @flags: Must be 0405 * @flags: Combination of enum iommufd_hwpt_alloc_flags
354 * @dev_id: The device to allocate this HWPT for406 * @dev_id: The device to allocate this HWPT for
355 * @pt_id: The IOAS to connect this HWPT to407 * @pt_id: The IOAS or HWPT to connect this HWPT to
356 * @out_hwpt_id: The ID of the new HWPT408 * @out_hwpt_id: The ID of the new HWPT
357 * @__reserved: Must be 0409 * @__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
358 *413 *
359 * Explicitly allocate a hardware page table object. This is the same object414 * Explicitly allocate a hardware page table object. This is the same object
360 * type that is returned by iommufd_device_attach() and represents the415 * type that is returned by iommufd_device_attach() and represents the
361 * underlying iommu driver's iommu_domain kernel object.416 * underlying iommu driver's iommu_domain kernel object.
362 *417 *
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.
364 */432 */
365struct iommu_hwpt_alloc {433struct iommu_hwpt_alloc {
366 __u32 size;434 __u32 size;
@@ -369,13 +437,26 @@ struct iommu_hwpt_alloc { · 2 unmodified lines
369 __u32 pt_id;437 __u32 pt_id;
370 __u32 out_hwpt_id;438 __u32 out_hwpt_id;
371 __u32 __reserved;439 __u32 __reserved;
440 __u32 data_type;
441 __u32 data_len;
442 __aligned_u64 data_uptr;
372};443};
373#define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)444#define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC)
374 445
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 */
452enum iommu_hw_info_vtd_flags {
453 IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17 = 1 << 0,
454};
455
375/**456/**
376 * struct iommu_hw_info_vtd - Intel VT-d hardware information457 * struct iommu_hw_info_vtd - Intel VT-d hardware information
377 *458 *
378 * @flags: Must be 0459 * @flags: Combination of enum iommu_hw_info_vtd_flags
379 * @__reserved: Must be 0460 * @__reserved: Must be 0
380 *461 *
381 * @cap_reg: Value of Intel VT-d capability register defined in VT-d spec462 * @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
404 IOMMU_HW_INFO_TYPE_INTEL_VTD,485 IOMMU_HW_INFO_TYPE_INTEL_VTD,
405};486};
406 487
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 */
498enum iommufd_hw_capabilities {
499 IOMMU_HW_CAP_DIRTY_TRACKING = 1 << 0,
500};
501
407/**502/**
408 * struct iommu_hw_info - ioctl(IOMMU_GET_HW_INFO)503 * struct iommu_hw_info - ioctl(IOMMU_GET_HW_INFO)
409 * @size: sizeof(struct iommu_hw_info)504 * @size: sizeof(struct iommu_hw_info)
@@ -415,6 +510,8 @@ enum iommu_hw_info_type { · 5 unmodified lines
415 * the iommu type specific hardware information data510 * the iommu type specific hardware information data
416 * @out_data_type: Output the iommu hardware info type as defined in the enum511 * @out_data_type: Output the iommu hardware info type as defined in the enum
417 * iommu_hw_info_type.512 * iommu_hw_info_type.
513 * @out_capabilities: Output the generic iommu capability info type as defined
514 * in the enum iommu_hw_capabilities.
418 * @__reserved: Must be 0515 * @__reserved: Must be 0
419 *516 *
420 * Query an iommu type specific hardware information data from an iommu behind517 * Query an iommu type specific hardware information data from an iommu behind
@@ -439,6 +536,81 @@ struct iommu_hw_info { · 18 unmodified lines
439 __aligned_u64 data_uptr;536 __aligned_u64 data_uptr;
440 __u32 out_data_type;537 __u32 out_data_type;
441 __u32 __reserved;538 __u32 __reserved;
539 __aligned_u64 out_capabilities;
442};540};
443#define IOMMU_GET_HW_INFO _IO(IOMMUFD_TYPE, IOMMUFD_CMD_GET_HW_INFO)541#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 */
548enum 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 */
561struct 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 */
579enum 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 */
603struct 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
444#endif616#endif