!205 [next] Zhaoxin: iommu/vt-d: Add support for detecting ACPI namespace device in RMRR

Merge pull request !205 from LeoLiu-oc/next-6.6-22-iommu
This commit is contained in:
刘诗 2024-08-16 00:45:32 +00:00 committed by Gitee
commit 389e22e6a7
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
6 changed files with 172 additions and 2 deletions

View File

@ -562,6 +562,25 @@ resv_iova:
return 0;
}
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)
{

View File

@ -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,7 +847,11 @@ static int __init dmar_acpi_dev_scope_init(void)
andd->device_name);
continue;
}
dmar_acpi_insert_dev_scope(andd->device_number, adev);
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);
}
}
return 0;

View File

@ -3468,6 +3468,24 @@ out:
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;
@ -3726,6 +3744,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_to_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;
@ -3748,6 +3803,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;
}

View File

@ -1103,7 +1103,8 @@ map_end:
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))
@ -1171,6 +1172,16 @@ err_free_device:
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)

View File

@ -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;

View File

@ -586,6 +586,21 @@ void iommu_set_dma_strict(void);
extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
unsigned long iova, int flags);
static inline bool apply_zhaoxin_dmar_acpi_a_behavior(void)
{
#if defined(CONFIG_CPU_SUP_ZHAOXIN) || defined(CONFIG_CPU_SUP_CENTAUR)
if (((boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR) ||
(boot_cpu_data.x86_vendor == X86_VENDOR_ZHAOXIN)) &&
((boot_cpu_data.x86 == 7) && (boot_cpu_data.x86_model == 0x3b)))
return true;
#endif
return false;
}
extern int iova_reserve_domain_addr(struct iommu_domain *domain, dma_addr_t start, dma_addr_t end);
int __acpi_rmrr_device_create_direct_mappings(struct iommu_domain *domain, struct device *dev);
static inline void iommu_flush_iotlb_all(struct iommu_domain *domain)
{
if (domain->ops->flush_iotlb_all)