Re: [PATCH v6 10/36] nds32: MMU fault handling and page table management

2018-01-18 Thread Arnd Bergmann
On Mon, Jan 15, 2018 at 6:53 AM, Greentime Hu  wrote:
> From: Greentime Hu 
>
> This patch includes page fault handler, mmap and fixup implementations.
>
> Signed-off-by: Vincent Chen 
> Signed-off-by: Greentime Hu 

Acked-by: Arnd Bergmann 


[PATCH v6 10/36] nds32: MMU fault handling and page table management

2018-01-14 Thread Greentime Hu
From: Greentime Hu 

This patch includes page fault handler, mmap and fixup implementations.

Signed-off-by: Vincent Chen 
Signed-off-by: Greentime Hu 
---
 arch/nds32/lib/copy_page.S |   37 
 arch/nds32/mm/extable.c|   16 ++
 arch/nds32/mm/fault.c  |  410 
 arch/nds32/mm/mmap.c   |   73 
 4 files changed, 536 insertions(+)
 create mode 100644 arch/nds32/lib/copy_page.S
 create mode 100644 arch/nds32/mm/extable.c
 create mode 100644 arch/nds32/mm/fault.c
 create mode 100644 arch/nds32/mm/mmap.c

diff --git a/arch/nds32/lib/copy_page.S b/arch/nds32/lib/copy_page.S
new file mode 100644
index 000..4a2ff85
--- /dev/null
+++ b/arch/nds32/lib/copy_page.S
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2017 Andes Technology Corporation
+
+#include 
+#include 
+
+   .text
+ENTRY(copy_page)
+   pushm   $r2, $r10
+   movi$r2, PAGE_SIZE >> 5
+.Lcopy_loop:
+   lmw.bim $r3, [$r1], $r10
+   smw.bim $r3, [$r0], $r10
+   subi45  $r2, #1
+   bnez38  $r2, .Lcopy_loop
+   popm$r2, $r10
+   ret
+ENDPROC(copy_page)
+
+ENTRY(clear_page)
+   pushm   $r1, $r9
+   movi$r1, PAGE_SIZE >> 5
+   movi55  $r2, #0
+   movi55  $r3, #0
+   movi55  $r4, #0
+   movi55  $r5, #0
+   movi55  $r6, #0
+   movi55  $r7, #0
+   movi55  $r8, #0
+   movi55  $r9, #0
+.Lclear_loop:
+   smw.bim $r2, [$r0], $r9
+   subi45  $r1, #1
+   bnez38  $r1, .Lclear_loop
+   popm$r1, $r9
+ret
+ENDPROC(clear_page)
diff --git a/arch/nds32/mm/extable.c b/arch/nds32/mm/extable.c
new file mode 100644
index 000..db7f0a7
--- /dev/null
+++ b/arch/nds32/mm/extable.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2017 Andes Technology Corporation
+
+#include 
+#include 
+
+int fixup_exception(struct pt_regs *regs)
+{
+   const struct exception_table_entry *fixup;
+
+   fixup = search_exception_tables(instruction_pointer(regs));
+   if (fixup)
+   regs->ipc = fixup->fixup;
+
+   return fixup != NULL;
+}
diff --git a/arch/nds32/mm/fault.c b/arch/nds32/mm/fault.c
new file mode 100644
index 000..3a246fb
--- /dev/null
+++ b/arch/nds32/mm/fault.c
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2005-2017 Andes Technology Corporation
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+extern void die(const char *str, struct pt_regs *regs, long err);
+
+/*
+ * This is useful to dump out the page tables associated with
+ * 'addr' in mm 'mm'.
+ */
+void show_pte(struct mm_struct *mm, unsigned long addr)
+{
+   pgd_t *pgd;
+   if (!mm)
+   mm = _mm;
+
+   pr_alert("pgd = %p\n", mm->pgd);
+   pgd = pgd_offset(mm, addr);
+   pr_alert("[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
+
+   do {
+   pmd_t *pmd;
+
+   if (pgd_none(*pgd))
+   break;
+
+   if (pgd_bad(*pgd)) {
+   pr_alert("(bad)");
+   break;
+   }
+
+   pmd = pmd_offset(pgd, addr);
+#if PTRS_PER_PMD != 1
+   pr_alert(", *pmd=%08lx", pmd_val(*pmd));
+#endif
+
+   if (pmd_none(*pmd))
+   break;
+
+   if (pmd_bad(*pmd)) {
+   pr_alert("(bad)");
+   break;
+   }
+
+   if (IS_ENABLED(CONFIG_HIGHMEM))
+   {
+   pte_t *pte;
+   /* We must not map this if we have highmem enabled */
+   pte = pte_offset_map(pmd, addr);
+   pr_alert(", *pte=%08lx", pte_val(*pte));
+   pte_unmap(pte);
+   }
+   } while (0);
+
+   pr_alert("\n");
+}
+
+void do_page_fault(unsigned long entry, unsigned long addr,
+  unsigned int error_code, struct pt_regs *regs)
+{
+   struct task_struct *tsk;
+   struct mm_struct *mm;
+   struct vm_area_struct *vma;
+   siginfo_t info;
+   int fault;
+   unsigned int mask = VM_READ | VM_WRITE | VM_EXEC;
+   unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
+
+   error_code = error_code & (ITYPE_mskINST | ITYPE_mskETYPE);
+   tsk = current;
+   mm = tsk->mm;
+   info.si_code = SEGV_MAPERR;
+   /*
+* We fault-in kernel-space virtual memory on-demand. The
+* 'reference' page table is init_mm.pgd.
+*
+* NOTE! We MUST NOT take any locks for this case. We may
+* be in an interrupt or a critical region, and should
+* only copy the information from the master page table,
+* nothing more.
+*/
+   if (addr >= TASK_SIZE) {
+   if