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

Re: [Xen-devel] [PATCH] PCI: don't allow guest assignment of devices used by Xen


  • To: Jan Beulich <JBeulich@xxxxxxxx>, xen-devel <xen-devel@xxxxxxxxxxxxx>
  • From: Keir Fraser <keir@xxxxxxx>
  • Date: Tue, 11 Sep 2012 14:12:06 +0100
  • Delivery-date: Tue, 11 Sep 2012 13:12:50 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>
  • Thread-index: Ac2QHwqc7Wd3EgombUi4EGijej81Vw==
  • Thread-topic: [Xen-devel] [PATCH] PCI: don't allow guest assignment of devices used by Xen

On 11/09/2012 12:33, "Jan Beulich" <JBeulich@xxxxxxxx> 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@xxxxxxxx>

Acked-by: Keir Fraser <keir@xxxxxxx>

> ---
> 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@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel



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


 


Rackspace

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