summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorMitchel Humpherys <mitchelh@codeaurora.org>2015-12-21 15:06:34 -0800
committerJeevan Shriram <jshriram@codeaurora.org>2016-05-20 19:24:04 -0700
commit94c107c426ffc5d0db9230664ca6028dda2e521e (patch)
tree3f9beb86a1618d9f330debe2c7afb1e3b7be1726 /include/linux
parent0a70cf0fac2960a23bb1a21578a7e27411d34810 (diff)
iommu/io-pgtable-fast: Prove correctness of TLB maintenance
A common software error when it comes to page table code is missing TLB maintenance. Add some checks to the io-pgtable-fast code to detect when an address that might be stale in the TLB is being re-used. This can be accomplished by writing a "stale TLB" flag value to the reserved bits of the PTE during unmap and then removing the flag value when the TLBs are invalidated (by sweeping the entire page table). That way, whenever we map we can know that there might be a stale TLB in the location being mapped into if it contains the "stale TLB" flag value. CRs-Fixed: 997751 Change-Id: Icf9c1e41977cb71e8b137190adb3b4a201c339da Signed-off-by: Mitchel Humpherys <mitchelh@codeaurora.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/dma-mapping-fast.h1
-rw-r--r--include/linux/io-pgtable-fast.h33
2 files changed, 34 insertions, 0 deletions
diff --git a/include/linux/dma-mapping-fast.h b/include/linux/dma-mapping-fast.h
index ad82efca2153..aa9fcfe73162 100644
--- a/include/linux/dma-mapping-fast.h
+++ b/include/linux/dma-mapping-fast.h
@@ -33,6 +33,7 @@ struct dma_fast_smmu_mapping {
av8l_fast_iopte *pgtbl_pmds;
spinlock_t lock;
+ struct notifier_block notifier;
};
#ifdef CONFIG_IOMMU_IO_PGTABLE_FAST
diff --git a/include/linux/io-pgtable-fast.h b/include/linux/io-pgtable-fast.h
index b482ffe8d20c..ab5a1dc6753e 100644
--- a/include/linux/io-pgtable-fast.h
+++ b/include/linux/io-pgtable-fast.h
@@ -13,6 +13,8 @@
#ifndef __LINUX_IO_PGTABLE_FAST_H
#define __LINUX_IO_PGTABLE_FAST_H
+#include <linux/notifier.h>
+
typedef u64 av8l_fast_iopte;
#define iopte_pmd_offset(pmds, iova) (pmds + (iova >> 12))
@@ -21,4 +23,35 @@ int av8l_fast_map_public(av8l_fast_iopte *ptep, phys_addr_t paddr, size_t size,
int prot);
void av8l_fast_unmap_public(av8l_fast_iopte *ptep, size_t size);
+/* events for notifiers passed to av8l_register_notify */
+#define MAPPED_OVER_STALE_TLB 1
+
+
+#ifdef CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB
+/*
+ * Doesn't matter what we use as long as bit 0 is unset. The reason why we
+ * need a different value at all is that there are certain hardware
+ * platforms with erratum that require that a PTE actually be zero'd out
+ * and not just have its valid bit unset.
+ */
+#define AV8L_FAST_PTE_UNMAPPED_NEED_TLBI 0xa
+
+void av8l_fast_clear_stale_ptes(av8l_fast_iopte *puds, bool skip_sync);
+void av8l_register_notify(struct notifier_block *nb);
+
+#else /* !CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB */
+
+#define AV8L_FAST_PTE_UNMAPPED_NEED_TLBI 0
+
+static inline void av8l_fast_clear_stale_ptes(av8l_fast_iopte *puds,
+ bool skip_sync)
+{
+}
+
+static inline void av8l_register_notify(struct notifier_block *nb)
+{
+}
+
+#endif /* CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB */
+
#endif /* __LINUX_IO_PGTABLE_FAST_H */