Skip to content

Commit

Permalink
s390: split TIF bits into CIF, PIF and TIF bits
Browse files Browse the repository at this point in the history
The oi and ni instructions used in entry[64].S to set and clear bits
in the thread-flags are not guaranteed to be atomic in regard to other
CPUs. Split the TIF bits into CPU, pt_regs and thread-info specific
bits. Updates on the TIF bits are done with atomic instructions,
updates on CPU and pt_regs bits are done with non-atomic instructions.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Martin Schwidefsky committed May 20, 2014
1 parent beef560 commit d3a73ac
Show file tree
Hide file tree
Showing 16 changed files with 173 additions and 126 deletions.
8 changes: 6 additions & 2 deletions arch/s390/include/asm/lowcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ struct _lowcore {
__u32 save_area_sync[8]; /* 0x0200 */
__u32 save_area_async[8]; /* 0x0220 */
__u32 save_area_restart[1]; /* 0x0240 */
__u8 pad_0x0244[0x0248-0x0244]; /* 0x0244 */

/* CPU flags. */
__u32 cpu_flags; /* 0x0244 */

/* Return psws. */
psw_t return_psw; /* 0x0248 */
Expand Down Expand Up @@ -237,7 +239,9 @@ struct _lowcore {
__u64 save_area_sync[8]; /* 0x0200 */
__u64 save_area_async[8]; /* 0x0240 */
__u64 save_area_restart[1]; /* 0x0280 */
__u8 pad_0x0288[0x0290-0x0288]; /* 0x0288 */

/* CPU flags. */
__u64 cpu_flags; /* 0x0288 */

/* Return psws. */
psw_t return_psw; /* 0x0290 */
Expand Down
6 changes: 3 additions & 3 deletions arch/s390/include/asm/mmu_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ static inline void set_user_asce(struct mm_struct *mm)

S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd);
set_fs(current->thread.mm_segment);
set_thread_flag(TIF_ASCE);
set_cpu_flag(CIF_ASCE);
}

static inline void clear_user_asce(void)
Expand All @@ -54,7 +54,7 @@ static inline void load_kernel_asce(void)
__ctl_store(asce, 1, 1);
if (asce != S390_lowcore.kernel_asce)
__ctl_load(S390_lowcore.kernel_asce, 1, 1);
set_thread_flag(TIF_ASCE);
set_cpu_flag(CIF_ASCE);
}

static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
Expand All @@ -70,7 +70,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
__ctl_load(S390_lowcore.kernel_asce, 1, 1);
__ctl_load(S390_lowcore.kernel_asce, 7, 7);
/* Delay loading of the new ASCE to control registers CR1 & CR7 */
set_thread_flag(TIF_ASCE);
set_cpu_flag(CIF_ASCE);
atomic_inc(&next->context.attach_count);
atomic_dec(&prev->context.attach_count);
if (MACHINE_HAS_TLB_LC)
Expand Down
22 changes: 22 additions & 0 deletions arch/s390/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
#ifndef __ASM_S390_PROCESSOR_H
#define __ASM_S390_PROCESSOR_H

#define CIF_MCCK_PENDING 0 /* machine check handling is pending */
#define CIF_ASCE 1 /* user asce needs fixup / uaccess */

#define _CIF_MCCK_PENDING (1<<CIF_MCCK_PENDING)
#define _CIF_ASCE (1<<CIF_ASCE)


#ifndef __ASSEMBLY__

#include <linux/linkage.h>
Expand All @@ -21,6 +28,21 @@
#include <asm/setup.h>
#include <asm/runtime_instr.h>

static inline void set_cpu_flag(int flag)
{
S390_lowcore.cpu_flags |= (1U << flag);
}

static inline void clear_cpu_flag(int flag)
{
S390_lowcore.cpu_flags &= ~(1U << flag);
}

static inline int test_cpu_flag(int flag)
{
return !!(S390_lowcore.cpu_flags & (1U << flag));
}

/*
* Default implementation of macro that returns current
* instruction pointer ("program counter").
Expand Down
22 changes: 22 additions & 0 deletions arch/s390/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

#include <uapi/asm/ptrace.h>

#define PIF_SYSCALL 0 /* inside a system call */
#define PIF_PER_TRAP 1 /* deliver sigtrap on return to user */

#define _PIF_SYSCALL (1<<PIF_SYSCALL)
#define _PIF_PER_TRAP (1<<PIF_PER_TRAP)

#ifndef __ASSEMBLY__

#define PSW_KERNEL_BITS (PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_HOME | \
Expand All @@ -29,6 +35,7 @@ struct pt_regs
unsigned int int_code;
unsigned int int_parm;
unsigned long int_parm_long;
unsigned long flags;
};

