Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/iommu: Do not immediately panic when failed IOMMU table allocation

Most platforms allocate IOMMU table structures (specifically it_map)
at the boot time and when this fails - it is a valid reason for panic().

However the powernv platform allocates it_map after a device is returned
to the host OS after being passed through and this happens long after
the host OS booted. It is quite possible to trigger the it_map allocation
panic() and kill the host even though it is not necessary - the host OS
can still use the DMA bypass mode (requires a tiny fraction of it_map's
memory) and even if that fails, the host OS is runnnable as it was without
the device for which allocating it_map causes the panic.

Instead of immediately crashing in a powernv/ioda2 system, this prints
an error and continues. All other platforms still call panic().

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Leonardo Bras <leobras.c@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210216033307.69863-3-aik@ozlabs.ru

authored by

Alexey Kardashevskiy and committed by
Michael Ellerman
4be518d8 7f1fa82d

+26 -15
+4 -2
arch/powerpc/kernel/iommu.c
··· 727 727 sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long); 728 728 729 729 tbl->it_map = vzalloc_node(sz, nid); 730 - if (!tbl->it_map) 731 - panic("iommu_init_table: Can't allocate %ld bytes\n", sz); 730 + if (!tbl->it_map) { 731 + pr_err("%s: Can't allocate %ld bytes\n", __func__, sz); 732 + return NULL; 733 + } 732 734 733 735 iommu_table_reserve_pages(tbl, res_start, res_end); 734 736
+2 -1
arch/powerpc/platforms/cell/iommu.c
··· 486 486 window->table.it_size = size >> window->table.it_page_shift; 487 487 window->table.it_ops = &cell_iommu_ops; 488 488 489 - iommu_init_table(&window->table, iommu->nid, 0, 0); 489 + if (!iommu_init_table(&window->table, iommu->nid, 0, 0)) 490 + panic("Failed to initialize iommu table"); 490 491 491 492 pr_debug("\tioid %d\n", window->ioid); 492 493 pr_debug("\tblocksize %ld\n", window->table.it_blocksize);
+3 -1
arch/powerpc/platforms/pasemi/iommu.c
··· 146 146 */ 147 147 iommu_table_iobmap.it_blocksize = 4; 148 148 iommu_table_iobmap.it_ops = &iommu_table_iobmap_ops; 149 - iommu_init_table(&iommu_table_iobmap, 0, 0, 0); 149 + if (!iommu_init_table(&iommu_table_iobmap, 0, 0, 0)) 150 + panic("Failed to initialize iommu table"); 151 + 150 152 pr_debug(" <- %s\n", __func__); 151 153 } 152 154
+8 -7
arch/powerpc/platforms/powernv/pci-ioda.c
··· 1762 1762 tbl->it_ops = &pnv_ioda1_iommu_ops; 1763 1763 pe->table_group.tce32_start = tbl->it_offset << tbl->it_page_shift; 1764 1764 pe->table_group.tce32_size = tbl->it_size << tbl->it_page_shift; 1765 - iommu_init_table(tbl, phb->hose->node, 0, 0); 1765 + if (!iommu_init_table(tbl, phb->hose->node, 0, 0)) 1766 + panic("Failed to initialize iommu table"); 1766 1767 1767 1768 pe->dma_setup_done = true; 1768 1769 return; ··· 1931 1930 res_start = pe->phb->ioda.m32_pci_base >> tbl->it_page_shift; 1932 1931 res_end = min(window_size, SZ_4G) >> tbl->it_page_shift; 1933 1932 } 1934 - iommu_init_table(tbl, pe->phb->hose->node, res_start, res_end); 1935 1933 1936 - rc = pnv_pci_ioda2_set_window(&pe->table_group, 0, tbl); 1934 + if (iommu_init_table(tbl, pe->phb->hose->node, res_start, res_end)) 1935 + rc = pnv_pci_ioda2_set_window(&pe->table_group, 0, tbl); 1936 + else 1937 + rc = -ENOMEM; 1937 1938 if (rc) { 1938 - pe_err(pe, "Failed to configure 32-bit TCE table, err %ld\n", 1939 - rc); 1939 + pe_err(pe, "Failed to configure 32-bit TCE table, err %ld\n", rc); 1940 1940 iommu_tce_table_put(tbl); 1941 - return rc; 1941 + tbl = NULL; /* This clears iommu_table_base below */ 1942 1942 } 1943 - 1944 1943 if (!pnv_iommu_bypass_disabled) 1945 1944 pnv_pci_ioda2_set_bypass(pe, true); 1946 1945
+7 -3
arch/powerpc/platforms/pseries/iommu.c
··· 638 638 639 639 iommu_table_setparms(pci->phb, dn, tbl); 640 640 tbl->it_ops = &iommu_table_pseries_ops; 641 - iommu_init_table(tbl, pci->phb->node, 0, 0); 641 + if (!iommu_init_table(tbl, pci->phb->node, 0, 0)) 642 + panic("Failed to initialize iommu table"); 642 643 643 644 /* Divide the rest (1.75GB) among the children */ 644 645 pci->phb->dma_window_size = 0x80000000ul; ··· 721 720 iommu_table_setparms_lpar(ppci->phb, pdn, tbl, 722 721 ppci->table_group, dma_window); 723 722 tbl->it_ops = &iommu_table_lpar_multi_ops; 724 - iommu_init_table(tbl, ppci->phb->node, 0, 0); 723 + if (!iommu_init_table(tbl, ppci->phb->node, 0, 0)) 724 + panic("Failed to initialize iommu table"); 725 725 iommu_register_group(ppci->table_group, 726 726 pci_domain_nr(bus), 0); 727 727 pr_debug(" created table: %p\n", ppci->table_group); ··· 751 749 tbl = PCI_DN(dn)->table_group->tables[0]; 752 750 iommu_table_setparms(phb, dn, tbl); 753 751 tbl->it_ops = &iommu_table_pseries_ops; 754 - iommu_init_table(tbl, phb->node, 0, 0); 752 + if (!iommu_init_table(tbl, phb->node, 0, 0)) 753 + panic("Failed to initialize iommu table"); 754 + 755 755 set_iommu_table_base(&dev->dev, tbl); 756 756 return; 757 757 }
+2 -1
arch/powerpc/sysdev/dart_iommu.c
··· 344 344 iommu_table_dart.it_index = 0; 345 345 iommu_table_dart.it_blocksize = 1; 346 346 iommu_table_dart.it_ops = &iommu_dart_ops; 347 - iommu_init_table(&iommu_table_dart, -1, 0, 0); 347 + if (!iommu_init_table(&iommu_table_dart, -1, 0, 0)) 348 + panic("Failed to initialize iommu table"); 348 349 349 350 /* Reserve the last page of the DART to avoid possible prefetch 350 351 * past the DART mapped area