ia64/xen-unstable
changeset 19806:703ced548925
VT-d: fix MSI source-id of interrupt remapping
This patch fixes an issue of MSI source-id. Currently MSI source-ids
are all set device bdf. It's incorrect for PCI (not PCIe) devices. The
patch set correct requester-ids of MSI to source-id. And also, wrap
functions to clean ioapic source-id.
Signed-off-by: Weidong Han <weidong.han@intel.com>
This patch fixes an issue of MSI source-id. Currently MSI source-ids
are all set device bdf. It's incorrect for PCI (not PCIe) devices. The
patch set correct requester-ids of MSI to source-id. And also, wrap
functions to clean ioapic source-id.
Signed-off-by: Weidong Han <weidong.han@intel.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Fri Jun 19 08:45:55 2009 +0100 (2009-06-19) |
parents | 2f1fa2215e60 |
children | 468561f3c8ee |
files | xen/drivers/passthrough/vtd/intremap.c |
line diff
1.1 --- a/xen/drivers/passthrough/vtd/intremap.c Fri Jun 19 08:45:20 2009 +0100 1.2 +++ b/xen/drivers/passthrough/vtd/intremap.c Fri Jun 19 08:45:55 2009 +0100 1.3 @@ -39,6 +39,27 @@ 1.4 #define nr_ioapic_registers(i) nr_ioapic_registers[i] 1.5 #endif 1.6 1.7 +/* 1.8 + * source validation type (SVT) 1.9 + */ 1.10 +#define SVT_NO_VERIFY 0x0 /* no verification is required */ 1.11 +#define SVT_VERIFY_SID_SQ 0x1 /* verify using SID and SQ fiels */ 1.12 +#define SVT_VERIFY_BUS 0x2 /* verify bus of request-id */ 1.13 + 1.14 +/* 1.15 + * source-id qualifier (SQ) 1.16 + */ 1.17 +#define SQ_ALL_16 0x0 /* verify all 16 bits of request-id */ 1.18 +#define SQ_13_IGNORE_1 0x1 /* verify most significant 13 bits, ignore 1.19 + * the third least significant bit 1.20 + */ 1.21 +#define SQ_13_IGNORE_2 0x2 /* verify most significant 13 bits, ignore 1.22 + * the second and third least significant bits 1.23 + */ 1.24 +#define SQ_13_IGNORE_3 0x3 /* verify most significant 13 bits, ignore 1.25 + * the least three significant bits 1.26 + */ 1.27 + 1.28 /* apic_pin_2_ir_idx[apicid][pin] = interrupt remapping table index */ 1.29 static unsigned int **apic_pin_2_ir_idx; 1.30 1.31 @@ -86,6 +107,20 @@ u16 apicid_to_bdf(int apic_id) 1.32 return 0; 1.33 } 1.34 1.35 +static void set_ire_sid(struct iremap_entry *ire, 1.36 + unsigned int svt, unsigned int sq, unsigned int sid) 1.37 +{ 1.38 + ire->hi.svt = svt; 1.39 + ire->hi.sq = sq; 1.40 + ire->hi.sid = sid; 1.41 +} 1.42 + 1.43 +static void set_ioapic_source_id(int apic_id, struct iremap_entry *ire) 1.44 +{ 1.45 + set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16, 1.46 + apicid_to_bdf(apic_id)); 1.47 +} 1.48 + 1.49 static int remap_entry_to_ioapic_rte( 1.50 struct iommu *iommu, struct IO_xAPIC_route_entry *old_rte) 1.51 { 1.52 @@ -191,10 +226,8 @@ static int ioapic_rte_to_remap_entry(str 1.53 new_ire.lo.res_1 = 0; 1.54 new_ire.lo.vector = new_rte.vector; 1.55 new_ire.lo.res_2 = 0; 1.56 - new_ire.hi.sid = apicid_to_bdf(IO_APIC_ID(apic)); 1.57 1.58 - new_ire.hi.sq = 0; /* comparing all 16-bit of SID */ 1.59 - new_ire.hi.svt = 1; /* requestor ID verification SID/SQ */ 1.60 + set_ioapic_source_id(IO_APIC_ID(apic), &new_ire); 1.61 new_ire.hi.res_1 = 0; 1.62 new_ire.lo.p = 1; /* finally, set present bit */ 1.63 1.64 @@ -345,6 +378,56 @@ void io_apic_write_remap_rte( 1.65 } 1.66 1.67 #if defined(__i386__) || defined(__x86_64__) 1.68 + 1.69 +static void set_msi_source_id(struct pci_dev *pdev, struct iremap_entry *ire) 1.70 +{ 1.71 + int type; 1.72 + u8 bus, devfn, secbus; 1.73 + int ret; 1.74 + 1.75 + if ( !pdev || !ire ) 1.76 + return; 1.77 + 1.78 + bus = pdev->bus; 1.79 + devfn = pdev->devfn; 1.80 + type = pdev_type(bus, devfn); 1.81 + switch ( type ) 1.82 + { 1.83 + case DEV_TYPE_PCIe_BRIDGE: 1.84 + case DEV_TYPE_PCIe2PCI_BRIDGE: 1.85 + case DEV_TYPE_LEGACY_PCI_BRIDGE: 1.86 + break; 1.87 + 1.88 + case DEV_TYPE_PCIe_ENDPOINT: 1.89 + set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16, PCI_BDF2(bus, devfn)); 1.90 + break; 1.91 + 1.92 + case DEV_TYPE_PCI: 1.93 + ret = find_upstream_bridge(&bus, &devfn, &secbus); 1.94 + if ( ret == 0 ) /* integrated PCI device */ 1.95 + { 1.96 + set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16, 1.97 + PCI_BDF2(bus, devfn)); 1.98 + } 1.99 + else if ( ret == 1 ) /* find upstream bridge */ 1.100 + { 1.101 + if ( pdev_type(bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE ) 1.102 + set_ire_sid(ire, SVT_VERIFY_BUS, SQ_ALL_16, 1.103 + (bus << 8) | pdev->bus); 1.104 + else if ( pdev_type(bus, devfn) == DEV_TYPE_LEGACY_PCI_BRIDGE ) 1.105 + set_ire_sid(ire, SVT_VERIFY_BUS, SQ_ALL_16, 1.106 + PCI_BDF2(bus, devfn)); 1.107 + } 1.108 + break; 1.109 + 1.110 + default: 1.111 + gdprintk(XENLOG_WARNING VTDPREFIX, 1.112 + "set_msi_source_id: unknown type : bdf = %x:%x.%x\n", 1.113 + bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); 1.114 + break; 1.115 + } 1.116 +} 1.117 + 1.118 static int remap_entry_to_msi_msg( 1.119 struct iommu *iommu, struct msi_msg *msg) 1.120 { 1.121 @@ -456,9 +539,7 @@ static int msi_msg_to_remap_entry( 1.122 new_ire.lo.dst = ((msg->address_lo >> MSI_ADDR_DEST_ID_SHIFT) 1.123 & 0xff) << 8; 1.124 1.125 - new_ire.hi.sid = (pdev->bus << 8) | pdev->devfn; 1.126 - new_ire.hi.sq = 0; 1.127 - new_ire.hi.svt = 1; 1.128 + set_msi_source_id(pdev, &new_ire); 1.129 new_ire.hi.res_1 = 0; 1.130 new_ire.lo.p = 1; /* finally, set present bit */ 1.131