[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
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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |