xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] PCI: don't allow guest assignment of devices used by Xen
@ 2012-09-11 11:33 Jan Beulich
  2012-09-11 13:12 ` Keir Fraser
  0 siblings, 1 reply; 2+ messages in thread
From: Jan Beulich @ 2012-09-11 11:33 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 7710 bytes --]

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@suse.com>
---
Note that to apply cleanly, this has to go on top of the serial console
improvement series posted earlier.

--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -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.
--- a/xen/drivers/char/ehci-dbgp.c
+++ b/xen/drivers/char/ehci-dbgp.c
@@ -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)
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -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)
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -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",
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -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));
         }
     }
 
--- a/xen/drivers/video/vga.c
+++ b/xen/drivers/video/vga.c
@@ -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 )
     {
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -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);



[-- Attachment #2: pci-disallow-assign.patch --]
[-- Type: text/plain, Size: 7766 bytes --]

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@suse.com>
---
Note that to apply cleanly, this has to go on top of the serial console
improvement series posted earlier.

--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -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.
--- a/xen/drivers/char/ehci-dbgp.c
+++ b/xen/drivers/char/ehci-dbgp.c
@@ -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)
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -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)
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -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",
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -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));
         }
     }
 
--- a/xen/drivers/video/vga.c
+++ b/xen/drivers/video/vga.c
@@ -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 )
     {
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -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);

[-- Attachment #3: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] PCI: don't allow guest assignment of devices used by Xen
  2012-09-11 11:33 [PATCH] PCI: don't allow guest assignment of devices used by Xen Jan Beulich
@ 2012-09-11 13:12 ` Keir Fraser
  0 siblings, 0 replies; 2+ messages in thread
From: Keir Fraser @ 2012-09-11 13:12 UTC (permalink / raw)
  To: Jan Beulich, xen-devel

On 11/09/2012 12:33, "Jan Beulich" <JBeulich@suse.com> wrote:

> 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@suse.com>

Acked-by: Keir Fraser <keir@xen.org>

> ---
> Note that to apply cleanly, this has to go on top of the serial console
> improvement series posted earlier.
> 
> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -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.
> --- a/xen/drivers/char/ehci-dbgp.c
> +++ b/xen/drivers/char/ehci-dbgp.c
> @@ -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)
> --- a/xen/drivers/char/ns16550.c
> +++ b/xen/drivers/char/ns16550.c
> @@ -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)
> --- a/xen/drivers/passthrough/iommu.c
> +++ b/xen/drivers/passthrough/iommu.c
> @@ -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",
> --- a/xen/drivers/passthrough/pci.c
> +++ b/xen/drivers/passthrough/pci.c
> @@ -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));
>          }
>      }
>  
> --- a/xen/drivers/video/vga.c
> +++ b/xen/drivers/video/vga.c
> @@ -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 )
>      {
> --- a/xen/include/xen/pci.h
> +++ b/xen/include/xen/pci.h
> @@ -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-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2012-09-11 13:12 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-11 11:33 [PATCH] PCI: don't allow guest assignment of devices used by Xen Jan Beulich
2012-09-11 13:12 ` Keir Fraser

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).