Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/cell/spu_fault.c
10818 views
1
/*
2
* SPU mm fault handler
3
*
4
* (C) Copyright IBM Deutschland Entwicklung GmbH 2007
5
*
6
* Author: Arnd Bergmann <[email protected]>
7
* Author: Jeremy Kerr <[email protected]>
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
*/
35
int 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 (mm == NULL)
43
return -EFAULT;
44
45
if (mm->pgd == NULL)
46
return -EFAULT;
47
48
down_read(&mm->mmap_sem);
49
ret = -EFAULT;
50
vma = find_vma(mm, ea);
51
if (!vma)
52
goto out_unlock;
53
54
if (ea < vma->vm_start) {
55
if (!(vma->vm_flags & VM_GROWSDOWN))
56
goto out_unlock;
57
if (expand_stack(vma, ea))
58
goto out_unlock;
59
}
60
61
is_write = dsisr & MFC_DSISR_ACCESS_PUT;
62
if (is_write) {
63
if (!(vma->vm_flags & VM_WRITE))
64
goto out_unlock;
65
} else {
66
if (dsisr & MFC_DSISR_ACCESS_DENIED)
67
goto out_unlock;
68
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
69
goto out_unlock;
70
}
71
72
ret = 0;
73
*flt = handle_mm_fault(mm, vma, ea, is_write ? FAULT_FLAG_WRITE : 0);
74
if (unlikely(*flt & VM_FAULT_ERROR)) {
75
if (*flt & VM_FAULT_OOM) {
76
ret = -ENOMEM;
77
goto out_unlock;
78
} else if (*flt & VM_FAULT_SIGBUS) {
79
ret = -EFAULT;
80
goto out_unlock;
81
}
82
BUG();
83
}
84
85
if (*flt & VM_FAULT_MAJOR)
86
current->maj_flt++;
87
else
88
current->min_flt++;
89
90
out_unlock:
91
up_read(&mm->mmap_sem);
92
return ret;
93
}
94
EXPORT_SYMBOL_GPL(spu_handle_mm_fault);
95
96