Commit cbc67add authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: base fixes.

s390 arch changes/bug fixes:
 * add sys_fadvise64 system call
 * add initialization of init_sighand
 * add support for clone option CLONE_SETTLS
 * make use of ptrace_notify
 * sig -> sighand rename
 * move ptrace_signal_deliver to the correct place
 * make eieio a memory barrier
 * fix race condition on cpu_vm_mask in __flush_tlb_mm
 * add missing KM_SOFTIRQ0, KM_SOFTIRQ1 in asm-s390x/kmap_types.h
 * add inline assmelby for _raw_write_trylock
parent a871d09c
...@@ -616,7 +616,8 @@ sys_call_table: ...@@ -616,7 +616,8 @@ sys_call_table:
.long sys_epoll_ctl /* 250 */ .long sys_epoll_ctl /* 250 */
.long sys_epoll_wait .long sys_epoll_wait
.long sys_set_tid_address .long sys_set_tid_address
.rept 255-252 .long sys_fadvise64
.rept 255-253
.long sys_ni_syscall .long sys_ni_syscall
.endr .endr
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
static struct fs_struct init_fs = INIT_FS; static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES; static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm); struct mm_struct init_mm = INIT_MM(init_mm);
/* /*
......
...@@ -196,8 +196,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, ...@@ -196,8 +196,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
/* new return point is ret_from_fork */ /* new return point is ret_from_fork */
frame->gprs[8] = (unsigned long) ret_from_fork; frame->gprs[8] = (unsigned long) ret_from_fork;
/* start disabled because of schedule_tick and rq->lock being held */
frame->childregs.psw.mask &= ~0x03000000;
/* fake return stack for resume(), don't go back to schedule */ /* fake return stack for resume(), don't go back to schedule */
frame->gprs[9] = (unsigned long) frame; frame->gprs[9] = (unsigned long) frame;
...@@ -213,6 +211,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, ...@@ -213,6 +211,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
p->thread.ar4 = get_fs().ar4; p->thread.ar4 = get_fs().ar4;
/* Don't copy debug registers */ /* Don't copy debug registers */
memset(&p->thread.per_info,0,sizeof(p->thread.per_info)); memset(&p->thread.per_info,0,sizeof(p->thread.per_info));
/* Set a new TLS ? */
if (clone_flags & CLONE_SETTLS)
frame->childregs.acrs[0] = regs->gprs[6];
return 0; return 0;
} }
...@@ -335,7 +337,7 @@ unsigned long get_wchan(struct task_struct *p) ...@@ -335,7 +337,7 @@ unsigned long get_wchan(struct task_struct *p)
int count = 0; int count = 0;
if (!p || p == current || p->state == TASK_RUNNING) if (!p || p == current || p->state == TASK_RUNNING)
return 0; return 0;
stack_page = (unsigned long) p; stack_page = (unsigned long) p->thread_info;
r15 = p->thread.ksp; r15 = p->thread.ksp;
if (!stack_page || r15 < stack_page || r15 >= 8188+stack_page) if (!stack_page || r15 < stack_page || r15 >= 8188+stack_page)
return 0; return 0;
......
...@@ -359,11 +359,9 @@ asmlinkage void syscall_trace(void) ...@@ -359,11 +359,9 @@ asmlinkage void syscall_trace(void)
return; return;
if (!(current->ptrace & PT_PTRACED)) if (!(current->ptrace & PT_PTRACED))
return; return;
current->exit_code = ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0); ? 0x80 : 0));
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* /*
* this isn't the same as continuing with a signal, but it will do * this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the * for normal use. strace only continues with a signal if the
......
...@@ -391,7 +391,7 @@ static void ...@@ -391,7 +391,7 @@ static void
handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
struct pt_regs * regs) struct pt_regs * regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1]; struct k_sigaction *ka = &current->sighand->action[sig-1];
/* Are we from a system call? */ /* Are we from a system call? */
if (regs->trap == __LC_SVC_OLD_PSW) { if (regs->trap == __LC_SVC_OLD_PSW) {
......
...@@ -644,7 +644,8 @@ sys_call_table: ...@@ -644,7 +644,8 @@ sys_call_table:
.long SYSCALL(sys_epoll_ctl,sys_ni_syscall) .long SYSCALL(sys_epoll_ctl,sys_ni_syscall)
.long SYSCALL(sys_epoll_wait,sys_ni_syscall) .long SYSCALL(sys_epoll_wait,sys_ni_syscall)
.long SYSCALL(sys_set_tid_address,sys_ni_syscall) .long SYSCALL(sys_set_tid_address,sys_ni_syscall)
.rept 255-252 .long SYSCALL(sys_fadvise64,sys_ni_syscall)
.rept 255-253
.long SYSCALL(sys_ni_syscall,sys_ni_syscall) .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
.endr .endr
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
static struct fs_struct init_fs = INIT_FS; static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES; static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals); static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
struct mm_struct init_mm = INIT_MM(init_mm); struct mm_struct init_mm = INIT_MM(init_mm);
/* /*
......
...@@ -203,6 +203,19 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp, ...@@ -203,6 +203,19 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
p->thread.ar4 = get_fs().ar4; p->thread.ar4 = get_fs().ar4;
/* Don't copy debug registers */ /* Don't copy debug registers */
memset(&p->thread.per_info,0,sizeof(p->thread.per_info)); memset(&p->thread.per_info,0,sizeof(p->thread.per_info));
/* Set a new TLS ? */
if (clone_flags & CLONE_SETTLS) {
if (current->thread.flags & S390_FLAG_31BIT) {
frame->childregs.acrs[0] =
(unsigned int) regs->gprs[6];
} else {
frame->childregs.acrs[0] =
(unsigned int)(regs->gprs[6] >> 32);
frame->childregs.acrs[1] =
(unsigned int) regs->gprs[6];
}
}
return 0; return 0;
} }
...@@ -319,7 +332,7 @@ unsigned long get_wchan(struct task_struct *p) ...@@ -319,7 +332,7 @@ unsigned long get_wchan(struct task_struct *p)
int count = 0; int count = 0;
if (!p || p == current || p->state == TASK_RUNNING) if (!p || p == current || p->state == TASK_RUNNING)
return 0; return 0;
stack_page = (unsigned long) p; stack_page = (unsigned long) p->thread_info;
r15 = p->thread.ksp; r15 = p->thread.ksp;
if (!stack_page || r15 < stack_page || r15 >= 16380+stack_page) if (!stack_page || r15 < stack_page || r15 >= 16380+stack_page)
return 0; return 0;
......
...@@ -598,11 +598,9 @@ asmlinkage void syscall_trace(void) ...@@ -598,11 +598,9 @@ asmlinkage void syscall_trace(void)
return; return;
if (!(current->ptrace & PT_PTRACED)) if (!(current->ptrace & PT_PTRACED))
return; return;
current->exit_code = ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0); ? 0x80 : 0));
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
/* /*
* this isn't the same as continuing with a signal, but it will do * this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the * for normal use. strace only continues with a signal if the
......
...@@ -385,7 +385,7 @@ static void ...@@ -385,7 +385,7 @@ static void
handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
struct pt_regs * regs) struct pt_regs * regs)
{ {
struct k_sigaction *ka = &current->sig->action[sig-1]; struct k_sigaction *ka = &current->sighand->action[sig-1];
/* Are we from a system call? */ /* Are we from a system call? */
if (regs->trap == __LC_SVC_OLD_PSW) { if (regs->trap == __LC_SVC_OLD_PSW) {
......
...@@ -159,6 +159,9 @@ struct sigaction { ...@@ -159,6 +159,9 @@ struct sigaction {
struct k_sigaction { struct k_sigaction {
struct sigaction sa; struct sigaction sa;
}; };
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#else #else
/* Here we must cater to libcs that poke about in kernel headers. */ /* Here we must cater to libcs that poke about in kernel headers. */
...@@ -175,8 +178,6 @@ struct sigaction { ...@@ -175,8 +178,6 @@ struct sigaction {
#define sa_handler _u._sa_handler #define sa_handler _u._sa_handler
#define sa_sigaction _u._sa_sigaction #define sa_sigaction _u._sa_sigaction
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
typedef struct sigaltstack { typedef struct sigaltstack {
......
...@@ -122,4 +122,17 @@ typedef struct { ...@@ -122,4 +122,17 @@ typedef struct {
: "+m" ((rw)->lock) : "a" (&(rw)->lock) \ : "+m" ((rw)->lock) : "a" (&(rw)->lock) \
: "2", "3", "cc" ) : "2", "3", "cc" )
extern inline int _raw_write_trylock(rwlock_t *rw)
{
unsigned int result, reg;
__asm__ __volatile__(" lhi %0,1\n"
" sll %0,31\n"
" basr %1,0\n"
"0: cs %0,%1,0(%3)\n"
: "=&d" (result), "=&d" (reg), "+m" (rw->lock)
: "a" (&rw->lock) : "cc" );
return !result;
}
#endif /* __ASM_SPINLOCK_H */ #endif /* __ASM_SPINLOCK_H */
...@@ -222,7 +222,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) ...@@ -222,7 +222,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
* all memory ops have completed wrt other CPU's ( see 7-15 POP DJB ). * all memory ops have completed wrt other CPU's ( see 7-15 POP DJB ).
*/ */
#define eieio() __asm__ __volatile__ ("BCR 15,0") #define eieio() __asm__ __volatile__ ( "bcr 15,0" : : : "memory" )
# define SYNC_OTHER_CORES(x) eieio() # define SYNC_OTHER_CORES(x) eieio()
#define mb() eieio() #define mb() eieio()
#define rmb() eieio() #define rmb() eieio()
......
...@@ -91,15 +91,17 @@ static inline void global_flush_tlb(void) ...@@ -91,15 +91,17 @@ static inline void global_flush_tlb(void)
static inline void __flush_tlb_mm(struct mm_struct * mm) static inline void __flush_tlb_mm(struct mm_struct * mm)
{ {
preempt_disable();
if (mm->cpu_vm_mask != (1UL << smp_processor_id())) { if (mm->cpu_vm_mask != (1UL << smp_processor_id())) {
/* mm was active on more than one cpu. */ /* mm was active on more than one cpu. */
if (mm == current->active_mm && if (mm == current->active_mm &&
atomic_read(&mm->mm_count) == 1) atomic_read(&mm->mm_users) == 1)
/* this cpu is the only one using the mm. */ /* this cpu is the only one using the mm. */
mm->cpu_vm_mask = 1UL << smp_processor_id(); mm->cpu_vm_mask = 1UL << smp_processor_id();
global_flush_tlb(); global_flush_tlb();
} else } else
local_flush_tlb(); local_flush_tlb();
preempt_enable();
} }
static inline void flush_tlb(void) static inline void flush_tlb(void)
......
...@@ -248,6 +248,7 @@ ...@@ -248,6 +248,7 @@
#define __NR_epoll_ctl 250 #define __NR_epoll_ctl 250
#define __NR_epoll_wait 251 #define __NR_epoll_wait 251
#define __NR_set_tid_address 252 #define __NR_set_tid_address 252
#define __NR_fadvise64 253
/* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */ /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
......
...@@ -14,6 +14,8 @@ enum km_type { ...@@ -14,6 +14,8 @@ enum km_type {
KM_PTE1, KM_PTE1,
KM_IRQ0, KM_IRQ0,
KM_IRQ1, KM_IRQ1,
KM_SOFTIRQ0,
KM_SOFTIRQ1,
KM_TYPE_NR KM_TYPE_NR
}; };
......
...@@ -159,6 +159,9 @@ struct sigaction { ...@@ -159,6 +159,9 @@ struct sigaction {
struct k_sigaction { struct k_sigaction {
struct sigaction sa; struct sigaction sa;
}; };
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#else #else
/* Here we must cater to libcs that poke about in kernel headers. */ /* Here we must cater to libcs that poke about in kernel headers. */
...@@ -175,8 +178,6 @@ struct sigaction { ...@@ -175,8 +178,6 @@ struct sigaction {
#define sa_handler _u._sa_handler #define sa_handler _u._sa_handler
#define sa_sigaction _u._sa_sigaction #define sa_sigaction _u._sa_sigaction
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
typedef struct sigaltstack { typedef struct sigaltstack {
......
...@@ -139,5 +139,17 @@ typedef struct { ...@@ -139,5 +139,17 @@ typedef struct {
: "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \ : "a" (&(rw)->lock), "i" (__DIAG44_OPERAND) \
: "2", "3", "cc" ) : "2", "3", "cc" )
extern inline int _raw_write_trylock(rwlock_t *rw)
{
unsigned int result, reg;
__asm__ __volatile__(" llihh %0,0x8000\n"
" basr %1,0\n"
"0: csg %0,%1,0(%3)\n"
: "=&d" (result), "=&d" (reg), "+m" (rw->lock)
: "a" (&rw->lock) : "cc" );
return !result;
}
#endif /* __ASM_SPINLOCK_H */ #endif /* __ASM_SPINLOCK_H */
...@@ -233,7 +233,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) ...@@ -233,7 +233,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
* all memory ops have completed wrt other CPU's ( see 7-15 POP DJB ). * all memory ops have completed wrt other CPU's ( see 7-15 POP DJB ).
*/ */
#define eieio() __asm__ __volatile__ ("BCR 15,0") #define eieio() __asm__ __volatile__ ( "bcr 15,0" : : : "memory" )
# define SYNC_OTHER_CORES(x) eieio() # define SYNC_OTHER_CORES(x) eieio()
#define mb() eieio() #define mb() eieio()
#define rmb() eieio() #define rmb() eieio()
......
...@@ -88,15 +88,17 @@ static inline void global_flush_tlb(void) ...@@ -88,15 +88,17 @@ static inline void global_flush_tlb(void)
static inline void __flush_tlb_mm(struct mm_struct * mm) static inline void __flush_tlb_mm(struct mm_struct * mm)
{ {
preempt_disable();
if (mm->cpu_vm_mask != (1UL << smp_processor_id())) { if (mm->cpu_vm_mask != (1UL << smp_processor_id())) {
/* mm was active on more than one cpu. */ /* mm was active on more than one cpu. */
if (mm == current->active_mm && if (mm == current->active_mm &&
atomic_read(&mm->mm_count) == 1) atomic_read(&mm->mm_users) == 1)
/* this cpu is the only one using the mm. */ /* this cpu is the only one using the mm. */
mm->cpu_vm_mask = 1UL << smp_processor_id(); mm->cpu_vm_mask = 1UL << smp_processor_id();
global_flush_tlb(); global_flush_tlb();
} else } else
local_flush_tlb(); local_flush_tlb();
preempt_enable();
} }
static inline void flush_tlb(void) static inline void flush_tlb(void)
......
...@@ -215,6 +215,7 @@ ...@@ -215,6 +215,7 @@
#define __NR_epoll_ctl 250 #define __NR_epoll_ctl 250
#define __NR_epoll_wait 251 #define __NR_epoll_wait 251
#define __NR_set_tid_address 252 #define __NR_set_tid_address 252
#define __NR_fadvise64 253
/* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */ /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
......
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