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

Commit b9d989c7 authored by Andy Lutomirski's avatar Andy Lutomirski Committed by Ingo Molnar
Browse files

x86/asm: Move the thread_info::status field to thread_struct



Because sched.h and thread_info.h are a tangled mess, I turned
in_compat_syscall() into a macro.  If we had current_thread_struct()
or similar and we could use it from thread_info.h, then this would
be a bit cleaner.

Signed-off-by: default avatarAndy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Jann Horn <jann@thejh.net>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/ccc8a1b2f41f9c264a41f771bb4a6539a642ad72.1473801993.git.luto@kernel.org


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent d4b80afb
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -209,7 +209,7 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
	 * special case only applies after poking regs and before the
	 * very next return to user mode.
	 */
	ti->status &= ~(TS_COMPAT|TS_I386_REGS_POKED);
	current->thread.status &= ~(TS_COMPAT|TS_I386_REGS_POKED);
#endif

	user_enter_irqoff();
@@ -307,7 +307,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs)
	unsigned int nr = (unsigned int)regs->orig_ax;

#ifdef CONFIG_IA32_EMULATION
	ti->status |= TS_COMPAT;
	current->thread.status |= TS_COMPAT;
#endif

	if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY) {
+12 −0
Original line number Diff line number Diff line
@@ -389,6 +389,9 @@ struct thread_struct {
	unsigned short		fsindex;
	unsigned short		gsindex;
#endif

	u32			status;		/* thread synchronous flags */

#ifdef CONFIG_X86_64
	unsigned long		fsbase;
	unsigned long		gsbase;
@@ -434,6 +437,15 @@ struct thread_struct {
	 */
};

/*
 * Thread-synchronous status.
 *
 * This is different from the flags in that nobody else
 * ever touches our thread-synchronous status, so we don't
 * have to worry about atomic accesses.
 */
#define TS_COMPAT		0x0002	/* 32bit syscall active (64BIT)*/

/*
 * Set IOPL bits in EFLAGS from given mask
 */
+5 −15
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ static inline long syscall_get_error(struct task_struct *task,
	 * TS_COMPAT is set for 32-bit syscall entries and then
	 * remains set until we return to user mode.
	 */
	if (task_thread_info(task)->status & (TS_COMPAT|TS_I386_REGS_POKED))
	if (task->thread.status & (TS_COMPAT|TS_I386_REGS_POKED))
		/*
		 * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
		 * and will match correctly in comparisons.
@@ -116,7 +116,7 @@ static inline void syscall_get_arguments(struct task_struct *task,
					 unsigned long *args)
{
# ifdef CONFIG_IA32_EMULATION
	if (task_thread_info(task)->status & TS_COMPAT)
	if (task->thread.status & TS_COMPAT)
		switch (i) {
		case 0:
			if (!n--) break;
@@ -177,7 +177,7 @@ static inline void syscall_set_arguments(struct task_struct *task,
					 const unsigned long *args)
{
# ifdef CONFIG_IA32_EMULATION
	if (task_thread_info(task)->status & TS_COMPAT)
	if (task->thread.status & TS_COMPAT)
		switch (i) {
		case 0:
			if (!n--) break;
@@ -234,18 +234,8 @@ static inline void syscall_set_arguments(struct task_struct *task,

static inline int syscall_get_arch(void)
{
#ifdef CONFIG_IA32_EMULATION
	/*
	 * TS_COMPAT is set for 32-bit syscall entry and then
	 * remains set until we return to user mode.
	 *
	 * x32 tasks should be considered AUDIT_ARCH_X86_64.
	 */
	if (task_thread_info(current)->status & TS_COMPAT)
		return AUDIT_ARCH_I386;
#endif
	/* Both x32 and x86_64 are considered "64-bit". */
	return AUDIT_ARCH_X86_64;
	/* x32 tasks should be considered AUDIT_ARCH_X86_64. */
	return in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
}
#endif	/* CONFIG_X86_32 */

+4 −19
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ struct task_struct;
struct thread_info {
	struct task_struct	*task;		/* main task structure */
	__u32			flags;		/* low level flags */
	__u32			status;		/* thread synchronous flags */
	__u32			cpu;		/* current CPU */
};

@@ -253,31 +252,17 @@ static inline int arch_within_stack_frames(const void * const stack,

#endif

/*
 * Thread-synchronous status.
 *
 * This is different from the flags in that nobody else
 * ever touches our thread-synchronous status, so we don't
 * have to worry about atomic accesses.
 */
#define TS_COMPAT		0x0002	/* 32bit syscall active (64BIT)*/
#ifdef CONFIG_COMPAT
#define TS_I386_REGS_POKED	0x0004	/* regs poked by 32-bit ptracer */
#endif

#ifndef __ASSEMBLY__

static inline bool in_ia32_syscall(void)
{
#ifdef CONFIG_X86_32
	return true;
#endif
#ifdef CONFIG_IA32_EMULATION
	if (current_thread_info()->status & TS_COMPAT)
		return true;
#define in_ia32_syscall() true
#else
#define in_ia32_syscall() (IS_ENABLED(CONFIG_IA32_EMULATION) && \
			   current->thread.status & TS_COMPAT)
#endif
	return false;
}

/*
 * Force syscall return via IRET by making it look as if there was
+0 −1
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ void common(void) {

	BLANK();
	OFFSET(TI_flags, thread_info, flags);
	OFFSET(TI_status, thread_info, status);

	BLANK();
	OFFSET(TASK_addr_limit, task_struct, thread.addr_limit);
Loading