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 @@
...
@@ -4,7 +4,7 @@
-----------------------------------
-----------------------------------
Started: 13-Jan-2002
Started: 13-Jan-2002
Last update: 1
4
-Jan-2002
Last update: 1
5
-Jan-2002
David Mosberger-Tang
David Mosberger-Tang
<davidm@hpl.hp.com>
<davidm@hpl.hp.com>
...
@@ -14,23 +14,22 @@ execution to the ia64 linux kernel. We call this mode the
...
@@ -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:
"fsys-mode". To recap, the normal states of execution are:
- kernel mode:
- kernel mode:
Both the register stack and the kernel stack have been
Both the register stack and the memory stack have been
switched over to the kernel stack. The user-level state
switched over to kernel memory. The user-level state is saved
is saved in a pt-regs structure at the top of the kernel
in a pt-regs structure at the top of the kernel memory stack.
memory stack.
- user mode:
- user mode:
Both the register stack and the kernel stack are in
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.
CPU registers.
- bank 0 interruption-handling mode:
- bank 0 interruption-handling mode:
This is the non-interruptible state
in that
all
This is the non-interruptible state
which
all
interruption-handlers start executi
ng
in. The user-level
interruption-handlers start executi
on
in. The user-level
state remains in the CPU registers and some kernel state may
state remains in the CPU registers and some kernel state may
be stored in bank 0 of registers r16-r31.
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)
- execution is at privilege level 0 (most-privileged)
...
@@ -61,18 +60,19 @@ yet. For convenience, the header file <asm-ia64/ptrace.h> provides
...
@@ -61,18 +60,19 @@ yet. For convenience, the header file <asm-ia64/ptrace.h> provides
three macros:
three macros:
user_mode(regs)
user_mode(regs)
user_stack(regs)
user_stack(
task,
regs)
fsys_mode(regs)
fsys_mode(
task,
regs)
The "regs" argument is a pointer to a pt_regs structure. user_mode()
The "regs" argument is a pointer to a pt_regs structure. The "task"
returns TRUE if the CPU state pointed to by "regs" was executing in
argument is a pointer to the task structure to which the "regs"
user mode (privilege level 3). user_stack() returns TRUE if the state
pointer belongs to. user_mode() returns TRUE if the CPU state pointed
pointed to by "regs" was executing on the user-level stack(s).
to by "regs" was executing in user mode (privilege level 3).
Finally, fsys_mode() returns TRUE if the CPU state pointed to by
user_stack() returns TRUE if the state pointed to by "regs" was
"regs" was executing in fsys-mode. The fsys_mode() macro corresponds
executing on the user-level stack(s). Finally, fsys_mode() returns
exactly to the expression:
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
* How to write an fsyscall handler
...
@@ -155,6 +155,17 @@ fast system call execution (while fully preserving system call
...
@@ -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
semantics), but there is also a lot of flexibility in handling more
complicated cases.
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
* PSR Handling
The "epc" instruction doesn't change the contents of PSR at all. This
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 @@
...
@@ -13,6 +13,7 @@
ENTRY
(
fsys_ni_syscall
)
ENTRY
(
fsys_ni_syscall
)
mov
r8
=
ENOSYS
mov
r8
=
ENOSYS
mov
r10
=-
1
mov
r10
=-
1
MCKINLEY_E7_WORKAROUND
br.ret.sptk.many
b6
br.ret.sptk.many
b6
END
(
fsys_ni_syscall
)
END
(
fsys_ni_syscall
)
...
@@ -27,6 +28,7 @@ ENTRY(fsys_getpid)
...
@@ -27,6 +28,7 @@ ENTRY(fsys_getpid)
;;
;;
cmp.ne
p8
,
p0
=
0
,
r9
cmp.ne
p8
,
p0
=
0
,
r9
(
p8
)
br.spnt.many
fsys_fallback_syscall
(
p8
)
br.spnt.many
fsys_fallback_syscall
MCKINLEY_E7_WORKAROUND
br.ret.sptk.many
b6
br.ret.sptk.many
b6
END
(
fsys_getpid
)
END
(
fsys_getpid
)
...
...
arch/ia64/kernel/gate.S
View file @
25ed6267
...
@@ -66,6 +66,7 @@ GLOBAL_ENTRY(syscall_via_epc)
...
@@ -66,6 +66,7 @@ GLOBAL_ENTRY(syscall_via_epc)
mov
r10
=-
1
mov
r10
=-
1
mov
r8
=
ENOSYS
mov
r8
=
ENOSYS
MCKINLEY_E7_WORKAROUND
br.ret.sptk.many
b6
br.ret.sptk.many
b6
END
(
syscall_via_epc
)
END
(
syscall_via_epc
)
...
@@ -88,6 +89,7 @@ GLOBAL_ENTRY(fsys_fallback_syscall)
...
@@ -88,6 +89,7 @@ GLOBAL_ENTRY(fsys_fallback_syscall)
*/
*/
movl
r2
=(
syscall_via_break
-
.
start_gate
)
+
GATE_ADDR
movl
r2
=(
syscall_via_break
-
.
start_gate
)
+
GATE_ADDR
;;
;;
MCKINLEY_E7_WORKAROUND
mov
b7
=
r2
mov
b7
=
r2
br.ret.sptk.many
b7
br.ret.sptk.many
b7
END
(
fsys_fallback_syscall
)
END
(
fsys_fallback_syscall
)
...
...
arch/ia64/kernel/process.c
View file @
25ed6267
/*
/*
* Architecture-specific setup.
* 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>
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
*/
#define __KERNEL_SYSCALLS__
/* see <asm/unistd.h> */
#define __KERNEL_SYSCALLS__
/* see <asm/unistd.h> */
...
@@ -144,6 +144,13 @@ show_regs (struct pt_regs *regs)
...
@@ -144,6 +144,13 @@ show_regs (struct pt_regs *regs)
void
void
do_notify_resume_user
(
sigset_t
*
oldset
,
struct
sigscratch
*
scr
,
long
in_syscall
)
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
#ifdef CONFIG_PERFMON
if
(
current
->
thread
.
pfm_ovfl_block_reset
)
if
(
current
->
thread
.
pfm_ovfl_block_reset
)
pfm_ovfl_block_reset
();
pfm_ovfl_block_reset
();
...
...
arch/ia64/kernel/traps.c
View file @
25ed6267
/*
/*
* Architecture-specific trap handling.
* 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>
* David Mosberger-Tang <davidm@hpl.hp.com>
*
*
* 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE
* 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,
...
@@ -524,7 +524,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
case
29
:
/* Debug */
case
29
:
/* Debug */
case
35
:
/* Taken Branch Trap */
case
35
:
/* Taken Branch Trap */
case
36
:
/* Single Step Trap */
case
36
:
/* Single Step Trap */
if
(
fsys_mode
(
regs
))
{
if
(
fsys_mode
(
current
,
regs
))
{
extern
char
syscall_via_break
[],
__start_gate_section
[];
extern
char
syscall_via_break
[],
__start_gate_section
[];
/*
/*
* Got a trap in fsys-mode: Taken Branch Trap and Single Step trap
* 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,
...
@@ -580,19 +580,31 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
}
}
return
;
return
;
case
34
:
/* Unimplemented Instruction Address Trap */
case
34
:
if
(
user_mode
(
regs
))
{
if
(
isr
&
0x2
)
{
siginfo
.
si_signo
=
SIGILL
;
/* Lower-Privilege Transfer Trap */
siginfo
.
si_code
=
ILL_BADIADDR
;
/*
siginfo
.
si_errno
=
0
;
* Just clear PSR.lp and then return immediately: all the
siginfo
.
si_flags
=
0
;
* interesting work (e.g., signal delivery is done in the kernel
siginfo
.
si_isr
=
0
;
* exit path).
siginfo
.
si_imm
=
0
;
*/
siginfo
.
si_addr
=
(
void
*
)
(
regs
->
cr_iip
+
ia64_psr
(
regs
)
->
ri
);
ia64_psr
(
regs
)
->
lp
=
0
;
force_sig_info
(
SIGILL
,
&
siginfo
,
current
);
return
;
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
;
break
;
case
45
:
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)
...
@@ -331,7 +331,7 @@ set_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long val, int nat)
return
;
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
);
DPRINT
(
"ignoring kernel write to r%lu; register isn't on the kernel RBS!"
,
r1
);
return
;
return
;
}
}
...
@@ -402,7 +402,7 @@ get_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long *val, int *na
...
@@ -402,7 +402,7 @@ get_rse_reg (struct pt_regs *regs, unsigned long r1, unsigned long *val, int *na
return
;
return
;
}
}
if
(
!
user_stack
(
regs
))
{
if
(
!
user_stack
(
current
,
regs
))
{
DPRINT
(
"ignoring kernel read of r%lu; register isn't on the RBS!"
,
r1
);
DPRINT
(
"ignoring kernel read of r%lu; register isn't on the RBS!"
,
r1
);
goto
fail
;
goto
fail
;
}
}
...
...
include/asm-ia64/asmmacro.h
View file @
25ed6267
...
@@ -6,6 +6,8 @@
...
@@ -6,6 +6,8 @@
* David Mosberger-Tang <davidm@hpl.hp.com>
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
*/
#include <linux/config.h>
#define ENTRY(name) \
#define ENTRY(name) \
.align 32; \
.align 32; \
.proc name; \
.proc name; \
...
@@ -57,4 +59,13 @@
...
@@ -57,4 +59,13 @@
99: x
99: x
#endif
#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 */
#endif
/* _ASM_IA64_ASMMACRO_H */
include/asm-ia64/ptrace.h
View file @
25ed6267
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
#define _ASM_IA64_PTRACE_H
#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>
* David Mosberger-Tang <davidm@hpl.hp.com>
* Stephane Eranian <eranian@hpl.hp.com>
* Stephane Eranian <eranian@hpl.hp.com>
*
*
...
@@ -218,8 +218,13 @@ struct switch_stack {
...
@@ -218,8 +218,13 @@ struct switch_stack {
# define ia64_task_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
# 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 ia64_psr(regs) ((struct ia64_psr *) &(regs)->cr_ipsr)
# define user_mode(regs) (((struct ia64_psr *) &(regs)->cr_ipsr)->cpl != 0)
# define user_mode(regs) (((struct ia64_psr *) &(regs)->cr_ipsr)->cpl != 0)
# define user_stack(regs) (current->thread.on_ustack != 0)
# define user_stack(task,regs) ((long) regs - (long) task == IA64_STK_OFFSET - sizeof(*regs))
# define fsys_mode(regs) (!user_mode(regs) && user_stack(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 */
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