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

📄 intremap.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2006, Intel Corporation. * * 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. * * Copyright (C) Allen Kay <allen.m.kay@intel.com> * Copyright (C) Xiaohui Xin <xiaohui.xin@intel.com> */#include <xen/irq.h>#include <xen/sched.h>#include <xen/iommu.h>#include <xen/time.h>#include <xen/pci.h>#include <xen/pci_regs.h>#include <asm/msi.h>#include "iommu.h"#include "dmar.h"#include "vtd.h"#include "extern.h"u16 apicid_to_bdf(int apic_id){    struct acpi_drhd_unit *drhd = ioapic_to_drhd(apic_id);    struct acpi_ioapic_unit *acpi_ioapic_unit;    list_for_each_entry ( acpi_ioapic_unit, &drhd->ioapic_list, list )        if ( acpi_ioapic_unit->apic_id == apic_id )            return acpi_ioapic_unit->ioapic.info;    dprintk(XENLOG_ERR VTDPREFIX, "Didn't find the bdf for the apic_id!\n");    return 0;}static void remap_entry_to_ioapic_rte(    struct iommu *iommu, struct IO_APIC_route_entry *old_rte){    struct iremap_entry *iremap_entry = NULL, *iremap_entries;    struct IO_APIC_route_remap_entry *remap_rte;    int index = 0;    unsigned long flags;    struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);    if ( ir_ctrl == NULL )    {        dprintk(XENLOG_ERR VTDPREFIX,                "remap_entry_to_ioapic_rte: ir_ctl is not ready\n");        return;    }    remap_rte = (struct IO_APIC_route_remap_entry *) old_rte;    index = (remap_rte->index_15 << 15) | remap_rte->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];    old_rte->vector = iremap_entry->lo.vector;    old_rte->delivery_mode = iremap_entry->lo.dlm;    old_rte->dest_mode = iremap_entry->lo.dm;    old_rte->trigger = iremap_entry->lo.tm;    old_rte->__reserved_2 = 0;    old_rte->dest.logical.__reserved_1 = 0;    old_rte->dest.logical.logical_dest = iremap_entry->lo.dst >> 8;    unmap_vtd_domain_page(iremap_entries);    spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);}static void ioapic_rte_to_remap_entry(struct iommu *iommu,    int apic_id, struct IO_APIC_route_entry *old_rte,    unsigned int rte_upper, unsigned int value){    struct iremap_entry *iremap_entry = NULL, *iremap_entries;    struct iremap_entry new_ire;    struct IO_APIC_route_remap_entry *remap_rte;    struct IO_APIC_route_entry new_rte;    int index;    unsigned long flags;    struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);    remap_rte = (struct IO_APIC_route_remap_entry *) old_rte;    spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);    if ( remap_rte->format == 0 )    {        ir_ctrl->iremap_index++;        index = ir_ctrl->iremap_index;    }    else        index = (remap_rte->index_15 << 15) | remap_rte->index_0_14;    if ( index > IREMAP_ENTRY_NR - 1 )        panic("ioapic_rte_to_remap_entry: intremap index is more than 256!\n");    iremap_entries =        (struct iremap_entry *)map_vtd_domain_page(ir_ctrl->iremap_maddr);    iremap_entry = &iremap_entries[index];    memcpy(&new_ire, iremap_entry, sizeof(struct iremap_entry));    if ( rte_upper )        new_ire.lo.dst = (value >> 24) << 8;    else    {        *(((u32 *)&new_rte) + 0) = value;        new_ire.lo.fpd = 0;        new_ire.lo.dm = new_rte.dest_mode;        new_ire.lo.rh = 0;        new_ire.lo.tm = new_rte.trigger;        new_ire.lo.dlm = new_rte.delivery_mode;        new_ire.lo.avail = 0;        new_ire.lo.res_1 = 0;        new_ire.lo.vector = new_rte.vector;        new_ire.lo.res_2 = 0;        new_ire.hi.sid = apicid_to_bdf(apic_id);        new_ire.hi.sq = 0;    /* comparing all 16-bit of SID */        new_ire.hi.svt = 1;   /* requestor ID verification SID/SQ */        new_ire.hi.res_1 = 0;        new_ire.lo.p = 1;     /* finally, set present bit */        /* now construct new ioapic rte entry */        remap_rte->vector = new_rte.vector;        remap_rte->delivery_mode = 0;    /* has to be 0 for remap format */        remap_rte->index_15 = (index >> 15) & 0x1;        remap_rte->index_0_14 = index & 0x7fff;        remap_rte->delivery_status = new_rte.delivery_status;        remap_rte->polarity = new_rte.polarity;        remap_rte->irr = new_rte.irr;        remap_rte->trigger = new_rte.trigger;        remap_rte->mask = new_rte.mask;        remap_rte->reserved = 0;        remap_rte->format = 1;    /* indicate remap format */    }    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;}unsigned int io_apic_read_remap_rte(    unsigned int apic, unsigned int reg){    struct IO_APIC_route_entry old_rte = { 0 };    struct IO_APIC_route_remap_entry *remap_rte;    int rte_upper = (reg & 1) ? 1 : 0;    struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid);    struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);    if ( !iommu || !ir_ctrl || ir_ctrl->iremap_maddr == 0 ||         ir_ctrl->iremap_index == -1 )    {        *IO_APIC_BASE(apic) = reg;        return *(IO_APIC_BASE(apic)+4);    }    if ( rte_upper )        reg--;    /* read lower and upper 32-bits of rte entry */    *IO_APIC_BASE(apic) = reg;    *(((u32 *)&old_rte) + 0) = *(IO_APIC_BASE(apic)+4);    *IO_APIC_BASE(apic) = reg + 1;    *(((u32 *)&old_rte) + 1) = *(IO_APIC_BASE(apic)+4);    remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte;    if ( remap_rte->mask || (remap_rte->format == 0) )    {        *IO_APIC_BASE(apic) = reg;        return *(IO_APIC_BASE(apic)+4);    }    remap_entry_to_ioapic_rte(iommu, &old_rte);    if ( rte_upper )    {        *IO_APIC_BASE(apic) = reg + 1;        return (*(((u32 *)&old_rte) + 1));    }    else    {        *IO_APIC_BASE(apic) = reg;        return (*(((u32 *)&old_rte) + 0));    }}void io_apic_write_remap_rte(    unsigned int apic, unsigned int reg, unsigned int value){    struct IO_APIC_route_entry old_rte = { 0 };    struct IO_APIC_route_remap_entry *remap_rte;    unsigned int rte_upper = (reg & 1) ? 1 : 0;    struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid);    struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);    int saved_mask;    if ( !iommu || !ir_ctrl || ir_ctrl->iremap_maddr == 0 )    {        *IO_APIC_BASE(apic) = reg;        *(IO_APIC_BASE(apic)+4) = value;        return;    }    if ( rte_upper )        reg--;    /* read both lower and upper 32-bits of rte entry */    *IO_APIC_BASE(apic) = reg;    *(((u32 *)&old_rte) + 0) = *(IO_APIC_BASE(apic)+4);    *IO_APIC_BASE(apic) = reg + 1;    *(((u32 *)&old_rte) + 1) = *(IO_APIC_BASE(apic)+4);    remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte;    /* mask the interrupt while we change the intremap table */    saved_mask = remap_rte->mask;    remap_rte->mask = 1;    *IO_APIC_BASE(apic) = reg;    *(IO_APIC_BASE(apic)+4) = *(((int *)&old_rte)+0);    remap_rte->mask = saved_mask;    ioapic_rte_to_remap_entry(iommu, mp_ioapics[apic].mpc_apicid,                              &old_rte, rte_upper, value);    /* write new entry to ioapic */    *IO_APIC_BASE(apic) = reg;    *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+0);    *IO_APIC_BASE(apic) = reg + 1;    *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+1);}static void remap_entry_to_msi_msg(

⌨️ 快捷键说明

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