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-ia64-devel

[Xen-ia64-devel] [PATCH] Extended I/O port space support

To: xen-ia64-devel <xen-ia64-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-ia64-devel] [PATCH] Extended I/O port space support
From: Alex Williamson <alex.williamson@xxxxxx>
Date: Mon, 11 Jun 2007 17:10:27 -0600
Delivery-date: Mon, 11 Jun 2007 16:08:34 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-ia64-devel-request@lists.xensource.com?subject=help>
List-id: Discussion of the ia64 port of Xen <xen-ia64-devel.lists.xensource.com>
List-post: <mailto:xen-ia64-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ia64-devel>, <mailto:xen-ia64-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-ia64-devel>, <mailto:xen-ia64-devel-request@lists.xensource.com?subject=unsubscribe>
Organization: HP OSLO R&D
Sender: xen-ia64-devel-bounces@xxxxxxxxxxxxxxxxxxx
This version doesn't have any significant functional changes from the
RFC I sent out before.  I just wanted to provide an opportunity to
comment before I check it in.  See here for a complete description:

http://lists.xensource.com/archives/html/xen-ia64-devel/2007-06/msg00087.html

Thanks,

        Alex

Signed-off-by: Alex Williamson <alex.williamson@xxxxxx>
---

diff -r 0cf6b75423e9 linux-2.6-xen-sparse/arch/ia64/pci/pci.c
--- a/linux-2.6-xen-sparse/arch/ia64/pci/pci.c  Mon Jun 04 14:17:54 2007 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/pci/pci.c  Sun Jun 10 12:12:33 2007 -0600
@@ -164,6 +164,11 @@ new_space (u64 phys_base, int sparse)
        i = num_io_spaces++;
        io_space[i].mmio_base = mmio_base;
        io_space[i].sparse = sparse;
+
+#ifdef CONFIG_XEN
+       if (is_initial_xendomain())
+               HYPERVISOR_add_io_space(phys_base, sparse, i);
+#endif
 
        return i;
 }
