diff options
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/kernel/trap_kern.c | 28 |
1 files changed, 13 insertions, 15 deletions
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index bef8abd5ea9e..b5fc89fe9eab 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(). */ | ||
29 | int handle_page_fault(unsigned long address, unsigned long ip, | 30 | int 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: | 55 | good_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: | 64 | survive: |
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: | 90 | out: |
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; |