Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3a73acb authored by Martin Schwidefsky's avatar Martin Schwidefsky
Browse files

s390: split TIF bits into CIF, PIF and TIF bits



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: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent beef560b
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -93,7 +93,9 @@ struct _lowcore {
	__u32	save_area_sync[8];		/* 0x0200 */
	__u32	save_area_sync[8];		/* 0x0200 */
	__u32	save_area_async[8];		/* 0x0220 */
	__u32	save_area_async[8];		/* 0x0220 */
	__u32	save_area_restart[1];		/* 0x0240 */
	__u32	save_area_restart[1];		/* 0x0240 */
	__u8	pad_0x0244[0x0248-0x0244];	/* 0x0244 */

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


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

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


	/* Return psws. */
	/* Return psws. */
	psw_t	return_psw;			/* 0x0290 */
	psw_t	return_psw;			/* 0x0290 */
+3 −3
Original line number Original line Diff line number Diff line
@@ -36,7 +36,7 @@ static inline void set_user_asce(struct mm_struct *mm)


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


static inline void clear_user_asce(void)
static inline void clear_user_asce(void)
@@ -54,7 +54,7 @@ static inline void load_kernel_asce(void)
	__ctl_store(asce, 1, 1);
	__ctl_store(asce, 1, 1);
	if (asce != S390_lowcore.kernel_asce)
	if (asce != S390_lowcore.kernel_asce)
		__ctl_load(S390_lowcore.kernel_asce, 1, 1);
		__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,
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
@@ -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, 1, 1);
	__ctl_load(S390_lowcore.kernel_asce, 7, 7);
	__ctl_load(S390_lowcore.kernel_asce, 7, 7);
	/* Delay loading of the new ASCE to control registers CR1 & CR7 */
	/* 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_inc(&next->context.attach_count);
	atomic_dec(&prev->context.attach_count);
	atomic_dec(&prev->context.attach_count);
	if (MACHINE_HAS_TLB_LC)
	if (MACHINE_HAS_TLB_LC)
+22 −0
Original line number Original line Diff line number Diff line
@@ -11,6 +11,13 @@
#ifndef __ASM_S390_PROCESSOR_H
#ifndef __ASM_S390_PROCESSOR_H
#define __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__
#ifndef __ASSEMBLY__


#include <linux/linkage.h>
#include <linux/linkage.h>
@@ -21,6 +28,21 @@
#include <asm/setup.h>
#include <asm/setup.h>
#include <asm/runtime_instr.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
 * Default implementation of macro that returns current
 * instruction pointer ("program counter").
 * instruction pointer ("program counter").
+22 −0
Original line number Original line Diff line number Diff line
@@ -8,6 +8,12 @@


#include <uapi/asm/ptrace.h>
#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__
#ifndef __ASSEMBLY__


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


/*
/*
@@ -79,6 +86,21 @@ struct per_struct_kernel {
#define PER_CONTROL_SUSPENSION		0x00400000UL
#define PER_CONTROL_SUSPENSION		0x00400000UL
#define PER_CONTROL_ALTERATION		0x00200000UL
#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.
 * These are defined as per linux/ptrace.h, which see.
 */
 */
+1 −1
Original line number Original line Diff line number Diff line
@@ -28,7 +28,7 @@ extern const unsigned int sys_call_table_emu[];
static inline long syscall_get_nr(struct task_struct *task,
static inline long syscall_get_nr(struct task_struct *task,
				  struct pt_regs *regs)
				  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;
		(regs->int_code & 0xffff) : -1;
}
}


Loading