Unverified Commit ea2dca63 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!3133 [OLK-6.6] iommu/vt-d:Add support for detecting ACPI device in RMRR

Merge Pull Request from: @leoliu-oc 
 
Some ACPI devices need to issue dma requests to access the reserved memory area. BIOS uses the device scope type ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices. This patch add support for detecting ACPI
devices in RMRR and in order to distinguish it from PCI device, some interface functions are modified.

### Issue
https://gitee.com/openeuler/kernel/issues/I8WY3L

### Test
Pass: RMRR devices is correctly identified
 
 
Link:https://gitee.com/openeuler/kernel/pulls/3133

 

Reviewed-by: default avatarJason Zeng <jason.zeng@intel.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents 4da472bb 40c9fc02
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -584,6 +584,25 @@ static int iova_reserve_pci_regions(struct device *dev,
	return ret;
}

int iova_reserve_domain_addr(struct iommu_domain *domain, dma_addr_t start, dma_addr_t end)
{
	struct iommu_dma_cookie *cookie = domain->iova_cookie;
	struct iova_domain *iovad = &cookie->iovad;

	unsigned long lo, hi;

	lo = iova_pfn(iovad, start);
	hi = iova_pfn(iovad, end);

	if (!cookie)
		return -EINVAL;

	reserve_iova(iovad, lo, hi);

	return 0;
}
EXPORT_SYMBOL_GPL(iova_reserve_domain_addr);

static int iova_reserve_iommu_regions(struct device *dev,
		struct iommu_domain *domain)
{
+58 −1
Original line number Diff line number Diff line
@@ -767,6 +767,59 @@ static void __init dmar_acpi_insert_dev_scope(u8 device_number,
		device_number, dev_name(&adev->dev));
}

/* Return: > 0 if match found, 0 if no match found */
bool dmar_rmrr_acpi_insert_dev_scope(u8 device_number,
				struct acpi_device *adev,
				void *start, void *end,
				struct dmar_dev_scope *devices,
				int devices_cnt)
{
	struct acpi_dmar_device_scope *scope;
	struct device *tmp;
	int i;
	struct acpi_dmar_pci_path *path;

	for (; start < end; start += scope->length) {
		scope = start;
		if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
			continue;
		if (scope->enumeration_id != device_number)
			continue;
		path = (void *)(scope + 1);
		pr_info("ACPI device \"%s\" under DMAR as %02x:%02x.%d\n", dev_name(&adev->dev),
				scope->bus, path->device, path->function);
		for_each_dev_scope(devices, devices_cnt, i, tmp)
			if (tmp == NULL) {
				devices[i].bus = scope->bus;
				devices[i].devfn = PCI_DEVFN(path->device, path->function);
				rcu_assign_pointer(devices[i].dev, get_device(&adev->dev));
				return true;
			}
		WARN_ON(i >= devices_cnt);
	}
	return false;
}

static int dmar_acpi_bus_add_dev(u8 device_number, struct acpi_device *adev)
{
	struct dmar_drhd_unit *dmaru;
	struct acpi_dmar_hardware_unit *drhd;
	int ret;

	for_each_drhd_unit(dmaru) {
		drhd = container_of(dmaru->hdr, struct acpi_dmar_hardware_unit, header);
		ret = dmar_rmrr_acpi_insert_dev_scope(device_number, adev, (void *)(drhd+1),
						((void *)drhd)+drhd->header.length,
						dmaru->devices, dmaru->devices_cnt);
		if (ret)
			break;
	}
	if (ret > 0)
		ret = dmar_rmrr_add_acpi_dev(device_number, adev);

	return ret;
}

static int __init dmar_acpi_dev_scope_init(void)
{
	struct acpi_dmar_andd *andd;
@@ -794,6 +847,10 @@ static int __init dmar_acpi_dev_scope_init(void)
				       andd->device_name);
				continue;
			}

			if (apply_zhaoxin_dmar_acpi_a_behavior())
				dmar_acpi_bus_add_dev(andd->device_number, adev);
			else
				dmar_acpi_insert_dev_scope(andd->device_number, adev);
		}
	}
+59 −0
Original line number Diff line number Diff line
@@ -3333,6 +3333,24 @@ static int dmar_ats_supported(struct pci_dev *dev, struct intel_iommu *iommu)
	return ret;
}

