[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] PCI: don't allow guest assignment of devices used by Xen


  • To: xen-changelog@xxxxxxxxxxxxxxxxxxx
  • From: Xen patchbot-unstable <patchbot@xxxxxxx>
  • Date: Fri, 14 Sep 2012 10:55:26 +0000
  • Delivery-date: Fri, 14 Sep 2012 10:55:32 +0000
  • List-id: "Change log for Mercurial \(receive only\)" <xen-changelog.lists.xen.org>

# HG changeset patch
# User Jan Beulich <jbeulich@xxxxxxxx>
# Date 1347372075 -7200
# Node ID 47e6725ec6f2b5d129f928ffa2ed4eb19d1095a3
# Parent  59b3663316db97d2e5d25501438a8b93d0cb287a
PCI: don't allow guest assignment of devices used by Xen

This covers the devices used for the console and the AMD IOMMU ones (as
would be any others that might get passed to pci_ro_device()).

Boot video device determination cloned from similar Linux logic.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
Acked-by: Keir Fraser <keir@xxxxxxx>
---


diff -r 59b3663316db -r 47e6725ec6f2 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Tue Sep 11 15:59:43 2012 +0200
+++ b/xen/arch/x86/mm.c Tue Sep 11 16:01:15 2012 +0200
@@ -311,9 +311,12 @@ void __init arch_init_memory(void)
      * Initialise our DOMID_XEN domain.
      * Any Xen-heap pages that we will allow to be mapped will have
      * their domain field set to dom_xen.
+     * Hidden PCI devices will also be associated with this domain
+     * (but be [partly] controlled by Dom0 nevertheless).
      */
     dom_xen = domain_create(DOMID_XEN, DOMCRF_dummy, 0);
     BUG_ON(IS_ERR(dom_xen));
+    INIT_LIST_HEAD(&dom_xen->arch.pdev_list);
 
     /*
      * Initialise our DOMID_IO domain.
diff -r 59b3663316db -r 47e6725ec6f2 xen/drivers/char/ehci-dbgp.c
--- a/xen/drivers/char/ehci-dbgp.c      Tue Sep 11 15:59:43 2012 +0200
+++ b/xen/drivers/char/ehci-dbgp.c      Tue Sep 11 16:01:15 2012 +0200
@@ -1364,6 +1364,8 @@ static void __init ehci_dbgp_init_postir
     init_timer(&dbgp->timer, ehci_dbgp_poll, port, 0);
 
     ehci_dbgp_setup_postirq(dbgp);
+
+    pci_hide_device(dbgp->bus, PCI_DEVFN(dbgp->slot, dbgp->func));
 }
 
 static int ehci_dbgp_check_release(struct ehci_dbgp *dbgp)
diff -r 59b3663316db -r 47e6725ec6f2 xen/drivers/char/ns16550.c
--- a/xen/drivers/char/ns16550.c        Tue Sep 11 15:59:43 2012 +0200
+++ b/xen/drivers/char/ns16550.c        Tue Sep 11 16:01:15 2012 +0200
@@ -334,6 +334,10 @@ static void __init ns16550_init_postirq(
     }
 
     ns16550_setup_postirq(uart);
+
+    if ( uart->bar || uart->ps_bdf_enable )
+        pci_hide_device(uart->ps_bdf[0], PCI_DEVFN(uart->ps_bdf[1],
+                                                   uart->ps_bdf[2]));
 }
 
 static void ns16550_suspend(struct serial_port *port)
diff -r 59b3663316db -r 47e6725ec6f2 xen/drivers/passthrough/iommu.c
--- a/xen/drivers/passthrough/iommu.c   Tue Sep 11 15:59:43 2012 +0200
+++ b/xen/drivers/passthrough/iommu.c   Tue Sep 11 16:01:15 2012 +0200
@@ -208,7 +208,7 @@ static int device_assigned(u16 seg, u8 b
     pdev = pci_get_pdev_by_domain(dom0, seg, bus, devfn);
     spin_unlock(&pcidevs_lock);
 
-    return pdev ? 0 : -1;
+    return pdev ? 0 : -EBUSY;
 }
 
 static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn)
@@ -614,7 +614,8 @@ int iommu_do_domctl(
         bus = (domctl->u.assign_device.machine_sbdf >> 8) & 0xff;
         devfn = domctl->u.assign_device.machine_sbdf & 0xff;
 
-        ret = assign_device(d, seg, bus, devfn);
+        ret = device_assigned(seg, bus, devfn) ?:
+              assign_device(d, seg, bus, devfn);
         if ( ret )
             printk(XENLOG_G_ERR "XEN_DOMCTL_assign_device: "
                    "assign %04x:%02x:%02x.%u to dom%d failed (%d)\n",
diff -r 59b3663316db -r 47e6725ec6f2 xen/drivers/passthrough/pci.c
--- a/xen/drivers/passthrough/pci.c     Tue Sep 11 15:59:43 2012 +0200
+++ b/xen/drivers/passthrough/pci.c     Tue Sep 11 16:01:15 2012 +0200
@@ -208,6 +208,31 @@ static void free_pdev(struct pci_seg *ps
     xfree(pdev);
 }
 
+static void _pci_hide_device(struct pci_dev *pdev)
+{
+    if ( pdev->domain )
+        return;
+    pdev->domain = dom_xen;
+    list_add(&pdev->domain_list, &dom_xen->arch.pdev_list);
+}
+
+int __init pci_hide_device(int bus, int devfn)
+{
+    struct pci_dev *pdev;
+    int rc = -ENOMEM;
+
+    spin_lock(&pcidevs_lock);
+    pdev = alloc_pdev(get_pseg(0), bus, devfn);
+    if ( pdev )
+    {
+        _pci_hide_device(pdev);
+        rc = 0;
+    }
+    spin_unlock(&pcidevs_lock);
+
+    return rc;
+}
+
 int __init pci_ro_device(int seg, int bus, int devfn)
 {
     struct pci_seg *pseg = alloc_pseg(seg);
@@ -231,6 +256,7 @@ int __init pci_ro_device(int seg, int bu
 
     __set_bit(PCI_BDF2(bus, devfn), pseg->ro_map);
     arch_pci_ro_device(seg, PCI_BDF2(bus, devfn));
+    _pci_hide_device(pdev);
 
     return 0;
 }
@@ -718,9 +744,22 @@ static int __init _setup_dom0_pci_device
             if ( !pdev )
                 continue;
 
-            pdev->domain = ctxt->d;
-            list_add(&pdev->domain_list, &ctxt->d->arch.pdev_list);
-            ctxt->handler(pdev);
+            if ( !pdev->domain )
+            {
+                pdev->domain = ctxt->d;
+                list_add(&pdev->domain_list, &ctxt->d->arch.pdev_list);
+                ctxt->handler(pdev);
+            }
+            else if ( pdev->domain == dom_xen )
+            {
+                pdev->domain = ctxt->d;
+                ctxt->handler(pdev);
+                pdev->domain = dom_xen;
+            }
+            else if ( pdev->domain != ctxt->d )
+                printk(XENLOG_WARNING "Dom%d owning %04x:%02x:%02x.%u?\n",
+                       pdev->domain->domain_id, pseg->nr, bus,
+                       PCI_SLOT(devfn), PCI_FUNC(devfn));
         }
     }
 
diff -r 59b3663316db -r 47e6725ec6f2 xen/drivers/video/vga.c
--- a/xen/drivers/video/vga.c   Tue Sep 11 15:59:43 2012 +0200
+++ b/xen/drivers/video/vga.c   Tue Sep 11 16:01:15 2012 +0200
@@ -9,6 +9,7 @@
 #include <xen/lib.h>
 #include <xen/mm.h>
 #include <xen/vga.h>
+#include <xen/pci.h>
 #include <asm/io.h>
 
 /* Filled in by arch boot code. */
