#include <linux/anon_inodes.h>
#include <linux/debugfs.h>
#include <linux/fault-inject.h>
#include <linux/file.h>
#include <linux/iommu.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/xarray.h>
#include <uapi/linux/iommufd.h>
#include "../iommu-priv.h"
#include "io_pagetable.h"
#include "iommufd_private.h"
#include "iommufd_test.h"
static DECLARE_FAULT_ATTR(fail_iommufd);
static struct dentry *dbgfs_root;
static struct platform_device *selftest_iommu_dev;
static const struct iommu_ops mock_ops;
static struct iommu_domain_ops domain_nested_ops;
size_t iommufd_test_memory_limit = …;
struct mock_bus_type { … };
static struct mock_bus_type iommufd_mock_bus_type = …;
static DEFINE_IDA(mock_dev_ida);
enum { … };
static unsigned long __iommufd_test_syz_conv_iova(struct io_pagetable *iopt,
u64 *iova)
{ … }
static unsigned long iommufd_test_syz_conv_iova(struct iommufd_access *access,
u64 *iova)
{ … }
void iommufd_test_syz_conv_iova_id(struct iommufd_ucmd *ucmd,
unsigned int ioas_id, u64 *iova, u32 *flags)
{ … }
struct mock_iommu_domain { … };
struct mock_iommu_domain_nested { … };
enum selftest_obj_type { … };
struct mock_dev { … };
struct selftest_obj { … };
static int mock_domain_nop_attach(struct iommu_domain *domain,
struct device *dev)
{ … }
static const struct iommu_domain_ops mock_blocking_ops = …;
static struct iommu_domain mock_blocking_domain = …;
static void *mock_domain_hw_info(struct device *dev, u32 *length, u32 *type)
{ … }
static int mock_domain_set_dirty_tracking(struct iommu_domain *domain,
bool enable)
{ … }
static bool mock_test_and_clear_dirty(struct mock_iommu_domain *mock,
unsigned long iova, size_t page_size,
unsigned long flags)
{ … }
static int mock_domain_read_and_clear_dirty(struct iommu_domain *domain,
unsigned long iova, size_t size,
unsigned long flags,
struct iommu_dirty_bitmap *dirty)
{ … }
static const struct iommu_dirty_ops dirty_ops = …;
static struct iommu_domain *mock_domain_alloc_paging(struct device *dev)
{ … }
static struct iommu_domain *
__mock_domain_alloc_nested(struct mock_iommu_domain *mock_parent,
const struct iommu_hwpt_selftest *user_cfg)
{ … }
static struct iommu_domain *
mock_domain_alloc_user(struct device *dev, u32 flags,
struct iommu_domain *parent,
const struct iommu_user_data *user_data)
{ … }
static void mock_domain_free(struct iommu_domain *domain)
{ … }
static int mock_domain_map_pages(struct iommu_domain *domain,
unsigned long iova, phys_addr_t paddr,
size_t pgsize, size_t pgcount, int prot,
gfp_t gfp, size_t *mapped)
{ … }
static size_t mock_domain_unmap_pages(struct iommu_domain *domain,
unsigned long iova, size_t pgsize,
size_t pgcount,
struct iommu_iotlb_gather *iotlb_gather)
{ … }
static phys_addr_t mock_domain_iova_to_phys(struct iommu_domain *domain,
dma_addr_t iova)
{ … }
static bool mock_domain_capable(struct device *dev, enum iommu_cap cap)
{ … }
static struct iopf_queue *mock_iommu_iopf_queue;
static struct iommu_device mock_iommu_device = …;
static struct iommu_device *mock_probe_device(struct device *dev)
{ … }
static void mock_domain_page_response(struct device *dev, struct iopf_fault *evt,
struct iommu_page_response *msg)
{ … }
static int mock_dev_enable_feat(struct device *dev, enum iommu_dev_features feat)
{ … }
static int mock_dev_disable_feat(struct device *dev, enum iommu_dev_features feat)
{ … }
static const struct iommu_ops mock_ops = …;
static void mock_domain_free_nested(struct iommu_domain *domain)
{ … }
static int
mock_domain_cache_invalidate_user(struct iommu_domain *domain,
struct iommu_user_data_array *array)
{ … }
static struct iommu_domain_ops domain_nested_ops = …;
static inline struct iommufd_hw_pagetable *
__get_md_pagetable(struct iommufd_ucmd *ucmd, u32 mockpt_id, u32 hwpt_type)
{ … }
static inline struct iommufd_hw_pagetable *
get_md_pagetable(struct iommufd_ucmd *ucmd, u32 mockpt_id,
struct mock_iommu_domain **mock)
{ … }
static inline struct iommufd_hw_pagetable *
get_md_pagetable_nested(struct iommufd_ucmd *ucmd, u32 mockpt_id,
struct mock_iommu_domain_nested **mock_nested)
{ … }
static void mock_dev_release(struct device *dev)
{ … }
static struct mock_dev *mock_dev_create(unsigned long dev_flags)
{ … }
static void mock_dev_destroy(struct mock_dev *mdev)
{ … }
bool iommufd_selftest_is_mock_dev(struct device *dev)
{ … }
static int iommufd_test_mock_domain(struct iommufd_ucmd *ucmd,
struct iommu_test_cmd *cmd)
{ … }
static int iommufd_test_mock_domain_replace(struct iommufd_ucmd *ucmd,
unsigned int device_id, u32 pt_id,
struct iommu_test_cmd *cmd)
{ … }
static int iommufd_test_add_reserved(struct iommufd_ucmd *ucmd,
unsigned int mockpt_id,
unsigned long start, size_t length)
{ … }
static int iommufd_test_md_check_pa(struct iommufd_ucmd *ucmd,
unsigned int mockpt_id, unsigned long iova,
size_t length, void __user *uptr)
{ … }
static int iommufd_test_md_check_refs(struct iommufd_ucmd *ucmd,
void __user *uptr, size_t length,
unsigned int refs)
{ … }
static int iommufd_test_md_check_iotlb(struct iommufd_ucmd *ucmd,
u32 mockpt_id, unsigned int iotlb_id,
u32 iotlb)
{ … }
struct selftest_access { … };
struct selftest_access_item { … };
static const struct file_operations iommfd_test_staccess_fops;
static struct selftest_access *iommufd_access_get(int fd)
{ … }
static void iommufd_test_access_unmap(void *data, unsigned long iova,
unsigned long length)
{ … }
static int iommufd_test_access_item_destroy(struct iommufd_ucmd *ucmd,
unsigned int access_id,
unsigned int item_id)
{ … }
static int iommufd_test_staccess_release(struct inode *inode,
struct file *filep)
{ … }
static const struct iommufd_access_ops selftest_access_ops_pin = …;
static const struct iommufd_access_ops selftest_access_ops = …;
static const struct file_operations iommfd_test_staccess_fops = …;
static struct selftest_access *iommufd_test_alloc_access(void)
{ … }
static int iommufd_test_create_access(struct iommufd_ucmd *ucmd,
unsigned int ioas_id, unsigned int flags)
{ … }
static int iommufd_test_access_replace_ioas(struct iommufd_ucmd *ucmd,
unsigned int access_id,
unsigned int ioas_id)
{ … }
static int iommufd_test_check_pages(void __user *uptr, struct page **pages,
size_t npages)
{ … }
static int iommufd_test_access_pages(struct iommufd_ucmd *ucmd,
unsigned int access_id, unsigned long iova,
size_t length, void __user *uptr,
u32 flags)
{ … }
static int iommufd_test_access_rw(struct iommufd_ucmd *ucmd,
unsigned int access_id, unsigned long iova,
size_t length, void __user *ubuf,
unsigned int flags)
{ … }
static_assert(…);
static_assert(…);
static int iommufd_test_dirty(struct iommufd_ucmd *ucmd, unsigned int mockpt_id,
unsigned long iova, size_t length,
unsigned long page_size, void __user *uptr,
u32 flags)
{ … }
static int iommufd_test_trigger_iopf(struct iommufd_ucmd *ucmd,
struct iommu_test_cmd *cmd)
{ … }
void iommufd_selftest_destroy(struct iommufd_object *obj)
{ … }
int iommufd_test(struct iommufd_ucmd *ucmd)
{ … }
bool iommufd_should_fail(void)
{ … }
int __init iommufd_test_init(void)
{ … }
void iommufd_test_exit(void)
{ … }