mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
amd iommu: Simplify IVHD device flag handling
These bits are aligned to corresponding fields in device table entry. They can be updated by a single device entry write. Signed-off-by: Wei Wang <wei.wang2@amd.com> Committed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
756273ab10
commit
6757a17b2a
6 files changed
+22
-91
No files matched your search
@@ -31,38 +31,14 @@ static void __init add_ivrs_mapping_entry(
|
||||
u16 bdf, u16 alias_id, u8 flags, struct amd_iommu *iommu)
|
||||
{
|
||||
struct ivrs_mappings *ivrs_mappings = get_ivrs_mappings(iommu->seg);
|
||||
u8 sys_mgt, lint1_pass, lint0_pass, nmi_pass, ext_int_pass, init_pass;
|
||||
|
||||
ASSERT( ivrs_mappings != NULL );
|
||||
|
||||
/* setup requestor id */
|
||||
ivrs_mappings[bdf].dte_requestor_id = alias_id;
|
||||
|
||||
/* override flags for range of devices */
|
||||
sys_mgt = get_field_from_byte(flags,
|
||||
AMD_IOMMU_ACPI_SYS_MGT_MASK,
|
||||
AMD_IOMMU_ACPI_SYS_MGT_SHIFT);
|
||||
lint1_pass = get_field_from_byte(flags,
|
||||
AMD_IOMMU_ACPI_LINT1_PASS_MASK,
|
||||
AMD_IOMMU_ACPI_LINT1_PASS_SHIFT);
|
||||
lint0_pass = get_field_from_byte(flags,
|
||||
AMD_IOMMU_ACPI_LINT0_PASS_MASK,
|
||||
AMD_IOMMU_ACPI_LINT0_PASS_SHIFT);
|
||||
nmi_pass = get_field_from_byte(flags,
|
||||
AMD_IOMMU_ACPI_NMI_PASS_MASK,
|
||||
AMD_IOMMU_ACPI_NMI_PASS_SHIFT);
|
||||
ext_int_pass = get_field_from_byte(flags,
|
||||
AMD_IOMMU_ACPI_EINT_PASS_MASK,
|
||||
AMD_IOMMU_ACPI_EINT_PASS_SHIFT);
|
||||
init_pass = get_field_from_byte(flags,
|
||||
AMD_IOMMU_ACPI_INIT_PASS_MASK,
|
||||
AMD_IOMMU_ACPI_INIT_PASS_SHIFT);
|
||||
|
||||
ivrs_mappings[bdf].dte_sys_mgt_enable = sys_mgt;
|
||||
ivrs_mappings[bdf].dte_lint1_pass = lint1_pass;
|
||||
ivrs_mappings[bdf].dte_lint0_pass = lint0_pass;
|
||||
ivrs_mappings[bdf].dte_nmi_pass = nmi_pass;
|
||||
ivrs_mappings[bdf].dte_ext_int_pass = ext_int_pass;
|
||||
ivrs_mappings[bdf].dte_init_pass = init_pass;
|
||||
ivrs_mappings[bdf].device_flags = flags;
|
||||
|
||||
if (ivrs_mappings[alias_id].intremap_table == NULL )
|
||||
{
|
||||
|
||||
@@ -790,18 +790,12 @@ static int __init alloc_ivrs_mappings(u16 seg)
|
||||
for ( bdf = 0; bdf < ivrs_bdf_entries; bdf++ )
|
||||
{
|
||||
ivrs_mappings[bdf].dte_requestor_id = bdf;
|
||||
ivrs_mappings[bdf].dte_sys_mgt_enable =
|
||||
IOMMU_DEV_TABLE_SYS_MGT_MSG_FORWARDED;
|
||||
ivrs_mappings[bdf].dte_allow_exclusion = IOMMU_CONTROL_DISABLED;
|
||||
ivrs_mappings[bdf].unity_map_enable = IOMMU_CONTROL_DISABLED;
|
||||
ivrs_mappings[bdf].iommu = NULL;
|
||||
|
||||
ivrs_mappings[bdf].intremap_table = NULL;
|
||||
ivrs_mappings[bdf].dte_lint1_pass = IOMMU_CONTROL_DISABLED;
|
||||
ivrs_mappings[bdf].dte_lint0_pass = IOMMU_CONTROL_DISABLED;
|
||||
ivrs_mappings[bdf].dte_nmi_pass = IOMMU_CONTROL_DISABLED;
|
||||
ivrs_mappings[bdf].dte_ext_int_pass = IOMMU_CONTROL_DISABLED;
|
||||
ivrs_mappings[bdf].dte_init_pass = IOMMU_CONTROL_DISABLED;
|
||||
ivrs_mappings[bdf].device_flags = 0;
|
||||
|
||||
if ( amd_iommu_perdev_intremap )
|
||||
spin_lock_init(&ivrs_mappings[bdf].intremap_lock);
|
||||
@@ -817,8 +811,6 @@ static int __init amd_iommu_setup_device_table(
|
||||
{
|
||||
int bdf;
|
||||
void *intr_tb, *dte;
|
||||
int sys_mgt, dev_ex, lint1_pass, lint0_pass,
|
||||
nmi_pass, ext_int_pass, init_pass;
|
||||
|
||||
BUG_ON( (ivrs_bdf_entries == 0) );
|
||||
|
||||
@@ -840,21 +832,9 @@ static int __init amd_iommu_setup_device_table(
|
||||
|
||||
if ( intr_tb )
|
||||
{
|
||||
sys_mgt = ivrs_mappings[bdf].dte_sys_mgt_enable;
|
||||
dev_ex = ivrs_mappings[bdf].dte_allow_exclusion;
|
||||
|
||||
/* get interrupt remapping settings */
|
||||
lint1_pass = ivrs_mappings[bdf].dte_lint1_pass;
|
||||
lint0_pass = ivrs_mappings[bdf].dte_lint0_pass;
|
||||
nmi_pass = ivrs_mappings[bdf].dte_nmi_pass;
|
||||
ext_int_pass = ivrs_mappings[bdf].dte_ext_int_pass;
|
||||
init_pass = ivrs_mappings[bdf].dte_init_pass;
|
||||
|
||||
/* add device table entry */
|
||||
dte = device_table.buffer + (bdf * IOMMU_DEV_TABLE_ENTRY_SIZE);
|
||||
amd_iommu_add_dev_table_entry(
|
||||
dte, sys_mgt, dev_ex, lint1_pass, lint0_pass,
|
||||
nmi_pass, ext_int_pass, init_pass);
|
||||
iommu_dte_add_device_entry(dte, &ivrs_mappings[bdf]);
|
||||
|
||||
amd_iommu_set_intremap_table(
|
||||
dte, (u64)virt_to_maddr(intr_tb), iommu_intremap);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <xen/hvm/iommu.h>
|
||||
#include <asm/amd-iommu.h>
|
||||
#include <asm/hvm/svm/amd-iommu-proto.h>
|
||||
#include <asm/hvm/svm/amd-iommu-acpi.h>
|
||||
#include "../ats.h"
|
||||
#include <xen/pci.h>
|
||||
|
||||
@@ -419,35 +420,23 @@ void __init amd_iommu_set_intremap_table(
|
||||
dte[4] = entry;
|
||||
}
|
||||
|
||||
void __init amd_iommu_add_dev_table_entry(
|
||||
u32 *dte, u8 sys_mgt, u8 dev_ex, u8 lint1_pass, u8 lint0_pass,
|
||||
u8 nmi_pass, u8 ext_int_pass, u8 init_pass)
|
||||
void __init iommu_dte_add_device_entry(u32 *dte, struct ivrs_mappings *ivrs_dev)
|
||||
{
|
||||
u32 entry;
|
||||
u8 sys_mgt, dev_ex, flags;
|
||||
u8 mask = ~(0x7 << 3);
|
||||
|
||||
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);
|
||||
dev_ex = ivrs_dev->dte_allow_exclusion;
|
||||
|
||||
set_field_in_reg_u32(init_pass ? IOMMU_CONTROL_ENABLED :
|
||||
IOMMU_CONTROL_DISABLED, 0,
|
||||
IOMMU_DEV_TABLE_INIT_PASSTHRU_MASK,
|
||||
IOMMU_DEV_TABLE_INIT_PASSTHRU_SHIFT, &entry);
|
||||
set_field_in_reg_u32(ext_int_pass ? IOMMU_CONTROL_ENABLED :
|
||||
IOMMU_CONTROL_DISABLED, entry,
|
||||
IOMMU_DEV_TABLE_EINT_PASSTHRU_MASK,
|
||||
IOMMU_DEV_TABLE_EINT_PASSTHRU_SHIFT, &entry);
|
||||
set_field_in_reg_u32(nmi_pass ? IOMMU_CONTROL_ENABLED :
|
||||
IOMMU_CONTROL_DISABLED, entry,
|
||||
IOMMU_DEV_TABLE_NMI_PASSTHRU_MASK,
|
||||
IOMMU_DEV_TABLE_NMI_PASSTHRU_SHIFT, &entry);
|
||||
set_field_in_reg_u32(lint0_pass ? IOMMU_CONTROL_ENABLED :
|
||||
IOMMU_CONTROL_DISABLED, entry,
|
||||
IOMMU_DEV_TABLE_LINT0_ENABLE_MASK,
|
||||
IOMMU_DEV_TABLE_LINT0_ENABLE_SHIFT, &entry);
|
||||
set_field_in_reg_u32(lint1_pass ? IOMMU_CONTROL_ENABLED :
|
||||
IOMMU_CONTROL_DISABLED, entry,
|
||||
IOMMU_DEV_TABLE_LINT1_ENABLE_MASK,
|
||||
IOMMU_DEV_TABLE_LINT1_ENABLE_SHIFT, &entry);
|
||||
flags &= mask;
|
||||
set_field_in_reg_u32(flags, 0,
|
||||
IOMMU_DEV_TABLE_IVHD_FLAGS_MASK,
|
||||
IOMMU_DEV_TABLE_IVHD_FLAGS_SHIFT, &entry);
|
||||
dte[5] = entry;
|
||||
|
||||
set_field_in_reg_u32(sys_mgt, 0,
|
||||
|
||||
@@ -86,7 +86,6 @@ struct amd_iommu {
|
||||
|
||||
struct ivrs_mappings {
|
||||
u16 dte_requestor_id;
|
||||
u8 dte_sys_mgt_enable;
|
||||
u8 dte_allow_exclusion;
|
||||
u8 unity_map_enable;
|
||||
u8 write_permission;
|
||||
@@ -99,12 +98,8 @@ struct ivrs_mappings {
|
||||
void *intremap_table;
|
||||
spinlock_t intremap_lock;
|
||||
|
||||
/* interrupt remapping settings */
|
||||
u8 dte_lint1_pass;
|
||||
u8 dte_lint0_pass;
|
||||
u8 dte_nmi_pass;
|
||||
u8 dte_ext_int_pass;
|
||||
u8 dte_init_pass;
|
||||
/* ivhd device data settings */
|
||||
u8 device_flags;
|
||||
};
|
||||
|
||||
extern unsigned short ivrs_bdf_entries;
|
||||
|
||||
@@ -158,18 +158,11 @@
|
||||
/* DeviceTable Entry[191:160] */
|
||||
#define IOMMU_DEV_TABLE_INT_TABLE_PTR_HIGH_MASK 0x000FFFFF
|
||||
#define IOMMU_DEV_TABLE_INT_TABLE_PTR_HIGH_SHIFT 0
|
||||
#define IOMMU_DEV_TABLE_INIT_PASSTHRU_MASK 0x01000000
|
||||
#define IOMMU_DEV_TABLE_INIT_PASSTHRU_SHIFT 24
|
||||
#define IOMMU_DEV_TABLE_EINT_PASSTHRU_MASK 0x02000000
|
||||
#define IOMMU_DEV_TABLE_EINT_PASSTHRU_SHIFT 25
|
||||
#define IOMMU_DEV_TABLE_NMI_PASSTHRU_MASK 0x04000000
|
||||
#define IOMMU_DEV_TABLE_NMI_PASSTHRU_SHIFT 26
|
||||
#define IOMMU_DEV_TABLE_IVHD_FLAGS_SHIFT 24
|
||||
#define IOMMU_DEV_TABLE_IVHD_FLAGS_MASK 0xC7000000
|
||||
#define IOMMU_DEV_TABLE_INT_CONTROL_MASK 0x30000000
|
||||
#define IOMMU_DEV_TABLE_INT_CONTROL_SHIFT 28
|
||||
#define IOMMU_DEV_TABLE_LINT0_ENABLE_MASK 0x40000000
|
||||
#define IOMMU_DEV_TABLE_LINT0_ENABLE_SHIFT 30
|
||||
#define IOMMU_DEV_TABLE_LINT1_ENABLE_MASK 0x80000000
|
||||
#define IOMMU_DEV_TABLE_LINT1_ENABLE_SHIFT 31
|
||||
|
||||
|
||||
/* Command Buffer */
|
||||
#define IOMMU_CMD_BUFFER_BASE_LOW_OFFSET 0x08
|
||||
|
||||
@@ -68,14 +68,12 @@ void amd_iommu_share_p2m(struct domain *d);
|
||||
|
||||
/* device table functions */
|
||||
int get_dma_requestor_id(u16 seg, u16 bdf);
|
||||
void amd_iommu_add_dev_table_entry(
|
||||
u32 *dte, u8 sys_mgt, u8 dev_ex, u8 lint1_pass, u8 lint0_pass,
|
||||
u8 nmi_pass, u8 ext_int_pass, u8 init_pass);
|
||||
void amd_iommu_set_intremap_table(
|
||||
u32 *dte, u64 intremap_ptr, u8 int_valid);
|
||||
void amd_iommu_set_root_page_table(
|
||||
u32 *dte, u64 root_ptr, u16 domain_id, u8 paging_mode, u8 valid);
|
||||
void iommu_dte_set_iotlb(u32 *dte, u8 i);
|
||||
void iommu_dte_add_device_entry(u32 *dte, struct ivrs_mappings *ivrs_dev);
|
||||
void invalidate_dev_table_entry(struct amd_iommu *iommu, u16 devic_id);
|
||||
|
||||
/* send cmd to iommu */
|
||||
|
||||