WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] vtd: IO NUMA support

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] vtd: IO NUMA support
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 23 Jun 2009 03:45:12 -0700
Delivery-date: Tue, 23 Jun 2009 03:46:03 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] vtd: IO NUMA support, Xen patchbot-unstable <=