ia64/xen-unstable

changeset 17542:86c0353f19d0

MSI 3/6: add msi support to xen

Signed-off-by: Jiang Yunhong <yunhong.jiang@intel.com>
Signed-off-by: Shan Haitao <haitao.shan@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 01 10:31:29 2008 +0100 (2008-05-01)
parents 6ecbb00e58cd
children a0ebceaf41ff
files xen/arch/x86/Makefile xen/arch/x86/i8259.c xen/arch/x86/io_apic.c xen/arch/x86/irq.c xen/arch/x86/msi.c xen/arch/x86/physdev.c xen/drivers/passthrough/amd/iommu_init.c xen/drivers/passthrough/vtd/intremap.c xen/drivers/passthrough/vtd/iommu.c xen/drivers/passthrough/vtd/msi.h xen/drivers/passthrough/vtd/qinval.c xen/drivers/passthrough/vtd/utils.c xen/include/asm-x86/fixmap.h xen/include/asm-x86/hvm/svm/amd-iommu-defs.h xen/include/asm-x86/msi.h xen/include/public/physdev.h xen/include/xen/iommu.h xen/include/xen/irq.h xen/include/xen/pci.h
line diff
     1.1 --- a/xen/arch/x86/Makefile	Thu May 01 10:30:22 2008 +0100
     1.2 +++ b/xen/arch/x86/Makefile	Thu May 01 10:31:29 2008 +0100
     1.3 @@ -24,6 +24,7 @@ obj-y += platform_hypercall.o
     1.4  obj-y += i387.o
     1.5  obj-y += i8259.o
     1.6  obj-y += io_apic.o
     1.7 +obj-y += msi.o
     1.8  obj-y += ioport_emulate.o
     1.9  obj-y += irq.o
    1.10  obj-y += microcode.o
     2.1 --- a/xen/arch/x86/i8259.c	Thu May 01 10:30:22 2008 +0100
     2.2 +++ b/xen/arch/x86/i8259.c	Thu May 01 10:31:29 2008 +0100
     2.3 @@ -382,6 +382,7 @@ void __devinit init_8259A(int auto_eoi)
     2.4  
     2.5  static struct irqaction cascade = { no_action, "cascade", NULL};
     2.6  
     2.7 +extern struct list_head msi_pdev_list;
     2.8  void __init init_IRQ(void)
     2.9  {
    2.10      int i;
    2.11 @@ -418,5 +419,7 @@ void __init init_IRQ(void)
    2.12      outb(LATCH >> 8, PIT_CH0);     /* MSB */
    2.13  
    2.14      setup_irq(2, &cascade);
    2.15 +
    2.16 +    INIT_LIST_HEAD(&msi_pdev_list);
    2.17  }
    2.18  
     3.1 --- a/xen/arch/x86/io_apic.c	Thu May 01 10:30:22 2008 +0100
     3.2 +++ b/xen/arch/x86/io_apic.c	Thu May 01 10:31:29 2008 +0100
     3.3 @@ -27,13 +27,17 @@
     3.4  #include <xen/delay.h>
     3.5  #include <xen/sched.h>
     3.6  #include <xen/acpi.h>
     3.7 +#include <xen/pci.h>
     3.8 +#include <xen/pci_regs.h>
     3.9  #include <xen/keyhandler.h>
    3.10  #include <asm/io.h>
    3.11  #include <asm/mc146818rtc.h>
    3.12  #include <asm/smp.h>
    3.13  #include <asm/desc.h>
    3.14 +#include <asm/msi.h>
    3.15  #include <mach_apic.h>
    3.16  #include <io_ports.h>
    3.17 +#include <public/physdev.h>
    3.18  
    3.19  /* Different to Linux: our implementation can be simpler. */
    3.20  #define make_8259A_irq(irq) (io_apic_irqs &= ~(1<<(irq)))
    3.21 @@ -726,6 +730,7 @@ next:
    3.22  
    3.23  static struct hw_interrupt_type ioapic_level_type;
    3.24  static struct hw_interrupt_type ioapic_edge_type;
    3.25 +struct hw_interrupt_type pci_msi_type;
    3.26  
    3.27  #define IOAPIC_AUTO	-1
    3.28  #define IOAPIC_EDGE	0
    3.29 @@ -1554,6 +1559,59 @@ static struct hw_interrupt_type ioapic_l
    3.30      .set_affinity 	= set_ioapic_affinity_vector,
    3.31  };
    3.32  
    3.33 +static void mask_msi_vector(unsigned int vector)
    3.34 +{
    3.35 +    mask_msi_irq(vector);
    3.36 +}
    3.37 +
    3.38 +static void unmask_msi_vector(unsigned int vector)
    3.39 +{
    3.40 +    unmask_msi_irq(vector);
    3.41 +}
    3.42 +
    3.43 +static unsigned int startup_msi_vector(unsigned int vector)
    3.44 +{
    3.45 +    dprintk(XENLOG_INFO, "startup msi vector %x\n", vector);
    3.46 +    unmask_msi_irq(vector);
    3.47 +    return 0;
    3.48 +}
    3.49 +
    3.50 +static void ack_msi_vector(unsigned int vector)
    3.51 +{
    3.52 +    ack_APIC_irq();
    3.53 +}
    3.54 +
    3.55 +static void end_msi_vector(unsigned int vector)
    3.56 +{
    3.57 +}
    3.58 +
    3.59 +static void shutdown_msi_vector(unsigned int vector)
    3.60 +{
    3.61 +    dprintk(XENLOG_INFO, "shutdown msi vector %x\n", vector);
    3.62 +    mask_msi_irq(vector);
    3.63 +}
    3.64 +
    3.65 +static void set_msi_affinity_vector(unsigned int vector, cpumask_t cpu_mask)
    3.66 +{
    3.67 +    set_native_irq_info(vector, cpu_mask);
    3.68 +    set_msi_irq_affinity(vector, cpu_mask);
    3.69 +}
    3.70 +
    3.71 +/*
    3.72 + * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
    3.73 + * which implement the MSI or MSI-X Capability Structure.
    3.74 + */
    3.75 +struct hw_interrupt_type pci_msi_type = {
    3.76 +    .typename   = "PCI-MSI",
    3.77 +    .startup    = startup_msi_vector,
    3.78 +    .shutdown   = shutdown_msi_vector,
    3.79 +    .enable	    = unmask_msi_vector,
    3.80 +    .disable    = mask_msi_vector,
    3.81 +    .ack        = ack_msi_vector,
    3.82 +    .end        = end_msi_vector,
    3.83 +    .set_affinity   = set_msi_affinity_vector,
    3.84 +};
    3.85 +
    3.86  static inline void init_IO_APIC_traps(void)
    3.87  {
    3.88      int irq;
     4.1 --- a/xen/arch/x86/irq.c	Thu May 01 10:30:22 2008 +0100
     4.2 +++ b/xen/arch/x86/irq.c	Thu May 01 10:31:29 2008 +0100
     4.3 @@ -395,9 +395,11 @@ int pirq_acktype(struct domain *d, int i
     4.4      /*
     4.5       * Edge-triggered IO-APIC and LAPIC interrupts need no final
     4.6       * acknowledgement: we ACK early during interrupt processing.
     4.7 +     * MSIs are treated as edge-triggered interrupts.
     4.8       */
     4.9      if ( !strcmp(desc->handler->typename, "IO-APIC-edge") ||
    4.10 -         !strcmp(desc->handler->typename, "local-APIC-edge") )
    4.11 +         !strcmp(desc->handler->typename, "local-APIC-edge") ||
    4.12 +         !strcmp(desc->handler->typename, "PCI-MSI") )
    4.13          return ACKTYPE_NONE;
    4.14  
    4.15      /*
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xen/arch/x86/msi.c	Thu May 01 10:31:29 2008 +0100
     5.3 @@ -0,0 +1,787 @@
     5.4 +/*
     5.5 + * File:    msi.c
     5.6 + * Purpose: PCI Message Signaled Interrupt (MSI)
     5.7 + *
     5.8 + * Copyright (C) 2003-2004 Intel
     5.9 + * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
    5.10 + */
    5.11 +
    5.12 +#include <xen/config.h>
    5.13 +#include <xen/lib.h>
    5.14 +#include <xen/init.h>
    5.15 +#include <xen/irq.h>
    5.16 +#include <xen/delay.h>
    5.17 +#include <xen/sched.h>
    5.18 +#include <xen/acpi.h>
    5.19 +#include <xen/errno.h>
    5.20 +#include <xen/pci.h>
    5.21 +#include <xen/pci_regs.h>
    5.22 +#include <xen/keyhandler.h>
    5.23 +#include <asm/io.h>
    5.24 +#include <asm/smp.h>
    5.25 +#include <asm/desc.h>
    5.26 +#include <asm/msi.h>
    5.27 +#include <asm/fixmap.h>
    5.28 +#include <mach_apic.h>
    5.29 +#include <io_ports.h>
    5.30 +#include <public/physdev.h>
    5.31 +
    5.32 +extern int msi_irq_enable;
    5.33 +
    5.34 +/* PCI-dev list with MSI/MSIX capabilities */
    5.35 +DEFINE_SPINLOCK(msi_pdev_lock);
    5.36 +struct list_head msi_pdev_list;
    5.37 +
    5.38 +struct pci_dev *get_msi_pdev(u8 bus, u8 devfn)
    5.39 +{
    5.40 +    struct pci_dev *pdev = NULL;
    5.41 +
    5.42 +    list_for_each_entry(pdev, &msi_pdev_list, msi_dev_list)
    5.43 +        if ( pdev->bus == bus && pdev->devfn == devfn )
    5.44 +            return pdev;
    5.45 +
    5.46 +    return NULL;
    5.47 +}
    5.48 +
    5.49 +/* bitmap indicate which fixed map is free */
    5.50 +DEFINE_SPINLOCK(msix_fixmap_lock);
    5.51 +DECLARE_BITMAP(msix_fixmap_pages, MAX_MSIX_PAGES);
    5.52 +
    5.53 +static int msix_fixmap_alloc(void)
    5.54 +{
    5.55 +    int i;
    5.56 +    int rc = -1;
    5.57 +
    5.58 +    spin_lock(&msix_fixmap_lock);
    5.59 +    for ( i = 0; i < MAX_MSIX_PAGES; i++ )
    5.60 +        if ( !test_bit(i, &msix_fixmap_pages) )
    5.61 +            break;
    5.62 +    if ( i == MAX_MSIX_PAGES )
    5.63 +        goto out;
    5.64 +    rc = FIX_MSIX_IO_RESERV_BASE + i;
    5.65 +    set_bit(i, &msix_fixmap_pages);
    5.66 +
    5.67 + out:
    5.68 +    spin_unlock(&msix_fixmap_lock);
    5.69 +    return rc;
    5.70 +}
    5.71 +
    5.72 +static void msix_fixmap_free(int idx)
    5.73 +{
    5.74 +    if ( idx < FIX_MSIX_IO_RESERV_BASE )
    5.75 +        return;
    5.76 +
    5.77 +    spin_lock(&msix_fixmap_lock);
    5.78 +    clear_bit(idx - FIX_MSIX_IO_RESERV_BASE, &msix_fixmap_pages);
    5.79 +    spin_unlock(&msix_fixmap_lock);
    5.80 +}
    5.81 +
    5.82 +/*
    5.83 + * MSI message composition
    5.84 + */
    5.85 +static void msi_compose_msg(struct pci_dev *pdev, int vector,
    5.86 +                            struct msi_msg *msg)
    5.87 +{
    5.88 +    unsigned dest;
    5.89 +    cpumask_t tmp;
    5.90 +
    5.91 +    tmp = TARGET_CPUS;
    5.92 +    if ( vector )
    5.93 +    {
    5.94 +        dest = cpu_mask_to_apicid(tmp);
    5.95 +
    5.96 +        msg->address_hi = MSI_ADDR_BASE_HI;
    5.97 +        msg->address_lo =
    5.98 +            MSI_ADDR_BASE_LO |
    5.99 +            ((INT_DEST_MODE == 0) ?
   5.100 +                MSI_ADDR_DESTMODE_PHYS:
   5.101 +                MSI_ADDR_DESTMODE_LOGIC) |
   5.102 +            ((INT_DELIVERY_MODE != dest_LowestPrio) ?
   5.103 +                MSI_ADDR_REDIRECTION_CPU:
   5.104 +                MSI_ADDR_REDIRECTION_LOWPRI) |
   5.105 +            MSI_ADDR_DEST_ID(dest);
   5.106 +
   5.107 +        msg->data =
   5.108 +            MSI_DATA_TRIGGER_EDGE |
   5.109 +            MSI_DATA_LEVEL_ASSERT |
   5.110 +            ((INT_DELIVERY_MODE != dest_LowestPrio) ?
   5.111 +                MSI_DATA_DELIVERY_FIXED:
   5.112 +                MSI_DATA_DELIVERY_LOWPRI) |
   5.113 +            MSI_DATA_VECTOR(vector);
   5.114 +    }
   5.115 +}
   5.116 +
   5.117 +void read_msi_msg(unsigned int irq, struct msi_msg *msg)
   5.118 +{
   5.119 +    struct msi_desc *entry = irq_desc[irq].msi_desc;
   5.120 +
   5.121 +    switch ( entry->msi_attrib.type )
   5.122 +    {
   5.123 +    case PCI_CAP_ID_MSI:
   5.124 +    {
   5.125 +        struct pci_dev *dev = entry->dev;
   5.126 +        int pos = entry->msi_attrib.pos;
   5.127 +        u16 data;
   5.128 +        u8 bus = dev->bus;
   5.129 +        u8 slot = PCI_SLOT(dev->devfn);
   5.130 +        u8 func = PCI_FUNC(dev->devfn);
   5.131 +
   5.132 +        msg->address_lo = pci_conf_read32(bus, slot, func,
   5.133 +                                          msi_lower_address_reg(pos));
   5.134 +        if ( entry->msi_attrib.is_64 )
   5.135 +        {
   5.136 +            msg->address_hi = pci_conf_read32(bus, slot, func,
   5.137 +                                              msi_upper_address_reg(pos));
   5.138 +            data = pci_conf_read16(bus, slot, func, msi_data_reg(pos, 1));
   5.139 +        }
   5.140 +        else
   5.141 +        {
   5.142 +            msg->address_hi = 0;
   5.143 +            data = pci_conf_read16(bus, slot, func, msi_data_reg(pos, 0));
   5.144 +        }
   5.145 +        msg->data = data;
   5.146 +        break;
   5.147 +    }
   5.148 +    case PCI_CAP_ID_MSIX:
   5.149 +    {
   5.150 +        void __iomem *base;
   5.151 +        base = entry->mask_base +
   5.152 +            entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
   5.153 +
   5.154 +        msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
   5.155 +        msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
   5.156 +        msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET);
   5.157 +        break;
   5.158 +    }
   5.159 +    default:
   5.160 +        BUG();
   5.161 +    }
   5.162 +}
   5.163 +
   5.164 +static int set_vector_msi(struct msi_desc *entry)
   5.165 +{
   5.166 +    irq_desc_t *desc;
   5.167 +    unsigned long flags;
   5.168 +
   5.169 +    if ( entry->vector >= NR_VECTORS )
   5.170 +    {
   5.171 +        dprintk(XENLOG_ERR, "Trying to install msi data for Vector %d\n",
   5.172 +                entry->vector);
   5.173 +        return -EINVAL;
   5.174 +    }
   5.175 +
   5.176 +    desc = &irq_desc[entry->vector];
   5.177 +    spin_lock_irqsave(&desc->lock, flags);
   5.178 +    desc->msi_desc = entry;
   5.179 +    spin_unlock_irqrestore(&desc->lock, flags);
   5.180 +
   5.181 +    return 0;
   5.182 +}
   5.183 +
   5.184 +static int unset_vector_msi(int vector)
   5.185 +{
   5.186 +    irq_desc_t *desc;
   5.187 +    unsigned long flags;
   5.188 +
   5.189 +    if ( vector >= NR_VECTORS )
   5.190 +    {
   5.191 +        dprintk(XENLOG_ERR, "Trying to uninstall msi data for Vector %d\n",
   5.192 +                vector);
   5.193 +        return -EINVAL;
   5.194 +    }
   5.195 +
   5.196 +    desc = &irq_desc[vector];
   5.197 +    spin_lock_irqsave(&desc->lock, flags);
   5.198 +    desc->msi_desc = NULL;
   5.199 +    spin_unlock_irqrestore(&desc->lock, flags);
   5.200 +
   5.201 +    return 0;
   5.202 +}
   5.203 +
   5.204 +void write_msi_msg(unsigned int irq, struct msi_msg *msg)
   5.205 +{
   5.206 +    struct msi_desc *entry = irq_desc[irq].msi_desc;
   5.207 +
   5.208 +    switch ( entry->msi_attrib.type )
   5.209 +    {
   5.210 +    case PCI_CAP_ID_MSI:
   5.211 +    {
   5.212 +        struct pci_dev *dev = entry->dev;
   5.213 +        int pos = entry->msi_attrib.pos;
   5.214 +        u8 bus = dev->bus;
   5.215 +        u8 slot = PCI_SLOT(dev->devfn);
   5.216 +        u8 func = PCI_FUNC(dev->devfn);
   5.217 +
   5.218 +        pci_conf_write32(bus, slot, func, msi_lower_address_reg(pos),
   5.219 +                         msg->address_lo);
   5.220 +        if ( entry->msi_attrib.is_64 )
   5.221 +        {
   5.222 +            pci_conf_write32(bus, slot, func, msi_upper_address_reg(pos),
   5.223 +                             msg->address_hi);
   5.224 +            pci_conf_write16(bus, slot, func, msi_data_reg(pos, 1),
   5.225 +                             msg->data);
   5.226 +        }
   5.227 +        else
   5.228 +            pci_conf_write16(bus, slot, func, msi_data_reg(pos, 0),
   5.229 +                             msg->data);
   5.230 +        break;
   5.231 +    }
   5.232 +    case PCI_CAP_ID_MSIX:
   5.233 +    {
   5.234 +        void __iomem *base;
   5.235 +        base = entry->mask_base +
   5.236 +            entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
   5.237 +
   5.238 +        writel(msg->address_lo,
   5.239 +            base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
   5.240 +        writel(msg->address_hi,
   5.241 +            base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
   5.242 +        writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET);
   5.243 +        break;
   5.244 +    }
   5.245 +    default:
   5.246 +        BUG();
   5.247 +    }
   5.248 +    entry->msg = *msg;
   5.249 +}
   5.250 +
   5.251 +void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
   5.252 +{
   5.253 +    struct msi_msg msg;
   5.254 +    unsigned int dest;
   5.255 +
   5.256 +    memset(&msg, 0, sizeof(msg));
   5.257 +    cpus_and(mask, mask, cpu_online_map);
   5.258 +    if ( cpus_empty(mask) )
   5.259 +        mask = TARGET_CPUS;
   5.260 +    dest = cpu_mask_to_apicid(mask);
   5.261 +
   5.262 +    read_msi_msg(irq, &msg);
   5.263 +
   5.264 +    msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
   5.265 +    msg.address_lo |= MSI_ADDR_DEST_ID(dest);
   5.266 +
   5.267 +    write_msi_msg(irq, &msg);
   5.268 +}
   5.269 +
   5.270 +static void msi_set_enable(struct pci_dev *dev, int enable)
   5.271 +{
   5.272 +    int pos;
   5.273 +    u16 control;
   5.274 +    u8 bus = dev->bus;
   5.275 +    u8 slot = PCI_SLOT(dev->devfn);
   5.276 +    u8 func = PCI_FUNC(dev->devfn);
   5.277 +
   5.278 +    pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSI);
   5.279 +    if ( pos )
   5.280 +    {
   5.281 +        control = pci_conf_read16(bus, slot, func, pos + PCI_MSI_FLAGS);
   5.282 +        control &= ~PCI_MSI_FLAGS_ENABLE;
   5.283 +        if ( enable )
   5.284 +            control |= PCI_MSI_FLAGS_ENABLE;
   5.285 +        pci_conf_write16(bus, slot, func, pos + PCI_MSI_FLAGS, control);
   5.286 +    }
   5.287 +}
   5.288 +
   5.289 +void msix_set_enable(struct pci_dev *dev, int enable)
   5.290 +{
   5.291 +    int pos;
   5.292 +    u16 control;
   5.293 +    u8 bus = dev->bus;
   5.294 +    u8 slot = PCI_SLOT(dev->devfn);
   5.295 +    u8 func = PCI_FUNC(dev->devfn);
   5.296 +
   5.297 +    pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSIX);
   5.298 +    if ( pos )
   5.299 +    {
   5.300 +        control = pci_conf_read16(bus, slot, func, pos + PCI_MSIX_FLAGS);
   5.301 +        control &= ~PCI_MSIX_FLAGS_ENABLE;
   5.302 +        if ( enable )
   5.303 +            control |= PCI_MSIX_FLAGS_ENABLE;
   5.304 +        pci_conf_write16(bus, slot, func, pos + PCI_MSIX_FLAGS, control);
   5.305 +    }
   5.306 +}
   5.307 +
   5.308 +static void msix_flush_writes(unsigned int irq)
   5.309 +{
   5.310 +    struct msi_desc *entry = irq_desc[irq].msi_desc;
   5.311 +
   5.312 +    BUG_ON(!entry || !entry->dev);
   5.313 +    switch (entry->msi_attrib.type) {
   5.314 +    case PCI_CAP_ID_MSI:
   5.315 +        /* nothing to do */
   5.316 +        break;
   5.317 +    case PCI_CAP_ID_MSIX:
   5.318 +    {
   5.319 +        int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
   5.320 +            PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
   5.321 +        readl(entry->mask_base + offset);
   5.322 +        break;
   5.323 +    }
   5.324 +    default:
   5.325 +        BUG();
   5.326 +        break;
   5.327 +    }
   5.328 +}
   5.329 +
   5.330 +static void msi_set_mask_bit(unsigned int irq, int flag)
   5.331 +{
   5.332 +    struct msi_desc *entry = irq_desc[irq].msi_desc;
   5.333 +
   5.334 +    BUG_ON(!entry || !entry->dev);
   5.335 +    switch (entry->msi_attrib.type) {
   5.336 +    case PCI_CAP_ID_MSI:
   5.337 +        if (entry->msi_attrib.maskbit) {
   5.338 +            int pos;
   5.339 +            u32 mask_bits;
   5.340 +            u8 bus = entry->dev->bus;
   5.341 +            u8 slot = PCI_SLOT(entry->dev->devfn);
   5.342 +            u8 func = PCI_FUNC(entry->dev->devfn);
   5.343 +
   5.344 +            pos = (long)entry->mask_base;
   5.345 +            mask_bits = pci_conf_read32(bus, slot, func, pos);
   5.346 +            mask_bits &= ~(1);
   5.347 +            mask_bits |= flag;
   5.348 +            pci_conf_write32(bus, slot, func, pos, mask_bits);
   5.349 +        } else {
   5.350 +            msi_set_enable(entry->dev, !flag);
   5.351 +        }
   5.352 +        break;
   5.353 +    case PCI_CAP_ID_MSIX:
   5.354 +    {
   5.355 +        int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
   5.356 +            PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET;
   5.357 +        writel(flag, entry->mask_base + offset);
   5.358 +        readl(entry->mask_base + offset);
   5.359 +        break;
   5.360 +    }
   5.361 +    default:
   5.362 +        BUG();
   5.363 +        break;
   5.364 +    }
   5.365 +    entry->msi_attrib.masked = !!flag;
   5.366 +}
   5.367 +
   5.368 +void mask_msi_irq(unsigned int irq)
   5.369 +{
   5.370 +    msi_set_mask_bit(irq, 1);
   5.371 +    msix_flush_writes(irq);
   5.372 +}
   5.373 +
   5.374 +void unmask_msi_irq(unsigned int irq)
   5.375 +{
   5.376 +    msi_set_mask_bit(irq, 0);
   5.377 +    msix_flush_writes(irq);
   5.378 +}
   5.379 +
   5.380 +static struct msi_desc* alloc_msi_entry(void)
   5.381 +{
   5.382 +    struct msi_desc *entry;
   5.383 +
   5.384 +    entry = xmalloc(struct msi_desc);
   5.385 +    if ( !entry )
   5.386 +        return NULL;
   5.387 +
   5.388 +    INIT_LIST_HEAD(&entry->list);
   5.389 +    entry->dev = NULL;
   5.390 +
   5.391 +    return entry;
   5.392 +}
   5.393 +
   5.394 +static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
   5.395 +{
   5.396 +    struct msi_msg msg;
   5.397 +
   5.398 +    msi_compose_msg(dev, desc->vector, &msg);
   5.399 +    set_vector_msi(desc);
   5.400 +    write_msi_msg(desc->vector, &msg);
   5.401 +
   5.402 +    return 0;
   5.403 +}
   5.404 +
   5.405 +static void teardown_msi_vector(int vector)
   5.406 +{
   5.407 +    unset_vector_msi(vector);
   5.408 +}
   5.409 +
   5.410 +static void msi_free_vector(int vector)
   5.411 +{
   5.412 +    struct msi_desc *entry;
   5.413 +
   5.414 +    entry = irq_desc[vector].msi_desc;
   5.415 +
   5.416 +    teardown_msi_vector(vector);
   5.417 +
   5.418 +    if ( entry->msi_attrib.type == PCI_CAP_ID_MSIX )
   5.419 +    {
   5.420 +        unsigned long start;
   5.421 +
   5.422 +        writel(1, entry->mask_base + entry->msi_attrib.entry_nr
   5.423 +              * PCI_MSIX_ENTRY_SIZE
   5.424 +              + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
   5.425 +
   5.426 +        start = (unsigned long)entry->mask_base & ~(PAGE_SIZE - 1);
   5.427 +        msix_fixmap_free(virt_to_fix(start));
   5.428 +        destroy_xen_mappings(start, start + PAGE_SIZE);
   5.429 +    }
   5.430 +    list_del(&entry->list);
   5.431 +    xfree(entry);
   5.432 +}
   5.433 +
   5.434 +void msi_free_vectors(struct pci_dev* dev)
   5.435 +{
   5.436 +    struct msi_desc *entry, *tmp;
   5.437 +
   5.438 +    list_for_each_entry_safe( entry, tmp, &dev->msi_list, list )
   5.439 +        msi_free_vector(entry->vector);
   5.440 +}
   5.441 +
   5.442 +static struct msi_desc *find_msi_entry(struct pci_dev *dev,
   5.443 +                                       int vector, int cap_id)
   5.444 +{
   5.445 +    struct msi_desc *entry;
   5.446 +
   5.447 +    list_for_each_entry( entry, &dev->msi_list, list )
   5.448 +    {
   5.449 +        if ( entry->msi_attrib.type == cap_id &&
   5.450 +             (vector == -1 || entry->vector == vector) )
   5.451 +            return entry;
   5.452 +    }
   5.453 +
   5.454 +    return NULL;
   5.455 +}
   5.456 +
   5.457 +/**
   5.458 + * msi_capability_init - configure device's MSI capability structure
   5.459 + * @dev: pointer to the pci_dev data structure of MSI device function
   5.460 + *
   5.461 + * Setup the MSI capability structure of device function with a single
   5.462 + * MSI irq, regardless of device function is capable of handling
   5.463 + * multiple messages. A return of zero indicates the successful setup
   5.464 + * of an entry zero with the new MSI irq or non-zero for otherwise.
   5.465 + **/
   5.466 +static int msi_capability_init(struct pci_dev *dev, int vector)
   5.467 +{
   5.468 +    struct msi_desc *entry;
   5.469 +    int pos, ret;
   5.470 +    u16 control;
   5.471 +    u8 bus = dev->bus;
   5.472 +    u8 slot = PCI_SLOT(dev->devfn);
   5.473 +    u8 func = PCI_FUNC(dev->devfn);
   5.474 +
   5.475 +    pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSI);
   5.476 +    control = pci_conf_read16(bus, slot, func, msi_control_reg(pos));
   5.477 +    /* MSI Entry Initialization */
   5.478 +    msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */
   5.479 +
   5.480 +    entry = alloc_msi_entry();
   5.481 +    if ( !entry )
   5.482 +        return -ENOMEM;
   5.483 +
   5.484 +    entry->msi_attrib.type = PCI_CAP_ID_MSI;
   5.485 +    entry->msi_attrib.is_64 = is_64bit_address(control);
   5.486 +    entry->msi_attrib.entry_nr = 0;
   5.487 +    entry->msi_attrib.maskbit = is_mask_bit_support(control);
   5.488 +    entry->msi_attrib.masked = 1;
   5.489 +    entry->msi_attrib.pos = pos;
   5.490 +    entry->vector = vector;
   5.491 +    if ( is_mask_bit_support(control) )
   5.492 +        entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
   5.493 +                is_64bit_address(control));
   5.494 +    entry->dev = dev;
   5.495 +    if ( entry->msi_attrib.maskbit )
   5.496 +    {
   5.497 +        unsigned int maskbits, temp;
   5.498 +        /* All MSIs are unmasked by default, Mask them all */
   5.499 +        maskbits = pci_conf_read32(bus, slot, func,
   5.500 +                       msi_mask_bits_reg(pos, is_64bit_address(control)));
   5.501 +        temp = (1 << multi_msi_capable(control));
   5.502 +        temp = ((temp - 1) & ~temp);
   5.503 +        maskbits |= temp;
   5.504 +        pci_conf_write32(bus, slot, func,
   5.505 +            msi_mask_bits_reg(pos, is_64bit_address(control)),
   5.506 +            maskbits);
   5.507 +    }
   5.508 +    list_add_tail(&entry->list, &dev->msi_list);
   5.509 +
   5.510 +    /* Configure MSI capability structure */
   5.511 +    ret = setup_msi_irq(dev, entry);
   5.512 +    if ( ret )
   5.513 +    {
   5.514 +        msi_free_vector(vector);
   5.515 +        return ret;
   5.516 +    }
   5.517 +
   5.518 +    /* Restore the original MSI enabled bits  */
   5.519 +    pci_conf_write16(bus, slot, func, msi_control_reg(pos), control);
   5.520 +
   5.521 +    return 0;
   5.522 +}
   5.523 +
   5.524 +static u64 pci_resource_start(struct pci_dev *dev, u8 bar_index)
   5.525 +{
   5.526 +    unsigned long bar_base;
   5.527 +    u8 bus = dev->bus;
   5.528 +    u8 slot = PCI_SLOT(dev->devfn);
   5.529 +    u8 func = PCI_FUNC(dev->devfn);
   5.530 +
   5.531 +    bar_base = pci_conf_read32(bus, slot, func,
   5.532 +                               PCI_BASE_ADDRESS_0 + 4 * bar_index);
   5.533 +    if ( bar_base & PCI_BASE_ADDRESS_MEM_TYPE_64 )
   5.534 +    {
   5.535 +        bar_base <<= 32;
   5.536 +        bar_base += pci_conf_read32(bus, slot, func,
   5.537 +                               PCI_BASE_ADDRESS_0 + 4 * (bar_index + 1));
   5.538 +    }
   5.539 +
   5.540 +    return bar_base;
   5.541 +}
   5.542 +
   5.543 +/**
   5.544 + * msix_capability_init - configure device's MSI-X capability
   5.545 + * @dev: pointer to the pci_dev data structure of MSI-X device function
   5.546 + * @entries: pointer to an array of struct msix_entry entries
   5.547 + * @nvec: number of @entries
   5.548 + *
   5.549 + * Setup the MSI-X capability structure of device function with a
   5.550 + * single MSI-X irq. A return of zero indicates the successful setup of
   5.551 + * requested MSI-X entries with allocated irqs or non-zero for otherwise.
   5.552 + **/
   5.553 +static int msix_capability_init(struct pci_dev *dev, int vector, int entry_nr)
   5.554 +{
   5.555 +    struct msi_desc *entry;
   5.556 +    int pos;
   5.557 +    u16 control;
   5.558 +    unsigned long phys_addr;
   5.559 +    u32 table_offset;
   5.560 +    u8 bir;
   5.561 +    void __iomem *base;
   5.562 +    int idx;
   5.563 +    u8 bus = dev->bus;
   5.564 +    u8 slot = PCI_SLOT(dev->devfn);
   5.565 +    u8 func = PCI_FUNC(dev->devfn);
   5.566 +
   5.567 +    pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSIX);
   5.568 +    control = pci_conf_read16(bus, slot, func, msix_control_reg(pos));
   5.569 +    msix_set_enable(dev, 0);/* Ensure msix is disabled as I set it up */
   5.570 +
   5.571 +    /* MSI-X Table Initialization */
   5.572 +    entry = alloc_msi_entry();
   5.573 +    if ( !entry )
   5.574 +        return -ENOMEM;
   5.575 +
   5.576 +    /* Request & Map MSI-X table region */
   5.577 +    table_offset = pci_conf_read32(bus, slot, func, msix_table_offset_reg(pos));
   5.578 +    bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
   5.579 +    table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
   5.580 +    phys_addr = pci_resource_start(dev, bir) + table_offset;
   5.581 +    idx = msix_fixmap_alloc();
   5.582 +    if ( idx < 0 )
   5.583 +    {
   5.584 +        xfree(entry);
   5.585 +        return -ENOMEM;
   5.586 +    }
   5.587 +    set_fixmap_nocache(idx, phys_addr);
   5.588 +    base = (void *)(fix_to_virt(idx) + (phys_addr & ((1UL << PAGE_SHIFT) - 1)));
   5.589 +
   5.590 +    entry->msi_attrib.type = PCI_CAP_ID_MSIX;
   5.591 +    entry->msi_attrib.is_64 = 1;
   5.592 +    entry->msi_attrib.entry_nr = entry_nr;
   5.593 +    entry->msi_attrib.maskbit = 1;
   5.594 +    entry->msi_attrib.masked = 1;
   5.595 +    entry->msi_attrib.pos = pos;
   5.596 +    entry->vector = vector;
   5.597 +    entry->dev = dev;
   5.598 +    entry->mask_base = base;
   5.599 +
   5.600 +    list_add_tail(&entry->list, &dev->msi_list);
   5.601 +
   5.602 +    setup_msi_irq(dev, entry);
   5.603 +
   5.604 +    /* Set MSI-X enabled bits */
   5.605 +    pci_conf_write16(bus, slot, func, msix_control_reg(pos), control);
   5.606 +
   5.607 +    return 0;
   5.608 +}
   5.609 +
   5.610 +/**
   5.611 + * pci_enable_msi - configure device's MSI capability structure
   5.612 + * @dev: pointer to the pci_dev data structure of MSI device function
   5.613 + *
   5.614 + * Setup the MSI capability structure of device function with
   5.615 + * a single MSI irq upon its software driver call to request for
   5.616 + * MSI mode enabled on its hardware device function. A return of zero
   5.617 + * indicates the successful setup of an entry zero with the new MSI
   5.618 + * irq or non-zero for otherwise.
   5.619 + **/
   5.620 +static int __pci_enable_msi(u8 bus, u8 devfn, int vector)
   5.621 +{
   5.622 +    int status;
   5.623 +    struct pci_dev *dev;
   5.624 +
   5.625 +    dev = get_msi_pdev(bus, devfn);
   5.626 +    if ( !dev )
   5.627 +    {
   5.628 +        dev = xmalloc(struct pci_dev);
   5.629 +        if ( !dev )
   5.630 +            return -ENOMEM;
   5.631 +        dev->bus = bus;
   5.632 +        dev->devfn = devfn;
   5.633 +        INIT_LIST_HEAD(&dev->msi_list);
   5.634 +    }
   5.635 +
   5.636 +    if ( find_msi_entry(dev, vector, PCI_CAP_ID_MSI) )
   5.637 +    {
   5.638 +        dprintk(XENLOG_WARNING, "vector %d has already mapped to MSI on device \
   5.639 +            %02x:%02x.%01x.\n", vector, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
   5.640 +        return 0;
   5.641 +    }
   5.642 +
   5.643 +    status = msi_capability_init(dev, vector);
   5.644 +
   5.645 +    if ( dev != get_msi_pdev(bus, devfn) )
   5.646 +    {
   5.647 +        spin_lock(&msi_pdev_lock);
   5.648 +        list_add_tail(&dev->msi_dev_list, &msi_pdev_list);
   5.649 +        spin_unlock(&msi_pdev_lock);
   5.650 +    }
   5.651 +
   5.652 +    return status;
   5.653 +}
   5.654 +
   5.655 +static void __pci_disable_msi(int vector)
   5.656 +{
   5.657 +    struct msi_desc *entry;
   5.658 +    struct pci_dev *dev;
   5.659 +    int pos;
   5.660 +    u16 control;
   5.661 +    u8 bus, slot, func;
   5.662 +
   5.663 +    entry = irq_desc[vector].msi_desc;
   5.664 +    dev = entry->dev;
   5.665 +    bus = dev->bus;
   5.666 +    slot = PCI_SLOT(dev->devfn);
   5.667 +    func = PCI_FUNC(dev->devfn);
   5.668 +
   5.669 +    pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSI);
   5.670 +    control = pci_conf_read16(bus, slot, func, msi_control_reg(pos));
   5.671 +    msi_set_enable(dev, 0);
   5.672 +
   5.673 +    BUG_ON(list_empty(&dev->msi_list));
   5.674 +
   5.675 +    msi_free_vector(vector);
   5.676 +
   5.677 +    pci_conf_write16(bus, slot, func, msi_control_reg(pos), control);
   5.678 +}
   5.679 +
   5.680 +/**
   5.681 + * pci_enable_msix - configure device's MSI-X capability structure
   5.682 + * @dev: pointer to the pci_dev data structure of MSI-X device function
   5.683 + * @entries: pointer to an array of MSI-X entries
   5.684 + * @nvec: number of MSI-X irqs requested for allocation by device driver
   5.685 + *
   5.686 + * Setup the MSI-X capability structure of device function with the number
   5.687 + * of requested irqs upon its software driver call to request for
   5.688 + * MSI-X mode enabled on its hardware device function. A return of zero
   5.689 + * indicates the successful configuration of MSI-X capability structure
   5.690 + * with new allocated MSI-X irqs. A return of < 0 indicates a failure.
   5.691 + * Or a return of > 0 indicates that driver request is exceeding the number
   5.692 + * of irqs available. Driver should use the returned value to re-send
   5.693 + * its request.
   5.694 + **/
   5.695 +static int __pci_enable_msix(u8 bus, u8 devfn, int vector, int entry_nr)
   5.696 +{
   5.697 +    int status, pos, nr_entries;
   5.698 +    struct pci_dev *dev;
   5.699 +    u16 control;
   5.700 +    u8 slot = PCI_SLOT(devfn);
   5.701 +    u8 func = PCI_FUNC(devfn);
   5.702 +
   5.703 +    pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSIX);
   5.704 +    control = pci_conf_read16(bus, slot, func, msi_control_reg(pos));
   5.705 +    nr_entries = multi_msix_capable(control);
   5.706 +    if (entry_nr > nr_entries)
   5.707 +        return -EINVAL;
   5.708 +
   5.709 +    /* Check whether driver already requested for MSI-X irqs */
   5.710 +    dev = get_msi_pdev(bus, devfn);
   5.711 +
   5.712 +    if ( !dev )
   5.713 +    {
   5.714 +        dev = xmalloc(struct pci_dev);
   5.715 +        if ( !dev )
   5.716 +            return -ENOMEM;
   5.717 +        dev->bus = bus;
   5.718 +        dev->devfn = devfn;
   5.719 +        INIT_LIST_HEAD(&dev->msi_list);
   5.720 +    }
   5.721 +
   5.722 +    if ( find_msi_entry(dev, vector, PCI_CAP_ID_MSIX) )
   5.723 +    {
   5.724 +        dprintk(XENLOG_WARNING, "vector %d has already mapped to MSIX on \
   5.725 +                device %02x:%02x.%01x.\n", vector, bus,
   5.726 +                PCI_SLOT(devfn), PCI_FUNC(devfn));
   5.727 +        return 0;
   5.728 +    }
   5.729 +
   5.730 +    status = msix_capability_init(dev, vector, entry_nr);
   5.731 +
   5.732 +    if ( dev != get_msi_pdev(bus, devfn) )
   5.733 +    {
   5.734 +        spin_lock(&msi_pdev_lock);
   5.735 +        list_add_tail(&dev->msi_dev_list, &msi_pdev_list);
   5.736 +        spin_unlock(&msi_pdev_lock);
   5.737 +    }
   5.738 +
   5.739 +    return status;
   5.740 +}
   5.741 +
   5.742 +static void __pci_disable_msix(int vector)
   5.743 +{
   5.744 +    struct msi_desc *entry;
   5.745 +    struct pci_dev *dev;
   5.746 +    int pos;
   5.747 +    u16 control;
   5.748 +    u8 bus, slot, func;
   5.749 +
   5.750 +    entry = irq_desc[vector].msi_desc;
   5.751 +    dev = entry->dev;
   5.752 +    bus = dev->bus;
   5.753 +    slot = PCI_SLOT(dev->devfn);
   5.754 +    func = PCI_FUNC(dev->devfn);
   5.755 +
   5.756 +    pos = pci_find_cap_offset(bus, slot, func, PCI_CAP_ID_MSIX);
   5.757 +    control = pci_conf_read16(bus, slot, func, msix_control_reg(pos));
   5.758 +    msi_set_enable(dev, 0);
   5.759 +
   5.760 +    BUG_ON(list_empty(&dev->msi_list));
   5.761 +
   5.762 +    msi_free_vector(vector);
   5.763 +
   5.764 +    pci_conf_write16(bus, slot, func, msix_control_reg(pos), control);
   5.765 +}
   5.766 +
   5.767 +int pci_enable_msi(u8 bus, u8 devfn, int vector, int entry_nr, int msi)
   5.768 +{
   5.769 +    if ( msi )
   5.770 +        return __pci_enable_msi(bus, devfn, vector);
   5.771 +    else
   5.772 +        return __pci_enable_msix(bus, devfn, vector, entry_nr);
   5.773 +}
   5.774 +
   5.775 +void pci_disable_msi(int vector)
   5.776 +{
   5.777 +    irq_desc_t *desc;
   5.778 +
   5.779 +    desc = &irq_desc[vector];
   5.780 +    if ( desc->msi_desc->msi_attrib.type == PCI_CAP_ID_MSI )
   5.781 +        __pci_disable_msi(vector);
   5.782 +    else if ( desc->msi_desc->msi_attrib.type == PCI_CAP_ID_MSIX )
   5.783 +        __pci_disable_msix(vector);
   5.784 +}
   5.785 +
   5.786 +void pci_cleanup_msi(struct pci_dev *dev)
   5.787 +{
   5.788 +    msi_free_vectors(dev);
   5.789 +}
   5.790 +
     6.1 --- a/xen/arch/x86/physdev.c	Thu May 01 10:30:22 2008 +0100
     6.2 +++ b/xen/arch/x86/physdev.c	Thu May 01 10:31:29 2008 +0100
     6.3 @@ -9,6 +9,7 @@
     6.4  #include <xen/guest_access.h>
     6.5  #include <xen/iocap.h>
     6.6  #include <asm/current.h>
     6.7 +#include <asm/msi.h>
     6.8  #include <asm/hypercall.h>
     6.9  #include <public/xen.h>
    6.10  #include <public/physdev.h>
    6.11 @@ -25,6 +26,9 @@ int
    6.12  ioapic_guest_write(
    6.13      unsigned long physbase, unsigned int reg, u32 pval);
    6.14  
    6.15 +
    6.16 +extern struct hw_interrupt_type pci_msi_type;
    6.17 +
    6.18  static int get_free_pirq(struct domain *d, int type, int index)
    6.19  {
    6.20      int i;
    6.21 @@ -57,7 +61,8 @@ static int get_free_pirq(struct domain *
    6.22  /*
    6.23   * Caller hold the irq_lock
    6.24   */
    6.25 -static int map_domain_pirq(struct domain *d, int pirq, int vector, int type)
    6.26 +static int map_domain_pirq(struct domain *d, int pirq, int vector,
    6.27 +                           struct physdev_map_pirq *map)
    6.28  {
    6.29      int ret = 0;
    6.30      int old_vector, old_pirq;
    6.31 @@ -97,6 +102,28 @@ static int map_domain_pirq(struct domain
    6.32          goto done;
    6.33      }
    6.34  
    6.35 +    if ( map && MAP_PIRQ_TYPE_MSI == map->type )
    6.36 +    {
    6.37 +        irq_desc_t         *desc;
    6.38 +        unsigned long flags;
    6.39 +
    6.40 +        desc = &irq_desc[vector];
    6.41 +
    6.42 +        spin_lock_irqsave(&desc->lock, flags);
    6.43 +        if ( desc->handler != &no_irq_type )
    6.44 +            gdprintk(XENLOG_G_ERR, "Map vector %x to msi while it is in use\n",
    6.45 +                     vector);
    6.46 +        desc->handler = &pci_msi_type;
    6.47 +        spin_unlock_irqrestore(&desc->lock, flags);
    6.48 +
    6.49 +        ret = pci_enable_msi(map->msi_info.bus,
    6.50 +		                     map->msi_info.devfn, vector,
    6.51 +							 map->msi_info.entry_nr,
    6.52 +							 map->msi_info.msi);
    6.53 +        if ( ret )
    6.54 +            goto done;
    6.55 +    }
    6.56 +
    6.57      d->arch.pirq_vector[pirq] = vector;
    6.58      d->arch.vector_pirq[vector] = pirq;
    6.59  
    6.60 @@ -129,7 +156,26 @@ static int unmap_domain_pirq(struct doma
    6.61          ret = -EINVAL;
    6.62      }
    6.63      else
    6.64 +    {
    6.65 +        unsigned long flags;
    6.66 +        irq_desc_t *desc;
    6.67 +
    6.68 +        desc = &irq_desc[vector];
    6.69 +        if ( desc->msi_desc )
    6.70 +            pci_disable_msi(vector);
    6.71 +
    6.72 +        spin_lock_irqsave(&desc->lock, flags);
    6.73 +        if ( desc->handler == &pci_msi_type )
    6.74 +        {
    6.75 +            /* MSI is not shared, so should be released already */
    6.76 +            BUG_ON(desc->status & IRQ_GUEST);
    6.77 +            irq_desc[vector].handler = &no_irq_type;
    6.78 +        }
    6.79 +        spin_unlock_irqrestore(&desc->lock, flags);
    6.80 +
    6.81          d->arch.pirq_vector[pirq] = d->arch.vector_pirq[vector] = 0;
    6.82 +    }
    6.83 +
    6.84      ret = irq_deny_access(d, pirq);
    6.85  
    6.86      if ( ret )
    6.87 @@ -187,6 +233,9 @@ static int physdev_map_pirq(struct physd
    6.88              break;
    6.89          case MAP_PIRQ_TYPE_MSI:
    6.90              vector = map->index;
    6.91 +			if ( vector == -1 )
    6.92 +				vector = assign_irq_vector(AUTO_ASSIGN);
    6.93 +
    6.94              if ( vector < 0 || vector >= NR_VECTORS )
    6.95              {
    6.96                  ret = -EINVAL;
    6.97 @@ -237,7 +286,8 @@ static int physdev_map_pirq(struct physd
    6.98              pirq = map->pirq;
    6.99      }
   6.100  
   6.101 -    ret = map_domain_pirq(d, pirq, vector, map->type);
   6.102 +
   6.103 +    ret = map_domain_pirq(d, pirq, vector, map);
   6.104  
   6.105      if ( !ret )
   6.106          map->pirq = pirq;
   6.107 @@ -331,6 +381,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
   6.108              break;
   6.109  
   6.110          ret = physdev_map_pirq(&map);
   6.111 +
   6.112          if ( copy_to_guest(arg, &map, 1) != 0 )
   6.113              ret = -EFAULT;
   6.114          break;
   6.115 @@ -397,7 +448,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
   6.116  
   6.117          irq = irq_op.irq;
   6.118          ret = -EINVAL;
   6.119 -        if ( (irq < 0) || (irq >= NR_IRQS) )
   6.120 +        if ( ((irq < 0) && (irq != AUTO_ASSIGN)) || (irq >= NR_IRQS) )
   6.121              break;
   6.122  
   6.123          irq_op.vector = assign_irq_vector(irq);
   6.124 @@ -408,8 +459,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H
   6.125          {
   6.126              spin_lock_irqsave(&dom0->arch.irq_lock, flags);
   6.127              if ( irq != AUTO_ASSIGN )
   6.128 -                ret = map_domain_pirq(dom0, irq_op.irq, irq_op.vector,
   6.129 -                                     MAP_PIRQ_TYPE_GSI);
   6.130 +                ret = map_domain_pirq(dom0, irq_op.irq, irq_op.vector, NULL);
   6.131              spin_unlock_irqrestore(&dom0->arch.irq_lock, flags);
   6.132          }
   6.133  
     7.1 --- a/xen/drivers/passthrough/amd/iommu_init.c	Thu May 01 10:30:22 2008 +0100
     7.2 +++ b/xen/drivers/passthrough/amd/iommu_init.c	Thu May 01 10:31:29 2008 +0100
     7.3 @@ -23,6 +23,7 @@
     7.4  #include <xen/pci.h>
     7.5  #include <xen/pci_regs.h>
     7.6  #include <asm/amd-iommu.h>
     7.7 +#include <asm/msi.h>
     7.8  #include <asm/hvm/svm/amd-iommu-proto.h>
     7.9  #include <asm-x86/fixmap.h>
    7.10  
    7.11 @@ -292,7 +293,7 @@ static void amd_iommu_msi_addr_init(stru
    7.12      u32 address_lo = MSI_ADDR_HEADER |
    7.13              MSI_ADDR_DESTMODE_PHYS |
    7.14              MSI_ADDR_REDIRECTION_CPU |
    7.15 -            MSI_ADDR_DESTID_CPU(phy_cpu);
    7.16 +            MSI_ADDR_DEST_ID(phy_cpu);
    7.17  
    7.18      pci_conf_write32(bus, dev, func,
    7.19          iommu->msi_cap + PCI_MSI_ADDRESS_LO, address_lo);
     8.1 --- a/xen/drivers/passthrough/vtd/intremap.c	Thu May 01 10:30:22 2008 +0100
     8.2 +++ b/xen/drivers/passthrough/vtd/intremap.c	Thu May 01 10:31:29 2008 +0100
     8.3 @@ -24,10 +24,10 @@
     8.4  #include <xen/time.h>
     8.5  #include <xen/pci.h>
     8.6  #include <xen/pci_regs.h>
     8.7 +#include <asm/msi.h>
     8.8  #include "iommu.h"
     8.9  #include "dmar.h"
    8.10  #include "vtd.h"
    8.11 -#include "msi.h"
    8.12  #include "extern.h"
    8.13  
    8.14  u16 apicid_to_bdf(int apic_id)
     9.1 --- a/xen/drivers/passthrough/vtd/iommu.c	Thu May 01 10:30:22 2008 +0100
     9.2 +++ b/xen/drivers/passthrough/vtd/iommu.c	Thu May 01 10:31:29 2008 +0100
     9.3 @@ -29,9 +29,9 @@
     9.4  #include <xen/pci.h>
     9.5  #include <xen/pci_regs.h>
     9.6  #include <asm/paging.h>
     9.7 +#include <asm/msi.h>
     9.8  #include "iommu.h"
     9.9  #include "dmar.h"
    9.10 -#include "msi.h"
    9.11  #include "extern.h"
    9.12  #include "vtd.h"
    9.13  
    10.1 --- a/xen/drivers/passthrough/vtd/msi.h	Thu May 01 10:30:22 2008 +0100
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,127 +0,0 @@
    10.4 -/*
    10.5 - * Copyright (C) 2003-2004 Intel
    10.6 - * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
    10.7 - */
    10.8 -
    10.9 -#ifndef MSI_H
   10.10 -#define MSI_H
   10.11 -
   10.12 -/*
   10.13 - * Assume the maximum number of hot plug slots supported by the system is about
   10.14 - * ten. The worstcase is that each of these slots is hot-added with a device,
   10.15 - * which has two MSI/MSI-X capable functions. To avoid any MSI-X driver, which
   10.16 - * attempts to request all available vectors, NR_HP_RESERVED_VECTORS is defined
   10.17 - * as below to ensure at least one message is assigned to each detected MSI/
   10.18 - * MSI-X device function.
   10.19 - */
   10.20 -#define NR_HP_RESERVED_VECTORS 	20
   10.21 -
   10.22 -extern int vector_irq[NR_VECTORS];
   10.23 -extern int pci_vector_resources(int last, int nr_released);
   10.24 -
   10.25 -/*
   10.26 - * MSI-X Address Register
   10.27 - */
   10.28 -#define PCI_MSIX_FLAGS_QSIZE		0x7FF
   10.29 -#define PCI_MSIX_FLAGS_ENABLE		(1 << 15)
   10.30 -#define PCI_MSIX_FLAGS_BIRMASK		(7 << 0)
   10.31 -#define PCI_MSIX_FLAGS_BITMASK		(1 << 0)
   10.32 -
   10.33 -#define PCI_MSIX_ENTRY_SIZE			16
   10.34 -#define  PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET	0
   10.35 -#define  PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET	4
   10.36 -#define  PCI_MSIX_ENTRY_DATA_OFFSET		8
   10.37 -#define  PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET	12
   10.38 -
   10.39 -#define msi_control_reg(base)		(base + PCI_MSI_FLAGS)
   10.40 -#define msi_lower_address_reg(base)	(base + PCI_MSI_ADDRESS_LO)
   10.41 -#define msi_upper_address_reg(base)	(base + PCI_MSI_ADDRESS_HI)
   10.42 -#define msi_data_reg(base, is64bit)	\
   10.43 -	( (is64bit == 1) ? base+PCI_MSI_DATA_64 : base+PCI_MSI_DATA_32 )
   10.44 -#define msi_mask_bits_reg(base, is64bit) \
   10.45 -	( (is64bit == 1) ? base+PCI_MSI_MASK_BIT : base+PCI_MSI_MASK_BIT-4)
   10.46 -#define msi_disable(control)		control &= ~PCI_MSI_FLAGS_ENABLE
   10.47 -#define multi_msi_capable(control) \
   10.48 -	(1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1))
   10.49 -#define multi_msi_enable(control, num) \
   10.50 -	control |= (((num >> 1) << 4) & PCI_MSI_FLAGS_QSIZE);
   10.51 -#define is_64bit_address(control)	(control & PCI_MSI_FLAGS_64BIT)
   10.52 -#define is_mask_bit_support(control)	(control & PCI_MSI_FLAGS_MASKBIT)
   10.53 -#define msi_enable(control, num) multi_msi_enable(control, num); \
   10.54 -	control |= PCI_MSI_FLAGS_ENABLE
   10.55 -
   10.56 -#define msix_table_offset_reg(base)	(base + 0x04)
   10.57 -#define msix_pba_offset_reg(base)	(base + 0x08)
   10.58 -#define msix_enable(control)	 	control |= PCI_MSIX_FLAGS_ENABLE
   10.59 -#define msix_disable(control)	 	control &= ~PCI_MSIX_FLAGS_ENABLE
   10.60 -#define msix_table_size(control) 	((control & PCI_MSIX_FLAGS_QSIZE)+1)
   10.61 -#define multi_msix_capable		msix_table_size
   10.62 -#define msix_unmask(address)	 	(address & ~PCI_MSIX_FLAGS_BITMASK)
   10.63 -#define msix_mask(address)		(address | PCI_MSIX_FLAGS_BITMASK)
   10.64 -#define msix_is_pending(address) 	(address & PCI_MSIX_FLAGS_PENDMASK)
   10.65 -
   10.66 -/*
   10.67 - * MSI Defined Data Structures
   10.68 - */
   10.69 -#define MSI_ADDRESS_HEADER		0xfee
   10.70 -#define MSI_ADDRESS_HEADER_SHIFT	12
   10.71 -#define MSI_ADDRESS_HEADER_MASK		0xfff000
   10.72 -#define MSI_ADDRESS_DEST_ID_MASK	0xfff0000f
   10.73 -#define MSI_TARGET_CPU_MASK		0xff
   10.74 -#define MSI_TARGET_CPU_SHIFT		12
   10.75 -#define MSI_DELIVERY_MODE		0
   10.76 -#define MSI_LEVEL_MODE			1	/* Edge always assert */
   10.77 -#define MSI_TRIGGER_MODE		0	/* MSI is edge sensitive */
   10.78 -#define MSI_PHYSICAL_MODE		0
   10.79 -#define MSI_LOGICAL_MODE		1
   10.80 -#define MSI_REDIRECTION_HINT_MODE	0
   10.81 -
   10.82 -#define __LITTLE_ENDIAN_BITFIELD	1
   10.83 -
   10.84 -struct msg_data {
   10.85 -#if defined(__LITTLE_ENDIAN_BITFIELD)
   10.86 -	__u32	vector		:  8;
   10.87 -	__u32	delivery_mode	:  3;	/* 000b: FIXED | 001b: lowest prior */
   10.88 -	__u32	reserved_1	:  3;
   10.89 -	__u32	level		:  1;	/* 0: deassert | 1: assert */
   10.90 -	__u32	trigger		:  1;	/* 0: edge | 1: level */
   10.91 -	__u32	reserved_2	: 16;
   10.92 -#elif defined(__BIG_ENDIAN_BITFIELD)
   10.93 -	__u32	reserved_2	: 16;
   10.94 -	__u32	trigger		:  1;	/* 0: edge | 1: level */
   10.95 -	__u32	level		:  1;	/* 0: deassert | 1: assert */
   10.96 -	__u32	reserved_1	:  3;
   10.97 -	__u32	delivery_mode	:  3;	/* 000b: FIXED | 001b: lowest prior */
   10.98 -	__u32	vector		:  8;
   10.99 -#else
  10.100 -#error "Bitfield endianness not defined! Check your byteorder.h"
  10.101 -#endif
  10.102 -} __attribute__ ((packed));
  10.103 -
  10.104 -struct msg_address {
  10.105 -	union {
  10.106 -		struct {
  10.107 -#if defined(__LITTLE_ENDIAN_BITFIELD)
  10.108 -			__u32	reserved_1	:  2;
  10.109 -			__u32	dest_mode	:  1;	/*0:physic | 1:logic */
  10.110 -			__u32	redirection_hint:  1;  	/*0: dedicated CPU
  10.111 -							  1: lowest priority */
  10.112 -			__u32	reserved_2	:  4;
  10.113 - 			__u32	dest_id		: 24;	/* Destination ID */
  10.114 -#elif defined(__BIG_ENDIAN_BITFIELD)
  10.115 - 			__u32	dest_id		: 24;	/* Destination ID */
  10.116 -			__u32	reserved_2	:  4;
  10.117 -			__u32	redirection_hint:  1;  	/*0: dedicated CPU
  10.118 -							  1: lowest priority */
  10.119 -			__u32	dest_mode	:  1;	/*0:physic | 1:logic */
  10.120 -			__u32	reserved_1	:  2;
  10.121 -#else
  10.122 -#error "Bitfield endianness not defined! Check your byteorder.h"
  10.123 -#endif
  10.124 -      		}u;
  10.125 -       		__u32  value;
  10.126 -	}lo_address;
  10.127 -	__u32 	hi_address;
  10.128 -} __attribute__ ((packed));
  10.129 -
  10.130 -#endif /* MSI_H */
    11.1 --- a/xen/drivers/passthrough/vtd/qinval.c	Thu May 01 10:30:22 2008 +0100
    11.2 +++ b/xen/drivers/passthrough/vtd/qinval.c	Thu May 01 10:31:29 2008 +0100
    11.3 @@ -24,10 +24,10 @@
    11.4  #include <xen/time.h>
    11.5  #include <xen/pci.h>
    11.6  #include <xen/pci_regs.h>
    11.7 +#include <asm/msi.h>
    11.8  #include "iommu.h"
    11.9  #include "dmar.h"
   11.10  #include "vtd.h"
   11.11 -#include "msi.h"
   11.12  #include "extern.h"
   11.13  
   11.14  static void print_qi_regs(struct iommu *iommu)
    12.1 --- a/xen/drivers/passthrough/vtd/utils.c	Thu May 01 10:30:22 2008 +0100
    12.2 +++ b/xen/drivers/passthrough/vtd/utils.c	Thu May 01 10:31:29 2008 +0100
    12.3 @@ -23,9 +23,9 @@
    12.4  #include <xen/time.h>
    12.5  #include <xen/pci.h>
    12.6  #include <xen/pci_regs.h>
    12.7 +#include <asm/msi.h>
    12.8  #include "iommu.h"
    12.9  #include "dmar.h"
   12.10 -#include "msi.h"
   12.11  #include "vtd.h"
   12.12  
   12.13  #define INTEL   0x8086
    13.1 --- a/xen/include/asm-x86/fixmap.h	Thu May 01 10:30:22 2008 +0100
    13.2 +++ b/xen/include/asm-x86/fixmap.h	Thu May 01 10:31:29 2008 +0100
    13.3 @@ -19,6 +19,7 @@
    13.4  #include <xen/kexec.h>
    13.5  #include <xen/iommu.h>
    13.6  #include <asm/amd-iommu.h>
    13.7 +#include <asm/msi.h>
    13.8  
    13.9  /*
   13.10   * Here we define all the compile-time 'special' virtual
   13.11 @@ -47,6 +48,8 @@ enum fixed_addresses {
   13.12      FIX_IOMMU_MMIO_BASE_0,
   13.13      FIX_IOMMU_MMIO_END = FIX_IOMMU_MMIO_BASE_0 + IOMMU_PAGES -1,
   13.14      FIX_TBOOT_SHARED_BASE,
   13.15 +    FIX_MSIX_IO_RESERV_BASE,
   13.16 +    FIX_MSIX_IO_RESERV_END = FIX_MSIX_IO_RESERV_BASE + MAX_MSIX_PAGES -1,
   13.17      __end_of_fixed_addresses
   13.18  };
   13.19  
    14.1 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h	Thu May 01 10:30:22 2008 +0100
    14.2 +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h	Thu May 01 10:31:29 2008 +0100
    14.3 @@ -435,33 +435,4 @@
    14.4  #define IOMMU_IO_READ_ENABLED           1
    14.5  #define HACK_BIOS_SETTINGS                  0
    14.6  
    14.7 -/* MSI interrupt */
    14.8 -#define MSI_DATA_VECTOR_SHIFT       0
    14.9 -#define MSI_DATA_VECTOR(v)      (((u8)v) << MSI_DATA_VECTOR_SHIFT)
   14.10 -
   14.11 -#define MSI_DATA_DELIVERY_SHIFT     8
   14.12 -#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT)
   14.13 -#define MSI_DATA_DELIVERY_LOWPRI    (1 << MSI_DATA_DELIVERY_SHIFT)
   14.14 -
   14.15 -#define MSI_DATA_LEVEL_SHIFT        14
   14.16 -#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT)
   14.17 -#define MSI_DATA_LEVEL_ASSERT   (1 << MSI_DATA_LEVEL_SHIFT)
   14.18 -
   14.19 -#define MSI_DATA_TRIGGER_SHIFT      15
   14.20 -#define MSI_DATA_TRIGGER_EDGE   (0 << MSI_DATA_TRIGGER_SHIFT)
   14.21 -#define  MSI_DATA_TRIGGER_LEVEL  (1 << MSI_DATA_TRIGGER_SHIFT)
   14.22 -
   14.23 -#define MSI_TARGET_CPU_SHIFT        12
   14.24 -#define MSI_ADDR_HEADER         0xfee00000
   14.25 -#define MSI_ADDR_DESTID_MASK        0xfff0000f
   14.26 -#define MSI_ADDR_DESTID_CPU(cpu)    ((cpu) << MSI_TARGET_CPU_SHIFT)
   14.27 -
   14.28 -#define MSI_ADDR_DESTMODE_SHIFT     2
   14.29 -#define MSI_ADDR_DESTMODE_PHYS  (0 << MSI_ADDR_DESTMODE_SHIFT)
   14.30 -#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT)
   14.31 -
   14.32 -#define MSI_ADDR_REDIRECTION_SHIFT  3
   14.33 -#define MSI_ADDR_REDIRECTION_CPU    (0 << MSI_ADDR_REDIRECTION_SHIFT)
   14.34 -#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
   14.35 -
   14.36  #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/xen/include/asm-x86/msi.h	Thu May 01 10:31:29 2008 +0100
    15.3 @@ -0,0 +1,210 @@
    15.4 +#ifndef __ASM_MSI_H
    15.5 +#define __ASM_MSI_H
    15.6 +
    15.7 +#include <xen/cpumask.h>
    15.8 +#include <asm/irq.h>
    15.9 +/*
   15.10 + * Constants for Intel APIC based MSI messages.
   15.11 + */
   15.12 +
   15.13 +/*
   15.14 + * Shifts for MSI data
   15.15 + */
   15.16 +
   15.17 +#define MSI_DATA_VECTOR_SHIFT		0
   15.18 +#define  MSI_DATA_VECTOR_MASK		0x000000ff
   15.19 +#define	 MSI_DATA_VECTOR(v)		(((v) << MSI_DATA_VECTOR_SHIFT) & MSI_DATA_VECTOR_MASK)
   15.20 +
   15.21 +#define MSI_DATA_DELIVERY_MODE_SHIFT	8
   15.22 +#define  MSI_DATA_DELIVERY_FIXED	(0 << MSI_DATA_DELIVERY_MODE_SHIFT)
   15.23 +#define  MSI_DATA_DELIVERY_LOWPRI	(1 << MSI_DATA_DELIVERY_MODE_SHIFT)
   15.24 +
   15.25 +#define MSI_DATA_LEVEL_SHIFT		14
   15.26 +#define	 MSI_DATA_LEVEL_DEASSERT	(0 << MSI_DATA_LEVEL_SHIFT)
   15.27 +#define	 MSI_DATA_LEVEL_ASSERT		(1 << MSI_DATA_LEVEL_SHIFT)
   15.28 +
   15.29 +#define MSI_DATA_TRIGGER_SHIFT		15
   15.30 +#define  MSI_DATA_TRIGGER_EDGE		(0 << MSI_DATA_TRIGGER_SHIFT)
   15.31 +#define  MSI_DATA_TRIGGER_LEVEL		(1 << MSI_DATA_TRIGGER_SHIFT)
   15.32 +
   15.33 +/*
   15.34 + * Shift/mask fields for msi address
   15.35 + */
   15.36 +
   15.37 +#define MSI_ADDR_BASE_HI	    	0
   15.38 +#define MSI_ADDR_BASE_LO	    	0xfee00000
   15.39 +#define MSI_ADDR_HEADER             MSI_ADDR_BASE_LO
   15.40 +
   15.41 +#define MSI_ADDR_DESTMODE_SHIFT     2
   15.42 +#define MSI_ADDR_DESTMODE_PHYS      (0 << MSI_ADDR_DESTMODE_SHIFT)
   15.43 +#define MSI_ADDR_DESTMODE_LOGIC     (1 << MSI_ADDR_DESTMODE_SHIFT)
   15.44 +
   15.45 +#define MSI_ADDR_REDIRECTION_SHIFT  3
   15.46 +#define MSI_ADDR_REDIRECTION_CPU    (0 << MSI_ADDR_REDIRECTION_SHIFT)
   15.47 +#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
   15.48 +
   15.49 +#define MSI_ADDR_DEST_ID_SHIFT		12
   15.50 +#define	 MSI_ADDR_DEST_ID_MASK		0x00ffff0
   15.51 +#define  MSI_ADDR_DEST_ID(dest)		(((dest) << MSI_ADDR_DEST_ID_SHIFT) & MSI_ADDR_DEST_ID_MASK)
   15.52 +
   15.53 +/* MAX fixed pages reserved for mapping MSIX tables. */
   15.54 +#if defined(__x86_64__)
   15.55 +#define MAX_MSIX_PAGES              512
   15.56 +#else
   15.57 +#define MAX_MSIX_PAGES              32
   15.58 +#endif
   15.59 +
   15.60 +struct msi_msg {
   15.61 +	u32	address_lo;	/* low 32 bits of msi message address */
   15.62 +	u32	address_hi;	/* high 32 bits of msi message address */
   15.63 +	u32	data;		/* 16 bits of msi message data */
   15.64 +};
   15.65 +
   15.66 +/* Helper functions */
   15.67 +extern void mask_msi_irq(unsigned int irq);
   15.68 +extern void unmask_msi_irq(unsigned int irq);
   15.69 +extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
   15.70 +extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
   15.71 +extern void set_msi_irq_affinity(unsigned int irq, cpumask_t mask);
   15.72 +extern int pci_enable_msi(u8 bus, u8 devfn, int vector, int entry_nr, int msi);
   15.73 +extern void pci_disable_msi(int vector);
   15.74 +
   15.75 +struct msi_desc {
   15.76 +	struct {
   15.77 +		__u8	type	: 5; 	/* {0: unused, 5h:MSI, 11h:MSI-X} */
   15.78 +		__u8	maskbit	: 1; 	/* mask-pending bit supported ?   */
   15.79 +		__u8	masked	: 1;
   15.80 +		__u8	is_64	: 1;	/* Address size: 0=32bit 1=64bit  */
   15.81 +		__u8	pos;	 	/* Location of the msi capability */
   15.82 +		__u16	entry_nr;    	/* specific enabled entry 	  */
   15.83 +	}msi_attrib;
   15.84 +
   15.85 +	struct list_head list;
   15.86 +
   15.87 +	void __iomem *mask_base;
   15.88 +	struct pci_dev *dev;
   15.89 +    int vector;
   15.90 +
   15.91 +	/* Last set MSI message */
   15.92 +	struct msi_msg msg;
   15.93 +};
   15.94 +
   15.95 +/*
   15.96 + * Assume the maximum number of hot plug slots supported by the system is about
   15.97 + * ten. The worstcase is that each of these slots is hot-added with a device,
   15.98 + * which has two MSI/MSI-X capable functions. To avoid any MSI-X driver, which
   15.99 + * attempts to request all available vectors, NR_HP_RESERVED_VECTORS is defined
  15.100 + * as below to ensure at least one message is assigned to each detected MSI/
  15.101 + * MSI-X device function.
  15.102 + */
  15.103 +#define NR_HP_RESERVED_VECTORS 	20
  15.104 +
  15.105 +extern int vector_irq[NR_VECTORS];
  15.106 +
  15.107 +/*
  15.108 + * MSI-X Address Register
  15.109 + */
  15.110 +#define PCI_MSIX_FLAGS_QSIZE		0x7FF
  15.111 +#define PCI_MSIX_FLAGS_ENABLE		(1 << 15)
  15.112 +#define PCI_MSIX_FLAGS_BIRMASK		(7 << 0)
  15.113 +#define PCI_MSIX_FLAGS_BITMASK		(1 << 0)
  15.114 +
  15.115 +#define PCI_MSIX_ENTRY_SIZE			16
  15.116 +#define  PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET	0
  15.117 +#define  PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET	4
  15.118 +#define  PCI_MSIX_ENTRY_DATA_OFFSET		8
  15.119 +#define  PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET	12
  15.120 +
  15.121 +#define msi_control_reg(base)		(base + PCI_MSI_FLAGS)
  15.122 +#define msi_lower_address_reg(base)	(base + PCI_MSI_ADDRESS_LO)
  15.123 +#define msi_upper_address_reg(base)	(base + PCI_MSI_ADDRESS_HI)
  15.124 +#define msi_data_reg(base, is64bit)	\
  15.125 +	( (is64bit == 1) ? base+PCI_MSI_DATA_64 : base+PCI_MSI_DATA_32 )
  15.126 +#define msi_mask_bits_reg(base, is64bit) \
  15.127 +	( (is64bit == 1) ? base+PCI_MSI_MASK_BIT : base+PCI_MSI_MASK_BIT-4)
  15.128 +#define msi_disable(control)		control &= ~PCI_MSI_FLAGS_ENABLE
  15.129 +#define multi_msi_capable(control) \
  15.130 +	(1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1))
  15.131 +#define multi_msi_enable(control, num) \
  15.132 +	control |= (((num >> 1) << 4) & PCI_MSI_FLAGS_QSIZE);
  15.133 +#define is_64bit_address(control)	(!!(control & PCI_MSI_FLAGS_64BIT))
  15.134 +#define is_mask_bit_support(control)	(!!(control & PCI_MSI_FLAGS_MASKBIT))
  15.135 +#define msi_enable(control, num) multi_msi_enable(control, num); \
  15.136 +	control |= PCI_MSI_FLAGS_ENABLE
  15.137 +
  15.138 +#define msix_control_reg(base)		(base + PCI_MSIX_FLAGS)
  15.139 +#define msix_table_offset_reg(base)	(base + 0x04)
  15.140 +#define msix_pba_offset_reg(base)	(base + 0x08)
  15.141 +#define msix_enable(control)	 	control |= PCI_MSIX_FLAGS_ENABLE
  15.142 +#define msix_disable(control)	 	control &= ~PCI_MSIX_FLAGS_ENABLE
  15.143 +#define msix_table_size(control) 	((control & PCI_MSIX_FLAGS_QSIZE)+1)
  15.144 +#define multi_msix_capable		msix_table_size
  15.145 +#define msix_unmask(address)	 	(address & ~PCI_MSIX_FLAGS_BITMASK)
  15.146 +#define msix_mask(address)		(address | PCI_MSIX_FLAGS_BITMASK)
  15.147 +#define msix_is_pending(address) 	(address & PCI_MSIX_FLAGS_PENDMASK)
  15.148 +
  15.149 +/*
  15.150 + * MSI Defined Data Structures
  15.151 + */
  15.152 +#define MSI_ADDRESS_HEADER		0xfee
  15.153 +#define MSI_ADDRESS_HEADER_SHIFT	12
  15.154 +#define MSI_ADDRESS_HEADER_MASK		0xfff000
  15.155 +#define MSI_ADDRESS_DEST_ID_MASK	0xfff0000f
  15.156 +#define MSI_TARGET_CPU_MASK		0xff
  15.157 +#define MSI_TARGET_CPU_SHIFT		12
  15.158 +#define MSI_DELIVERY_MODE		0
  15.159 +#define MSI_LEVEL_MODE			1	/* Edge always assert */
  15.160 +#define MSI_TRIGGER_MODE		0	/* MSI is edge sensitive */
  15.161 +#define MSI_PHYSICAL_MODE		0
  15.162 +#define MSI_LOGICAL_MODE		1
  15.163 +#define MSI_REDIRECTION_HINT_MODE	0
  15.164 +
  15.165 +#define __LITTLE_ENDIAN_BITFIELD	1
  15.166 +
  15.167 +struct msg_data {
  15.168 +#if defined(__LITTLE_ENDIAN_BITFIELD)
  15.169 +	__u32	vector		:  8;
  15.170 +	__u32	delivery_mode	:  3;	/* 000b: FIXED | 001b: lowest prior */
  15.171 +	__u32	reserved_1	:  3;
  15.172 +	__u32	level		:  1;	/* 0: deassert | 1: assert */
  15.173 +	__u32	trigger		:  1;	/* 0: edge | 1: level */
  15.174 +	__u32	reserved_2	: 16;
  15.175 +#elif defined(__BIG_ENDIAN_BITFIELD)
  15.176 +	__u32	reserved_2	: 16;
  15.177 +	__u32	trigger		:  1;	/* 0: edge | 1: level */
  15.178 +	__u32	level		:  1;	/* 0: deassert | 1: assert */
  15.179 +	__u32	reserved_1	:  3;
  15.180 +	__u32	delivery_mode	:  3;	/* 000b: FIXED | 001b: lowest prior */
  15.181 +	__u32	vector		:  8;
  15.182 +#else
  15.183 +#error "Bitfield endianness not defined! Check your byteorder.h"
  15.184 +#endif
  15.185 +} __attribute__ ((packed));
  15.186 +
  15.187 +struct msg_address {
  15.188 +	union {
  15.189 +		struct {
  15.190 +#if defined(__LITTLE_ENDIAN_BITFIELD)
  15.191 +			__u32	reserved_1	:  2;
  15.192 +			__u32	dest_mode	:  1;	/*0:physic | 1:logic */
  15.193 +			__u32	redirection_hint:  1;  	/*0: dedicated CPU
  15.194 +							  1: lowest priority */
  15.195 +			__u32	reserved_2	:  4;
  15.196 + 			__u32	dest_id		: 24;	/* Destination ID */
  15.197 +#elif defined(__BIG_ENDIAN_BITFIELD)
  15.198 + 			__u32	dest_id		: 24;	/* Destination ID */
  15.199 +			__u32	reserved_2	:  4;
  15.200 +			__u32	redirection_hint:  1;  	/*0: dedicated CPU
  15.201 +							  1: lowest priority */
  15.202 +			__u32	dest_mode	:  1;	/*0:physic | 1:logic */
  15.203 +			__u32	reserved_1	:  2;
  15.204 +#else
  15.205 +#error "Bitfield endianness not defined! Check your byteorder.h"
  15.206 +#endif
  15.207 +      		}u;
  15.208 +       		__u32  value;
  15.209 +	}lo_address;
  15.210 +	__u32 	hi_address;
  15.211 +} __attribute__ ((packed));
  15.212 +
  15.213 +#endif /* __ASM_MSI_H */
    16.1 --- a/xen/include/public/physdev.h	Thu May 01 10:30:22 2008 +0100
    16.2 +++ b/xen/include/public/physdev.h	Thu May 01 10:31:29 2008 +0100
    16.3 @@ -135,6 +135,11 @@ struct physdev_map_pirq {
    16.4      int index;
    16.5      /* IN or OUT */
    16.6      int pirq;
    16.7 +    /* IN */
    16.8 +    struct {
    16.9 +        int bus, devfn, entry_nr;
   16.10 +		int msi;  /* 0 - MSIX    1 - MSI */
   16.11 +    } msi_info;
   16.12  };
   16.13  typedef struct physdev_map_pirq physdev_map_pirq_t;
   16.14  DEFINE_XEN_GUEST_HANDLE(physdev_map_pirq_t);
    17.1 --- a/xen/include/xen/iommu.h	Thu May 01 10:30:22 2008 +0100
    17.2 +++ b/xen/include/xen/iommu.h	Thu May 01 10:31:29 2008 +0100
    17.3 @@ -23,6 +23,7 @@
    17.4  #include <xen/init.h>
    17.5  #include <xen/pci.h>
    17.6  #include <xen/spinlock.h>
    17.7 +#include <xen/pci.h>
    17.8  #include <public/hvm/ioreq.h>
    17.9  #include <public/domctl.h>
   17.10  
    18.1 --- a/xen/include/xen/irq.h	Thu May 01 10:30:22 2008 +0100
    18.2 +++ b/xen/include/xen/irq.h	Thu May 01 10:31:29 2008 +0100
    18.3 @@ -44,6 +44,7 @@ typedef struct hw_interrupt_type hw_irq_
    18.4  
    18.5  #include <asm/irq.h>
    18.6  
    18.7 +struct msi_desc;
    18.8  /*
    18.9   * This is the "IRQ descriptor", which contains various information
   18.10   * about the irq, including what kind of hardware handling it has,
   18.11 @@ -54,6 +55,7 @@ typedef struct hw_interrupt_type hw_irq_
   18.12  typedef struct {
   18.13      unsigned int status;		/* IRQ status */
   18.14      hw_irq_controller *handler;
   18.15 +    struct msi_desc   *msi_desc;
   18.16      struct irqaction *action;	/* IRQ action list */
   18.17      unsigned int depth;		/* nested irq disables */
   18.18      spinlock_t lock;
    19.1 --- a/xen/include/xen/pci.h	Thu May 01 10:30:22 2008 +0100
    19.2 +++ b/xen/include/xen/pci.h	Thu May 01 10:31:29 2008 +0100
    19.3 @@ -26,8 +26,10 @@
    19.4  
    19.5  struct pci_dev {
    19.6      struct list_head list;
    19.7 +    struct list_head msi_dev_list;
    19.8      u8 bus;
    19.9      u8 devfn;
   19.10 +    struct list_head msi_list;
   19.11  };
   19.12  
   19.13  uint8_t pci_conf_read8(