aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm/fault.c
diff options
context:
space:
mode:
authorStuart Menefy <stuart.menefy@st.com>2006-11-21 01:38:05 -0500
committerPaul Mundt <lethal@linux-sh.org>2006-12-05 20:45:38 -0500
commit99a596f93be10001c50894bcab69e458a49a3b8c (patch)
tree16faf593cc3f7a2c39f3079f0f64f410e530e1c4 /arch/sh/mm/fault.c
parent6e4662ff49c6b94e16a47bfddb920576963b5a20 (diff)
sh: pmd rework.
Remove extra bits from the pmd structure and store a kernel logical address rather than a physical address. This allows it to be directly dereferenced. Another piece of wierdness inherited from x86. Signed-off-by: Stuart Menefy <stuart.menefy@st.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
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;