Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
xenomai
ipipe-arm
Commits
b05a282b
Commit
b05a282b
authored
Dec 03, 2017
by
Philippe Gerum
Browse files
ARM: ipipe: route traps to co-kernel
parent
193e4e70
Changes
6
Hide whitespace changes
Inline
Side-by-side
arch/arm/include/asm/ipipe_base.h
View file @
b05a282b
...
...
@@ -74,6 +74,18 @@ unsigned __ipipe_processor_id(void);
#define IPIPE_TRAP_MAYDAY 0
/* Internal recovery trap */
/* ARM traps */
#define IPIPE_TRAP_ACCESS 1
/* Data or instruction access exception */
#define IPIPE_TRAP_SECTION 2
/* Section fault */
#define IPIPE_TRAP_DABT 3
/* Generic data abort */
#define IPIPE_TRAP_UNKNOWN 4
/* Unknown exception */
#define IPIPE_TRAP_BREAK 5
/* Instruction breakpoint */
#define IPIPE_TRAP_FPU 6
/* Floating point exception */
#define IPIPE_TRAP_VFP 7
/* VFP floating point exception */
#define IPIPE_TRAP_UNDEFINSTR 8
/* Undefined instruction */
#define IPIPE_TRAP_ALIGNMENT 9
/* Unaligned access exception */
#define IPIPE_NR_FAULTS 10
#endif
/* CONFIG_IPIPE */
#endif
/* __ASM_ARM_IPIPE_BASE_H */
arch/arm/kernel/entry-armv.S
View file @
b05a282b
...
...
@@ -286,6 +286,13 @@ __und_svc:
svc_entry
#endif
#ifdef CONFIG_IPIPE
mov
r0
,
#
7
@
r0
=
IPIPE_TRAP_UNDEFINSTR
mov
r1
,
sp
@
r1
=
&
regs
bl
__ipipe_notify_trap
@
branch
to
trap
handler
cmp
r0
,
#
0
bne
__und_svc_finish
#endif /* CONFIG_IPIPE */
@
@
call
emulation
code
,
which
returns
using
r9
if
it
has
emulated
@
the
instruction
,
or
the
more
conventional
lr
if
we
are
to
treat
...
...
@@ -507,6 +514,15 @@ ENDPROC(__irq_usr)
__und_usr
:
usr_entry
uaccess
=
0
#ifdef CONFIG_IPIPE
mov
r0
,
#
7
@
r0
=
IPIPE_TRAP_UNDEFINSTR
mov
r1
,
sp
@
r1
=
&
regs
bl
__ipipe_notify_trap
@
branch
to
trap
handler
cmp
r0
,
#
0
bne
ret_from_exception
uaccess_enable
ip
#endif /* CONFIG_IPIPE */
mov
r2
,
r4
mov
r3
,
r5
...
...
arch/arm/kernel/ptrace.c
View file @
b05a282b
...
...
@@ -216,6 +216,10 @@ void ptrace_break(struct task_struct *tsk, struct pt_regs *regs)
static
int
break_trap
(
struct
pt_regs
*
regs
,
unsigned
int
instr
)
{
if
(
__ipipe_report_trap
(
IPIPE_TRAP_BREAK
,
regs
))
return
0
;
ptrace_break
(
current
,
regs
);
return
0
;
}
...
...
arch/arm/kernel/traps.c
View file @
b05a282b
...
...
@@ -528,6 +528,9 @@ asmlinkage void __exception_irq_entry handle_fiq_as_nmi(struct pt_regs *regs)
*/
asmlinkage
void
bad_mode
(
struct
pt_regs
*
regs
,
int
reason
)
{
if
(
__ipipe_report_trap
(
IPIPE_TRAP_UNKNOWN
,
regs
))
return
;
console_verbose
();
pr_crit
(
"Bad mode in %s handler detected
\n
"
,
handler
[
reason
]);
...
...
arch/arm/mm/alignment.c
View file @
b05a282b
...
...
@@ -14,6 +14,7 @@
#include
<linux/moduleparam.h>
#include
<linux/compiler.h>
#include
<linux/kernel.h>
#include
<linux/ipipe.h>
#include
<linux/sched/debug.h>
#include
<linux/errno.h>
#include
<linux/string.h>
...
...
@@ -781,7 +782,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
int
thumb2_32b
=
0
;
if
(
interrupts_enabled
(
regs
))
local_irq_enable
();
hard_local_irq_enable
();
if
(
__ipipe_report_trap
(
IPIPE_TRAP_ALIGNMENT
,
regs
))
return
0
;
instrptr
=
instruction_pointer
(
regs
);
...
...
@@ -970,7 +974,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
* entry-common.S) and disable the alignment trap only if
* there is no work pending for this thread.
*/
raw
_local_irq_disable
();
hard
_local_irq_disable
();
if
(
!
(
current_thread_info
()
->
flags
&
_TIF_WORK_MASK
))
set_cr
(
cr_no_alignment
);
}
...
...
arch/arm/mm/fault.c
View file @
b05a282b
...
...
@@ -30,6 +30,39 @@
#ifdef CONFIG_MMU
#ifdef CONFIG_IPIPE
static
inline
unsigned
long
ipipe_fault_entry
(
void
)
{
unsigned
long
flags
;
int
s
;
flags
=
hard_local_irq_save
();
s
=
__test_and_set_bit
(
IPIPE_STALL_FLAG
,
&
__ipipe_root_status
);
hard_local_irq_enable
();
return
arch_mangle_irq_bits
(
s
,
flags
);
}
static
inline
void
ipipe_fault_exit
(
unsigned
long
x
)
{
if
(
!
arch_demangle_irq_bits
(
&
x
))
local_irq_enable
();
else
hard_local_irq_restore
(
x
);
}
#else
static
inline
unsigned
long
ipipe_fault_entry
(
void
)
{
return
0
;
}
static
inline
void
ipipe_fault_exit
(
unsigned
long
x
)
{
}
#endif
#ifdef CONFIG_KPROBES
static
inline
int
notify_page_fault
(
struct
pt_regs
*
regs
,
unsigned
int
fsr
)
{
...
...
@@ -267,10 +300,16 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
int
sig
,
code
;
vm_fault_t
fault
;
unsigned
int
flags
=
FAULT_FLAG_ALLOW_RETRY
|
FAULT_FLAG_KILLABLE
;
unsigned
long
irqflags
;
if
(
notify_page_fault
(
regs
,
fsr
))
if
(
__ipipe_report_trap
(
IPIPE_TRAP_ACCESS
,
regs
))
return
0
;
irqflags
=
ipipe_fault_entry
();
if
(
notify_page_fault
(
regs
,
fsr
))
goto
out
;
tsk
=
current
;
mm
=
tsk
->
mm
;
...
...
@@ -323,7 +362,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
if
((
fault
&
VM_FAULT_RETRY
)
&&
fatal_signal_pending
(
current
))
{
if
(
!
user_mode
(
regs
))
goto
no_context
;
return
0
;
goto
out
;
}
/*
...
...
@@ -358,7 +397,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
* Handle the "normal" case first - VM_FAULT_MAJOR
*/
if
(
likely
(
!
(
fault
&
(
VM_FAULT_ERROR
|
VM_FAULT_BADMAP
|
VM_FAULT_BADACCESS
))))
return
0
;
goto
out
;
/*
* If we are in kernel mode at this point, we
...
...
@@ -374,7 +413,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
* got oom-killed)
*/
pagefault_out_of_memory
();
return
0
;
goto
out
;
}
if
(
fault
&
VM_FAULT_SIGBUS
)
{
...
...
@@ -395,10 +434,13 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
}
__do_user_fault
(
tsk
,
addr
,
fsr
,
sig
,
code
,
regs
);
return
0
;
goto
out
;
no_context:
__do_kernel_fault
(
mm
,
addr
,
fsr
,
regs
);
out:
ipipe_fault_exit
(
irqflags
);
return
0
;
}
#else
/* CONFIG_MMU */
...
...
@@ -431,11 +473,14 @@ static int __kprobes
do_translation_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
unsigned
long
irqflags
;
unsigned
int
index
;
pgd_t
*
pgd
,
*
pgd_k
;
pud_t
*
pud
,
*
pud_k
;
pmd_t
*
pmd
,
*
pmd_k
;
IPIPE_BUG_ON
(
!
hard_irqs_disabled
());
if
(
addr
<
TASK_SIZE
)
return
do_page_fault
(
addr
,
fsr
,
regs
);
...
...
@@ -483,10 +528,19 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
goto
bad_area
;
copy_pmd
(
pmd
,
pmd_k
);
return
0
;
bad_area:
if
(
__ipipe_report_trap
(
IPIPE_TRAP_ACCESS
,
regs
))
return
0
;
irqflags
=
ipipe_fault_entry
();
do_bad_area
(
addr
,
fsr
,
regs
);
ipipe_fault_exit
(
irqflags
);
return
0
;
}
#else
/* CONFIG_MMU */
...
...
@@ -506,7 +560,17 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
static
int
do_sect_fault
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
unsigned
long
irqflags
;
if
(
__ipipe_report_trap
(
IPIPE_TRAP_SECTION
,
regs
))
return
0
;
irqflags
=
ipipe_fault_entry
();
do_bad_area
(
addr
,
fsr
,
regs
);
ipipe_fault_exit
(
irqflags
);
return
0
;
}
#endif
/* CONFIG_ARM_LPAE */
...
...
@@ -517,6 +581,9 @@ do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
static
int
do_bad
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
if
(
__ipipe_report_trap
(
IPIPE_TRAP_DABT
,
regs
))
return
0
;
return
1
;
}
...
...
@@ -554,11 +621,17 @@ asmlinkage void
do_DataAbort
(
unsigned
long
addr
,
unsigned
int
fsr
,
struct
pt_regs
*
regs
)
{
const
struct
fsr_info
*
inf
=
fsr_info
+
fsr_fs
(
fsr
);
unsigned
long
irqflags
;
struct
siginfo
info
;
if
(
!
inf
->
fn
(
addr
,
fsr
&
~
FSR_LNX_PF
,
regs
))
return
;
if
(
__ipipe_report_trap
(
IPIPE_TRAP_UNKNOWN
,
regs
))
return
;
irqflags
=
ipipe_fault_entry
();
pr_alert
(
"Unhandled fault: %s (0x%03x) at 0x%08lx
\n
"
,
inf
->
name
,
fsr
,
addr
);
show_pte
(
current
->
mm
,
addr
);
...
...
@@ -569,6 +642,8 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
info
.
si_code
=
inf
->
code
;
info
.
si_addr
=
(
void
__user
*
)
addr
;
arm_notify_die
(
""
,
regs
,
&
info
,
fsr
,
0
);
ipipe_fault_exit
(
irqflags
);
}
void
__init
...
...
@@ -588,11 +663,17 @@ asmlinkage void
do_PrefetchAbort
(
unsigned
long
addr
,
unsigned
int
ifsr
,
struct
pt_regs
*
regs
)
{
const
struct
fsr_info
*
inf
=
ifsr_info
+
fsr_fs
(
ifsr
);
unsigned
long
irqflags
;
struct
siginfo
info
;
if
(
!
inf
->
fn
(
addr
,
ifsr
|
FSR_LNX_PF
,
regs
))
return
;
if
(
__ipipe_report_trap
(
IPIPE_TRAP_UNKNOWN
,
regs
))
return
;
irqflags
=
ipipe_fault_entry
();
pr_alert
(
"Unhandled prefetch abort: %s (0x%03x) at 0x%08lx
\n
"
,
inf
->
name
,
ifsr
,
addr
);
...
...
@@ -602,6 +683,8 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
info
.
si_code
=
inf
->
code
;
info
.
si_addr
=
(
void
__user
*
)
addr
;
arm_notify_die
(
""
,
regs
,
&
info
,
ifsr
,
0
);
ipipe_fault_exit
(
irqflags
);
}
/*
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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