diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-03 19:13:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-03 19:13:28 -0400 |
commit | 1a4a2bc460721bc8f91e4c1294d39b38e5af132f (patch) | |
tree | fe646d05f6e17f05601e0a32cc796bec718ab6e7 /include | |
parent | 110a9e42b68719f584879c5c5c727bbae90d15f9 (diff) | |
parent | 1ef55be16ed69538f89e0a6508be5e62fdc9851c (diff) |
Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull low-level x86 updates from Ingo Molnar:
"In this cycle this topic tree has become one of those 'super topics'
that accumulated a lot of changes:
- Add CONFIG_VMAP_STACK=y support to the core kernel and enable it on
x86 - preceded by an array of changes. v4.8 saw preparatory changes
in this area already - this is the rest of the work. Includes the
thread stack caching performance optimization. (Andy Lutomirski)
- switch_to() cleanups and all around enhancements. (Brian Gerst)
- A large number of dumpstack infrastructure enhancements and an
unwinder abstraction. The secret long term plan is safe(r) live
patching plus maybe another attempt at debuginfo based unwinding -
but all these current bits are standalone enhancements in a frame
pointer based debug environment as well. (Josh Poimboeuf)
- More __ro_after_init and const annotations. (Kees Cook)
- Enable KASLR for the vmemmap memory region. (Thomas Garnier)"
[ The virtually mapped stack changes are pretty fundamental, and not
x86-specific per se, even if they are only used on x86 right now. ]
* 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (70 commits)
x86/asm: Get rid of __read_cr4_safe()
thread_info: Use unsigned long for flags
x86/alternatives: Add stack frame dependency to alternative_call_2()
x86/dumpstack: Fix show_stack() task pointer regression
x86/dumpstack: Remove dump_trace() and related callbacks
x86/dumpstack: Convert show_trace_log_lvl() to use the new unwinder
oprofile/x86: Convert x86_backtrace() to use the new unwinder
x86/stacktrace: Convert save_stack_trace_*() to use the new unwinder
perf/x86: Convert perf_callchain_kernel() to use the new unwinder
x86/unwind: Add new unwind interface and implementations
x86/dumpstack: Remove NULL task pointer convention
fork: Optimize task creation by caching two thread stacks per CPU if CONFIG_VMAP_STACK=y
sched/core: Free the stack early if CONFIG_THREAD_INFO_IN_TASK
lib/syscall: Pin the task stack in collect_syscall()
x86/process: Pin the target stack in get_wchan()
x86/dumpstack: Pin the target stack when dumping it
kthread: Pin the stack via try_get_task_stack()/put_task_stack() in to_live_kthread() function
sched/core: Add try_get_task_stack() and put_task_stack()
x86/entry/64: Fix a minor comment rebase error
iommu/amd: Don't put completion-wait semaphore on stack
...
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/ftrace.h | 17 | ||||
-rw-r--r-- | include/linux/init_task.h | 11 | ||||
-rw-r--r-- | include/linux/sched.h | 81 | ||||
-rw-r--r-- | include/linux/thread_info.h | 15 |
4 files changed, 121 insertions, 3 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 7d565afe35d2..6f93ac46e7f0 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h | |||
@@ -795,7 +795,12 @@ struct ftrace_ret_stack { | |||
795 | unsigned long func; | 795 | unsigned long func; |
796 | unsigned long long calltime; | 796 | unsigned long long calltime; |
797 | unsigned long long subtime; | 797 | unsigned long long subtime; |
798 | #ifdef HAVE_FUNCTION_GRAPH_FP_TEST | ||
798 | unsigned long fp; | 799 | unsigned long fp; |
800 | #endif | ||
801 | #ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR | ||
802 | unsigned long *retp; | ||
803 | #endif | ||
799 | }; | 804 | }; |
800 | 805 | ||
801 | /* | 806 | /* |
@@ -807,7 +812,10 @@ extern void return_to_handler(void); | |||
807 | 812 | ||
808 | extern int | 813 | extern int |
809 | ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth, | 814 | ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth, |
810 | unsigned long frame_pointer); | 815 | unsigned long frame_pointer, unsigned long *retp); |
816 | |||
817 | unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx, | ||
818 | unsigned long ret, unsigned long *retp); | ||
811 | 819 | ||
812 | /* | 820 | /* |
813 | * Sometimes we don't want to trace a function with the function | 821 | * Sometimes we don't want to trace a function with the function |
@@ -870,6 +878,13 @@ static inline int task_curr_ret_stack(struct task_struct *tsk) | |||
870 | return -1; | 878 | return -1; |
871 | } | 879 | } |
872 | 880 | ||
881 | static inline unsigned long | ||
882 | ftrace_graph_ret_addr(struct task_struct *task, int *idx, unsigned long ret, | ||
883 | unsigned long *retp) | ||
884 | { | ||
885 | return ret; | ||
886 | } | ||
887 | |||
873 | static inline void pause_graph_tracing(void) { } | 888 | static inline void pause_graph_tracing(void) { } |
874 | static inline void unpause_graph_tracing(void) { } | 889 | static inline void unpause_graph_tracing(void) { } |
875 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 890 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index f8834f820ec2..325f649d77ff 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <net/net_namespace.h> | 15 | #include <net/net_namespace.h> |
16 | #include <linux/sched/rt.h> | 16 | #include <linux/sched/rt.h> |
17 | 17 | ||
18 | #include <asm/thread_info.h> | ||
19 | |||
18 | #ifdef CONFIG_SMP | 20 | #ifdef CONFIG_SMP |
19 | # define INIT_PUSHABLE_TASKS(tsk) \ | 21 | # define INIT_PUSHABLE_TASKS(tsk) \ |
20 | .pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO), | 22 | .pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO), |
@@ -183,12 +185,21 @@ extern struct task_group root_task_group; | |||
183 | # define INIT_KASAN(tsk) | 185 | # define INIT_KASAN(tsk) |
184 | #endif | 186 | #endif |
185 | 187 | ||
188 | #ifdef CONFIG_THREAD_INFO_IN_TASK | ||
189 | # define INIT_TASK_TI(tsk) \ | ||
190 | .thread_info = INIT_THREAD_INFO(tsk), \ | ||
191 | .stack_refcount = ATOMIC_INIT(1), | ||
192 | #else | ||
193 | # define INIT_TASK_TI(tsk) | ||
194 | #endif | ||
195 | |||
186 | /* | 196 | /* |
187 | * INIT_TASK is used to set up the first task table, touch at | 197 | * INIT_TASK is used to set up the first task table, touch at |
188 | * your own risk!. Base=0, limit=0x1fffff (=2MB) | 198 | * your own risk!. Base=0, limit=0x1fffff (=2MB) |
189 | */ | 199 | */ |
190 | #define INIT_TASK(tsk) \ | 200 | #define INIT_TASK(tsk) \ |
191 | { \ | 201 | { \ |
202 | INIT_TASK_TI(tsk) \ | ||
192 | .state = 0, \ | 203 | .state = 0, \ |
193 | .stack = init_stack, \ | 204 | .stack = init_stack, \ |
194 | .usage = ATOMIC_INIT(2), \ | 205 | .usage = ATOMIC_INIT(2), \ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index f76d75fc9eaf..7543a476178b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1471,6 +1471,13 @@ struct tlbflush_unmap_batch { | |||
1471 | }; | 1471 | }; |
1472 | 1472 | ||
1473 | struct task_struct { | 1473 | struct task_struct { |
1474 | #ifdef CONFIG_THREAD_INFO_IN_TASK | ||
1475 | /* | ||
1476 | * For reasons of header soup (see current_thread_info()), this | ||
1477 | * must be the first element of task_struct. | ||
1478 | */ | ||
1479 | struct thread_info thread_info; | ||
1480 | #endif | ||
1474 | volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ | 1481 | volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ |
1475 | void *stack; | 1482 | void *stack; |
1476 | atomic_t usage; | 1483 | atomic_t usage; |
@@ -1480,6 +1487,9 @@ struct task_struct { | |||
1480 | #ifdef CONFIG_SMP | 1487 | #ifdef CONFIG_SMP |
1481 | struct llist_node wake_entry; | 1488 | struct llist_node wake_entry; |
1482 | int on_cpu; | 1489 | int on_cpu; |
1490 | #ifdef CONFIG_THREAD_INFO_IN_TASK | ||
1491 | unsigned int cpu; /* current CPU */ | ||
1492 | #endif | ||
1483 | unsigned int wakee_flips; | 1493 | unsigned int wakee_flips; |
1484 | unsigned long wakee_flip_decay_ts; | 1494 | unsigned long wakee_flip_decay_ts; |
1485 | struct task_struct *last_wakee; | 1495 | struct task_struct *last_wakee; |
@@ -1936,6 +1946,13 @@ struct task_struct { | |||
1936 | #ifdef CONFIG_MMU | 1946 | #ifdef CONFIG_MMU |
1937 | struct task_struct *oom_reaper_list; | 1947 | struct task_struct *oom_reaper_list; |
1938 | #endif | 1948 | #endif |
1949 | #ifdef CONFIG_VMAP_STACK | ||
1950 | struct vm_struct *stack_vm_area; | ||
1951 | #endif | ||
1952 | #ifdef CONFIG_THREAD_INFO_IN_TASK | ||
1953 | /* A live task holds one reference. */ | ||
1954 | atomic_t stack_refcount; | ||
1955 | #endif | ||
1939 | /* CPU-specific state of this task */ | 1956 | /* CPU-specific state of this task */ |
1940 | struct thread_struct thread; | 1957 | struct thread_struct thread; |
1941 | /* | 1958 | /* |
@@ -1952,6 +1969,18 @@ extern int arch_task_struct_size __read_mostly; | |||
1952 | # define arch_task_struct_size (sizeof(struct task_struct)) | 1969 | # define arch_task_struct_size (sizeof(struct task_struct)) |
1953 | #endif | 1970 | #endif |
1954 | 1971 | ||
1972 | #ifdef CONFIG_VMAP_STACK | ||
1973 | static inline struct vm_struct *task_stack_vm_area(const struct task_struct *t) | ||
1974 | { | ||
1975 | return t->stack_vm_area; | ||
1976 | } | ||
1977 | #else | ||
1978 | static inline struct vm_struct *task_stack_vm_area(const struct task_struct *t) | ||
1979 | { | ||
1980 | return NULL; | ||
1981 | } | ||
1982 | #endif | ||
1983 | |||
1955 | /* Future-safe accessor for struct task_struct's cpus_allowed. */ | 1984 | /* Future-safe accessor for struct task_struct's cpus_allowed. */ |
1956 | #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) | 1985 | #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) |
1957 | 1986 | ||
@@ -2586,7 +2615,9 @@ extern void ia64_set_curr_task(int cpu, struct task_struct *p); | |||
2586 | void yield(void); | 2615 | void yield(void); |
2587 | 2616 | ||
2588 | union thread_union { | 2617 | union thread_union { |
2618 | #ifndef CONFIG_THREAD_INFO_IN_TASK | ||
2589 | struct thread_info thread_info; | 2619 | struct thread_info thread_info; |
2620 | #endif | ||
2590 | unsigned long stack[THREAD_SIZE/sizeof(long)]; | 2621 | unsigned long stack[THREAD_SIZE/sizeof(long)]; |
2591 | }; | 2622 | }; |
2592 | 2623 | ||
@@ -3074,10 +3105,34 @@ static inline void threadgroup_change_end(struct task_struct *tsk) | |||
3074 | cgroup_threadgroup_change_end(tsk); | 3105 | cgroup_threadgroup_change_end(tsk); |
3075 | } | 3106 | } |
3076 | 3107 | ||
3077 | #ifndef __HAVE_THREAD_FUNCTIONS | 3108 | #ifdef CONFIG_THREAD_INFO_IN_TASK |
3109 | |||
3110 | static inline struct thread_info *task_thread_info(struct task_struct *task) | ||
3111 | { | ||
3112 | return &task->thread_info; | ||
3113 | } | ||
3114 | |||
3115 | /* | ||
3116 | * When accessing the stack of a non-current task that might exit, use | ||
3117 | * try_get_task_stack() instead. task_stack_page will return a pointer | ||
3118 | * that could get freed out from under you. | ||
3119 | */ | ||
3120 | static inline void *task_stack_page(const struct task_struct *task) | ||
3121 | { | ||
3122 | return task->stack; | ||
3123 | } | ||
3124 | |||
3125 | #define setup_thread_stack(new,old) do { } while(0) | ||
3126 | |||
3127 | static inline unsigned long *end_of_stack(const struct task_struct *task) | ||
3128 | { | ||
3129 | return task->stack; | ||
3130 | } | ||
3131 | |||
3132 | #elif !defined(__HAVE_THREAD_FUNCTIONS) | ||
3078 | 3133 | ||
3079 | #define task_thread_info(task) ((struct thread_info *)(task)->stack) | 3134 | #define task_thread_info(task) ((struct thread_info *)(task)->stack) |
3080 | #define task_stack_page(task) ((task)->stack) | 3135 | #define task_stack_page(task) ((void *)(task)->stack) |
3081 | 3136 | ||
3082 | static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) | 3137 | static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) |
3083 | { | 3138 | { |
@@ -3104,6 +3159,24 @@ static inline unsigned long *end_of_stack(struct task_struct *p) | |||
3104 | } | 3159 | } |
3105 | 3160 | ||
3106 | #endif | 3161 | #endif |
3162 | |||
3163 | #ifdef CONFIG_THREAD_INFO_IN_TASK | ||
3164 | static inline void *try_get_task_stack(struct task_struct *tsk) | ||
3165 | { | ||
3166 | return atomic_inc_not_zero(&tsk->stack_refcount) ? | ||
3167 | task_stack_page(tsk) : NULL; | ||
3168 | } | ||
3169 | |||
3170 | extern void put_task_stack(struct task_struct *tsk); | ||
3171 | #else | ||
3172 | static inline void *try_get_task_stack(struct task_struct *tsk) | ||
3173 | { | ||
3174 | return task_stack_page(tsk); | ||
3175 | } | ||
3176 | |||
3177 | static inline void put_task_stack(struct task_struct *tsk) {} | ||
3178 | #endif | ||
3179 | |||
3107 | #define task_stack_end_corrupted(task) \ | 3180 | #define task_stack_end_corrupted(task) \ |
3108 | (*(end_of_stack(task)) != STACK_END_MAGIC) | 3181 | (*(end_of_stack(task)) != STACK_END_MAGIC) |
3109 | 3182 | ||
@@ -3390,7 +3463,11 @@ static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume) | |||
3390 | 3463 | ||
3391 | static inline unsigned int task_cpu(const struct task_struct *p) | 3464 | static inline unsigned int task_cpu(const struct task_struct *p) |
3392 | { | 3465 | { |
3466 | #ifdef CONFIG_THREAD_INFO_IN_TASK | ||
3467 | return p->cpu; | ||
3468 | #else | ||
3393 | return task_thread_info(p)->cpu; | 3469 | return task_thread_info(p)->cpu; |
3470 | #endif | ||
3394 | } | 3471 | } |
3395 | 3472 | ||
3396 | static inline int task_node(const struct task_struct *p) | 3473 | static inline int task_node(const struct task_struct *p) |
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index 2b5b10eed74f..45f004e9cc59 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h | |||
@@ -13,6 +13,21 @@ | |||
13 | struct timespec; | 13 | struct timespec; |
14 | struct compat_timespec; | 14 | struct compat_timespec; |
15 | 15 | ||
16 | #ifdef CONFIG_THREAD_INFO_IN_TASK | ||
17 | struct thread_info { | ||
18 | unsigned long flags; /* low level flags */ | ||
19 | }; | ||
20 | |||
21 | #define INIT_THREAD_INFO(tsk) \ | ||
22 | { \ | ||
23 | .flags = 0, \ | ||
24 | } | ||
25 | #endif | ||
26 | |||
27 | #ifdef CONFIG_THREAD_INFO_IN_TASK | ||
28 | #define current_thread_info() ((struct thread_info *)current) | ||
29 | #endif | ||
30 | |||
16 | /* | 31 | /* |
17 | * System call restart block. | 32 | * System call restart block. |
18 | */ | 33 | */ |