iommu/vt-d: Detect pre enabled translation
authorJoerg Roedel <jroedel@suse.de>
Fri, 12 Jun 2015 08:14:02 +0000 (10:14 +0200)
committerJoerg Roedel <jroedel@suse.de>
Tue, 16 Jun 2015 08:59:34 +0000 (10:59 +0200)
Add code to detect whether translation is already enabled in
the IOMMU. Save this state in a flags field added to
struct intel_iommu.

Tested-by: ZhenHua Li <zhen-hual@hp.com>
Tested-by: Baoquan He <bhe@redhat.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/intel-iommu.c
include/linux/intel-iommu.h

index bf3e450..39b9062 100644 (file)
@@ -443,6 +443,20 @@ static LIST_HEAD(device_domain_list);
 
 static const struct iommu_ops intel_iommu_ops;
 
+static bool translation_pre_enabled(struct intel_iommu *iommu)
+{
+       return (iommu->flags & VTD_FLAG_TRANS_PRE_ENABLED);
+}
+
+static void init_translation_status(struct intel_iommu *iommu)
+{
+       u32 gsts;
+
+       gsts = readl(iommu->reg + DMAR_GSTS_REG);
+       if (gsts & DMA_GSTS_TES)
+               iommu->flags |= VTD_FLAG_TRANS_PRE_ENABLED;
+}
+
 /* Convert generic 'struct iommu_domain to private struct dmar_domain */
 static struct dmar_domain *to_dmar_domain(struct iommu_domain *dom)
 {
@@ -2809,6 +2823,11 @@ static int __init init_dmars(void)
                if (ret)
                        goto free_iommu;
 
+               init_translation_status(iommu);
+
+               if (translation_pre_enabled(iommu))
+                       pr_info("Translation already enabled - trying to copy translation structures\n");
+
                /*
                 * TBD:
                 * we could share the same root & context tables
index a240e61..b85b81a 100644 (file)
@@ -320,6 +320,9 @@ enum {
        MAX_SR_DMAR_REGS
 };
 
+#define VTD_FLAG_TRANS_PRE_ENABLED     (1 << 0)
+#define VTD_FLAG_IRQ_REMAP_PRE_ENABLED (1 << 1)
+
 struct intel_iommu {
        void __iomem    *reg; /* Pointer to hardware regs, virtual addr */
        u64             reg_phys; /* physical address of hw register set */
@@ -351,6 +354,7 @@ struct intel_iommu {
 #endif
        struct device   *iommu_dev; /* IOMMU-sysfs device */
        int             node;
+       u32             flags;      /* Software defined flags */
 };
 
 static inline void __iommu_flush_cache(