aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/kernel/trap_kern.c28
1 files changed, 13 insertions, 15 deletions
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index bef8abd5ea9..b5fc89fe9ea 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -26,6 +26,7 @@
26#include "mem.h" 26#include "mem.h"
27#include "mem_kern.h" 27#include "mem_kern.h"
28 28
29/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
29int handle_page_fault(unsigned long address, unsigned long ip, 30int handle_page_fault(unsigned long address, unsigned long ip,
30 int is_write, int is_user, int *code_out) 31 int is_write, int is_user, int *code_out)
31{ 32{
@@ -35,7 +36,6 @@ int handle_page_fault(unsigned long address, unsigned long ip,
35 pud_t *pud; 36 pud_t *pud;
36 pmd_t *pmd; 37 pmd_t *pmd;
37 pte_t *pte; 38 pte_t *pte;
38 unsigned long page;
39 int err = -EFAULT; 39 int err = -EFAULT;
40 40
41 *code_out = SEGV_MAPERR; 41 *code_out = SEGV_MAPERR;
@@ -52,7 +52,7 @@ int handle_page_fault(unsigned long address, unsigned long ip,
52 else if(expand_stack(vma, address)) 52 else if(expand_stack(vma, address))
53 goto out; 53 goto out;
54 54
55 good_area: 55good_area:
56 *code_out = SEGV_ACCERR; 56 *code_out = SEGV_ACCERR;
57 if(is_write && !(vma->vm_flags & VM_WRITE)) 57 if(is_write && !(vma->vm_flags & VM_WRITE))
58 goto out; 58 goto out;
@@ -60,9 +60,8 @@ int handle_page_fault(unsigned long address, unsigned long ip,
60 if(!(vma->vm_flags & (VM_READ | VM_EXEC))) 60 if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
61 goto out; 61 goto out;
62 62
63 page = address & PAGE_MASK;
64 do { 63 do {
65 survive: 64survive:
66 switch (handle_mm_fault(mm, vma, address, is_write)){ 65 switch (handle_mm_fault(mm, vma, address, is_write)){
67 case VM_FAULT_MINOR: 66 case VM_FAULT_MINOR:
68 current->min_flt++; 67 current->min_flt++;
@@ -79,16 +78,16 @@ int handle_page_fault(unsigned long address, unsigned long ip,
79 default: 78 default:
80 BUG(); 79 BUG();
81 } 80 }
82 pgd = pgd_offset(mm, page); 81 pgd = pgd_offset(mm, address);
83 pud = pud_offset(pgd, page); 82 pud = pud_offset(pgd, address);
84 pmd = pmd_offset(pud, page); 83 pmd = pmd_offset(pud, address);
85 pte = pte_offset_kernel(pmd, page); 84 pte = pte_offset_kernel(pmd, address);
86 } while(!pte_present(*pte)); 85 } while(!pte_present(*pte));
87 err = 0; 86 err = 0;
88 *pte = pte_mkyoung(*pte); 87 *pte = pte_mkyoung(*pte);
89 if(pte_write(*pte)) *pte = pte_mkdirty(*pte); 88 if(pte_write(*pte)) *pte = pte_mkdirty(*pte);
90 flush_tlb_page(vma, page); 89 flush_tlb_page(vma, address);
91 out: 90out:
92 up_read(&mm->mmap_sem); 91 up_read(&mm->mmap_sem);
93 return(err); 92 return(err);
94 93
@@ -144,19 +143,18 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
144 panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", 143 panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
145 address, ip); 144 address, ip);
146 145
147 if(err == -EACCES){ 146 if (err == -EACCES) {
148 si.si_signo = SIGBUS; 147 si.si_signo = SIGBUS;
149 si.si_errno = 0; 148 si.si_errno = 0;
150 si.si_code = BUS_ADRERR; 149 si.si_code = BUS_ADRERR;
151 si.si_addr = (void *)address; 150 si.si_addr = (void *)address;
152 current->thread.arch.faultinfo = fi; 151 current->thread.arch.faultinfo = fi;
153 force_sig_info(SIGBUS, &si, current); 152 force_sig_info(SIGBUS, &si, current);
154 } 153 } else if (err == -ENOMEM) {
155 else if(err == -ENOMEM){
156 printk("VM: killing process %s\n", current->comm); 154 printk("VM: killing process %s\n", current->comm);
157 do_exit(SIGKILL); 155 do_exit(SIGKILL);
158 } 156 } else {
159 else { 157 BUG_ON(err != -EFAULT);
160 si.si_signo = SIGSEGV; 158 si.si_signo = SIGSEGV;
161 si.si_addr = (void *) address; 159 si.si_addr = (void *) address;
162 current->thread.arch.faultinfo = fi; 160 current->thread.arch.faultinfo = fi;