diff mbox series

[V4] MIPS: make userspace mapping young by default

Message ID 20201019081257.32127-1-huangpei@loongson.cn (mailing list archive)
State Superseded
Headers show
Series [V4] MIPS: make userspace mapping young by default | expand

Commit Message

Huang Pei Oct. 19, 2020, 8:12 a.m. UTC
MIPS page fault path takes 3 exceptions (1 TLB Miss + 2 TLB Invalid), but
the second TLB Invalid exception is just triggered by __update_tlb from
do_page_fault writing tlb without _PAGE_VALID set. With this patch, user
space mapping prot is made young by default (with both _PAGE_VALID and
_PAGE_YOUNG set), and it only take 1 TLB Miss + 1 TLB Invalid exception

+. remove pte_sw_mkyoung without polluting MM code and make page fault
delay of MIPS on par with other architecture and covers both no-rixi and
rixi MIPS CPUS

+. clean up cpu_has_rixi case in setup_protection_map with PAGE_*_XI,
since only _PAGE_NO_EXEC(eXecute Inhibit) provide additional control
while _PAGE_NO_READ equals _PAGE_READ for no-rixi MIPS CPUs;

[1]: https://lkml.kernel.org/lkml/1591416169-26666-1-git-send-email
-maobibo@loongson.cn/
---
V4:
- clean up cpu_has_rixi case 
V3:
- reformat with whitespace cleaned up following Thomas's advice
V2:
- remove unused asm-generic definition of pte_sw_mkyoung following Mao's
advice
---
---
 arch/mips/include/asm/pgtable.h | 15 ++++++---
 arch/mips/mm/cache.c            | 55 +++++++++++++++++----------------
 include/linux/pgtable.h         |  8 -----
 mm/memory.c                     |  3 --
 4 files changed, 39 insertions(+), 42 deletions(-)
diff mbox series

Patch

diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index e5ef0fdd4838..3712d9d683f1 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -27,11 +27,20 @@  struct vm_area_struct;
 
 #define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_NO_READ | \
 				 _page_cachable_default)
+#define PAGE_NONE_XI	__pgprot(_PAGE_PRESENT | _PAGE_NO_READ | \
+				 _PAGE_NO_EXEC | _page_cachable_default)
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_WRITE | \
-				 _page_cachable_default)
+				 __READABLE | _page_cachable_default)
+#define PAGE_SHARED_XI	__pgprot(_PAGE_PRESENT | _PAGE_WRITE | __READABLE | \
+				 _PAGE_NO_EXEC | _page_cachable_default)
 #define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_NO_EXEC | \
+				 __READABLE | _page_cachable_default)
+#define PAGE_READONLY	__pgprot(_PAGE_PRESENT |  __READABLE | \
 				 _page_cachable_default)
-#define PAGE_READONLY	__pgprot(_PAGE_PRESENT | \
+#define PAGE_READONLY_XI	__pgprot(_PAGE_PRESENT | __READABLE | \
+				 _PAGE_NO_EXEC | _page_cachable_default)
+#define PAGE_WRITEONLY_XI	__pgprot(_PAGE_PRESENT | _PAGE_WRITE | \
+				 _PAGE_NO_EXEC | _PAGE_NO_READ | \
 				 _page_cachable_default)
 #define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
 				 _PAGE_GLOBAL | _page_cachable_default)
@@ -412,8 +421,6 @@  static inline pte_t pte_mkyoung(pte_t pte)
 	return pte;
 }
 
