mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
ACPI: eliminate duplicate IVRS definitions
Use their proper counterparts in include/acpi/actbl*.h instead. Signed-off-by: Jan Beulich <jbeulich@suse.com> Acked-by: Keir Fraser <keir@xen.org>
This commit is contained in:
1 parent
fee3eddfae
commit
e941abd7ca
6 files changed
+214
-384
No files matched your search
@@ -20,10 +20,38 @@
|
|||||||
|
|
||||||
#include <xen/config.h>
|
#include <xen/config.h>
|
||||||
#include <xen/errno.h>
|
#include <xen/errno.h>
|
||||||
|
#include <xen/acpi.h>
|
||||||
#include <asm/apicdef.h>
|
#include <asm/apicdef.h>
|
||||||
#include <asm/amd-iommu.h>
|
#include <asm/amd-iommu.h>
|
||||||
#include <asm/hvm/svm/amd-iommu-proto.h>
|
#include <asm/hvm/svm/amd-iommu-proto.h>
|
||||||
#include <asm/hvm/svm/amd-iommu-acpi.h>
|
|
||||||
|
/* 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;
|
static unsigned short __initdata last_bdf;
|
||||||
|
|
||||||
@@ -242,12 +270,12 @@ static int __init register_exclusion_range_for_iommu_devices(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int __init parse_ivmd_device_select(
|
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)
|
unsigned long base, unsigned long limit, u8 iw, u8 ir)
|
||||||
{
|
{
|
||||||
u16 bdf;
|
u16 bdf;
|
||||||
|
|
||||||
bdf = ivmd_block->header.dev_id;
|
bdf = ivmd_block->header.device_id;
|
||||||
if ( bdf >= ivrs_bdf_entries )
|
if ( bdf >= ivrs_bdf_entries )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVMD Error: Invalid Dev_Id 0x%x\n", bdf);
|
AMD_IOMMU_DEBUG("IVMD Error: Invalid Dev_Id 0x%x\n", bdf);
|
||||||
@@ -258,13 +286,13 @@ static int __init parse_ivmd_device_select(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int __init parse_ivmd_device_range(
|
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)
|
unsigned long base, unsigned long limit, u8 iw, u8 ir)
|
||||||
{
|
{
|
||||||
u16 first_bdf, last_bdf, bdf;
|
u16 first_bdf, last_bdf, bdf;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
first_bdf = ivmd_block->header.dev_id;
|
first_bdf = ivmd_block->header.device_id;
|
||||||
if ( first_bdf >= ivrs_bdf_entries )
|
if ( first_bdf >= ivrs_bdf_entries )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVMD Error: "
|
AMD_IOMMU_DEBUG("IVMD Error: "
|
||||||
@@ -272,7 +300,7 @@ static int __init parse_ivmd_device_range(
|
|||||||
return -ENODEV;
|
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) )
|
if ( (last_bdf >= ivrs_bdf_entries) || (last_bdf <= first_bdf) )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVMD Error: "
|
AMD_IOMMU_DEBUG("IVMD Error: "
|
||||||
@@ -288,18 +316,18 @@ static int __init parse_ivmd_device_range(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int __init parse_ivmd_device_iommu(
|
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)
|
unsigned long base, unsigned long limit, u8 iw, u8 ir)
|
||||||
{
|
{
|
||||||
struct amd_iommu *iommu;
|
struct amd_iommu *iommu;
|
||||||
|
|
||||||
/* find target IOMMU */
|
/* find target IOMMU */
|
||||||
iommu = find_iommu_from_bdf_cap(ivmd_block->header.dev_id,
|
iommu = find_iommu_from_bdf_cap(ivmd_block->header.device_id,
|
||||||
ivmd_block->cap_offset);
|
ivmd_block->aux_data);
|
||||||
if ( !iommu )
|
if ( !iommu )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVMD Error: No IOMMU for Dev_Id 0x%x Cap 0x%x\n",
|
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;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,20 +335,19 @@ static int __init parse_ivmd_device_iommu(
|
|||||||
iommu, base, limit, iw, ir);
|
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;
|
unsigned long start_addr, mem_length, base, limit;
|
||||||
u8 iw, ir;
|
u8 iw, ir;
|
||||||
|
|
||||||
if ( ivmd_block->header.length <
|
if ( ivmd_block->header.length < sizeof(*ivmd_block) )
|
||||||
sizeof(struct acpi_ivmd_block_header) )
|
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVMD Error: Invalid Block Length!\n");
|
AMD_IOMMU_DEBUG("IVMD Error: Invalid Block Length!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
start_addr = (unsigned long)ivmd_block->start_addr;
|
start_addr = (unsigned long)ivmd_block->start_address;
|
||||||
mem_length = (unsigned long)ivmd_block->mem_length;
|
mem_length = (unsigned long)ivmd_block->memory_length;
|
||||||
base = start_addr & PAGE_MASK;
|
base = start_addr & PAGE_MASK;
|
||||||
limit = (start_addr + mem_length - 1) & PAGE_MASK;
|
limit = (start_addr + mem_length - 1) & PAGE_MASK;
|
||||||
|
|
||||||
@@ -328,20 +355,14 @@ static int __init parse_ivmd_block(struct acpi_ivmd_block_header *ivmd_block)
|
|||||||
AMD_IOMMU_DEBUG(" Start_Addr_Phys 0x%lx\n", start_addr);
|
AMD_IOMMU_DEBUG(" Start_Addr_Phys 0x%lx\n", start_addr);
|
||||||
AMD_IOMMU_DEBUG(" Mem_Length 0x%lx\n", mem_length);
|
AMD_IOMMU_DEBUG(" Mem_Length 0x%lx\n", mem_length);
|
||||||
|
|
||||||
if ( get_field_from_byte(ivmd_block->header.flags,
|
if ( ivmd_block->header.flags & ACPI_IVMD_EXCLUSION_RANGE )
|
||||||
AMD_IOMMU_ACPI_EXCLUSION_RANGE_MASK,
|
|
||||||
AMD_IOMMU_ACPI_EXCLUSION_RANGE_SHIFT) )
|
|
||||||
iw = ir = IOMMU_CONTROL_ENABLED;
|
iw = ir = IOMMU_CONTROL_ENABLED;
|
||||||
else if ( get_field_from_byte(ivmd_block->header.flags,
|
else if ( ivmd_block->header.flags & ACPI_IVMD_UNITY )
|
||||||
AMD_IOMMU_ACPI_UNITY_MAPPING_MASK,
|
|
||||||
AMD_IOMMU_ACPI_UNITY_MAPPING_SHIFT) )
|
|
||||||
{
|
{
|
||||||
iw = get_field_from_byte(ivmd_block->header.flags,
|
iw = ivmd_block->header.flags & ACPI_IVMD_READ ?
|
||||||
AMD_IOMMU_ACPI_IW_PERMISSION_MASK,
|
IOMMU_CONTROL_ENABLED : IOMMU_CONTROL_DISABLED;
|
||||||
AMD_IOMMU_ACPI_IW_PERMISSION_SHIFT);
|
ir = ivmd_block->header.flags & ACPI_IVMD_WRITE ?
|
||||||
ir = get_field_from_byte(ivmd_block->header.flags,
|
IOMMU_CONTROL_ENABLED : IOMMU_CONTROL_DISABLED;
|
||||||
AMD_IOMMU_ACPI_IR_PERMISSION_MASK,
|
|
||||||
AMD_IOMMU_ACPI_IR_PERMISSION_SHIFT);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -351,19 +372,19 @@ static int __init parse_ivmd_block(struct acpi_ivmd_block_header *ivmd_block)
|
|||||||
|
|
||||||
switch( ivmd_block->header.type )
|
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(
|
return register_exclusion_range_for_all_devices(
|
||||||
base, limit, iw, ir);
|
base, limit, iw, ir);
|
||||||
|
|
||||||
case AMD_IOMMU_ACPI_IVMD_ONE_TYPE:
|
case ACPI_IVRS_TYPE_MEMORY_ONE:
|
||||||
return parse_ivmd_device_select(ivmd_block,
|
return parse_ivmd_device_select(ivmd_block,
|
||||||
base, limit, iw, ir);
|
base, limit, iw, ir);
|
||||||
|
|
||||||
case AMD_IOMMU_ACPI_IVMD_RANGE_TYPE:
|
case ACPI_IVRS_TYPE_MEMORY_RANGE:
|
||||||
return parse_ivmd_device_range(ivmd_block,
|
return parse_ivmd_device_range(ivmd_block,
|
||||||
base, limit, iw, ir);
|
base, limit, iw, ir);
|
||||||
|
|
||||||
case AMD_IOMMU_ACPI_IVMD_IOMMU_TYPE:
|
case ACPI_IVRS_TYPE_MEMORY_IOMMU:
|
||||||
return parse_ivmd_device_iommu(ivmd_block,
|
return parse_ivmd_device_iommu(ivmd_block,
|
||||||
base, limit, iw, ir);
|
base, limit, iw, ir);
|
||||||
|
|
||||||
@@ -386,45 +407,44 @@ static u16 __init parse_ivhd_device_padding(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static u16 __init parse_ivhd_device_select(
|
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;
|
u16 bdf;
|
||||||
|
|
||||||
bdf = ivhd_device->header.dev_id;
|
bdf = select->header.id;
|
||||||
if ( bdf >= ivrs_bdf_entries )
|
if ( bdf >= ivrs_bdf_entries )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf);
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf);
|
||||||
return 0;
|
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(
|
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 header_length, u16 block_length, struct amd_iommu *iommu)
|
||||||
{
|
{
|
||||||
u16 dev_length, first_bdf, last_bdf, bdf;
|
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) )
|
if ( header_length < (block_length + dev_length) )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ivhd_device->range.trailer.type !=
|
if ( range->end.header.type != ACPI_IVRS_TYPE_END )
|
||||||
AMD_IOMMU_ACPI_IVHD_DEV_RANGE_END )
|
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: "
|
AMD_IOMMU_DEBUG("IVHD Error: "
|
||||||
"Invalid Range: End_Type 0x%x\n",
|
"Invalid Range: End_Type 0x%x\n",
|
||||||
ivhd_device->range.trailer.type);
|
range->end.header.type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
first_bdf = ivhd_device->header.dev_id;
|
first_bdf = range->start.header.id;
|
||||||
if ( first_bdf >= ivrs_bdf_entries )
|
if ( first_bdf >= ivrs_bdf_entries )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: "
|
AMD_IOMMU_DEBUG("IVHD Error: "
|
||||||
@@ -432,7 +452,7 @@ static u16 __init parse_ivhd_device_range(
|
|||||||
return 0;
|
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) )
|
if ( (last_bdf >= ivrs_bdf_entries) || (last_bdf <= first_bdf) )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: "
|
AMD_IOMMU_DEBUG("IVHD Error: "
|
||||||
@@ -443,32 +463,33 @@ static u16 __init parse_ivhd_device_range(
|
|||||||
AMD_IOMMU_DEBUG(" Dev_Id Range: 0x%x -> 0x%x\n", first_bdf, last_bdf);
|
AMD_IOMMU_DEBUG(" Dev_Id Range: 0x%x -> 0x%x\n", first_bdf, last_bdf);
|
||||||
|
|
||||||
for ( bdf = first_bdf; bdf <= last_bdf; 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;
|
return dev_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 __init parse_ivhd_device_alias(
|
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 header_length, u16 block_length, struct amd_iommu *iommu)
|
||||||
{
|
{
|
||||||
u16 dev_length, alias_id, bdf;
|
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) )
|
if ( header_length < (block_length + dev_length) )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdf = ivhd_device->header.dev_id;
|
bdf = alias->header.id;
|
||||||
if ( bdf >= ivrs_bdf_entries )
|
if ( bdf >= ivrs_bdf_entries )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf);
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
alias_id = ivhd_device->alias.dev_id;
|
alias_id = alias->used_id;
|
||||||
if ( alias_id >= ivrs_bdf_entries )
|
if ( alias_id >= ivrs_bdf_entries )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Alias Dev_Id 0x%x\n", alias_id);
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Alias Dev_Id 0x%x\n", alias_id);
|
||||||
@@ -477,35 +498,34 @@ static u16 __init parse_ivhd_device_alias(
|
|||||||
|
|
||||||
AMD_IOMMU_DEBUG(" Dev_Id Alias: 0x%x\n", alias_id);
|
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;
|
return dev_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 __init parse_ivhd_device_alias_range(
|
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 header_length, u16 block_length, struct amd_iommu *iommu)
|
||||||
{
|
{
|
||||||
|
|
||||||
u16 dev_length, first_bdf, last_bdf, alias_id, bdf;
|
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) )
|
if ( header_length < (block_length + dev_length) )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ivhd_device->alias_range.trailer.type !=
|
if ( range->end.header.type != ACPI_IVRS_TYPE_END )
|
||||||
AMD_IOMMU_ACPI_IVHD_DEV_RANGE_END )
|
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: "
|
AMD_IOMMU_DEBUG("IVHD Error: "
|
||||||
"Invalid Range: End_Type 0x%x\n",
|
"Invalid Range: End_Type 0x%x\n",
|
||||||
ivhd_device->alias_range.trailer.type);
|
range->end.header.type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
first_bdf = ivhd_device->header.dev_id;
|
first_bdf = range->alias.header.id;
|
||||||
if ( first_bdf >= ivrs_bdf_entries )
|
if ( first_bdf >= ivrs_bdf_entries )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: "
|
AMD_IOMMU_DEBUG("IVHD Error: "
|
||||||
@@ -513,7 +533,7 @@ static u16 __init parse_ivhd_device_alias_range(
|
|||||||
return 0;
|
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 )
|
if ( last_bdf >= ivrs_bdf_entries || last_bdf <= first_bdf )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG(
|
AMD_IOMMU_DEBUG(
|
||||||
@@ -521,7 +541,7 @@ static u16 __init parse_ivhd_device_alias_range(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
alias_id = ivhd_device->alias_range.alias.dev_id;
|
alias_id = range->alias.used_id;
|
||||||
if ( alias_id >= ivrs_bdf_entries )
|
if ( alias_id >= ivrs_bdf_entries )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Alias Dev_Id 0x%x\n", alias_id);
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Alias Dev_Id 0x%x\n", alias_id);
|
||||||
@@ -532,59 +552,59 @@ static u16 __init parse_ivhd_device_alias_range(
|
|||||||
AMD_IOMMU_DEBUG(" Dev_Id Alias: 0x%x\n", alias_id);
|
AMD_IOMMU_DEBUG(" Dev_Id Alias: 0x%x\n", alias_id);
|
||||||
|
|
||||||
for ( bdf = first_bdf; bdf <= last_bdf; bdf++ )
|
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;
|
return dev_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 __init parse_ivhd_device_extended(
|
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 header_length, u16 block_length, struct amd_iommu *iommu)
|
||||||
{
|
{
|
||||||
u16 dev_length, bdf;
|
u16 dev_length, bdf;
|
||||||
|
|
||||||
dev_length = sizeof(struct acpi_ivhd_device_extended);
|
dev_length = sizeof(*ext);
|
||||||
if ( header_length < (block_length + dev_length) )
|
if ( header_length < (block_length + dev_length) )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdf = ivhd_device->header.dev_id;
|
bdf = ext->header.id;
|
||||||
if ( bdf >= ivrs_bdf_entries )
|
if ( bdf >= ivrs_bdf_entries )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf);
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf);
|
||||||
return 0;
|
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;
|
return dev_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 __init parse_ivhd_device_extended_range(
|
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 header_length, u16 block_length, struct amd_iommu *iommu)
|
||||||
{
|
{
|
||||||
u16 dev_length, first_bdf, last_bdf, bdf;
|
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) )
|
if ( header_length < (block_length + dev_length) )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ivhd_device->extended_range.trailer.type !=
|
if ( range->end.header.type != ACPI_IVRS_TYPE_END )
|
||||||
AMD_IOMMU_ACPI_IVHD_DEV_RANGE_END )
|
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: "
|
AMD_IOMMU_DEBUG("IVHD Error: "
|
||||||
"Invalid Range: End_Type 0x%x\n",
|
"Invalid Range: End_Type 0x%x\n",
|
||||||
ivhd_device->extended_range.trailer.type);
|
range->end.header.type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
first_bdf = ivhd_device->header.dev_id;
|
first_bdf = range->extended.header.id;
|
||||||
if ( first_bdf >= ivrs_bdf_entries )
|
if ( first_bdf >= ivrs_bdf_entries )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: "
|
AMD_IOMMU_DEBUG("IVHD Error: "
|
||||||
@@ -592,7 +612,7 @@ static u16 __init parse_ivhd_device_extended_range(
|
|||||||
return 0;
|
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) )
|
if ( (last_bdf >= ivrs_bdf_entries) || (last_bdf <= first_bdf) )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: "
|
AMD_IOMMU_DEBUG("IVHD Error: "
|
||||||
@@ -604,116 +624,116 @@ static u16 __init parse_ivhd_device_extended_range(
|
|||||||
first_bdf, last_bdf);
|
first_bdf, last_bdf);
|
||||||
|
|
||||||
for ( bdf = first_bdf; bdf <= last_bdf; 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;
|
return dev_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 __init parse_ivhd_device_special(
|
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 header_length, u16 block_length, struct amd_iommu *iommu)
|
||||||
{
|
{
|
||||||
u16 dev_length, bdf;
|
u16 dev_length, bdf;
|
||||||
|
|
||||||
dev_length = sizeof(struct acpi_ivhd_device_special);
|
dev_length = sizeof(*special);
|
||||||
if ( header_length < (block_length + dev_length) )
|
if ( header_length < (block_length + dev_length) )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Length!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bdf = ivhd_device->special.dev_id;
|
bdf = special->used_id;
|
||||||
if ( bdf >= ivrs_bdf_entries )
|
if ( bdf >= ivrs_bdf_entries )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf);
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device_Entry Dev_Id 0x%x\n", bdf);
|
||||||
return 0;
|
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 */
|
/* set device id of ioapic */
|
||||||
ioapic_sbdf[ivhd_device->special.handle].bdf = bdf;
|
ioapic_sbdf[special->handle].bdf = bdf;
|
||||||
ioapic_sbdf[ivhd_device->special.handle].seg = seg;
|
ioapic_sbdf[special->handle].seg = seg;
|
||||||
return dev_length;
|
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;
|
u16 block_length, dev_length;
|
||||||
struct amd_iommu *iommu;
|
struct amd_iommu *iommu;
|
||||||
|
|
||||||
if ( ivhd_block->header.length <
|
if ( ivhd_block->header.length < sizeof(*ivhd_block) )
|
||||||
sizeof(struct acpi_ivhd_block_header) )
|
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Block Length!\n");
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Block Length!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
iommu = find_iommu_from_bdf_cap(ivhd_block->header.dev_id,
|
iommu = find_iommu_from_bdf_cap(ivhd_block->header.device_id,
|
||||||
ivhd_block->cap_offset);
|
ivhd_block->capability_offset);
|
||||||
if ( !iommu )
|
if ( !iommu )
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: No IOMMU for Dev_Id 0x%x Cap 0x%x\n",
|
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;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse Device Entries */
|
/* parse Device Entries */
|
||||||
block_length = sizeof(struct acpi_ivhd_block_header);
|
block_length = sizeof(*ivhd_block);
|
||||||
while ( ivhd_block->header.length >=
|
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 *)
|
ivhd_device = (const void *)((const u8 *)ivhd_block + block_length);
|
||||||
((u8 *)ivhd_block + block_length);
|
|
||||||
|
|
||||||
AMD_IOMMU_DEBUG( "IVHD Device Entry:\n");
|
AMD_IOMMU_DEBUG( "IVHD Device Entry:\n");
|
||||||
AMD_IOMMU_DEBUG( " Type 0x%x\n", ivhd_device->header.type);
|
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( " Dev_Id 0x%x\n", ivhd_device->header.id);
|
||||||
AMD_IOMMU_DEBUG( " Flags 0x%x\n", ivhd_device->header.flags);
|
AMD_IOMMU_DEBUG( " Flags 0x%x\n", ivhd_device->header.data_setting);
|
||||||
|
|
||||||
switch ( ivhd_device->header.type )
|
switch ( ivhd_device->header.type )
|
||||||
{
|
{
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_U32_PAD:
|
case ACPI_IVRS_TYPE_PAD4:
|
||||||
dev_length = parse_ivhd_device_padding(
|
dev_length = parse_ivhd_device_padding(
|
||||||
sizeof(u32),
|
sizeof(u32),
|
||||||
ivhd_block->header.length, block_length);
|
ivhd_block->header.length, block_length);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_U64_PAD:
|
case ACPI_IVRS_TYPE_PAD8:
|
||||||
dev_length = parse_ivhd_device_padding(
|
dev_length = parse_ivhd_device_padding(
|
||||||
sizeof(u64),
|
sizeof(u64),
|
||||||
ivhd_block->header.length, block_length);
|
ivhd_block->header.length, block_length);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_SELECT:
|
case ACPI_IVRS_TYPE_SELECT:
|
||||||
dev_length = parse_ivhd_device_select(ivhd_device, iommu);
|
dev_length = parse_ivhd_device_select(&ivhd_device->select, iommu);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_RANGE_START:
|
case ACPI_IVRS_TYPE_START:
|
||||||
dev_length = parse_ivhd_device_range(
|
dev_length = parse_ivhd_device_range(
|
||||||
ivhd_device,
|
&ivhd_device->range,
|
||||||
ivhd_block->header.length, block_length, iommu);
|
ivhd_block->header.length, block_length, iommu);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_SELECT:
|
case ACPI_IVRS_TYPE_ALIAS_SELECT:
|
||||||
dev_length = parse_ivhd_device_alias(
|
dev_length = parse_ivhd_device_alias(
|
||||||
ivhd_device,
|
&ivhd_device->alias,
|
||||||
ivhd_block->header.length, block_length, iommu);
|
ivhd_block->header.length, block_length, iommu);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_RANGE:
|
case ACPI_IVRS_TYPE_ALIAS_START:
|
||||||
dev_length = parse_ivhd_device_alias_range(
|
dev_length = parse_ivhd_device_alias_range(
|
||||||
ivhd_device,
|
&ivhd_device->alias_range,
|
||||||
ivhd_block->header.length, block_length, iommu);
|
ivhd_block->header.length, block_length, iommu);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_EXT_SELECT:
|
case ACPI_IVRS_TYPE_EXT_SELECT:
|
||||||
dev_length = parse_ivhd_device_extended(
|
dev_length = parse_ivhd_device_extended(
|
||||||
ivhd_device,
|
&ivhd_device->extended,
|
||||||
ivhd_block->header.length, block_length, iommu);
|
ivhd_block->header.length, block_length, iommu);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_EXT_RANGE:
|
case ACPI_IVRS_TYPE_EXT_START:
|
||||||
dev_length = parse_ivhd_device_extended_range(
|
dev_length = parse_ivhd_device_extended_range(
|
||||||
ivhd_device,
|
&ivhd_device->extended_range,
|
||||||
ivhd_block->header.length, block_length, iommu);
|
ivhd_block->header.length, block_length, iommu);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_SPECIAL:
|
case ACPI_IVRS_TYPE_SPECIAL:
|
||||||
dev_length = parse_ivhd_device_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);
|
ivhd_block->header.length, block_length, iommu);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -730,22 +750,24 @@ static int __init parse_ivhd_block(struct acpi_ivhd_block_header *ivhd_block)
|
|||||||
return 0;
|
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;
|
const struct acpi_ivrs_hardware *ivhd_block;
|
||||||
struct acpi_ivmd_block_header *ivmd_block;
|
const struct acpi_ivrs_memory *ivmd_block;
|
||||||
|
|
||||||
switch ( ivrs_block->type )
|
switch ( ivrs_block->type )
|
||||||
{
|
{
|
||||||
case AMD_IOMMU_ACPI_IVHD_TYPE:
|
case ACPI_IVRS_TYPE_HARDWARE:
|
||||||
ivhd_block = (struct acpi_ivhd_block_header *)ivrs_block;
|
ivhd_block = container_of(ivrs_block, const struct acpi_ivrs_hardware,
|
||||||
|
header);
|
||||||
return parse_ivhd_block(ivhd_block);
|
return parse_ivhd_block(ivhd_block);
|
||||||
|
|
||||||
case AMD_IOMMU_ACPI_IVMD_ALL_TYPE:
|
case ACPI_IVRS_TYPE_MEMORY_ALL:
|
||||||
case AMD_IOMMU_ACPI_IVMD_ONE_TYPE:
|
case ACPI_IVRS_TYPE_MEMORY_ONE:
|
||||||
case AMD_IOMMU_ACPI_IVMD_RANGE_TYPE:
|
case ACPI_IVRS_TYPE_MEMORY_RANGE:
|
||||||
case AMD_IOMMU_ACPI_IVMD_IOMMU_TYPE:
|
case ACPI_IVRS_TYPE_MEMORY_IOMMU:
|
||||||
ivmd_block = (struct acpi_ivmd_block_header *)ivrs_block;
|
ivmd_block = container_of(ivrs_block, const struct acpi_ivrs_memory,
|
||||||
|
header);
|
||||||
return parse_ivmd_block(ivmd_block);
|
return parse_ivmd_block(ivmd_block);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -792,12 +814,11 @@ static void __init dump_acpi_table_header(struct acpi_table_header *table)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
unsigned long length;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
struct acpi_table_header *table = (struct acpi_table_header *)_table;
|
|
||||||
|
|
||||||
BUG_ON(!table);
|
BUG_ON(!table);
|
||||||
|
|
||||||
@@ -805,17 +826,16 @@ static int __init parse_ivrs_table(struct acpi_table_header *_table)
|
|||||||
dump_acpi_table_header(table);
|
dump_acpi_table_header(table);
|
||||||
|
|
||||||
/* parse IVRS blocks */
|
/* 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))) )
|
while ( (error == 0) && (table->length > (length + sizeof(*ivrs_block))) )
|
||||||
{
|
{
|
||||||
ivrs_block = (struct acpi_ivrs_block_header *)
|
ivrs_block = (struct acpi_ivrs_header *)((u8 *)table + length);
|
||||||
((u8 *)table + length);
|
|
||||||
|
|
||||||
AMD_IOMMU_DEBUG("IVRS Block:\n");
|
AMD_IOMMU_DEBUG("IVRS Block:\n");
|
||||||
AMD_IOMMU_DEBUG(" Type 0x%x\n", ivrs_block->type);
|
AMD_IOMMU_DEBUG(" Type 0x%x\n", ivrs_block->type);
|
||||||
AMD_IOMMU_DEBUG(" Flags 0x%x\n", ivrs_block->flags);
|
AMD_IOMMU_DEBUG(" Flags 0x%x\n", ivrs_block->flags);
|
||||||
AMD_IOMMU_DEBUG(" Length 0x%x\n", ivrs_block->length);
|
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) )
|
if ( table->length < (length + ivrs_block->length) )
|
||||||
{
|
{
|
||||||
@@ -833,12 +853,11 @@ static int __init parse_ivrs_table(struct acpi_table_header *_table)
|
|||||||
return error;
|
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;
|
const struct acpi_ivrs_header *ivrs_block;
|
||||||
struct acpi_table_header *table = (struct acpi_table_header *)_table;
|
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
unsigned long length = sizeof(struct acpi_ivrs_table_header);
|
unsigned long length = sizeof(struct acpi_table_ivrs);
|
||||||
u8 checksum, *raw_table;
|
u8 checksum, *raw_table;
|
||||||
|
|
||||||
/* validate checksum: sum of entire table == 0 */
|
/* validate checksum: sum of entire table == 0 */
|
||||||
@@ -854,11 +873,13 @@ static int __init detect_iommu_acpi(struct acpi_table_header *_table)
|
|||||||
|
|
||||||
while ( table->length > (length + sizeof(*ivrs_block)) )
|
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) )
|
if ( table->length < (length + ivrs_block->length) )
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
if ( ivrs_block->type == AMD_IOMMU_ACPI_IVHD_TYPE )
|
if ( ivrs_block->type == ACPI_IVRS_TYPE_HARDWARE &&
|
||||||
if ( amd_iommu_detect_one_acpi((void*)ivrs_block) != 0 )
|
amd_iommu_detect_one_acpi(
|
||||||
|
container_of(ivrs_block, const struct acpi_ivrs_hardware,
|
||||||
|
header)) != 0 )
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
length += ivrs_block->length;
|
length += ivrs_block->length;
|
||||||
}
|
}
|
||||||
@@ -870,63 +891,59 @@ static int __init detect_iommu_acpi(struct acpi_table_header *_table)
|
|||||||
last_bdf = (x); \
|
last_bdf = (x); \
|
||||||
} while(0);
|
} 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;
|
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(*ivhd_block) )
|
||||||
|
|
||||||
if ( ivhd_block->header.length <
|
|
||||||
sizeof(struct acpi_ivhd_block_header) )
|
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Block Length!\n");
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Block Length!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
block_length = sizeof(struct acpi_ivhd_block_header);
|
block_length = sizeof(*ivhd_block);
|
||||||
while ( ivhd_block->header.length >=
|
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 *)
|
ivhd_device = (const void *)((u8 *)ivhd_block + block_length);
|
||||||
((u8 *)ivhd_block + block_length);
|
|
||||||
|
|
||||||
switch ( ivhd_device->header.type )
|
switch ( ivhd_device->header.type )
|
||||||
{
|
{
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_U32_PAD:
|
case ACPI_IVRS_TYPE_PAD4:
|
||||||
dev_length = sizeof(u32);
|
dev_length = sizeof(u32);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_U64_PAD:
|
case ACPI_IVRS_TYPE_PAD8:
|
||||||
dev_length = sizeof(u64);
|
dev_length = sizeof(u64);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_SELECT:
|
case ACPI_IVRS_TYPE_SELECT:
|
||||||
UPDATE_LAST_BDF(ivhd_device->header.dev_id);
|
UPDATE_LAST_BDF(ivhd_device->select.header.id);
|
||||||
dev_length = sizeof(struct acpi_ivhd_device_header);
|
dev_length = sizeof(ivhd_device->header);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_SELECT:
|
case ACPI_IVRS_TYPE_ALIAS_SELECT:
|
||||||
UPDATE_LAST_BDF(ivhd_device->header.dev_id);
|
UPDATE_LAST_BDF(ivhd_device->alias.header.id);
|
||||||
dev_length = sizeof(struct acpi_ivhd_device_alias);
|
dev_length = sizeof(ivhd_device->alias);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_EXT_SELECT:
|
case ACPI_IVRS_TYPE_EXT_SELECT:
|
||||||
UPDATE_LAST_BDF(ivhd_device->header.dev_id);
|
UPDATE_LAST_BDF(ivhd_device->extended.header.id);
|
||||||
dev_length = sizeof(struct acpi_ivhd_device_extended);
|
dev_length = sizeof(ivhd_device->extended);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_RANGE_START:
|
case ACPI_IVRS_TYPE_START:
|
||||||
UPDATE_LAST_BDF(ivhd_device->range.trailer.dev_id);
|
UPDATE_LAST_BDF(ivhd_device->range.end.header.id);
|
||||||
dev_length = sizeof(struct acpi_ivhd_device_range);
|
dev_length = sizeof(ivhd_device->range);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_ALIAS_RANGE:
|
case ACPI_IVRS_TYPE_ALIAS_START:
|
||||||
UPDATE_LAST_BDF(ivhd_device->alias_range.trailer.dev_id)
|
UPDATE_LAST_BDF(ivhd_device->alias_range.end.header.id)
|
||||||
dev_length = sizeof(struct acpi_ivhd_device_alias_range);
|
dev_length = sizeof(ivhd_device->alias_range);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_EXT_RANGE:
|
case ACPI_IVRS_TYPE_EXT_START:
|
||||||
UPDATE_LAST_BDF(ivhd_device->extended_range.trailer.dev_id)
|
UPDATE_LAST_BDF(ivhd_device->extended_range.end.header.id)
|
||||||
dev_length = sizeof(struct acpi_ivhd_device_extended_range);
|
dev_length = sizeof(ivhd_device->extended_range);
|
||||||
break;
|
break;
|
||||||
case AMD_IOMMU_ACPI_IVHD_DEV_SPECIAL:
|
case ACPI_IVRS_TYPE_SPECIAL:
|
||||||
UPDATE_LAST_BDF(ivhd_device->special.dev_id)
|
UPDATE_LAST_BDF(ivhd_device->special.used_id)
|
||||||
dev_length = sizeof(struct acpi_ivhd_device_special);
|
dev_length = sizeof(ivhd_device->special);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device Type!\n");
|
AMD_IOMMU_DEBUG("IVHD Error: Invalid Device Type!\n");
|
||||||
@@ -942,19 +959,20 @@ static int __init get_last_bdf_ivhd(void *ivhd)
|
|||||||
return 0;
|
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;
|
const struct acpi_ivrs_header *ivrs_block;
|
||||||
struct acpi_table_header *table = (struct acpi_table_header *)_table;
|
unsigned long length = sizeof(struct acpi_table_ivrs);
|
||||||
unsigned long length = sizeof(struct acpi_ivrs_table_header);
|
|
||||||
|
|
||||||
while ( table->length > (length + sizeof(*ivrs_block)) )
|
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) )
|
if ( table->length < (length + ivrs_block->length) )
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
if ( ivrs_block->type == AMD_IOMMU_ACPI_IVHD_TYPE )
|
if ( ivrs_block->type == ACPI_IVRS_TYPE_HARDWARE &&
|
||||||
if ( get_last_bdf_ivhd((void*)ivrs_block) != 0 )
|
get_last_bdf_ivhd(
|
||||||
|
container_of(ivrs_block, const struct acpi_ivrs_hardware,
|
||||||
|
header)) != 0 )
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
length += ivrs_block->length;
|
length += ivrs_block->length;
|
||||||
}
|
}
|
||||||
@@ -963,16 +981,16 @@ static int __init get_last_bdf_acpi(struct acpi_table_header *_table)
|
|||||||
|
|
||||||
int __init amd_iommu_detect_acpi(void)
|
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)
|
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;
|
return last_bdf + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __init amd_iommu_update_ivrs_mapping_acpi(void)
|
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);
|
||||||
}
|
}
|
||||||
@@ -20,12 +20,12 @@
|
|||||||
|
|
||||||
#include <xen/config.h>
|
#include <xen/config.h>
|
||||||
#include <xen/errno.h>
|
#include <xen/errno.h>
|
||||||
|
#include <xen/acpi.h>
|
||||||
#include <xen/iommu.h>
|
#include <xen/iommu.h>
|
||||||
#include <xen/pci.h>
|
#include <xen/pci.h>
|
||||||
#include <xen/pci_regs.h>
|
#include <xen/pci_regs.h>
|
||||||
#include <asm/amd-iommu.h>
|
#include <asm/amd-iommu.h>
|
||||||
#include <asm/hvm/svm/amd-iommu-proto.h>
|
#include <asm/hvm/svm/amd-iommu-proto.h>
|
||||||
#include <asm/hvm/svm/amd-iommu-acpi.h>
|
|
||||||
|
|
||||||
static int __init get_iommu_msi_capabilities(
|
static int __init get_iommu_msi_capabilities(
|
||||||
u16 seg, u8 bus, u8 dev, u8 func, struct amd_iommu *iommu)
|
u16 seg, u8 bus, u8 dev, u8 func, struct amd_iommu *iommu)
|
||||||
@@ -103,23 +103,21 @@ void __init get_iommu_features(struct amd_iommu *iommu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
struct amd_iommu *iommu;
|
||||||
u8 bus, dev, func;
|
u8 bus, dev, func;
|
||||||
struct acpi_ivhd_block_header *ivhd_block;
|
|
||||||
int rt = 0;
|
int rt = 0;
|
||||||
|
|
||||||
ivhd_block = (struct acpi_ivhd_block_header *)ivhd;
|
if ( ivhd_block->header.length < sizeof(*ivhd_block) )
|
||||||
|
|
||||||
if ( ivhd_block->header.length < sizeof(struct acpi_ivhd_block_header) )
|
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("Invalid IVHD Block Length!\n");
|
AMD_IOMMU_DEBUG("Invalid IVHD Block Length!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !ivhd_block->header.dev_id ||
|
if ( !ivhd_block->header.device_id ||
|
||||||
!ivhd_block->cap_offset || !ivhd_block->mmio_base)
|
!ivhd_block->capability_offset || !ivhd_block->base_address)
|
||||||
{
|
{
|
||||||
AMD_IOMMU_DEBUG("Invalid IVHD Block!\n");
|
AMD_IOMMU_DEBUG("Invalid IVHD Block!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@@ -134,10 +132,10 @@ int __init amd_iommu_detect_one_acpi(void *ivhd)
|
|||||||
|
|
||||||
spin_lock_init(&iommu->lock);
|
spin_lock_init(&iommu->lock);
|
||||||
|
|
||||||
iommu->seg = ivhd_block->pci_segment;
|
iommu->seg = ivhd_block->pci_segment_group;
|
||||||
iommu->bdf = ivhd_block->header.dev_id;
|
iommu->bdf = ivhd_block->header.device_id;
|
||||||
iommu->cap_offset = ivhd_block->cap_offset;
|
iommu->cap_offset = ivhd_block->capability_offset;
|
||||||
iommu->mmio_base_phys = ivhd_block->mmio_base;
|
iommu->mmio_base_phys = ivhd_block->base_address;
|
||||||
|
|
||||||
/* override IOMMU HT flags */
|
/* override IOMMU HT flags */
|
||||||
iommu->ht_flags = ivhd_block->header.flags;
|
iommu->ht_flags = ivhd_block->header.flags;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <xen/config.h>
|
#include <xen/config.h>
|
||||||
#include <xen/errno.h>
|
#include <xen/errno.h>
|
||||||
|
#include <xen/acpi.h>
|
||||||
#include <xen/pci.h>
|
#include <xen/pci.h>
|
||||||
#include <xen/pci_regs.h>
|
#include <xen/pci_regs.h>
|
||||||
#include <xen/irq.h>
|
#include <xen/irq.h>
|
||||||
@@ -28,7 +29,6 @@
|
|||||||
#include <asm/hvm/svm/amd-iommu-proto.h>
|
#include <asm/hvm/svm/amd-iommu-proto.h>
|
||||||
#include <asm-x86/fixmap.h>
|
#include <asm-x86/fixmap.h>
|
||||||
#include <mach_apic.h>
|
#include <mach_apic.h>
|
||||||
#include <asm/hvm/svm/amd-iommu-acpi.h>
|
|
||||||
|
|
||||||
static int __initdata nr_amd_iommus;
|
static int __initdata nr_amd_iommus;
|
||||||
|
|
||||||
@@ -37,9 +37,8 @@ static struct radix_tree_root ivrs_maps;
|
|||||||
struct list_head amd_iommu_head;
|
struct list_head amd_iommu_head;
|
||||||
struct table_struct device_table;
|
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;
|
return iommu->ht_flags & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,19 +79,19 @@ static void set_iommu_ht_flags(struct amd_iommu *iommu)
|
|||||||
|
|
||||||
/* Setup HT flags */
|
/* Setup HT flags */
|
||||||
if ( iommu_has_cap(iommu, PCI_CAP_HT_TUNNEL_SHIFT) )
|
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_set_bit(&entry, IOMMU_CONTROL_HT_TUNNEL_TRANSLATION_SHIFT) :
|
||||||
iommu_clear_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_set_bit(&entry, IOMMU_CONTROL_RESP_PASS_POSTED_WRITE_SHIFT):
|
||||||
iommu_clear_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_set_bit(&entry, IOMMU_CONTROL_ISOCHRONOUS_SHIFT):
|
||||||
iommu_clear_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_set_bit(&entry, IOMMU_CONTROL_PASS_POSTED_WRITE_SHIFT):
|
||||||
iommu_clear_bit(&entry, IOMMU_CONTROL_PASS_POSTED_WRITE_SHIFT);
|
iommu_clear_bit(&entry, IOMMU_CONTROL_PASS_POSTED_WRITE_SHIFT);
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,13 @@
|
|||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <xen/config.h>
|
||||||
|
#include <xen/acpi.h>
|
||||||
#include <xen/sched.h>
|
#include <xen/sched.h>
|
||||||
#include <asm/p2m.h>
|
#include <asm/p2m.h>
|
||||||
#include <xen/hvm/iommu.h>
|
#include <xen/hvm/iommu.h>
|
||||||
#include <asm/amd-iommu.h>
|
#include <asm/amd-iommu.h>
|
||||||
#include <asm/hvm/svm/amd-iommu-proto.h>
|
#include <asm/hvm/svm/amd-iommu-proto.h>
|
||||||
#include <asm/hvm/svm/amd-iommu-acpi.h>
|
|
||||||
#include "../ats.h"
|
#include "../ats.h"
|
||||||
#include <xen/pci.h>
|
#include <xen/pci.h>
|
||||||
|
|
||||||
@@ -215,8 +216,7 @@ void __init iommu_dte_add_device_entry(u32 *dte, struct ivrs_mappings *ivrs_dev)
|
|||||||
dte[7] = dte[6] = dte[4] = dte[2] = dte[1] = dte[0] = 0;
|
dte[7] = dte[6] = dte[4] = dte[2] = dte[1] = dte[0] = 0;
|
||||||
|
|
||||||
flags = ivrs_dev->device_flags;
|
flags = ivrs_dev->device_flags;
|
||||||
sys_mgt = get_field_from_byte(flags, AMD_IOMMU_ACPI_SYS_MGT_MASK,
|
sys_mgt = get_field_from_byte(flags, ACPI_IVHD_SYSTEM_MGMT);
|
||||||
AMD_IOMMU_ACPI_SYS_MGT_SHIFT);
|
|
||||||
dev_ex = ivrs_dev->dte_allow_exclusion;
|
dev_ex = ivrs_dev->dte_allow_exclusion;
|
||||||
|
|
||||||
flags &= mask;
|
flags &= mask;
|
||||||
|
|||||||
@@ -1,185 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2007 Advanced Micro Devices, Inc.
|
|
||||||
* Author: Leo Duran <leo.duran@amd.com>
|
|
||||||
* Author: Wei Wang <wei.wang2@amd.com> - 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 <xen/acpi.h>
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
@@ -26,6 +26,8 @@
|
|||||||
#include <asm/apicdef.h>
|
#include <asm/apicdef.h>
|
||||||
#include <xen/domain_page.h>
|
#include <xen/domain_page.h>
|
||||||
|
|
||||||
|
struct acpi_ivrs_hardware;
|
||||||
|
|
||||||
#define for_each_amd_iommu(amd_iommu) \
|
#define for_each_amd_iommu(amd_iommu) \
|
||||||
list_for_each_entry(amd_iommu, \
|
list_for_each_entry(amd_iommu, \
|
||||||
&amd_iommu_head, list)
|
&amd_iommu_head, list)
|
||||||
@@ -41,7 +43,7 @@
|
|||||||
|
|
||||||
/* amd-iommu-detect functions */
|
/* amd-iommu-detect functions */
|
||||||
int amd_iommu_get_ivrs_dev_entries(void);
|
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);
|
int amd_iommu_detect_acpi(void);
|
||||||
void get_iommu_features(struct amd_iommu *iommu);
|
void get_iommu_features(struct amd_iommu *iommu);
|
||||||
|
|
||||||
@@ -121,11 +123,9 @@ static inline u32 set_field_in_reg_u32(u32 field, u32 reg_value,
|
|||||||
return reg_value;
|
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;
|
return (value & mask) / (mask & -mask);
|
||||||
field = (value & mask) >> shift;
|
|
||||||
return field;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long region_to_pages(unsigned long addr, unsigned long size)
|
static inline unsigned long region_to_pages(unsigned long addr, unsigned long size)
|
||||||
|
|||||||