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
25ed6267
Commit
25ed6267
authored
Jan 15, 2003
by
David Mosberger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ia64: Make asynchronous signal delivery work properly during fsys-mode execution.
Add workaround for McKinley Erratum 7.
parent
50d5299d
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
88 additions
and
38 deletions
+88
-38
Documentation/ia64/fsys.txt
Documentation/ia64/fsys.txt
+30
-19
arch/ia64/kernel/fsys.S
arch/ia64/kernel/fsys.S
+2
-0
arch/ia64/kernel/gate.S
arch/ia64/kernel/gate.S
+2
-0
arch/ia64/kernel/process.c
arch/ia64/kernel/process.c
+8
-1
arch/ia64/kernel/traps.c
arch/ia64/kernel/traps.c
+25
-13
arch/ia64/kernel/unaligned.c
arch/ia64/kernel/unaligned.c
+2
-2
include/asm-ia64/asmmacro.h
include/asm-ia64/asmmacro.h
+11
-0
include/asm-ia64/ptrace.h
include/asm-ia64/ptrace.h
+8
-3
No files found.
Documentation/ia64/fsys.txt
View file @
25ed6267
...
...
@@ -4,7 +4,7 @@
-----------------------------------
Started: 13-Jan-2002
Last update: 1
4
-Jan-2002
Last update: 1
5
-Jan-2002
David Mosberger-Tang
<davidm@hpl.hp.com>
...
...
@@ -14,23 +14,22 @@ execution to the ia64 linux kernel. We call this mode the
"fsys-mode". To recap, the normal states of execution are:
- kernel mode:
Both the register stack and the kernel stack have been
switched over to the kernel stack. The user-level state
is saved in a pt-regs structure at the top of the kernel
memory stack.
Both the register stack and the memory stack have been
switched over to kernel memory. The user-level state is saved
in a pt-regs structure at the top of the kernel memory stack.
- user mode:
Both the register stack and the kernel stack are in
user
land
. The user-level state is contained in the
user
memory
. The user-level state is contained in the
CPU registers.
- bank 0 interruption-handling mode:
This is the non-interruptible state
in that
all
interruption-handlers start executi
ng
in. The user-level
This is the non-interruptible state
which
all
interruption-handlers start executi
on
in. The user-level
state remains in the CPU registers and some kernel state may
be stored in bank 0 of registers r16-r31.
F
sys-mode has the following special properties:
In contrast, f
sys-mode has the following special properties:
- execution is at privilege level 0 (most-privileged)
...
...
@@ -61,18 +60,19 @@ yet. For convenience, the header file <asm-ia64/ptrace.h> provides
three macros:
user_mode(regs)
user_stack(regs)
fsys_mode(regs)
user_stack(
task,
regs)
fsys_mode(
task,
regs)
The "regs" argument is a pointer to a pt_regs structure. user_mode()
returns TRUE if the CPU state pointed to by "regs" was executing in
user mode (privilege level 3). user_stack() returns TRUE if the state
pointed to by "regs" was executing on the user-level stack(s).
Finally, fsys_mode() returns TRUE if the CPU state pointed to by
"regs" was executing in fsys-mode. The fsys_mode() macro corresponds
exactly to the expression:
The "regs" argument is a pointer to a pt_regs structure. The "task"
argument is a pointer to the task structure to which the "regs"
pointer belongs to. user_mode() returns TRUE if the CPU state pointed
to by "regs" was executing in user mode (privilege level 3).
user_stack() returns TRUE if the state pointed to by "regs" was
executing on the user-level stack(s). Finally, fsys_mode() returns
TRUE if the CPU state pointed to by "regs" was executing in fsys-mode.
The fsys_mode() macro is equivalent to the expression:
!user_mode(regs) && user_stack(regs)
!user_mode(regs) && user_stack(
task,
regs)
* How to write an fsyscall handler
...
...
@@ -155,6 +155,17 @@ fast system call execution (while fully preserving system call
semantics), but there is also a lot of flexibility in handling more
complicated cases.
* Signal handling
The delivery of (asynchronous) signals must be delayed until fsys-mode
is exited. This is acomplished with the help of the lower-privilege
transfer trap: arch/ia64/kernel/process.c:do_notify_resume_user()
checks whether the interrupted task was in fsys-mode and, if so, sets
PSR.lp and returns immediately. When fsys-mode is exited via the
"br.ret" instruction that lowers the privilege level, a trap will
occur. The trap handler clears PSR.lp again and returns immediately.
The kernel exit path then checks for and delivers any pending signals.
* PSR Handling
The "epc" instruction doesn't change the contents of PSR at all. This
...
...
arch/ia64/kernel/fsys.S
View file @
25ed6267
...
...
@@ -13,6 +13,7 @@
ENTRY
(
fsys_ni_syscall
)
mov
r8
=
ENOSYS
mov
r10
=-
1
MCKINLEY_E7_WORKAROUND
br.ret.sptk.many
b6
END
(
fsys_ni_syscall
)
...
...
@@ -27,6 +28,7 @@ ENTRY(fsys_getpid)
;;
cmp.ne
p8
,
p0
=
0
,
r9
(
p8
)
br.spnt.many
fsys_fallback_syscall
MCKINLEY_E7_WORKAROUND
br.ret.sptk.many
b6
END
(
fsys_getpid
)
...
...
arch/ia64/kernel/gate.S
View file @
25ed6267
...
...
@@ -66,6 +66,7 @@ GLOBAL_ENTRY(syscall_via_epc)
mov
r10
=-
1
mov
r8
=
ENOSYS
MCKINLEY_E7_WORKAROUND
br.ret.sptk.many
b6
END
(
syscall_via_epc
)
...
...
@@ -88,6 +89,7 @@ GLOBAL_ENTRY(fsys_fallback_syscall)
*/
movl
r2
=(
syscall_via_break
-
.
start_gate
)
+
GATE_ADDR
;;
MCKINLEY_E7_WORKAROUND
mov
b7
=
r2
br.ret.sptk.many
b7
END
(
fsys_fallback_syscall
)
...
...
arch/ia64/kernel/process.c
View file @
25ed6267
/*
* Architecture-specific setup.
*
* Copyright (C) 1998-200
2
Hewlett-Packard Co
* Copyright (C) 1998-200
3
Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#define __KERNEL_SYSCALLS__
/* see <asm/unistd.h> */
...
...
@@ -144,6 +144,13 @@ show_regs (struct pt_regs *regs)
void
do_notify_resume_user
(
sigset_t
*
oldset
,
struct
sigscratch
*
scr
,
long
in_syscall
)
{
if
(
fsys_mode
(
current
,
&
scr
->
pt
))
{
/* defer signal-handling etc. until we return to privilege-level 0. */
if
(
!
ia64_psr
(
&
scr
->
pt
)
->
lp
)
ia64_psr
(
&
scr
->
pt
)
->
lp
=
1
;
return
;
}
#ifdef CONFIG_PERFMON
if
(
current
->
thread
.
pfm_ovfl_block_reset
)
pfm_ovfl_block_reset
();
...
...
arch/ia64/kernel/traps.c
View file @
25ed6267
/*
* Architecture-specific trap handling.
*
* Copyright (C) 1998-200
2
Hewlett-Packard Co
* Copyright (C) 1998-200
3
Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*
* 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE
...
...
@@ -524,7 +524,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
case
29
:
/* Debug */
case
35
:
/* Taken Branch Trap */
case
36
:
/* Single Step Trap */
if
(
fsys_mode
(
regs
))
{
if
(
fsys_mode
(
current
,
regs
))
{
extern
char
syscall_via_break
[],
__start_gate_section
[];
/*
* Got a trap in fsys-mode: Taken Branch Trap and Single Step trap
...
...
@@ -580,19 +580,31 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
}
return
;
case
34
:
/* Unimplemented Instruction Address Trap */
if
(
user_mode
(
regs
))
{
siginfo
.
si_signo
=
SIGILL
;
siginfo
.
si_code
=
ILL_BADIADDR
;
siginfo
.
si_errno
=
0
;
siginfo
.
si_flags
=
0
;
siginfo
.
si_isr
=
0
;
siginfo
.
si_imm
=
0
;
siginfo
.
si_addr
=
(
void
*
)
(
regs
->
cr_iip
+
ia64_psr
(
regs
)
->
ri
);
force_sig_info
(
SIGILL
,
&
siginfo
,
current
);
case
34
:
if
(
isr
&
0x2
)
{
/* Lower-Privilege Transfer Trap */
/*
* Just clear PSR.lp and then return immediately: all the
* interesting work (e.g., signal delivery is done in the kernel
* exit path).
*/
ia64_psr
(
regs
)
->
lp
=
0
;
return
;
}
else
{
/* Unimplemented Instr. Address Trap */
if
(
user_mode
(
regs
))
{
siginfo
.
si_signo
=
SIGILL
;
siginfo
.
si_code
=
ILL_BADIADDR
;
siginfo
.
si_errno
=
0
;
siginfo
.
si_flags
=
0
;
siginfo
.
si_isr
=
0
;
siginfo
.
si_imm
=
0
;
siginfo
.
si_addr
=
(
void
*
)
(
regs
->
cr_iip
+
ia64_psr
(
regs
)
->
ri
);
force_sig_info
(
SIGILL
,
&
siginfo
,
current
);
return
;
}
sprintf
(
buf
,
"Unimplemented Instruction Address fault"
);
}
sprintf
(
buf
,
"Unimplemented Instruction Address fault"
);
break
;
case
45
:
...
...
arch/ia64/kernel/unaligned.c
View file @
25ed6267
...
...
@@ -331,7 +331,7 @@ set_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long val, int nat)
return
;
}
if
(
!
user_stack
(
regs
))
{
if
(
!
user_stack
(
current
,
regs
))
{
DPRINT
(
"ignoring kernel write to r%lu; register isn't on the kernel RBS!"
,
r1
);
return
;
}
...
...
@@ -402,7 +402,7 @@ get_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long *val, int *na
return
;
}
if
(
!
user_stack
(
regs
))
{
if
(
!
user_stack
(
current
,
regs
))
{
DPRINT
(
"ignoring kernel read of r%lu; register isn't on the RBS!"
,
r1
);
goto
fail
;
}
...
...
include/asm-ia64/asmmacro.h
View file @
25ed6267
...
...
@@ -6,6 +6,8 @@
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
#include <linux/config.h>
#define ENTRY(name) \
.align 32; \
.proc name; \
...
...
@@ -57,4 +59,13 @@
99: x
#endif
#ifdef CONFIG_MCKINLEY
/* workaround for Itanium 2 Errata 7: */
# define MCKINLEY_E7_WORKAROUND \
br.call.sptk.many b7=1f;; \
1:
#else
# define MCKINLEY_E7_WORKAROUND
#endif
#endif
/* _ASM_IA64_ASMMACRO_H */
include/asm-ia64/ptrace.h
View file @
25ed6267
...
...
@@ -2,7 +2,7 @@
#define _ASM_IA64_PTRACE_H
/*
* Copyright (C) 1998-200
2
Hewlett-Packard Co
* Copyright (C) 1998-200
3
Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
* Stephane Eranian <eranian@hpl.hp.com>
*
...
...
@@ -218,8 +218,13 @@ struct switch_stack {
# define ia64_task_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
# define ia64_psr(regs) ((struct ia64_psr *) &(regs)->cr_ipsr)
# define user_mode(regs) (((struct ia64_psr *) &(regs)->cr_ipsr)->cpl != 0)
# define user_stack(regs) (current->thread.on_ustack != 0)
# define fsys_mode(regs) (!user_mode(regs) && user_stack(regs))
# define user_stack(task,regs) ((long) regs - (long) task == IA64_STK_OFFSET - sizeof(*regs))
# define fsys_mode(task,regs) \
({ \
struct task_struct *_task = (task); \
struct pt_regs *_regs = (regs); \
!user_mode(regs) && user_stack(task, regs); \
})
struct
task_struct
;
/* forward decl */
...
...
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