* 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.
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)
}
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)
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)
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",
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);
__set_bit(PCI_BDF2(bus, devfn), pseg->ro_map);
arch_pci_ro_device(seg, PCI_BDF2(bus, devfn));
+ _pci_hide_device(pdev);
return 0;
}
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));
}
}
#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. */
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 )
{
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);