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

📄 intremap.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 2 页
字号:
    struct iommu *iommu, struct msi_msg *msg){    struct iremap_entry *iremap_entry = NULL, *iremap_entries;    struct msi_msg_remap_entry *remap_rte;    int index;    unsigned long flags;    struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);    if ( ir_ctrl == NULL )    {        dprintk(XENLOG_ERR VTDPREFIX,                "remap_entry_to_msi_msg: ir_ctl == NULL");        return;    }    remap_rte = (struct msi_msg_remap_entry *) msg;    index = (remap_rte->address_lo.index_15 << 15) |             remap_rte->address_lo.index_0_14;    if ( index > ir_ctrl->iremap_index )        panic("%s: index (%d) is larger than remap table entry size (%d)\n",              __func__, index, ir_ctrl->iremap_index);    spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);    iremap_entries =        (struct iremap_entry *)map_vtd_domain_page(ir_ctrl->iremap_maddr);    iremap_entry = &iremap_entries[index];    msg->address_hi = MSI_ADDR_BASE_HI;    msg->address_lo =        MSI_ADDR_BASE_LO |        ((iremap_entry->lo.dm == 0) ?            MSI_ADDR_DESTMODE_PHYS:            MSI_ADDR_DESTMODE_LOGIC) |        ((iremap_entry->lo.dlm != dest_LowestPrio) ?            MSI_ADDR_REDIRECTION_CPU:            MSI_ADDR_REDIRECTION_LOWPRI) |        iremap_entry->lo.dst >> 8;    msg->data =        MSI_DATA_TRIGGER_EDGE |        MSI_DATA_LEVEL_ASSERT |        ((iremap_entry->lo.dlm != dest_LowestPrio) ?            MSI_DATA_DELIVERY_FIXED:            MSI_DATA_DELIVERY_LOWPRI) |        iremap_entry->lo.vector;    unmap_vtd_domain_page(iremap_entries);    spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);}static void msi_msg_to_remap_entry(    struct iommu *iommu, struct pci_dev *pdev, struct msi_msg *msg){    struct iremap_entry *iremap_entry = NULL, *iremap_entries;    struct iremap_entry new_ire;    struct msi_msg_remap_entry *remap_rte;    unsigned int index;    unsigned long flags;    struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);    int i = 0;    remap_rte = (struct msi_msg_remap_entry *) msg;    spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);    iremap_entries =        (struct iremap_entry *)map_vtd_domain_page(ir_ctrl->iremap_maddr);    /* If the entry for a PCI device has been there, use the old entry,     * Or, assign a new entry for it.     */    for ( i = 0; i <= ir_ctrl->iremap_index; i++ )    {        iremap_entry = &iremap_entries[i];        if ( iremap_entry->hi.sid ==             ((pdev->bus << 8) | pdev->devfn) )           break;    }    if ( i > ir_ctrl->iremap_index )    {    	ir_ctrl->iremap_index++;        index = ir_ctrl->iremap_index;    }    else        index = i;    if ( index > IREMAP_ENTRY_NR - 1 )        panic("msi_msg_to_remap_entry: intremap index is more than 256!\n");    iremap_entry = &iremap_entries[index];    memcpy(&new_ire, iremap_entry, sizeof(struct iremap_entry));    /* Set interrupt remapping table entry */    new_ire.lo.fpd = 0;    new_ire.lo.dm = (msg->address_lo >> MSI_ADDR_DESTMODE_SHIFT) & 0x1;    new_ire.lo.rh = 0;    new_ire.lo.tm = (msg->data >> MSI_DATA_TRIGGER_SHIFT) & 0x1;    new_ire.lo.dlm = (msg->data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x1;    new_ire.lo.avail = 0;    new_ire.lo.res_1 = 0;    new_ire.lo.vector = (msg->data >> MSI_DATA_VECTOR_SHIFT) &                        MSI_DATA_VECTOR_MASK;    new_ire.lo.res_2 = 0;    new_ire.lo.dst = ((msg->address_lo >> MSI_ADDR_DEST_ID_SHIFT)                      & 0xff) << 8;    new_ire.hi.sid = (pdev->bus << 8) | pdev->devfn;    new_ire.hi.sq = 0;    new_ire.hi.svt = 1;    new_ire.hi.res_1 = 0;    new_ire.lo.p = 1;    /* finally, set present bit */    /* now construct new MSI/MSI-X rte entry */    remap_rte->address_lo.dontcare = 0;    remap_rte->address_lo.index_15 = (index >> 15) & 0x1;    remap_rte->address_lo.index_0_14 = index & 0x7fff;    remap_rte->address_lo.SHV = 1;    remap_rte->address_lo.format = 1;    remap_rte->address_hi = 0;    remap_rte->data = 0;    memcpy(iremap_entry, &new_ire, sizeof(struct iremap_entry));    iommu_flush_cache_entry(iremap_entry);    iommu_flush_iec_index(iommu, 0, index);    invalidate_sync(iommu);    unmap_vtd_domain_page(iremap_entries);    spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);    return;}void msi_msg_read_remap_rte(    struct msi_desc *msi_desc, struct msi_msg *msg){    struct pci_dev *pdev = msi_desc->dev;    struct acpi_drhd_unit *drhd = NULL;    struct iommu *iommu = NULL;    struct ir_ctrl *ir_ctrl;    drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn);    iommu = drhd->iommu;    ir_ctrl = iommu_ir_ctrl(iommu);    if ( !iommu || !ir_ctrl || ir_ctrl->iremap_maddr == 0 )        return;    remap_entry_to_msi_msg(iommu, msg);}void msi_msg_write_remap_rte(    struct msi_desc *msi_desc, struct msi_msg *msg){    struct pci_dev *pdev = msi_desc->dev;    struct acpi_drhd_unit *drhd = NULL;    struct iommu *iommu = NULL;    struct ir_ctrl *ir_ctrl;    drhd = acpi_find_matched_drhd_unit(pdev->bus, pdev->devfn);    iommu = drhd->iommu;    ir_ctrl = iommu_ir_ctrl(iommu);    if ( !iommu || !ir_ctrl || ir_ctrl->iremap_maddr == 0 )        return;    msi_msg_to_remap_entry(iommu, pdev, msg);}int intremap_setup(struct iommu *iommu){    struct ir_ctrl *ir_ctrl;    s_time_t start_time;    if ( !ecap_intr_remap(iommu->ecap) )        return -ENODEV;    ir_ctrl = iommu_ir_ctrl(iommu);    if ( ir_ctrl->iremap_maddr == 0 )    {        ir_ctrl->iremap_maddr = alloc_pgtable_maddr();        if ( ir_ctrl->iremap_maddr == 0 )        {            dprintk(XENLOG_WARNING VTDPREFIX,                    "Cannot allocate memory for ir_ctrl->iremap_maddr\n");            return -ENODEV;        }        ir_ctrl->iremap_index = -1;    }#if defined(ENABLED_EXTENDED_INTERRUPT_SUPPORT)    /* set extended interrupt mode bit */    ir_ctrl->iremap_maddr |=            ecap_ext_intr(iommu->ecap) ? (1 << IRTA_REG_EIMI_SHIFT) : 0;#endif    /* size field = 256 entries per 4K page = 8 - 1 */    ir_ctrl->iremap_maddr |= 7;    dmar_writeq(iommu->reg, DMAR_IRTA_REG, ir_ctrl->iremap_maddr);    /* set SIRTP */    iommu->gcmd |= DMA_GCMD_SIRTP;    dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);    /* Make sure hardware complete it */    start_time = NOW();    while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_SIRTPS) )    {        if ( NOW() > (start_time + DMAR_OPERATION_TIMEOUT) )        {            dprintk(XENLOG_ERR VTDPREFIX,                    "Cannot set SIRTP field for interrupt remapping\n");            return -ENODEV;        }        cpu_relax();    }    /* enable comaptiblity format interrupt pass through */    iommu->gcmd |= DMA_GCMD_CFI;    dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);    start_time = NOW();    while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_CFIS) )    {        if ( NOW() > (start_time + DMAR_OPERATION_TIMEOUT) )        {            dprintk(XENLOG_ERR VTDPREFIX,                    "Cannot set CFI field for interrupt remapping\n");            return -ENODEV;        }        cpu_relax();    }    /* enable interrupt remapping hardware */    iommu->gcmd |= DMA_GCMD_IRE;    dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);    start_time = NOW();    while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_IRES) )    {        if ( NOW() > (start_time + DMAR_OPERATION_TIMEOUT) )         {            dprintk(XENLOG_ERR VTDPREFIX,                    "Cannot set IRE field for interrupt remapping\n");            return -ENODEV;        }        cpu_relax();    }    /* After set SIRTP, we should do globally invalidate the IEC */    iommu_flush_iec_global(iommu);    return 0;}

⌨️ 快捷键说明

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