aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/mm
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
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')
-rw-r--r--arch/sh/mm/fault.c40
-rw-r--r--arch/sh/mm/init.c26
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:
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;
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);