⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci.c

📁 xen虚拟机源代码安装包
💻 C
字号:
/* * Copyright (C) 2008,  Netronome Systems, Inc. *                 * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. */#include <xen/sched.h>#include <xen/pci.h>#include <xen/pci_regs.h>#include <xen/list.h>#include <xen/prefetch.h>#include <xen/iommu.h>#include <xen/delay.h>#include <xen/keyhandler.h>LIST_HEAD(alldevs_list);rwlock_t pcidevs_lock = RW_LOCK_UNLOCKED;struct pci_dev *alloc_pdev(u8 bus, u8 devfn){    struct pci_dev *pdev;    list_for_each_entry ( pdev, &alldevs_list, alldevs_list )        if ( pdev->bus == bus && pdev->devfn == devfn )            return pdev;    pdev = xmalloc(struct pci_dev);    if ( !pdev )        return NULL;    *((u8*) &pdev->bus) = bus;    *((u8*) &pdev->devfn) = devfn;    pdev->domain = NULL;    spin_lock_init(&pdev->lock);    INIT_LIST_HEAD(&pdev->msi_list);    list_add(&pdev->alldevs_list, &alldevs_list);    return pdev;}void free_pdev(struct pci_dev *pdev){    list_del(&pdev->alldevs_list);    xfree(pdev);}struct pci_dev *pci_lock_pdev(int bus, int devfn){    struct pci_dev *pdev;    read_lock(&pcidevs_lock);    list_for_each_entry ( pdev, &alldevs_list, alldevs_list )        if ( (pdev->bus == bus || bus == -1) &&             (pdev->devfn == devfn || devfn == -1) )    {        spin_lock(&pdev->lock);        read_unlock(&pcidevs_lock);        return pdev;    }    read_unlock(&pcidevs_lock);    return NULL;}struct pci_dev *pci_lock_domain_pdev(struct domain *d, int bus, int devfn){    struct pci_dev *pdev;    read_lock(&pcidevs_lock);    list_for_each_entry ( pdev, &d->arch.pdev_list, domain_list )    {        spin_lock(&pdev->lock);        if ( (pdev->bus == bus || bus == -1) &&             (pdev->devfn == devfn || devfn == -1) &&             (pdev->domain == d) )        {            read_unlock(&pcidevs_lock);            return pdev;        }        spin_unlock(&pdev->lock);    }    read_unlock(&pcidevs_lock);    return NULL;}int pci_add_device(u8 bus, u8 devfn){    struct pci_dev *pdev;    int ret = -ENOMEM;    write_lock(&pcidevs_lock);    pdev = alloc_pdev(bus, devfn);    if ( !pdev )        goto out;    ret = 0;    spin_lock(&pdev->lock);    if ( !pdev->domain )    {        pdev->domain = dom0;        ret = iommu_add_device(pdev);        if ( ret )        {            spin_unlock(&pdev->lock);            goto out;        }        list_add(&pdev->domain_list, &dom0->arch.pdev_list);    }    spin_unlock(&pdev->lock);    printk(XENLOG_DEBUG "PCI add device %02x:%02x.%x\n", bus,           PCI_SLOT(devfn), PCI_FUNC(devfn));out:    write_unlock(&pcidevs_lock);    return ret;}int pci_remove_device(u8 bus, u8 devfn){    struct pci_dev *pdev;    int ret = -ENODEV;;    write_lock(&pcidevs_lock);    list_for_each_entry ( pdev, &alldevs_list, alldevs_list )        if ( pdev->bus == bus && pdev->devfn == devfn )        {            spin_lock(&pdev->lock);            ret = iommu_remove_device(pdev);            if ( pdev->domain )                list_del(&pdev->domain_list);            pci_cleanup_msi(pdev);            free_pdev(pdev);            printk(XENLOG_DEBUG "PCI remove device %02x:%02x.%x\n", bus,                   PCI_SLOT(devfn), PCI_FUNC(devfn));            break;        }    write_unlock(&pcidevs_lock);    return ret;}static void pci_clean_dpci_irqs(struct domain *d){    struct hvm_irq_dpci *hvm_irq_dpci = domain_get_irq_dpci(d);    uint32_t i;    struct list_head *digl_list, *tmp;    struct dev_intx_gsi_link *digl;    if ( !iommu_enabled )        return;    if ( !is_hvm_domain(d) && !need_iommu(d) )        return;    if ( hvm_irq_dpci != NULL )    {        for ( i = 0; i < NR_IRQS; i++ )        {            if ( !(hvm_irq_dpci->mirq[i].flags & HVM_IRQ_DPCI_VALID) )                continue;            pirq_guest_unbind(d, i);            kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(i)]);            list_for_each_safe ( digl_list, tmp,                                 &hvm_irq_dpci->mirq[i].digl_list )            {                digl = list_entry(digl_list,                                  struct dev_intx_gsi_link, list);                list_del(&digl->list);                xfree(digl);            }        }        d->arch.hvm_domain.irq.dpci = NULL;        xfree(hvm_irq_dpci);    }}void pci_release_devices(struct domain *d){    struct pci_dev *pdev;    u8 bus, devfn;    pci_clean_dpci_irqs(d);    while ( (pdev = pci_lock_domain_pdev(d, -1, -1)) )    {        pci_cleanup_msi(pdev);        bus = pdev->bus; devfn = pdev->devfn;        spin_unlock(&pdev->lock);        deassign_device(d, bus, devfn);    }}static void dump_pci_devices(unsigned char ch){    struct pci_dev *pdev;    struct msi_desc *msi;    printk("==== PCI devices ====\n");    read_lock(&pcidevs_lock);    list_for_each_entry ( pdev, &alldevs_list, alldevs_list )    {        spin_lock(&pdev->lock);        printk("%02x:%02x.%x - dom %-3d - MSIs < ",               pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),               pdev->domain ? pdev->domain->domain_id : -1);        list_for_each_entry ( msi, &pdev->msi_list, list )               printk("%d ", msi->vector);        printk(">\n");        spin_unlock(&pdev->lock);    }    read_unlock(&pcidevs_lock);}static int __init setup_dump_pcidevs(void){    register_keyhandler('Q', dump_pci_devices, "dump PCI devices");    return 0;}__initcall(setup_dump_pcidevs);/* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * indent-tabs-mode: nil * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -