[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v6 5/8] AMD/IOMMU: restrict interrupt remapping table sizes
> -----Original Message----- > From: Xen-devel <xen-devel-bounces@xxxxxxxxxxxxxxxxxxxx> On Behalf Of Jan > Beulich > Sent: 19 September 2019 14:24 > To: xen-devel@xxxxxxxxxxxxxxxxxxxx > Cc: Andrew Cooper <Andrew.Cooper3@xxxxxxxxxx>; Suravee Suthikulpanit > <suravee.suthikulpanit@xxxxxxx> > Subject: [Xen-devel] [PATCH v6 5/8] AMD/IOMMU: restrict interrupt remapping > table sizes > > There's no point setting up tables with more space than a PCI device can > use. For both MSI and MSI-X we can determine how many interrupts could > be set up at most. Tables allocated during ACPI table parsing, however, > will (for now at least) continue to be set up to have maximum size. > > Note that until we would want to use sub-page allocations here there's > no point checking whether both MSI and MSI-X are supported by a device - > an order-0 allocation will fit the dual case in any event, no matter > that the MSI-X vector count may be smaller than the MSI one. > > On my Rome system this reduces space needed from just over 1k pages to > about 125. > > Suggested-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> > Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Paul Durrant <paul.durrant@xxxxxxxxxx> > --- > v6: Don't allocate any IRT at all when device is neither MSI-X nor > MSI-capable. Re-base over changes earlier in this series. > v5: New. > > --- > xen/drivers/passthrough/amd/iommu_acpi.c | 4 +- > xen/drivers/passthrough/amd/iommu_init.c | 13 ++++----- > xen/drivers/passthrough/amd/iommu_intr.c | 36 > +++++++++++++++----------- > xen/drivers/passthrough/amd/iommu_map.c | 20 ++++++++++---- > xen/drivers/passthrough/amd/pci_amd_iommu.c | 18 +++++++------ > xen/include/asm-x86/hvm/svm/amd-iommu-defs.h | 3 -- > xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 5 ++- > 7 files changed, 59 insertions(+), 40 deletions(-) > > --- a/xen/drivers/passthrough/amd/iommu_acpi.c > +++ b/xen/drivers/passthrough/amd/iommu_acpi.c > @@ -77,7 +77,7 @@ static void __init add_ivrs_mapping_entr > { > if ( !shared_intremap_table ) > shared_intremap_table = amd_iommu_alloc_intremap_table( > - iommu, &shared_intremap_inuse); > + iommu, &shared_intremap_inuse, 0); > > if ( !shared_intremap_table ) > panic("No memory for shared IRT\n"); > @@ -89,7 +89,7 @@ static void __init add_ivrs_mapping_entr > { > ivrs_mappings[alias_id].intremap_table = > amd_iommu_alloc_intremap_table( > - iommu, &ivrs_mappings[alias_id].intremap_inuse); > + iommu, &ivrs_mappings[alias_id].intremap_inuse, 0); > > if ( !ivrs_mappings[alias_id].intremap_table ) > panic("No memory for %04x:%02x:%02x.%u's IRT\n", > --- a/xen/drivers/passthrough/amd/iommu_init.c > +++ b/xen/drivers/passthrough/amd/iommu_init.c > @@ -1284,12 +1284,14 @@ static int __init amd_iommu_setup_device > pcidevs_unlock(); > } > > - if ( pdev ) > + if ( pdev && (pdev->msix || pdev->msi_maxvec) ) > { > ivrs_mappings[bdf].intremap_table = > amd_iommu_alloc_intremap_table( > ivrs_mappings[bdf].iommu, > - &ivrs_mappings[bdf].intremap_inuse); > + &ivrs_mappings[bdf].intremap_inuse, > + pdev->msix ? pdev->msix->nr_entries > + : pdev->msi_maxvec); > if ( !ivrs_mappings[bdf].intremap_table ) > return -ENOMEM; > > @@ -1312,11 +1314,8 @@ static int __init amd_iommu_setup_device > } > > amd_iommu_set_intremap_table( > - dte, > - ivrs_mappings[bdf].intremap_table > - ? virt_to_maddr(ivrs_mappings[bdf].intremap_table) > - : 0, > - iommu_intremap); > + dte, ivrs_mappings[bdf].intremap_table, > + ivrs_mappings[bdf].iommu, iommu_intremap); > } > } > > --- a/xen/drivers/passthrough/amd/iommu_intr.c > +++ b/xen/drivers/passthrough/amd/iommu_intr.c > @@ -69,7 +69,8 @@ union irte_cptr { > const union irte128 *ptr128; > } __transparent__; > > -#define INTREMAP_MAX_ENTRIES (1 << IOMMU_INTREMAP_ORDER) > +#define INTREMAP_MAX_ORDER 0xB > +#define INTREMAP_MAX_ENTRIES (1 << INTREMAP_MAX_ORDER) > > struct ioapic_sbdf ioapic_sbdf[MAX_IO_APICS]; > struct hpet_sbdf hpet_sbdf; > @@ -80,17 +81,13 @@ unsigned int nr_ioapic_sbdf; > > static void dump_intremap_tables(unsigned char key); > > -static unsigned int __init intremap_table_order(const struct amd_iommu > *iommu) > -{ > - return iommu->ctrl.ga_en > - ? get_order_from_bytes(INTREMAP_MAX_ENTRIES * sizeof(union > irte128)) > - : get_order_from_bytes(INTREMAP_MAX_ENTRIES * sizeof(union > irte32)); > -} > +#define intremap_page_order(irt) PFN_ORDER(virt_to_page(irt)) > > unsigned int amd_iommu_intremap_table_order( > const void *irt, const struct amd_iommu *iommu) > { > - return IOMMU_INTREMAP_ORDER; > + return intremap_page_order(irt) + PAGE_SHIFT - > + (iommu->ctrl.ga_en ? 4 : 2); > } > > static unsigned int intremap_table_entries( > @@ -825,7 +822,10 @@ int amd_iommu_free_intremap_table( > > if ( *tblp ) > { > - __free_amd_iommu_tables(*tblp, intremap_table_order(iommu)); > + unsigned int order = intremap_page_order(*tblp); > + > + intremap_page_order(*tblp) = 0; > + __free_amd_iommu_tables(*tblp, order); > *tblp = NULL; > } > > @@ -833,15 +833,23 @@ int amd_iommu_free_intremap_table( > } > > void *amd_iommu_alloc_intremap_table( > - const struct amd_iommu *iommu, unsigned long **inuse_map) > + const struct amd_iommu *iommu, unsigned long **inuse_map, unsigned int > nr) > { > - unsigned int order = intremap_table_order(iommu); > - void *tb = __alloc_amd_iommu_tables(order); > + unsigned int order; > + void *tb; > > + if ( !nr ) > + nr = INTREMAP_MAX_ENTRIES; > + > + order = iommu->ctrl.ga_en > + ? get_order_from_bytes(nr * sizeof(union irte128)) > + : get_order_from_bytes(nr * sizeof(union irte32)); > + > + tb = __alloc_amd_iommu_tables(order); > if ( tb ) > { > - unsigned int nr = intremap_table_entries(tb, iommu); > - > + intremap_page_order(tb) = order; > + nr = intremap_table_entries(tb, iommu); > *inuse_map = xzalloc_array(unsigned long, BITS_TO_LONGS(nr)); > if ( *inuse_map ) > memset(tb, 0, PAGE_SIZE << order); > --- a/xen/drivers/passthrough/amd/iommu_map.c > +++ b/xen/drivers/passthrough/amd/iommu_map.c > @@ -113,12 +113,22 @@ void amd_iommu_set_root_page_table(struc > } > > void __init amd_iommu_set_intremap_table( > - struct amd_iommu_dte *dte, uint64_t intremap_ptr, bool valid) > + struct amd_iommu_dte *dte, const void *ptr, > + const struct amd_iommu *iommu, bool valid) > { > - dte->it_root = intremap_ptr >> 6; > - dte->int_tab_len = intremap_ptr ? IOMMU_INTREMAP_ORDER : 0; > - dte->int_ctl = intremap_ptr ? IOMMU_DEV_TABLE_INT_CONTROL_TRANSLATED > - : IOMMU_DEV_TABLE_INT_CONTROL_ABORTED; > + if ( ptr ) > + { > + dte->it_root = virt_to_maddr(ptr) >> 6; > + dte->int_tab_len = amd_iommu_intremap_table_order(ptr, iommu); > + dte->int_ctl = IOMMU_DEV_TABLE_INT_CONTROL_TRANSLATED; > + } > + else > + { > + dte->it_root = 0; > + dte->int_tab_len = 0; > + dte->int_ctl = IOMMU_DEV_TABLE_INT_CONTROL_ABORTED; > + } > + > dte->ig = false; /* unmapped interrupts result in i/o page faults */ > dte->iv = valid; > } > --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c > +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c > @@ -470,18 +470,22 @@ static int amd_iommu_add_device(u8 devfn > { > unsigned long flags; > > - ivrs_mappings[bdf].intremap_table = > - amd_iommu_alloc_intremap_table( > - iommu, &ivrs_mappings[bdf].intremap_inuse); > - if ( !ivrs_mappings[bdf].intremap_table ) > - return -ENOMEM; > + if ( pdev->msix || pdev->msi_maxvec ) > + { > + ivrs_mappings[bdf].intremap_table = > + amd_iommu_alloc_intremap_table( > + iommu, &ivrs_mappings[bdf].intremap_inuse, > + pdev->msix ? pdev->msix->nr_entries > + : pdev->msi_maxvec); > + if ( !ivrs_mappings[bdf].intremap_table ) > + return -ENOMEM; > + } > > spin_lock_irqsave(&iommu->lock, flags); > > amd_iommu_set_intremap_table( > iommu->dev_table.buffer + (bdf * IOMMU_DEV_TABLE_ENTRY_SIZE), > - virt_to_maddr(ivrs_mappings[bdf].intremap_table), > - iommu_intremap); > + ivrs_mappings[bdf].intremap_table, iommu, iommu_intremap); > > amd_iommu_flush_device(iommu, bdf); > > --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h > +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h > @@ -107,9 +107,6 @@ > #define IOMMU_DEV_TABLE_INT_CONTROL_FORWARDED 0x1 > #define IOMMU_DEV_TABLE_INT_CONTROL_TRANSLATED 0x2 > > -/* For now, we always allocate the maximum: 2048 entries. */ > -#define IOMMU_INTREMAP_ORDER 0xB > - > struct amd_iommu_dte { > /* 0 - 63 */ > bool v:1; > --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h > +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h > @@ -72,7 +72,8 @@ int __must_check amd_iommu_flush_iotlb_a > /* device table functions */ > int get_dma_requestor_id(uint16_t seg, uint16_t bdf); > void amd_iommu_set_intremap_table(struct amd_iommu_dte *dte, > - uint64_t intremap_ptr, > + const void *ptr, > + const struct amd_iommu *iommu, > bool valid); > void amd_iommu_set_root_page_table(struct amd_iommu_dte *dte, > uint64_t root_ptr, uint16_t domain_id, > @@ -99,7 +100,7 @@ struct amd_iommu *find_iommu_for_device( > bool iov_supports_xt(void); > int amd_iommu_setup_ioapic_remapping(void); > void *amd_iommu_alloc_intremap_table( > - const struct amd_iommu *, unsigned long **); > + const struct amd_iommu *, unsigned long **, unsigned int nr); > int amd_iommu_free_intremap_table( > const struct amd_iommu *, struct ivrs_mappings *, uint16_t); > unsigned int amd_iommu_intremap_table_order( > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxxxxxxxxx > https://lists.xenproject.org/mailman/listinfo/xen-devel _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |