forked from Minki/linux
Merge remote branch 'tip/x86/entry' into kvm-updates/2.6.33
Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
commit
58988b07cf
10
arch/Kconfig
10
arch/Kconfig
@ -83,6 +83,13 @@ config KRETPROBES
|
||||
def_bool y
|
||||
depends on KPROBES && HAVE_KRETPROBES
|
||||
|
||||
config USER_RETURN_NOTIFIER
|
||||
bool
|
||||
depends on HAVE_USER_RETURN_NOTIFIER
|
||||
help
|
||||
Provide a kernel-internal notification when a cpu is about to
|
||||
switch to user mode.
|
||||
|
||||
config HAVE_IOREMAP_PROT
|
||||
bool
|
||||
|
||||
@ -126,4 +133,7 @@ config HAVE_DMA_API_DEBUG
|
||||
config HAVE_DEFAULT_NO_SPIN_MUTEXES
|
||||
bool
|
||||
|
||||
config HAVE_USER_RETURN_NOTIFIER
|
||||
bool
|
||||
|
||||
source "kernel/gcov/Kconfig"
|
||||
|
@ -50,6 +50,7 @@ config X86
|
||||
select HAVE_KERNEL_BZIP2
|
||||
select HAVE_KERNEL_LZMA
|
||||
select HAVE_ARCH_KMEMCHECK
|
||||
select HAVE_USER_RETURN_NOTIFIER
|
||||
|
||||
config OUTPUT_FORMAT
|
||||
string
|
||||
|
@ -83,6 +83,7 @@ struct thread_info {
|
||||
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
|
||||
#define TIF_SECCOMP 8 /* secure computing */
|
||||
#define TIF_MCE_NOTIFY 10 /* notify userspace of an MCE */
|
||||
#define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */
|
||||
#define TIF_NOTSC 16 /* TSC is not accessible in userland */
|
||||
#define TIF_IA32 17 /* 32bit process */
|
||||
#define TIF_FORK 18 /* ret_from_fork */
|
||||
@ -107,6 +108,7 @@ struct thread_info {
|
||||
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
|
||||
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
|
||||
#define _TIF_MCE_NOTIFY (1 << TIF_MCE_NOTIFY)
|
||||
#define _TIF_USER_RETURN_NOTIFY (1 << TIF_USER_RETURN_NOTIFY)
|
||||
#define _TIF_NOTSC (1 << TIF_NOTSC)
|
||||
#define _TIF_IA32 (1 << TIF_IA32)
|
||||
#define _TIF_FORK (1 << TIF_FORK)
|
||||
@ -142,13 +144,14 @@ struct thread_info {
|
||||
|
||||
/* Only used for 64 bit */
|
||||
#define _TIF_DO_NOTIFY_MASK \
|
||||
(_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_NOTIFY_RESUME)
|
||||
(_TIF_SIGPENDING | _TIF_MCE_NOTIFY | _TIF_NOTIFY_RESUME | \
|
||||
_TIF_USER_RETURN_NOTIFY)
|
||||
|
||||
/* flags to check in __switch_to() */
|
||||
#define _TIF_WORK_CTXSW \
|
||||
(_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_NOTSC)
|
||||
|
||||
#define _TIF_WORK_CTXSW_PREV _TIF_WORK_CTXSW
|
||||
#define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY)
|
||||
#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG)
|
||||
|
||||
#define PREEMPT_ACTIVE 0x10000000
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <linux/pm.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/user-return-notifier.h>
|
||||
#include <trace/events/power.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/apic.h>
|
||||
@ -224,6 +225,7 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
|
||||
*/
|
||||
memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
|
||||
}
|
||||
propagate_user_return_notify(prev_p, next_p);
|
||||
}
|
||||
|
||||
int sys_fork(struct pt_regs *regs)
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/user-return-notifier.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/ucontext.h>
|
||||
@ -872,6 +873,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
|
||||
if (current->replacement_session_keyring)
|
||||
key_replace_session_keyring();
|
||||
}
|
||||
if (thread_info_flags & _TIF_USER_RETURN_NOTIFY)
|
||||
fire_user_return_notifiers();
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
clear_thread_flag(TIF_IRET);
|
||||
|
49
include/linux/user-return-notifier.h
Normal file
49
include/linux/user-return-notifier.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef _LINUX_USER_RETURN_NOTIFIER_H
|
||||
#define _LINUX_USER_RETURN_NOTIFIER_H
|
||||
|
||||
#ifdef CONFIG_USER_RETURN_NOTIFIER
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
struct user_return_notifier {
|
||||
void (*on_user_return)(struct user_return_notifier *urn);
|
||||
struct hlist_node link;
|
||||
};
|
||||
|
||||
|
||||
void user_return_notifier_register(struct user_return_notifier *urn);
|
||||
void user_return_notifier_unregister(struct user_return_notifier *urn);
|
||||
|
||||
static inline void propagate_user_return_notify(struct task_struct *prev,
|
||||
struct task_struct *next)
|
||||
{
|
||||
if (test_tsk_thread_flag(prev, TIF_USER_RETURN_NOTIFY)) {
|
||||
clear_tsk_thread_flag(prev, TIF_USER_RETURN_NOTIFY);
|
||||
set_tsk_thread_flag(next, TIF_USER_RETURN_NOTIFY);
|
||||
}
|
||||
}
|
||||
|
||||
void fire_user_return_notifiers(void);
|
||||
|
||||
static inline void clear_user_return_notifier(struct task_struct *p)
|
||||
{
|
||||
clear_tsk_thread_flag(p, TIF_USER_RETURN_NOTIFY);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct user_return_notifier {};
|
||||
|
||||
static inline void propagate_user_return_notify(struct task_struct *prev,
|
||||
struct task_struct *next)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void fire_user_return_notifiers(void) {}
|
||||
|
||||
static inline void clear_user_return_notifier(struct task_struct *p) {}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -96,6 +96,7 @@ obj-$(CONFIG_SMP) += sched_cpupri.o
|
||||
obj-$(CONFIG_SLOW_WORK) += slow-work.o
|
||||
obj-$(CONFIG_SLOW_WORK_DEBUG) += slow-work-debugfs.o
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o
|
||||
obj-$(CONFIG_USER_RETURN_NOTIFIER) += user-return-notifier.o
|
||||
|
||||
ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
|
||||
# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include <linux/magic.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/posix-timers.h>
|
||||
#include <linux/user-return-notifier.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/pgalloc.h>
|
||||
@ -249,6 +250,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
|
||||
goto out;
|
||||
|
||||
setup_thread_stack(tsk, orig);
|
||||
clear_user_return_notifier(tsk);
|
||||
stackend = end_of_stack(tsk);
|
||||
*stackend = STACK_END_MAGIC; /* for overflow detection */
|
||||
|
||||
|
46
kernel/user-return-notifier.c
Normal file
46
kernel/user-return-notifier.c
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
#include <linux/user-return-notifier.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
static DEFINE_PER_CPU(struct hlist_head, return_notifier_list);
|
||||
|
||||
#define URN_LIST_HEAD per_cpu(return_notifier_list, raw_smp_processor_id())
|
||||
|
||||
/*
|
||||
* Request a notification when the current cpu returns to userspace. Must be
|
||||
* called in atomic context. The notifier will also be called in atomic
|
||||
* context.
|
||||
*/
|
||||
void user_return_notifier_register(struct user_return_notifier *urn)
|
||||
{
|
||||
set_tsk_thread_flag(current, TIF_USER_RETURN_NOTIFY);
|
||||
hlist_add_head(&urn->link, &URN_LIST_HEAD);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(user_return_notifier_register);
|
||||
|
||||
/*
|
||||
* Removes a registered user return notifier. Must be called from atomic
|
||||
* context, and from the same cpu registration occured in.
|
||||
*/
|
||||
void user_return_notifier_unregister(struct user_return_notifier *urn)
|
||||
{
|
||||
hlist_del(&urn->link);
|
||||
if (hlist_empty(&URN_LIST_HEAD))
|
||||
clear_tsk_thread_flag(current, TIF_USER_RETURN_NOTIFY);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(user_return_notifier_unregister);
|
||||
|
||||
/* Calls registered user return notifiers */
|
||||
void fire_user_return_notifiers(void)
|
||||
{
|
||||
struct user_return_notifier *urn;
|
||||
struct hlist_node *tmp1, *tmp2;
|
||||
struct hlist_head *head;
|
||||
|
||||
head = &get_cpu_var(return_notifier_list);
|
||||
hlist_for_each_entry_safe(urn, tmp1, tmp2, head, link)
|
||||
urn->on_user_return(urn);
|
||||
put_cpu_var(return_notifier_list);
|
||||
}
|
Loading…
Reference in New Issue
Block a user