[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] vtd: IO NUMA support
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1245752064 -3600 # Node ID aa472909b39c1228434c4550915ee3cc18c57bfe # Parent 71c67be96ef68e7f94c78e991e9b8f25a76af658 vtd: IO NUMA support This patch adds VT-d RHSA processing for IO NUMA support. The basic idea is to parse ACPI RHSA structure to obtain VT-d HW to proximity domain mapping. This mapping is then used when allocating pages for Vt-d HW data structures. Signed-off-by: Allen Kay <allen.m.kay@xxxxxxxxx> --- xen/drivers/passthrough/vtd/dmar.c | 56 +++++++++++++++++++++++++++++++++ xen/drivers/passthrough/vtd/dmar.h | 5 ++ xen/drivers/passthrough/vtd/extern.h | 2 + xen/drivers/passthrough/vtd/ia64/vtd.c | 19 ----------- xen/drivers/passthrough/vtd/intremap.c | 4 +- xen/drivers/passthrough/vtd/iommu.c | 54 ++++++++++++++++++++++++++++--- xen/drivers/passthrough/vtd/qinval.c | 4 +- xen/drivers/passthrough/vtd/vtd.h | 2 - xen/drivers/passthrough/vtd/x86/vtd.c | 21 ------------ xen/include/xen/acpi.h | 7 ++++ 10 files changed, 126 insertions(+), 48 deletions(-) diff -r 71c67be96ef6 -r aa472909b39c xen/drivers/passthrough/vtd/dmar.c --- a/xen/drivers/passthrough/vtd/dmar.c Tue Jun 23 11:13:29 2009 +0100 +++ b/xen/drivers/passthrough/vtd/dmar.c Tue Jun 23 11:14:24 2009 +0100 @@ -42,6 +42,7 @@ LIST_HEAD(acpi_drhd_units); LIST_HEAD(acpi_drhd_units); LIST_HEAD(acpi_rmrr_units); LIST_HEAD(acpi_atsr_units); +LIST_HEAD(acpi_rhsa_units); u8 dmar_host_address_width; @@ -127,6 +128,20 @@ struct acpi_drhd_unit * ioapic_to_drhd(u return NULL; } +struct acpi_drhd_unit * iommu_to_drhd(struct iommu *iommu) +{ + struct acpi_drhd_unit *drhd; + + if ( iommu == NULL ) + return NULL; + + list_for_each_entry( drhd, &acpi_drhd_units, list ) + if ( drhd->iommu == iommu ) + return drhd; + + return NULL; +} + struct iommu * ioapic_to_iommu(unsigned int apic_id) { struct acpi_drhd_unit *drhd; @@ -157,6 +172,9 @@ struct acpi_drhd_unit * acpi_find_matche struct acpi_drhd_unit *include_all = NULL; int i; + if ( pdev == NULL ) + return NULL; + if (pdev->info.is_extfn) { bus = pdev->bus; devfn = 0; @@ -197,6 +215,21 @@ struct acpi_atsr_unit * acpi_find_matche all_ports = atsr; } return all_ports; +} + +struct acpi_rhsa_unit * drhd_to_rhsa(struct acpi_drhd_unit *drhd) +{ + struct acpi_rhsa_unit *rhsa; + + if ( drhd == NULL ) + return NULL; + + list_for_each_entry ( rhsa, &acpi_rhsa_units, list ) + { + if ( rhsa->address == drhd->address ) + return rhsa; + } + return NULL; } /* @@ -453,6 +486,25 @@ acpi_parse_one_atsr(struct acpi_dmar_ent return ret; } +static int __init +acpi_parse_one_rhsa(struct acpi_dmar_entry_header *header) +{ + struct acpi_table_rhsa *rhsa = (struct acpi_table_rhsa *)header; + struct acpi_rhsa_unit *rhsau; + int ret = 0; + + rhsau = xmalloc(struct acpi_rhsa_unit); + if ( !rhsau ) + return -ENOMEM; + memset(rhsau, 0, sizeof(struct acpi_rhsa_unit)); + + rhsau->address = rhsa->address; + rhsau->domain = rhsa->domain; + list_add_tail(&rhsau->list, &acpi_rhsa_units); + + return ret; +} + static int __init acpi_parse_dmar(struct acpi_table_header *table) { struct acpi_table_dmar *dmar; @@ -491,6 +543,10 @@ static int __init acpi_parse_dmar(struct case ACPI_DMAR_ATSR: dprintk(XENLOG_INFO VTDPREFIX, "found ACPI_DMAR_ATSR\n"); ret = acpi_parse_one_atsr(entry_header); + break; + case ACPI_DMAR_RHSA: + dprintk(XENLOG_INFO VTDPREFIX, "found ACPI_DMAR_RHSA\n"); + ret = acpi_parse_one_rhsa(entry_header); break; default: dprintk(XENLOG_WARNING VTDPREFIX, "Unknown DMAR structure type\n"); diff -r 71c67be96ef6 -r aa472909b39c xen/drivers/passthrough/vtd/dmar.h --- a/xen/drivers/passthrough/vtd/dmar.h Tue Jun 23 11:13:29 2009 +0100 +++ b/xen/drivers/passthrough/vtd/dmar.h Tue Jun 23 11:14:24 2009 +0100 @@ -69,6 +69,11 @@ struct acpi_atsr_unit { u8 all_ports:1; }; +struct acpi_rhsa_unit { + struct list_head list; + u64 address; + u32 domain; +}; #define for_each_drhd_unit(drhd) \ list_for_each_entry(drhd, &acpi_drhd_units, list) diff -r 71c67be96ef6 -r aa472909b39c xen/drivers/passthrough/vtd/extern.h --- a/xen/drivers/passthrough/vtd/extern.h Tue Jun 23 11:13:29 2009 +0100 +++ b/xen/drivers/passthrough/vtd/extern.h Tue Jun 23 11:14:24 2009 +0100 @@ -45,6 +45,8 @@ int iommu_flush_iec_index(struct iommu * int iommu_flush_iec_index(struct iommu *iommu, u8 im, u16 iidx); struct iommu * ioapic_to_iommu(unsigned int apic_id); struct acpi_drhd_unit * ioapic_to_drhd(unsigned int apic_id); +struct acpi_drhd_unit * iommu_to_drhd(struct iommu *iommu); +struct acpi_rhsa_unit * drhd_to_rhsa(struct acpi_drhd_unit *drhd); void clear_fault_bits(struct iommu *iommu); int ats_device(int seg, int bus, int devfn); int enable_ats_device(int seg, int bus, int devfn); diff -r 71c67be96ef6 -r aa472909b39c xen/drivers/passthrough/vtd/ia64/vtd.c --- a/xen/drivers/passthrough/vtd/ia64/vtd.c Tue Jun 23 11:13:29 2009 +0100 +++ b/xen/drivers/passthrough/vtd/ia64/vtd.c Tue Jun 23 11:14:24 2009 +0100 @@ -44,25 +44,6 @@ void unmap_vtd_domain_page(void *va) void unmap_vtd_domain_page(void *va) { unmap_domain_page(va); -} - -/* Allocate page table, return its machine address */ -u64 alloc_pgtable_maddr(struct domain *d, unsigned long npages) -{ - struct page_info *pg; - u64 *vaddr; - - pg = alloc_domheap_pages(NULL, get_order_from_pages(npages), - d ? MEMF_node(domain_to_node(d)) : 0); - vaddr = map_domain_page(page_to_mfn(pg)); - if ( !vaddr ) - return 0; - memset(vaddr, 0, PAGE_SIZE * npages); - - iommu_flush_cache_page(vaddr, npages); - unmap_domain_page(vaddr); - - return page_to_maddr(pg); } void free_pgtable_maddr(u64 maddr) diff -r 71c67be96ef6 -r aa472909b39c xen/drivers/passthrough/vtd/intremap.c --- a/xen/drivers/passthrough/vtd/intremap.c Tue Jun 23 11:13:29 2009 +0100 +++ b/xen/drivers/passthrough/vtd/intremap.c Tue Jun 23 11:14:24 2009 +0100 @@ -614,6 +614,7 @@ void msi_msg_write_remap_rte( int enable_intremap(struct iommu *iommu) { + struct acpi_drhd_unit *drhd; struct ir_ctrl *ir_ctrl; u32 sts, gcmd; unsigned long flags; @@ -623,7 +624,8 @@ int enable_intremap(struct iommu *iommu) ir_ctrl = iommu_ir_ctrl(iommu); if ( ir_ctrl->iremap_maddr == 0 ) { - ir_ctrl->iremap_maddr = alloc_pgtable_maddr(NULL, 1); + drhd = iommu_to_drhd(iommu); + ir_ctrl->iremap_maddr = alloc_pgtable_maddr(drhd, 1); if ( ir_ctrl->iremap_maddr == 0 ) { dprintk(XENLOG_WARNING VTDPREFIX, diff -r 71c67be96ef6 -r aa472909b39c xen/drivers/passthrough/vtd/iommu.c --- a/xen/drivers/passthrough/vtd/iommu.c Tue Jun 23 11:13:29 2009 +0100 +++ b/xen/drivers/passthrough/vtd/iommu.c Tue Jun 23 11:14:24 2009 +0100 @@ -38,6 +38,7 @@ #define domain_iommu_domid(d) ((d)->arch.hvm_domain.hvm_iommu.iommu_domid) +int nr_iommus; static spinlock_t domid_bitmap_lock; /* protect domain id bitmap */ static int domid_bitmap_size; /* domain id bitmap size in bits */ static unsigned long *domid_bitmap; /* iommu domain id bitmap */ @@ -136,10 +137,37 @@ void iommu_flush_cache_page(void *addr, __iommu_flush_cache(addr, PAGE_SIZE_4K * npages); } -int nr_iommus; +/* Allocate page table, return its machine address */ +u64 alloc_pgtable_maddr(struct acpi_drhd_unit *drhd, unsigned long npages) +{ + struct acpi_rhsa_unit *rhsa; + struct page_info *pg; + u64 *vaddr; + + rhsa = drhd_to_rhsa(drhd); + if ( !rhsa ) + dprintk(XENLOG_INFO VTDPREFIX, + "IOMMU: RHSA == NULL, IO NUMA memory allocation disabled\n"); + + pg = alloc_domheap_pages(NULL, get_order_from_pages(npages), + rhsa ? rhsa->domain : 0); + if ( !pg ) + return 0; + vaddr = map_domain_page(page_to_mfn(pg)); + if ( !vaddr ) + return 0; + memset(vaddr, 0, PAGE_SIZE * npages); + + iommu_flush_cache_page(vaddr, npages); + unmap_domain_page(vaddr); + + return page_to_maddr(pg); +} + /* context entry handling */ static u64 bus_to_context_maddr(struct iommu *iommu, u8 bus) { + struct acpi_drhd_unit *drhd; struct root_entry *root, *root_entries; u64 maddr; @@ -148,7 +176,8 @@ static u64 bus_to_context_maddr(struct i root = &root_entries[bus]; if ( !root_present(*root) ) { - maddr = alloc_pgtable_maddr(NULL, 1); + drhd = iommu_to_drhd(iommu); + maddr = alloc_pgtable_maddr(drhd, 1); if ( maddr == 0 ) { unmap_vtd_domain_page(root_entries); @@ -165,6 +194,8 @@ static u64 bus_to_context_maddr(struct i static u64 addr_to_dma_page_maddr(struct domain *domain, u64 addr, int alloc) { + struct acpi_drhd_unit *drhd; + struct pci_dev *pdev; struct hvm_iommu *hd = domain_hvm_iommu(domain); int addr_width = agaw_to_width(hd->agaw); struct dma_pte *parent, *pte = NULL; @@ -176,8 +207,12 @@ static u64 addr_to_dma_page_maddr(struct addr &= (((u64)1) << addr_width) - 1; ASSERT(spin_is_locked(&hd->mapping_lock)); if ( hd->pgd_maddr == 0 ) - if ( !alloc || ((hd->pgd_maddr = alloc_pgtable_maddr(domain, 1)) == 0) ) + { + pdev = pci_get_pdev_by_domain(domain, -1, -1); + drhd = acpi_find_matched_drhd_unit(pdev); + if ( !alloc || ((hd->pgd_maddr = alloc_pgtable_maddr(drhd, 1)) == 0) ) goto out; + } parent = (struct dma_pte *)map_vtd_domain_page(hd->pgd_maddr); while ( level > 1 ) @@ -189,9 +224,13 @@ static u64 addr_to_dma_page_maddr(struct { if ( !alloc ) break; - maddr = alloc_pgtable_maddr(domain, 1); + + pdev = pci_get_pdev_by_domain(domain, -1, -1); + drhd = acpi_find_matched_drhd_unit(pdev); + maddr = alloc_pgtable_maddr(drhd, 1); if ( !maddr ) break; + dma_set_pte_addr(*pte, maddr); vaddr = map_vtd_domain_page(maddr); @@ -548,13 +587,18 @@ static void iommu_free_pagetable(u64 pt_ static int iommu_set_root_entry(struct iommu *iommu) { + struct acpi_drhd_unit *drhd; u32 sts; unsigned long flags; spin_lock(&iommu->lock); if ( iommu->root_maddr == 0 ) - iommu->root_maddr = alloc_pgtable_maddr(NULL, 1); + { + drhd = iommu_to_drhd(iommu); + iommu->root_maddr = alloc_pgtable_maddr(drhd, 1); + } + if ( iommu->root_maddr == 0 ) { spin_unlock(&iommu->lock); diff -r 71c67be96ef6 -r aa472909b39c xen/drivers/passthrough/vtd/qinval.c --- a/xen/drivers/passthrough/vtd/qinval.c Tue Jun 23 11:13:29 2009 +0100 +++ b/xen/drivers/passthrough/vtd/qinval.c Tue Jun 23 11:14:24 2009 +0100 @@ -416,6 +416,7 @@ static int flush_iotlb_qi( int enable_qinval(struct iommu *iommu) { + struct acpi_drhd_unit *drhd; struct qi_ctrl *qi_ctrl; struct iommu_flush *flush; u32 sts; @@ -428,7 +429,8 @@ int enable_qinval(struct iommu *iommu) if ( qi_ctrl->qinval_maddr == 0 ) { - qi_ctrl->qinval_maddr = alloc_pgtable_maddr(NULL, NUM_QINVAL_PAGES); + drhd = iommu_to_drhd(iommu); + qi_ctrl->qinval_maddr = alloc_pgtable_maddr(drhd, NUM_QINVAL_PAGES); if ( qi_ctrl->qinval_maddr == 0 ) { dprintk(XENLOG_WARNING VTDPREFIX, diff -r 71c67be96ef6 -r aa472909b39c xen/drivers/passthrough/vtd/vtd.h --- a/xen/drivers/passthrough/vtd/vtd.h Tue Jun 23 11:13:29 2009 +0100 +++ b/xen/drivers/passthrough/vtd/vtd.h Tue Jun 23 11:14:24 2009 +0100 @@ -101,7 +101,7 @@ void cacheline_flush(char *); void cacheline_flush(char *); void flush_all_cache(void); void *map_to_nocache_virt(int nr_iommus, u64 maddr); -u64 alloc_pgtable_maddr(struct domain *d, unsigned long npages); +u64 alloc_pgtable_maddr(struct acpi_drhd_unit *drhd, unsigned long npages); void free_pgtable_maddr(u64 maddr); void *map_vtd_domain_page(u64 maddr); void unmap_vtd_domain_page(void *va); diff -r 71c67be96ef6 -r aa472909b39c xen/drivers/passthrough/vtd/x86/vtd.c --- a/xen/drivers/passthrough/vtd/x86/vtd.c Tue Jun 23 11:13:29 2009 +0100 +++ b/xen/drivers/passthrough/vtd/x86/vtd.c Tue Jun 23 11:14:24 2009 +0100 @@ -42,27 +42,6 @@ void unmap_vtd_domain_page(void *va) void unmap_vtd_domain_page(void *va) { unmap_domain_page(va); -} - -/* Allocate page table, return its machine address */ -u64 alloc_pgtable_maddr(struct domain *d, unsigned long npages) -{ - struct page_info *pg; - u64 *vaddr; - unsigned long mfn; - - pg = alloc_domheap_pages(NULL, get_order_from_pages(npages), - d ? MEMF_node(domain_to_node(d)) : 0); - if ( !pg ) - return 0; - mfn = page_to_mfn(pg); - vaddr = map_domain_page(mfn); - memset(vaddr, 0, PAGE_SIZE * npages); - - iommu_flush_cache_page(vaddr, npages); - unmap_domain_page(vaddr); - - return (u64)mfn << PAGE_SHIFT_4K; } void free_pgtable_maddr(u64 maddr) diff -r 71c67be96ef6 -r aa472909b39c xen/include/xen/acpi.h --- a/xen/include/xen/acpi.h Tue Jun 23 11:13:29 2009 +0100 +++ b/xen/include/xen/acpi.h Tue Jun 23 11:14:24 2009 +0100 @@ -197,6 +197,7 @@ enum acpi_dmar_entry_type { ACPI_DMAR_DRHD = 0, ACPI_DMAR_RMRR, ACPI_DMAR_ATSR, + ACPI_DMAR_RHSA, ACPI_DMAR_ENTRY_COUNT }; @@ -222,6 +223,12 @@ struct acpi_table_atsr { u8 flags; u8 reserved; u16 segment; +} __attribute__ ((packed)); + +struct acpi_table_rhsa { + struct acpi_dmar_entry_header header; + u32 domain; + u64 address; /* register base address for this drhd */ } __attribute__ ((packed)); enum acpi_dev_scope_type { _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |