diff options
author | Stuart Menefy <stuart.menefy@st.com> | 2006-11-21 01:38:05 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2006-12-05 20:45:38 -0500 |
commit | 99a596f93be10001c50894bcab69e458a49a3b8c (patch) | |
tree | 16faf593cc3f7a2c39f3079f0f64f410e530e1c4 /arch/sh/mm/fault.c | |
parent | 6e4662ff49c6b94e16a47bfddb920576963b5a20 (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.c | 40 |
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: | |||
109 | bad_area: | 148 | bad_area: |
110 | up_read(&mm->mmap_sem); | 149 | up_read(&mm->mmap_sem); |
111 | 150 | ||
151 | bad_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; |