433e2f307b
This reverts commit 6b5c8045ec
.
Conflicts:
arch/arm/kernel/ptrace.c
The new syscall restarting code can lead to problems if we take an
interrupt in userspace just before restarting the svc instruction. If
a signal is delivered when returning from the interrupt, the
TIF_SYSCALL_RESTARTSYS will remain set and cause any syscalls executed
from the signal handler to be treated as a restart of the previously
interrupted system call. This includes the final sigreturn call, meaning
that we may fail to exit from the signal context. Furthermore, if a
system call made from the signal handler requires a restart via the
restart_block, it is possible to clear the thread flag and fail to
restart the originally interrupted system call.
The right solution to this problem is to perform the restarting in the
kernel, avoiding the possibility of handling a further signal before the
restart is complete. Since we're almost at -rc6, let's revert the new
method for now and aim for in-kernel restarting at a later date.
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
177 lines
5.3 KiB
C
177 lines
5.3 KiB
C
/*
|
|
* arch/arm/include/asm/thread_info.h
|
|
*
|
|
* Copyright (C) 2002 Russell King.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
#ifndef __ASM_ARM_THREAD_INFO_H
|
|
#define __ASM_ARM_THREAD_INFO_H
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#include <linux/compiler.h>
|
|
#include <asm/fpstate.h>
|
|
|
|
#define THREAD_SIZE_ORDER 1
|
|
#define THREAD_SIZE 8192
|
|
#define THREAD_START_SP (THREAD_SIZE - 8)
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
struct task_struct;
|
|
struct exec_domain;
|
|
|
|
#include <asm/types.h>
|
|
#include <asm/domain.h>
|
|
|
|
typedef unsigned long mm_segment_t;
|
|
|
|
struct cpu_context_save {
|
|
__u32 r4;
|
|
__u32 r5;
|
|
__u32 r6;
|
|
__u32 r7;
|
|
__u32 r8;
|
|
__u32 r9;
|
|
__u32 sl;
|
|
__u32 fp;
|
|
__u32 sp;
|
|
__u32 pc;
|
|
__u32 extra[2]; /* Xscale 'acc' register, etc */
|
|
};
|
|
|
|
/*
|
|
* low level task data that entry.S needs immediate access to.
|
|
* __switch_to() assumes cpu_context follows immediately after cpu_domain.
|
|
*/
|
|
struct thread_info {
|
|
unsigned long flags; /* low level flags */
|
|
int preempt_count; /* 0 => preemptable, <0 => bug */
|
|
mm_segment_t addr_limit; /* address limit */
|
|
struct task_struct *task; /* main task structure */
|
|
struct exec_domain *exec_domain; /* execution domain */
|
|
__u32 cpu; /* cpu */
|
|
__u32 cpu_domain; /* cpu domain */
|
|
struct cpu_context_save cpu_context; /* cpu context */
|
|
__u32 syscall; /* syscall number */
|
|
__u8 used_cp[16]; /* thread used copro */
|
|
unsigned long tp_value;
|
|
struct crunch_state crunchstate;
|
|
union fp_state fpstate __attribute__((aligned(8)));
|
|
union vfp_state vfpstate;
|
|
#ifdef CONFIG_ARM_THUMBEE
|
|
unsigned long thumbee_state; /* ThumbEE Handler Base register */
|
|
#endif
|
|
struct restart_block restart_block;
|
|
};
|
|
|
|
#define INIT_THREAD_INFO(tsk) \
|
|
{ \
|
|
.task = &tsk, \
|
|
.exec_domain = &default_exec_domain, \
|
|
.flags = 0, \
|
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
|
.addr_limit = KERNEL_DS, \
|
|
.cpu_domain = domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
|
|
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
|
|
domain_val(DOMAIN_IO, DOMAIN_CLIENT), \
|
|
.restart_block = { \
|
|
.fn = do_no_restart_syscall, \
|
|
}, \
|
|
}
|
|
|
|
#define init_thread_info (init_thread_union.thread_info)
|
|
#define init_stack (init_thread_union.stack)
|
|
|
|
/*
|
|
* how to get the thread information struct from C
|
|
*/
|
|
static inline struct thread_info *current_thread_info(void) __attribute_const__;
|
|
|
|
static inline struct thread_info *current_thread_info(void)
|
|
{
|
|
register unsigned long sp asm ("sp");
|
|
return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
|
|
}
|
|
|
|
#define thread_saved_pc(tsk) \
|
|
((unsigned long)(task_thread_info(tsk)->cpu_context.pc))
|
|
#define thread_saved_sp(tsk) \
|
|
((unsigned long)(task_thread_info(tsk)->cpu_context.sp))
|
|
#define thread_saved_fp(tsk) \
|
|
((unsigned long)(task_thread_info(tsk)->cpu_context.fp))
|
|
|
|
extern void crunch_task_disable(struct thread_info *);
|
|
extern void crunch_task_copy(struct thread_info *, void *);
|
|
extern void crunch_task_restore(struct thread_info *, void *);
|
|
extern void crunch_task_release(struct thread_info *);
|
|
|
|
extern void iwmmxt_task_disable(struct thread_info *);
|
|
extern void iwmmxt_task_copy(struct thread_info *, void *);
|
|
extern void iwmmxt_task_restore(struct thread_info *, void *);
|
|
extern void iwmmxt_task_release(struct thread_info *);
|
|
extern void iwmmxt_task_switch(struct thread_info *);
|
|
|
|
extern void vfp_sync_hwstate(struct thread_info *);
|
|
extern void vfp_flush_hwstate(struct thread_info *);
|
|
|
|
struct user_vfp;
|
|
struct user_vfp_exc;
|
|
|
|
extern int vfp_preserve_user_clear_hwstate(struct user_vfp __user *,
|
|
struct user_vfp_exc __user *);
|
|
extern int vfp_restore_user_hwstate(struct user_vfp __user *,
|
|
struct user_vfp_exc __user *);
|
|
#endif
|
|
|
|
/*
|
|
* We use bit 30 of the preempt_count to indicate that kernel
|
|
* preemption is occurring. See <asm/hardirq.h>.
|
|
*/
|
|
#define PREEMPT_ACTIVE 0x40000000
|
|
|
|
/*
|
|
* thread information flags:
|
|
* TIF_SYSCALL_TRACE - syscall trace active
|
|
* TIF_SYSCAL_AUDIT - syscall auditing active
|
|
* TIF_SIGPENDING - signal pending
|
|
* TIF_NEED_RESCHED - rescheduling necessary
|
|
* TIF_NOTIFY_RESUME - callback before returning to user
|
|
* TIF_USEDFPU - FPU was used by this task this quantum (SMP)
|
|
* TIF_POLLING_NRFLAG - true if poll_idle() is polling TIF_NEED_RESCHED
|
|
*/
|
|
#define TIF_SIGPENDING 0
|
|
#define TIF_NEED_RESCHED 1
|
|
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
|
|
#define TIF_SYSCALL_TRACE 8
|
|
#define TIF_SYSCALL_AUDIT 9
|
|
#define TIF_POLLING_NRFLAG 16
|
|
#define TIF_USING_IWMMXT 17
|
|
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
|
|
#define TIF_RESTORE_SIGMASK 20
|
|
#define TIF_SECCOMP 21
|
|
#define TIF_SWITCH_MM 22 /* deferred switch_mm */
|
|
|
|
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
|
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
|
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
|
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
|
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
|
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
|
|
#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
|
|
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
|
|
|
|
/* Checks for any syscall work in entry-common.S */
|
|
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT)
|
|
|
|
/*
|
|
* Change these and you break ASM code in entry-common.S
|
|
*/
|
|
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_RESUME)
|
|
|
|
#endif /* __KERNEL__ */
|
|
#endif /* __ASM_ARM_THREAD_INFO_H */
|