diff -r 0cf6b75423e9 linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Mon Jun 04 14:17:54 
2007 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Thu Jun 07 08:37:01 
2007 -0600
@@ -387,6 +387,15 @@ xencomm_arch_hypercall_fpswa_revision(st
 {
        return _hypercall2(int, ia64_dom0vp_op,
                           IA64_DOM0VP_fpswa_revision, arg);
+}
+
+static inline int
+HYPERVISOR_add_io_space(unsigned long phys_base,
+                       unsigned long sparse,
+                       unsigned long space_number)
+{
+       return _hypercall4(int, ia64_dom0vp_op, IA64_DOM0VP_add_io_space,
+                          phys_base, sparse, space_number);
 }
 
 // for balloon driver
diff -r 0cf6b75423e9 xen/arch/ia64/xen/dom0_ops.c
--- a/xen/arch/ia64/xen/dom0_ops.c      Mon Jun 04 14:17:54 2007 -0600
+++ b/xen/arch/ia64/xen/dom0_ops.c      Sat Jun 09 14:18:21 2007 -0600
@@ -363,6 +363,40 @@ dom0vp_fpswa_revision(XEN_GUEST_HANDLE(u
     return 0;
 }
 
+static unsigned long
+dom0vp_add_io_space(struct domain *d, unsigned long phys_base,
+                    unsigned long sparse, unsigned long space_number)
+{
+    unsigned int fp, lp;
+
+    /*
+     * Registering new io_space roughly based on linux
+     * arch/ia64/pci/pci.c:new_space()
+     */
+
+    /* Skip legacy I/O port space, we already know about it */
+    if (phys_base == 0)
+        return 0;
+
+    /*
+     * Dom0 Linux initializes io spaces sequentially, if that changes,
+     * we'll need to add thread protection and the ability to handle
+     * a sparsely populated io_space array.
+     */
+    if (space_number > MAX_IO_SPACES || space_number != num_io_spaces)
+        return -EINVAL;
+
+    io_space[space_number].mmio_base = phys_base;
+    io_space[space_number].sparse = sparse;
+
+    num_io_spaces++;
+
+    fp = space_number << IO_SPACE_BITS;
+    lp = fp | 0xffff;
+
+    return ioports_permit_access(d, fp, lp);
+}
+
 unsigned long
 do_dom0vp_op(unsigned long cmd,
              unsigned long arg0, unsigned long arg1, unsigned long arg2,
@@ -419,6 +453,9 @@ do_dom0vp_op(unsigned long cmd,
         ret = dom0vp_fpswa_revision(hnd);
         break;
     }
+    case IA64_DOM0VP_add_io_space:
+        ret = dom0vp_add_io_space(d, arg0, arg1, arg2);
+        break;
     default:
         ret = -1;
                printk("unknown dom0_vp_op 0x%lx\n", cmd);
diff -r 0cf6b75423e9 xen/arch/ia64/xen/mm.c
--- a/xen/arch/ia64/xen/mm.c    Mon Jun 04 14:17:54 2007 -0600
+++ b/xen/arch/ia64/xen/mm.c    Sat Jun 09 15:53:50 2007 -0600
@@ -886,81 +886,144 @@ assign_domain_page(struct domain *d,
 }
 
 int
-ioports_permit_access(struct domain *d, unsigned long fp, unsigned long lp)
-{
+ioports_permit_access(struct domain *d, unsigned int fp, unsigned int lp)
+{
+    struct io_space *space;
+    unsigned long mmio_start, mmio_end, mach_start;
     int ret;
-    unsigned long off;
-    unsigned long fp_offset;
-    unsigned long lp_offset;
-
+
+    if (IO_SPACE_NR(fp) >= num_io_spaces) {
+        dprintk(XENLOG_WARNING, "Unknown I/O Port range 0x%x - 0x%x\n", fp, 
lp);
+        return -EFAULT;
+    }
+
+    /*
+     * The ioport_cap rangeset tracks the I/O port address including
+     * the port space ID.  This means port space IDs need to match
+     * between Xen and dom0.  This is also a requirement because
+     * the hypercall to pass these port ranges only uses a u32.
+     *
+     * NB - non-dom0 driver domains may only have a subset of the
+     * I/O port spaces and thus will number port spaces differently.
+     * This is ok, they don't make use of this interface.
+     */
     ret = rangeset_add_range(d->arch.ioport_caps, fp, lp);
     if (ret != 0)
         return ret;
 
-    /* Domain 0 doesn't virtualize IO ports space. */
-    if (d == dom0)
+    space = &io_space[IO_SPACE_NR(fp)];
+
+    /* Legacy I/O on dom0 is already setup */
+    if (d == dom0 && space == &io_space[0])
         return 0;
 
-    fp_offset = IO_SPACE_SPARSE_ENCODING(fp) & ~PAGE_MASK;
-    lp_offset = PAGE_ALIGN(IO_SPACE_SPARSE_ENCODING(lp));
-
-    for (off = fp_offset; off <= lp_offset; off += PAGE_SIZE)
-        (void)__assign_domain_page(d, IO_PORTS_PADDR + off,
-                                   __pa(ia64_iobase) + off, ASSIGN_nocache);
+    fp = IO_SPACE_PORT(fp);
+    lp = IO_SPACE_PORT(lp);
+
+    if (space->sparse) {
+        mmio_start = IO_SPACE_SPARSE_ENCODING(fp) & ~PAGE_MASK;
+        mmio_end = PAGE_ALIGN(IO_SPACE_SPARSE_ENCODING(lp));
+    } else {
+        mmio_start = fp & ~PAGE_MASK;
+        mmio_end = PAGE_ALIGN(lp);
+    }
+
+    /*
+     * The "machine first port" is not necessarily identity mapped
+     * to the guest first port.  At least for the legacy range.
+     */
+    mach_start = mmio_start | __pa(space->mmio_base);
+
+    if (space == &io_space[0]) {
+        mmio_start |= IO_PORTS_PADDR;
+        mmio_end |= IO_PORTS_PADDR;
+    } else {
+        mmio_start |= __pa(space->mmio_base);
+        mmio_end |= __pa(space->mmio_base);
+    }
+
+    while (mmio_start <= mmio_end) {
+        (void)__assign_domain_page(d, mmio_start, mach_start, ASSIGN_nocache); 
+        mmio_start += PAGE_SIZE;
+        mach_start += PAGE_SIZE;
+    }
 
     return 0;
 }
 
 static int
-ioports_has_allowed(struct domain *d, unsigned long fp, unsigned long lp)
-{
-    unsigned long i;
-    for (i = fp; i < lp; i++)
-        if (rangeset_contains_singleton(d->arch.ioport_caps, i))
+ioports_has_allowed(struct domain *d, unsigned int fp, unsigned int lp)
+{
+    for (; fp < lp; fp++)
+        if (rangeset_contains_singleton(d->arch.ioport_caps, fp))
             return 1;
+
     return 0;
 }
 
 int
-ioports_deny_access(struct domain *d, unsigned long fp, unsigned long lp)
+ioports_deny_access(struct domain *d, unsigned int fp, unsigned int lp)
 {
     int ret;
     struct mm_struct *mm = &d->arch.mm;
-    unsigned long off;
-    unsigned long io_ports_base;
-    unsigned long fp_offset;
-    unsigned long lp_offset;
+    unsigned long mmio_start, mmio_end, mmio_base;
+    unsigned int fp_base, lp_base;
+    struct io_space *space;
+
+    if (IO_SPACE_NR(fp) >= num_io_spaces) {
+        dprintk(XENLOG_WARNING, "Unknown I/O Port range 0x%x - 0x%x\n", fp, 
lp);
+        return -EFAULT;
+    }
 
     ret = rangeset_remove_range(d->arch.ioport_caps, fp, lp);
     if (ret != 0)
         return ret;
-    if (d == dom0)
-        io_ports_base = __pa(ia64_iobase);
+
+    space = &io_space[IO_SPACE_NR(fp)];
+    fp_base = IO_SPACE_PORT(fp);
+    lp_base = IO_SPACE_PORT(lp);
+
+    if (space->sparse) {
+        mmio_start = IO_SPACE_SPARSE_ENCODING(fp_base) & ~PAGE_MASK;
+        mmio_end = PAGE_ALIGN(IO_SPACE_SPARSE_ENCODING(lp_base));
+    } else {
+        mmio_start = fp_base & ~PAGE_MASK;
+        mmio_end = PAGE_ALIGN(lp_base);
+    }
+
+    if (space == &io_space[0] && d != dom0)
+        mmio_base = IO_PORTS_PADDR;
     else
-        io_ports_base = IO_PORTS_PADDR;
-
-    fp_offset = IO_SPACE_SPARSE_ENCODING(fp) & PAGE_MASK;
-    lp_offset = PAGE_ALIGN(IO_SPACE_SPARSE_ENCODING(lp));
-
-    for (off = fp_offset; off < lp_offset; off += PAGE_SIZE) {
-        unsigned long mpaddr = io_ports_base + off;
-        unsigned long port;
+        mmio_base = __pa(space->mmio_base);
+
+    for (; mmio_start < mmio_end; mmio_start += PAGE_SIZE) {
+        unsigned int port, range;
+        unsigned long mpaddr;
         volatile pte_t *pte;
         pte_t old_pte;
 
-        port = IO_SPACE_SPARSE_DECODING (off);
-        if (port < fp || port + IO_SPACE_SPARSE_PORTS_PER_PAGE - 1 > lp) {
+        if (space->sparse) {
+            port = IO_SPACE_SPARSE_DECODING(mmio_start);
+            range = IO_SPACE_SPARSE_PORTS_PER_PAGE - 1;
+        } else {
+            port = mmio_start;
+            range = PAGE_SIZE - 1;
+        }
+
+        port |= IO_SPACE_BASE(IO_SPACE_NR(fp));
+
+        if (port < fp || port + range > lp) {
             /* Maybe this covers an allowed port.  */
-            if (ioports_has_allowed(d, port,
-                                    port + IO_SPACE_SPARSE_PORTS_PER_PAGE - 1))
+            if (ioports_has_allowed(d, port, port + range))
                 continue;
         }
 
+        mpaddr = mmio_start | mmio_base;
         pte = lookup_noalloc_domain_pte_none(d, mpaddr);
         BUG_ON(pte == NULL);
         BUG_ON(pte_none(*pte));
 
-        // clear pte
+        /* clear pte */
         old_pte = ptep_get_and_clear(mm, mpaddr, pte);
     }
     domain_flush_vtlb_all(d);
diff -r 0cf6b75423e9 xen/include/asm-ia64/iocap.h
--- a/xen/include/asm-ia64/iocap.h      Mon Jun 04 14:17:54 2007 -0600
+++ b/xen/include/asm-ia64/iocap.h      Thu Jun 07 15:57:30 2007 -0600
@@ -8,9 +8,9 @@
 #define __IA64_IOCAP_H__
 
 extern int ioports_permit_access(struct domain *d,
-                                 unsigned long s, unsigned long e);
+                                unsigned int s, unsigned int e);
 extern int ioports_deny_access(struct domain *d,
-                               unsigned long s, unsigned long e);
+                              unsigned int s, unsigned int e);
 
 #define ioports_access_permitted(d, s, e)               \
     rangeset_contains_range((d)->arch.ioport_caps, s, e)
diff -r 0cf6b75423e9 xen/include/public/arch-ia64.h
--- a/xen/include/public/arch-ia64.h    Mon Jun 04 14:17:54 2007 -0600
+++ b/xen/include/public/arch-ia64.h    Wed Jun 06 16:52:17 2007 -0600
@@ -526,6 +526,9 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_conte
 /* get fpswa revision */
 #define IA64_DOM0VP_fpswa_revision      10
 
+/* Add an I/O port space range */
+#define IA64_DOM0VP_add_io_space        11
+
 // flags for page assignement to pseudo physical address space
 #define _ASSIGN_readonly                0
 #define ASSIGN_readonly                 (1UL << _ASSIGN_readonly)



_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-ia64-devel] [PATCH] Extended I/O port space support, Alex Williamson <=