Skip to content

Commit

Permalink
x86/amd-iommu: Workaround for erratum 63
Browse files Browse the repository at this point in the history
There is an erratum for IOMMU hardware which documents
undefined behavior when forwarding SMI requests from
peripherals and the DTE of that peripheral has a sysmgt
value of 01b. This problem caused weird IO_PAGE_FAULTS in my
case.
This patch implements the suggested workaround for that
erratum into the AMD IOMMU driver.  The erratum is
documented with number 63.

Cc: stable@kernel.org
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
  • Loading branch information
Joerg Roedel committed Oct 9, 2009
1 parent c7084b3 commit c5cca14
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/x86/include/asm/amd_iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
extern void amd_iommu_flush_all_domains(void);
extern void amd_iommu_flush_all_devices(void);
extern void amd_iommu_shutdown(void);
extern void amd_iommu_apply_erratum_63(u16 devid);
#else
static inline int amd_iommu_init(void) { return -ENODEV; }
static inline void amd_iommu_detect(void) { }
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/kernel/amd_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,8 @@ static void __detach_device(struct protection_domain *domain, u16 devid)
amd_iommu_dev_table[devid].data[1] = 0;
amd_iommu_dev_table[devid].data[2] = 0;

amd_iommu_apply_erratum_63(devid);

/* decrease reference counter */
domain->dev_cnt -= 1;

Expand Down
22 changes: 22 additions & 0 deletions arch/x86/kernel/amd_iommu_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,26 @@ static void set_dev_entry_bit(u16 devid, u8 bit)
amd_iommu_dev_table[devid].data[i] |= (1 << _bit);
}

static int get_dev_entry_bit(u16 devid, u8 bit)
{
int i = (bit >> 5) & 0x07;
int _bit = bit & 0x1f;

return (amd_iommu_dev_table[devid].data[i] & (1 << _bit)) >> _bit;
}


void amd_iommu_apply_erratum_63(u16 devid)
{
int sysmgt;

sysmgt = get_dev_entry_bit(devid, DEV_ENTRY_SYSMGT1) |
(get_dev_entry_bit(devid, DEV_ENTRY_SYSMGT2) << 1);

if (sysmgt == 0x01)
set_dev_entry_bit(devid, DEV_ENTRY_IW);
}

/* Writes the specific IOMMU for a device into the rlookup table */
static void __init set_iommu_for_device(struct amd_iommu *iommu, u16 devid)
{
Expand Down Expand Up @@ -537,6 +557,8 @@ static void __init set_dev_entry_from_acpi(struct amd_iommu *iommu,
if (flags & ACPI_DEVFLAG_LINT1)
set_dev_entry_bit(devid, DEV_ENTRY_LINT1_PASS);

amd_iommu_apply_erratum_63(devid);

set_iommu_for_device(iommu, devid);
}

Expand Down

0 comments on commit c5cca14

Please sign in to comment.