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 | |
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')
-rw-r--r-- | arch/sh/mm/fault.c | 40 | ||||
-rw-r--r-- | arch/sh/mm/init.c | 26 |
2 files changed, 49 insertions, 17 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; |
diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 8c8d39118387..462bfeac6d9c 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c | |||
@@ -84,30 +84,22 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot) | |||
84 | pmd_t *pmd; | 84 | pmd_t *pmd; |
85 | pte_t *pte; | 85 | pte_t *pte; |
86 | 86 | ||
87 | pgd = swapper_pg_dir + pgd_index(addr); | 87 | pgd = pgd_offset_k(addr); |
88 | if (pgd_none(*pgd)) { | 88 | if (pgd_none(*pgd)) { |
89 | pgd_ERROR(*pgd); | 89 | pgd_ERROR(*pgd); |
90 | return; | 90 | return; |
91 | } | 91 | } |
92 | 92 | ||
93 | pud = pud_offset(pgd, addr); | 93 | pud = pud_alloc(NULL, pgd, addr); |
94 | if (pud_none(*pud)) { | 94 | if (unlikely(!pud)) { |
95 | pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC); | 95 | pud_ERROR(*pud); |
96 | set_pud(pud, __pud(__pa(pmd) | _PAGE_TABLE)); | 96 | return; |
97 | if (pmd != pmd_offset(pud, 0)) { | ||
98 | pud_ERROR(*pud); | ||
99 | return; | ||
100 | } | ||
101 | } | 97 | } |
102 | 98 | ||
103 | pmd = pmd_offset(pud, addr); | 99 | pmd = pmd_alloc(NULL, pud, addr); |
104 | if (pmd_none(*pmd)) { | 100 | if (unlikely(!pmd)) { |
105 | pte = (pte_t *)get_zeroed_page(GFP_ATOMIC); | 101 | pmd_ERROR(*pmd); |
106 | set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE)); | 102 | return; |
107 | if (pte != pte_offset_kernel(pmd, 0)) { | ||
108 | pmd_ERROR(*pmd); | ||
109 | return; | ||
110 | } | ||
111 | } | 103 | } |
112 | 104 | ||
113 | pte = pte_offset_kernel(pmd, addr); | 105 | pte = pte_offset_kernel(pmd, addr); |