diff options
Diffstat (limited to 'drivers/iommu/amd/init.c')
| -rw-r--r-- | drivers/iommu/amd/init.c | 30 | 
1 files changed, 25 insertions, 5 deletions
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 19a46b9f7357..329a406cc37d 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -153,6 +153,8 @@ bool amd_iommu_dump;  bool amd_iommu_irq_remap __read_mostly;  enum io_pgtable_fmt amd_iommu_pgtable = AMD_IOMMU_V1; +/* Guest page table level */ +int amd_iommu_gpt_level = PAGE_MODE_4_LEVEL;  int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;  static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE; @@ -306,6 +308,11 @@ static bool check_feature_on_all_iommus(u64 mask)  	return !!(amd_iommu_efr & mask);  } +static inline int check_feature_gpt_level(void) +{ +	return ((amd_iommu_efr >> FEATURE_GATS_SHIFT) & FEATURE_GATS_MASK); +} +  /*   * For IVHD type 0x11/0x40, EFR is also available via IVHD.   * Default to IVHD EFR since it is available sooner @@ -1941,7 +1948,7 @@ static ssize_t amd_iommu_show_cap(struct device *dev,  				  char *buf)  {  	struct amd_iommu *iommu = dev_to_amd_iommu(dev); -	return sprintf(buf, "%x\n", iommu->cap); +	return sysfs_emit(buf, "%x\n", iommu->cap);  }  static DEVICE_ATTR(cap, S_IRUGO, amd_iommu_show_cap, NULL); @@ -1950,7 +1957,7 @@ static ssize_t amd_iommu_show_features(struct device *dev,  				       char *buf)  {  	struct amd_iommu *iommu = dev_to_amd_iommu(dev); -	return sprintf(buf, "%llx:%llx\n", iommu->features2, iommu->features); +	return sysfs_emit(buf, "%llx:%llx\n", iommu->features2, iommu->features);  }  static DEVICE_ATTR(features, S_IRUGO, amd_iommu_show_features, NULL); @@ -2155,8 +2162,10 @@ static void print_iommu_info(void)  		if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)  			pr_info("X2APIC enabled\n");  	} -	if (amd_iommu_pgtable == AMD_IOMMU_V2) -		pr_info("V2 page table enabled\n"); +	if (amd_iommu_pgtable == AMD_IOMMU_V2) { +		pr_info("V2 page table enabled (Paging mode : %d level)\n", +			amd_iommu_gpt_level); +	}  }  static int __init amd_iommu_init_pci(void) @@ -2383,6 +2392,7 @@ static int iommu_setup_intcapxt(struct amd_iommu *iommu)  	struct irq_domain *domain;  	struct irq_alloc_info info;  	int irq, ret; +	int node = dev_to_node(&iommu->dev->dev);  	domain = iommu_get_irqdomain();  	if (!domain) @@ -2392,7 +2402,7 @@ static int iommu_setup_intcapxt(struct amd_iommu *iommu)  	info.type = X86_IRQ_ALLOC_TYPE_AMDVI;  	info.data = iommu; -	irq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, &info); +	irq = irq_domain_alloc_irqs(domain, 1, node, &info);  	if (irq < 0) {  		irq_domain_remove(domain);  		return irq; @@ -3025,6 +3035,11 @@ static int __init early_amd_iommu_init(void)  	if (ret)  		goto out; +	/* 5 level guest page table */ +	if (cpu_feature_enabled(X86_FEATURE_LA57) && +	    check_feature_gpt_level() == GUEST_PGTABLE_5_LEVEL) +		amd_iommu_gpt_level = PAGE_MODE_5_LEVEL; +  	/* Disable any previously enabled IOMMUs */  	if (!is_kdump_kernel() || amd_iommu_disabled)  		disable_iommus(); @@ -3556,6 +3571,11 @@ __setup("ivrs_acpihid",		parse_ivrs_acpihid);  bool amd_iommu_v2_supported(void)  { +	/* CPU page table size should match IOMMU guest page table size */ +	if (cpu_feature_enabled(X86_FEATURE_LA57) && +	    amd_iommu_gpt_level != PAGE_MODE_5_LEVEL) +		return false; +  	/*  	 * Since DTE[Mode]=0 is prohibited on SNP-enabled system  	 * (i.e. EFR[SNPSup]=1), IOMMUv2 page table cannot be used without  |