1 /* 2 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 * Licensed under the GPL 4 */ 5 6 #include <linux/mm.h> 7 #include <linux/sched.h> 8 #include <linux/hardirq.h> 9 #include <asm/current.h> 10 #include <asm/pgtable.h> 11 #include <asm/tlbflush.h> 12 #include "arch.h" 13 #include "as-layout.h" 14 #include "kern_util.h" 15 #include "os.h" 16 #include "sysdep/sigcontext.h" 17 18 /* 19 * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by 20 * segv(). 21 */ 22 int handle_page_fault(unsigned long address, unsigned long ip, 23 int is_write, int is_user, int *code_out) 24 { 25 struct mm_struct *mm = current->mm; 26 struct vm_area_struct *vma; 27 pgd_t *pgd; 28 pud_t *pud; 29 pmd_t *pmd; 30 pte_t *pte; 31 int err = -EFAULT; 32 33 *code_out = SEGV_MAPERR; 34 35 /* 36 * If the fault was during atomic operation, don't take the fault, just 37 * fail. 38 */ 39 if (in_atomic()) 40 goto out_nosemaphore; 41 42 down_read(&mm->mmap_sem); 43 vma = find_vma(mm, address); 44 if (!vma) 45 goto out; 46 else if (vma->vm_start <= address) 47 goto good_area; 48 else if (!(vma->vm_flags & VM_GROWSDOWN)) 49 goto out; 50 else if (is_user && !ARCH_IS_STACKGROW(address)) 51 goto out; 52 else if (expand_stack(vma, address)) 53 goto out; 54 55 good_area: 56 *code_out = SEGV_ACCERR; 57 if (is_write && !(vma->vm_flags & VM_WRITE)) 58 goto out; 59 60 /* Don't require VM_READ|VM_EXEC for write faults! */ 61 if (!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) 62 goto out; 63 64 do { 65 int fault; 66 survive: 67 fault = handle_mm_fault(mm, vma, address, is_write); 68 if (unlikely(fault & VM_FAULT_ERROR)) { 69 if (fault & VM_FAULT_OOM) { 70 err = -ENOMEM; 71 goto out_of_memory; 72 } else if (fault & VM_FAULT_SIGBUS) { 73 err = -EACCES; 74 goto out; 75 } 76 BUG(); 77 } 78 if (fault & VM_FAULT_MAJOR) 79 current->maj_flt++; 80 else 81 current->min_flt++; 82 83 pgd = pgd_offset(mm, address); 84 pud = pud_offset(pgd, address); 85 pmd = pmd_offset(pud, address); 86 pte = pte_offset_kernel(pmd, address); 87 } while (!pte_present(*pte)); 88 err = 0; 89 /* 90 * The below warning was added in place of 91 * pte_mkyoung(); if (is_write) pte_mkdirty(); 92 * If it's triggered, we'd see normally a hang here (a clean pte is 93 * marked read-only to emulate the dirty bit). 94 * However, the generic code can mark a PTE writable but clean on a 95 * concurrent read fault, triggering this harmlessly. So comment it out. 96 */ 97 #if 0 98 WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); 99 #endif 100 flush_tlb_page(vma, address); 101 out: 102 up_read(&mm->mmap_sem); 103 out_nosemaphore: 104 return err; 105 106 /* 107 * We ran out of memory, or some other thing happened to us that made 108 * us unable to handle the page fault gracefully. 109 */ 110 out_of_memory: 111 if (is_global_init(current)) { 112 up_read(&mm->mmap_sem); 113 yield(); 114 down_read(&mm->mmap_sem); 115 goto survive; 116 } 117 goto out; 118 } 119 120 static void bad_segv(struct faultinfo fi, unsigned long ip) 121 { 122 struct siginfo si; 123 124 si.si_signo = SIGSEGV; 125 si.si_code = SEGV_ACCERR; 126 si.si_addr = (void __user *) FAULT_ADDRESS(fi); 127 current->thread.arch.faultinfo = fi; 128 force_sig_info(SIGSEGV, &si, current); 129 } 130 131 static void segv_handler(int sig, struct uml_pt_regs *regs) 132 { 133 struct faultinfo * fi = UPT_FAULTINFO(regs); 134 135 if (UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)) { 136 bad_segv(*fi, UPT_IP(regs)); 137 return; 138 } 139 segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs); 140 } 141 142 /* 143 * We give a *copy* of the faultinfo in the regs to segv. 144 * This must be done, since nesting SEGVs could overwrite 145 * the info in the regs. A pointer to the info then would 146 * give us bad data! 147 */ 148 unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, 149 struct uml_pt_regs *regs) 150 { 151 struct siginfo si; 152 jmp_buf *catcher; 153 int err; 154 int is_write = FAULT_WRITE(fi); 155 unsigned long address = FAULT_ADDRESS(fi); 156 157 if (!is_user && (address >= start_vm) && (address < end_vm)) { 158 flush_tlb_kernel_vm(); 159 return 0; 160 } 161 else if (current->mm == NULL) { 162 show_regs(container_of(regs, struct pt_regs, regs)); 163 panic("Segfault with no mm"); 164 } 165 166 if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) 167 err = handle_page_fault(address, ip, is_write, is_user, 168 &si.si_code); 169 else { 170 err = -EFAULT; 171 /* 172 * A thread accessed NULL, we get a fault, but CR2 is invalid. 173 * This code is used in __do_copy_from_user() of TT mode. 174 * XXX tt mode is gone, so maybe this isn't needed any more 175 */ 176 address = 0; 177 } 178 179 catcher = current->thread.fault_catcher; 180 if (!err) 181 return 0; 182 else if (catcher != NULL) { 183 current->thread.fault_addr = (void *) address; 184 UML_LONGJMP(catcher, 1); 185 } 186 else if (current->thread.fault_addr != NULL) 187 panic("fault_addr set but no fault catcher"); 188 else if (!is_user && arch_fixup(ip, regs)) 189 return 0; 190 191 if (!is_user) { 192 show_regs(container_of(regs, struct pt_regs, regs)); 193 panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", 194 address, ip); 195 } 196 197 if (err == -EACCES) { 198 si.si_signo = SIGBUS; 199 si.si_errno = 0; 200 si.si_code = BUS_ADRERR; 201 si.si_addr = (void __user *)address; 202 current->thread.arch.faultinfo = fi; 203 force_sig_info(SIGBUS, &si, current); 204 } else if (err == -ENOMEM) { 205 printk(KERN_INFO "VM: killing process %s\n", current->comm); 206 do_exit(SIGKILL); 207 } else { 208 BUG_ON(err != -EFAULT); 209 si.si_signo = SIGSEGV; 210 si.si_addr = (void __user *) address; 211 current->thread.arch.faultinfo = fi; 212 force_sig_info(SIGSEGV, &si, current); 213 } 214 return 0; 215 } 216 217 void relay_signal(int sig, struct uml_pt_regs *regs) 218 { 219 if (arch_handle_signal(sig, regs)) 220 return; 221 222 if (!UPT_IS_USER(regs)) { 223 if (sig == SIGBUS) 224 printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " 225 "mount likely just ran out of space\n"); 226 panic("Kernel mode signal %d", sig); 227 } 228 229 current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); 230 force_sig(sig, current); 231 } 232 233 static void bus_handler(int sig, struct uml_pt_regs *regs) 234 { 235 if (current->thread.fault_catcher != NULL) 236 UML_LONGJMP(current->thread.fault_catcher, 1); 237 else relay_signal(sig, regs); 238 } 239 240 static void winch(int sig, struct uml_pt_regs *regs) 241 { 242 do_IRQ(WINCH_IRQ, regs); 243 } 244 245 const struct kern_handlers handlinfo_kern = { 246 .relay_signal = relay_signal, 247 .winch = winch, 248 .bus_handler = bus_handler, 249 .page_fault = segv_handler, 250 .sigio_handler = sigio_handler, 251 .timer_handler = timer_handler 252 }; 253 254 void trap_init(void) 255 { 256 } 257