Commit 854a9895 authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
  sparc: Fix debugger syscall restart interactions.
  sparc: Fix ptrace() detach.
  sparc32: Don't twiddle PT_DTRACE in exec.
  sparc video: remove open boot prom code
parents 633331f3 28e61036
...@@ -1306,6 +1306,8 @@ ret_from_fork: ...@@ -1306,6 +1306,8 @@ ret_from_fork:
.align 4 .align 4
.globl linux_sparc_syscall .globl linux_sparc_syscall
linux_sparc_syscall: linux_sparc_syscall:
sethi %hi(PSR_SYSCALL), %l4
or %l0, %l4, %l0
/* Direct access to user regs, must faster. */ /* Direct access to user regs, must faster. */
cmp %g1, NR_SYSCALLS cmp %g1, NR_SYSCALLS
bgeu linux_sparc_ni_syscall bgeu linux_sparc_ni_syscall
......
...@@ -638,11 +638,6 @@ asmlinkage int sparc_execve(struct pt_regs *regs) ...@@ -638,11 +638,6 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
(char __user * __user *)regs->u_regs[base + UREG_I2], (char __user * __user *)regs->u_regs[base + UREG_I2],
regs); regs);
putname(filename); putname(filename);
if (error == 0) {
task_lock(current);
current->ptrace &= ~PT_DTRACE;
task_unlock(current);
}
out: out:
return error; return error;
} }
......
...@@ -170,8 +170,8 @@ static int genregs32_set(struct task_struct *target, ...@@ -170,8 +170,8 @@ static int genregs32_set(struct task_struct *target,
switch (pos) { switch (pos) {
case 32: /* PSR */ case 32: /* PSR */
psr = regs->psr; psr = regs->psr;
psr &= ~PSR_ICC; psr &= ~(PSR_ICC | PSR_SYSCALL);
psr |= (reg & PSR_ICC); psr |= (reg & (PSR_ICC | PSR_SYSCALL));
regs->psr = psr; regs->psr = psr;
break; break;
case 33: /* PC */ case 33: /* PC */
...@@ -441,6 +441,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -441,6 +441,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
default: default:
if (request == PTRACE_SPARC_DETACH)
request = PTRACE_DETACH;
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
break; break;
} }
......
...@@ -50,8 +50,9 @@ rtrap_7win_patch5: and %g1, 0x7f, %g1 ...@@ -50,8 +50,9 @@ rtrap_7win_patch5: and %g1, 0x7f, %g1
ret_trap_entry: ret_trap_entry:
ret_trap_lockless_ipi: ret_trap_lockless_ipi:
andcc %t_psr, PSR_PS, %g0 andcc %t_psr, PSR_PS, %g0
sethi %hi(PSR_SYSCALL), %g1
be 1f be 1f
nop andn %t_psr, %g1, %t_psr
wr %t_psr, 0x0, %psr wr %t_psr, 0x0, %psr
b ret_trap_kernel b ret_trap_kernel
...@@ -73,7 +74,6 @@ signal_p: ...@@ -73,7 +74,6 @@ signal_p:
ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
mov %l5, %o1 mov %l5, %o1
mov %l6, %o2
call do_signal call do_signal
add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr
...@@ -81,6 +81,8 @@ signal_p: ...@@ -81,6 +81,8 @@ signal_p:
ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
clr %l6 clr %l6
ret_trap_continue: ret_trap_continue:
sethi %hi(PSR_SYSCALL), %g1
andn %t_psr, %g1, %t_psr
wr %t_psr, 0x0, %psr wr %t_psr, 0x0, %psr
WRITE_PAUSE WRITE_PAUSE
...@@ -137,8 +139,9 @@ ret_trap_userwins_ok: ...@@ -137,8 +139,9 @@ ret_trap_userwins_ok:
LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc) LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
or %t_pc, %t_npc, %g2 or %t_pc, %t_npc, %g2
andcc %g2, 0x3, %g0 andcc %g2, 0x3, %g0
sethi %hi(PSR_SYCALL), %g2
be 1f be 1f
nop andn %t_psr, %g2, %t_psr
b ret_trap_unaligned_pc b ret_trap_unaligned_pc
add %sp, STACKFRAME_SZ, %o0 add %sp, STACKFRAME_SZ, %o0
...@@ -201,6 +204,8 @@ rtrap_patch5: and %g1, 0xff, %g1 ...@@ -201,6 +204,8 @@ rtrap_patch5: and %g1, 0xff, %g1
1: 1:
LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1) LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
2: 2:
sethi %hi(PSR_SYSCALL), %twin_tmp1
andn %t_psr, %twin_tmp1, %t_psr
wr %t_psr, 0x0, %psr wr %t_psr, 0x0, %psr
WRITE_PAUSE WRITE_PAUSE
......
...@@ -145,6 +145,9 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) ...@@ -145,6 +145,9 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
regs->psr = (up_psr & ~(PSR_ICC | PSR_EF)) regs->psr = (up_psr & ~(PSR_ICC | PSR_EF))
| (regs->psr & (PSR_ICC | PSR_EF)); | (regs->psr & (PSR_ICC | PSR_EF));
/* Prevent syscall restart. */
pt_regs_clear_syscall(regs);
err |= __get_user(fpu_save, &sf->fpu_save); err |= __get_user(fpu_save, &sf->fpu_save);
if (fpu_save) if (fpu_save)
...@@ -199,6 +202,9 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) ...@@ -199,6 +202,9 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC); regs->psr = (regs->psr & ~PSR_ICC) | (psr & PSR_ICC);
/* Prevent syscall restart. */
pt_regs_clear_syscall(regs);
err |= __get_user(fpu_save, &sf->fpu_save); err |= __get_user(fpu_save, &sf->fpu_save);
if (fpu_save) if (fpu_save)
...@@ -507,26 +513,36 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, ...@@ -507,26 +513,36 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
* want to handle. Thus you cannot kill init even with a SIGKILL even by * want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake. * mistake.
*/ */
asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall) asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0)
{ {
siginfo_t info;
struct sparc_deliver_cookie cookie;
struct k_sigaction ka; struct k_sigaction ka;
int signr; int restart_syscall;
sigset_t *oldset; sigset_t *oldset;
siginfo_t info;
int signr;
cookie.restart_syscall = restart_syscall; if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
cookie.orig_i0 = orig_i0; restart_syscall = 1;
else
restart_syscall = 0;
if (test_thread_flag(TIF_RESTORE_SIGMASK)) if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask; oldset = &current->saved_sigmask;
else else
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, &cookie); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
/* If the debugger messes with the program counter, it clears
* the software "in syscall" bit, directing us to not perform
* a syscall restart.
*/
if (restart_syscall && !pt_regs_is_syscall(regs))
restart_syscall = 0;
if (signr > 0) { if (signr > 0) {
if (cookie.restart_syscall) if (restart_syscall)
syscall_restart(cookie.orig_i0, regs, &ka.sa); syscall_restart(orig_i0, regs, &ka.sa);
handle_signal(signr, &ka, &info, oldset, regs); handle_signal(signr, &ka, &info, oldset, regs);
/* a signal was successfully delivered; the saved /* a signal was successfully delivered; the saved
...@@ -538,16 +554,16 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest ...@@ -538,16 +554,16 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest
clear_thread_flag(TIF_RESTORE_SIGMASK); clear_thread_flag(TIF_RESTORE_SIGMASK);
return; return;
} }
if (cookie.restart_syscall && if (restart_syscall &&
(regs->u_regs[UREG_I0] == ERESTARTNOHAND || (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTSYS ||
regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
/* replay the system call when we are done */ /* replay the system call when we are done */
regs->u_regs[UREG_I0] = cookie.orig_i0; regs->u_regs[UREG_I0] = orig_i0;
regs->pc -= 4; regs->pc -= 4;
regs->npc -= 4; regs->npc -= 4;
} }
if (cookie.restart_syscall && if (restart_syscall &&
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->u_regs[UREG_G1] = __NR_restart_syscall;
regs->pc -= 4; regs->pc -= 4;
...@@ -599,27 +615,3 @@ do_sys_sigstack(struct sigstack __user *ssptr, struct sigstack __user *ossptr, ...@@ -599,27 +615,3 @@ do_sys_sigstack(struct sigstack __user *ssptr, struct sigstack __user *ossptr,
out: out:
return ret; return ret;
} }
void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
{
struct sparc_deliver_cookie *cp = cookie;
if (cp->restart_syscall &&
(regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
regs->u_regs[UREG_I0] == ERESTARTSYS ||
regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
/* replay the system call when we are done */
regs->u_regs[UREG_I0] = cp->orig_i0;
regs->pc -= 4;
regs->npc -= 4;
cp->restart_syscall = 0;
}
if (cp->restart_syscall &&
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
regs->u_regs[UREG_G1] = __NR_restart_syscall;
regs->pc -= 4;
regs->npc -= 4;
cp->restart_syscall = 0;
}
}
...@@ -27,11 +27,12 @@ ...@@ -27,11 +27,12 @@
.text .text
.align 64 .align 64
.globl etrap, etrap_irq, etraptl1 .globl etrap_syscall, etrap, etrap_irq, etraptl1
etrap: rdpr %pil, %g2 etrap: rdpr %pil, %g2
etrap_irq: etrap_irq: clr %g3
TRAP_LOAD_THREAD_REG(%g6, %g1) etrap_syscall: TRAP_LOAD_THREAD_REG(%g6, %g1)
rdpr %tstate, %g1 rdpr %tstate, %g1
or %g1, %g3, %g1
sllx %g2, 20, %g3 sllx %g2, 20, %g3
andcc %g1, TSTATE_PRIV, %g0 andcc %g1, TSTATE_PRIV, %g0
or %g1, %g3, %g1 or %g1, %g3, %g1
......
...@@ -287,11 +287,11 @@ static int genregs64_set(struct task_struct *target, ...@@ -287,11 +287,11 @@ static int genregs64_set(struct task_struct *target,
32 * sizeof(u64), 32 * sizeof(u64),
33 * sizeof(u64)); 33 * sizeof(u64));
if (!ret) { if (!ret) {
/* Only the condition codes can be modified /* Only the condition codes and the "in syscall"
* in the %tstate register. * state can be modified in the %tstate register.
*/ */
tstate &= (TSTATE_ICC | TSTATE_XCC); tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC); regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
regs->tstate |= tstate; regs->tstate |= tstate;
} }
} }
...@@ -657,8 +657,10 @@ static int genregs32_set(struct task_struct *target, ...@@ -657,8 +657,10 @@ static int genregs32_set(struct task_struct *target,
switch (pos) { switch (pos) {
case 32: /* PSR */ case 32: /* PSR */
tstate = regs->tstate; tstate = regs->tstate;
tstate &= ~(TSTATE_ICC | TSTATE_XCC); tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL);
tstate |= psr_to_tstate_icc(reg); tstate |= psr_to_tstate_icc(reg);
if (reg & PSR_SYSCALL)
tstate |= TSTATE_SYSCALL;
regs->tstate = tstate; regs->tstate = tstate;
break; break;
case 33: /* PC */ case 33: /* PC */
...@@ -944,6 +946,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, ...@@ -944,6 +946,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
break; break;
default: default:
if (request == PTRACE_SPARC_DETACH)
request = PTRACE_DETACH;
ret = compat_ptrace_request(child, request, addr, data); ret = compat_ptrace_request(child, request, addr, data);
break; break;
} }
...@@ -1036,6 +1040,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -1036,6 +1040,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
break; break;
default: default:
if (request == PTRACE_SPARC_DETACH)
request = PTRACE_DETACH;
ret = ptrace_request(child, request, addr, data); ret = ptrace_request(child, request, addr, data);
break; break;
} }
......
...@@ -257,6 +257,7 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1 ...@@ -257,6 +257,7 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
wr %o3, %g0, %y wr %o3, %g0, %y
wrpr %l4, 0x0, %pil wrpr %l4, 0x0, %pil
wrpr %g0, 0x1, %tl wrpr %g0, 0x1, %tl
andn %l1, TSTATE_SYSCALL, %l1
wrpr %l1, %g0, %tstate wrpr %l1, %g0, %tstate
wrpr %l2, %g0, %tpc wrpr %l2, %g0, %tpc
wrpr %o2, %g0, %tnpc wrpr %o2, %g0, %tnpc
......
...@@ -333,7 +333,7 @@ void do_rt_sigreturn(struct pt_regs *regs) ...@@ -333,7 +333,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
regs->tnpc = tnpc; regs->tnpc = tnpc;
/* Prevent syscall restart. */ /* Prevent syscall restart. */
pt_regs_clear_trap_type(regs); pt_regs_clear_syscall(regs);
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
...@@ -525,19 +525,17 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, ...@@ -525,19 +525,17 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
*/ */
static void do_signal(struct pt_regs *regs, unsigned long orig_i0) static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
{ {
struct signal_deliver_cookie cookie;
struct k_sigaction ka; struct k_sigaction ka;
int restart_syscall;
sigset_t *oldset; sigset_t *oldset;
siginfo_t info; siginfo_t info;
int signr; int signr;
if (pt_regs_is_syscall(regs) && if (pt_regs_is_syscall(regs) &&
(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) { (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
pt_regs_clear_trap_type(regs); restart_syscall = 1;
cookie.restart_syscall = 1;
} else } else
cookie.restart_syscall = 0; restart_syscall = 0;
cookie.orig_i0 = orig_i0;
if (test_thread_flag(TIF_RESTORE_SIGMASK)) if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask; oldset = &current->saved_sigmask;
...@@ -547,16 +545,25 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) ...@@ -547,16 +545,25 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_32BIT)) { if (test_thread_flag(TIF_32BIT)) {
extern void do_signal32(sigset_t *, struct pt_regs *, extern void do_signal32(sigset_t *, struct pt_regs *,
struct signal_deliver_cookie *); int restart_syscall,
do_signal32(oldset, regs, &cookie); unsigned long orig_i0);
do_signal32(oldset, regs, restart_syscall, orig_i0);
return; return;
} }
#endif #endif
signr = get_signal_to_deliver(&info, &ka, regs, &cookie); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
/* If the debugger messes with the program counter, it clears
* the software "in syscall" bit, directing us to not perform
* a syscall restart.
*/
if (restart_syscall && !pt_regs_is_syscall(regs))
restart_syscall = 0;
if (signr > 0) { if (signr > 0) {
if (cookie.restart_syscall) if (restart_syscall)
syscall_restart(cookie.orig_i0, regs, &ka.sa); syscall_restart(orig_i0, regs, &ka.sa);
handle_signal(signr, &ka, &info, oldset, regs); handle_signal(signr, &ka, &info, oldset, regs);
/* a signal was successfully delivered; the saved /* a signal was successfully delivered; the saved
...@@ -568,16 +575,16 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) ...@@ -568,16 +575,16 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
clear_thread_flag(TIF_RESTORE_SIGMASK); clear_thread_flag(TIF_RESTORE_SIGMASK);
return; return;
} }
if (cookie.restart_syscall && if (restart_syscall &&
(regs->u_regs[UREG_I0] == ERESTARTNOHAND || (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTSYS ||
regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
/* replay the system call when we are done */ /* replay the system call when we are done */
regs->u_regs[UREG_I0] = cookie.orig_i0; regs->u_regs[UREG_I0] = orig_i0;
regs->tpc -= 4; regs->tpc -= 4;
regs->tnpc -= 4; regs->tnpc -= 4;
} }
if (cookie.restart_syscall && if (restart_syscall &&
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->u_regs[UREG_G1] = __NR_restart_syscall;
regs->tpc -= 4; regs->tpc -= 4;
...@@ -598,26 +605,3 @@ void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long ...@@ -598,26 +605,3 @@ void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
do_signal(regs, orig_i0); do_signal(regs, orig_i0);
} }
void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
{
struct signal_deliver_cookie *cp = cookie;
if (cp->restart_syscall &&
(regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
regs->u_regs[UREG_I0] == ERESTARTSYS ||
regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
/* replay the system call when we are done */
regs->u_regs[UREG_I0] = cp->orig_i0;
regs->tpc -= 4;
regs->tnpc -= 4;
cp->restart_syscall = 0;
}
if (cp->restart_syscall &&
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
regs->u_regs[UREG_G1] = __NR_restart_syscall;
regs->tpc -= 4;
regs->tnpc -= 4;
cp->restart_syscall = 0;
}
}
...@@ -269,7 +269,7 @@ void do_sigreturn32(struct pt_regs *regs) ...@@ -269,7 +269,7 @@ void do_sigreturn32(struct pt_regs *regs)
regs->tstate |= psr_to_tstate_icc(psr); regs->tstate |= psr_to_tstate_icc(psr);
/* Prevent syscall restart. */ /* Prevent syscall restart. */
pt_regs_clear_trap_type(regs); pt_regs_clear_syscall(regs);
err |= __get_user(fpu_save, &sf->fpu_save); err |= __get_user(fpu_save, &sf->fpu_save);
if (fpu_save) if (fpu_save)
...@@ -355,7 +355,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) ...@@ -355,7 +355,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
regs->tstate |= psr_to_tstate_icc(psr); regs->tstate |= psr_to_tstate_icc(psr);
/* Prevent syscall restart. */ /* Prevent syscall restart. */
pt_regs_clear_trap_type(regs); pt_regs_clear_syscall(regs);
err |= __get_user(fpu_save, &sf->fpu_save); err |= __get_user(fpu_save, &sf->fpu_save);
if (fpu_save) if (fpu_save)
...@@ -768,16 +768,24 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs ...@@ -768,16 +768,24 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
* mistake. * mistake.
*/ */
void do_signal32(sigset_t *oldset, struct pt_regs * regs, void do_signal32(sigset_t *oldset, struct pt_regs * regs,
struct signal_deliver_cookie *cookie) int restart_syscall, unsigned long orig_i0)
{ {
struct k_sigaction ka; struct k_sigaction ka;
siginfo_t info; siginfo_t info;
int signr; int signr;
signr = get_signal_to_deliver(&info, &ka, regs, cookie); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
/* If the debugger messes with the program counter, it clears
* the "in syscall" bit, directing us to not perform a syscall
* restart.
*/
if (restart_syscall && !pt_regs_is_syscall(regs))
restart_syscall = 0;
if (signr > 0) { if (signr > 0) {
if (cookie->restart_syscall) if (restart_syscall)
syscall_restart32(cookie->orig_i0, regs, &ka.sa); syscall_restart32(orig_i0, regs, &ka.sa);
handle_signal32(signr, &ka, &info, oldset, regs); handle_signal32(signr, &ka, &info, oldset, regs);
/* a signal was successfully delivered; the saved /* a signal was successfully delivered; the saved
...@@ -789,16 +797,16 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, ...@@ -789,16 +797,16 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
clear_thread_flag(TIF_RESTORE_SIGMASK); clear_thread_flag(TIF_RESTORE_SIGMASK);
return; return;
} }
if (cookie->restart_syscall && if (restart_syscall &&
(regs->u_regs[UREG_I0] == ERESTARTNOHAND || (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
regs->u_regs[UREG_I0] == ERESTARTSYS || regs->u_regs[UREG_I0] == ERESTARTSYS ||
regs->u_regs[UREG_I0] == ERESTARTNOINTR)) { regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
/* replay the system call when we are done */ /* replay the system call when we are done */
regs->u_regs[UREG_I0] = cookie->orig_i0; regs->u_regs[UREG_I0] = orig_i0;
regs->tpc -= 4; regs->tpc -= 4;
regs->tnpc -= 4; regs->tnpc -= 4;
} }
if (cookie->restart_syscall && if (restart_syscall &&
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->u_regs[UREG_G1] = __NR_restart_syscall;
regs->tpc -= 4; regs->tpc -= 4;
......
...@@ -17,11 +17,9 @@ ...@@ -17,11 +17,9 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/of_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/fbio.h> #include <asm/fbio.h>
#include "sbuslib.h" #include "sbuslib.h"
...@@ -299,7 +297,7 @@ static int __devinit bw2_probe(struct of_device *op, const struct of_device_id * ...@@ -299,7 +297,7 @@ static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *
par->physbase = op->resource[0].start; par->physbase = op->resource[0].start;
par->which_io = op->resource[0].flags & IORESOURCE_BITS; par->which_io = op->resource[0].flags & IORESOURCE_BITS;
sbusfb_fill_var(&info->var, dp->node, 1); sbusfb_fill_var(&info->var, dp, 1);
linebytes = of_getintprop_default(dp, "linebytes", linebytes = of_getintprop_default(dp, "linebytes",
info->var.xres); info->var.xres);
......
...@@ -17,10 +17,9 @@ ...@@ -17,10 +17,9 @@
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/of_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/fbio.h> #include <asm/fbio.h>
#include "sbuslib.h" #include "sbuslib.h"
...@@ -482,7 +481,7 @@ static int __devinit cg14_probe(struct of_device *op, const struct of_device_id ...@@ -482,7 +481,7 @@ static int __devinit cg14_probe(struct of_device *op, const struct of_device_id
spin_lock_init(&par->lock); spin_lock_init(&par->lock);
sbusfb_fill_var(&info->var, dp->node, 8); sbusfb_fill_var(&info->var, dp, 8);
info->var.red.length = 8; info->var.red.length = 8;
info->var.green.length = 8; info->var.green.length = 8;
info->var.blue.length = 8; info->var.blue.length = 8;
......
...@@ -17,11 +17,9 @@ ...@@ -17,11 +17,9 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/of_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/oplib.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/fbio.h> #include <asm/fbio.h>
#include "sbuslib.h" #include "sbuslib.h"
...@@ -373,7 +371,7 @@ static int __devinit cg3_probe(struct of_device *op, ...@@ -373,7 +371,7 @@ static int __devinit cg3_probe(struct of_device *op,
par->physbase = op->resource[0].start; par->physbase = op->resource[0].start;
par->which_io = op->resource[0].flags & IORESOURCE_BITS; par->which_io = op->resource[0].flags & IORESOURCE_BITS;
sbusfb_fill_var(&info->var, dp->node, 8); sbusfb_fill_var(&info->var, dp, 8);
info->var.red.length = 8; info->var.red.length = 8;
info->var.green.length = 8; info->var.green.length = 8;
info->var.blue.length = 8; info->var.blue.length = 8;
......
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/of_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/of_device.h>
#include <asm/fbio.h> #include <asm/fbio.h>
#include "sbuslib.h" #include "sbuslib.h"
...@@ -728,7 +728,7 @@ static int __devinit cg6_probe(struct of_device *op, ...@@ -728,7 +728,7 @@ static int __devinit cg6_probe(struct of_device *op,
par->physbase = op->resource[0].start; par->physbase = op->resource[0].start;
par->which_io = op->resource[0].flags & IORESOURCE_BITS; par->which_io = op->resource[0].flags & IORESOURCE_BITS;
sbusfb_fill_var(&info->var, dp->node, 8); sbusfb_fill_var(&info->var, dp, 8);
info->var.red.length = 8; info->var.red.length = 8;
info->var.green.length = 8; info->var.green.length = 8;
info->var.blue.length = 8; info->var.blue.length = 8;
......
...@@ -16,11 +16,10 @@ ...@@ -16,11 +16,10 @@
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/of_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/upa.h> #include <asm/upa.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/fbio.h> #include <asm/fbio.h>
#include "sbuslib.h" #include "sbuslib.h"
...@@ -941,7 +940,7 @@ static int __devinit ffb_probe(struct of_device *op, ...@@ -941,7 +940,7 @@ static int __devinit ffb_probe(struct of_device *op,
info->screen_base = (char *) par->physbase + FFB_DFB24_POFF; info->screen_base = (char *) par->physbase + FFB_DFB24_POFF;
info->pseudo_palette = par->pseudo_palette; info->pseudo_palette = par->pseudo_palette;
sbusfb_fill_var(&info->var, dp->node, 32); sbusfb_fill_var(&info->var, dp, 32);
par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4); par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4);
ffb_fixup_var_rgb(&info->var); ffb_fixup_var_rgb(&info->var);
......
...@@ -16,10 +16,9 @@ ...@@ -16,10 +16,9 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/of_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/fbio.h> #include <asm/fbio.h>
#include "sbuslib.h" #include "sbuslib.h"
...@@ -562,7 +561,7 @@ static int __devinit leo_probe(struct of_device *op, const struct of_device_id * ...@@ -562,7 +561,7 @@ static int __devinit leo_probe(struct of_device *op, const struct of_device_id *
par->physbase = op->resource[0].start; par->physbase = op->resource[0].start;
par->which_io = op->resource[0].flags & IORESOURCE_BITS; par->which_io = op->resource[0].flags & IORESOURCE_BITS;
sbusfb_fill_var(&info->var, dp->node, 32); sbusfb_fill_var(&info->var, dp, 32);
leo_fixup_var_rgb(&info->var); leo_fixup_var_rgb(&info->var);
linebytes = of_getintprop_default(dp, "linebytes", linebytes = of_getintprop_default(dp, "linebytes",
......
...@@ -15,10 +15,9 @@ ...@@ -15,10 +15,9 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/of_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/fbio.h> #include <asm/fbio.h>
#include "sbuslib.h" #include "sbuslib.h"
...@@ -275,7 +274,7 @@ static int __devinit p9100_probe(struct of_device *op, const struct of_device_id ...@@ -275,7 +274,7 @@ static int __devinit p9100_probe(struct of_device *op, const struct of_device_id
par->physbase = op->resource[2].start; par->physbase = op->resource[2].start;
par->which_io = op->resource[2].flags & IORESOURCE_BITS; par->which_io = op->resource[2].flags & IORESOURCE_BITS;
sbusfb_fill_var(&info->var, dp->node, 8); sbusfb_fill_var(&info->var, dp, 8);
info->var.red.length = 8; info->var.red.length = 8;
info->var.green.length = 8; info->var.green.length = 8;
info->var.blue.length = 8; info->var.blue.length = 8;
......
...@@ -10,18 +10,19 @@ ...@@ -10,18 +10,19 @@
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/of_device.h>
#include <asm/oplib.h>
#include <asm/fbio.h> #include <asm/fbio.h>
#include "sbuslib.h" #include "sbuslib.h"
void sbusfb_fill_var(struct fb_var_screeninfo *var, int prom_node, int bpp) void sbusfb_fill_var(struct fb_var_screeninfo *var, struct device_node *dp,
int bpp)
{ {
memset(var, 0, sizeof(*var)); memset(var, 0, sizeof(*var));
var->xres = prom_getintdefault(prom_node, "width", 1152); var->xres = of_getintprop_default(dp, "width", 1152);
var->yres = prom_getintdefault(prom_node, "height", 900); var->yres = of_getintprop_default(dp, "height", 900);
var->xres_virtual = var->xres; var->xres_virtual = var->xres;
var->yres_virtual = var->yres; var->yres_virtual = var->yres;
var->bits_per_pixel = bpp; var->bits_per_pixel = bpp;
......
...@@ -11,7 +11,8 @@ struct sbus_mmap_map { ...@@ -11,7 +11,8 @@ struct sbus_mmap_map {
#define SBUS_MMAP_FBSIZE(n) (-n) #define SBUS_MMAP_FBSIZE(n) (-n)
#define SBUS_MMAP_EMPTY 0x80000000 #define SBUS_MMAP_EMPTY 0x80000000
extern void sbusfb_fill_var(struct fb_var_screeninfo *var, int prom_node, int bpp); extern void sbusfb_fill_var(struct fb_var_screeninfo *var,
struct device_node *dp, int bpp);
struct vm_area_struct; struct vm_area_struct;
extern int sbusfb_mmap_helper(struct sbus_mmap_map *map, extern int sbusfb_mmap_helper(struct sbus_mmap_map *map,
unsigned long physbase, unsigned long fbsize, unsigned long physbase, unsigned long fbsize,
......
...@@ -9,10 +9,9 @@ ...@@ -9,10 +9,9 @@
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/of_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h>
#include <asm/of_device.h>
struct s3d_info { struct s3d_info {
struct fb_info *info; struct fb_info *info;
......
...@@ -9,10 +9,9 @@ ...@@ -9,10 +9,9 @@
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/of_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h>
#include <asm/of_device.h>
/* XXX This device has a 'dev-comm' property which aparently is /* XXX This device has a 'dev-comm' property which aparently is
* XXX a pointer into the openfirmware's address space which is * XXX a pointer into the openfirmware's address space which is
......
...@@ -17,10 +17,9 @@ ...@@ -17,10 +17,9 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/of_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h>
#include <asm/of_device.h>
#include <asm/fbio.h> #include <asm/fbio.h>
#include "sbuslib.h" #include "sbuslib.h"
...@@ -385,7 +384,7 @@ static int __devinit tcx_probe(struct of_device *op, ...@@ -385,7 +384,7 @@ static int __devinit tcx_probe(struct of_device *op,
par->lowdepth = par->lowdepth =
(of_find_property(dp, "tcx-8-bit", NULL) != NULL); (of_find_property(dp, "tcx-8-bit", NULL) != NULL);
sbusfb_fill_var(&info->var, dp->node, 8); sbusfb_fill_var(&info->var, dp, 8);
info->var.red.length = 8; info->var.red.length = 8;
info->var.green.length = 8; info->var.green.length = 8;
info->var.blue.length = 8; info->var.blue.length = 8;
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#define PSR_PIL 0x00000f00 /* processor interrupt level */ #define PSR_PIL 0x00000f00 /* processor interrupt level */
#define PSR_EF 0x00001000 /* enable floating point */ #define PSR_EF 0x00001000 /* enable floating point */
#define PSR_EC 0x00002000 /* enable co-processor */ #define PSR_EC 0x00002000 /* enable co-processor */
#define PSR_SYSCALL 0x00004000 /* inside of a syscall */
#define PSR_LE 0x00008000 /* SuperSparcII little-endian */ #define PSR_LE 0x00008000 /* SuperSparcII little-endian */
#define PSR_ICC 0x00f00000 /* integer condition codes */ #define PSR_ICC 0x00f00000 /* integer condition codes */
#define PSR_C 0x00100000 /* carry bit */ #define PSR_C 0x00100000 /* carry bit */
......
...@@ -39,6 +39,16 @@ struct pt_regs { ...@@ -39,6 +39,16 @@ struct pt_regs {
#define UREG_FP UREG_I6 #define UREG_FP UREG_I6
#define UREG_RETPC UREG_I7 #define UREG_RETPC UREG_I7
static inline bool pt_regs_is_syscall(struct pt_regs *regs)
{
return (regs->psr & PSR_SYSCALL);
}
static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
{
return (regs->psr &= ~PSR_SYSCALL);
}
/* A register window */ /* A register window */
struct reg_window { struct reg_window {
unsigned long locals[8]; unsigned long locals[8];
...@@ -149,6 +159,7 @@ extern void show_regs(struct pt_regs *); ...@@ -149,6 +159,7 @@ extern void show_regs(struct pt_regs *);
#define SF_XXARG 0x5c #define SF_XXARG 0x5c
/* Stuff for the ptrace system call */ /* Stuff for the ptrace system call */
#define PTRACE_SPARC_DETACH 11
#define PTRACE_GETREGS 12 #define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13 #define PTRACE_SETREGS 13
#define PTRACE_GETFPREGS 14 #define PTRACE_GETFPREGS 14
......
...@@ -199,13 +199,7 @@ typedef struct sigaltstack { ...@@ -199,13 +199,7 @@ typedef struct sigaltstack {
size_t ss_size; size_t ss_size;
} stack_t; } stack_t;
struct sparc_deliver_cookie { #define ptrace_signal_deliver(regs, cookie) do { } while (0)
int restart_syscall;
unsigned long orig_i0;
};
struct pt_regs;
extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
#endif /* !(__KERNEL__) */ #endif /* !(__KERNEL__) */
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define PSR_PIL 0x00000f00 /* processor interrupt level */ #define PSR_PIL 0x00000f00 /* processor interrupt level */
#define PSR_EF 0x00001000 /* enable floating point */ #define PSR_EF 0x00001000 /* enable floating point */
#define PSR_EC 0x00002000 /* enable co-processor */ #define PSR_EC 0x00002000 /* enable co-processor */
#define PSR_SYSCALL 0x00004000 /* inside of a syscall */
#define PSR_LE 0x00008000 /* SuperSparcII little-endian */ #define PSR_LE 0x00008000 /* SuperSparcII little-endian */
#define PSR_ICC 0x00f00000 /* integer condition codes */ #define PSR_ICC 0x00f00000 /* integer condition codes */
#define PSR_C 0x00100000 /* carry bit */ #define PSR_C 0x00100000 /* carry bit */
...@@ -30,6 +31,7 @@ static inline unsigned int tstate_to_psr(unsigned long tstate) ...@@ -30,6 +31,7 @@ static inline unsigned int tstate_to_psr(unsigned long tstate)
PSR_S | PSR_S |
((tstate & TSTATE_ICC) >> 12) | ((tstate & TSTATE_ICC) >> 12) |
((tstate & TSTATE_XCC) >> 20) | ((tstate & TSTATE_XCC) >> 20) |
((tstate & TSTATE_SYSCALL) ? PSR_SYSCALL : 0) |
PSR_V8PLUS); PSR_V8PLUS);
} }
......
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
#define TSTATE_PRIV _AC(0x0000000000000400,UL) /* Privilege. */ #define TSTATE_PRIV _AC(0x0000000000000400,UL) /* Privilege. */
#define TSTATE_IE _AC(0x0000000000000200,UL) /* Interrupt Enable. */ #define TSTATE_IE _AC(0x0000000000000200,UL) /* Interrupt Enable. */
#define TSTATE_AG _AC(0x0000000000000100,UL) /* Alternate Globals.*/ #define TSTATE_AG _AC(0x0000000000000100,UL) /* Alternate Globals.*/
#define TSTATE_SYSCALL _AC(0x0000000000000020,UL) /* in syscall trap */
#define TSTATE_CWP _AC(0x000000000000001f,UL) /* Curr Win-Pointer. */ #define TSTATE_CWP _AC(0x000000000000001f,UL) /* Curr Win-Pointer. */
/* Floating-Point Registers State Register. /* Floating-Point Registers State Register.
......
...@@ -42,16 +42,14 @@ static inline int pt_regs_trap_type(struct pt_regs *regs) ...@@ -42,16 +42,14 @@ static inline int pt_regs_trap_type(struct pt_regs *regs)
return regs->magic & 0x1ff; return regs->magic & 0x1ff;
} }
static inline int pt_regs_clear_trap_type(struct pt_regs *regs) static inline bool pt_regs_is_syscall(struct pt_regs *regs)
{ {
return regs->magic &= ~0x1ff; return (regs->tstate & TSTATE_SYSCALL);
} }
static inline bool pt_regs_is_syscall(struct pt_regs *regs) static inline bool pt_regs_clear_syscall(struct pt_regs *regs)
{ {
int tt = pt_regs_trap_type(regs); return (regs->tstate &= ~TSTATE_SYSCALL);
return (tt == 0x110 || tt == 0x111 || tt == 0x16d);
} }
struct pt_regs32 { struct pt_regs32 {
...@@ -298,6 +296,7 @@ extern void __show_regs(struct pt_regs *); ...@@ -298,6 +296,7 @@ extern void __show_regs(struct pt_regs *);
#define SF_XXARG 0x5c #define SF_XXARG 0x5c
/* Stuff for the ptrace system call */ /* Stuff for the ptrace system call */
#define PTRACE_SPARC_DETACH 11
#define PTRACE_GETREGS 12 #define PTRACE_GETREGS 12
#define PTRACE_SETREGS 13 #define PTRACE_SETREGS 13
#define PTRACE_GETFPREGS 14 #define PTRACE_GETFPREGS 14
......
...@@ -186,13 +186,7 @@ struct k_sigaction { ...@@ -186,13 +186,7 @@ struct k_sigaction {
void __user *ka_restorer; void __user *ka_restorer;
}; };
struct signal_deliver_cookie { #define ptrace_signal_deliver(regs, cookie) do { } while (0)
int restart_syscall;
unsigned long orig_i0;
};
struct pt_regs;
extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
#endif /* !(__KERNEL__) */ #endif /* !(__KERNEL__) */
......
...@@ -91,13 +91,14 @@ ...@@ -91,13 +91,14 @@
nop; nop;
#define SYSCALL_TRAP(routine, systbl) \ #define SYSCALL_TRAP(routine, systbl) \
rdpr %pil, %g2; \
mov TSTATE_SYSCALL, %g3; \
sethi %hi(109f), %g7; \ sethi %hi(109f), %g7; \
ba,pt %xcc, etrap; \ ba,pt %xcc, etrap_syscall; \
109: or %g7, %lo(109b), %g7; \ 109: or %g7, %lo(109b), %g7; \
sethi %hi(systbl), %l7; \ sethi %hi(systbl), %l7; \
ba,pt %xcc, routine; \ ba,pt %xcc, routine; \
or %l7, %lo(systbl), %l7; \ or %l7, %lo(systbl), %l7;
nop; nop;
#define TRAP_UTRAP(handler,lvl) \ #define TRAP_UTRAP(handler,lvl) \
mov handler, %g3; \ mov handler, %g3; \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment