debuggers.hg
changeset 17573: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>
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(