int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev)
{
	int ret;
	struct dmar_rmrr_unit *rmrru;
	struct acpi_dmar_reserved_memory *rmrr;

	list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
		rmrr = container_of(rmrru->hdr, struct acpi_dmar_reserved_memory, header);
		ret = dmar_rmrr_acpi_insert_dev_scope(device_number, adev, (void *)(rmrr + 1),
					((void *)rmrr) + rmrr->header.length,
					rmrru->devices, rmrru->devices_cnt);
		if (ret)
			break;
	}

	return 0;
}

int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
{
	int ret;
@@ -3591,6 +3609,43 @@ static int __init platform_optin_force_iommu(void)
	return 1;
}

static inline int acpi_rmrr_device_create_direct_mappings(struct iommu_domain *domain,
				struct device *dev)
{
	int ret;

	pr_info("rmrr andd dev:%s enter to %s\n", dev_name(dev), __func__);
	ret = __acpi_rmrr_device_create_direct_mappings(domain, dev);

	return ret;
}

static inline int acpi_rmrr_andd_probe(struct device *dev)
{
	struct intel_iommu *iommu = NULL;
	struct pci_dev *pci_device = NULL;
	u8 bus, devfn;
	int ret = 0;

	ret = iommu_probe_device(dev);

	iommu = device_lookup_iommu(dev, &bus, &devfn);
	if (!iommu) {
		pr_info("dpoint-- cannot get acpi device corresponding iommu\n");
		return -EINVAL;
	}

	pci_device = pci_get_domain_bus_and_slot(iommu->segment, bus, devfn);
	if (!pci_device) {
		pr_info("dpoint-- cannot get acpi devie corresponding pci_device\n");
		return -EINVAL;
	}
	ret = acpi_rmrr_device_create_direct_mappings(iommu_get_domain_for_dev(&pci_device->dev),
			dev);

	return ret;
}

static int __init probe_acpi_namespace_devices(void)
{
	struct dmar_drhd_unit *drhd;
@@ -3613,6 +3668,10 @@ static int __init probe_acpi_namespace_devices(void)
			list_for_each_entry(pn,
					    &adev->physical_node_list, node) {
				ret = iommu_probe_device(pn->dev);

				if (apply_zhaoxin_dmar_acpi_a_behavior())
					ret = acpi_rmrr_andd_probe(dev);

				if (ret)
					break;
			}
+12 −1
Original line number Diff line number Diff line
@@ -1137,7 +1137,8 @@ static int iommu_create_device_direct_mappings(struct iommu_domain *domain,
				map_size = 0;
			}
		}

		if (apply_zhaoxin_dmar_acpi_a_behavior())
			iova_reserve_domain_addr(domain, start, end);
	}

	if (!list_empty(&mappings) && iommu_is_dma_domain(domain))
@@ -1205,6 +1206,16 @@ static struct group_device *iommu_group_alloc_device(struct iommu_group *group,
	return ERR_PTR(ret);
}

int __acpi_rmrr_device_create_direct_mappings(struct iommu_domain *domain, struct device *dev)
{
	int ret;

	ret = iommu_create_device_direct_mappings(domain, dev);

	return ret;
}
EXPORT_SYMBOL_GPL(__acpi_rmrr_device_create_direct_mappings);

/**
 * iommu_group_add_device - add a device to an iommu group
 * @group: the group into which to add the device (reference should be held)
+9 −0
Original line number Diff line number Diff line
@@ -112,6 +112,9 @@ extern int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
				 void *start, void*end, u16 segment,
				 struct dmar_dev_scope *devices,
				 int devices_cnt);
extern bool dmar_rmrr_acpi_insert_dev_scope(u8 device_number,
				struct acpi_device *adev, void *start, void *end,
				struct dmar_dev_scope *devices, int devices_cnt);
extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
				 u16 segment, struct dmar_dev_scope *devices,
				 int count);
@@ -144,6 +147,7 @@ extern int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg);
extern int dmar_parse_one_satc(struct acpi_dmar_header *hdr, void *arg);
extern int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg);
extern int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert);
extern int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev);
extern int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info);
#else /* !CONFIG_INTEL_IOMMU: */
static inline int intel_iommu_init(void) { return -ENODEV; }
@@ -155,6 +159,11 @@ static inline void intel_iommu_shutdown(void) { }
#define	dmar_release_one_atsr		dmar_res_noop
#define	dmar_parse_one_satc		dmar_res_noop

static inline int dmar_rmrr_add_acpi_dev(u8 device_number, struct acpi_device *adev)
{
	return 0;
}

static inline int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
{
	return 0;
Loading