-#define pte_sw_mkyoung	pte_mkyoung
-
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
 static inline int pte_huge(pte_t pte)	{ return pte_val(pte) & _PAGE_HUGE; }
 
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 3e81ba000096..e0488030c76e 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -158,35 +158,36 @@  EXPORT_SYMBOL(_page_cachable_default);
 static inline void setup_protection_map(void)
 {
 	if (cpu_has_rixi) {
-		protection_map[0]  = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
-		protection_map[1]  = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
-		protection_map[2]  = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
-		protection_map[3]  = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
-		protection_map[4]  = __pgprot(_page_cachable_default | _PAGE_PRESENT);
-		protection_map[5]  = __pgprot(_page_cachable_default | _PAGE_PRESENT);
-		protection_map[6]  = __pgprot(_page_cachable_default | _PAGE_PRESENT);
-		protection_map[7]  = __pgprot(_page_cachable_default | _PAGE_PRESENT);
-
-		protection_map[8]  = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
-		protection_map[9]  = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
-		protection_map[10] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE | _PAGE_NO_READ);
-		protection_map[11] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE);
-		protection_map[12] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
-		protection_map[13] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
-		protection_map[14] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_WRITE);
-		protection_map[15] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_WRITE);
+		protection_map[0]  = PAGE_NONE_XI;
+		protection_map[1]  = PAGE_COPY;
+		protection_map[2]  = PAGE_NONE_XI;
+		protection_map[3]  = PAGE_COPY;
+		protection_map[4]  = PAGE_READONLY;
+		protection_map[5]  = PAGE_READONLY;
+		protection_map[6]  = PAGE_READONLY;
+		protection_map[7]  = PAGE_READONLY;
+
+		protection_map[8]  = PAGE_NONE_XI;
+		protection_map[9]  = PAGE_COPY;
+		protection_map[10] = PAGE_WRITEONLY_XI;
+		protection_map[11] = PAGE_SHARED_XI;
+		protection_map[12] = PAGE_READONLY;
+		protection_map[13] = PAGE_READONLY;
+		protection_map[14] = PAGE_READONLY_XI;
+		protection_map[15] = PAGE_READONLY_XI;
+
 
 	} else {
-		protection_map[0] = PAGE_NONE;
-		protection_map[1] = PAGE_READONLY;
-		protection_map[2] = PAGE_COPY;
-		protection_map[3] = PAGE_COPY;
-		protection_map[4] = PAGE_READONLY;
-		protection_map[5] = PAGE_READONLY;
-		protection_map[6] = PAGE_COPY;
-		protection_map[7] = PAGE_COPY;
-		protection_map[8] = PAGE_NONE;
-		protection_map[9] = PAGE_READONLY;
+		protection_map[0]  = PAGE_NONE;
+		protection_map[1]  = PAGE_READONLY;
+		protection_map[2]  = PAGE_COPY;
+		protection_map[3]  = PAGE_COPY;
+		protection_map[4]  = PAGE_READONLY;
+		protection_map[5]  = PAGE_READONLY;
+		protection_map[6]  = PAGE_COPY;
+		protection_map[7]  = PAGE_COPY;
+		protection_map[8]  = PAGE_NONE;
+		protection_map[9]  = PAGE_READONLY;
 		protection_map[10] = PAGE_SHARED;
 		protection_map[11] = PAGE_SHARED;
 		protection_map[12] = PAGE_READONLY;
diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h
index 38c33eabea89..c0326efbaa12 100644
--- a/include/linux/pgtable.h
+++ b/include/linux/pgtable.h
@@ -377,14 +377,6 @@  static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
  * To be differentiate with macro pte_mkyoung, this macro is used on platforms
  * where software maintains page access bit.
  */
-#ifndef pte_sw_mkyoung
-static inline pte_t pte_sw_mkyoung(pte_t pte)
-{
-	return pte;
-}
-#define pte_sw_mkyoung	pte_sw_mkyoung
-#endif
-
 #ifndef pte_savedwrite
 #define pte_savedwrite pte_write
 #endif
diff --git a/mm/memory.c b/mm/memory.c
index 589afe45d0b3..95d85d03b0a2 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2877,7 +2877,6 @@  static vm_fault_t wp_page_copy(struct vm_fault *vmf)
 		}
 		flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte));
 		entry = mk_pte(new_page, vma->vm_page_prot);
-		entry = pte_sw_mkyoung(entry);
 		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
 		/*
 		 * Clear the pte entry and flush it first, before updating the
@@ -3533,7 +3532,6 @@  static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
 	__SetPageUptodate(page);
 
 	entry = mk_pte(page, vma->vm_page_prot);
-	entry = pte_sw_mkyoung(entry);
 	if (vma->vm_flags & VM_WRITE)
 		entry = pte_mkwrite(pte_mkdirty(entry));
 
@@ -3809,7 +3807,6 @@  vm_fault_t alloc_set_pte(struct vm_fault *vmf, struct page *page)
 
 	flush_icache_page(vma, page);
 	entry = mk_pte(page, vma->vm_page_prot);
-	entry = pte_sw_mkyoung(entry);
 	if (write)
 		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
 	/* copy-on-write page */