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
nexedi
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 @@
#
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
...
...
arch/arm/mm/fault-armv.c
View file @
de837a59
...
...
@@ -10,124 +10,15 @@
*/
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mm.h>
#include <linux/bitops.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <asm/cacheflush.h>
#include <asm/io.h>
#include <asm/pgtable.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
;
/*
...
...
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
* 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
* it under the terms of the GNU General Public License version 2 as
...
...
@@ -11,11 +11,8 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <asm/system.h>
...
...
@@ -25,20 +22,6 @@
#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
* 'addr' in mm 'mm'.
...
...
@@ -186,10 +169,10 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
* memory access, so we can handle it.
*/
good_area:
if
(
READ_FAULT
(
fsr
))
/* read? */
mask
=
VM_READ
|
VM_EXEC
;
else
if
(
fsr
&
(
1
<<
11
))
/* write? */
mask
=
VM_WRITE
;
else
mask
=
VM_READ
|
VM_EXEC
;
fault
=
VM_FAULT_BADACCESS
;
if
(
!
(
vma
->
vm_flags
&
mask
))
...
...
@@ -201,7 +184,7 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
* than endlessly redo the fault.
*/
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
...
...
@@ -233,7 +216,8 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
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
mm_struct
*
mm
;
...
...
@@ -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
* from the master page table, nothing more.
*/
int
do_translation_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
static
int
do_translation_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
struct
task_struct
*
tsk
;
unsigned
int
index
;
...
...
@@ -372,3 +357,108 @@ int do_translation_fault(unsigned long addr, unsigned int fsr,
do_bad_area
(
tsk
,
tsk
->
active_mm
,
addr
,
fsr
,
regs
);
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,
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
);
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