@@ -106,6 +107,61 @@ void __init vga_endboot(void)
 
     if ( !vgacon_keep )
         vga_puts = vga_noop_puts;
+    else
+    {
+        int bus, devfn;
+
+        for ( bus = 0; bus < 256; ++bus )
+            for ( devfn = 0; devfn < 256; ++devfn )
+            {
+                const struct pci_dev *pdev;
+                u8 b = bus, df = devfn, sb;
+
+                spin_lock(&pcidevs_lock);
+                pdev = pci_get_pdev(0, bus, devfn);
+                spin_unlock(&pcidevs_lock);
+
+                if ( !pdev ||
+                     pci_conf_read16(0, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
+                                     PCI_CLASS_DEVICE) != 0x0300 ||
+                     !(pci_conf_read16(0, bus, PCI_SLOT(devfn),
+                                       PCI_FUNC(devfn), PCI_COMMAND) &
+                       (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) )
+                    continue;
+
+                while ( b )
+                {
+                    switch ( find_upstream_bridge(0, &b, &df, &sb) )
+                    {
+                    case 0:
+                        b = 0;
+                        break;
+                    case 1:
+                        switch ( pci_conf_read8(0, b, PCI_SLOT(df),
+                                                PCI_FUNC(df),
+                                                PCI_HEADER_TYPE) )
+                        {
+                        case PCI_HEADER_TYPE_BRIDGE:
+                        case PCI_HEADER_TYPE_CARDBUS:
+                            if ( pci_conf_read16(0, b, PCI_SLOT(df),
+                                                 PCI_FUNC(df),
+                                                 PCI_BRIDGE_CONTROL) &
+                                 PCI_BRIDGE_CTL_VGA )
+                                continue;
+                            break;
+                        }
+                        break;
+                    }
+                    break;
+                }
+                if ( !b )
+                {
+                    printk(XENLOG_INFO "Boot video device %02x:%02x.%u\n",
+                           bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+                    pci_hide_device(bus, devfn);
+                }
+            }
+    }
 
     switch ( vga_console_info.video_type )
     {
diff -r 59b3663316db -r 47e6725ec6f2 xen/include/xen/pci.h
--- a/xen/include/xen/pci.h     Tue Sep 11 15:59:43 2012 +0200
+++ b/xen/include/xen/pci.h     Tue Sep 11 16:01:15 2012 +0200
@@ -103,6 +103,7 @@ int pci_add_device(u16 seg, u8 bus, u8 d
 int pci_remove_device(u16 seg, u8 bus, u8 devfn);
 int pci_ro_device(int seg, int bus, int devfn);
 void arch_pci_ro_device(int seg, int bdf);
+int pci_hide_device(int bus, int devfn);
 struct pci_dev *pci_get_pdev(int seg, int bus, int devfn);
 struct pci_dev *pci_get_pdev_by_domain(
     struct domain *, int seg, int bus, int devfn);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.