aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm/fault.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/mm/fault.c')
-rw-r--r--arch/sh/mm/fault.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 43bed2cb00e3..128907ef7fcd 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -46,6 +46,45 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
46 mm = tsk->mm; 46 mm = tsk->mm;
47 si_code = SEGV_MAPERR; 47 si_code = SEGV_MAPERR;
48 48
49 if (unlikely(address >= TASK_SIZE)) {
50 /*
51 * Synchronize this task's top level page-table
52 * with the 'reference' page table.
53 *
54 * Do _not_ use "tsk" here. We might be inside
55 * an interrupt in the middle of a task switch..
56 */
57 int offset = pgd_index(address);
58 pgd_t *pgd, *pgd_k;
59 pud_t *pud, *pud_k;
60 pmd_t *pmd, *pmd_k;
61
62 pgd = get_TTB() + offset;
63 pgd_k = swapper_pg_dir + offset;
64
65 /* This will never happen with the folded page table. */
66 if (!pgd_present(*pgd)) {
67 if (!pgd_present(*pgd_k))
68 goto bad_area_nosemaphore;
69 set_pgd(pgd, *pgd_k);
70 return;
71 }
72
73 pud = pud_offset(pgd, address);
74 pud_k = pud_offset(pgd_k, address);
75 if (pud_present(*pud) || !pud_present(*pud_k))
76 goto bad_area_nosemaphore;
77 set_pud(pud, *pud_k);
78
79 pmd = pmd_offset(pud, address);
80 pmd_k = pmd_offset(pud_k, address);
81 if (pmd_present(*pmd) || !pmd_present(*pmd_k))
82 goto bad_area_nosemaphore;
83 set_pmd(pmd, *pmd_k);
84
85 return;
86 }
87
49 /* 88 /*
50 * If we're in an interrupt or have no user 89 * If we're in an interrupt or have no user
51 * context, we must not take the fault.. 90 * context, we must not take the fault..
@@ -109,6 +148,7 @@ survive:
109bad_area: 148bad_area:
110 up_read(&mm->mmap_sem); 149 up_read(&mm->mmap_sem);
111 150
151bad_area_nosemaphore:
112 if (user_mode(regs)) { 152 if (user_mode(regs)) {
113 info.si_signo = SIGSEGV; 153 info.si_signo = SIGSEGV;
114 info.si_errno = 0; 154 info.si_errno = 0;