/*
Expand Down Expand Up @@ -79,6 +86,21 @@ struct per_struct_kernel {
#define PER_CONTROL_SUSPENSION 0x00400000UL
#define PER_CONTROL_ALTERATION 0x00200000UL

static inline void set_pt_regs_flag(struct pt_regs *regs, int flag)
{
regs->flags |= (1U << flag);
}

static inline void clear_pt_regs_flag(struct pt_regs *regs, int flag)
{
regs->flags &= ~(1U << flag);
}

static inline int test_pt_regs_flag(struct pt_regs *regs, int flag)
{
return !!(regs->flags & (1U << flag));
}

/*
* These are defined as per linux/ptrace.h, which see.
*/
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extern const unsigned int sys_call_table_emu[];
static inline long syscall_get_nr(struct task_struct *task,
struct pt_regs *regs)
{
return test_tsk_thread_flag(task, TIF_SYSCALL) ?
return test_pt_regs_flag(regs, PIF_SYSCALL) ?
(regs->int_code & 0xffff) : -1;
}

Expand Down
32 changes: 12 additions & 20 deletions arch/s390/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,30 +77,22 @@ static inline struct thread_info *current_thread_info(void)
/*
* thread information flags bit numbers
*/
#define TIF_SYSCALL 0 /* inside a system call */
#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_ASCE 5 /* user asce needs fixup / uaccess */
#define TIF_PER_TRAP 6 /* deliver sigtrap on return to user */
#define TIF_MCCK_PENDING 7 /* machine check handling is pending */
#define TIF_SYSCALL_TRACE 8 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */
#define TIF_SECCOMP 10 /* secure computing */
#define TIF_SYSCALL_TRACEPOINT 11 /* syscall tracepoint instrumentation */
#define TIF_31BIT 17 /* 32bit process */
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
#define TIF_RESTORE_SIGMASK 19 /* restore signal mask in do_signal() */
#define TIF_SINGLE_STEP 20 /* This task is single stepped */
#define TIF_BLOCK_STEP 21 /* This task is block stepped */
#define TIF_NOTIFY_RESUME 0 /* callback before returning to user */
#define TIF_SIGPENDING 1 /* signal pending */
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
#define TIF_SYSCALL_TRACE 3 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 4 /* syscall auditing active */
#define TIF_SECCOMP 5 /* secure computing */
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
#define TIF_31BIT 16 /* 32bit process */
#define TIF_MEMDIE 17 /* is terminating due to OOM killer */
#define TIF_RESTORE_SIGMASK 18 /* restore signal mask in do_signal() */
#define TIF_SINGLE_STEP 19 /* This task is single stepped */
#define TIF_BLOCK_STEP 20 /* This task is block stepped */

#define _TIF_SYSCALL (1<<TIF_SYSCALL)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_ASCE (1<<TIF_ASCE)
#define _TIF_PER_TRAP (1<<TIF_PER_TRAP)
#define _TIF_MCCK_PENDING (1<<TIF_MCCK_PENDING)
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
Expand Down
2 changes: 2 additions & 0 deletions arch/s390/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ int main(void)
DEFINE(__PT_INT_CODE, offsetof(struct pt_regs, int_code));
DEFINE(__PT_INT_PARM, offsetof(struct pt_regs, int_parm));
DEFINE(__PT_INT_PARM_LONG, offsetof(struct pt_regs, int_parm_long));
DEFINE(__PT_FLAGS, offsetof(struct pt_regs, flags));
DEFINE(__PT_SIZE, sizeof(struct pt_regs));
BLANK();
DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain));
Expand Down Expand Up @@ -115,6 +116,7 @@ int main(void)
DEFINE(__LC_SAVE_AREA_SYNC, offsetof(struct _lowcore, save_area_sync));
DEFINE(__LC_SAVE_AREA_ASYNC, offsetof(struct _lowcore, save_area_async));
DEFINE(__LC_SAVE_AREA_RESTART, offsetof(struct _lowcore, save_area_restart));
DEFINE(__LC_CPU_FLAGS, offsetof(struct _lowcore, cpu_flags));
DEFINE(__LC_RETURN_PSW, offsetof(struct _lowcore, return_psw));
DEFINE(__LC_RETURN_MCCK_PSW, offsetof(struct _lowcore, return_mcck_psw));
DEFINE(__LC_SYNC_ENTER_TIMER, offsetof(struct _lowcore, sync_enter_timer));
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/compat_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
sizeof(current->thread.fp_regs));

restore_fp_regs(current->thread.fp_regs.fprs);
clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */
clear_pt_regs_flag(regs, PIF_SYSCALL); /* No longer in a system call */
return 0;
}

Expand Down
Loading

0 comments on commit d3a73ac

Please sign in to comment.