aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2014-11-09 09:47:58 -0500
committerJoerg Roedel <jroedel@suse.de>2014-11-18 05:18:35 -0500
commit6b1972493a84f8fe13ff9d202745590f6c53d670 (patch)
treebb418163c4f1e0497bbc5b0b74c6159e03205610 /drivers/iommu
parent78d8e7046111425bb688cddc4303d79cb0f0d281 (diff)
iommu/vt-d: Implement DMAR unit hotplug framework
On Intel platforms, an IO Hub (PCI/PCIe host bridge) may contain DMAR units, so we need to support DMAR hotplug when supporting PCI host bridge hotplug on Intel platforms. According to Section 8.8 "Remapping Hardware Unit Hot Plug" in "Intel Virtualization Technology for Directed IO Architecture Specification Rev 2.2", ACPI BIOS should implement ACPI _DSM method under the ACPI object for the PCI host bridge to support DMAR hotplug. This patch introduces interfaces to parse ACPI _DSM method for DMAR unit hotplug. It also implements state machines for DMAR unit hot-addition and hot-removal. The PCI host bridge hotplug driver should call dmar_hotplug_hotplug() before scanning PCI devices connected for hot-addition and after destroying all PCI devices for hot-removal. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Reviewed-by: Yijing Wang <wangyijing@huawei.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/dmar.c268
-rw-r--r--drivers/iommu/intel-iommu.c78
-rw-r--r--drivers/iommu/intel_irq_remapping.c5
3 files changed, 337 insertions, 14 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 78aa1b2af113..0bd536d769a9 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -75,7 +75,7 @@ static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)];
75static int alloc_iommu(struct dmar_drhd_unit *drhd); 75static int alloc_iommu(struct dmar_drhd_unit *drhd);
76static void free_iommu(struct intel_iommu *iommu); 76static void free_iommu(struct intel_iommu *iommu);
77 77
78static void __init dmar_register_drhd_unit(struct dmar_drhd_unit *drhd) 78static void dmar_register_drhd_unit(struct dmar_drhd_unit *drhd)
79{ 79{
80 /* 80 /*
81 * add INCLUDE_ALL at the tail, so scan the list will find it at 81 * add INCLUDE_ALL at the tail, so scan the list will find it at
@@ -353,24 +353,45 @@ static struct notifier_block dmar_pci_bus_nb = {
353 .priority = INT_MIN, 353 .priority = INT_MIN,
354}; 354};
355 355
356static struct dmar_drhd_unit *
357dmar_find_dmaru(struct acpi_dmar_hardware_unit *drhd)
358{
359 struct dmar_drhd_unit *dmaru;
360
361 list_for_each_entry_rcu(dmaru, &dmar_drhd_units, list)
362 if (dmaru->segment == drhd->segment &&
363 dmaru->reg_base_addr == drhd->address)
364 return dmaru;
365
366 return NULL;
367}
368
356/** 369/**
357 * dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition 370 * dmar_parse_one_drhd - parses exactly one DMA remapping hardware definition
358 * structure which uniquely represent one DMA remapping hardware unit 371 * structure which uniquely represent one DMA remapping hardware unit
359 * present in the platform 372 * present in the platform
360 */ 373 */
361static int __init 374static int dmar_parse_one_drhd(struct acpi_dmar_header *header, void *arg)
362dmar_parse_one_drhd(struct acpi_dmar_header *header, void *arg)
363{ 375{
364 struct acpi_dmar_hardware_unit *drhd; 376 struct acpi_dmar_hardware_unit *drhd;
365 struct dmar_drhd_unit *dmaru; 377 struct dmar_drhd_unit *dmaru;
366 int ret = 0; 378 int ret = 0;
367 379
368 drhd = (struct acpi_dmar_hardware_unit *)header; 380 drhd = (struct acpi_dmar_hardware_unit *)header;
369 dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL); 381 dmaru = dmar_find_dmaru(drhd);
382 if (dmaru)
383 goto out;
384
385 dmaru = kzalloc(sizeof(*dmaru) + header->length, GFP_KERNEL);
370 if (!dmaru) 386 if (!dmaru)
371 return -ENOMEM; 387 return -ENOMEM;
372 388
373 dmaru->hdr = header; 389 /*
390 * If header is allocated from slab by ACPI _DSM method, we need to
391 * copy the content because the memory buffer will be freed on return.
392 */
393 dmaru->hdr = (void *)(dmaru + 1);
394 memcpy(dmaru->hdr, header, header->length);
374 dmaru->reg_base_addr = drhd->address; 395 dmaru->reg_base_addr = drhd->address;
375 dmaru->segment = drhd->segment; 396 dmaru->segment = drhd->segment;
376 dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */ 397 dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
@@ -391,6 +412,7 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header, void *arg)
391 } 412 }
392 dmar_register_drhd_unit(dmaru); 413 dmar_register_drhd_unit(dmaru);
393 414
415out:
394 if (arg) 416 if (arg)
395 (*(int *)arg)++; 417 (*(int *)arg)++;
396 418
@@ -428,8 +450,7 @@ static int __init dmar_parse_one_andd(struct acpi_dmar_header *header,
428} 450}
429 451
430#ifdef CONFIG_ACPI_NUMA 452#ifdef CONFIG_ACPI_NUMA
431static int __init 453static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg)
432dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg)
433{ 454{
434 struct acpi_dmar_rhsa *rhsa; 455 struct acpi_dmar_rhsa *rhsa;
435 struct dmar_drhd_unit *drhd; 456 struct dmar_drhd_unit *drhd;
@@ -821,14 +842,22 @@ dmar_validate_one_drhd(struct acpi_dmar_header *entry, void *arg)
821 return -EINVAL; 842 return -EINVAL;
822 } 843 }
823 844
824 addr = early_ioremap(drhd->address, VTD_PAGE_SIZE); 845 if (arg)
846 addr = ioremap(drhd->address, VTD_PAGE_SIZE);
847 else
848 addr = early_ioremap(drhd->address, VTD_PAGE_SIZE);
825 if (!addr) { 849 if (!addr) {
826 pr_warn("IOMMU: can't validate: %llx\n", drhd->address); 850 pr_warn("IOMMU: can't validate: %llx\n", drhd->address);
827 return -EINVAL; 851 return -EINVAL;
828 } 852 }
853
829 cap = dmar_readq(addr + DMAR_CAP_REG); 854 cap = dmar_readq(addr + DMAR_CAP_REG);
830 ecap = dmar_readq(addr + DMAR_ECAP_REG); 855 ecap = dmar_readq(addr + DMAR_ECAP_REG);
831 early_iounmap(addr, VTD_PAGE_SIZE); 856
857 if (arg)
858 iounmap(addr);
859 else
860 early_iounmap(addr, VTD_PAGE_SIZE);
832 861
833 if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) { 862 if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) {
834 warn_invalid_dmar(drhd->address, " returns all ones"); 863 warn_invalid_dmar(drhd->address, " returns all ones");
@@ -1702,12 +1731,17 @@ int __init dmar_ir_support(void)
1702 return dmar->flags & 0x1; 1731 return dmar->flags & 0x1;
1703} 1732}
1704 1733
1734/* Check whether DMAR units are in use */
1735static inline bool dmar_in_use(void)
1736{
1737 return irq_remapping_enabled || intel_iommu_enabled;
1738}
1739
1705static int __init dmar_free_unused_resources(void) 1740static int __init dmar_free_unused_resources(void)
1706{ 1741{
1707 struct dmar_drhd_unit *dmaru, *dmaru_n; 1742 struct dmar_drhd_unit *dmaru, *dmaru_n;
1708 1743
1709 /* DMAR units are in use */ 1744 if (dmar_in_use())
1710 if (irq_remapping_enabled || intel_iommu_enabled)
1711 return 0; 1745 return 0;
1712 1746
1713 if (dmar_dev_scope_status != 1 && !list_empty(&dmar_drhd_units)) 1747 if (dmar_dev_scope_status != 1 && !list_empty(&dmar_drhd_units))
@@ -1725,3 +1759,215 @@ static int __init dmar_free_unused_resources(void)
1725 1759
1726late_initcall(dmar_free_unused_resources); 1760late_initcall(dmar_free_unused_resources);
1727IOMMU_INIT_POST(detect_intel_iommu); 1761IOMMU_INIT_POST(detect_intel_iommu);
1762
1763/*
1764 * DMAR Hotplug Support
1765 * For more details, please refer to Intel(R) Virtualization Technology
1766 * for Directed-IO Architecture Specifiction, Rev 2.2, Section 8.8
1767 * "Remapping Hardware Unit Hot Plug".
1768 */
1769static u8 dmar_hp_uuid[] = {
1770 /* 0000 */ 0xA6, 0xA3, 0xC1, 0xD8, 0x9B, 0xBE, 0x9B, 0x4C,
1771 /* 0008 */ 0x91, 0xBF, 0xC3, 0xCB, 0x81, 0xFC, 0x5D, 0xAF
1772};
1773
1774/*
1775 * Currently there's only one revision and BIOS will not check the revision id,
1776 * so use 0 for safety.
1777 */
1778#define DMAR_DSM_REV_ID 0
1779#define DMAR_DSM_FUNC_DRHD 1
1780#define DMAR_DSM_FUNC_ATSR 2
1781#define DMAR_DSM_FUNC_RHSA 3
1782
1783static inline bool dmar_detect_dsm(acpi_handle handle, int func)
1784{
1785 return acpi_check_dsm(handle, dmar_hp_uuid, DMAR_DSM_REV_ID, 1 << func);
1786}
1787
1788static int dmar_walk_dsm_resource(acpi_handle handle, int func,
1789 dmar_res_handler_t handler, void *arg)
1790{
1791 int ret = -ENODEV;
1792 union acpi_object *obj;
1793 struct acpi_dmar_header *start;
1794 struct dmar_res_callback callback;
1795 static int res_type[] = {
1796 [DMAR_DSM_FUNC_DRHD] = ACPI_DMAR_TYPE_HARDWARE_UNIT,
1797 [DMAR_DSM_FUNC_ATSR] = ACPI_DMAR_TYPE_ROOT_ATS,
1798 [DMAR_DSM_FUNC_RHSA] = ACPI_DMAR_TYPE_HARDWARE_AFFINITY,
1799 };
1800
1801 if (!dmar_detect_dsm(handle, func))
1802 return 0;
1803
1804 obj = acpi_evaluate_dsm_typed(handle, dmar_hp_uuid, DMAR_DSM_REV_ID,
1805 func, NULL, ACPI_TYPE_BUFFER);
1806 if (!obj)
1807 return -ENODEV;
1808
1809 memset(&callback, 0, sizeof(callback));
1810 callback.cb[res_type[func]] = handler;
1811 callback.arg[res_type[func]] = arg;
1812 start = (struct acpi_dmar_header *)obj->buffer.pointer;
1813 ret = dmar_walk_remapping_entries(start, obj->buffer.length, &callback);
1814
1815 ACPI_FREE(obj);
1816
1817 return ret;
1818}
1819
1820static int dmar_hp_add_drhd(struct acpi_dmar_header *header, void *arg)
1821{
1822 int ret;
1823 struct dmar_drhd_unit *dmaru;
1824
1825 dmaru = dmar_find_dmaru((struct acpi_dmar_hardware_unit *)header);
1826 if (!dmaru)
1827 return -ENODEV;
1828
1829 ret = dmar_ir_hotplug(dmaru, true);
1830 if (ret == 0)
1831 ret = dmar_iommu_hotplug(dmaru, true);
1832
1833 return ret;
1834}
1835
1836static int dmar_hp_remove_drhd(struct acpi_dmar_header *header, void *arg)
1837{
1838 int i, ret;
1839 struct device *dev;
1840 struct dmar_drhd_unit *dmaru;
1841
1842 dmaru = dmar_find_dmaru((struct acpi_dmar_hardware_unit *)header);
1843 if (!dmaru)
1844 return 0;
1845
1846 /*
1847 * All PCI devices managed by this unit should have been destroyed.
1848 */
1849 if (!dmaru->include_all && dmaru->devices && dmaru->devices_cnt)
1850 for_each_active_dev_scope(dmaru->devices,
1851 dmaru->devices_cnt, i, dev)
1852 return -EBUSY;
1853
1854 ret = dmar_ir_hotplug(dmaru, false);
1855 if (ret == 0)
1856 ret = dmar_iommu_hotplug(dmaru, false);
1857
1858 return ret;
1859}
1860
1861static int dmar_hp_release_drhd(struct acpi_dmar_header *header, void *arg)
1862{
1863 struct dmar_drhd_unit *dmaru;
1864
1865 dmaru = dmar_find_dmaru((struct acpi_dmar_hardware_unit *)header);
1866 if (dmaru) {
1867 list_del_rcu(&dmaru->list);
1868 synchronize_rcu();
1869 dmar_free_drhd(dmaru);
1870 }
1871
1872 return 0;
1873}
1874
1875static int dmar_hotplug_insert(acpi_handle handle)
1876{
1877 int ret;
1878 int drhd_count = 0;
1879
1880 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1881 &dmar_validate_one_drhd, (void *)1);
1882 if (ret)
1883 goto out;
1884
1885 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1886 &dmar_parse_one_drhd, (void *)&drhd_count);
1887 if (ret == 0 && drhd_count == 0) {
1888 pr_warn(FW_BUG "No DRHD structures in buffer returned by _DSM method\n");
1889 goto out;
1890 } else if (ret) {
1891 goto release_drhd;
1892 }
1893
1894 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_RHSA,
1895 &dmar_parse_one_rhsa, NULL);
1896 if (ret)
1897 goto release_drhd;
1898
1899 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_ATSR,
1900 &dmar_parse_one_atsr, NULL);
1901 if (ret)
1902 goto release_atsr;
1903
1904 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1905 &dmar_hp_add_drhd, NULL);
1906 if (!ret)
1907 return 0;
1908
1909 dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1910 &dmar_hp_remove_drhd, NULL);
1911release_atsr:
1912 dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_ATSR,
1913 &dmar_release_one_atsr, NULL);
1914release_drhd:
1915 dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1916 &dmar_hp_release_drhd, NULL);
1917out:
1918 return ret;
1919}
1920
1921static int dmar_hotplug_remove(acpi_handle handle)
1922{
1923 int ret;
1924
1925 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_ATSR,
1926 &dmar_check_one_atsr, NULL);
1927 if (ret)
1928 return ret;
1929
1930 ret = dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1931 &dmar_hp_remove_drhd, NULL);
1932 if (ret == 0) {
1933 WARN_ON(dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_ATSR,
1934 &dmar_release_one_atsr, NULL));
1935 WARN_ON(dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1936 &dmar_hp_release_drhd, NULL));
1937 } else {
1938 dmar_walk_dsm_resource(handle, DMAR_DSM_FUNC_DRHD,
1939 &dmar_hp_add_drhd, NULL);
1940 }
1941
1942 return ret;
1943}
1944
1945static int dmar_device_hotplug(acpi_handle handle, bool insert)
1946{
1947 int ret;
1948
1949 if (!dmar_in_use())
1950 return 0;
1951
1952 if (!dmar_detect_dsm(handle, DMAR_DSM_FUNC_DRHD))
1953 return 0;
1954
1955 down_write(&dmar_global_lock);
1956 if (insert)
1957 ret = dmar_hotplug_insert(handle);
1958 else
1959 ret = dmar_hotplug_remove(handle);
1960 up_write(&dmar_global_lock);
1961
1962 return ret;
1963}
1964
1965int dmar_device_add(acpi_handle handle)
1966{
1967 return dmar_device_hotplug(handle, true);
1968}
1969
1970int dmar_device_remove(acpi_handle handle)
1971{
1972 return dmar_device_hotplug(handle, false);
1973}
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 2779354321f5..7c49ab51904f 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3703,17 +3703,48 @@ int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
3703 return 0; 3703 return 0;
3704} 3704}
3705 3705
3706int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg) 3706static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
3707{
3708 struct dmar_atsr_unit *atsru;
3709 struct acpi_dmar_atsr *tmp;
3710
3711 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
3712 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
3713 if (atsr->segment != tmp->segment)
3714 continue;
3715 if (atsr->header.length != tmp->header.length)
3716 continue;
3717 if (memcmp(atsr, tmp, atsr->header.length) == 0)
3718 return atsru;
3719 }
3720
3721 return NULL;
3722}
3723
3724int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
3707{ 3725{
3708 struct acpi_dmar_atsr *atsr; 3726 struct acpi_dmar_atsr *atsr;
3709 struct dmar_atsr_unit *atsru; 3727 struct dmar_atsr_unit *atsru;
3710 3728
3729 if (system_state != SYSTEM_BOOTING && !intel_iommu_enabled)
3730 return 0;
3731
3711 atsr = container_of(hdr, struct acpi_dmar_atsr, header); 3732 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
3712 atsru = kzalloc(sizeof(*atsru), GFP_KERNEL); 3733 atsru = dmar_find_atsr(atsr);
3734 if (atsru)
3735 return 0;
3736
3737 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
3713 if (!atsru) 3738 if (!atsru)
3714 return -ENOMEM; 3739 return -ENOMEM;
3715 3740
3716 atsru->hdr = hdr; 3741 /*
3742 * If memory is allocated from slab by ACPI _DSM method, we need to
3743 * copy the memory content because the memory buffer will be freed
3744 * on return.
3745 */
3746 atsru->hdr = (void *)(atsru + 1);
3747 memcpy(atsru->hdr, hdr, hdr->length);
3717 atsru->include_all = atsr->flags & 0x1; 3748 atsru->include_all = atsr->flags & 0x1;
3718 if (!atsru->include_all) { 3749 if (!atsru->include_all) {
3719 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1), 3750 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
@@ -3736,6 +3767,47 @@ static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
3736 kfree(atsru); 3767 kfree(atsru);
3737} 3768}
3738 3769
3770int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
3771{
3772 struct acpi_dmar_atsr *atsr;
3773 struct dmar_atsr_unit *atsru;
3774
3775 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
3776 atsru = dmar_find_atsr(atsr);
3777 if (atsru) {
3778 list_del_rcu(&atsru->list);
3779 synchronize_rcu();
3780 intel_iommu_free_atsr(atsru);
3781 }
3782
3783 return 0;
3784}
3785
3786int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
3787{
3788 int i;
3789 struct device *dev;
3790 struct acpi_dmar_atsr *atsr;
3791 struct dmar_atsr_unit *atsru;
3792
3793 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
3794 atsru = dmar_find_atsr(atsr);
3795 if (!atsru)
3796 return 0;
3797
3798 if (!atsru->include_all && atsru->devices && atsru->devices_cnt)
3799 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
3800 i, dev)
3801 return -EBUSY;
3802
3803 return 0;
3804}
3805
3806int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
3807{
3808 return intel_iommu_enabled ? -ENOSYS : 0;
3809}
3810
3739static void intel_iommu_free_dmars(void) 3811static void intel_iommu_free_dmars(void)
3740{ 3812{
3741 struct dmar_rmrr_unit *rmrru, *rmrr_n; 3813 struct dmar_rmrr_unit *rmrru, *rmrr_n;
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
index 7c80661b35c1..1cbdb509bc7b 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -1171,3 +1171,8 @@ struct irq_remap_ops intel_irq_remap_ops = {
1171 .msi_setup_irq = intel_msi_setup_irq, 1171 .msi_setup_irq = intel_msi_setup_irq,
1172 .alloc_hpet_msi = intel_alloc_hpet_msi, 1172 .alloc_hpet_msi = intel_alloc_hpet_msi,
1173}; 1173};
1174
1175int dmar_ir_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
1176{
1177 return irq_remapping_enabled ? -ENOSYS : 0;
1178}