ACPI: eliminate duplicate IVRS definitions Use their proper counterparts in include/acpi/actbl*.h instead. Signed-off-by: Jan Beulich --- a/xen/drivers/passthrough/amd/iommu_acpi.c +++ b/xen/drivers/passthrough/amd/iommu_acpi.c @@ -20,10 +20,38 @@ #include #include +#include #include #include #include -#include + +/* Some helper structures, particularly to deal with ranges. */ + +struct acpi_ivhd_device_range { + struct acpi_ivrs_device4 start; + struct acpi_ivrs_device4 end; +}; + +struct acpi_ivhd_device_alias_range { + struct acpi_ivrs_device8a alias; + struct acpi_ivrs_device4 end; +}; + +struct acpi_ivhd_device_extended_range { + struct acpi_ivrs_device8b extended; + struct acpi_ivrs_device4 end; +}; + +union acpi_ivhd_device { + struct acpi_ivrs_de_header header; + struct acpi_ivrs_device4 select; + struct acpi_ivhd_device_range range; + struct acpi_ivrs_device8a alias; + struct acpi_ivhd_device_alias_range alias_range; + struct acpi_ivrs_device8b extended; + struct acpi_ivhd_device_extended_range extended_range; + struct acpi_ivrs_device8c special; +}; static unsigned short __initdata last_bdf; @@ -242,12 +270,12 @@ static int __init register_exclusion_ran } static int __init parse_ivmd_device_select( - struct acpi_ivmd_block_header *ivmd_block, + const struct acpi_ivrs_memory *ivmd_block, unsigned long base, unsigned long limit, u8 iw, u8 ir) { u16 bdf; - bdf = ivmd_block->header.dev_id; + bdf = ivmd_block->header.device_id; if ( bdf >= ivrs_bdf_entries ) { AMD_IOMMU_DEBUG("IVMD Error: Invalid Dev_Id 0x%x\n", bdf); @@ -258,13 +286,13 @@ static int __init parse_ivmd_device_sele } static int __init parse_ivmd_device_range( - struct acpi_ivmd_block_header *ivmd_block, + const struct acpi_ivrs_memory *ivmd_block, unsigned long base, unsigned long limit, u8 iw, u8 ir) { u16 first_bdf, last_bdf, bdf; int error; - first_bdf = ivmd_block->header.dev_id; + first_bdf = ivmd_block->header.device_id; if ( first_bdf >= ivrs_bdf_entries ) { AMD_IOMMU_DEBUG("IVMD Error: " @@ -272,7 +300,7 @@ static int __init parse_ivmd_device_rang return -ENODEV; } - last_bdf = ivmd_block->last_dev_id; + last_bdf = ivmd_block->aux_data; if ( (last_bdf >= ivrs_bdf_entries) || (last_bdf <= first_bdf) ) { AMD_IOMMU_DEBUG("IVMD Error: " @@ -288,18 +316,18 @@ static int __init parse_ivmd_device_rang } static int __init parse_ivmd_device_iommu( - struct acpi_ivmd_block_header *ivmd_block, + const struct acpi_ivrs_memory *ivmd_block, unsigned long base, unsigned long limit, u8 iw, u8 ir) { struct amd_iommu *iommu; /* find target IOMMU */ - iommu = find_iommu_from_bdf_cap(ivmd_block->header.dev_id, - ivmd_block->cap_offset); + iommu = find_iommu_from_bdf_cap(ivmd_block->header.device_id, + ivmd_block->aux_data); if ( !iommu ) { AMD_IOMMU_DEBUG("IVMD Error: No IOMMU for Dev_Id 0x%x Cap 0x%x\n", - ivmd_block->header.dev_id, ivmd_block->cap_offset); + ivmd_block->header.device_id, ivmd_block->aux_data); return -ENODEV; } @@ -307,20 +335,19 @@ static int __init parse_ivmd_device_iomm iommu, base, limit, iw, ir); } -static int __init parse_ivmd_block(struct acpi_ivmd_block_header *ivmd_block) +static int __init parse_ivmd_block(const struct acpi_ivrs_memory *ivmd_block) { unsigned long start_addr, mem_length, base, limit; u8 iw, ir; - if ( ivmd_block->header.length < - sizeof(struct acpi_ivmd_block_header) ) + if ( ivmd_block->header.length < sizeof(*ivmd_block) ) { AMD_IOMMU_DEBUG("IVMD Error: Invalid Block Length!\n"); return -ENODEV; } - start_addr = (unsigned long)ivmd_block->start_addr; - mem_length = (unsigned long)ivmd_block->mem_length; + start_addr = (unsigned long)ivmd_block->start_address; + mem_length = (unsigned long)ivmd_block->memory_length; base = start_addr & PAGE_MASK; limit = (start_addr + mem_length - 1) & PAGE_MASK; @@ -328,20 +355,14 @@ static int __init parse_ivmd_block(struc AMD_IOMMU_DEBUG(" Start_Addr_Phys 0x%lx\n", start_addr); AMD_IOMMU_DEBUG(" Mem_Length 0x%lx\n", mem_length); - if ( get_field_from_byte(ivmd_block->header.flags, - AMD_IOMMU_ACPI_EXCLUSION_RANGE_MASK, - AMD_IOMMU_ACPI_EXCLUSION_RANGE_SHIFT) ) + if ( ivmd_block->header.flags & ACPI_IVMD_EXCLUSION_RANGE ) iw = ir = IOMMU_CONTROL_ENABLED; - else if ( get_field_from_byte(ivmd_block->header.flags, - AMD_IOMMU_ACPI_UNITY_MAPPING_MASK, - AMD_IOMMU_ACPI_UNITY_MAPPING_SHIFT) ) - { - iw = get_field_from_byte(ivmd_block->header.flags, - AMD_IOMMU_ACPI_IW_PERMISSION_MASK, - AMD_IOMMU_ACPI_IW_PERMISSION_SHIFT); - ir = get_field_from_byte(ivmd_block->header.flags, - AMD_IOMMU_ACPI_IR_PERMISSION_MASK, - AMD_IOMMU_ACPI_IR_PERMISSION_SHIFT); + else if ( ivmd_block->header.flags & ACPI_IVMD_UNITY ) + { + iw = ivmd_block->header.flags & ACPI_IVMD_READ ? + IOMMU_CONTROL_ENABLED : IOMMU_CONTROL_DISABLED; + ir = ivmd_block->header.flags & ACPI_IVMD_WRITE ? + IOMMU_CONTROL_ENABLED : IOMMU_CONTROL_DISABLED; } else { @@ -351,19 +372,19 @@ static int __init parse_ivmd_block(struc switch( ivmd_block->header.type ) { - case AMD_IOMMU_ACPI_IVMD_ALL_TYPE: + case ACPI_IVRS_TYPE_MEMORY_ALL: return register_exclusion_range_for_all_devices( base, limit, iw, ir); - case AMD_IOMMU_ACPI_IVMD_ONE_TYPE: + case ACPI_IVRS_TYPE_MEMORY_ONE: return parse_ivmd_device_select(ivmd_block, base, limit, iw, ir); - case AMD_IOMMU_ACPI_IVMD_RANGE_TYPE: + case ACPI_IVRS_TYPE_MEMORY_RANGE: return parse_ivmd_device_range(ivmd_block, base, limit, iw, ir); - case AMD_IOMMU_ACPI_IVMD_IOMMU_TYPE: + case ACPI_IVRS_TYPE_MEMORY_IOMMU: return parse_ivmd_device_iommu(ivmd_block, base, limit, iw, ir); @@ -386,45 +407,44 @@ static u16 __init parse_ivhd_device_padd } static u16 __init parse_ivhd_device_select( - union acpi_ivhd_device *ivhd_device, struct amd_iommu *iommu) + const struct acpi_ivrs_device4 *select, struct amd_iommu *iommu) { u16 bdf; - bdf = ivhd_device->header.dev_id; + bdf = select->header.id; if ( bdf >= ivrs_bdf_entries ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf); return 0; } - add_ivrs_mapping_entry(bdf, bdf, ivhd_device->header.flags, iommu); + add_ivrs_mapping_entry(bdf, bdf, select->header.data_setting, iommu); - return sizeof(struct acpi_ivhd_device_header); + return sizeof(*select); } static u16 __init parse_ivhd_device_range( - union acpi_ivhd_device *ivhd_device, + const struct acpi_ivhd_device_range *range, u16 header_length, u16 block_length, struct amd_iommu *iommu) { u16 dev_length, first_bdf, last_bdf, bdf; - dev_length = sizeof(struct acpi_ivhd_device_range); + dev_length = sizeof(*range); if ( header_length < (block_length + dev_length) ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n"); return 0; } - if ( ivhd_device->range.trailer.type != - AMD_IOMMU_ACPI_IVHD_DEV_RANGE_END ) + if ( range->end.header.type != ACPI_IVRS_TYPE_END ) { AMD_IOMMU_DEBUG("IVHD Error: " "Invalid Range: End_Type 0x%x\n", - ivhd_device->range.trailer.type); + range->end.header.type); return 0; } - first_bdf = ivhd_device->header.dev_id; + first_bdf = range->start.header.id; if ( first_bdf >= ivrs_bdf_entries ) { AMD_IOMMU_DEBUG("IVHD Error: " @@ -432,7 +452,7 @@ static u16 __init parse_ivhd_device_rang return 0; } - last_bdf = ivhd_device->range.trailer.dev_id; + last_bdf = range->end.header.id; if ( (last_bdf >= ivrs_bdf_entries) || (last_bdf <= first_bdf) ) { AMD_IOMMU_DEBUG("IVHD Error: " @@ -443,32 +463,33 @@ static u16 __init parse_ivhd_device_rang AMD_IOMMU_DEBUG(" Dev_Id Range: 0x%x -> 0x%x\n", first_bdf, last_bdf); for ( bdf = first_bdf; bdf <= last_bdf; bdf++ ) - add_ivrs_mapping_entry(bdf, bdf, ivhd_device->header.flags, iommu); + add_ivrs_mapping_entry(bdf, bdf, range->start.header.data_setting, + iommu); return dev_length; } static u16 __init parse_ivhd_device_alias( - union acpi_ivhd_device *ivhd_device, + const struct acpi_ivrs_device8a *alias, u16 header_length, u16 block_length, struct amd_iommu *iommu) { u16 dev_length, alias_id, bdf; - dev_length = sizeof(struct acpi_ivhd_device_alias); + dev_length = sizeof(*alias); if ( header_length < (block_length + dev_length) ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n"); return 0; } - bdf = ivhd_device->header.dev_id; + bdf = alias->header.id; if ( bdf >= ivrs_bdf_entries ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf); return 0; } - alias_id = ivhd_device->alias.dev_id; + alias_id = alias->used_id; if ( alias_id >= ivrs_bdf_entries ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Alias Dev_Id 0x%x\n", alias_id); @@ -477,35 +498,34 @@ static u16 __init parse_ivhd_device_alia AMD_IOMMU_DEBUG(" Dev_Id Alias: 0x%x\n", alias_id); - add_ivrs_mapping_entry(bdf, alias_id, ivhd_device->header.flags, iommu); + add_ivrs_mapping_entry(bdf, alias_id, alias->header.data_setting, iommu); return dev_length; } static u16 __init parse_ivhd_device_alias_range( - union acpi_ivhd_device *ivhd_device, + const struct acpi_ivhd_device_alias_range *range, u16 header_length, u16 block_length, struct amd_iommu *iommu) { u16 dev_length, first_bdf, last_bdf, alias_id, bdf; - dev_length = sizeof(struct acpi_ivhd_device_alias_range); + dev_length = sizeof(*range); if ( header_length < (block_length + dev_length) ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n"); return 0; } - if ( ivhd_device->alias_range.trailer.type != - AMD_IOMMU_ACPI_IVHD_DEV_RANGE_END ) + if ( range->end.header.type != ACPI_IVRS_TYPE_END ) { AMD_IOMMU_DEBUG("IVHD Error: " "Invalid Range: End_Type 0x%x\n", - ivhd_device->alias_range.trailer.type); + range->end.header.type); return 0; } - first_bdf = ivhd_device->header.dev_id; + first_bdf = range->alias.header.id; if ( first_bdf >= ivrs_bdf_entries ) { AMD_IOMMU_DEBUG("IVHD Error: " @@ -513,7 +533,7 @@ static u16 __init parse_ivhd_device_alia return 0; } - last_bdf = ivhd_device->alias_range.trailer.dev_id; + last_bdf = range->end.header.id; if ( last_bdf >= ivrs_bdf_entries || last_bdf <= first_bdf ) { AMD_IOMMU_DEBUG( @@ -521,7 +541,7 @@ static u16 __init parse_ivhd_device_alia return 0; } - alias_id = ivhd_device->alias_range.alias.dev_id; + alias_id = range->alias.used_id; if ( alias_id >= ivrs_bdf_entries ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Alias Dev_Id 0x%x\n", alias_id); @@ -532,59 +552,59 @@ static u16 __init parse_ivhd_device_alia AMD_IOMMU_DEBUG(" Dev_Id Alias: 0x%x\n", alias_id); for ( bdf = first_bdf; bdf <= last_bdf; bdf++ ) - add_ivrs_mapping_entry(bdf, alias_id, ivhd_device->header.flags, iommu); + add_ivrs_mapping_entry(bdf, alias_id, range->alias.header.data_setting, + iommu); return dev_length; } static u16 __init parse_ivhd_device_extended( - union acpi_ivhd_device *ivhd_device, + const struct acpi_ivrs_device8b *ext, u16 header_length, u16 block_length, struct amd_iommu *iommu) { u16 dev_length, bdf; - dev_length = sizeof(struct acpi_ivhd_device_extended); + dev_length = sizeof(*ext); if ( header_length < (block_length + dev_length) ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n"); return 0; } - bdf = ivhd_device->header.dev_id; + bdf = ext->header.id; if ( bdf >= ivrs_bdf_entries ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf); return 0; } - add_ivrs_mapping_entry(bdf, bdf, ivhd_device->header.flags, iommu); + add_ivrs_mapping_entry(bdf, bdf, ext->header.data_setting, iommu); return dev_length; } static u16 __init parse_ivhd_device_extended_range( - union acpi_ivhd_device *ivhd_device, + const struct acpi_ivhd_device_extended_range *range, u16 header_length, u16 block_length, struct amd_iommu *iommu) { u16 dev_length, first_bdf, last_bdf, bdf; - dev_length = sizeof(struct acpi_ivhd_device_extended_range); + dev_length = sizeof(*range); if ( header_length < (block_length + dev_length) ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n"); return 0; } - if ( ivhd_device->extended_range.trailer.type != - AMD_IOMMU_ACPI_IVHD_DEV_RANGE_END ) + if ( range->end.header.type != ACPI_IVRS_TYPE_END ) { AMD_IOMMU_DEBUG("IVHD Error: " "Invalid Range: End_Type 0x%x\n", - ivhd_device->extended_range.trailer.type); + range->end.header.type); return 0; } - first_bdf = ivhd_device->header.dev_id; + first_bdf = range->extended.header.id; if ( first_bdf >= ivrs_bdf_entries ) { AMD_IOMMU_DEBUG("IVHD Error: " @@ -592,7 +612,7 @@ static u16 __init parse_ivhd_device_exte return 0; } - last_bdf = ivhd_device->extended_range.trailer.dev_id; + last_bdf = range->end.header.id; if ( (last_bdf >= ivrs_bdf_entries) || (last_bdf <= first_bdf) ) { AMD_IOMMU_DEBUG("IVHD Error: " @@ -604,116 +624,116 @@ static u16 __init parse_ivhd_device_exte first_bdf, last_bdf); for ( bdf = first_bdf; bdf <= last_bdf; bdf++ ) - add_ivrs_mapping_entry(bdf, bdf, ivhd_device->header.flags, iommu); + add_ivrs_mapping_entry(bdf, bdf, range->extended.header.data_setting, + iommu); return dev_length; } static u16 __init parse_ivhd_device_special( - union acpi_ivhd_device *ivhd_device, u16 seg, + const struct acpi_ivrs_device8c *special, u16 seg, u16 header_length, u16 block_length, struct amd_iommu *iommu) { u16 dev_length, bdf; - dev_length = sizeof(struct acpi_ivhd_device_special); + dev_length = sizeof(*special); if ( header_length < (block_length + dev_length) ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n"); return 0; } - bdf = ivhd_device->special.dev_id; + bdf = special->used_id; if ( bdf >= ivrs_bdf_entries ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf); return 0; } - add_ivrs_mapping_entry(bdf, bdf, ivhd_device->header.flags, iommu); + add_ivrs_mapping_entry(bdf, bdf, special->header.data_setting, iommu); /* set device id of ioapic */ - ioapic_sbdf[ivhd_device->special.handle].bdf = bdf; - ioapic_sbdf[ivhd_device->special.handle].seg = seg; + ioapic_sbdf[special->handle].bdf = bdf; + ioapic_sbdf[special->handle].seg = seg; return dev_length; } -static int __init parse_ivhd_block(struct acpi_ivhd_block_header *ivhd_block) +static int __init parse_ivhd_block(const struct acpi_ivrs_hardware *ivhd_block) { - union acpi_ivhd_device *ivhd_device; + const union acpi_ivhd_device *ivhd_device; u16 block_length, dev_length; struct amd_iommu *iommu; - if ( ivhd_block->header.length < - sizeof(struct acpi_ivhd_block_header) ) + if ( ivhd_block->header.length < sizeof(*ivhd_block) ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Block Length!\n"); return -ENODEV; } - iommu = find_iommu_from_bdf_cap(ivhd_block->header.dev_id, - ivhd_block->cap_offset); + iommu = find_iommu_from_bdf_cap(ivhd_block->header.device_id, + ivhd_block->capability_offset); if ( !iommu ) { AMD_IOMMU_DEBUG("IVHD Error: No IOMMU for Dev_Id 0x%x Cap 0x%x\n", - ivhd_block->header.dev_id, ivhd_block->cap_offset); + ivhd_block->header.device_id, + ivhd_block->capability_offset); return -ENODEV; } /* parse Device Entries */ - block_length = sizeof(struct acpi_ivhd_block_header); + block_length = sizeof(*ivhd_block); while ( ivhd_block->header.length >= - (block_length + sizeof(struct acpi_ivhd_device_header)) ) + (block_length + sizeof(struct acpi_ivrs_de_header)) ) { - ivhd_device = (union acpi_ivhd_device *) - ((u8 *)ivhd_block + block_length); + ivhd_device = (const void *)((const u8 *)ivhd_block + block_length); AMD_IOMMU_DEBUG( "IVHD Device Entry:\n"); AMD_IOMMU_DEBUG( " Type 0x%x\n", ivhd_device->header.type); - AMD_IOMMU_DEBUG( " Dev_Id 0x%x\n", ivhd_device->header.dev_id); - AMD_IOMMU_DEBUG( " Flags 0x%x\n", ivhd_device->header.flags); + AMD_IOMMU_DEBUG( " Dev_Id 0x%x\n", ivhd_device->header.id); + AMD_IOMMU_DEBUG( " Flags 0x%x\n", ivhd_device->header.data_setting); switch ( ivhd_device->header.type ) { - case AMD_IOMMU_ACPI_IVHD_DEV_U32_PAD: + case ACPI_IVRS_TYPE_PAD4: dev_length = parse_ivhd_device_padding( sizeof(u32), ivhd_block->header.length, block_length); break; - case AMD_IOMMU_ACPI_IVHD_DEV_U64_PAD: + case ACPI_IVRS_TYPE_PAD8: dev_length = parse_ivhd_device_padding( sizeof(u64), ivhd_block->header.length, block_length); break; - case AMD_IOMMU_ACPI_IVHD_DEV_SELECT: - dev_length = parse_ivhd_device_select(ivhd_device, iommu); + case ACPI_IVRS_TYPE_SELECT: + dev_length = parse_ivhd_device_select(&ivhd_device->select, iommu); break; - case AMD_IOMMU_ACPI_IVHD_DEV_RANGE_START: + case ACPI_IVRS_TYPE_START: dev_length = parse_ivhd_device_range( - ivhd_device, + &ivhd_device->range, ivhd_block->header.length, block_length, iommu); break; - case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_SELECT: + case ACPI_IVRS_TYPE_ALIAS_SELECT: dev_length = parse_ivhd_device_alias( - ivhd_device, + &ivhd_device->alias, ivhd_block->header.length, block_length, iommu); break; - case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_RANGE: + case ACPI_IVRS_TYPE_ALIAS_START: dev_length = parse_ivhd_device_alias_range( - ivhd_device, + &ivhd_device->alias_range, ivhd_block->header.length, block_length, iommu); break; - case AMD_IOMMU_ACPI_IVHD_DEV_EXT_SELECT: + case ACPI_IVRS_TYPE_EXT_SELECT: dev_length = parse_ivhd_device_extended( - ivhd_device, + &ivhd_device->extended, ivhd_block->header.length, block_length, iommu); break; - case AMD_IOMMU_ACPI_IVHD_DEV_EXT_RANGE: + case ACPI_IVRS_TYPE_EXT_START: dev_length = parse_ivhd_device_extended_range( - ivhd_device, + &ivhd_device->extended_range, ivhd_block->header.length, block_length, iommu); break; - case AMD_IOMMU_ACPI_IVHD_DEV_SPECIAL: + case ACPI_IVRS_TYPE_SPECIAL: dev_length = parse_ivhd_device_special( - ivhd_device, ivhd_block->pci_segment, + &ivhd_device->special, ivhd_block->pci_segment_group, ivhd_block->header.length, block_length, iommu); break; default: @@ -730,22 +750,24 @@ static int __init parse_ivhd_block(struc return 0; } -static int __init parse_ivrs_block(struct acpi_ivrs_block_header *ivrs_block) +static int __init parse_ivrs_block(const struct acpi_ivrs_header *ivrs_block) { - struct acpi_ivhd_block_header *ivhd_block; - struct acpi_ivmd_block_header *ivmd_block; + const struct acpi_ivrs_hardware *ivhd_block; + const struct acpi_ivrs_memory *ivmd_block; switch ( ivrs_block->type ) { - case AMD_IOMMU_ACPI_IVHD_TYPE: - ivhd_block = (struct acpi_ivhd_block_header *)ivrs_block; + case ACPI_IVRS_TYPE_HARDWARE: + ivhd_block = container_of(ivrs_block, const struct acpi_ivrs_hardware, + header); return parse_ivhd_block(ivhd_block); - case AMD_IOMMU_ACPI_IVMD_ALL_TYPE: - case AMD_IOMMU_ACPI_IVMD_ONE_TYPE: - case AMD_IOMMU_ACPI_IVMD_RANGE_TYPE: - case AMD_IOMMU_ACPI_IVMD_IOMMU_TYPE: - ivmd_block = (struct acpi_ivmd_block_header *)ivrs_block; + case ACPI_IVRS_TYPE_MEMORY_ALL: + case ACPI_IVRS_TYPE_MEMORY_ONE: + case ACPI_IVRS_TYPE_MEMORY_RANGE: + case ACPI_IVRS_TYPE_MEMORY_IOMMU: + ivmd_block = container_of(ivrs_block, const struct acpi_ivrs_memory, + header); return parse_ivmd_block(ivmd_block); default: @@ -792,12 +814,11 @@ static void __init dump_acpi_table_heade } -static int __init parse_ivrs_table(struct acpi_table_header *_table) +static int __init parse_ivrs_table(struct acpi_table_header *table) { - struct acpi_ivrs_block_header *ivrs_block; + const struct acpi_ivrs_header *ivrs_block; unsigned long length; int error = 0; - struct acpi_table_header *table = (struct acpi_table_header *)_table; BUG_ON(!table); @@ -805,17 +826,16 @@ static int __init parse_ivrs_table(struc dump_acpi_table_header(table); /* parse IVRS blocks */ - length = sizeof(struct acpi_ivrs_table_header); + length = sizeof(struct acpi_table_ivrs); while ( (error == 0) && (table->length > (length + sizeof(*ivrs_block))) ) { - ivrs_block = (struct acpi_ivrs_block_header *) - ((u8 *)table + length); + ivrs_block = (struct acpi_ivrs_header *)((u8 *)table + length); AMD_IOMMU_DEBUG("IVRS Block:\n"); AMD_IOMMU_DEBUG(" Type 0x%x\n", ivrs_block->type); AMD_IOMMU_DEBUG(" Flags 0x%x\n", ivrs_block->flags); AMD_IOMMU_DEBUG(" Length 0x%x\n", ivrs_block->length); - AMD_IOMMU_DEBUG(" Dev_Id 0x%x\n", ivrs_block->dev_id); + AMD_IOMMU_DEBUG(" Dev_Id 0x%x\n", ivrs_block->device_id); if ( table->length < (length + ivrs_block->length) ) { @@ -833,12 +853,11 @@ static int __init parse_ivrs_table(struc return error; } -static int __init detect_iommu_acpi(struct acpi_table_header *_table) +static int __init detect_iommu_acpi(struct acpi_table_header *table) { - struct acpi_ivrs_block_header *ivrs_block; - struct acpi_table_header *table = (struct acpi_table_header *)_table; + const struct acpi_ivrs_header *ivrs_block; unsigned long i; - unsigned long length = sizeof(struct acpi_ivrs_table_header); + unsigned long length = sizeof(struct acpi_table_ivrs); u8 checksum, *raw_table; /* validate checksum: sum of entire table == 0 */ @@ -854,12 +873,14 @@ static int __init detect_iommu_acpi(stru while ( table->length > (length + sizeof(*ivrs_block)) ) { - ivrs_block = (struct acpi_ivrs_block_header *) ((u8 *)table + length); + ivrs_block = (struct acpi_ivrs_header *)((u8 *)table + length); if ( table->length < (length + ivrs_block->length) ) return -ENODEV; - if ( ivrs_block->type == AMD_IOMMU_ACPI_IVHD_TYPE ) - if ( amd_iommu_detect_one_acpi((void*)ivrs_block) != 0 ) - return -ENODEV; + if ( ivrs_block->type == ACPI_IVRS_TYPE_HARDWARE && + amd_iommu_detect_one_acpi( + container_of(ivrs_block, const struct acpi_ivrs_hardware, + header)) != 0 ) + return -ENODEV; length += ivrs_block->length; } return 0; @@ -870,63 +891,59 @@ static int __init detect_iommu_acpi(stru last_bdf = (x); \ } while(0); -static int __init get_last_bdf_ivhd(void *ivhd) +static int __init get_last_bdf_ivhd( + const struct acpi_ivrs_hardware *ivhd_block) { - union acpi_ivhd_device *ivhd_device; + const union acpi_ivhd_device *ivhd_device; u16 block_length, dev_length; - struct acpi_ivhd_block_header *ivhd_block; - - ivhd_block = (struct acpi_ivhd_block_header *)ivhd; - if ( ivhd_block->header.length < - sizeof(struct acpi_ivhd_block_header) ) + if ( ivhd_block->header.length < sizeof(*ivhd_block) ) { AMD_IOMMU_DEBUG("IVHD Error: Invalid Block Length!\n"); return -ENODEV; } - block_length = sizeof(struct acpi_ivhd_block_header); + block_length = sizeof(*ivhd_block); while ( ivhd_block->header.length >= - (block_length + sizeof(struct acpi_ivhd_device_header)) ) + (block_length + sizeof(struct acpi_ivrs_de_header)) ) { - ivhd_device = (union acpi_ivhd_device *) - ((u8 *)ivhd_block + block_length); + ivhd_device = (const void *)((u8 *)ivhd_block + block_length); switch ( ivhd_device->header.type ) { - case AMD_IOMMU_ACPI_IVHD_DEV_U32_PAD: + case ACPI_IVRS_TYPE_PAD4: dev_length = sizeof(u32); break; - case AMD_IOMMU_ACPI_IVHD_DEV_U64_PAD: + case ACPI_IVRS_TYPE_PAD8: dev_length = sizeof(u64); break; - case AMD_IOMMU_ACPI_IVHD_DEV_SELECT: - UPDATE_LAST_BDF(ivhd_device->header.dev_id); - dev_length = sizeof(struct acpi_ivhd_device_header); - break; - case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_SELECT: - UPDATE_LAST_BDF(ivhd_device->header.dev_id); - dev_length = sizeof(struct acpi_ivhd_device_alias); - break; - case AMD_IOMMU_ACPI_IVHD_DEV_EXT_SELECT: - UPDATE_LAST_BDF(ivhd_device->header.dev_id); - dev_length = sizeof(struct acpi_ivhd_device_extended); - break; - case AMD_IOMMU_ACPI_IVHD_DEV_RANGE_START: - UPDATE_LAST_BDF(ivhd_device->range.trailer.dev_id); - dev_length = sizeof(struct acpi_ivhd_device_range); - break; - case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_RANGE: - UPDATE_LAST_BDF(ivhd_device->alias_range.trailer.dev_id) - dev_length = sizeof(struct acpi_ivhd_device_alias_range); - break; - case AMD_IOMMU_ACPI_IVHD_DEV_EXT_RANGE: - UPDATE_LAST_BDF(ivhd_device->extended_range.trailer.dev_id) - dev_length = sizeof(struct acpi_ivhd_device_extended_range); - break; - case AMD_IOMMU_ACPI_IVHD_DEV_SPECIAL: - UPDATE_LAST_BDF(ivhd_device->special.dev_id) - dev_length = sizeof(struct acpi_ivhd_device_special); + case ACPI_IVRS_TYPE_SELECT: + UPDATE_LAST_BDF(ivhd_device->select.header.id); + dev_length = sizeof(ivhd_device->header); + break; + case ACPI_IVRS_TYPE_ALIAS_SELECT: + UPDATE_LAST_BDF(ivhd_device->alias.header.id); + dev_length = sizeof(ivhd_device->alias); + break; + case ACPI_IVRS_TYPE_EXT_SELECT: + UPDATE_LAST_BDF(ivhd_device->extended.header.id); + dev_length = sizeof(ivhd_device->extended); + break; + case ACPI_IVRS_TYPE_START: + UPDATE_LAST_BDF(ivhd_device->range.end.header.id); + dev_length = sizeof(ivhd_device->range); + break; + case ACPI_IVRS_TYPE_ALIAS_START: + UPDATE_LAST_BDF(ivhd_device->alias_range.end.header.id) + dev_length = sizeof(ivhd_device->alias_range); + break; + case ACPI_IVRS_TYPE_EXT_START: + UPDATE_LAST_BDF(ivhd_device->extended_range.end.header.id) + dev_length = sizeof(ivhd_device->extended_range); + break; + case ACPI_IVRS_TYPE_SPECIAL: + UPDATE_LAST_BDF(ivhd_device->special.used_id) + dev_length = sizeof(ivhd_device->special); break; default: AMD_IOMMU_DEBUG("IVHD Error: Invalid Device Type!\n"); @@ -942,20 +959,21 @@ static int __init get_last_bdf_ivhd(void return 0; } -static int __init get_last_bdf_acpi(struct acpi_table_header *_table) +static int __init get_last_bdf_acpi(struct acpi_table_header *table) { - struct acpi_ivrs_block_header *ivrs_block; - struct acpi_table_header *table = (struct acpi_table_header *)_table; - unsigned long length = sizeof(struct acpi_ivrs_table_header); + const struct acpi_ivrs_header *ivrs_block; + unsigned long length = sizeof(struct acpi_table_ivrs); while ( table->length > (length + sizeof(*ivrs_block)) ) { - ivrs_block = (struct acpi_ivrs_block_header *) ((u8 *)table + length); + ivrs_block = (struct acpi_ivrs_header *)((u8 *)table + length); if ( table->length < (length + ivrs_block->length) ) return -ENODEV; - if ( ivrs_block->type == AMD_IOMMU_ACPI_IVHD_TYPE ) - if ( get_last_bdf_ivhd((void*)ivrs_block) != 0 ) - return -ENODEV; + if ( ivrs_block->type == ACPI_IVRS_TYPE_HARDWARE && + get_last_bdf_ivhd( + container_of(ivrs_block, const struct acpi_ivrs_hardware, + header)) != 0 ) + return -ENODEV; length += ivrs_block->length; } return 0; @@ -963,16 +981,16 @@ static int __init get_last_bdf_acpi(stru int __init amd_iommu_detect_acpi(void) { - return acpi_table_parse(AMD_IOMMU_ACPI_IVRS_SIG, detect_iommu_acpi); + return acpi_table_parse(ACPI_SIG_IVRS, detect_iommu_acpi); } int __init amd_iommu_get_ivrs_dev_entries(void) { - acpi_table_parse(AMD_IOMMU_ACPI_IVRS_SIG, get_last_bdf_acpi); + acpi_table_parse(ACPI_SIG_IVRS, get_last_bdf_acpi); return last_bdf + 1; } int __init amd_iommu_update_ivrs_mapping_acpi(void) { - return acpi_table_parse(AMD_IOMMU_ACPI_IVRS_SIG, parse_ivrs_table); + return acpi_table_parse(ACPI_SIG_IVRS, parse_ivrs_table); } --- a/xen/drivers/passthrough/amd/iommu_detect.c +++ b/xen/drivers/passthrough/amd/iommu_detect.c @@ -20,12 +20,12 @@ #include #include +#include #include #include #include #include #include -#include static int __init get_iommu_msi_capabilities( u16 seg, u8 bus, u8 dev, u8 func, struct amd_iommu *iommu) @@ -103,23 +103,21 @@ void __init get_iommu_features(struct am } } -int __init amd_iommu_detect_one_acpi(void *ivhd) +int __init amd_iommu_detect_one_acpi( + const struct acpi_ivrs_hardware *ivhd_block) { struct amd_iommu *iommu; u8 bus, dev, func; - struct acpi_ivhd_block_header *ivhd_block; int rt = 0; - ivhd_block = (struct acpi_ivhd_block_header *)ivhd; - - if ( ivhd_block->header.length < sizeof(struct acpi_ivhd_block_header) ) + if ( ivhd_block->header.length < sizeof(*ivhd_block) ) { AMD_IOMMU_DEBUG("Invalid IVHD Block Length!\n"); return -ENODEV; } - if ( !ivhd_block->header.dev_id || - !ivhd_block->cap_offset || !ivhd_block->mmio_base) + if ( !ivhd_block->header.device_id || + !ivhd_block->capability_offset || !ivhd_block->base_address) { AMD_IOMMU_DEBUG("Invalid IVHD Block!\n"); return -ENODEV; @@ -134,10 +132,10 @@ int __init amd_iommu_detect_one_acpi(voi spin_lock_init(&iommu->lock); - iommu->seg = ivhd_block->pci_segment; - iommu->bdf = ivhd_block->header.dev_id; - iommu->cap_offset = ivhd_block->cap_offset; - iommu->mmio_base_phys = ivhd_block->mmio_base; + iommu->seg = ivhd_block->pci_segment_group; + iommu->bdf = ivhd_block->header.device_id; + iommu->cap_offset = ivhd_block->capability_offset; + iommu->mmio_base_phys = ivhd_block->base_address; /* override IOMMU HT flags */ iommu->ht_flags = ivhd_block->header.flags; --- a/xen/drivers/passthrough/amd/iommu_init.c +++ b/xen/drivers/passthrough/amd/iommu_init.c @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -28,7 +29,6 @@ #include #include #include -#include static int __initdata nr_amd_iommus; @@ -37,9 +37,8 @@ static struct radix_tree_root ivrs_maps; struct list_head amd_iommu_head; struct table_struct device_table; -static int iommu_has_ht_flag(struct amd_iommu *iommu, uint8_t bit) +static int iommu_has_ht_flag(struct amd_iommu *iommu, u8 mask) { - u8 mask = 1U << bit; return iommu->ht_flags & mask; } @@ -80,19 +79,19 @@ static void set_iommu_ht_flags(struct am /* Setup HT flags */ if ( iommu_has_cap(iommu, PCI_CAP_HT_TUNNEL_SHIFT) ) - iommu_has_ht_flag(iommu, AMD_IOMMU_ACPI_HT_TUN_ENB_SHIFT) ? + iommu_has_ht_flag(iommu, ACPI_IVHD_TT_ENABLE) ? iommu_set_bit(&entry, IOMMU_CONTROL_HT_TUNNEL_TRANSLATION_SHIFT) : iommu_clear_bit(&entry, IOMMU_CONTROL_HT_TUNNEL_TRANSLATION_SHIFT); - iommu_has_ht_flag(iommu, AMD_IOMMU_ACPI_RES_PASS_PW_SHIFT) ? + iommu_has_ht_flag(iommu, ACPI_IVHD_RES_PASS_PW) ? iommu_set_bit(&entry, IOMMU_CONTROL_RESP_PASS_POSTED_WRITE_SHIFT): iommu_clear_bit(&entry, IOMMU_CONTROL_RESP_PASS_POSTED_WRITE_SHIFT); - iommu_has_ht_flag(iommu, AMD_IOMMU_ACPI_ISOC_SHIFT) ? + iommu_has_ht_flag(iommu, ACPI_IVHD_ISOC) ? iommu_set_bit(&entry, IOMMU_CONTROL_ISOCHRONOUS_SHIFT): iommu_clear_bit(&entry, IOMMU_CONTROL_ISOCHRONOUS_SHIFT); - iommu_has_ht_flag(iommu, AMD_IOMMU_ACPI_PASS_PW_SHIFT) ? + iommu_has_ht_flag(iommu, ACPI_IVHD_PASS_PW) ? iommu_set_bit(&entry, IOMMU_CONTROL_PASS_POSTED_WRITE_SHIFT): iommu_clear_bit(&entry, IOMMU_CONTROL_PASS_POSTED_WRITE_SHIFT); --- a/xen/drivers/passthrough/amd/iommu_map.c +++ b/xen/drivers/passthrough/amd/iommu_map.c @@ -18,12 +18,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include +#include #include #include #include #include #include -#include #include "../ats.h" #include @@ -215,8 +216,7 @@ void __init iommu_dte_add_device_entry(u dte[7] = dte[6] = dte[4] = dte[2] = dte[1] = dte[0] = 0; flags = ivrs_dev->device_flags; - sys_mgt = get_field_from_byte(flags, AMD_IOMMU_ACPI_SYS_MGT_MASK, - AMD_IOMMU_ACPI_SYS_MGT_SHIFT); + sys_mgt = get_field_from_byte(flags, ACPI_IVHD_SYSTEM_MGMT); dev_ex = ivrs_dev->dte_allow_exclusion; flags &= mask; --- a/xen/include/asm-x86/hvm/svm/amd-iommu-acpi.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2007 Advanced Micro Devices, Inc. - * Author: Leo Duran - * Author: Wei Wang - adapted to xen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _ASM_X86_64_AMD_IOMMU_ACPI_H -#define _ASM_X86_64_AMD_IOMMU_ACPI_H - -#include - -/* I/O Virtualization Reporting Structure */ -#define AMD_IOMMU_ACPI_IVRS_SIG "IVRS" -#define AMD_IOMMU_ACPI_IVHD_TYPE 0x10 -#define AMD_IOMMU_ACPI_IVMD_ALL_TYPE 0x20 -#define AMD_IOMMU_ACPI_IVMD_ONE_TYPE 0x21 -#define AMD_IOMMU_ACPI_IVMD_RANGE_TYPE 0x22 -#define AMD_IOMMU_ACPI_IVMD_IOMMU_TYPE 0x23 - -/* 4-byte Device Entries */ -#define AMD_IOMMU_ACPI_IVHD_DEV_U32_PAD 0 -#define AMD_IOMMU_ACPI_IVHD_DEV_SELECT 2 -#define AMD_IOMMU_ACPI_IVHD_DEV_RANGE_START 3 -#define AMD_IOMMU_ACPI_IVHD_DEV_RANGE_END 4 - -/* 8-byte Device Entries */ -#define AMD_IOMMU_ACPI_IVHD_DEV_U64_PAD 64 -#define AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_SELECT 66 -#define AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_RANGE 67 -#define AMD_IOMMU_ACPI_IVHD_DEV_EXT_SELECT 70 -#define AMD_IOMMU_ACPI_IVHD_DEV_EXT_RANGE 71 -#define AMD_IOMMU_ACPI_IVHD_DEV_SPECIAL 72 - -/* IVHD IOMMU Flags */ -#define AMD_IOMMU_ACPI_COHERENT_MASK 0x20 -#define AMD_IOMMU_ACPI_COHERENT_SHIFT 5 -#define AMD_IOMMU_ACPI_IOTLB_SUP_MASK 0x10 -#define AMD_IOMMU_ACPI_IOTLB_SUP_SHIFT 4 -#define AMD_IOMMU_ACPI_ISOC_MASK 0x08 -#define AMD_IOMMU_ACPI_ISOC_SHIFT 3 -#define AMD_IOMMU_ACPI_RES_PASS_PW_MASK 0x04 -#define AMD_IOMMU_ACPI_RES_PASS_PW_SHIFT 2 -#define AMD_IOMMU_ACPI_PASS_PW_MASK 0x02 -#define AMD_IOMMU_ACPI_PASS_PW_SHIFT 1 -#define AMD_IOMMU_ACPI_HT_TUN_ENB_MASK 0x01 -#define AMD_IOMMU_ACPI_HT_TUN_ENB_SHIFT 0 - -/* IVHD Device Flags */ -#define AMD_IOMMU_ACPI_LINT1_PASS_MASK 0x80 -#define AMD_IOMMU_ACPI_LINT1_PASS_SHIFT 7 -#define AMD_IOMMU_ACPI_LINT0_PASS_MASK 0x40 -#define AMD_IOMMU_ACPI_LINT0_PASS_SHIFT 6 -#define AMD_IOMMU_ACPI_SYS_MGT_MASK 0x30 -#define AMD_IOMMU_ACPI_SYS_MGT_SHIFT 4 -#define AMD_IOMMU_ACPI_NMI_PASS_MASK 0x04 -#define AMD_IOMMU_ACPI_NMI_PASS_SHIFT 2 -#define AMD_IOMMU_ACPI_EINT_PASS_MASK 0x02 -#define AMD_IOMMU_ACPI_EINT_PASS_SHIFT 1 -#define AMD_IOMMU_ACPI_INIT_PASS_MASK 0x01 -#define AMD_IOMMU_ACPI_INIT_PASS_SHIFT 0 - -/* IVHD Device Extended Flags */ -#define AMD_IOMMU_ACPI_ATS_DISABLED_MASK 0x80000000 -#define AMD_IOMMU_ACPI_ATS_DISABLED_SHIFT 31 - -/* IVMD Device Flags */ -#define AMD_IOMMU_ACPI_EXCLUSION_RANGE_MASK 0x08 -#define AMD_IOMMU_ACPI_EXCLUSION_RANGE_SHIFT 3 -#define AMD_IOMMU_ACPI_IW_PERMISSION_MASK 0x04 -#define AMD_IOMMU_ACPI_IW_PERMISSION_SHIFT 2 -#define AMD_IOMMU_ACPI_IR_PERMISSION_MASK 0x02 -#define AMD_IOMMU_ACPI_IR_PERMISSION_SHIFT 1 -#define AMD_IOMMU_ACPI_UNITY_MAPPING_MASK 0x01 -#define AMD_IOMMU_ACPI_UNITY_MAPPING_SHIFT 0 - -#define ACPI_OEM_ID_SIZE 6 -#define ACPI_OEM_TABLE_ID_SIZE 8 - -#pragma pack(1) -struct acpi_ivrs_table_header { - struct acpi_table_header acpi_header; - u32 io_info; - u8 reserved[8]; -}; - -struct acpi_ivrs_block_header { - u8 type; - u8 flags; - u16 length; - u16 dev_id; -}; - -struct acpi_ivhd_block_header { - struct acpi_ivrs_block_header header; - u16 cap_offset; - u64 mmio_base; - u16 pci_segment; - u16 iommu_info; - u8 reserved[4]; -}; - -struct acpi_ivhd_device_header { - u8 type; - u16 dev_id; - u8 flags; -}; - -struct acpi_ivhd_device_trailer { - u8 type; - u16 dev_id; - u8 reserved; -}; - -struct acpi_ivhd_device_range { - struct acpi_ivhd_device_header header; - struct acpi_ivhd_device_trailer trailer; -}; - -struct acpi_ivhd_device_alias { - struct acpi_ivhd_device_header header; - u8 reserved1; - u16 dev_id; - u8 reserved2; -}; - -struct acpi_ivhd_device_alias_range { - struct acpi_ivhd_device_alias alias; - struct acpi_ivhd_device_trailer trailer; -}; - -struct acpi_ivhd_device_extended { - struct acpi_ivhd_device_header header; - u32 ext_flags; -}; - -struct acpi_ivhd_device_extended_range { - struct acpi_ivhd_device_extended extended; - struct acpi_ivhd_device_trailer trailer; -}; - -struct acpi_ivhd_device_special { - struct acpi_ivhd_device_header header; - u8 handle; - u16 dev_id; - u8 variety; -}; - -union acpi_ivhd_device { - struct acpi_ivhd_device_header header; - struct acpi_ivhd_device_range range; - struct acpi_ivhd_device_alias alias; - struct acpi_ivhd_device_alias_range alias_range; - struct acpi_ivhd_device_extended extended; - struct acpi_ivhd_device_extended_range extended_range; - struct acpi_ivhd_device_special special; -}; - -struct acpi_ivmd_block_header { - struct acpi_ivrs_block_header header; - union { - u16 last_dev_id; - u16 cap_offset; - u16 reserved1; - }; - u64 reserved2; - u64 start_addr; - u64 mem_length; -}; -#pragma pack() - -#endif /* _ASM_X86_64_AMD_IOMMU_ACPI_H */ --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h @@ -26,6 +26,8 @@ #include #include +struct acpi_ivrs_hardware; + #define for_each_amd_iommu(amd_iommu) \ list_for_each_entry(amd_iommu, \ &amd_iommu_head, list) @@ -41,7 +43,7 @@ /* amd-iommu-detect functions */ int amd_iommu_get_ivrs_dev_entries(void); -int amd_iommu_detect_one_acpi(void *ivhd); +int amd_iommu_detect_one_acpi(const struct acpi_ivrs_hardware *); int amd_iommu_detect_acpi(void); void get_iommu_features(struct amd_iommu *iommu); @@ -121,11 +123,9 @@ static inline u32 set_field_in_reg_u32(u return reg_value; } -static inline u8 get_field_from_byte(u8 value, u8 mask, u8 shift) +static inline u8 get_field_from_byte(u8 value, u8 mask) { - u8 field; - field = (value & mask) >> shift; - return field; + return (value & mask) / (mask & -mask); } static inline unsigned long region_to_pages(unsigned long addr, unsigned long size)