iommupt: Add a mock pagetable format for iommufd selftest to use

The iommufd self test uses an xarray to store the pfns and their orders to
emulate a page table. Slightly modify the amdv1 page table to create a
real page table that has similar properties:

 - 2k base granule to simulate something like a 4k page table on a 64K
   PAGE_SIZE ARM system
 - Contiguous page support for every PFN order
 - Dirty tracking

AMDv1 is the closest format, as it is the only one that already supports
every page size. Tweak it to have only 5 levels and an 11 bit base granule
and compile it separately as a format variant.

Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Samiullah Khawaja <skhawaja@google.com>
Tested-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
Tested-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
This commit is contained in:
Jason Gunthorpe
2025-11-04 14:30:08 -04:00
committed by Joerg Roedel
parent 1dd4187f53
commit e5359dcc61
4 changed files with 33 additions and 2 deletions

View File

@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
iommu_pt_fmt-$(CONFIG_IOMMU_PT_AMDV1) += amdv1
iommu_pt_fmt-$(CONFIG_IOMMUFD_TEST) += mock
IOMMU_PT_KUNIT_TEST :=
define create_format

View File

@@ -26,11 +26,23 @@
#include <linux/string.h>
enum {
PT_MAX_OUTPUT_ADDRESS_LG2 = 52,
PT_MAX_VA_ADDRESS_LG2 = 64,
PT_ITEM_WORD_SIZE = sizeof(u64),
/*
* The IOMMUFD selftest uses the AMDv1 format with some alterations It
* uses a 2k page size to test cases where the CPU page size is not the
* same.
*/
#ifdef AMDV1_IOMMUFD_SELFTEST
PT_MAX_VA_ADDRESS_LG2 = 56,
PT_MAX_OUTPUT_ADDRESS_LG2 = 51,
PT_MAX_TOP_LEVEL = 4,
PT_GRANULE_LG2SZ = 11,
#else
PT_MAX_VA_ADDRESS_LG2 = 64,
PT_MAX_OUTPUT_ADDRESS_LG2 = 52,
PT_MAX_TOP_LEVEL = 5,
PT_GRANULE_LG2SZ = 12,
#endif
PT_TABLEMEM_LG2SZ = 12,
/* The DTE only has these bits for the top phyiscal address */
@@ -374,6 +386,7 @@ static inline int amdv1pt_iommu_fmt_init(struct pt_iommu_amdv1 *iommu_table,
}
#define pt_iommu_fmt_init amdv1pt_iommu_fmt_init
#ifndef PT_FMT_VARIANT
static inline void
amdv1pt_iommu_fmt_hw_info(struct pt_iommu_amdv1 *table,
const struct pt_range *top_range,
@@ -384,6 +397,7 @@ amdv1pt_iommu_fmt_hw_info(struct pt_iommu_amdv1 *table,
info->mode = top_range->top_level + 1;
}
#define pt_iommu_fmt_hw_info amdv1pt_iommu_fmt_hw_info
#endif
#if defined(GENERIC_PT_KUNIT)
static const struct pt_iommu_amdv1_cfg amdv1_kunit_fmt_cfgs[] = {

View File

@@ -0,0 +1,10 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2024-2025, NVIDIA CORPORATION & AFFILIATES
*/
#define AMDV1_IOMMUFD_SELFTEST 1
#define PT_FMT amdv1
#define PT_FMT_VARIANT mock
#define PT_SUPPORTED_FEATURES 0
#include "iommu_template.h"

View File

@@ -237,6 +237,12 @@ struct pt_iommu_amdv1_hw_info {
IOMMU_FORMAT(amdv1, amdpt);
/* amdv1_mock is used by the iommufd selftest */
#define pt_iommu_amdv1_mock pt_iommu_amdv1
#define pt_iommu_amdv1_mock_cfg pt_iommu_amdv1_cfg
struct pt_iommu_amdv1_mock_hw_info;
IOMMU_PROTOTYPES(amdv1_mock);
#undef IOMMU_PROTOTYPES
#undef IOMMU_FORMAT
#endif