aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKamalesh Babulal <kamalesh@linux.vnet.ibm.com>2017-09-20 06:19:51 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2017-10-10 00:27:42 -0400
commite36a82ee4c514a2f4f8fa30c780ad059282f5d64 (patch)
tree7648167660b5bfba12cfca281966af9d6404b19e
parent53ecde0b9126ff140abe3aefd7f0ec64d6fa36b0 (diff)
powerpc/livepatch: Fix livepatch stack access
While running stress test with livepatch module loaded, kernel bug was triggered. cpu 0x5: Vector: 400 (Instruction Access) at [c0000000eb9d3b60] 5:mon> t [c0000000eb9d3de0] c0000000eb9d3e30 (unreliable) [c0000000eb9d3e30] c000000000008ab4 hardware_interrupt_common+0x114/0x120 --- Exception: 501 (Hardware Interrupt) at c000000000053040 livepatch_handler+0x4c/0x74 [c0000000eb9d4120] 0000000057ac6e9d (unreliable) [d0000000089d9f78] 2e0965747962382e SP (965747962342e09) is in userspace When an interrupt occurs during the livepatch_handler execution, it's possible for the livepatch_stack and/or thread_info to be corrupted. eg: Task A Interrupt Handler ========= ================= livepatch_handler: mr r0, r1 ld r1, TI_livepatch_sp(r12) hardware_interrupt_common: do_IRQ+0x8: mflr r0 <- saved stack pointer is overwritten bl _mcount ... std r27,-40(r1) <- overwrite of thread_info() lis r2, STACK_END_MAGIC@h ori r2, r2, STACK_END_MAGIC@l ld r12, -8(r1) Fix the corruption by using r11 register for livepatch stack manipulation, instead of shuffling task stack and livepatch stack into r1 register. Using r11 register also avoids disabling/enabling irq's while setting up the livepatch stack. Signed-off-by: Kamalesh Babulal <kamalesh@linux.vnet.ibm.com> Reviewed-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> Reviewed-by: Balbir Singh <bsingharora@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/kernel/trace/ftrace_64_mprofile.S45
1 files changed, 15 insertions, 30 deletions
diff --git a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
index c98e90b4ea7b..b4e2b7165f79 100644
--- a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
+++ b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
@@ -181,34 +181,25 @@ _GLOBAL(ftrace_stub)
181 * - we have no stack frame and can not allocate one 181 * - we have no stack frame and can not allocate one
182 * - LR points back to the original caller (in A) 182 * - LR points back to the original caller (in A)
183 * - CTR holds the new NIP in C 183 * - CTR holds the new NIP in C
184 * - r0 & r12 are free 184 * - r0, r11 & r12 are free
185 *
186 * r0 can't be used as the base register for a DS-form load or store, so
187 * we temporarily shuffle r1 (stack pointer) into r0 and then put it back.
188 */ 185 */
189livepatch_handler: 186livepatch_handler:
190 CURRENT_THREAD_INFO(r12, r1) 187 CURRENT_THREAD_INFO(r12, r1)
191 188
192 /* Save stack pointer into r0 */
193 mr r0, r1
194
195 /* Allocate 3 x 8 bytes */ 189 /* Allocate 3 x 8 bytes */
196 ld r1, TI_livepatch_sp(r12) 190 ld r11, TI_livepatch_sp(r12)
197 addi r1, r1, 24 191 addi r11, r11, 24
198 std r1, TI_livepatch_sp(r12) 192 std r11, TI_livepatch_sp(r12)
199 193
200 /* Save toc & real LR on livepatch stack */ 194 /* Save toc & real LR on livepatch stack */
201 std r2, -24(r1) 195 std r2, -24(r11)
202 mflr r12 196 mflr r12
203 std r12, -16(r1) 197 std r12, -16(r11)
204 198
205 /* Store stack end marker */ 199 /* Store stack end marker */
206 lis r12, STACK_END_MAGIC@h 200 lis r12, STACK_END_MAGIC@h
207 ori r12, r12, STACK_END_MAGIC@l 201 ori r12, r12, STACK_END_MAGIC@l
208 std r12, -8(r1) 202 std r12, -8(r11)
209
210 /* Restore real stack pointer */
211 mr r1, r0
212 203
213 /* Put ctr in r12 for global entry and branch there */ 204 /* Put ctr in r12 for global entry and branch there */
214 mfctr r12 205 mfctr r12
@@ -216,36 +207,30 @@ livepatch_handler:
216 207
217 /* 208 /*
218 * Now we are returning from the patched function to the original 209 * Now we are returning from the patched function to the original
219 * caller A. We are free to use r0 and r12, and we can use r2 until we 210 * caller A. We are free to use r11, r12 and we can use r2 until we
220 * restore it. 211 * restore it.
221 */ 212 */
222 213
223 CURRENT_THREAD_INFO(r12, r1) 214 CURRENT_THREAD_INFO(r12, r1)
224 215
225 /* Save stack pointer into r0 */ 216 ld r11, TI_livepatch_sp(r12)
226 mr r0, r1
227
228 ld r1, TI_livepatch_sp(r12)
229 217
230 /* Check stack marker hasn't been trashed */ 218 /* Check stack marker hasn't been trashed */
231 lis r2, STACK_END_MAGIC@h 219 lis r2, STACK_END_MAGIC@h
232 ori r2, r2, STACK_END_MAGIC@l 220 ori r2, r2, STACK_END_MAGIC@l
233 ld r12, -8(r1) 221 ld r12, -8(r11)
2341: tdne r12, r2 2221: tdne r12, r2
235 EMIT_BUG_ENTRY 1b, __FILE__, __LINE__ - 1, 0 223 EMIT_BUG_ENTRY 1b, __FILE__, __LINE__ - 1, 0
236 224
237 /* Restore LR & toc from livepatch stack */ 225 /* Restore LR & toc from livepatch stack */
238 ld r12, -16(r1) 226 ld r12, -16(r11)
239 mtlr r12 227 mtlr r12
240 ld r2, -24(r1) 228 ld r2, -24(r11)
241 229
242 /* Pop livepatch stack frame */ 230 /* Pop livepatch stack frame */
243 CURRENT_THREAD_INFO(r12, r0) 231 CURRENT_THREAD_INFO(r12, r1)
244 subi r1, r1, 24 232 subi r11, r11, 24
245 std r1, TI_livepatch_sp(r12) 233 std r11, TI_livepatch_sp(r12)
246
247 /* Restore real stack pointer */
248 mr r1, r0
249 234
250 /* Return to original caller of live patched function */ 235 /* Return to original caller of live patched function */
251 blr 236 blr