aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/amd_iommu_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu/amd_iommu_init.c')
-rw-r--r--drivers/iommu/amd_iommu_init.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index eb104c719629..4413aa67000e 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -23,6 +23,8 @@
23#include <linux/mem_encrypt.h> 23#include <linux/mem_encrypt.h>
24#include <asm/pci-direct.h> 24#include <asm/pci-direct.h>
25#include <asm/iommu.h> 25#include <asm/iommu.h>
26#include <asm/apic.h>
27#include <asm/msidef.h>
26#include <asm/gart.h> 28#include <asm/gart.h>
27#include <asm/x86_init.h> 29#include <asm/x86_init.h>
28#include <asm/iommu_table.h> 30#include <asm/iommu_table.h>
@@ -1920,6 +1922,90 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
1920 return 0; 1922 return 0;
1921} 1923}
1922 1924
1925#define XT_INT_DEST_MODE(x) (((x) & 0x1ULL) << 2)
1926#define XT_INT_DEST_LO(x) (((x) & 0xFFFFFFULL) << 8)
1927#define XT_INT_VEC(x) (((x) & 0xFFULL) << 32)
1928#define XT_INT_DEST_HI(x) ((((x) >> 24) & 0xFFULL) << 56)
1929
1930/**
1931 * Setup the IntCapXT registers with interrupt routing information
1932 * based on the PCI MSI capability block registers, accessed via
1933 * MMIO MSI address low/hi and MSI data registers.
1934 */
1935static void iommu_update_intcapxt(struct amd_iommu *iommu)
1936{
1937 u64 val;
1938 u32 addr_lo = readl(iommu->mmio_base + MMIO_MSI_ADDR_LO_OFFSET);
1939 u32 addr_hi = readl(iommu->mmio_base + MMIO_MSI_ADDR_HI_OFFSET);
1940 u32 data = readl(iommu->mmio_base + MMIO_MSI_DATA_OFFSET);
1941 bool dm = (addr_lo >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1;
1942 u32 dest = ((addr_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xFF);
1943
1944 if (x2apic_enabled())
1945 dest |= MSI_ADDR_EXT_DEST_ID(addr_hi);
1946
1947 val = XT_INT_VEC(data & 0xFF) |
1948 XT_INT_DEST_MODE(dm) |
1949 XT_INT_DEST_LO(dest) |
1950 XT_INT_DEST_HI(dest);
1951
1952 /**
1953 * Current IOMMU implemtation uses the same IRQ for all
1954 * 3 IOMMU interrupts.
1955 */
1956 writeq(val, iommu->mmio_base + MMIO_INTCAPXT_EVT_OFFSET);
1957 writeq(val, iommu->mmio_base + MMIO_INTCAPXT_PPR_OFFSET);
1958 writeq(val, iommu->mmio_base + MMIO_INTCAPXT_GALOG_OFFSET);
1959}
1960
1961static void _irq_notifier_notify(struct irq_affinity_notify *notify,
1962 const cpumask_t *mask)
1963{
1964 struct amd_iommu *iommu;
1965
1966 for_each_iommu(iommu) {
1967 if (iommu->dev->irq == notify->irq) {
1968 iommu_update_intcapxt(iommu);
1969 break;
1970 }
1971 }
1972}
1973
1974static void _irq_notifier_release(struct kref *ref)
1975{
1976}
1977
1978static int iommu_init_intcapxt(struct amd_iommu *iommu)
1979{
1980 int ret;
1981 struct irq_affinity_notify *notify = &iommu->intcapxt_notify;
1982
1983 /**
1984 * IntCapXT requires XTSup=1, which can be inferred
1985 * amd_iommu_xt_mode.
1986 */
1987 if (amd_iommu_xt_mode != IRQ_REMAP_X2APIC_MODE)
1988 return 0;
1989
1990 /**
1991 * Also, we need to setup notifier to update the IntCapXT registers
1992 * whenever the irq affinity is changed from user-space.
1993 */
1994 notify->irq = iommu->dev->irq;
1995 notify->notify = _irq_notifier_notify,
1996 notify->release = _irq_notifier_release,
1997 ret = irq_set_affinity_notifier(iommu->dev->irq, notify);
1998 if (ret) {
1999 pr_err("Failed to register irq affinity notifier (devid=%#x, irq %d)\n",
2000 iommu->devid, iommu->dev->irq);
2001 return ret;
2002 }
2003
2004 iommu_update_intcapxt(iommu);
2005 iommu_feature_enable(iommu, CONTROL_INTCAPXT_EN);
2006 return ret;
2007}
2008
1923static int iommu_init_msi(struct amd_iommu *iommu) 2009static int iommu_init_msi(struct amd_iommu *iommu)
1924{ 2010{
1925 int ret; 2011 int ret;
@@ -1936,6 +2022,10 @@ static int iommu_init_msi(struct amd_iommu *iommu)
1936 return ret; 2022 return ret;
1937 2023
1938enable_faults: 2024enable_faults:
2025 ret = iommu_init_intcapxt(iommu);
2026 if (ret)
2027 return ret;
2028
1939 iommu_feature_enable(iommu, CONTROL_EVT_INT_EN); 2029 iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
1940 2030
1941 if (iommu->ppr_log != NULL) 2031 if (iommu->ppr_log != NULL)