Re: [PATCH v2] MIPS: Remove race window in page fault handling

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 08/08/2014 06:47 AM, Lars Persson wrote:
Multicore MIPSes without I/D hardware coherency suffered from a race
condition in the page fault handler. The page table entry was
published before any pending lazy D-cache flush was committed, hence
it allowed execution of stale page cache data by other VPEs in the
system.

To make the cache handling safe we need to perform flushing already in
the set_pte_at function. MIPSes without coherent I-caches can get a
small increase in flushes due to the unavailability of the execute
flag in set_pte_at.

Signed-off-by: Lars Persson <larper@xxxxxxxx>
---
  arch/mips/include/asm/pgtable.h |   22 +++++++++++++++++-----
  arch/mips/mm/cache.c            |   16 ++++++++--------
  2 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 027c74d..1834298 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -122,6 +122,9 @@ do {									\
  	}								\
  } while(0)

+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+	pte_t *ptep, pte_t pteval);
+

Is it possible to reorder the code such that this declaration is not necessary?


  #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)

  #define pte_none(pte)		(!(((pte).pte_low | (pte).pte_high) & ~_PAGE_GLOBAL))
@@ -145,7 +148,6 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
  		}
  	}
  }
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)

  static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
  {
@@ -183,7 +185,6 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
  	}
  #endif
  }
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)

  static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
  {
@@ -198,6 +199,20 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
  }
  #endif

+extern void mips_flush_dcache_from_pte(pte_t pteval, unsigned long address);
+
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+	pte_t *ptep, pte_t pteval)
+{
+	if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc) {
+		if (pte_present(pteval))
+			mips_flush_dcache_from_pte(pteval, addr);
+	}
+
+	set_pte(ptep, pteval);
+}
+
+

[...]


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux