diff options
Diffstat (limited to 'arch/powerpc/kernel/process.c')
-rw-r--r-- | arch/powerpc/kernel/process.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index fb7049c054c0..eac064948780 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -33,7 +33,10 @@ | |||
33 | #include <linux/mqueue.h> | 33 | #include <linux/mqueue.h> |
34 | #include <linux/hardirq.h> | 34 | #include <linux/hardirq.h> |
35 | #include <linux/utsname.h> | 35 | #include <linux/utsname.h> |
36 | #include <linux/ftrace.h> | ||
36 | #include <linux/kernel_stat.h> | 37 | #include <linux/kernel_stat.h> |
38 | #include <linux/personality.h> | ||
39 | #include <linux/random.h> | ||
37 | 40 | ||
38 | #include <asm/pgtable.h> | 41 | #include <asm/pgtable.h> |
39 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
@@ -1008,6 +1011,14 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
1008 | unsigned long sp, ip, lr, newsp; | 1011 | unsigned long sp, ip, lr, newsp; |
1009 | int count = 0; | 1012 | int count = 0; |
1010 | int firstframe = 1; | 1013 | int firstframe = 1; |
1014 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
1015 | int curr_frame = current->curr_ret_stack; | ||
1016 | extern void return_to_handler(void); | ||
1017 | unsigned long addr = (unsigned long)return_to_handler; | ||
1018 | #ifdef CONFIG_PPC64 | ||
1019 | addr = *(unsigned long*)addr; | ||
1020 | #endif | ||
1021 | #endif | ||
1011 | 1022 | ||
1012 | sp = (unsigned long) stack; | 1023 | sp = (unsigned long) stack; |
1013 | if (tsk == NULL) | 1024 | if (tsk == NULL) |
@@ -1030,6 +1041,13 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
1030 | ip = stack[STACK_FRAME_LR_SAVE]; | 1041 | ip = stack[STACK_FRAME_LR_SAVE]; |
1031 | if (!firstframe || ip != lr) { | 1042 | if (!firstframe || ip != lr) { |
1032 | printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip); | 1043 | printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip); |
1044 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
1045 | if (ip == addr && curr_frame >= 0) { | ||
1046 | printk(" (%pS)", | ||
1047 | (void *)current->ret_stack[curr_frame].ret); | ||
1048 | curr_frame--; | ||
1049 | } | ||
1050 | #endif | ||
1033 | if (firstframe) | 1051 | if (firstframe) |
1034 | printk(" (unreliable)"); | 1052 | printk(" (unreliable)"); |
1035 | printk("\n"); | 1053 | printk("\n"); |
@@ -1122,3 +1140,43 @@ void thread_info_cache_init(void) | |||
1122 | } | 1140 | } |
1123 | 1141 | ||
1124 | #endif /* THREAD_SHIFT < PAGE_SHIFT */ | 1142 | #endif /* THREAD_SHIFT < PAGE_SHIFT */ |
1143 | |||
1144 | unsigned long arch_align_stack(unsigned long sp) | ||
1145 | { | ||
1146 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) | ||
1147 | sp -= get_random_int() & ~PAGE_MASK; | ||
1148 | return sp & ~0xf; | ||
1149 | } | ||
1150 | |||
1151 | static inline unsigned long brk_rnd(void) | ||
1152 | { | ||
1153 | unsigned long rnd = 0; | ||
1154 | |||
1155 | /* 8MB for 32bit, 1GB for 64bit */ | ||
1156 | if (is_32bit_task()) | ||
1157 | rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT))); | ||
1158 | else | ||
1159 | rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT))); | ||
1160 | |||
1161 | return rnd << PAGE_SHIFT; | ||
1162 | } | ||
1163 | |||
1164 | unsigned long arch_randomize_brk(struct mm_struct *mm) | ||
1165 | { | ||
1166 | unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd()); | ||
1167 | |||
1168 | if (ret < mm->brk) | ||
1169 | return mm->brk; | ||
1170 | |||
1171 | return ret; | ||
1172 | } | ||
1173 | |||
1174 | unsigned long randomize_et_dyn(unsigned long base) | ||
1175 | { | ||
1176 | unsigned long ret = PAGE_ALIGN(base + brk_rnd()); | ||
1177 | |||
1178 | if (ret < base) | ||
1179 | return base; | ||
1180 | |||
1181 | return ret; | ||
1182 | } | ||