ia64/xen-unstable

changeset 17028:faefbf2c4840

vt-d: Remap interrupt for passthru device if such HW is detected on VT-d platforms.
Signed-off-by: Allen Kay <allen.m.kay@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Feb 11 10:51:41 2008 +0000 (2008-02-11)
parents e3d417c4786b
children bab9e298450a
files xen/arch/x86/hvm/vmx/vtd/Makefile xen/arch/x86/hvm/vmx/vtd/extern.h xen/arch/x86/hvm/vmx/vtd/intel-iommu.c xen/arch/x86/hvm/vmx/vtd/intremap.c xen/include/asm-x86/io_apic.h xen/include/asm-x86/iommu.h
line diff
     1.1 --- a/xen/arch/x86/hvm/vmx/vtd/Makefile	Mon Feb 11 10:50:57 2008 +0000
     1.2 +++ b/xen/arch/x86/hvm/vmx/vtd/Makefile	Mon Feb 11 10:51:41 2008 +0000
     1.3 @@ -3,3 +3,4 @@ obj-y += dmar.o
     1.4  obj-y += utils.o
     1.5  obj-y += io.o
     1.6  obj-y += qinval.o
     1.7 +obj-y += intremap.o
     2.1 --- a/xen/arch/x86/hvm/vmx/vtd/extern.h	Mon Feb 11 10:50:57 2008 +0000
     2.2 +++ b/xen/arch/x86/hvm/vmx/vtd/extern.h	Mon Feb 11 10:51:41 2008 +0000
     2.3 @@ -23,11 +23,6 @@
     2.4  
     2.5  #include "dmar.h"
     2.6  
     2.7 -extern int iommu_setup_done;
     2.8 -extern int vtd2_thurley_enabled;
     2.9 -extern int vtd2_qinval_enabled;
    2.10 -
    2.11 -extern spinlock_t ioapic_lock;
    2.12  extern struct qi_ctrl *qi_ctrl;
    2.13  extern struct ir_ctrl *ir_ctrl;
    2.14  
    2.15 @@ -37,6 +32,7 @@ void print_vtd_entries(struct domain *d,
    2.16  void pdev_flr(u8 bus, u8 devfn);
    2.17  
    2.18  int qinval_setup(struct iommu *iommu);
    2.19 +int intremap_setup(struct iommu *iommu);
    2.20  int queue_invalidate_context(struct iommu *iommu,
    2.21      u16 did, u16 source_id, u8 function_mask, u8 granu);
    2.22  int queue_invalidate_iotlb(struct iommu *iommu,
    2.23 @@ -46,7 +42,6 @@ int queue_invalidate_iec(struct iommu *i
    2.24  int invalidate_sync(struct iommu *iommu);
    2.25  int iommu_flush_iec_global(struct iommu *iommu);
    2.26  int iommu_flush_iec_index(struct iommu *iommu, u8 im, u16 iidx);
    2.27 -void gsi_remapping(unsigned int gsi);
    2.28  void print_iommu_regs(struct acpi_drhd_unit *drhd);
    2.29  int vtd_hw_check(void);
    2.30  struct iommu * ioapic_to_iommu(unsigned int apic_id);
     3.1 --- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c	Mon Feb 11 10:50:57 2008 +0000
     3.2 +++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c	Mon Feb 11 10:51:41 2008 +0000
     3.3 @@ -1816,9 +1816,13 @@ static int init_vtd_hw(void)
     3.4          flush->context = flush_context_reg;
     3.5          flush->iotlb = flush_iotlb_reg;
     3.6  
     3.7 -        if ( qinval_setup(iommu) != 0);
     3.8 +        if ( qinval_setup(iommu) != 0 )
     3.9              dprintk(XENLOG_ERR VTDPREFIX,
    3.10                      "Queued Invalidation hardware not found\n");
    3.11 +
    3.12 +        if ( intremap_setup(iommu) != 0 )
    3.13 +            dprintk(XENLOG_ERR VTDPREFIX,
    3.14 +                    "Interrupt Remapping hardware not found\n");
    3.15      }
    3.16      return 0;
    3.17  }
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xen/arch/x86/hvm/vmx/vtd/intremap.c	Mon Feb 11 10:51:41 2008 +0000
     4.3 @@ -0,0 +1,340 @@
     4.4 +/*
     4.5 + * Copyright (c) 2006, Intel Corporation.
     4.6 + *
     4.7 + * This program is free software; you can redistribute it and/or modify it
     4.8 + * under the terms and conditions of the GNU General Public License,
     4.9 + * version 2, as published by the Free Software Foundation.
    4.10 + *
    4.11 + * This program is distributed in the hope it will be useful, but WITHOUT
    4.12 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.13 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    4.14 + * more details.
    4.15 + *
    4.16 + * You should have received a copy of the GNU General Public License along with
    4.17 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    4.18 + * Place - Suite 330, Boston, MA 02111-1307 USA.
    4.19 + *
    4.20 + * Copyright (C) Allen Kay <allen.m.kay@intel.com>
    4.21 + * Copyright (C) Xiaohui Xin <xiaohui.xin@intel.com>
    4.22 + */
    4.23 +
    4.24 +#include <xen/config.h>
    4.25 +#include <xen/lib.h>
    4.26 +#include <xen/init.h>
    4.27 +#include <xen/irq.h>
    4.28 +#include <xen/delay.h>
    4.29 +#include <xen/sched.h>
    4.30 +#include <xen/acpi.h>
    4.31 +#include <xen/keyhandler.h>
    4.32 +#include <xen/spinlock.h>
    4.33 +#include <asm/io.h>
    4.34 +#include <asm/mc146818rtc.h>
    4.35 +#include <asm/smp.h>
    4.36 +#include <asm/desc.h>
    4.37 +#include <mach_apic.h>
    4.38 +#include <io_ports.h>
    4.39 +
    4.40 +#include <xen/spinlock.h>
    4.41 +#include <xen/xmalloc.h>
    4.42 +#include <xen/domain_page.h>
    4.43 +#include <asm/delay.h>
    4.44 +#include <asm/string.h>
    4.45 +#include <asm/iommu.h>
    4.46 +#include <asm/hvm/vmx/intel-iommu.h>
    4.47 +#include "dmar.h"
    4.48 +#include "vtd.h"
    4.49 +#include "pci-direct.h"
    4.50 +#include "pci_regs.h"
    4.51 +#include "msi.h"
    4.52 +#include "extern.h"
    4.53 +
    4.54 +u16 apicid_to_bdf(int apic_id)
    4.55 +{
    4.56 +    struct acpi_drhd_unit *drhd = ioapic_to_drhd(apic_id);
    4.57 +    struct acpi_ioapic_unit *acpi_ioapic_unit;
    4.58 +
    4.59 +    list_for_each_entry ( acpi_ioapic_unit, &drhd->ioapic_list, list )
    4.60 +        if ( acpi_ioapic_unit->apic_id == apic_id )
    4.61 +            return acpi_ioapic_unit->ioapic.info;
    4.62 +
    4.63 +    dprintk(XENLOG_ERR VTDPREFIX, "Didn't find the bdf for the apic_id!\n");
    4.64 +    return 0;
    4.65 +}
    4.66 +
    4.67 +static void remap_entry_to_ioapic_rte(
    4.68 +    struct iommu *iommu, struct IO_APIC_route_entry *old_rte)
    4.69 +{
    4.70 +    struct iremap_entry *iremap_entry = NULL;
    4.71 +    struct IO_APIC_route_remap_entry *remap_rte;
    4.72 +    unsigned int index;
    4.73 +    unsigned long flags;
    4.74 +    struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);
    4.75 +
    4.76 +    if ( ir_ctrl == NULL )
    4.77 +    {
    4.78 +        dprintk(XENLOG_ERR VTDPREFIX,
    4.79 +                "remap_entry_to_ioapic_rte: ir_ctl == NULL");
    4.80 +        return;
    4.81 +    }
    4.82 +
    4.83 +    remap_rte = (struct IO_APIC_route_remap_entry *) old_rte;
    4.84 +    index = (remap_rte->index_15 << 15) + remap_rte->index_0_14;
    4.85 +
    4.86 +    if ( index > ir_ctrl->iremap_index )
    4.87 +    {
    4.88 +        dprintk(XENLOG_ERR VTDPREFIX,
    4.89 +            "Index is larger than remap table entry size. Error!\n");
    4.90 +        return;
    4.91 +    }
    4.92 +
    4.93 +    spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);
    4.94 +
    4.95 +    iremap_entry = &ir_ctrl->iremap[index];
    4.96 +
    4.97 +    old_rte->vector = iremap_entry->lo.vector;
    4.98 +    old_rte->delivery_mode = iremap_entry->lo.dlm;
    4.99 +    old_rte->dest_mode = iremap_entry->lo.dm;
   4.100 +    old_rte->trigger = iremap_entry->lo.tm;
   4.101 +    old_rte->__reserved_2 = 0;
   4.102 +    old_rte->dest.logical.__reserved_1 = 0;
   4.103 +    old_rte->dest.logical.logical_dest = iremap_entry->lo.dst;
   4.104 +
   4.105 +    spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
   4.106 +}
   4.107 +
   4.108 +static void ioapic_rte_to_remap_entry(struct iommu *iommu,
   4.109 +    int apic_id, struct IO_APIC_route_entry *old_rte)
   4.110 +{
   4.111 +    struct iremap_entry *iremap_entry = NULL;
   4.112 +    struct IO_APIC_route_remap_entry *remap_rte;
   4.113 +    unsigned int index;
   4.114 +    unsigned long flags;
   4.115 +    int ret = 0;
   4.116 +    struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);
   4.117 +
   4.118 +    remap_rte = (struct IO_APIC_route_remap_entry *) old_rte;
   4.119 +    spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);
   4.120 +    index = ir_ctrl->iremap_index;
   4.121 +    if ( index > IREMAP_ENTRY_NR - 1 )
   4.122 +    {
   4.123 +        dprintk(XENLOG_ERR VTDPREFIX,
   4.124 +               "The interrupt number is more than 256!\n");
   4.125 +        goto out;
   4.126 +    }
   4.127 +
   4.128 +    iremap_entry = &(ir_ctrl->iremap[index]);
   4.129 +    if ( *(u64 *)iremap_entry != 0 )
   4.130 +        dprintk(XENLOG_WARNING VTDPREFIX,
   4.131 +               "Interrupt remapping entry is in use already!\n");
   4.132 +    iremap_entry->lo.fpd = 0;
   4.133 +    iremap_entry->lo.dm = old_rte->dest_mode;
   4.134 +    iremap_entry->lo.rh = 0;
   4.135 +    iremap_entry->lo.tm = old_rte->trigger;
   4.136 +    iremap_entry->lo.dlm = old_rte->delivery_mode;
   4.137 +    iremap_entry->lo.avail = 0;
   4.138 +    iremap_entry->lo.res_1 = 0;
   4.139 +    iremap_entry->lo.vector = old_rte->vector;
   4.140 +    iremap_entry->lo.res_2 = 0;
   4.141 +    iremap_entry->lo.dst = (old_rte->dest.logical.logical_dest << 8);
   4.142 +    iremap_entry->hi.sid = apicid_to_bdf(apic_id);
   4.143 +    iremap_entry->hi.sq = 0;    /* comparing all 16-bit of SID */
   4.144 +    iremap_entry->hi.svt = 1;   /* turn on requestor ID verification SID/SQ */
   4.145 +    iremap_entry->hi.res_1 = 0;
   4.146 +    iremap_entry->lo.p = 1;    /* finally, set present bit */
   4.147 +    ir_ctrl->iremap_index++;
   4.148 +
   4.149 +    iommu_flush_iec_index(iommu, 0, index);
   4.150 +    ret = invalidate_sync(iommu);
   4.151 +
   4.152 +    /* now construct new ioapic rte entry */ 
   4.153 +    remap_rte->vector = old_rte->vector;
   4.154 +    remap_rte->delivery_mode = 0;    /* has to be 0 for remap format */ 
   4.155 +    remap_rte->index_15 = index & 0x8000;
   4.156 +    remap_rte->index_0_14 = index & 0x7fff;
   4.157 +    remap_rte->delivery_status = old_rte->delivery_status;
   4.158 +    remap_rte->polarity = old_rte->polarity;
   4.159 +    remap_rte->irr = old_rte->irr;
   4.160 +    remap_rte->trigger = old_rte->trigger;
   4.161 +    remap_rte->mask = 1;
   4.162 +    remap_rte->reserved = 0;
   4.163 +    remap_rte->format = 1;    /* indicate remap format */
   4.164 +out:
   4.165 +    spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags);
   4.166 +    return;
   4.167 +}
   4.168 +
   4.169 +unsigned int
   4.170 +io_apic_read_remap_rte(
   4.171 +    unsigned int apic, unsigned int reg)
   4.172 +{
   4.173 +    struct IO_APIC_route_entry old_rte = { 0 };
   4.174 +    struct IO_APIC_route_remap_entry *remap_rte;
   4.175 +    int rte_upper = (reg & 1) ? 1 : 0;
   4.176 +    struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid);
   4.177 +    struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);
   4.178 +
   4.179 +    if ( !iommu || !(ir_ctrl->iremap) )
   4.180 +    {
   4.181 +        *IO_APIC_BASE(apic) = reg;
   4.182 +        return *(IO_APIC_BASE(apic)+4);
   4.183 +    }
   4.184 +
   4.185 +    if ( rte_upper )
   4.186 +        reg--;
   4.187 +
   4.188 +    /* read lower and upper 32-bits of rte entry */
   4.189 +    *IO_APIC_BASE(apic) = reg;
   4.190 +    *(((u32 *)&old_rte) + 0) = *(IO_APIC_BASE(apic)+4);
   4.191 +    *IO_APIC_BASE(apic) = reg + 1;
   4.192 +    *(((u32 *)&old_rte) + 1) = *(IO_APIC_BASE(apic)+4);
   4.193 +
   4.194 +    remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte;
   4.195 +
   4.196 +    if ( remap_rte->mask || (remap_rte->format == 0) )
   4.197 +    {
   4.198 +        *IO_APIC_BASE(apic) = reg;
   4.199 +        return *(IO_APIC_BASE(apic)+4);
   4.200 +    }
   4.201 +
   4.202 +    remap_entry_to_ioapic_rte(iommu, &old_rte);
   4.203 +    if ( rte_upper )
   4.204 +    {
   4.205 +        *IO_APIC_BASE(apic) = reg + 1;
   4.206 +        return (*(((u32 *)&old_rte) + 1));
   4.207 +    }
   4.208 +    else
   4.209 +    {
   4.210 +        *IO_APIC_BASE(apic) = reg;
   4.211 +        return (*(((u32 *)&old_rte) + 0));
   4.212 +    }
   4.213 +}
   4.214 +
   4.215 +void
   4.216 +io_apic_write_remap_rte(
   4.217 +    unsigned int apic, unsigned int reg, unsigned int value)
   4.218 +{
   4.219 +    struct IO_APIC_route_entry old_rte = { 0 };
   4.220 +    struct IO_APIC_route_remap_entry *remap_rte;
   4.221 +    int rte_upper = (reg & 1) ? 1 : 0;
   4.222 +    struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid);
   4.223 +    struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu);
   4.224 +
   4.225 +    if ( !iommu || !(ir_ctrl->iremap) )
   4.226 +    {
   4.227 +        *IO_APIC_BASE(apic) = reg;
   4.228 +        *(IO_APIC_BASE(apic)+4) = value;
   4.229 +        return;
   4.230 +    }
   4.231 +
   4.232 +    if ( rte_upper )
   4.233 +        reg--;
   4.234 +
   4.235 +    /* read both lower and upper 32-bits of rte entry */
   4.236 +    *IO_APIC_BASE(apic) = reg;
   4.237 +    *(((u32 *)&old_rte) + 0) = *(IO_APIC_BASE(apic)+4);
   4.238 +    *IO_APIC_BASE(apic) = reg + 1;
   4.239 +    *(((u32 *)&old_rte) + 1) = *(IO_APIC_BASE(apic)+4);
   4.240 +
   4.241 +    remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte;
   4.242 +    if ( remap_rte->mask || (remap_rte->format == 0) )
   4.243 +    {
   4.244 +        *IO_APIC_BASE(apic) = rte_upper ? ++reg : reg;
   4.245 +        *(IO_APIC_BASE(apic)+4) = value;
   4.246 +        return;
   4.247 +    }
   4.248 +
   4.249 +    *(((u32 *)&old_rte) + rte_upper) = value;
   4.250 +    ioapic_rte_to_remap_entry(iommu, mp_ioapics[apic].mpc_apicid, &old_rte);
   4.251 +
   4.252 +    /* write new entry to ioapic */
   4.253 +    *IO_APIC_BASE(apic) = reg;
   4.254 +    *(IO_APIC_BASE(apic)+4) = *(((int *)&old_rte)+0);
   4.255 +    *IO_APIC_BASE(apic) = reg + 1;
   4.256 +    *(IO_APIC_BASE(apic)+4) = *(((int *)&old_rte)+1);
   4.257 +}
   4.258 +
   4.259 +int intremap_setup(struct iommu *iommu)
   4.260 +{
   4.261 +    struct ir_ctrl *ir_ctrl;
   4.262 +    unsigned long start_time;
   4.263 +    u64 paddr;
   4.264 +
   4.265 +    if ( !ecap_intr_remap(iommu->ecap) )
   4.266 +        return -ENODEV;
   4.267 +
   4.268 +    ir_ctrl = iommu_ir_ctrl(iommu);
   4.269 +    if ( ir_ctrl->iremap == NULL )
   4.270 +    {
   4.271 +        ir_ctrl->iremap = alloc_xenheap_page();
   4.272 +        if ( ir_ctrl->iremap == NULL )
   4.273 +        {
   4.274 +            dprintk(XENLOG_WARNING VTDPREFIX,
   4.275 +                    "Cannot allocate memory for ir_ctrl->iremap\n");
   4.276 +            return -ENODEV;
   4.277 +        }
   4.278 +        memset(ir_ctrl->iremap, 0, PAGE_SIZE);
   4.279 +    }
   4.280 +
   4.281 +    paddr = virt_to_maddr(ir_ctrl->iremap);
   4.282 +#if defined(ENABLED_EXTENDED_INTERRUPT_SUPPORT)
   4.283 +    /* set extended interrupt mode bit */
   4.284 +    paddr |= ecap_ext_intr(iommu->ecap) ? (1 << IRTA_REG_EIMI_SHIFT) : 0;
   4.285 +#endif
   4.286 +    /* size field = 256 entries per 4K page = 8 - 1 */
   4.287 +    paddr |= 7;
   4.288 +    dmar_writeq(iommu->reg, DMAR_IRTA_REG, paddr);
   4.289 +
   4.290 +    /* set SIRTP */
   4.291 +    iommu->gcmd |= DMA_GCMD_SIRTP;
   4.292 +    dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
   4.293 +
   4.294 +    /* Make sure hardware complete it */
   4.295 +    start_time = jiffies;
   4.296 +    while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_SIRTPS) )
   4.297 +    {
   4.298 +        if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) )
   4.299 +        {
   4.300 +            dprintk(XENLOG_ERR VTDPREFIX,
   4.301 +                    "Cannot set SIRTP field for interrupt remapping\n");
   4.302 +            return -ENODEV;
   4.303 +        }
   4.304 +        cpu_relax();
   4.305 +    }
   4.306 +
   4.307 +    /* enable comaptiblity format interrupt pass through */
   4.308 +    iommu->gcmd |= DMA_GCMD_CFI;
   4.309 +    dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
   4.310 +
   4.311 +    start_time = jiffies;
   4.312 +    while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_CFIS) )
   4.313 +    {
   4.314 +        if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) )
   4.315 +        {
   4.316 +            dprintk(XENLOG_ERR VTDPREFIX,
   4.317 +                    "Cannot set CFI field for interrupt remapping\n");
   4.318 +            return -ENODEV;
   4.319 +        }
   4.320 +        cpu_relax();
   4.321 +    }
   4.322 +
   4.323 +    /* enable interrupt remapping hardware */
   4.324 +    iommu->gcmd |= DMA_GCMD_IRE;
   4.325 +    dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd);
   4.326 +
   4.327 +    start_time = jiffies;
   4.328 +    while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_IRES) )
   4.329 +    {
   4.330 +        if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) )
   4.331 +        {
   4.332 +            dprintk(XENLOG_ERR VTDPREFIX,
   4.333 +                    "Cannot set IRE field for interrupt remapping\n");
   4.334 +            return -ENODEV;
   4.335 +        }
   4.336 +        cpu_relax();
   4.337 +    }
   4.338 +
   4.339 +    /* After set SIRTP, we should do globally invalidate the IEC */
   4.340 +    iommu_flush_iec_global(iommu);
   4.341 +
   4.342 +    return 0;
   4.343 +}
     5.1 --- a/xen/include/asm-x86/io_apic.h	Mon Feb 11 10:50:57 2008 +0000
     5.2 +++ b/xen/include/asm-x86/io_apic.h	Mon Feb 11 10:51:41 2008 +0000
     5.3 @@ -6,6 +6,7 @@
     5.4  #include <asm/mpspec.h>
     5.5  #include <asm/apicdef.h>
     5.6  #include <asm/fixmap.h>
     5.7 +#include <asm/iommu.h>
     5.8  
     5.9  /*
    5.10   * Intel IO-APIC support for SMP and UP systems.
    5.11 @@ -124,12 +125,16 @@ extern int mpc_default_type;
    5.12  
    5.13  static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
    5.14  {
    5.15 +	if (vtd_enabled)
    5.16 +		return io_apic_read_remap_rte(apic, reg);
    5.17  	*IO_APIC_BASE(apic) = reg;
    5.18  	return *(IO_APIC_BASE(apic)+4);
    5.19  }
    5.20  
    5.21  static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
    5.22  {
    5.23 +	if (vtd_enabled)
    5.24 +		return io_apic_write_remap_rte(apic, reg, value);
    5.25  	*IO_APIC_BASE(apic) = reg;
    5.26  	*(IO_APIC_BASE(apic)+4) = value;
    5.27  }
     6.1 --- a/xen/include/asm-x86/iommu.h	Mon Feb 11 10:50:57 2008 +0000
     6.2 +++ b/xen/include/asm-x86/iommu.h	Mon Feb 11 10:51:41 2008 +0000
     6.3 @@ -81,6 +81,10 @@ int hvm_do_IRQ_dpci(struct domain *d, un
     6.4  int dpci_ioport_intercept(ioreq_t *p);
     6.5  int pt_irq_create_bind_vtd(struct domain *d,
     6.6                             xen_domctl_bind_pt_irq_t *pt_irq_bind);
     6.7 +unsigned int io_apic_read_remap_rte(
     6.8 +    unsigned int apic, unsigned int reg);
     6.9 +void io_apic_write_remap_rte(unsigned int apic,
    6.10 +    unsigned int reg, unsigned int value);
    6.11  
    6.12  #define PT_IRQ_TIME_OUT MILLISECS(8)
    6.13  #define VTDPREFIX "[VT-D]"