aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mm/fault.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/mm/fault.c')
-rw-r--r--arch/mips/mm/fault.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index ec8077c74e9c..2d9624fd10ec 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -25,6 +25,7 @@
25#include <asm/system.h> 25#include <asm/system.h>
26#include <asm/uaccess.h> 26#include <asm/uaccess.h>
27#include <asm/ptrace.h> 27#include <asm/ptrace.h>
28#include <asm/highmem.h> /* For VMALLOC_END */
28 29
29/* 30/*
30 * This routine handles page faults. It determines the address, 31 * This routine handles page faults. It determines the address,
@@ -57,7 +58,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
57 * only copy the information from the master page table, 58 * only copy the information from the master page table,
58 * nothing more. 59 * nothing more.
59 */ 60 */
60 if (unlikely(address >= VMALLOC_START)) 61 if (unlikely(address >= VMALLOC_START && address <= VMALLOC_END))
61 goto vmalloc_fault; 62 goto vmalloc_fault;
62 63
63 /* 64 /*
@@ -140,7 +141,7 @@ bad_area_nosemaphore:
140 info.si_signo = SIGSEGV; 141 info.si_signo = SIGSEGV;
141 info.si_errno = 0; 142 info.si_errno = 0;
142 /* info.si_code has been set above */ 143 /* info.si_code has been set above */
143 info.si_addr = (void *) address; 144 info.si_addr = (void __user *) address;
144 force_sig_info(SIGSEGV, &info, tsk); 145 force_sig_info(SIGSEGV, &info, tsk);
145 return; 146 return;
146 } 147 }
@@ -196,7 +197,7 @@ do_sigbus:
196 info.si_signo = SIGBUS; 197 info.si_signo = SIGBUS;
197 info.si_errno = 0; 198 info.si_errno = 0;
198 info.si_code = BUS_ADRERR; 199 info.si_code = BUS_ADRERR;
199 info.si_addr = (void *) address; 200 info.si_addr = (void __user *) address;
200 force_sig_info(SIGBUS, &info, tsk); 201 force_sig_info(SIGBUS, &info, tsk);
201 202
202 return; 203 return;
@@ -212,6 +213,7 @@ vmalloc_fault:
212 */ 213 */
213 int offset = __pgd_offset(address); 214 int offset = __pgd_offset(address);
214 pgd_t *pgd, *pgd_k; 215 pgd_t *pgd, *pgd_k;
216 pud_t *pud, *pud_k;
215 pmd_t *pmd, *pmd_k; 217 pmd_t *pmd, *pmd_k;
216 pte_t *pte_k; 218 pte_t *pte_k;
217 219
@@ -222,8 +224,13 @@ vmalloc_fault:
222 goto no_context; 224 goto no_context;
223 set_pgd(pgd, *pgd_k); 225 set_pgd(pgd, *pgd_k);
224 226
225 pmd = pmd_offset(pgd, address); 227 pud = pud_offset(pgd, address);
226 pmd_k = pmd_offset(pgd_k, address); 228 pud_k = pud_offset(pgd_k, address);
229 if (!pud_present(*pud_k))
230 goto no_context;
231
232 pmd = pmd_offset(pud, address);
233 pmd_k = pmd_offset(pud_k, address);
227 if (!pmd_present(*pmd_k)) 234 if (!pmd_present(*pmd_k))
228 goto no_context; 235 goto no_context;
229 set_pmd(pmd, *pmd_k); 236 set_pmd(pmd, *pmd_k);