powerpc/powernv: Implement multilevel TCE tables
TCE tables might get too big in case of 4K IOMMU pages and DDW enabled on huge guests (hundreds of GB of RAM) so the kernel might be unable to allocate contiguous chunk of physical memory to store the TCE table. To address this, POWER8 CPU (actually, IODA2) supports multi-level TCE tables, up to 5 levels which splits the table into a tree of smaller subtables. This adds multi-level TCE tables support to pnv_pci_ioda2_table_alloc_pages() and pnv_pci_ioda2_table_free_pages() helpers. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:

committed by
Michael Ellerman

parent
43cb60ab7f
commit
bbb845c4ba
@@ -575,6 +575,19 @@ struct pci_ops pnv_pci_ops = {
|
||||
static __be64 *pnv_tce(struct iommu_table *tbl, long idx)
|
||||
{
|
||||
__be64 *tmp = ((__be64 *)tbl->it_base);
|
||||
int level = tbl->it_indirect_levels;
|
||||
const long shift = ilog2(tbl->it_level_size);
|
||||
unsigned long mask = (tbl->it_level_size - 1) << (level * shift);
|
||||
|
||||
while (level) {
|
||||
int n = (idx & mask) >> (level * shift);
|
||||
unsigned long tce = be64_to_cpu(tmp[n]);
|
||||
|
||||
tmp = __va(tce & ~(TCE_PCI_READ | TCE_PCI_WRITE));
|
||||
idx &= ~mask;
|
||||
mask >>= shift;
|
||||
--level;
|
||||
}
|
||||
|
||||
return tmp + idx;
|
||||
}
|
||||
|
Reference in New Issue
Block a user