Re: [kvm-unit-tests PATCH] x86/intel-iommu: add test for address width 48 and 57.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Nov 09, 2018 at 08:02:40PM +0800, Yu Zhang wrote:
> Current iommu test only covers 39-bit address width. This patch
> extends the test case to based on the supported maximum guest
> address width.
> 
> Signed-off-by: Yu Zhang <yu.c.zhang@xxxxxxxxxxxxxxx>


Reviewed-by: Michael S. Tsirkin <mst@xxxxxxxxxx>

> ---
>  lib/x86/intel-iommu.c | 14 ++++----------
>  lib/x86/intel-iommu.h | 11 ++++++++++-
>  x86/intel-iommu.c     | 21 ++++++++++++++++-----
>  3 files changed, 30 insertions(+), 16 deletions(-)
> 
> diff --git a/lib/x86/intel-iommu.c b/lib/x86/intel-iommu.c
> index 3f3f211..e1ea9d2 100644
> --- a/lib/x86/intel-iommu.c
> +++ b/lib/x86/intel-iommu.c
> @@ -16,13 +16,6 @@
>  #include "atomic.h"
>  #include "alloc_page.h"
>  
> -/*
> - * VT-d in QEMU currently only support 39 bits address width, which is
> - * 3-level translation.
> - */
> -#define VTD_PAGE_LEVEL      3
> -#define VTD_CE_AW_39BIT     0x1
> -
>  typedef uint64_t vtd_pte_t;
>  
>  struct vtd_root_entry {
> @@ -75,6 +68,8 @@ typedef struct vtd_irte vtd_irte_t;
>  #define VTD_IRTA_MASK (PAGE_MASK)
>  
>  void *vtd_reg_base;
> +uint8_t max_gaw;
> +uint8_t max_page_level;
>  
>  static uint64_t vtd_root_table(void)
>  {
> @@ -149,7 +144,7 @@ static void vtd_install_pte(vtd_pte_t *root, iova_t iova,
>  	unsigned int offset;
>  	void *page;
>  
> -	for (level = VTD_PAGE_LEVEL; level > level_target; level--) {
> +	for (level = max_page_level; level > level_target; level--) {
>  		offset = PGDIR_OFFSET(iova, level);
>  		if (!(root[offset] & VTD_PTE_RW)) {
>  			page = alloc_page();
> @@ -213,8 +208,7 @@ void vtd_map_range(uint16_t sid, iova_t iova, phys_addr_t pa, size_t size)
>  		memset(ce, 0, sizeof(*ce));
>  		/* To make it simple, domain ID is the same as SID */
>  		ce->domain_id = sid;
> -		/* We only test 39 bits width case (3-level paging) */
> -		ce->addr_width = VTD_CE_AW_39BIT;
> +		ce->addr_width = max_page_level - 2;
>  		ce->slptptr = virt_to_phys(slptptr) >> VTD_PAGE_SHIFT;
>  		ce->trans_type = VTD_CONTEXT_TT_MULTI_LEVEL;
>  		ce->present = 1;
> diff --git a/lib/x86/intel-iommu.h b/lib/x86/intel-iommu.h
> index 05b9744..7057417 100644
> --- a/lib/x86/intel-iommu.h
> +++ b/lib/x86/intel-iommu.h
> @@ -26,6 +26,7 @@
>  #define Q35_HOST_BRIDGE_IOMMU_ADDR  0xfed90000ULL
>  #define VTD_PAGE_SHIFT              PAGE_SHIFT
>  #define VTD_PAGE_SIZE               PAGE_SIZE
> +#define VTD_PAGE_LEVEL_STRIDE       9
>  
>  /*
>   * Intel IOMMU register specification
> @@ -100,7 +101,13 @@
>  #define VTD_CAP_SAGAW_39bit         (0x2ULL << VTD_CAP_SAGAW_SHIFT)
>  /* 48-bit AGAW, 4-level page-table */
>  #define VTD_CAP_SAGAW_48bit         (0x4ULL << VTD_CAP_SAGAW_SHIFT)
> -#define VTD_CAP_SAGAW               VTD_CAP_SAGAW_39bit
> +/* 57-bit AGAW, 5-level page-table */
> +#define VTD_CAP_SAGAW_57bit         (0x8ULL << VTD_CAP_SAGAW_SHIFT)
> +#define VTD_CAP_SAGAW(cap)          (((cap) >> VTD_CAP_SAGAW_SHIFT) & 0x1fULL)
> +
> +/* Maximum Guest Address Widths */
> +#define VTD_CAP_MGAW_SHIFT    16
> +#define VTD_CAP_MGAW(cap)     ((((cap) >> VTD_CAP_MGAW_SHIFT) & 0x3fULL) + 1)
>  
>  /* Both 1G/2M huge pages */
>  #define VTD_CAP_SLLPS               ((1ULL << 34) | (1ULL << 35))
> @@ -118,6 +125,8 @@
>  extern void *vtd_reg_base;
>  #define vtd_reg(reg) ({ assert(vtd_reg_base); \
>  			(volatile void *)(vtd_reg_base + reg); })
> +extern  uint8_t max_gaw;
> +extern  uint8_t max_page_level;
>  
>  static inline void vtd_writel(unsigned int reg, uint32_t value)
>  {
> diff --git a/x86/intel-iommu.c b/x86/intel-iommu.c
> index f24170d..9d2194d 100644
> --- a/x86/intel-iommu.c
> +++ b/x86/intel-iommu.c
> @@ -132,25 +132,36 @@ static void vtd_test_ir(void)
>  
>  int main(int argc, char *argv[])
>  {
> +	uint64_t dmar_cap;
> +	uint8_t sagaw;
> +
>  	setup_vm();
>  	smp_init();
> -
>  	vtd_init();
>  
>  	report_prefix_push("vtd_init");
> -
>  	report("fault status check", vtd_readl(DMAR_FSTS_REG) == 0);
>  	report("QI enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_QI);
>  	report("DMAR table setup", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_ROOT);
>  	report("IR table setup", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR_TABLE);
>  	report("DMAR enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_DMAR);
>  	report("IR enablement", vtd_readl(DMAR_GSTS_REG) & VTD_GCMD_IR);
> -	report("DMAR support 39 bits address width",
> -	       vtd_readq(DMAR_CAP_REG) & VTD_CAP_SAGAW);
>  	report("DMAR support huge pages", vtd_readq(DMAR_CAP_REG) & VTD_CAP_SLLPS);
> -
>  	report_prefix_pop();
>  
> +	dmar_cap = vtd_readq(DMAR_CAP_REG);
> +	max_gaw = VTD_CAP_MGAW(dmar_cap);
> +	sagaw = VTD_CAP_SAGAW(dmar_cap);
> +	max_page_level = (max_gaw - VTD_PAGE_SHIFT)/VTD_PAGE_LEVEL_STRIDE;
> +
> +	report("address width check", ((1 << (max_page_level - 2)) & sagaw));
> +	if (dmar_cap & VTD_CAP_SAGAW_39bit)
> +		printf("DMAR supports 39 bits address width.\n");
> +	if (dmar_cap & VTD_CAP_SAGAW_48bit)
> +		printf("DMAR supports 48 bits address width.\n");
> +	if (dmar_cap & VTD_CAP_SAGAW_57bit)
> +		printf("DMAR supports 57 bits address width.\n");
> +
>  	if (!edu_init(&edu_dev)) {
>  		printf("Please specify \"-device edu\" to do "
>  		       "further IOMMU tests.\n");
> -- 
> 1.9.1



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux