ia64/xen-unstable

changeset 18037:1e24033fb775

amd iommu: add interrupt remapping support
Signed-off-by: Wei Wang <wei.wang2@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jul 11 12:48:45 2008 +0100 (2008-07-11)
parents a762b4aed1a8
children bcef824afe1a
files xen/drivers/passthrough/amd/Makefile xen/drivers/passthrough/amd/iommu_intr.c xen/drivers/passthrough/amd/iommu_map.c xen/drivers/passthrough/amd/pci_amd_iommu.c xen/include/asm-x86/hvm/svm/amd-iommu-defs.h xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
line diff
     1.1 --- a/xen/drivers/passthrough/amd/Makefile	Fri Jul 11 12:47:50 2008 +0100
     1.2 +++ b/xen/drivers/passthrough/amd/Makefile	Fri Jul 11 12:48:45 2008 +0100
     1.3 @@ -3,3 +3,4 @@ obj-y += iommu_init.o
     1.4  obj-y += iommu_map.o
     1.5  obj-y += pci_amd_iommu.o
     1.6  obj-y += iommu_acpi.o
     1.7 +obj-y += iommu_intr.o
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/xen/drivers/passthrough/amd/iommu_intr.c	Fri Jul 11 12:48:45 2008 +0100
     2.3 @@ -0,0 +1,205 @@
     2.4 +/*
     2.5 + * Copyright (C) 2007 Advanced Micro Devices, Inc.
     2.6 + * Author: Wei Wang <wei.wang2@amd.com>
     2.7 + *
     2.8 + * This program is free software; you can redistribute it and/or modify
     2.9 + * it under the terms of the GNU General Public License as published by
    2.10 + * the Free Software Foundation; either version 2 of the License, or
    2.11 + * (at your option) any later version.
    2.12 + *
    2.13 + * This program is distributed in the hope that it will be useful,
    2.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.16 + * GNU General Public License for more details.
    2.17 + *
    2.18 + * You should have received a copy of the GNU General Public License
    2.19 + * along with this program; if not, write to the Free Software
    2.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    2.21 + */
    2.22 +
    2.23 +#include <xen/sched.h>
    2.24 +#include <xen/hvm/iommu.h>
    2.25 +#include <asm/amd-iommu.h>
    2.26 +#include <asm/hvm/svm/amd-iommu-proto.h>
    2.27 +
    2.28 +DEFINE_SPINLOCK(int_remap_table_lock);
    2.29 +void *int_remap_table = NULL;
    2.30 +
    2.31 +u8* get_intremap_entry(u8 vector, u8 dm)
    2.32 +{
    2.33 +    u8 *table;
    2.34 +    int offset = 0;
    2.35 +    table = (u8*)int_remap_table;
    2.36 +
    2.37 +    BUG_ON( !table );
    2.38 +    offset = (dm << INT_REMAP_INDEX_DM_SHIFT) & INT_REMAP_INDEX_DM_MASK;
    2.39 +    offset |= (vector << INT_REMAP_INDEX_VECTOR_SHIFT ) & 
    2.40 +        INT_REMAP_INDEX_VECTOR_MASK;
    2.41 +
    2.42 +    return (u8*) (table + offset);
    2.43 +}
    2.44 +
    2.45 +static void update_intremap_entry(u32* entry, u8 vector, u8 int_type,
    2.46 +    u8 dest_mode, u8 dest)
    2.47 +{
    2.48 +    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, 0,
    2.49 +                            INT_REMAP_ENTRY_REMAPEN_MASK,
    2.50 +                            INT_REMAP_ENTRY_REMAPEN_SHIFT, entry);
    2.51 +    set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, *entry,
    2.52 +                            INT_REMAP_ENTRY_SUPIOPF_MASK,
    2.53 +                            INT_REMAP_ENTRY_SUPIOPF_SHIFT, entry);
    2.54 +    set_field_in_reg_u32(int_type, *entry,
    2.55 +                            INT_REMAP_ENTRY_INTTYPE_MASK,
    2.56 +                            INT_REMAP_ENTRY_INTTYPE_SHIFT, entry);
    2.57 +    set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, *entry,
    2.58 +                            INT_REMAP_ENTRY_REQEOI_MASK,
    2.59 +                            INT_REMAP_ENTRY_REQEOI_SHIFT, entry);
    2.60 +    set_field_in_reg_u32((u32)dest_mode, *entry,
    2.61 +                            INT_REMAP_ENTRY_DM_MASK,
    2.62 +                            INT_REMAP_ENTRY_DM_SHIFT, entry);
    2.63 +    set_field_in_reg_u32((u32)dest, *entry,
    2.64 +                            INT_REMAP_ENTRY_DEST_MAST,
    2.65 +                            INT_REMAP_ENTRY_DEST_SHIFT, entry);
    2.66 +    set_field_in_reg_u32((u32)vector, *entry,
    2.67 +                            INT_REMAP_ENTRY_VECTOR_MASK,
    2.68 +                            INT_REMAP_ENTRY_VECTOR_SHIFT, entry);
    2.69 +}
    2.70 +
    2.71 +void invalidate_interrupt_table(struct amd_iommu *iommu, u16 device_id)
    2.72 +{
    2.73 +    u32 cmd[4], entry;
    2.74 +
    2.75 +    cmd[3] = cmd[2] = 0;
    2.76 +    set_field_in_reg_u32(device_id, 0,
    2.77 +                         IOMMU_INV_INT_TABLE_DEVICE_ID_MASK,
    2.78 +                         IOMMU_INV_INT_TABLE_DEVICE_ID_SHIFT, &entry);
    2.79 +    cmd[0] = entry;
    2.80 +    set_field_in_reg_u32(IOMMU_CMD_INVALIDATE_INT_TABLE, 0,
    2.81 +                         IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT,
    2.82 +                         &entry);
    2.83 +    cmd[1] = entry;
    2.84 +    send_iommu_command(iommu, cmd);
    2.85 +}
    2.86 +
    2.87 +static void update_intremap_entry_from_ioapic(
    2.88 +    struct IO_APIC_route_entry *ioapic_rte,
    2.89 +    unsigned int rte_upper, unsigned int value)
    2.90 +{
    2.91 +    unsigned long flags;
    2.92 +    u32* entry;
    2.93 +    u8 delivery_mode, dest, vector, dest_mode;
    2.94 +    struct IO_APIC_route_entry *rte = ioapic_rte;
    2.95 +
    2.96 +    spin_lock_irqsave(&int_remap_table_lock, flags);
    2.97 +
    2.98 +    if ( rte_upper )
    2.99 +    {
   2.100 +        dest = (value >> 24) & 0xFF;
   2.101 +        delivery_mode = rte->delivery_mode;
   2.102 +        vector = rte->vector;
   2.103 +        dest_mode = rte->dest_mode;
   2.104 +        entry = (u32*)get_intremap_entry((u8)rte->vector,
   2.105 +                                        (u8)rte->delivery_mode);
   2.106 +        update_intremap_entry(entry, vector, delivery_mode, dest_mode, dest);
   2.107 +    }
   2.108 +
   2.109 +    spin_unlock_irqrestore(&int_remap_table_lock, flags);
   2.110 +    return;
   2.111 +}
   2.112 +
   2.113 +int amd_iommu_setup_intremap_table(void)
   2.114 +{
   2.115 +    unsigned long flags;
   2.116 +
   2.117 +    spin_lock_irqsave(&int_remap_table_lock, flags);
   2.118 +    if ( int_remap_table == NULL )
   2.119 +        int_remap_table = (void *)alloc_xenheap_pages(1);
   2.120 +    if ( !int_remap_table )
   2.121 +    {
   2.122 +        spin_unlock_irqrestore(&int_remap_table_lock, flags);
   2.123 +        return -ENOMEM;
   2.124 +    }
   2.125 +    memset((u8*)int_remap_table, 0, PAGE_SIZE*2);
   2.126 +    spin_unlock_irqrestore(&int_remap_table_lock, flags);
   2.127 +
   2.128 +    return 0;
   2.129 +}
   2.130 +
   2.131 +void amd_iommu_ioapic_update_ire(
   2.132 +    unsigned int apic, unsigned int reg, unsigned int value)
   2.133 +{
   2.134 +    struct IO_APIC_route_entry ioapic_rte = { 0 };
   2.135 +    unsigned int rte_upper = (reg & 1) ? 1 : 0;
   2.136 +    int saved_mask;
   2.137 +
   2.138 +    *IO_APIC_BASE(apic) = reg;
   2.139 +    *(IO_APIC_BASE(apic)+4) = value;
   2.140 +
   2.141 +    if ( int_remap_table == NULL )
   2.142 +        return;
   2.143 +    if ( !rte_upper )
   2.144 +        return;
   2.145 +
   2.146 +    reg--;
   2.147 +    /* read both lower and upper 32-bits of rte entry */
   2.148 +    *IO_APIC_BASE(apic) = reg;
   2.149 +    *(((u32 *)&ioapic_rte) + 0) = *(IO_APIC_BASE(apic)+4);
   2.150 +    *IO_APIC_BASE(apic) = reg + 1;
   2.151 +    *(((u32 *)&ioapic_rte) + 1) = *(IO_APIC_BASE(apic)+4);
   2.152 +
   2.153 +    /* mask the interrupt while we change the intremap table */
   2.154 +    saved_mask = ioapic_rte.mask;
   2.155 +    ioapic_rte.mask = 1;
   2.156 +    *IO_APIC_BASE(apic) = reg;
   2.157 +    *(IO_APIC_BASE(apic)+4) = *(((int *)&ioapic_rte)+0);
   2.158 +    ioapic_rte.mask = saved_mask;
   2.159 +
   2.160 +    update_intremap_entry_from_ioapic(&ioapic_rte, rte_upper, value);
   2.161 +
   2.162 +    /* unmask the interrupt after we have updated the intremap table */
   2.163 +    *IO_APIC_BASE(apic) = reg;
   2.164 +    *(IO_APIC_BASE(apic)+4) = *(((u32 *)&ioapic_rte)+0);
   2.165 +}
   2.166 +
   2.167 +static void update_intremap_entry_from_msi_msg(
   2.168 +    struct amd_iommu *iommu, struct pci_dev *pdev, struct msi_msg *msg)
   2.169 +{
   2.170 +    unsigned long flags;
   2.171 +    u32* entry;
   2.172 +    u16 dev_id;
   2.173 +
   2.174 +    u8 delivery_mode, dest, vector, dest_mode;
   2.175 +
   2.176 +    dev_id = (pdev->bus << 8) | pdev->devfn;
   2.177 +
   2.178 +    spin_lock_irqsave(&int_remap_table_lock, flags);
   2.179 +    dest_mode = (msg->address_lo >> MSI_ADDR_DESTMODE_SHIFT) & 0x1;
   2.180 +    delivery_mode = (msg->data >> MSI_DATA_DELIVERY_MODE_SHIFT) & 0x1;
   2.181 +    vector = (msg->data >> MSI_DATA_VECTOR_SHIFT) & MSI_DATA_VECTOR_MASK;
   2.182 +    dest = (msg->address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff;
   2.183 +
   2.184 +    entry = (u32*)get_intremap_entry((u8)vector, (u8)delivery_mode);
   2.185 +    update_intremap_entry(entry, vector, delivery_mode, dest_mode, dest);
   2.186 +    spin_unlock_irqrestore(&int_remap_table_lock, flags);
   2.187 +
   2.188 +    spin_lock_irqsave(&iommu->lock, flags);
   2.189 +    invalidate_interrupt_table(iommu, dev_id);
   2.190 +    flush_command_buffer(iommu);
   2.191 +    spin_unlock_irqrestore(&iommu->lock, flags);
   2.192 +
   2.193 +    return;
   2.194 +}
   2.195 +
   2.196 +void amd_iommu_msi_msg_update_ire(
   2.197 +    struct msi_desc *msi_desc, struct msi_msg *msg)
   2.198 +{
   2.199 +    struct pci_dev *pdev = msi_desc->dev;
   2.200 +    struct amd_iommu *iommu = NULL;
   2.201 +
   2.202 +    iommu = find_iommu_for_device(pdev->bus, pdev->devfn);
   2.203 +
   2.204 +    if ( !iommu || !int_remap_table )
   2.205 +        return;
   2.206 +
   2.207 +    update_intremap_entry_from_msi_msg(iommu, pdev, msg);
   2.208 +}
     3.1 --- a/xen/drivers/passthrough/amd/iommu_map.c	Fri Jul 11 12:47:50 2008 +0100
     3.2 +++ b/xen/drivers/passthrough/amd/iommu_map.c	Fri Jul 11 12:48:45 2008 +0100
     3.3 @@ -235,13 +235,56 @@ static void amd_iommu_set_page_directory
     3.4      pde[0] = entry;
     3.5  }
     3.6  
     3.7 -void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u16 domain_id,
     3.8 -                                   u8 sys_mgt, u8 dev_ex, u8 paging_mode)
     3.9 +void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u64 intremap_ptr,
    3.10 +                                   u16 domain_id, u8 sys_mgt, u8 dev_ex,
    3.11 +                                   u8 paging_mode)
    3.12  {
    3.13      u64 addr_hi, addr_lo;
    3.14      u32 entry;
    3.15  
    3.16 -    dte[7] = dte[6] = dte[5] = dte[4] = 0;
    3.17 +    dte[7] = dte[6] = 0;
    3.18 +
    3.19 +    addr_lo = intremap_ptr & DMA_32BIT_MASK;
    3.20 +    addr_hi = intremap_ptr >> 32;
    3.21 +
    3.22 +    set_field_in_reg_u32((u32)addr_hi, 0,
    3.23 +                        IOMMU_DEV_TABLE_INT_TABLE_PTR_HIGH_MASK,
    3.24 +                        IOMMU_DEV_TABLE_INT_TABLE_PTR_HIGH_SHIFT, &entry);
    3.25 +    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
    3.26 +                        IOMMU_DEV_TABLE_INIT_PASSTHRU_MASK,
    3.27 +                        IOMMU_DEV_TABLE_INIT_PASSTHRU_SHIFT, &entry);
    3.28 +    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
    3.29 +                        IOMMU_DEV_TABLE_EINT_PASSTHRU_MASK,
    3.30 +                        IOMMU_DEV_TABLE_EINT_PASSTHRU_SHIFT, &entry);
    3.31 +    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
    3.32 +                        IOMMU_DEV_TABLE_NMI_PASSTHRU_MASK,
    3.33 +                        IOMMU_DEV_TABLE_NMI_PASSTHRU_SHIFT, &entry);
    3.34 +    /* Fixed and arbitrated interrupts remapepd */
    3.35 +    set_field_in_reg_u32(2, entry,
    3.36 +                        IOMMU_DEV_TABLE_INT_CONTROL_MASK,
    3.37 +                        IOMMU_DEV_TABLE_INT_CONTROL_SHIFT, &entry);
    3.38 +    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
    3.39 +                        IOMMU_DEV_TABLE_LINT0_ENABLE_MASK,
    3.40 +                        IOMMU_DEV_TABLE_LINT0_ENABLE_SHIFT, &entry);
    3.41 +    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
    3.42 +                        IOMMU_DEV_TABLE_LINT1_ENABLE_MASK,
    3.43 +                        IOMMU_DEV_TABLE_LINT1_ENABLE_SHIFT, &entry);
    3.44 +    dte[5] = entry;
    3.45 +
    3.46 +    set_field_in_reg_u32((u32)addr_lo >> 6, 0,
    3.47 +                        IOMMU_DEV_TABLE_INT_TABLE_PTR_LOW_MASK,
    3.48 +                        IOMMU_DEV_TABLE_INT_TABLE_PTR_LOW_SHIFT, &entry);
    3.49 +    /* 2048 entries */
    3.50 +    set_field_in_reg_u32(0xB, entry,
    3.51 +                         IOMMU_DEV_TABLE_INT_TABLE_LENGTH_MASK,
    3.52 +                         IOMMU_DEV_TABLE_INT_TABLE_LENGTH_SHIFT, &entry);
    3.53 +    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
    3.54 +                         IOMMU_DEV_TABLE_INT_VALID_MASK,
    3.55 +                         IOMMU_DEV_TABLE_INT_VALID_SHIFT, &entry);
    3.56 +    set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry,
    3.57 +                         IOMMU_DEV_TABLE_INT_TABLE_IGN_UNMAPPED_MASK,
    3.58 +                         IOMMU_DEV_TABLE_INT_TABLE_IGN_UNMAPPED_SHIFT, &entry);
    3.59 +    dte[4] = entry;
    3.60  
    3.61      set_field_in_reg_u32(sys_mgt, 0,
    3.62                           IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_MASK,
     4.1 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c	Fri Jul 11 12:47:50 2008 +0100
     4.2 +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c	Fri Jul 11 12:48:45 2008 +0100
     4.3 @@ -34,6 +34,7 @@ int nr_amd_iommus;
     4.4  
     4.5  unsigned short ivrs_bdf_entries;
     4.6  struct ivrs_mappings *ivrs_mappings;
     4.7 +extern void *int_remap_table;
     4.8  
     4.9  static void deallocate_domain_page_tables(struct hvm_iommu *hd)
    4.10  {
    4.11 @@ -256,12 +257,13 @@ static void amd_iommu_setup_domain_devic
    4.12  {
    4.13      void *dte;
    4.14      u64 root_ptr;
    4.15 +    u64 intremap_ptr;
    4.16      unsigned long flags;
    4.17      int req_id;
    4.18      u8 sys_mgt, dev_ex;
    4.19      struct hvm_iommu *hd = domain_hvm_iommu(domain);
    4.20  
    4.21 -    BUG_ON( !hd->root_table || !hd->paging_mode );
    4.22 +    BUG_ON( !hd->root_table || !hd->paging_mode || !int_remap_table );
    4.23  
    4.24      root_ptr = (u64)virt_to_maddr(hd->root_table);
    4.25      /* get device-table entry */
    4.26 @@ -269,6 +271,8 @@ static void amd_iommu_setup_domain_devic
    4.27      dte = iommu->dev_table.buffer +
    4.28          (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
    4.29  
    4.30 +    intremap_ptr = (u64)virt_to_maddr(int_remap_table);
    4.31 +
    4.32      if ( !amd_iommu_is_dte_page_translation_valid((u32 *)dte) )
    4.33      {
    4.34          spin_lock_irqsave(&iommu->lock, flags); 
    4.35 @@ -276,11 +280,12 @@ static void amd_iommu_setup_domain_devic
    4.36          /* bind DTE to domain page-tables */
    4.37          sys_mgt = ivrs_mappings[req_id].dte_sys_mgt_enable;
    4.38          dev_ex = ivrs_mappings[req_id].dte_allow_exclusion;
    4.39 -        amd_iommu_set_dev_table_entry((u32 *)dte, root_ptr,
    4.40 +        amd_iommu_set_dev_table_entry((u32 *)dte, root_ptr, intremap_ptr,
    4.41                                        hd->domain_id, sys_mgt, dev_ex,
    4.42                                        hd->paging_mode);
    4.43  
    4.44          invalidate_dev_table_entry(iommu, req_id);
    4.45 +        invalidate_interrupt_table(iommu, req_id);
    4.46          flush_command_buffer(iommu);
    4.47          amd_iov_info("Enable DTE:0x%x, "
    4.48                  "root_ptr:%"PRIx64", domain_id:%d, paging_mode:%d\n",
    4.49 @@ -365,6 +370,12 @@ int amd_iov_detect(void)
    4.50      memset(ivrs_mappings, 0,
    4.51             ivrs_bdf_entries * sizeof(struct ivrs_mappings));
    4.52  
    4.53 +    if ( amd_iommu_setup_intremap_table() != 0 )
    4.54 +    {
    4.55 +        amd_iov_error("Error allocating interrupt remapping table\n");
    4.56 +        goto error_out;
    4.57 +    }
    4.58 +
    4.59      if ( amd_iommu_init() != 0 )
    4.60      {
    4.61          amd_iov_error("Error initialization\n");
     5.1 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h	Fri Jul 11 12:47:50 2008 +0100
     5.2 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h	Fri Jul 11 12:48:45 2008 +0100
     5.3 @@ -195,28 +195,30 @@
     5.4  #define IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_SHIFT	8
     5.5  
     5.6  /* DeviceTable Entry[159:128] */
     5.7 -#define IOMMU_DEV_TABLE_INT_VALID_MASK			0x00000001
     5.8 -#define IOMMU_DEV_TABLE_INT_VALID_SHIFT			0
     5.9 -#define IOMMU_DEV_TABLE_INT_TABLE_LENGTH_MASK		0x0000001E
    5.10 -#define IOMMU_DEV_TABLE_INT_TABLE_LENGTH_SHIFT		1
    5.11 -#define IOMMU_DEV_TABLE_INT_TABLE_PTR_LOW_MASK		0xFFFFFFC0
    5.12 -#define IOMMU_DEV_TABLE_INT_TABLE_PTR_LOW_SHIFT		6
    5.13 +#define IOMMU_DEV_TABLE_INT_VALID_MASK          0x00000001
    5.14 +#define IOMMU_DEV_TABLE_INT_VALID_SHIFT         0
    5.15 +#define IOMMU_DEV_TABLE_INT_TABLE_LENGTH_MASK       0x0000001E
    5.16 +#define IOMMU_DEV_TABLE_INT_TABLE_LENGTH_SHIFT      1
    5.17 +#define IOMMU_DEV_TABLE_INT_TABLE_IGN_UNMAPPED_MASK      0x0000000020
    5.18 +#define IOMMU_DEV_TABLE_INT_TABLE_IGN_UNMAPPED_SHIFT      5
    5.19 +#define IOMMU_DEV_TABLE_INT_TABLE_PTR_LOW_MASK      0xFFFFFFC0
    5.20 +#define IOMMU_DEV_TABLE_INT_TABLE_PTR_LOW_SHIFT     6
    5.21  
    5.22  /* DeviceTable Entry[191:160] */
    5.23 -#define IOMMU_DEV_TABLE_INT_TABLE_PTR_HIGH_MASK		0x000FFFFF
    5.24 -#define IOMMU_DEV_TABLE_INT_TABLE_PTR_HIGH_SHIFT	0
    5.25 -#define IOMMU_DEV_TABLE_INIT_PASSTHRU_MASK		0x01000000
    5.26 -#define IOMMU_DEV_TABLE_INIT_PASSTHRU_SHIFT		24
    5.27 -#define IOMMU_DEV_TABLE_EINT_PASSTHRU_MASK		0x02000000
    5.28 -#define IOMMU_DEV_TABLE_EINT_PASSTHRU_SHIFT		25
    5.29 -#define IOMMU_DEV_TABLE_NMI_PASSTHRU_MASK		0x04000000
    5.30 -#define IOMMU_DEV_TABLE_NMI_PASSTHRU_SHIFT		26
    5.31 -#define IOMMU_DEV_TABLE_INT_CONTROL_MASK		0x30000000
    5.32 -#define IOMMU_DEV_TABLE_INT_CONTROL_SHIFT		28
    5.33 -#define IOMMU_DEV_TABLE_LINT0_ENABLE_MASK		0x40000000
    5.34 -#define IOMMU_DEV_TABLE_LINT0_ENABLE_SHIFT		30
    5.35 -#define IOMMU_DEV_TABLE_LINT1_ENABLE_MASK		0x80000000
    5.36 -#define IOMMU_DEV_TABLE_LINT1_ENABLE_SHIFT		31
    5.37 +#define IOMMU_DEV_TABLE_INT_TABLE_PTR_HIGH_MASK     0x000FFFFF
    5.38 +#define IOMMU_DEV_TABLE_INT_TABLE_PTR_HIGH_SHIFT    0
    5.39 +#define IOMMU_DEV_TABLE_INIT_PASSTHRU_MASK      0x01000000
    5.40 +#define IOMMU_DEV_TABLE_INIT_PASSTHRU_SHIFT     24
    5.41 +#define IOMMU_DEV_TABLE_EINT_PASSTHRU_MASK      0x02000000
    5.42 +#define IOMMU_DEV_TABLE_EINT_PASSTHRU_SHIFT     25
    5.43 +#define IOMMU_DEV_TABLE_NMI_PASSTHRU_MASK       0x04000000
    5.44 +#define IOMMU_DEV_TABLE_NMI_PASSTHRU_SHIFT      26
    5.45 +#define IOMMU_DEV_TABLE_INT_CONTROL_MASK        0x30000000
    5.46 +#define IOMMU_DEV_TABLE_INT_CONTROL_SHIFT       28
    5.47 +#define IOMMU_DEV_TABLE_LINT0_ENABLE_MASK       0x40000000
    5.48 +#define IOMMU_DEV_TABLE_LINT0_ENABLE_SHIFT      30
    5.49 +#define IOMMU_DEV_TABLE_LINT1_ENABLE_MASK       0x80000000
    5.50 +#define IOMMU_DEV_TABLE_LINT1_ENABLE_SHIFT      31
    5.51  
    5.52  /* Command Buffer */
    5.53  #define IOMMU_CMD_BUFFER_BASE_LOW_OFFSET	0x08
    5.54 @@ -276,6 +278,10 @@
    5.55  #define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_MASK   0x0000FFFF
    5.56  #define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_SHIFT  0
    5.57  
    5.58 +/* INVALIDATE_INTERRUPT_TABLE command */
    5.59 +#define IOMMU_INV_INT_TABLE_DEVICE_ID_MASK   0x0000FFFF
    5.60 +#define IOMMU_INV_INT_TABLE_DEVICE_ID_SHIFT  0
    5.61 +
    5.62  /* Event Log */
    5.63  #define IOMMU_EVENT_LOG_BASE_LOW_OFFSET		0x10
    5.64  #define IOMMU_EVENT_LOG_BASE_HIGH_OFFSET	0x14
    5.65 @@ -435,4 +441,24 @@
    5.66  #define IOMMU_IO_READ_ENABLED           1
    5.67  #define HACK_BIOS_SETTINGS                  0
    5.68  
    5.69 +/* interrupt remapping table */
    5.70 +#define INT_REMAP_INDEX_DM_MASK         0x1C00
    5.71 +#define INT_REMAP_INDEX_DM_SHIFT        10
    5.72 +#define INT_REMAP_INDEX_VECTOR_MASK     0x3FC
    5.73 +#define INT_REMAP_INDEX_VECTOR_SHIFT    2
    5.74 +#define INT_REMAP_ENTRY_REMAPEN_MASK    0x00000001
    5.75 +#define INT_REMAP_ENTRY_REMAPEN_SHIFT   0
    5.76 +#define INT_REMAP_ENTRY_SUPIOPF_MASK    0x00000002
    5.77 +#define INT_REMAP_ENTRY_SUPIOPF_SHIFT   1
    5.78 +#define INT_REMAP_ENTRY_INTTYPE_MASK    0x0000001C
    5.79 +#define INT_REMAP_ENTRY_INTTYPE_SHIFT   2
    5.80 +#define INT_REMAP_ENTRY_REQEOI_MASK     0x00000020
    5.81 +#define INT_REMAP_ENTRY_REQEOI_SHIFT    5
    5.82 +#define INT_REMAP_ENTRY_DM_MASK         0x00000040
    5.83 +#define INT_REMAP_ENTRY_DM_SHIFT        6
    5.84 +#define INT_REMAP_ENTRY_DEST_MAST       0x0000FF00
    5.85 +#define INT_REMAP_ENTRY_DEST_SHIFT      8
    5.86 +#define INT_REMAP_ENTRY_VECTOR_MASK     0x00FF0000
    5.87 +#define INT_REMAP_ENTRY_VECTOR_SHIFT    16
    5.88 +
    5.89  #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */
     6.1 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h	Fri Jul 11 12:47:50 2008 +0100
     6.2 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h	Fri Jul 11 12:48:45 2008 +0100
     6.3 @@ -70,7 +70,7 @@ int amd_iommu_reserve_domain_unity_map(s
     6.4  int amd_iommu_sync_p2m(struct domain *d);
     6.5  
     6.6  /* device table functions */
     6.7 -void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr,
     6.8 +void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u64 intremap_ptr,
     6.9          u16 domain_id, u8 sys_mgt, u8 dev_ex, u8 paging_mode);
    6.10  int amd_iommu_is_dte_page_translation_valid(u32 *entry);
    6.11  void invalidate_dev_table_entry(struct amd_iommu *iommu,
    6.12 @@ -86,6 +86,14 @@ struct amd_iommu *find_iommu_for_device(
    6.13  /* amd-iommu-acpi functions */
    6.14  int __init parse_ivrs_table(struct acpi_table_header *table);
    6.15  
    6.16 +/*interrupt remapping */
    6.17 +int amd_iommu_setup_intremap_table(void);
    6.18 +void invalidate_interrupt_table(struct amd_iommu *iommu, u16 device_id);
    6.19 +void amd_iommu_ioapic_update_ire(
    6.20 +    unsigned int apic, unsigned int reg, unsigned int value);
    6.21 +void amd_iommu_msi_msg_update_ire(
    6.22 +    struct msi_desc *msi_desc, struct msi_msg *msg);
    6.23 +
    6.24  static inline u32 get_field_from_reg_u32(u32 reg_value, u32 mask, u32 shift)
    6.25  {
    6.26      u32 field;