Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
de837a59
Commit
de837a59
authored
Apr 29, 2004
by
Russell King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[ARM] Move all page fault handling code to fault.c
parent
4b72375d
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
117 additions
and
140 deletions
+117
-140
arch/arm/mm/Makefile
arch/arm/mm/Makefile
+1
-1
arch/arm/mm/fault-armv.c
arch/arm/mm/fault-armv.c
+0
-109
arch/arm/mm/fault.c
arch/arm/mm/fault.c
+116
-26
arch/arm/mm/fault.h
arch/arm/mm/fault.h
+0
-4
No files found.
arch/arm/mm/Makefile
View file @
de837a59
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
#
#
obj-y
:=
consistent.o extable.o fault-armv.o
\
obj-y
:=
consistent.o extable.o fault-armv.o
\
fault
-common
.o init.o ioremap.o mmap.o mm-armv.o
fault.o init.o ioremap.o mmap.o mm-armv.o
obj-$(CONFIG_MODULES)
+=
proc-syms.o
obj-$(CONFIG_MODULES)
+=
proc-syms.o
...
...
arch/arm/mm/fault-armv.c
View file @
de837a59
...
@@ -10,124 +10,15 @@
...
@@ -10,124 +10,15 @@
*/
*/
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/bitops.h>
#include <linux/bitops.h>
#include <linux/vmalloc.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/init.h>
#include <asm/cacheflush.h>
#include <asm/cacheflush.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/tlbflush.h>
#include "fault.h"
/*
* Some section permission faults need to be handled gracefully.
* They can happen due to a __{get,put}_user during an oops.
*/
static
int
do_sect_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
struct
task_struct
*
tsk
=
current
;
do_bad_area
(
tsk
,
tsk
->
active_mm
,
addr
,
fsr
,
regs
);
return
0
;
}
/*
* This abort handler always returns "fault".
*/
static
int
do_bad
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
return
1
;
}
static
struct
fsr_info
{
int
(
*
fn
)(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
);
int
sig
;
const
char
*
name
;
}
fsr_info
[]
=
{
/*
* The following are the standard ARMv3 and ARMv4 aborts. ARMv5
* defines these to be "precise" aborts.
*/
{
do_bad
,
SIGSEGV
,
"vector exception"
},
{
do_bad
,
SIGILL
,
"alignment exception"
},
{
do_bad
,
SIGKILL
,
"terminal exception"
},
{
do_bad
,
SIGILL
,
"alignment exception"
},
{
do_bad
,
SIGBUS
,
"external abort on linefetch"
},
{
do_translation_fault
,
SIGSEGV
,
"section translation fault"
},
{
do_bad
,
SIGBUS
,
"external abort on linefetch"
},
{
do_page_fault
,
SIGSEGV
,
"page translation fault"
},
{
do_bad
,
SIGBUS
,
"external abort on non-linefetch"
},
{
do_bad
,
SIGSEGV
,
"section domain fault"
},
{
do_bad
,
SIGBUS
,
"external abort on non-linefetch"
},
{
do_bad
,
SIGSEGV
,
"page domain fault"
},
{
do_bad
,
SIGBUS
,
"external abort on translation"
},
{
do_sect_fault
,
SIGSEGV
,
"section permission fault"
},
{
do_bad
,
SIGBUS
,
"external abort on translation"
},
{
do_page_fault
,
SIGSEGV
,
"page permission fault"
},
/*
* The following are "imprecise" aborts, which are signalled by bit
* 10 of the FSR, and may not be recoverable. These are only
* supported if the CPU abort handler supports bit 10.
*/
{
do_bad
,
SIGBUS
,
"unknown 16"
},
{
do_bad
,
SIGBUS
,
"unknown 17"
},
{
do_bad
,
SIGBUS
,
"unknown 18"
},
{
do_bad
,
SIGBUS
,
"unknown 19"
},
{
do_bad
,
SIGBUS
,
"lock abort"
},
/* xscale */
{
do_bad
,
SIGBUS
,
"unknown 21"
},
{
do_bad
,
SIGBUS
,
"imprecise external abort"
},
/* xscale */
{
do_bad
,
SIGBUS
,
"unknown 23"
},
{
do_bad
,
SIGBUS
,
"dcache parity error"
},
/* xscale */
{
do_bad
,
SIGBUS
,
"unknown 25"
},
{
do_bad
,
SIGBUS
,
"unknown 26"
},
{
do_bad
,
SIGBUS
,
"unknown 27"
},
{
do_bad
,
SIGBUS
,
"unknown 28"
},
{
do_bad
,
SIGBUS
,
"unknown 29"
},
{
do_bad
,
SIGBUS
,
"unknown 30"
},
{
do_bad
,
SIGBUS
,
"unknown 31"
}
};
void
__init
hook_fault_code
(
int
nr
,
int
(
*
fn
)(
unsigned
long
,
unsigned
int
,
struct
pt_regs
*
),
int
sig
,
const
char
*
name
)
{
if
(
nr
>=
0
&&
nr
<
ARRAY_SIZE
(
fsr_info
))
{
fsr_info
[
nr
].
fn
=
fn
;
fsr_info
[
nr
].
sig
=
sig
;
fsr_info
[
nr
].
name
=
name
;
}
}
/*
* Dispatch a data abort to the relevant handler.
*/
asmlinkage
void
do_DataAbort
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
const
struct
fsr_info
*
inf
=
fsr_info
+
(
fsr
&
15
)
+
((
fsr
&
(
1
<<
10
))
>>
6
);
if
(
!
inf
->
fn
(
addr
,
fsr
,
regs
))
return
;
printk
(
KERN_ALERT
"Unhandled fault: %s (0x%03x) at 0x%08lx
\n
"
,
inf
->
name
,
fsr
,
addr
);
force_sig
(
inf
->
sig
,
current
);
show_pte
(
current
->
mm
,
addr
);
die_if_kernel
(
"Oops"
,
regs
,
0
);
}
asmlinkage
void
do_PrefetchAbort
(
unsigned
long
addr
,
struct
pt_regs
*
regs
)
{
do_translation_fault
(
addr
,
0
,
regs
);
}
static
unsigned
long
shared_pte_mask
=
L_PTE_CACHEABLE
;
static
unsigned
long
shared_pte_mask
=
L_PTE_CACHEABLE
;
/*
/*
...
...
arch/arm/mm/fault
-common
.c
→
arch/arm/mm/fault.c
View file @
de837a59
/*
/*
* linux/arch/arm/mm/fault
-common
.c
* linux/arch/arm/mm/fault.c
*
*
* Copyright (C) 1995 Linus Torvalds
* Copyright (C) 1995 Linus Torvalds
* Modifications for ARM processor (c) 1995-200
1
Russell King
* Modifications for ARM processor (c) 1995-200
4
Russell King
*
*
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* it under the terms of the GNU General Public License version 2 as
...
@@ -11,11 +11,8 @@
...
@@ -11,11 +11,8 @@
#include <linux/config.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/ptrace.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/system.h>
...
@@ -25,20 +22,6 @@
...
@@ -25,20 +22,6 @@
#include "fault.h"
#include "fault.h"
#ifdef CONFIG_CPU_26
#define FAULT_CODE_WRITE 0x02
#define FAULT_CODE_FORCECOW 0x01
#define DO_COW(m) ((m) & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW))
#define READ_FAULT(m) (!((m) & FAULT_CODE_WRITE))
#else
/*
* "code" is actually the FSR register. Bit 11 set means the
* instruction was performing a write.
*/
#define DO_COW(code) ((code) & (1 << 11))
#define READ_FAULT(code) (!DO_COW(code))
#endif
/*
/*
* This is useful to dump out the page tables associated with
* This is useful to dump out the page tables associated with
* 'addr' in mm 'mm'.
* 'addr' in mm 'mm'.
...
@@ -186,10 +169,10 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
...
@@ -186,10 +169,10 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
* memory access, so we can handle it.
* memory access, so we can handle it.
*/
*/
good_area:
good_area:
if
(
READ_FAULT
(
fsr
))
/* read? */
if
(
fsr
&
(
1
<<
11
))
/* write? */
mask
=
VM_READ
|
VM_EXEC
;
else
mask
=
VM_WRITE
;
mask
=
VM_WRITE
;
else
mask
=
VM_READ
|
VM_EXEC
;
fault
=
VM_FAULT_BADACCESS
;
fault
=
VM_FAULT_BADACCESS
;
if
(
!
(
vma
->
vm_flags
&
mask
))
if
(
!
(
vma
->
vm_flags
&
mask
))
...
@@ -201,7 +184,7 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
...
@@ -201,7 +184,7 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
* than endlessly redo the fault.
* than endlessly redo the fault.
*/
*/
survive:
survive:
fault
=
handle_mm_fault
(
mm
,
vma
,
addr
&
PAGE_MASK
,
DO_COW
(
fsr
));
fault
=
handle_mm_fault
(
mm
,
vma
,
addr
&
PAGE_MASK
,
fsr
&
(
1
<<
11
));
/*
/*
* Handle the "normal" cases first - successful and sigbus
* Handle the "normal" cases first - successful and sigbus
...
@@ -233,7 +216,8 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
...
@@ -233,7 +216,8 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
return
fault
;
return
fault
;
}
}
int
do_page_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
static
int
do_page_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
{
struct
task_struct
*
tsk
;
struct
task_struct
*
tsk
;
struct
mm_struct
*
mm
;
struct
mm_struct
*
mm
;
...
@@ -332,8 +316,9 @@ int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
...
@@ -332,8 +316,9 @@ int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
* interrupt or a critical region, and should only copy the information
* interrupt or a critical region, and should only copy the information
* from the master page table, nothing more.
* from the master page table, nothing more.
*/
*/
int
do_translation_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
static
int
struct
pt_regs
*
regs
)
do_translation_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
{
struct
task_struct
*
tsk
;
struct
task_struct
*
tsk
;
unsigned
int
index
;
unsigned
int
index
;
...
@@ -372,3 +357,108 @@ int do_translation_fault(unsigned long addr, unsigned int fsr,
...
@@ -372,3 +357,108 @@ int do_translation_fault(unsigned long addr, unsigned int fsr,
do_bad_area
(
tsk
,
tsk
->
active_mm
,
addr
,
fsr
,
regs
);
do_bad_area
(
tsk
,
tsk
->
active_mm
,
addr
,
fsr
,
regs
);
return
0
;
return
0
;
}
}
/*
* Some section permission faults need to be handled gracefully.
* They can happen due to a __{get,put}_user during an oops.
*/
static
int
do_sect_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
struct
task_struct
*
tsk
=
current
;
do_bad_area
(
tsk
,
tsk
->
active_mm
,
addr
,
fsr
,
regs
);
return
0
;
}
/*
* This abort handler always returns "fault".
*/
static
int
do_bad
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
return
1
;
}
static
struct
fsr_info
{
int
(
*
fn
)(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
);
int
sig
;
const
char
*
name
;
}
fsr_info
[]
=
{
/*
* The following are the standard ARMv3 and ARMv4 aborts. ARMv5
* defines these to be "precise" aborts.
*/
{
do_bad
,
SIGSEGV
,
"vector exception"
},
{
do_bad
,
SIGILL
,
"alignment exception"
},
{
do_bad
,
SIGKILL
,
"terminal exception"
},
{
do_bad
,
SIGILL
,
"alignment exception"
},
{
do_bad
,
SIGBUS
,
"external abort on linefetch"
},
{
do_translation_fault
,
SIGSEGV
,
"section translation fault"
},
{
do_bad
,
SIGBUS
,
"external abort on linefetch"
},
{
do_page_fault
,
SIGSEGV
,
"page translation fault"
},
{
do_bad
,
SIGBUS
,
"external abort on non-linefetch"
},
{
do_bad
,
SIGSEGV
,
"section domain fault"
},
{
do_bad
,
SIGBUS
,
"external abort on non-linefetch"
},
{
do_bad
,
SIGSEGV
,
"page domain fault"
},
{
do_bad
,
SIGBUS
,
"external abort on translation"
},
{
do_sect_fault
,
SIGSEGV
,
"section permission fault"
},
{
do_bad
,
SIGBUS
,
"external abort on translation"
},
{
do_page_fault
,
SIGSEGV
,
"page permission fault"
},
/*
* The following are "imprecise" aborts, which are signalled by bit
* 10 of the FSR, and may not be recoverable. These are only
* supported if the CPU abort handler supports bit 10.
*/
{
do_bad
,
SIGBUS
,
"unknown 16"
},
{
do_bad
,
SIGBUS
,
"unknown 17"
},
{
do_bad
,
SIGBUS
,
"unknown 18"
},
{
do_bad
,
SIGBUS
,
"unknown 19"
},
{
do_bad
,
SIGBUS
,
"lock abort"
},
/* xscale */
{
do_bad
,
SIGBUS
,
"unknown 21"
},
{
do_bad
,
SIGBUS
,
"imprecise external abort"
},
/* xscale */
{
do_bad
,
SIGBUS
,
"unknown 23"
},
{
do_bad
,
SIGBUS
,
"dcache parity error"
},
/* xscale */
{
do_bad
,
SIGBUS
,
"unknown 25"
},
{
do_bad
,
SIGBUS
,
"unknown 26"
},
{
do_bad
,
SIGBUS
,
"unknown 27"
},
{
do_bad
,
SIGBUS
,
"unknown 28"
},
{
do_bad
,
SIGBUS
,
"unknown 29"
},
{
do_bad
,
SIGBUS
,
"unknown 30"
},
{
do_bad
,
SIGBUS
,
"unknown 31"
}
};
void
__init
hook_fault_code
(
int
nr
,
int
(
*
fn
)(
unsigned
long
,
unsigned
int
,
struct
pt_regs
*
),
int
sig
,
const
char
*
name
)
{
if
(
nr
>=
0
&&
nr
<
ARRAY_SIZE
(
fsr_info
))
{
fsr_info
[
nr
].
fn
=
fn
;
fsr_info
[
nr
].
sig
=
sig
;
fsr_info
[
nr
].
name
=
name
;
}
}
/*
* Dispatch a data abort to the relevant handler.
*/
asmlinkage
void
do_DataAbort
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
const
struct
fsr_info
*
inf
=
fsr_info
+
(
fsr
&
15
)
+
((
fsr
&
(
1
<<
10
))
>>
6
);
if
(
!
inf
->
fn
(
addr
,
fsr
,
regs
))
return
;
printk
(
KERN_ALERT
"Unhandled fault: %s (0x%03x) at 0x%08lx
\n
"
,
inf
->
name
,
fsr
,
addr
);
force_sig
(
inf
->
sig
,
current
);
show_pte
(
current
->
mm
,
addr
);
die_if_kernel
(
"Oops"
,
regs
,
0
);
}
asmlinkage
void
do_PrefetchAbort
(
unsigned
long
addr
,
struct
pt_regs
*
regs
)
{
do_translation_fault
(
addr
,
0
,
regs
);
}
arch/arm/mm/fault.h
View file @
de837a59
...
@@ -3,8 +3,4 @@ void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
...
@@ -3,8 +3,4 @@ void do_bad_area(struct task_struct *tsk, struct mm_struct *mm,
void
show_pte
(
struct
mm_struct
*
mm
,
unsigned
long
addr
);
void
show_pte
(
struct
mm_struct
*
mm
,
unsigned
long
addr
);
int
do_page_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
);
int
do_translation_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
);
unsigned
long
search_exception_table
(
unsigned
long
addr
);
unsigned
long
search_exception_table
(
unsigned
long
addr
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment