ia64/xen-unstable

changeset 19752:fa51db0871e1

vtd: Fix flush for SRTP and SIRTP set

SRTP (Set Root Table Pointer) operation must be set before enable or
re-enable DMA remapping. And after set it, software must globally
invalidate the context-cache and then globally invalidate the
IOTLB. This is required to ensure hardware uses only the remapping
structures referenced by the new root-table pointer, and not stale
cached entries. Similarly, SIRTP (Set Interrupt Remap Table Pointer)
operation must be set before enable or re-enable Interrupt
remapping, and after set it, software must globally invalidate the
interrupt entry cache. This patch adds global context and iotlb
flush after set root entry, and globally flushs interrupt entry
cache before enabling Interrupt remapping. And remove the
iommu_flush_all in iommu_resume becuase it becomes redundant after
adds flush for SRTP in init_vtd_hw.

Signed-off-by: Weidong Han <weidong.han@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jun 16 11:30:45 2009 +0100 (2009-06-16)
parents eeb0fce9aeaf
children cc07094a02e4
files xen/drivers/passthrough/vtd/intremap.c xen/drivers/passthrough/vtd/iommu.c
line diff
     1.1 --- a/xen/drivers/passthrough/vtd/intremap.c	Tue Jun 16 11:25:37 2009 +0100
     1.2 +++ b/xen/drivers/passthrough/vtd/intremap.c	Tue Jun 16 11:30:45 2009 +0100
     1.3 @@ -568,6 +568,9 @@ int enable_intremap(struct iommu *iommu)
     1.4      IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
     1.5                    (sts & DMA_GSTS_SIRTPS), sts);
     1.6   
     1.7 +    /* After set SIRTP, must globally invalidate the interrupt entry cache */
     1.8 +    iommu_flush_iec_global(iommu);
     1.9 +
    1.10      /* enable comaptiblity format interrupt pass through */
    1.11      gcmd |= DMA_GCMD_CFI;
    1.12      dmar_writel(iommu->reg, DMAR_GCMD_REG, gcmd);
    1.13 @@ -582,9 +585,6 @@ int enable_intremap(struct iommu *iommu)
    1.14      IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
    1.15                    (sts & DMA_GSTS_IRES), sts);
    1.16  
    1.17 -    /* After set SIRTP, we should do globally invalidate the IEC */
    1.18 -    iommu_flush_iec_global(iommu);
    1.19 -
    1.20      return init_apic_pin_2_ir_idx();
    1.21  }
    1.22  
     2.1 --- a/xen/drivers/passthrough/vtd/iommu.c	Tue Jun 16 11:25:37 2009 +0100
     2.2 +++ b/xen/drivers/passthrough/vtd/iommu.c	Tue Jun 16 11:30:45 2009 +0100
     2.3 @@ -1639,13 +1639,6 @@ static int init_vtd_hw(void)
     2.4      for_each_drhd_unit ( drhd )
     2.5      {
     2.6          iommu = drhd->iommu;
     2.7 -        ret = iommu_set_root_entry(iommu);
     2.8 -        if ( ret )
     2.9 -        {
    2.10 -            gdprintk(XENLOG_ERR VTDPREFIX, "IOMMU: set root entry failed\n");
    2.11 -            return -EIO;
    2.12 -        }
    2.13 -
    2.14          if ( iommu->vector < 0 )
    2.15          {
    2.16              vector = iommu_set_interrupt(iommu);
    2.17 @@ -1695,6 +1688,23 @@ static int init_vtd_hw(void)
    2.18          }
    2.19      }
    2.20  
    2.21 +    for_each_drhd_unit ( drhd )
    2.22 +    {
    2.23 +        iommu = drhd->iommu;
    2.24 +        ret = iommu_set_root_entry(iommu);
    2.25 +        if ( ret )
    2.26 +        {
    2.27 +            gdprintk(XENLOG_ERR VTDPREFIX, "IOMMU: set root entry failed\n");
    2.28 +            return -EIO;
    2.29 +        }
    2.30 +    }
    2.31 +
    2.32 +    /*
    2.33 +     * After set root entry, must globally invalidate context cache, and
    2.34 +     * then globally invalidate IOTLB
    2.35 +     */
    2.36 +    iommu_flush_all();
    2.37 +
    2.38      return 0;
    2.39  }
    2.40  
    2.41 @@ -1931,35 +1941,11 @@ void iommu_resume(void)
    2.42  {
    2.43      struct acpi_drhd_unit *drhd;
    2.44      struct iommu *iommu;
    2.45 -    struct iommu_flush *flush;
    2.46      u32 i;
    2.47  
    2.48      if ( !iommu_enabled )
    2.49          return;
    2.50  
    2.51 -    /* Re-initialize the register-based flush functions.
    2.52 -     * In iommu_flush_all(), we invoke iommu_flush_{context,iotlb}_global(),
    2.53 -     * but at this point, on hosts that support QI(Queued Invalidation), QI
    2.54 -     * hasn't been re-enabed yet, so for now let's use the register-based
    2.55 -     * invalidation method before invoking init_vtd_hw().
    2.56 -     */
    2.57 -    if ( iommu_qinval )
    2.58 -    {
    2.59 -        for_each_drhd_unit ( drhd )
    2.60 -        {
    2.61 -            iommu = drhd->iommu;
    2.62 -            flush = iommu_get_flush(iommu);
    2.63 -            flush->context = flush_context_reg;
    2.64 -            flush->iotlb = flush_iotlb_reg;
    2.65 -        }
    2.66 -    }
    2.67 -
    2.68 -    /* Not sure whether the flush operation is required to meet iommu
    2.69 -     * specification. Note that BIOS also executes in S3 resume and iommu may
    2.70 -     * be touched again, so let us do the flush operation for safety.
    2.71 -     */
    2.72 -    iommu_flush_all();
    2.73 -
    2.74      if ( init_vtd_hw() != 0  && force_iommu )
    2.75           panic("IOMMU setup failed, crash Xen for security purpose!\n");
    2.76