.. | .. |
---|
37 | 37 | #include <asm/irq.h> |
---|
38 | 38 | #include <asm/nmi.h> |
---|
39 | 39 | #include <asm/smp.h> |
---|
| 40 | +#include <asm/stacktrace.h> |
---|
40 | 41 | #include <asm/switch_to.h> |
---|
41 | 42 | #include <asm/runtime_instr.h> |
---|
| 43 | +#include <asm/unwind.h> |
---|
42 | 44 | #include "entry.h" |
---|
43 | 45 | |
---|
44 | 46 | asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); |
---|
.. | .. |
---|
75 | 77 | |
---|
76 | 78 | memcpy(dst, src, arch_task_struct_size); |
---|
77 | 79 | dst->thread.fpu.regs = dst->thread.fpu.fprs; |
---|
| 80 | + |
---|
| 81 | + /* |
---|
| 82 | + * Don't transfer over the runtime instrumentation or the guarded |
---|
| 83 | + * storage control block pointers. These fields are cleared here instead |
---|
| 84 | + * of in copy_thread() to avoid premature freeing of associated memory |
---|
| 85 | + * on fork() failure. Wait to clear the RI flag because ->stack still |
---|
| 86 | + * refers to the source thread. |
---|
| 87 | + */ |
---|
| 88 | + dst->thread.ri_cb = NULL; |
---|
| 89 | + dst->thread.gs_cb = NULL; |
---|
| 90 | + dst->thread.gs_bc_cb = NULL; |
---|
| 91 | + |
---|
78 | 92 | return 0; |
---|
79 | 93 | } |
---|
80 | 94 | |
---|
81 | | -int copy_thread_tls(unsigned long clone_flags, unsigned long new_stackp, |
---|
82 | | - unsigned long arg, struct task_struct *p, unsigned long tls) |
---|
| 95 | +int copy_thread(unsigned long clone_flags, unsigned long new_stackp, |
---|
| 96 | + unsigned long arg, struct task_struct *p, unsigned long tls) |
---|
83 | 97 | { |
---|
84 | 98 | struct fake_frame |
---|
85 | 99 | { |
---|
.. | .. |
---|
104 | 118 | p->thread.system_timer = 0; |
---|
105 | 119 | p->thread.hardirq_timer = 0; |
---|
106 | 120 | p->thread.softirq_timer = 0; |
---|
| 121 | + p->thread.last_break = 1; |
---|
107 | 122 | |
---|
108 | 123 | frame->sf.back_chain = 0; |
---|
109 | 124 | /* new return point is ret_from_fork */ |
---|
.. | .. |
---|
112 | 127 | frame->sf.gprs[9] = (unsigned long) frame; |
---|
113 | 128 | |
---|
114 | 129 | /* Store access registers to kernel stack of new process. */ |
---|
115 | | - if (unlikely(p->flags & PF_KTHREAD)) { |
---|
| 130 | + if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { |
---|
116 | 131 | /* kernel thread */ |
---|
117 | 132 | memset(&frame->childregs, 0, sizeof(struct pt_regs)); |
---|
118 | 133 | frame->childregs.psw.mask = PSW_KERNEL_BITS | PSW_MASK_DAT | |
---|
.. | .. |
---|
131 | 146 | frame->childregs.flags = 0; |
---|
132 | 147 | if (new_stackp) |
---|
133 | 148 | frame->childregs.gprs[15] = new_stackp; |
---|
134 | | - |
---|
135 | | - /* Don't copy runtime instrumentation info */ |
---|
136 | | - p->thread.ri_cb = NULL; |
---|
| 149 | + /* |
---|
| 150 | + * Clear the runtime instrumentation flag after the above childregs |
---|
| 151 | + * copy. The CB pointer was already cleared in arch_dup_task_struct(). |
---|
| 152 | + */ |
---|
137 | 153 | frame->childregs.psw.mask &= ~PSW_MASK_RI; |
---|
138 | | - /* Don't copy guarded storage control block */ |
---|
139 | | - p->thread.gs_cb = NULL; |
---|
140 | | - p->thread.gs_bc_cb = NULL; |
---|
141 | 154 | |
---|
142 | 155 | /* Set a new TLS ? */ |
---|
143 | 156 | if (clone_flags & CLONE_SETTLS) { |
---|
.. | .. |
---|
157 | 170 | asm volatile("sfpc %0" : : "d" (0)); |
---|
158 | 171 | } |
---|
159 | 172 | |
---|
160 | | -/* |
---|
161 | | - * fill in the FPU structure for a core dump. |
---|
162 | | - */ |
---|
163 | | -int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) |
---|
164 | | -{ |
---|
165 | | - save_fpu_regs(); |
---|
166 | | - fpregs->fpc = current->thread.fpu.fpc; |
---|
167 | | - fpregs->pad = 0; |
---|
168 | | - if (MACHINE_HAS_VX) |
---|
169 | | - convert_vx_to_fp((freg_t *)&fpregs->fprs, |
---|
170 | | - current->thread.fpu.vxrs); |
---|
171 | | - else |
---|
172 | | - memcpy(&fpregs->fprs, current->thread.fpu.fprs, |
---|
173 | | - sizeof(fpregs->fprs)); |
---|
174 | | - return 1; |
---|
175 | | -} |
---|
176 | | -EXPORT_SYMBOL(dump_fpu); |
---|
177 | | - |
---|
178 | 173 | unsigned long get_wchan(struct task_struct *p) |
---|
179 | 174 | { |
---|
180 | | - struct stack_frame *sf, *low, *high; |
---|
181 | | - unsigned long return_address; |
---|
182 | | - int count; |
---|
| 175 | + struct unwind_state state; |
---|
| 176 | + unsigned long ip = 0; |
---|
183 | 177 | |
---|
184 | 178 | if (!p || p == current || p->state == TASK_RUNNING || !task_stack_page(p)) |
---|
185 | 179 | return 0; |
---|
.. | .. |
---|
187 | 181 | if (!try_get_task_stack(p)) |
---|
188 | 182 | return 0; |
---|
189 | 183 | |
---|
190 | | - low = task_stack_page(p); |
---|
191 | | - high = (struct stack_frame *) task_pt_regs(p); |
---|
192 | | - sf = (struct stack_frame *) p->thread.ksp; |
---|
193 | | - if (sf <= low || sf > high) { |
---|
194 | | - return_address = 0; |
---|
195 | | - goto out; |
---|
196 | | - } |
---|
197 | | - for (count = 0; count < 16; count++) { |
---|
198 | | - sf = (struct stack_frame *) sf->back_chain; |
---|
199 | | - if (sf <= low || sf > high) { |
---|
200 | | - return_address = 0; |
---|
201 | | - goto out; |
---|
| 184 | + unwind_for_each_frame(&state, p, NULL, 0) { |
---|
| 185 | + if (state.stack_info.type != STACK_TYPE_TASK) { |
---|
| 186 | + ip = 0; |
---|
| 187 | + break; |
---|
202 | 188 | } |
---|
203 | | - return_address = sf->gprs[8]; |
---|
204 | | - if (!in_sched_functions(return_address)) |
---|
205 | | - goto out; |
---|
| 189 | + |
---|
| 190 | + ip = unwind_get_return_address(&state); |
---|
| 191 | + if (!ip) |
---|
| 192 | + break; |
---|
| 193 | + |
---|
| 194 | + if (!in_sched_functions(ip)) |
---|
| 195 | + break; |
---|
206 | 196 | } |
---|
207 | | -out: |
---|
| 197 | + |
---|
208 | 198 | put_task_stack(p); |
---|
209 | | - return return_address; |
---|
| 199 | + return ip; |
---|
210 | 200 | } |
---|
211 | 201 | |
---|
212 | 202 | unsigned long arch_align_stack(unsigned long sp) |
---|