1/* 2 * SPU mm fault handler 3 * 4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2007 5 * 6 * Author: Arnd Bergmann <arndb@de.ibm.com> 7 * Author: Jeremy Kerr <jk@ozlabs.org> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2, or (at your option) 12 * any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 */ 23#include <linux/sched.h> 24#include <linux/mm.h> 25#include <linux/module.h> 26 27#include <asm/spu.h> 28#include <asm/spu_csa.h> 29 30/* 31 * This ought to be kept in sync with the powerpc specific do_page_fault 32 * function. Currently, there are a few corner cases that we haven't had 33 * to handle fortunately. 34 */ 35int spu_handle_mm_fault(struct mm_struct *mm, unsigned long ea, 36 unsigned long dsisr, unsigned *flt) 37{ 38 struct vm_area_struct *vma; 39 unsigned long is_write; 40 int ret; 41 42#if 0 43 if (!IS_VALID_EA(ea)) { 44 return -EFAULT; 45 } 46#endif /* XXX */ 47 if (mm == NULL) { 48 return -EFAULT; 49 } 50 if (mm->pgd == NULL) { 51 return -EFAULT; 52 } 53 54 down_read(&mm->mmap_sem); 55 vma = find_vma(mm, ea); 56 if (!vma) 57 goto bad_area; 58 if (vma->vm_start <= ea) 59 goto good_area; 60 if (!(vma->vm_flags & VM_GROWSDOWN)) 61 goto bad_area; 62 if (expand_stack(vma, ea)) 63 goto bad_area; 64good_area: 65 is_write = dsisr & MFC_DSISR_ACCESS_PUT; 66 if (is_write) { 67 if (!(vma->vm_flags & VM_WRITE)) 68 goto bad_area; 69 } else { 70 if (dsisr & MFC_DSISR_ACCESS_DENIED) 71 goto bad_area; 72 if (!(vma->vm_flags & (VM_READ | VM_EXEC))) 73 goto bad_area; 74 } 75 ret = 0; 76 *flt = handle_mm_fault(mm, vma, ea, is_write); 77 if (unlikely(*flt & VM_FAULT_ERROR)) { 78 if (*flt & VM_FAULT_OOM) { 79 ret = -ENOMEM; 80 goto bad_area; 81 } else if (*flt & VM_FAULT_SIGBUS) { 82 ret = -EFAULT; 83 goto bad_area; 84 } 85 BUG(); 86 } 87 if (*flt & VM_FAULT_MAJOR) 88 current->maj_flt++; 89 else 90 current->min_flt++; 91 up_read(&mm->mmap_sem); 92 return ret; 93 94bad_area: 95 up_read(&mm->mmap_sem); 96 return -EFAULT; 97} 98EXPORT_SYMBOL_GPL(spu_handle_mm_fault); 99

