From: Keir Fraser <keir@xen.org>
To: Jan Beulich <JBeulich@suse.com>, xen-devel <xen-devel@lists.xen.org>
Subject: Re: [PATCH] PCI: don't allow guest assignment of devices used by Xen
Date: Tue, 11 Sep 2012 14:12:06 +0100 [thread overview]
Message-ID: <CC74F736.4B6F7%keir@xen.org> (raw)
In-Reply-To: <504F3DB3020000780009A8CB@nat28.tlf.novell.com>
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
prev parent reply other threads:[~2012-09-11 13:12 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
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 message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CC74F736.4B6F7%keir@xen.org \
--to=keir@xen.org \
--cc=JBeulich@suse.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).