Commit e534a583 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mattst88/alpha

Pull alpha updates from Al Viro:
 "Mostly small janitorial fixes but there's also more important ones: a
  patch to fix loading large modules from Edward Humes, and some fixes
  from Al Viro"

[ The fixes from Al mostly came in separately through Al's trees too and
  are now duplicated..   - Linus ]

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mattst88/alpha:
  alpha: in_irq() cleanup
  alpha: lazy FPU switching
  alpha/boot/misc: trim unused declarations
  alpha/boot/tools/objstrip: fix the check for ELF header
  alpha/boot: fix the breakage from -isystem series...
  alpha: fix FEN fault handling
  alpha: Avoid comma separated statements
  alpha: fixed a typo in core_cia.c
  alpha: remove unused __SLOW_DOWN_IO and SLOW_DOWN_IO definitions
  alpha: update config files
  alpha: fix R_ALPHA_LITERAL reloc for large modules
  alpha: Add some spaces to ensure format specification
  alpha: replace NR_SYSCALLS by NR_syscalls
  alpha: Remove redundant local asm header redirections
  alpha: Implement "current_stack_pointer"
  alpha: remove redundant err variable
  alpha: osf_sys: reduce kernel log spamming on invalid osf_mount call typenr
parents cac85e46 290ec1d5
...@@ -3,6 +3,7 @@ config ALPHA ...@@ -3,6 +3,7 @@ config ALPHA
bool bool
default y default y
select ARCH_32BIT_USTAT_F_TINODE select ARCH_32BIT_USTAT_F_TINODE
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_MIGHT_HAVE_PC_PARPORT select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO select ARCH_MIGHT_HAVE_PC_SERIO
select ARCH_NO_PREEMPT select ARCH_NO_PREEMPT
......
...@@ -42,8 +42,8 @@ static int skip_atoi(const char **s) ...@@ -42,8 +42,8 @@ static int skip_atoi(const char **s)
static char * number(char * str, unsigned long long num, int base, int size, int precision, int type) static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
{ {
char c,sign,tmp[66]; char c, sign, tmp[66];
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
int i; int i;
if (type & LARGE) if (type & LARGE)
...@@ -83,14 +83,14 @@ static char * number(char * str, unsigned long long num, int base, int size, int ...@@ -83,14 +83,14 @@ static char * number(char * str, unsigned long long num, int base, int size, int
precision = i; precision = i;
size -= precision; size -= precision;
if (!(type&(ZEROPAD+LEFT))) if (!(type&(ZEROPAD+LEFT)))
while(size-->0) while (size-- > 0)
*str++ = ' '; *str++ = ' ';
if (sign) if (sign)
*str++ = sign; *str++ = sign;
if (type & SPECIAL) { if (type & SPECIAL) {
if (base==8) if (base==8)
*str++ = '0'; *str++ = '0';
else if (base==16) { else if (base == 16) {
*str++ = '0'; *str++ = '0';
*str++ = digits[33]; *str++ = digits[33];
} }
...@@ -125,7 +125,7 @@ int vsprintf(char *buf, const char *fmt, va_list args) ...@@ -125,7 +125,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
/* 'z' changed to 'Z' --davidm 1/25/99 */ /* 'z' changed to 'Z' --davidm 1/25/99 */
for (str=buf ; *fmt ; ++fmt) { for (str = buf ; *fmt ; ++fmt) {
if (*fmt != '%') { if (*fmt != '%') {
*str++ = *fmt; *str++ = *fmt;
continue; continue;
...@@ -296,7 +296,7 @@ int sprintf(char * buf, const char *fmt, ...) ...@@ -296,7 +296,7 @@ int sprintf(char * buf, const char *fmt, ...)
int i; int i;
va_start(args, fmt); va_start(args, fmt);
i=vsprintf(buf,fmt,args); i = vsprintf(buf, fmt, args);
va_end(args); va_end(args);
return i; return i;
} }
...@@ -39,14 +39,12 @@ CONFIG_PATA_CYPRESS=y ...@@ -39,14 +39,12 @@ CONFIG_PATA_CYPRESS=y
CONFIG_ATA_GENERIC=y CONFIG_ATA_GENERIC=y
CONFIG_NETDEVICES=y CONFIG_NETDEVICES=y
CONFIG_DUMMY=m CONFIG_DUMMY=m
CONFIG_NET_ETHERNET=y
CONFIG_NET_VENDOR_3COM=y CONFIG_NET_VENDOR_3COM=y
CONFIG_VORTEX=y CONFIG_VORTEX=y
CONFIG_NET_TULIP=y CONFIG_NET_TULIP=y
CONFIG_DE2104X=m CONFIG_DE2104X=m
CONFIG_TULIP=y CONFIG_TULIP=y
CONFIG_TULIP_MMIO=y CONFIG_TULIP_MMIO=y
CONFIG_NET_PCI=y
CONFIG_YELLOWFIN=y CONFIG_YELLOWFIN=y
CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_CONSOLE=y
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
generated-y += syscall_table.h generated-y += syscall_table.h
generic-y += agp.h generic-y += agp.h
generic-y += asm-offsets.h
generic-y += export.h generic-y += export.h
generic-y += kvm_para.h generic-y += kvm_para.h
generic-y += mcs_spinlock.h generic-y += mcs_spinlock.h
#include <generated/asm-offsets.h>
#include <asm-generic/div64.h>
...@@ -15,21 +15,27 @@ rdfpcr(void) ...@@ -15,21 +15,27 @@ rdfpcr(void)
{ {
unsigned long tmp, ret; unsigned long tmp, ret;
preempt_disable();
if (current_thread_info()->status & TS_SAVED_FP) {
ret = current_thread_info()->fp[31];
} else {
#if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67) #if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67)
__asm__ __volatile__ ( __asm__ __volatile__ (
"ftoit $f0,%0\n\t" "ftoit $f0,%0\n\t"
"mf_fpcr $f0\n\t" "mf_fpcr $f0\n\t"
"ftoit $f0,%1\n\t" "ftoit $f0,%1\n\t"
"itoft %0,$f0" "itoft %0,$f0"
: "=r"(tmp), "=r"(ret)); : "=r"(tmp), "=r"(ret));
#else #else
__asm__ __volatile__ ( __asm__ __volatile__ (
"stt $f0,%0\n\t" "stt $f0,%0\n\t"
"mf_fpcr $f0\n\t" "mf_fpcr $f0\n\t"
"stt $f0,%1\n\t" "stt $f0,%1\n\t"
"ldt $f0,%0" "ldt $f0,%0"
: "=m"(tmp), "=m"(ret)); : "=m"(tmp), "=m"(ret));
#endif #endif
}
preempt_enable();
return ret; return ret;
} }
...@@ -39,21 +45,28 @@ wrfpcr(unsigned long val) ...@@ -39,21 +45,28 @@ wrfpcr(unsigned long val)
{ {
unsigned long tmp; unsigned long tmp;
preempt_disable();
if (current_thread_info()->status & TS_SAVED_FP) {
current_thread_info()->status |= TS_RESTORE_FP;
current_thread_info()->fp[31] = val;
} else {
#if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67) #if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67)
__asm__ __volatile__ ( __asm__ __volatile__ (
"ftoit $f0,%0\n\t" "ftoit $f0,%0\n\t"
"itoft %1,$f0\n\t" "itoft %1,$f0\n\t"
"mt_fpcr $f0\n\t" "mt_fpcr $f0\n\t"
"itoft %0,$f0" "itoft %0,$f0"
: "=&r"(tmp) : "r"(val)); : "=&r"(tmp) : "r"(val));
#else #else
__asm__ __volatile__ ( __asm__ __volatile__ (
"stt $f0,%0\n\t" "stt $f0,%0\n\t"
"ldt $f0,%1\n\t" "ldt $f0,%1\n\t"
"mt_fpcr $f0\n\t" "mt_fpcr $f0\n\t"
"ldt $f0,%0" "ldt $f0,%0"
: "=m"(tmp) : "m"(val)); : "=m"(tmp) : "m"(val));
#endif #endif
}
preempt_enable();
} }
static inline unsigned long static inline unsigned long
......
...@@ -14,10 +14,6 @@ ...@@ -14,10 +14,6 @@
the implementation we have here matches that interface. */ the implementation we have here matches that interface. */
#include <asm-generic/iomap.h> #include <asm-generic/iomap.h>
/* We don't use IO slowdowns on the Alpha, but.. */
#define __SLOW_DOWN_IO do { } while (0)
#define SLOW_DOWN_IO do { } while (0)
/* /*
* Virtual -> physical identity mapping starts at this offset * Virtual -> physical identity mapping starts at this offset
*/ */
......
#include <asm-generic/irq_regs.h>
#include <asm-generic/kdebug.h>
...@@ -26,6 +26,7 @@ struct thread_info { ...@@ -26,6 +26,7 @@ struct thread_info {
int bpt_nsaved; int bpt_nsaved;
unsigned long bpt_addr[2]; /* breakpoint handling */ unsigned long bpt_addr[2]; /* breakpoint handling */
unsigned int bpt_insn[2]; unsigned int bpt_insn[2];
unsigned long fp[32];
}; };
/* /*
...@@ -41,6 +42,8 @@ struct thread_info { ...@@ -41,6 +42,8 @@ struct thread_info {
register struct thread_info *__current_thread_info __asm__("$8"); register struct thread_info *__current_thread_info __asm__("$8");
#define current_thread_info() __current_thread_info #define current_thread_info() __current_thread_info
register unsigned long *current_stack_pointer __asm__ ("$30");
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* Thread information allocation. */ /* Thread information allocation. */
...@@ -81,6 +84,9 @@ register struct thread_info *__current_thread_info __asm__("$8"); ...@@ -81,6 +84,9 @@ register struct thread_info *__current_thread_info __asm__("$8");
#define TS_UAC_NOFIX 0x0002 /* ! flags as they match */ #define TS_UAC_NOFIX 0x0002 /* ! flags as they match */
#define TS_UAC_SIGBUS 0x0004 /* ! userspace part of 'osf_sysinfo' */ #define TS_UAC_SIGBUS 0x0004 /* ! userspace part of 'osf_sysinfo' */
#define TS_SAVED_FP 0x0008
#define TS_RESTORE_FP 0x0010
#define SET_UNALIGN_CTL(task,value) ({ \ #define SET_UNALIGN_CTL(task,value) ({ \
__u32 status = task_thread_info(task)->status & ~UAC_BITMASK; \ __u32 status = task_thread_info(task)->status & ~UAC_BITMASK; \
if (value & PR_UNALIGN_NOPRINT) \ if (value & PR_UNALIGN_NOPRINT) \
...@@ -104,5 +110,17 @@ register struct thread_info *__current_thread_info __asm__("$8"); ...@@ -104,5 +110,17 @@ register struct thread_info *__current_thread_info __asm__("$8");
put_user(res, (int __user *)(value)); \ put_user(res, (int __user *)(value)); \
}) })
#ifndef __ASSEMBLY__
extern void __save_fpu(void);
static inline void save_fpu(void)
{
if (!(current_thread_info()->status & TS_SAVED_FP)) {
current_thread_info()->status |= TS_SAVED_FP;
__save_fpu();
}
}
#endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _ALPHA_THREAD_INFO_H */ #endif /* _ALPHA_THREAD_INFO_H */
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include <uapi/asm/unistd.h> #include <uapi/asm/unistd.h>
#define NR_SYSCALLS __NR_syscalls #define NR_syscalls __NR_syscalls
#define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_NEW_STAT
#define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_READDIR
......
...@@ -64,7 +64,9 @@ struct switch_stack { ...@@ -64,7 +64,9 @@ struct switch_stack {
unsigned long r14; unsigned long r14;
unsigned long r15; unsigned long r15;
unsigned long r26; unsigned long r26;
#ifndef __KERNEL__
unsigned long fp[32]; /* fp[31] is fpcr */ unsigned long fp[32]; /* fp[31] is fpcr */
#endif
}; };
......
...@@ -17,6 +17,8 @@ void foo(void) ...@@ -17,6 +17,8 @@ void foo(void)
DEFINE(TI_TASK, offsetof(struct thread_info, task)); DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
DEFINE(TI_FP, offsetof(struct thread_info, fp));
DEFINE(TI_STATUS, offsetof(struct thread_info, status));
BLANK(); BLANK();
DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked)); DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
......
...@@ -527,7 +527,7 @@ verify_tb_operation(void) ...@@ -527,7 +527,7 @@ verify_tb_operation(void)
if (use_tbia_try2) { if (use_tbia_try2) {
alpha_mv.mv_pci_tbi = cia_pci_tbi_try2; alpha_mv.mv_pci_tbi = cia_pci_tbi_try2;
/* Tags 0-3 must be disabled if we use this workaraund. */ /* Tags 0-3 must be disabled if we use this workaround. */
wmb(); wmb();
*(vip)CIA_IOC_TB_TAGn(0) = 2; *(vip)CIA_IOC_TB_TAGn(0) = 2;
*(vip)CIA_IOC_TB_TAGn(1) = 2; *(vip)CIA_IOC_TB_TAGn(1) = 2;
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
/* Stack offsets. */ /* Stack offsets. */
#define SP_OFF 184 #define SP_OFF 184
#define SWITCH_STACK_SIZE 320 #define SWITCH_STACK_SIZE 64
.macro CFI_START_OSF_FRAME func .macro CFI_START_OSF_FRAME func
.align 4 .align 4
...@@ -159,7 +159,6 @@ ...@@ -159,7 +159,6 @@
.cfi_rel_offset $13, 32 .cfi_rel_offset $13, 32
.cfi_rel_offset $14, 40 .cfi_rel_offset $14, 40
.cfi_rel_offset $15, 48 .cfi_rel_offset $15, 48
/* We don't really care about the FP registers for debugging. */
.endm .endm
.macro UNDO_SWITCH_STACK .macro UNDO_SWITCH_STACK
...@@ -454,7 +453,7 @@ entSys: ...@@ -454,7 +453,7 @@ entSys:
SAVE_ALL SAVE_ALL
lda $8, 0x3fff lda $8, 0x3fff
bic $sp, $8, $8 bic $sp, $8, $8
lda $4, NR_SYSCALLS($31) lda $4, NR_syscalls($31)
stq $16, SP_OFF+24($sp) stq $16, SP_OFF+24($sp)
lda $5, sys_call_table lda $5, sys_call_table
lda $27, sys_ni_syscall lda $27, sys_ni_syscall
...@@ -498,6 +497,10 @@ ret_to_user: ...@@ -498,6 +497,10 @@ ret_to_user:
and $17, _TIF_WORK_MASK, $2 and $17, _TIF_WORK_MASK, $2
bne $2, work_pending bne $2, work_pending
restore_all: restore_all:
ldl $2, TI_STATUS($8)
and $2, TS_SAVED_FP | TS_RESTORE_FP, $3
bne $3, restore_fpu
restore_other:
.cfi_remember_state .cfi_remember_state
RESTORE_ALL RESTORE_ALL
call_pal PAL_rti call_pal PAL_rti
...@@ -506,7 +509,7 @@ ret_to_kernel: ...@@ -506,7 +509,7 @@ ret_to_kernel:
.cfi_restore_state .cfi_restore_state
lda $16, 7 lda $16, 7
call_pal PAL_swpipl call_pal PAL_swpipl
br restore_all br restore_other
.align 3 .align 3
$syscall_error: $syscall_error:
...@@ -570,6 +573,14 @@ $work_notifysig: ...@@ -570,6 +573,14 @@ $work_notifysig:
.type strace, @function .type strace, @function
strace: strace:
/* set up signal stack, call syscall_trace */ /* set up signal stack, call syscall_trace */
// NB: if anyone adds preemption, this block will need to be protected
ldl $1, TI_STATUS($8)
and $1, TS_SAVED_FP, $3
or $1, TS_SAVED_FP, $2
bne $3, 1f
stl $2, TI_STATUS($8)
bsr $26, __save_fpu
1:
DO_SWITCH_STACK DO_SWITCH_STACK
jsr $26, syscall_trace_enter /* returns the syscall number */ jsr $26, syscall_trace_enter /* returns the syscall number */
UNDO_SWITCH_STACK UNDO_SWITCH_STACK
...@@ -583,7 +594,7 @@ strace: ...@@ -583,7 +594,7 @@ strace:
ldq $21, 88($sp) ldq $21, 88($sp)
/* get the system call pointer.. */ /* get the system call pointer.. */
lda $1, NR_SYSCALLS($31) lda $1, NR_syscalls($31)
lda $2, sys_call_table lda $2, sys_call_table
lda $27, sys_ni_syscall lda $27, sys_ni_syscall
cmpult $0, $1, $1 cmpult $0, $1, $1
...@@ -649,40 +660,6 @@ do_switch_stack: ...@@ -649,40 +660,6 @@ do_switch_stack:
stq $14, 40($sp) stq $14, 40($sp)
stq $15, 48($sp) stq $15, 48($sp)
stq $26, 56($sp) stq $26, 56($sp)
stt $f0, 64($sp)
stt $f1, 72($sp)
stt $f2, 80($sp)
stt $f3, 88($sp)
stt $f4, 96($sp)
stt $f5, 104($sp)
stt $f6, 112($sp)
stt $f7, 120($sp)
stt $f8, 128($sp)
stt $f9, 136($sp)
stt $f10, 144($sp)
stt $f11, 152($sp)
stt $f12, 160($sp)
stt $f13, 168($sp)
stt $f14, 176($sp)
stt $f15, 184($sp)
stt $f16, 192($sp)
stt $f17, 200($sp)
stt $f18, 208($sp)
stt $f19, 216($sp)
stt $f20, 224($sp)
stt $f21, 232($sp)
stt $f22, 240($sp)
stt $f23, 248($sp)
stt $f24, 256($sp)
stt $f25, 264($sp)
stt $f26, 272($sp)
stt $f27, 280($sp)
mf_fpcr $f0 # get fpcr
stt $f28, 288($sp)
stt $f29, 296($sp)
stt $f30, 304($sp)
stt $f0, 312($sp) # save fpcr in slot of $f31
ldt $f0, 64($sp) # dont let "do_switch_stack" change fp state.
ret $31, ($1), 1 ret $31, ($1), 1
.cfi_endproc .cfi_endproc
.size do_switch_stack, .-do_switch_stack .size do_switch_stack, .-do_switch_stack
...@@ -701,54 +678,71 @@ undo_switch_stack: ...@@ -701,54 +678,71 @@ undo_switch_stack:
ldq $14, 40($sp) ldq $14, 40($sp)
ldq $15, 48($sp) ldq $15, 48($sp)
ldq $26, 56($sp) ldq $26, 56($sp)
ldt $f30, 312($sp) # get saved fpcr
ldt $f0, 64($sp)
ldt $f1, 72($sp)
ldt $f2, 80($sp)
ldt $f3, 88($sp)
mt_fpcr $f30 # install saved fpcr
ldt $f4, 96($sp)
ldt $f5, 104($sp)
ldt $f6, 112($sp)
ldt $f7, 120($sp)
ldt $f8, 128($sp)
ldt $f9, 136($sp)
ldt $f10, 144($sp)
ldt $f11, 152($sp)
ldt $f12, 160($sp)
ldt $f13, 168($sp)
ldt $f14, 176($sp)
ldt $f15, 184($sp)
ldt $f16, 192($sp)
ldt $f17, 200($sp)
ldt $f18, 208($sp)
ldt $f19, 216($sp)
ldt $f20, 224($sp)
ldt $f21, 232($sp)
ldt $f22, 240($sp)
ldt $f23, 248($sp)
ldt $f24, 256($sp)
ldt $f25, 264($sp)
ldt $f26, 272($sp)
ldt $f27, 280($sp)
ldt $f28, 288($sp)
ldt $f29, 296($sp)
ldt $f30, 304($sp)
lda $sp, SWITCH_STACK_SIZE($sp) lda $sp, SWITCH_STACK_SIZE($sp)
ret $31, ($1), 1 ret $31, ($1), 1
.cfi_endproc .cfi_endproc
.size undo_switch_stack, .-undo_switch_stack .size undo_switch_stack, .-undo_switch_stack
#define FR(n) n * 8 + TI_FP($8)
.align 4
.globl __save_fpu
.type __save_fpu, @function
__save_fpu:
#define V(n) stt $f##n, FR(n)
V( 0); V( 1); V( 2); V( 3)
V( 4); V( 5); V( 6); V( 7)
V( 8); V( 9); V(10); V(11)
V(12); V(13); V(14); V(15)
V(16); V(17); V(18); V(19)
V(20); V(21); V(22); V(23)
V(24); V(25); V(26); V(27)
mf_fpcr $f0 # get fpcr
V(28); V(29); V(30)
stt $f0, FR(31) # save fpcr in slot of $f31
ldt $f0, FR(0) # don't let "__save_fpu" change fp state.
ret
#undef V
.size __save_fpu, .-__save_fpu
.align 4
restore_fpu:
and $3, TS_RESTORE_FP, $3
bic $2, TS_SAVED_FP | TS_RESTORE_FP, $2
beq $3, 1f
#define V(n) ldt $f##n, FR(n)
ldt $f30, FR(31) # get saved fpcr
V( 0); V( 1); V( 2); V( 3)
mt_fpcr $f30 # install saved fpcr
V( 4); V( 5); V( 6); V( 7)
V( 8); V( 9); V(10); V(11)
V(12); V(13); V(14); V(15)
V(16); V(17); V(18); V(19)
V(20); V(21); V(22); V(23)
V(24); V(25); V(26); V(27)
V(28); V(29); V(30)
1: stl $2, TI_STATUS($8)
br restore_other
#undef V
/* /*
* The meat of the context switch code. * The meat of the context switch code.
*/ */
.align 4 .align 4
.globl alpha_switch_to .globl alpha_switch_to
.type alpha_switch_to, @function .type alpha_switch_to, @function
.cfi_startproc .cfi_startproc
alpha_switch_to: alpha_switch_to:
DO_SWITCH_STACK DO_SWITCH_STACK
ldl $1, TI_STATUS($8)
and $1, TS_RESTORE_FP, $3
bne $3, 1f
or $1, TS_RESTORE_FP | TS_SAVED_FP, $2
and $1, TS_SAVED_FP, $3
stl $2, TI_STATUS($8)
bne $3, 1f
bsr $26, __save_fpu
1:
call_pal PAL_swpctx call_pal PAL_swpctx
lda $8, 0x3fff lda $8, 0x3fff
UNDO_SWITCH_STACK UNDO_SWITCH_STACK
...@@ -799,6 +793,14 @@ ret_from_kernel_thread: ...@@ -799,6 +793,14 @@ ret_from_kernel_thread:
alpha_\name: alpha_\name:
.prologue 0 .prologue 0
bsr $1, do_switch_stack bsr $1, do_switch_stack
// NB: if anyone adds preemption, this block will need to be protected
ldl $1, TI_STATUS($8)
and $1, TS_SAVED_FP, $3
or $1, TS_SAVED_FP, $2
bne $3, 1f
stl $2, TI_STATUS($8)
bsr $26, __save_fpu
1:
jsr $26, sys_\name jsr $26, sys_\name
ldq $26, 56($sp) ldq $26, 56($sp)
lda $sp, SWITCH_STACK_SIZE($sp) lda $sp, SWITCH_STACK_SIZE($sp)
......
...@@ -146,10 +146,8 @@ apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab, ...@@ -146,10 +146,8 @@ apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab,
base = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr; base = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr;
symtab = (Elf64_Sym *)sechdrs[symindex].sh_addr; symtab = (Elf64_Sym *)sechdrs[symindex].sh_addr;
/* The small sections were sorted to the end of the segment.
The following should definitely cover them. */
gp = (u64)me->core_layout.base + me->core_layout.size - 0x8000;
got = sechdrs[me->arch.gotsecindex].sh_addr; got = sechdrs[me->arch.gotsecindex].sh_addr;
gp = got + 0x8000;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
unsigned long r_sym = ELF64_R_SYM (rela[i].r_info); unsigned long r_sym = ELF64_R_SYM (rela[i].r_info);
......
...@@ -522,7 +522,7 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path, ...@@ -522,7 +522,7 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
break; break;
default: default:
retval = -EINVAL; retval = -EINVAL;
printk("osf_mount(%ld, %x)\n", typenr, flag); printk_ratelimited("osf_mount(%ld, %x)\n", typenr, flag);
} }
return retval; return retval;
......
...@@ -127,10 +127,12 @@ iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena, ...@@ -127,10 +127,12 @@ iommu_arena_find_pages(struct device *dev, struct pci_iommu_arena *arena,
goto again; goto again;
} }
if (ptes[p+i]) if (ptes[p+i]) {
p = ALIGN(p + i + 1, mask + 1), i = 0; p = ALIGN(p + i + 1, mask + 1);
else i = 0;
} else {
i = i + 1; i = i + 1;
}
} }
if (i < n) { if (i < n) {
......
...@@ -689,8 +689,6 @@ static int __hw_perf_event_init(struct perf_event *event) ...@@ -689,8 +689,6 @@ static int __hw_perf_event_init(struct perf_event *event)
*/ */
static int alpha_pmu_event_init(struct perf_event *event) static int alpha_pmu_event_init(struct perf_event *event)
{ {
int err;
/* does not support taken branch sampling */ /* does not support taken branch sampling */
if (has_branch_stack(event)) if (has_branch_stack(event))
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -709,9 +707,7 @@ static int alpha_pmu_event_init(struct perf_event *event) ...@@ -709,9 +707,7 @@ static int alpha_pmu_event_init(struct perf_event *event)
return -ENODEV; return -ENODEV;
/* Do the real initialisation work. */ /* Do the real initialisation work. */
err = __hw_perf_event_init(event); return __hw_perf_event_init(event);
return err;
} }
/* /*
......
...@@ -133,7 +133,7 @@ common_shutdown_1(void *generic_ptr) ...@@ -133,7 +133,7 @@ common_shutdown_1(void *generic_ptr)
#ifdef CONFIG_DUMMY_CONSOLE #ifdef CONFIG_DUMMY_CONSOLE
/* If we've gotten here after SysRq-b, leave interrupt /* If we've gotten here after SysRq-b, leave interrupt
context before taking over the console. */ context before taking over the console. */
if (in_irq()) if (in_hardirq())
irq_exit(); irq_exit();
/* This has the effect of resetting the VGA video origin. */ /* This has the effect of resetting the VGA video origin. */
console_lock(); console_lock();
...@@ -243,6 +243,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) ...@@ -243,6 +243,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
childstack = ((struct switch_stack *) childregs) - 1; childstack = ((struct switch_stack *) childregs) - 1;
childti->pcb.ksp = (unsigned long) childstack; childti->pcb.ksp = (unsigned long) childstack;
childti->pcb.flags = 1; /* set FEN, clear everything else */ childti->pcb.flags = 1; /* set FEN, clear everything else */
childti->status |= TS_SAVED_FP | TS_RESTORE_FP;
if (unlikely(args->fn)) { if (unlikely(args->fn)) {
/* kernel thread */ /* kernel thread */
...@@ -252,6 +253,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) ...@@ -252,6 +253,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
childstack->r9 = (unsigned long) args->fn; childstack->r9 = (unsigned long) args->fn;
childstack->r10 = (unsigned long) args->fn_arg; childstack->r10 = (unsigned long) args->fn_arg;
childregs->hae = alpha_mv.hae_cache; childregs->hae = alpha_mv.hae_cache;
memset(childti->fp, '\0', sizeof(childti->fp));
childti->pcb.usp = 0; childti->pcb.usp = 0;
return 0; return 0;
} }
...@@ -334,8 +336,7 @@ EXPORT_SYMBOL(dump_elf_task); ...@@ -334,8 +336,7 @@ EXPORT_SYMBOL(dump_elf_task);
int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu) int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
{ {
struct switch_stack *sw = (struct switch_stack *)task_pt_regs(t) - 1; memcpy(fpu, task_thread_info(t)->fp, 32 * 8);
memcpy(fpu, sw->fp, 32 * 8);
return 1; return 1;
} }
......
...@@ -78,6 +78,8 @@ enum { ...@@ -78,6 +78,8 @@ enum {
(PAGE_SIZE*2 - sizeof(struct pt_regs) - sizeof(struct switch_stack) \ (PAGE_SIZE*2 - sizeof(struct pt_regs) - sizeof(struct switch_stack) \
+ offsetof(struct switch_stack, reg)) + offsetof(struct switch_stack, reg))
#define FP_REG(reg) (offsetof(struct thread_info, reg))
static int regoff[] = { static int regoff[] = {
PT_REG( r0), PT_REG( r1), PT_REG( r2), PT_REG( r3), PT_REG( r0), PT_REG( r1), PT_REG( r2), PT_REG( r3),
PT_REG( r4), PT_REG( r5), PT_REG( r6), PT_REG( r7), PT_REG( r4), PT_REG( r5), PT_REG( r6), PT_REG( r7),
...@@ -87,14 +89,14 @@ static int regoff[] = { ...@@ -87,14 +89,14 @@ static int regoff[] = {
PT_REG( r20), PT_REG( r21), PT_REG( r22), PT_REG( r23), PT_REG( r20), PT_REG( r21), PT_REG( r22), PT_REG( r23),
PT_REG( r24), PT_REG( r25), PT_REG( r26), PT_REG( r27), PT_REG( r24), PT_REG( r25), PT_REG( r26), PT_REG( r27),
PT_REG( r28), PT_REG( gp), -1, -1, PT_REG( r28), PT_REG( gp), -1, -1,
SW_REG(fp[ 0]), SW_REG(fp[ 1]), SW_REG(fp[ 2]), SW_REG(fp[ 3]), FP_REG(fp[ 0]), FP_REG(fp[ 1]), FP_REG(fp[ 2]), FP_REG(fp[ 3]),
SW_REG(fp[ 4]), SW_REG(fp[ 5]), SW_REG(fp[ 6]), SW_REG(fp[ 7]), FP_REG(fp[ 4]), FP_REG(fp[ 5]), FP_REG(fp[ 6]), FP_REG(fp[ 7]),
SW_REG(fp[ 8]), SW_REG(fp[ 9]), SW_REG(fp[10]), SW_REG(fp[11]), FP_REG(fp[ 8]), FP_REG(fp[ 9]), FP_REG(fp[10]), FP_REG(fp[11]),
SW_REG(fp[12]), SW_REG(fp[13]), SW_REG(fp[14]), SW_REG(fp[15]), FP_REG(fp[12]), FP_REG(fp[13]), FP_REG(fp[14]), FP_REG(fp[15]),
SW_REG(fp[16]), SW_REG(fp[17]), SW_REG(fp[18]), SW_REG(fp[19]), FP_REG(fp[16]), FP_REG(fp[17]), FP_REG(fp[18]), FP_REG(fp[19]),
SW_REG(fp[20]), SW_REG(fp[21]), SW_REG(fp[22]), SW_REG(fp[23]), FP_REG(fp[20]), FP_REG(fp[21]), FP_REG(fp[22]), FP_REG(fp[23]),
SW_REG(fp[24]), SW_REG(fp[25]), SW_REG(fp[26]), SW_REG(fp[27]), FP_REG(fp[24]), FP_REG(fp[25]), FP_REG(fp[26]), FP_REG(fp[27]),
SW_REG(fp[28]), SW_REG(fp[29]), SW_REG(fp[30]), SW_REG(fp[31]), FP_REG(fp[28]), FP_REG(fp[29]), FP_REG(fp[30]), FP_REG(fp[31]),
PT_REG( pc) PT_REG( pc)
}; };
......
...@@ -150,9 +150,10 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) ...@@ -150,9 +150,10 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
{ {
unsigned long usp; unsigned long usp;
struct switch_stack *sw = (struct switch_stack *)regs - 1; struct switch_stack *sw = (struct switch_stack *)regs - 1;
long i, err = __get_user(regs->pc, &sc->sc_pc); long err = __get_user(regs->pc, &sc->sc_pc);
current->restart_block.fn = do_no_restart_syscall; current->restart_block.fn = do_no_restart_syscall;
current_thread_info()->status |= TS_SAVED_FP | TS_RESTORE_FP;
sw->r26 = (unsigned long) ret_from_sys_call; sw->r26 = (unsigned long) ret_from_sys_call;
...@@ -189,9 +190,9 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) ...@@ -189,9 +190,9 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
err |= __get_user(usp, sc->sc_regs+30); err |= __get_user(usp, sc->sc_regs+30);
wrusp(usp); wrusp(usp);
for (i = 0; i < 31; i++) err |= __copy_from_user(current_thread_info()->fp,
err |= __get_user(sw->fp[i], sc->sc_fpregs+i); sc->sc_fpregs, 31 * 8);
err |= __get_user(sw->fp[31], &sc->sc_fpcr); err |= __get_user(current_thread_info()->fp[31], &sc->sc_fpcr);
return err; return err;
} }
...@@ -272,7 +273,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -272,7 +273,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
unsigned long mask, unsigned long sp) unsigned long mask, unsigned long sp)
{ {
struct switch_stack *sw = (struct switch_stack *)regs - 1; struct switch_stack *sw = (struct switch_stack *)regs - 1;
long i, err = 0; long err = 0;
err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack); err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack);
err |= __put_user(mask, &sc->sc_mask); err |= __put_user(mask, &sc->sc_mask);
...@@ -312,10 +313,10 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -312,10 +313,10 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
err |= __put_user(sp, sc->sc_regs+30); err |= __put_user(sp, sc->sc_regs+30);
err |= __put_user(0, sc->sc_regs+31); err |= __put_user(0, sc->sc_regs+31);
for (i = 0; i < 31; i++) err |= __copy_to_user(sc->sc_fpregs,
err |= __put_user(sw->fp[i], sc->sc_fpregs+i); current_thread_info()->fp, 31 * 8);
err |= __put_user(0, sc->sc_fpregs+31); err |= __put_user(0, sc->sc_fpregs+31);
err |= __put_user(sw->fp[31], &sc->sc_fpcr); err |= __put_user(current_thread_info()->fp[31], &sc->sc_fpcr);
err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0); err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0);
err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1); err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1);
...@@ -528,6 +529,9 @@ do_work_pending(struct pt_regs *regs, unsigned long thread_flags, ...@@ -528,6 +529,9 @@ do_work_pending(struct pt_regs *regs, unsigned long thread_flags,
} else { } else {
local_irq_enable(); local_irq_enable();
if (thread_flags & (_TIF_SIGPENDING|_TIF_NOTIFY_SIGNAL)) { if (thread_flags & (_TIF_SIGPENDING|_TIF_NOTIFY_SIGNAL)) {
preempt_disable();
save_fpu();
preempt_enable();
do_signal(regs, r0, r19); do_signal(regs, r0, r19);
r0 = 0; r0 = 0;
} else { } else {
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/preempt.h>
#include <asm/thread_info.h>
#if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67) #if defined(CONFIG_ALPHA_EV6) || defined(CONFIG_ALPHA_EV67)
#define STT(reg,val) asm volatile ("ftoit $f"#reg",%0" : "=r"(val)); #define STT(reg,val) asm volatile ("ftoit $f"#reg",%0" : "=r"(val));
...@@ -19,7 +21,12 @@ alpha_read_fp_reg (unsigned long reg) ...@@ -19,7 +21,12 @@ alpha_read_fp_reg (unsigned long reg)
{ {
unsigned long val; unsigned long val;
switch (reg) { if (unlikely(reg >= 32))
return 0;
preempt_enable();
if (current_thread_info()->status & TS_SAVED_FP)
val = current_thread_info()->fp[reg];
else switch (reg) {
case 0: STT( 0, val); break; case 0: STT( 0, val); break;
case 1: STT( 1, val); break; case 1: STT( 1, val); break;
case 2: STT( 2, val); break; case 2: STT( 2, val); break;
...@@ -52,8 +59,8 @@ alpha_read_fp_reg (unsigned long reg) ...@@ -52,8 +59,8 @@ alpha_read_fp_reg (unsigned long reg)
case 29: STT(29, val); break; case 29: STT(29, val); break;
case 30: STT(30, val); break; case 30: STT(30, val); break;
case 31: STT(31, val); break; case 31: STT(31, val); break;
default: return 0;
} }
preempt_enable();
return val; return val;
} }
EXPORT_SYMBOL(alpha_read_fp_reg); EXPORT_SYMBOL(alpha_read_fp_reg);
...@@ -67,7 +74,14 @@ EXPORT_SYMBOL(alpha_read_fp_reg); ...@@ -67,7 +74,14 @@ EXPORT_SYMBOL(alpha_read_fp_reg);
void void
alpha_write_fp_reg (unsigned long reg, unsigned long val) alpha_write_fp_reg (unsigned long reg, unsigned long val)
{ {
switch (reg) { if (unlikely(reg >= 32))
return;
preempt_disable();
if (current_thread_info()->status & TS_SAVED_FP) {
current_thread_info()->status |= TS_RESTORE_FP;
current_thread_info()->fp[reg] = val;
} else switch (reg) {
case 0: LDT( 0, val); break; case 0: LDT( 0, val); break;
case 1: LDT( 1, val); break; case 1: LDT( 1, val); break;
case 2: LDT( 2, val); break; case 2: LDT( 2, val); break;
...@@ -101,6 +115,7 @@ alpha_write_fp_reg (unsigned long reg, unsigned long val) ...@@ -101,6 +115,7 @@ alpha_write_fp_reg (unsigned long reg, unsigned long val)
case 30: LDT(30, val); break; case 30: LDT(30, val); break;
case 31: LDT(31, val); break; case 31: LDT(31, val); break;
} }
preempt_enable();
} }
EXPORT_SYMBOL(alpha_write_fp_reg); EXPORT_SYMBOL(alpha_write_fp_reg);
...@@ -115,7 +130,14 @@ alpha_read_fp_reg_s (unsigned long reg) ...@@ -115,7 +130,14 @@ alpha_read_fp_reg_s (unsigned long reg)
{ {
unsigned long val; unsigned long val;
switch (reg) { if (unlikely(reg >= 32))
return 0;
preempt_enable();
if (current_thread_info()->status & TS_SAVED_FP) {
LDT(0, current_thread_info()->fp[reg]);
STS(0, val);
} else switch (reg) {
case 0: STS( 0, val); break; case 0: STS( 0, val); break;
case 1: STS( 1, val); break; case 1: STS( 1, val); break;
case 2: STS( 2, val); break; case 2: STS( 2, val); break;
...@@ -148,8 +170,8 @@ alpha_read_fp_reg_s (unsigned long reg) ...@@ -148,8 +170,8 @@ alpha_read_fp_reg_s (unsigned long reg)
case 29: STS(29, val); break; case 29: STS(29, val); break;
case 30: STS(30, val); break; case 30: STS(30, val); break;
case 31: STS(31, val); break; case 31: STS(31, val); break;
default: return 0;
} }
preempt_enable();
return val; return val;
} }
EXPORT_SYMBOL(alpha_read_fp_reg_s); EXPORT_SYMBOL(alpha_read_fp_reg_s);
...@@ -163,7 +185,15 @@ EXPORT_SYMBOL(alpha_read_fp_reg_s); ...@@ -163,7 +185,15 @@ EXPORT_SYMBOL(alpha_read_fp_reg_s);
void void
alpha_write_fp_reg_s (unsigned long reg, unsigned long val) alpha_write_fp_reg_s (unsigned long reg, unsigned long val)
{ {
switch (reg) { if (unlikely(reg >= 32))
return;
preempt_disable();
if (current_thread_info()->status & TS_SAVED_FP) {
current_thread_info()->status |= TS_RESTORE_FP;
LDS(0, val);
STT(0, current_thread_info()->fp[reg]);
} else switch (reg) {
case 0: LDS( 0, val); break; case 0: LDS( 0, val); break;
case 1: LDS( 1, val); break; case 1: LDS( 1, val); break;
case 2: LDS( 2, val); break; case 2: LDS( 2, val); break;
...@@ -197,5 +227,6 @@ alpha_write_fp_reg_s (unsigned long reg, unsigned long val) ...@@ -197,5 +227,6 @@ alpha_write_fp_reg_s (unsigned long reg, unsigned long val)
case 30: LDS(30, val); break; case 30: LDS(30, val); break;
case 31: LDS(31, val); break; case 31: LDS(31, val); break;
} }
preempt_enable();
} }
EXPORT_SYMBOL(alpha_write_fp_reg_s); EXPORT_SYMBOL(alpha_write_fp_reg_s);
...@@ -92,7 +92,7 @@ stacktrace(void) ...@@ -92,7 +92,7 @@ stacktrace(void)
{ {
instr * ret_pc; instr * ret_pc;
instr * prologue = (instr *)stacktrace; instr * prologue = (instr *)stacktrace;
register unsigned char * sp __asm__ ("$30"); unsigned char *sp = (unsigned char *)current_stack_pointer;
printk("\tstack trace:\n"); printk("\tstack trace:\n");
do { do {
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "pid_list.h" #include "pid_list.h"
#ifdef CONFIG_FTRACE_SYSCALLS #ifdef CONFIG_FTRACE_SYSCALLS
#include <asm/unistd.h> /* For NR_SYSCALLS */ #include <asm/unistd.h> /* For NR_syscalls */
#include <asm/syscall.h> /* some archs define it here */ #include <asm/syscall.h> /* some archs define it here */
#endif #endif
......
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