>>> On 26.08.11 at 13:57, Wei Wang2 <wei.wang2@xxxxxxx> wrote:
> Read PCI segment from IVHD block is fine. The value should be the same as in
> IVHDR if they both show up in BIOS. IVHDR also has PCI segment number, but
> IVHDR is only used by IVRS revision 2. Actually, IVRS rev 2 allows device
> IDs
> to be chosen freely by OS instead of by firmware. Rev 2 might co-exist with
> rev 1 in BIOS but if SW like Xen or Linux uses device IDs supplied by BIOS,
> it should just ignore rev 2 tables.
I don't really follow: The two cases where I can't spot where to get the
segment number from are register_exclusion_range_for_all_devices()
and register_exclusion_range_for_device(), both called in the context
of struct acpi_ivmd_block_header(), which only gets a struct
acpi_ivmd_block_header (not having a segment number afaict).
Jan
> On Thursday 25 August 2011 16:58:18 Jan Beulich wrote:
>> There are two places here where it is entirely unclear to me where the
>> necessary PCI segment number should be taken from (as IVMD descriptors
>> don't have such, only IVHD ones do).
>>
>> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
>>
>> --- 2011-08-25.orig/xen/drivers/passthrough/amd/iommu_acpi.c 2011-06-28
>> 09:41:39.000000000 +0200 +++
>> 2011-08-25/xen/drivers/passthrough/amd/iommu_acpi.c 2011-08-25
>> 15:06:47.000000000 +0200 @@ -30,6 +30,7 @@ static unsigned short __initdata
>> last_bd
>> static void __init add_ivrs_mapping_entry(
>> u16 bdf, u16 alias_id, u8 flags, struct amd_iommu *iommu)
>> {
>> + struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(iommu->seg);
>> u8 sys_mgt, lint1_pass, lint0_pass, nmi_pass, ext_int_pass, init_pass;
>> ASSERT( ivrs_mappings != NULL );
>>
>> @@ -118,9 +119,10 @@ static void __init reserve_iommu_exclusi
>> }
>>
>> static void __init reserve_unity_map_for_device(
>> - u16 bdf, unsigned long base,
>> + u16 seg, u16 bdf, unsigned long base,
>> unsigned long length, u8 iw, u8 ir)
>> {
>> + struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(seg);
>> unsigned long old_top, new_top;
>>
>> /* need to extend unity-mapped range? */
>> @@ -147,6 +149,7 @@ static void __init reserve_unity_map_for
>> static int __init register_exclusion_range_for_all_devices(
>> unsigned long base, unsigned long limit, u8 iw, u8 ir)
>> {
>> + int seg = 0; /* XXX */
>> unsigned long range_top, iommu_top, length;
>> struct amd_iommu *iommu;
>> u16 bdf;
>> @@ -163,7 +166,7 @@ static int __init register_exclusion_ran
>> /* reserve r/w unity-mapped page entries for devices */
>> /* note: these entries are part of the exclusion range */
>> for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
>> - reserve_unity_map_for_device(bdf, base, length, iw, ir);
>> + reserve_unity_map_for_device(seg, bdf, base, length, iw, ir);
>> /* push 'base' just outside of virtual address space */
>> base = iommu_top;
>> }
>> @@ -180,11 +183,13 @@ static int __init register_exclusion_ran
>> static int __init register_exclusion_range_for_device(
>> u16 bdf, unsigned long base, unsigned long limit, u8 iw, u8 ir)
>> {
>> + int seg = 0; /* XXX */
>> + struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(seg);
>> unsigned long range_top, iommu_top, length;
>> struct amd_iommu *iommu;
>> u16 req;
>>
>> - iommu = find_iommu_for_device(bdf);
>> + iommu = find_iommu_for_device(seg, bdf);
>> if ( !iommu )
>> {
>> AMD_IOMMU_DEBUG("IVMD Error: No IOMMU for Dev_Id 0x%x!\n", bdf);
>> @@ -202,8 +207,8 @@ static int __init register_exclusion_ran
>> length = range_top - base;
>> /* reserve unity-mapped page entries for device */
>> /* note: these entries are part of the exclusion range */
>> - reserve_unity_map_for_device(bdf, base, length, iw, ir);
>> - reserve_unity_map_for_device(req, base, length, iw, ir);
>> + reserve_unity_map_for_device(seg, bdf, base, length, iw, ir);
>> + reserve_unity_map_for_device(seg, req, base, length, iw, ir);
>>
>> /* push 'base' just outside of virtual address space */
>> base = iommu_top;
>> @@ -240,11 +245,13 @@ static int __init register_exclusion_ran
>> /* note: these entries are part of the exclusion range */
>> for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
>> {
>> - if ( iommu == find_iommu_for_device(bdf) )
>> + if ( iommu == find_iommu_for_device(iommu->seg, bdf) )
>> {
>> - reserve_unity_map_for_device(bdf, base, length, iw, ir);
>> - req = ivrs_mappings[bdf].dte_requestor_id;
>> - reserve_unity_map_for_device(req, base, length, iw, ir);
>> + reserve_unity_map_for_device(iommu->seg, bdf, base,
>> length, + iw, ir);
>> + req = get_ivrs_mappings(iommu->seg)[bdf].dte_requestor_id;
>> + reserve_unity_map_for_device(iommu->seg, req, base,
>> length, + iw, ir);
>> }
>> }
>>
>> @@ -627,7 +634,7 @@ static u16 __init parse_ivhd_device_exte
>> }
>>
>> static u16 __init parse_ivhd_device_special(
>> - union acpi_ivhd_device *ivhd_device,
>> + union acpi_ivhd_device *ivhd_device, u16 seg,
>> u16 header_length, u16 block_length, struct amd_iommu *iommu)
>> {
>> u16 dev_length, bdf;
>> @@ -648,6 +655,7 @@ static u16 __init parse_ivhd_device_spec
>>
>> add_ivrs_mapping_entry(bdf, bdf, ivhd_device->header.flags, iommu);
>> /* set device id of ioapic */
>> + ioapic_seg[ivhd_device->special.handle] = seg;
>> ioapic_bdf[ivhd_device->special.handle] = bdf;
>> return dev_length;
>> }
>> @@ -729,7 +737,7 @@ static int __init parse_ivhd_block(struc
>> break;
>> case AMD_IOMMU_ACPI_IVHD_DEV_SPECIAL:
>> dev_length = parse_ivhd_device_special(
>> - ivhd_device,
>> + ivhd_device, ivhd_block->pci_segment,
>> ivhd_block->header.length, block_length, iommu);
>> break;
>> default:
>> --- 2011-08-25.orig/xen/drivers/passthrough/amd/iommu_detect.c 2011-04-04
>> 09:11:24.000000000 +0200 +++
>> 2011-08-25/xen/drivers/passthrough/amd/iommu_detect.c 2011-08-25
>> 15:06:47.000000000 +0200 @@ -27,8 +27,8 @@
>> #include <asm/hvm/svm/amd-iommu-proto.h>
>> #include <asm/hvm/svm/amd-iommu-acpi.h>
>>
>> -static int __init get_iommu_msi_capabilities(u8 bus, u8 dev, u8 func,
>> - struct amd_iommu *iommu)
>> +static int __init get_iommu_msi_capabilities(
>> + u16 seg, u8 bus, u8 dev, u8 func, struct amd_iommu *iommu)
>> {
>> int cap_ptr, cap_id;
>> u32 cap_header;
>> @@ -66,8 +66,8 @@ static int __init get_iommu_msi_capabili
>> return 0;
>> }
>>
>> -static int __init get_iommu_capabilities(u8 bus, u8 dev, u8 func, u8
>> cap_ptr, - struct amd_iommu *iommu)
>> +static int __init get_iommu_capabilities(
>> + u16 seg, u8 bus, u8 dev, u8 func, u8 cap_ptr, struct amd_iommu *iommu)
>> {
>> u32 cap_header, cap_range, misc_info;
>>
>> @@ -121,6 +121,11 @@ int __init amd_iommu_detect_one_acpi(voi
>>
>> spin_lock_init(&iommu->lock);
>>
>> + iommu->seg = ivhd_block->pci_segment;
>> + if (alloc_ivrs_mappings(ivhd_block->pci_segment)) {
>> + xfree(iommu);
>> + return -ENOMEM;
>> + }
>> iommu->bdf = ivhd_block->header.dev_id;
>> iommu->cap_offset = ivhd_block->cap_offset;
>> iommu->mmio_base_phys = ivhd_block->mmio_base;
>> @@ -147,8 +152,9 @@ int __init amd_iommu_detect_one_acpi(voi
>> bus = iommu->bdf >> 8;
>> dev = PCI_SLOT(iommu->bdf & 0xFF);
>> func = PCI_FUNC(iommu->bdf & 0xFF);
>> - get_iommu_capabilities(bus, dev, func, iommu->cap_offset, iommu);
>> - get_iommu_msi_capabilities(bus, dev, func, iommu);
>> + get_iommu_capabilities(iommu->seg, bus, dev, func,
>> + iommu->cap_offset, iommu);
>> + get_iommu_msi_capabilities(iommu->seg, bus, dev, func, iommu);
>>
>> list_add_tail(&iommu->list, &amd_iommu_head);
>>
>> --- 2011-08-25.orig/xen/drivers/passthrough/amd/iommu_init.c 2011-08-19
>> 17:08:35.000000000 +0200 +++
>> 2011-08-25/xen/drivers/passthrough/amd/iommu_init.c 2011-08-25
>> 15:06:47.000000000 +0200 @@ -33,7 +33,7 @@ static struct amd_iommu
>> **__read_mostly
>> static int __initdata nr_amd_iommus;
>>
>> unsigned short ivrs_bdf_entries;
>> -struct ivrs_mappings *ivrs_mappings;
>> +static struct radix_tree_root ivrs_maps;
>> struct list_head amd_iommu_head;
>> struct table_struct device_table;
>>
>> @@ -697,7 +697,6 @@ error_out:
>> static void __init amd_iommu_init_cleanup(void)
>> {
>> struct amd_iommu *iommu, *next;
>> - int bdf;
>>
>> /* free amd iommu list */
>> list_for_each_entry_safe ( iommu, next, &amd_iommu_head, list )
>> @@ -713,21 +712,13 @@ static void __init amd_iommu_init_cleanu
>> }
>>
>> /* free interrupt remapping table */
>> - for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
>> - {
>> - if ( ivrs_mappings[bdf].intremap_table )
>> - amd_iommu_free_intremap_table(bdf);
>> - }
>> + iterate_ivrs_entries(amd_iommu_free_intremap_table);
>>
>> /* free device table */
>> deallocate_iommu_table_struct(&device_table);
>>
>> /* free ivrs_mappings[] */
>> - if ( ivrs_mappings )
>> - {
>> - xfree(ivrs_mappings);
>> - ivrs_mappings = NULL;
>> - }
>> + radix_tree_destroy(&ivrs_maps, xfree);
>>
>> /* free irq_to_iommu[] */
>> if ( irq_to_iommu )
>> @@ -741,19 +732,71 @@ static void __init amd_iommu_init_cleanu
>> iommu_intremap = 0;
>> }
>>
>> -static int __init init_ivrs_mapping(void)
>> +/*
>> + * We allocate an extra array element to store the segment number
>> + * (and in the future perhaps other global information).
>> + */
>> +#define IVRS_MAPPINGS_SEG(m) m[ivrs_bdf_entries].dte_requestor_id
>> +
>> +struct ivrs_mappings *get_ivrs_mappings(u16 seg)
>> +{
>> + return radix_tree_lookup(&ivrs_maps, seg);
>> +}
>> +
>> +int iterate_ivrs_mappings(int (*handler)(u16 seg, struct ivrs_mappings *))
>> {
>> + u16 seg = 0;
>> + int rc = 0;
>> +
>> + do {
>> + struct ivrs_mappings *map;
>> +
>> + if ( !radix_tree_gang_lookup(&ivrs_maps, (void **)&map, seg, 1) )
>> + break;
>> + seg = IVRS_MAPPINGS_SEG(map);
>> + rc = handler(seg, map);
>> + } while ( !rc && ++seg );
>> +
>> + return rc;
>> +}
>> +
>> +int iterate_ivrs_entries(int (*handler)(u16 seg, struct ivrs_mappings *))
>> +{
>> + u16 seg = 0;
>> + int rc = 0;
>> +
>> + do {
>> + struct ivrs_mappings *map;
>> + int bdf;
>> +
>> + if ( !radix_tree_gang_lookup(&ivrs_maps, (void **)&map, seg, 1) )
>> + break;
>> + seg = IVRS_MAPPINGS_SEG(map);
>> + for ( bdf = 0; !rc && bdf < ivrs_bdf_entries; ++bdf )
>> + rc = handler(seg, map + bdf);
>> + } while ( !rc && ++seg );
>> +
>> + return rc;
>> +}
>> +
>> +int __init alloc_ivrs_mappings(u16 seg)
>> +{
>> + struct ivrs_mappings *ivrs_mappings;
>> int bdf;
>>
>> BUG_ON( !ivrs_bdf_entries );
>>
>> - ivrs_mappings = xmalloc_array( struct ivrs_mappings,
>> ivrs_bdf_entries); + if ( get_ivrs_mappings(seg) )
>> + return 0;
>> +
>> + ivrs_mappings = xmalloc_array(struct ivrs_mappings, ivrs_bdf_entries +
>> 1); if ( ivrs_mappings == NULL )
>> {
>> AMD_IOMMU_DEBUG("Error allocating IVRS Mappings table\n");
>> return -ENOMEM;
>> }
>> memset(ivrs_mappings, 0, ivrs_bdf_entries * sizeof(struct
>> ivrs_mappings)); + IVRS_MAPPINGS_SEG(ivrs_mappings) = seg;
>>
>> /* assign default values for device entries */
>> for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
>> @@ -775,10 +818,14 @@ static int __init init_ivrs_mapping(void
>> if ( amd_iommu_perdev_intremap )
>> spin_lock_init(&ivrs_mappings[bdf].intremap_lock);
>> }
>> +
>> + radix_tree_insert(&ivrs_maps, seg, ivrs_mappings);
>> +
>> return 0;
>> }
>>
>> -static int __init amd_iommu_setup_device_table(void)
>> +static int __init amd_iommu_setup_device_table(
>> + u16 seg, struct ivrs_mappings *ivrs_mappings)
>> {
>> int bdf;
>> void *intr_tb, *dte;
>> @@ -849,7 +896,8 @@ int __init amd_iommu_init(void)
>> if ( !ivrs_bdf_entries )
>> goto error_out;
>>
>> - if ( init_ivrs_mapping() != 0 )
>> + radix_tree_init(&ivrs_maps);
>> + if ( alloc_ivrs_mappings(0) != 0 )
>> goto error_out;
>>
>> if ( amd_iommu_update_ivrs_mapping_acpi() != 0 )
>> @@ -860,7 +908,7 @@ int __init amd_iommu_init(void)
>> goto error_out;
>>
>> /* allocate and initialize a global device table shared by all iommus
>> */ - if ( amd_iommu_setup_device_table() != 0 )
>> + if ( iterate_ivrs_mappings(amd_iommu_setup_device_table) != 0 )
>> goto error_out;
>>
>> /* per iommu initialization */
>> @@ -905,7 +953,8 @@ static void invalidate_all_domain_pages(
>> amd_iommu_flush_all_pages(d);
>> }
>>
>> -static void invalidate_all_devices(void)
>> +static int _invalidate_all_devices(
>> + u16 seg, struct ivrs_mappings *ivrs_mappings)
>> {
>> int bdf, req_id;
>> unsigned long flags;
>> @@ -913,7 +962,7 @@ static void invalidate_all_devices(void)
>>
>> for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
>> {
>> - iommu = find_iommu_for_device(bdf);
>> + iommu = find_iommu_for_device(seg, bdf);
>> req_id = ivrs_mappings[bdf].dte_requestor_id;
>> if ( iommu )
>> {
>> @@ -924,6 +973,13 @@ static void invalidate_all_devices(void)
>> spin_unlock_irqrestore(&iommu->lock, flags);
>> }
>> }
>> +
>> + return 0;
>> +}
>> +
>> +static void invalidate_all_devices(void)
>> +{
>> + iterate_ivrs_mappings(_invalidate_all_devices);
>> }
>>
>> void amd_iommu_suspend(void)
>> --- 2011-08-25.orig/xen/drivers/passthrough/amd/iommu_intr.c 2011-08-19
>> 17:08:35.000000000 +0200 +++
>> 2011-08-25/xen/drivers/passthrough/amd/iommu_intr.c 2011-08-25
>> 15:06:47.000000000 +0200 @@ -28,20 +28,21 @@
>> #define INTREMAP_ENTRIES (1 << INTREMAP_LENGTH)
>>
>> int ioapic_bdf[MAX_IO_APICS];
>> +u16 ioapic_seg[MAX_IO_APICS];
>> void *shared_intremap_table;
>> static DEFINE_SPINLOCK(shared_intremap_lock);
>>
>> -static spinlock_t* get_intremap_lock(int req_id)
>> +static spinlock_t* get_intremap_lock(int seg, int req_id)
>> {
>> return (amd_iommu_perdev_intremap ?
>> - &ivrs_mappings[req_id].intremap_lock:
>> + &get_ivrs_mappings(seg)[req_id].intremap_lock:
>> &shared_intremap_lock);
>> }
>>
>> -static int get_intremap_requestor_id(int bdf)
>> +static int get_intremap_requestor_id(int seg, int bdf)
>> {
>> ASSERT( bdf < ivrs_bdf_entries );
>> - return ivrs_mappings[bdf].dte_requestor_id;
>> + return get_ivrs_mappings(seg)[bdf].dte_requestor_id;
>> }
>>
>> static int get_intremap_offset(u8 vector, u8 dm)
>> @@ -53,20 +54,20 @@ static int get_intremap_offset(u8 vector
>> return offset;
>> }
>>
>> -static u8 *get_intremap_entry(int bdf, int offset)
>> +static u8 *get_intremap_entry(int seg, int bdf, int offset)
>> {
>> u8 *table;
>>
>> - table = (u8*)ivrs_mappings[bdf].intremap_table;
>> + table = (u8*)get_ivrs_mappings(seg)[bdf].intremap_table;
>> ASSERT( (table != NULL) && (offset < INTREMAP_ENTRIES) );
>>
>> return (u8*) (table + offset);
>> }
>>
>> -static void free_intremap_entry(int bdf, int offset)
>> +static void free_intremap_entry(int seg, int bdf, int offset)
>> {
>> u32* entry;
>> - entry = (u32*)get_intremap_entry(bdf, offset);
>> + entry = (u32*)get_intremap_entry(seg, bdf, offset);
>> memset(entry, 0, sizeof(u32));
>> }
>>
>> @@ -125,8 +126,8 @@ static void update_intremap_entry_from_i
>> spinlock_t *lock;
>> int offset;
>>
>> - req_id = get_intremap_requestor_id(bdf);
>> - lock = get_intremap_lock(req_id);
>> + req_id = get_intremap_requestor_id(iommu->seg, bdf);
>> + lock = get_intremap_lock(iommu->seg, req_id);
>>
>> delivery_mode = rte->delivery_mode;
>> vector = rte->vector;
>> @@ -136,7 +137,7 @@ static void update_intremap_entry_from_i
>> spin_lock_irqsave(lock, flags);
>>
>> offset = get_intremap_offset(vector, delivery_mode);
>> - entry = (u32*)get_intremap_entry(req_id, offset);
>> + entry = (u32*)get_intremap_entry(iommu->seg, req_id, offset);
>> update_intremap_entry(entry, vector, delivery_mode, dest_mode, dest);
>>
>> spin_unlock_irqrestore(lock, flags);
>> @@ -175,7 +176,7 @@ int __init amd_iommu_setup_ioapic_remapp
>>
>> /* get device id of ioapic devices */
>> bdf = ioapic_bdf[IO_APIC_ID(apic)];
>> - iommu = find_iommu_for_device(bdf);
>> + iommu = find_iommu_for_device(ioapic_seg[IO_APIC_ID(apic)],
>> bdf); if ( !iommu )
>> {
>> AMD_IOMMU_DEBUG("Fail to find iommu for ioapic "
>> @@ -183,8 +184,8 @@ int __init amd_iommu_setup_ioapic_remapp
>> continue;
>> }
>>
>> - req_id = get_intremap_requestor_id(bdf);
>> - lock = get_intremap_lock(req_id);
>> + req_id = get_intremap_requestor_id(iommu->seg, bdf);
>> + lock = get_intremap_lock(iommu->seg, req_id);
>>
>> delivery_mode = rte.delivery_mode;
>> vector = rte.vector;
>> @@ -193,7 +194,7 @@ int __init amd_iommu_setup_ioapic_remapp
>>
>> spin_lock_irqsave(lock, flags);
>> offset = get_intremap_offset(vector, delivery_mode);
>> - entry = (u32*)get_intremap_entry(req_id, offset);
>> + entry = (u32*)get_intremap_entry(iommu->seg, req_id, offset);
>> update_intremap_entry(entry, vector,
>> delivery_mode, dest_mode, dest);
>> spin_unlock_irqrestore(lock, flags);
>> @@ -227,7 +228,7 @@ void amd_iommu_ioapic_update_ire(
>>
>> /* get device id of ioapic devices */
>> bdf = ioapic_bdf[IO_APIC_ID(apic)];
>> - iommu = find_iommu_for_device(bdf);
>> + iommu = find_iommu_for_device(ioapic_seg[IO_APIC_ID(apic)], bdf);
>> if ( !iommu )
>> {
>> AMD_IOMMU_DEBUG("Fail to find iommu for ioapic device id =
>> 0x%x\n", @@ -289,28 +290,28 @@ static void update_intremap_entry_from_m
>> int offset;
>>
>> bdf = (pdev->bus << 8) | pdev->devfn;
>> - req_id = get_dma_requestor_id(bdf);
>> - alias_id = get_intremap_requestor_id(bdf);
>> + req_id = get_dma_requestor_id(pdev->seg, bdf);
>> + alias_id = get_intremap_requestor_id(pdev->seg, bdf);
>>
>> if ( msg == NULL )
>> {
>> - lock = get_intremap_lock(req_id);
>> + lock = get_intremap_lock(iommu->seg, req_id);
>> spin_lock_irqsave(lock, flags);
>> - free_intremap_entry(req_id, msi_desc->remap_index);
>> + free_intremap_entry(iommu->seg, req_id, msi_desc->remap_index);
>> spin_unlock_irqrestore(lock, flags);
>>
>> if ( ( req_id != alias_id ) &&
>> - ivrs_mappings[alias_id].intremap_table != NULL )
>> + get_ivrs_mappings(pdev->seg)[alias_id].intremap_table != NULL
>> ) {
>> - lock = get_intremap_lock(alias_id);
>> + lock = get_intremap_lock(iommu->seg, alias_id);
>> spin_lock_irqsave(lock, flags);
>> - free_intremap_entry(alias_id, msi_desc->remap_index);
>> + free_intremap_entry(iommu->seg, alias_id,
>> msi_desc->remap_index); spin_unlock_irqrestore(lock, flags);
>> }
>> goto done;
>> }
>>
>> - lock = get_intremap_lock(req_id);
>> + lock = get_intremap_lock(iommu->seg, req_id);
>>
>> spin_lock_irqsave(lock, flags);
>> dest_mode = (msg->address_lo >> MSI_ADDR_DESTMODE_SHIFT) & 0x1;
>> @@ -320,7 +321,7 @@ static void update_intremap_entry_from_m
>> offset = get_intremap_offset(vector, delivery_mode);
>> msi_desc->remap_index = offset;
>>
>> - entry = (u32*)get_intremap_entry(req_id, offset);
>> + entry = (u32*)get_intremap_entry(iommu->seg, req_id, offset);
>> update_intremap_entry(entry, vector, delivery_mode, dest_mode, dest);
>> spin_unlock_irqrestore(lock, flags);
>>
>> @@ -331,12 +332,12 @@ static void update_intremap_entry_from_m
>> * devices.
>> */
>>
>> - lock = get_intremap_lock(alias_id);
>> + lock = get_intremap_lock(iommu->seg, alias_id);
>> if ( ( req_id != alias_id ) &&
>> - ivrs_mappings[alias_id].intremap_table != NULL )
>> + get_ivrs_mappings(pdev->seg)[alias_id].intremap_table != NULL )
>> {
>> spin_lock_irqsave(lock, flags);
>> - entry = (u32*)get_intremap_entry(alias_id, offset);
>> + entry = (u32*)get_intremap_entry(iommu->seg, alias_id, offset);
>> update_intremap_entry(entry, vector, delivery_mode, dest_mode,
>> dest); spin_unlock_irqrestore(lock, flags);
>> }
>> @@ -362,7 +363,7 @@ void amd_iommu_msi_msg_update_ire(
>> if ( !iommu_intremap )
>> return;
>>
>> - iommu = find_iommu_for_device((pdev->bus << 8) | pdev->devfn);
>> + iommu = find_iommu_for_device(pdev->seg, (pdev->bus << 8) |
>> pdev->devfn);
>>
>> if ( !iommu )
>> {
>> @@ -379,15 +380,18 @@ void amd_iommu_read_msi_from_ire(
>> {
>> }
>>
>> -void __init amd_iommu_free_intremap_table(int bdf)
>> +int __init amd_iommu_free_intremap_table(
>> + u16 seg, struct ivrs_mappings *ivrs_mapping)
>> {
>> - void *tb = ivrs_mappings[bdf].intremap_table;
>> + void *tb = ivrs_mapping->intremap_table;
>>
>> if ( tb )
>> {
>> __free_amd_iommu_tables(tb, INTREMAP_TABLE_ORDER);
>> - ivrs_mappings[bdf].intremap_table = NULL;
>> + ivrs_mapping->intremap_table = NULL;
>> }
>> +
>> + return 0;
>> }
>>
>> void* __init amd_iommu_alloc_intremap_table(void)
>> --- 2011-08-25.orig/xen/drivers/passthrough/amd/iommu_map.c 2011-08-25
>> 08:21:53.000000000 +0200 +++
>> 2011-08-25/xen/drivers/passthrough/amd/iommu_map.c 2011-08-25
>> 15:06:47.000000000 +0200 @@ -719,8 +719,8 @@ static int
>> update_paging_mode(struct dom
>> for_each_pdev( d, pdev )
>> {
>> bdf = (pdev->bus << 8) | pdev->devfn;
>> - req_id = get_dma_requestor_id(bdf);
>> - iommu = find_iommu_for_device(bdf);
>> + req_id = get_dma_requestor_id(pdev->seg, bdf);
>> + iommu = find_iommu_for_device(pdev->seg, bdf);
>> if ( !iommu )
>> {
>> AMD_IOMMU_DEBUG("%s Fail to find iommu.\n", __func__);
>> --- 2011-08-25.orig/xen/drivers/passthrough/amd/pci_amd_iommu.c 2011-08-25
>> 15:06:40.000000000 +0200 +++
>> 2011-08-25/xen/drivers/passthrough/amd/pci_amd_iommu.c 2011-08-25
>> 15:06:47.000000000 +0200 @@ -29,10 +29,12 @@
>> extern bool_t __read_mostly opt_irq_perdev_vector_map;
>> extern bool_t __read_mostly iommu_amd_perdev_vector_map;
>>
>> -struct amd_iommu *find_iommu_for_device(int bdf)
>> +struct amd_iommu *find_iommu_for_device(int seg, int bdf)
>> {
>> + struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(seg);
>> +
>> BUG_ON ( bdf >= ivrs_bdf_entries );
>> - return ivrs_mappings[bdf].iommu;
>> + return ivrs_mappings ? ivrs_mappings[bdf].iommu : NULL;
>> }
>>
>> /*
>> @@ -43,8 +45,9 @@ struct amd_iommu *find_iommu_for_device(
>> * Return original device id, if device has valid interrupt remapping
>> * table setup for both select entry and alias entry.
>> */
>> -int get_dma_requestor_id(u16 bdf)
>> +int get_dma_requestor_id(u16 seg, u16 bdf)
>> {
>> + struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(seg);
>> int req_id;
>>
>> BUG_ON ( bdf >= ivrs_bdf_entries );
>> @@ -95,7 +98,7 @@ static void amd_iommu_setup_domain_devic
>> valid = 0;
>>
>> /* get device-table entry */
>> - req_id = get_dma_requestor_id(bdf);
>> + req_id = get_dma_requestor_id(iommu->seg, bdf);
>> dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
>>
>> spin_lock_irqsave(&iommu->lock, flags);
>> @@ -139,7 +142,7 @@ static void __init amd_iommu_setup_dom0_
>> list_add(&pdev->domain_list, &d->arch.pdev_list);
>>
>> bdf = (bus << 8) | devfn;
>> - iommu = find_iommu_for_device(bdf);
>> + iommu = find_iommu_for_device(pdev->seg, bdf);
>>
>> if ( likely(iommu != NULL) )
>> amd_iommu_setup_domain_device(d, iommu, bdf);
>> @@ -270,7 +273,7 @@ static void amd_iommu_disable_domain_dev
>> int req_id;
>>
>> BUG_ON ( iommu->dev_table.buffer == NULL );
>> - req_id = get_dma_requestor_id(bdf);
>> + req_id = get_dma_requestor_id(iommu->seg, bdf);
>> dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE);
>>
>> spin_lock_irqsave(&iommu->lock, flags);
>> @@ -301,12 +304,12 @@ static int reassign_device( struct domai
>> return -ENODEV;
>>
>> bdf = (bus << 8) | devfn;
>> - iommu = find_iommu_for_device(bdf);
>> + iommu = find_iommu_for_device(seg, bdf);
>> if ( !iommu )
>> {
>> AMD_IOMMU_DEBUG("Fail to find iommu."
>> - " %02x:%x02.%x cannot be assigned to domain %d\n",
>> - bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
>> + " %04x:%02x:%x02.%x cannot be assigned to
>> dom%d\n", + seg, bus, PCI_SLOT(devfn),
>> PCI_FUNC(devfn), target->domain_id);
>> return -ENODEV;
>> }
>> @@ -322,8 +325,8 @@ static int reassign_device( struct domai
>> allocate_domain_resources(t);
>>
>> amd_iommu_setup_domain_device(target, iommu, bdf);
>> - AMD_IOMMU_DEBUG("Re-assign %02x:%02x.%x from domain %d to domain
>> %d\n", - bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
>> + AMD_IOMMU_DEBUG("Re-assign %04x:%02x:%02x.%u from dom%d to dom%d\n",
>> + seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
>> source->domain_id, target->domain_id);
>>
>> return 0;
>> @@ -331,8 +334,9 @@ static int reassign_device( struct domai
>>
>> static int amd_iommu_assign_device(struct domain *d, u16 seg, u8 bus, u8
>> devfn) {
>> + struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(seg);
>> int bdf = (bus << 8) | devfn;
>> - int req_id = get_dma_requestor_id(bdf);
>> + int req_id = get_dma_requestor_id(seg, bdf);
>>
>> if ( ivrs_mappings[req_id].unity_map_enable )
>> {
>> @@ -422,12 +426,12 @@ static int amd_iommu_add_device(struct p
>> return -EINVAL;
>>
>> bdf = (pdev->bus << 8) | pdev->devfn;
>> - iommu = find_iommu_for_device(bdf);
>> + iommu = find_iommu_for_device(pdev->seg, bdf);
>> if ( !iommu )
>> {
>> AMD_IOMMU_DEBUG("Fail to find iommu."
>> - " %02x:%02x.%x cannot be assigned to domain %d\n",
>> - pdev->bus, PCI_SLOT(pdev->devfn),
>> + " %04x:%02x:%02x.%u cannot be assigned to
>> dom%d\n", + pdev->seg, pdev->bus,
>> PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->domain->domain_id);
>> return -ENODEV;
>> }
>> @@ -444,12 +448,12 @@ static int amd_iommu_remove_device(struc
>> return -EINVAL;
>>
>> bdf = (pdev->bus << 8) | pdev->devfn;
>> - iommu = find_iommu_for_device(bdf);
>> + iommu = find_iommu_for_device(pdev->seg, bdf);
>> if ( !iommu )
>> {
>> AMD_IOMMU_DEBUG("Fail to find iommu."
>> - " %02x:%02x.%x cannot be removed from domain
>> %d\n", - pdev->bus, PCI_SLOT(pdev->devfn),
>> + " %04x:%02x:%02x.%u cannot be removed from
>> dom%d\n", + pdev->seg, pdev->bus,
>> PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev->domain->domain_id);
>> return -ENODEV;
>> }
>> @@ -463,7 +467,7 @@ static int amd_iommu_group_id(u16 seg, u
>> int rt;
>> int bdf = (bus << 8) | devfn;
>> rt = ( bdf < ivrs_bdf_entries ) ?
>> - get_dma_requestor_id(bdf) :
>> + get_dma_requestor_id(seg, bdf) :
>> bdf;
>> return rt;
>> }
>> --- 2011-08-25.orig/xen/include/asm-x86/amd-iommu.h 2011-06-16
>> 09:21:02.000000000 +0200 +++ 2011-08-25/xen/include/asm-x86/amd-iommu.h
>> 2011-08-25 15:06:47.000000000 +0200 @@ -40,6 +40,7 @@ struct amd_iommu {
>> struct list_head list;
>> spinlock_t lock; /* protect iommu */
>>
>> + u16 seg;
>> u16 bdf;
>> u8 cap_offset;
>> u8 revision;
>> @@ -101,6 +102,10 @@ struct ivrs_mappings {
>> };
>>
>> extern unsigned short ivrs_bdf_entries;
>> -extern struct ivrs_mappings *ivrs_mappings;
>> +
>> +int alloc_ivrs_mappings(u16 seg);
>> +struct ivrs_mappings *get_ivrs_mappings(u16 seg);
>> +int iterate_ivrs_mappings(int (*)(u16 seg, struct ivrs_mappings *));
>> +int iterate_ivrs_entries(int (*)(u16 seg, struct ivrs_mappings *));
>>
>> #endif /* _ASM_X86_64_AMD_IOMMU_H */
>> --- 2011-08-25.orig/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h
>> 2011-08-19 17:08:35.000000000 +0200 +++
>> 2011-08-25/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h 2011-08-25
>> 15:06:47.000000000 +0200 @@ -65,7 +65,7 @@ int
>> amd_iommu_reserve_domain_unity_map(s
>> void amd_iommu_share_p2m(struct domain *d);
>>
>> /* device table functions */
>> -int get_dma_requestor_id(u16 bdf);
>> +int get_dma_requestor_id(u16 seg, u16 bdf);
>> void amd_iommu_add_dev_table_entry(
>> u32 *dte, u8 sys_mgt, u8 dev_ex, u8 lint1_pass, u8 lint0_pass,
>> u8 nmi_pass, u8 ext_int_pass, u8 init_pass);
>> @@ -80,12 +80,12 @@ int send_iommu_command(struct amd_iommu
>> void flush_command_buffer(struct amd_iommu *iommu);
>>
>> /* find iommu for bdf */
>> -struct amd_iommu *find_iommu_for_device(int bdf);
>> +struct amd_iommu *find_iommu_for_device(int seg, int bdf);
>>
>> /* interrupt remapping */
>> int amd_iommu_setup_ioapic_remapping(void);
>> void *amd_iommu_alloc_intremap_table(void);
>> -void amd_iommu_free_intremap_table(int bdf);
>> +int amd_iommu_free_intremap_table(u16 seg, struct ivrs_mappings *);
>> void invalidate_interrupt_table(struct amd_iommu *iommu, u16 device_id);
>> void amd_iommu_ioapic_update_ire(
>> unsigned int apic, unsigned int reg, unsigned int value);
>> @@ -95,6 +95,7 @@ void amd_iommu_read_msi_from_ire(
>> struct msi_desc *msi_desc, struct msi_msg *msg);
>>
>> extern int ioapic_bdf[MAX_IO_APICS];
>> +extern u16 ioapic_seg[MAX_IO_APICS];
>> extern void *shared_intremap_table;
>>
>> /* power management support */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|