diff options
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r-- | arch/arm/kernel/calls.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/head.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes-arm.c | 4 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes-test-arm.c | 27 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes-test-thumb.c | 16 | ||||
-rw-r--r-- | arch/arm/kernel/kprobes-test.h | 100 | ||||
-rw-r--r-- | arch/arm/kernel/machine_kexec.c | 35 | ||||
-rw-r--r-- | arch/arm/kernel/perf_event.c | 20 | ||||
-rw-r--r-- | arch/arm/kernel/pmu.c | 1 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/setup.c | 20 | ||||
-rw-r--r-- | arch/arm/kernel/topology.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/unwind.c | 129 |
14 files changed, 234 insertions, 129 deletions
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 9943e9e74a1b..463ff4a0ec8a 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
@@ -385,6 +385,8 @@ | |||
385 | CALL(sys_syncfs) | 385 | CALL(sys_syncfs) |
386 | CALL(sys_sendmmsg) | 386 | CALL(sys_sendmmsg) |
387 | /* 375 */ CALL(sys_setns) | 387 | /* 375 */ CALL(sys_setns) |
388 | CALL(sys_process_vm_readv) | ||
389 | CALL(sys_process_vm_writev) | ||
388 | #ifndef syscalls_counted | 390 | #ifndef syscalls_counted |
389 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls | 391 | .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls |
390 | #define syscalls_counted | 392 | #define syscalls_counted |
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 9ad50c4208ae..b145f16c91bc 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
@@ -497,7 +497,7 @@ ENDPROC(__und_usr) | |||
497 | .popsection | 497 | .popsection |
498 | .pushsection __ex_table,"a" | 498 | .pushsection __ex_table,"a" |
499 | .long 1b, 4b | 499 | .long 1b, 4b |
500 | #if __LINUX_ARM_ARCH__ >= 7 | 500 | #if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7 |
501 | .long 2b, 4b | 501 | .long 2b, 4b |
502 | .long 3b, 4b | 502 | .long 3b, 4b |
503 | #endif | 503 | #endif |
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 566c54c2a1fe..08c82fd844a8 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -360,7 +360,7 @@ __secondary_data: | |||
360 | * r13 = *virtual* address to jump to upon completion | 360 | * r13 = *virtual* address to jump to upon completion |
361 | */ | 361 | */ |
362 | __enable_mmu: | 362 | __enable_mmu: |
363 | #ifdef CONFIG_ALIGNMENT_TRAP | 363 | #if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6 |
364 | orr r0, r0, #CR_A | 364 | orr r0, r0, #CR_A |
365 | #else | 365 | #else |
366 | bic r0, r0, #CR_A | 366 | bic r0, r0, #CR_A |
diff --git a/arch/arm/kernel/kprobes-arm.c b/arch/arm/kernel/kprobes-arm.c index 9fe8910308af..8a30c89da70e 100644 --- a/arch/arm/kernel/kprobes-arm.c +++ b/arch/arm/kernel/kprobes-arm.c | |||
@@ -519,10 +519,12 @@ static const union decode_item arm_cccc_0000_____1001_table[] = { | |||
519 | static const union decode_item arm_cccc_0001_____1001_table[] = { | 519 | static const union decode_item arm_cccc_0001_____1001_table[] = { |
520 | /* Synchronization primitives */ | 520 | /* Synchronization primitives */ |
521 | 521 | ||
522 | #if __LINUX_ARM_ARCH__ < 6 | ||
523 | /* Deprecated on ARMv6 and may be UNDEFINED on v7 */ | ||
522 | /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */ | 524 | /* SMP/SWPB cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */ |
523 | DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc, | 525 | DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc, |
524 | REGS(NOPC, NOPC, 0, 0, NOPC)), | 526 | REGS(NOPC, NOPC, 0, 0, NOPC)), |
525 | 527 | #endif | |
526 | /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */ | 528 | /* LDREX/STREX{,D,B,H} cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */ |
527 | /* And unallocated instructions... */ | 529 | /* And unallocated instructions... */ |
528 | DECODE_END | 530 | DECODE_END |
diff --git a/arch/arm/kernel/kprobes-test-arm.c b/arch/arm/kernel/kprobes-test-arm.c index fc82de8bdcce..ba32b393b3f0 100644 --- a/arch/arm/kernel/kprobes-test-arm.c +++ b/arch/arm/kernel/kprobes-test-arm.c | |||
@@ -427,18 +427,25 @@ void kprobe_arm_test_cases(void) | |||
427 | 427 | ||
428 | TEST_GROUP("Synchronization primitives") | 428 | TEST_GROUP("Synchronization primitives") |
429 | 429 | ||
430 | /* | 430 | #if __LINUX_ARM_ARCH__ < 6 |
431 | * Use hard coded constants for SWP instructions to avoid warnings | 431 | TEST_RP("swp lr, r",7,VAL2,", [r",8,0,"]") |
432 | * about deprecated instructions. | 432 | TEST_R( "swpvs r0, r",1,VAL1,", [sp]") |
433 | */ | 433 | TEST_RP("swp sp, r",14,VAL2,", [r",12,13*4,"]") |
434 | TEST_RP( ".word 0xe108e097 @ swp lr, r",7,VAL2,", [r",8,0,"]") | 434 | #else |
435 | TEST_R( ".word 0x610d0091 @ swpvs r0, r",1,VAL1,", [sp]") | 435 | TEST_UNSUPPORTED(".word 0xe108e097 @ swp lr, r7, [r8]") |
436 | TEST_RP( ".word 0xe10cd09e @ swp sp, r",14,VAL2,", [r",12,13*4,"]") | 436 | TEST_UNSUPPORTED(".word 0x610d0091 @ swpvs r0, r1, [sp]") |
437 | TEST_UNSUPPORTED(".word 0xe10cd09e @ swp sp, r14 [r12]") | ||
438 | #endif | ||
437 | TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]") | 439 | TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]") |
438 | TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]") | 440 | TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]") |
439 | TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]") | 441 | TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]") |
440 | TEST_RP( ".word 0xe148e097 @ swpb lr, r",7,VAL2,", [r",8,0,"]") | 442 | #if __LINUX_ARM_ARCH__ < 6 |
441 | TEST_R( ".word 0x614d0091 @ swpvsb r0, r",1,VAL1,", [sp]") | 443 | TEST_RP("swpb lr, r",7,VAL2,", [r",8,0,"]") |
444 | TEST_R( "swpvsb r0, r",1,VAL1,", [sp]") | ||
445 | #else | ||
446 | TEST_UNSUPPORTED(".word 0xe148e097 @ swpb lr, r7, [r8]") | ||
447 | TEST_UNSUPPORTED(".word 0x614d0091 @ swpvsb r0, r1, [sp]") | ||
448 | #endif | ||
442 | TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]") | 449 | TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]") |
443 | 450 | ||
444 | TEST_UNSUPPORTED(".word 0xe1100090") /* Unallocated space */ | 451 | TEST_UNSUPPORTED(".word 0xe1100090") /* Unallocated space */ |
@@ -550,7 +557,7 @@ void kprobe_arm_test_cases(void) | |||
550 | TEST_RPR( "strccd r",8, VAL2,", [r",13,0, ", r",12,48,"]") | 557 | TEST_RPR( "strccd r",8, VAL2,", [r",13,0, ", r",12,48,"]") |
551 | TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!") | 558 | TEST_RPR( "strd r",4, VAL1,", [r",2, 24,", r",3, 48,"]!") |
552 | TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!") | 559 | TEST_RPR( "strcsd r",12,VAL2,", [r",11,48,", -r",10,24,"]!") |
553 | TEST_RPR( "strd r",2, VAL1,", [r",3, 24,"], r",4,48,"") | 560 | TEST_RPR( "strd r",2, VAL1,", [r",5, 24,"], r",4,48,"") |
554 | TEST_RPR( "strd r",10,VAL2,", [r",9, 48,"], -r",7,24,"") | 561 | TEST_RPR( "strd r",10,VAL2,", [r",9, 48,"], -r",7,24,"") |
555 | TEST_UNSUPPORTED(".word 0xe1afc0fa @ strd r12, [pc, r10]!") | 562 | TEST_UNSUPPORTED(".word 0xe1afc0fa @ strd r12, [pc, r10]!") |
556 | 563 | ||
diff --git a/arch/arm/kernel/kprobes-test-thumb.c b/arch/arm/kernel/kprobes-test-thumb.c index 5e726c31c45a..5d8b85792222 100644 --- a/arch/arm/kernel/kprobes-test-thumb.c +++ b/arch/arm/kernel/kprobes-test-thumb.c | |||
@@ -222,8 +222,8 @@ void kprobe_thumb16_test_cases(void) | |||
222 | DONT_TEST_IN_ITBLOCK( | 222 | DONT_TEST_IN_ITBLOCK( |
223 | TEST_BF_R( "cbnz r",0,0, ", 2f") | 223 | TEST_BF_R( "cbnz r",0,0, ", 2f") |
224 | TEST_BF_R( "cbz r",2,-1,", 2f") | 224 | TEST_BF_R( "cbz r",2,-1,", 2f") |
225 | TEST_BF_RX( "cbnz r",4,1, ", 2f",0x20) | 225 | TEST_BF_RX( "cbnz r",4,1, ", 2f", SPACE_0x20) |
226 | TEST_BF_RX( "cbz r",7,0, ", 2f",0x40) | 226 | TEST_BF_RX( "cbz r",7,0, ", 2f", SPACE_0x40) |
227 | ) | 227 | ) |
228 | TEST_R("sxth r0, r",7, HH1,"") | 228 | TEST_R("sxth r0, r",7, HH1,"") |
229 | TEST_R("sxth r7, r",0, HH2,"") | 229 | TEST_R("sxth r7, r",0, HH2,"") |
@@ -246,7 +246,7 @@ DONT_TEST_IN_ITBLOCK( | |||
246 | TESTCASE_START(code) \ | 246 | TESTCASE_START(code) \ |
247 | TEST_ARG_PTR(13, offset) \ | 247 | TEST_ARG_PTR(13, offset) \ |
248 | TEST_ARG_END("") \ | 248 | TEST_ARG_END("") \ |
249 | TEST_BRANCH_F(code,0) \ | 249 | TEST_BRANCH_F(code) \ |
250 | TESTCASE_END | 250 | TESTCASE_END |
251 | 251 | ||
252 | TEST("push {r0}") | 252 | TEST("push {r0}") |
@@ -319,8 +319,8 @@ CONDITION_INSTRUCTIONS(8, | |||
319 | 319 | ||
320 | TEST_BF( "b 2f") | 320 | TEST_BF( "b 2f") |
321 | TEST_BB( "b 2b") | 321 | TEST_BB( "b 2b") |
322 | TEST_BF_X("b 2f", 0x400) | 322 | TEST_BF_X("b 2f", SPACE_0x400) |
323 | TEST_BB_X("b 2b", 0x400) | 323 | TEST_BB_X("b 2b", SPACE_0x400) |
324 | 324 | ||
325 | TEST_GROUP("Testing instructions in IT blocks") | 325 | TEST_GROUP("Testing instructions in IT blocks") |
326 | 326 | ||
@@ -746,7 +746,7 @@ CONDITION_INSTRUCTIONS(22, | |||
746 | TEST_BB("bne.w 2b") | 746 | TEST_BB("bne.w 2b") |
747 | TEST_BF("bgt.w 2f") | 747 | TEST_BF("bgt.w 2f") |
748 | TEST_BB("blt.w 2b") | 748 | TEST_BB("blt.w 2b") |
749 | TEST_BF_X("bpl.w 2f",0x1000) | 749 | TEST_BF_X("bpl.w 2f", SPACE_0x1000) |
750 | ) | 750 | ) |
751 | 751 | ||
752 | TEST_UNSUPPORTED("msr cpsr, r0") | 752 | TEST_UNSUPPORTED("msr cpsr, r0") |
@@ -786,11 +786,11 @@ CONDITION_INSTRUCTIONS(22, | |||
786 | 786 | ||
787 | TEST_BF( "b.w 2f") | 787 | TEST_BF( "b.w 2f") |
788 | TEST_BB( "b.w 2b") | 788 | TEST_BB( "b.w 2b") |
789 | TEST_BF_X("b.w 2f", 0x1000) | 789 | TEST_BF_X("b.w 2f", SPACE_0x1000) |
790 | 790 | ||
791 | TEST_BF( "bl.w 2f") | 791 | TEST_BF( "bl.w 2f") |
792 | TEST_BB( "bl.w 2b") | 792 | TEST_BB( "bl.w 2b") |
793 | TEST_BB_X("bl.w 2b", 0x1000) | 793 | TEST_BB_X("bl.w 2b", SPACE_0x1000) |
794 | 794 | ||
795 | TEST_X( "blx __dummy_arm_subroutine", | 795 | TEST_X( "blx __dummy_arm_subroutine", |
796 | ".arm \n\t" | 796 | ".arm \n\t" |
diff --git a/arch/arm/kernel/kprobes-test.h b/arch/arm/kernel/kprobes-test.h index 0dc5d77b9356..e28a869b1ae4 100644 --- a/arch/arm/kernel/kprobes-test.h +++ b/arch/arm/kernel/kprobes-test.h | |||
@@ -149,23 +149,31 @@ struct test_arg_end { | |||
149 | "1: "instruction" \n\t" \ | 149 | "1: "instruction" \n\t" \ |
150 | " nop \n\t" | 150 | " nop \n\t" |
151 | 151 | ||
152 | #define TEST_BRANCH_F(instruction, xtra_dist) \ | 152 | #define TEST_BRANCH_F(instruction) \ |
153 | TEST_INSTRUCTION(instruction) \ | 153 | TEST_INSTRUCTION(instruction) \ |
154 | ".if "#xtra_dist" \n\t" \ | ||
155 | " b 99f \n\t" \ | 154 | " b 99f \n\t" \ |
156 | ".space "#xtra_dist" \n\t" \ | 155 | "2: nop \n\t" |
157 | ".endif \n\t" \ | 156 | |
157 | #define TEST_BRANCH_B(instruction) \ | ||
158 | " b 50f \n\t" \ | ||
159 | " b 99f \n\t" \ | ||
160 | "2: nop \n\t" \ | ||
161 | " b 99f \n\t" \ | ||
162 | TEST_INSTRUCTION(instruction) | ||
163 | |||
164 | #define TEST_BRANCH_FX(instruction, codex) \ | ||
165 | TEST_INSTRUCTION(instruction) \ | ||
166 | " b 99f \n\t" \ | ||
167 | codex" \n\t" \ | ||
158 | " b 99f \n\t" \ | 168 | " b 99f \n\t" \ |
159 | "2: nop \n\t" | 169 | "2: nop \n\t" |
160 | 170 | ||
161 | #define TEST_BRANCH_B(instruction, xtra_dist) \ | 171 | #define TEST_BRANCH_BX(instruction, codex) \ |
162 | " b 50f \n\t" \ | 172 | " b 50f \n\t" \ |
163 | " b 99f \n\t" \ | 173 | " b 99f \n\t" \ |
164 | "2: nop \n\t" \ | 174 | "2: nop \n\t" \ |
165 | " b 99f \n\t" \ | 175 | " b 99f \n\t" \ |
166 | ".if "#xtra_dist" \n\t" \ | 176 | codex" \n\t" \ |
167 | ".space "#xtra_dist" \n\t" \ | ||
168 | ".endif \n\t" \ | ||
169 | TEST_INSTRUCTION(instruction) | 177 | TEST_INSTRUCTION(instruction) |
170 | 178 | ||
171 | #define TESTCASE_END \ | 179 | #define TESTCASE_END \ |
@@ -301,47 +309,60 @@ struct test_arg_end { | |||
301 | TESTCASE_START(code1 #reg1 code2) \ | 309 | TESTCASE_START(code1 #reg1 code2) \ |
302 | TEST_ARG_PTR(reg1, val1) \ | 310 | TEST_ARG_PTR(reg1, val1) \ |
303 | TEST_ARG_END("") \ | 311 | TEST_ARG_END("") \ |
304 | TEST_BRANCH_F(code1 #reg1 code2, 0) \ | 312 | TEST_BRANCH_F(code1 #reg1 code2) \ |
305 | TESTCASE_END | 313 | TESTCASE_END |
306 | 314 | ||
307 | #define TEST_BF_X(code, xtra_dist) \ | 315 | #define TEST_BF(code) \ |
308 | TESTCASE_START(code) \ | 316 | TESTCASE_START(code) \ |
309 | TEST_ARG_END("") \ | 317 | TEST_ARG_END("") \ |
310 | TEST_BRANCH_F(code, xtra_dist) \ | 318 | TEST_BRANCH_F(code) \ |
311 | TESTCASE_END | 319 | TESTCASE_END |
312 | 320 | ||
313 | #define TEST_BB_X(code, xtra_dist) \ | 321 | #define TEST_BB(code) \ |
314 | TESTCASE_START(code) \ | 322 | TESTCASE_START(code) \ |
315 | TEST_ARG_END("") \ | 323 | TEST_ARG_END("") \ |
316 | TEST_BRANCH_B(code, xtra_dist) \ | 324 | TEST_BRANCH_B(code) \ |
317 | TESTCASE_END | 325 | TESTCASE_END |
318 | 326 | ||
319 | #define TEST_BF_RX(code1, reg, val, code2, xtra_dist) \ | 327 | #define TEST_BF_R(code1, reg, val, code2) \ |
320 | TESTCASE_START(code1 #reg code2) \ | 328 | TESTCASE_START(code1 #reg code2) \ |
321 | TEST_ARG_REG(reg, val) \ | 329 | TEST_ARG_REG(reg, val) \ |
322 | TEST_ARG_END("") \ | 330 | TEST_ARG_END("") \ |
323 | TEST_BRANCH_F(code1 #reg code2, xtra_dist) \ | 331 | TEST_BRANCH_F(code1 #reg code2) \ |
324 | TESTCASE_END | 332 | TESTCASE_END |
325 | 333 | ||
326 | #define TEST_BB_RX(code1, reg, val, code2, xtra_dist) \ | 334 | #define TEST_BB_R(code1, reg, val, code2) \ |
327 | TESTCASE_START(code1 #reg code2) \ | 335 | TESTCASE_START(code1 #reg code2) \ |
328 | TEST_ARG_REG(reg, val) \ | 336 | TEST_ARG_REG(reg, val) \ |
329 | TEST_ARG_END("") \ | 337 | TEST_ARG_END("") \ |
330 | TEST_BRANCH_B(code1 #reg code2, xtra_dist) \ | 338 | TEST_BRANCH_B(code1 #reg code2) \ |
331 | TESTCASE_END | 339 | TESTCASE_END |
332 | 340 | ||
333 | #define TEST_BF(code) TEST_BF_X(code, 0) | ||
334 | #define TEST_BB(code) TEST_BB_X(code, 0) | ||
335 | |||
336 | #define TEST_BF_R(code1, reg, val, code2) TEST_BF_RX(code1, reg, val, code2, 0) | ||
337 | #define TEST_BB_R(code1, reg, val, code2) TEST_BB_RX(code1, reg, val, code2, 0) | ||
338 | |||
339 | #define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3) \ | 341 | #define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3) \ |
340 | TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ | 342 | TESTCASE_START(code1 #reg1 code2 #reg2 code3) \ |
341 | TEST_ARG_REG(reg1, val1) \ | 343 | TEST_ARG_REG(reg1, val1) \ |
342 | TEST_ARG_REG(reg2, val2) \ | 344 | TEST_ARG_REG(reg2, val2) \ |
343 | TEST_ARG_END("") \ | 345 | TEST_ARG_END("") \ |
344 | TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3, 0) \ | 346 | TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3) \ |
347 | TESTCASE_END | ||
348 | |||
349 | #define TEST_BF_X(code, codex) \ | ||
350 | TESTCASE_START(code) \ | ||
351 | TEST_ARG_END("") \ | ||
352 | TEST_BRANCH_FX(code, codex) \ | ||
353 | TESTCASE_END | ||
354 | |||
355 | #define TEST_BB_X(code, codex) \ | ||
356 | TESTCASE_START(code) \ | ||
357 | TEST_ARG_END("") \ | ||
358 | TEST_BRANCH_BX(code, codex) \ | ||
359 | TESTCASE_END | ||
360 | |||
361 | #define TEST_BF_RX(code1, reg, val, code2, codex) \ | ||
362 | TESTCASE_START(code1 #reg code2) \ | ||
363 | TEST_ARG_REG(reg, val) \ | ||
364 | TEST_ARG_END("") \ | ||
365 | TEST_BRANCH_FX(code1 #reg code2, codex) \ | ||
345 | TESTCASE_END | 366 | TESTCASE_END |
346 | 367 | ||
347 | #define TEST_X(code, codex) \ | 368 | #define TEST_X(code, codex) \ |
@@ -372,6 +393,25 @@ struct test_arg_end { | |||
372 | TESTCASE_END | 393 | TESTCASE_END |
373 | 394 | ||
374 | 395 | ||
396 | /* | ||
397 | * Macros for defining space directives spread over multiple lines. | ||
398 | * These are required so the compiler guesses better the length of inline asm | ||
399 | * code and will spill the literal pool early enough to avoid generating PC | ||
400 | * relative loads with out of range offsets. | ||
401 | */ | ||
402 | #define TWICE(x) x x | ||
403 | #define SPACE_0x8 TWICE(".space 4\n\t") | ||
404 | #define SPACE_0x10 TWICE(SPACE_0x8) | ||
405 | #define SPACE_0x20 TWICE(SPACE_0x10) | ||
406 | #define SPACE_0x40 TWICE(SPACE_0x20) | ||
407 | #define SPACE_0x80 TWICE(SPACE_0x40) | ||
408 | #define SPACE_0x100 TWICE(SPACE_0x80) | ||
409 | #define SPACE_0x200 TWICE(SPACE_0x100) | ||
410 | #define SPACE_0x400 TWICE(SPACE_0x200) | ||
411 | #define SPACE_0x800 TWICE(SPACE_0x400) | ||
412 | #define SPACE_0x1000 TWICE(SPACE_0x800) | ||
413 | |||
414 | |||
375 | /* Various values used in test cases... */ | 415 | /* Various values used in test cases... */ |
376 | #define N(val) (val ^ 0xffffffff) | 416 | #define N(val) (val ^ 0xffffffff) |
377 | #define VAL1 0x12345678 | 417 | #define VAL1 0x12345678 |
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index cc40b965d42a..29620b632ed9 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c | |||
@@ -32,24 +32,6 @@ static atomic_t waiting_for_crash_ipi; | |||
32 | 32 | ||
33 | int machine_kexec_prepare(struct kimage *image) | 33 | int machine_kexec_prepare(struct kimage *image) |
34 | { | 34 | { |
35 | unsigned long page_list; | ||
36 | void *reboot_code_buffer; | ||
37 | page_list = image->head & PAGE_MASK; | ||
38 | |||
39 | reboot_code_buffer = page_address(image->control_code_page); | ||
40 | |||
41 | /* Prepare parameters for reboot_code_buffer*/ | ||
42 | kexec_start_address = image->start; | ||
43 | kexec_indirection_page = page_list; | ||
44 | kexec_mach_type = machine_arch_type; | ||
45 | kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; | ||
46 | |||
47 | /* copy our kernel relocation code to the control code page */ | ||
48 | memcpy(reboot_code_buffer, | ||
49 | relocate_new_kernel, relocate_new_kernel_size); | ||
50 | |||
51 | flush_icache_range((unsigned long) reboot_code_buffer, | ||
52 | (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); | ||
53 | return 0; | 35 | return 0; |
54 | } | 36 | } |
55 | 37 | ||
@@ -100,14 +82,31 @@ void (*kexec_reinit)(void); | |||
100 | 82 | ||
101 | void machine_kexec(struct kimage *image) | 83 | void machine_kexec(struct kimage *image) |
102 | { | 84 | { |
85 | unsigned long page_list; | ||
103 | unsigned long reboot_code_buffer_phys; | 86 | unsigned long reboot_code_buffer_phys; |
104 | void *reboot_code_buffer; | 87 | void *reboot_code_buffer; |
105 | 88 | ||
89 | |||
90 | page_list = image->head & PAGE_MASK; | ||
91 | |||
106 | /* we need both effective and real address here */ | 92 | /* we need both effective and real address here */ |
107 | reboot_code_buffer_phys = | 93 | reboot_code_buffer_phys = |
108 | page_to_pfn(image->control_code_page) << PAGE_SHIFT; | 94 | page_to_pfn(image->control_code_page) << PAGE_SHIFT; |
109 | reboot_code_buffer = page_address(image->control_code_page); | 95 | reboot_code_buffer = page_address(image->control_code_page); |
110 | 96 | ||
97 | /* Prepare parameters for reboot_code_buffer*/ | ||
98 | kexec_start_address = image->start; | ||
99 | kexec_indirection_page = page_list; | ||
100 | kexec_mach_type = machine_arch_type; | ||
101 | kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; | ||
102 | |||
103 | /* copy our kernel relocation code to the control code page */ | ||
104 | memcpy(reboot_code_buffer, | ||
105 | relocate_new_kernel, relocate_new_kernel_size); | ||
106 | |||
107 | |||
108 | flush_icache_range((unsigned long) reboot_code_buffer, | ||
109 | (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE); | ||
111 | printk(KERN_INFO "Bye!\n"); | 110 | printk(KERN_INFO "Bye!\n"); |
112 | 111 | ||
113 | if (kexec_reinit) | 112 | if (kexec_reinit) |
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 24e2347be6b1..88b0941ce51e 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c | |||
@@ -343,19 +343,25 @@ validate_group(struct perf_event *event) | |||
343 | { | 343 | { |
344 | struct perf_event *sibling, *leader = event->group_leader; | 344 | struct perf_event *sibling, *leader = event->group_leader; |
345 | struct pmu_hw_events fake_pmu; | 345 | struct pmu_hw_events fake_pmu; |
346 | DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS); | ||
346 | 347 | ||
347 | memset(&fake_pmu, 0, sizeof(fake_pmu)); | 348 | /* |
349 | * Initialise the fake PMU. We only need to populate the | ||
350 | * used_mask for the purposes of validation. | ||
351 | */ | ||
352 | memset(fake_used_mask, 0, sizeof(fake_used_mask)); | ||
353 | fake_pmu.used_mask = fake_used_mask; | ||
348 | 354 | ||
349 | if (!validate_event(&fake_pmu, leader)) | 355 | if (!validate_event(&fake_pmu, leader)) |
350 | return -ENOSPC; | 356 | return -EINVAL; |
351 | 357 | ||
352 | list_for_each_entry(sibling, &leader->sibling_list, group_entry) { | 358 | list_for_each_entry(sibling, &leader->sibling_list, group_entry) { |
353 | if (!validate_event(&fake_pmu, sibling)) | 359 | if (!validate_event(&fake_pmu, sibling)) |
354 | return -ENOSPC; | 360 | return -EINVAL; |
355 | } | 361 | } |
356 | 362 | ||
357 | if (!validate_event(&fake_pmu, event)) | 363 | if (!validate_event(&fake_pmu, event)) |
358 | return -ENOSPC; | 364 | return -EINVAL; |
359 | 365 | ||
360 | return 0; | 366 | return 0; |
361 | } | 367 | } |
@@ -396,6 +402,9 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu) | |||
396 | int i, err, irq, irqs; | 402 | int i, err, irq, irqs; |
397 | struct platform_device *pmu_device = armpmu->plat_device; | 403 | struct platform_device *pmu_device = armpmu->plat_device; |
398 | 404 | ||
405 | if (!pmu_device) | ||
406 | return -ENODEV; | ||
407 | |||
399 | err = reserve_pmu(armpmu->type); | 408 | err = reserve_pmu(armpmu->type); |
400 | if (err) { | 409 | if (err) { |
401 | pr_warning("unable to reserve pmu\n"); | 410 | pr_warning("unable to reserve pmu\n"); |
@@ -631,6 +640,9 @@ static struct platform_device_id armpmu_plat_device_ids[] = { | |||
631 | 640 | ||
632 | static int __devinit armpmu_device_probe(struct platform_device *pdev) | 641 | static int __devinit armpmu_device_probe(struct platform_device *pdev) |
633 | { | 642 | { |
643 | if (!cpu_pmu) | ||
644 | return -ENODEV; | ||
645 | |||
634 | cpu_pmu->plat_device = pdev; | 646 | cpu_pmu->plat_device = pdev; |
635 | return 0; | 647 | return 0; |
636 | } | 648 | } |
diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c index 2c3407ee8576..2334bf8a650a 100644 --- a/arch/arm/kernel/pmu.c +++ b/arch/arm/kernel/pmu.c | |||
@@ -33,3 +33,4 @@ release_pmu(enum arm_pmu_type type) | |||
33 | { | 33 | { |
34 | clear_bit_unlock(type, pmu_lock); | 34 | clear_bit_unlock(type, pmu_lock); |
35 | } | 35 | } |
36 | EXPORT_SYMBOL_GPL(release_pmu); | ||
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 1e8b3e2de7a3..eeb3e16c6046 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -191,6 +191,9 @@ void cpu_idle(void) | |||
191 | #endif | 191 | #endif |
192 | 192 | ||
193 | local_irq_disable(); | 193 | local_irq_disable(); |
194 | #ifdef CONFIG_PL310_ERRATA_769419 | ||
195 | wmb(); | ||
196 | #endif | ||
194 | if (hlt_counter) { | 197 | if (hlt_counter) { |
195 | local_irq_enable(); | 198 | local_irq_enable(); |
196 | cpu_relax(); | 199 | cpu_relax(); |
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index a753880e984b..8b13930cdb0a 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c | |||
@@ -461,8 +461,10 @@ static void __init setup_processor(void) | |||
461 | cpu_name, read_cpuid_id(), read_cpuid_id() & 15, | 461 | cpu_name, read_cpuid_id(), read_cpuid_id() & 15, |
462 | proc_arch[cpu_architecture()], cr_alignment); | 462 | proc_arch[cpu_architecture()], cr_alignment); |
463 | 463 | ||
464 | sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS); | 464 | snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c", |
465 | sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS); | 465 | list->arch_name, ENDIANNESS); |
466 | snprintf(elf_platform, ELF_PLATFORM_SIZE, "%s%c", | ||
467 | list->elf_name, ENDIANNESS); | ||
466 | elf_hwcap = list->elf_hwcap; | 468 | elf_hwcap = list->elf_hwcap; |
467 | #ifndef CONFIG_ARM_THUMB | 469 | #ifndef CONFIG_ARM_THUMB |
468 | elf_hwcap &= ~HWCAP_THUMB; | 470 | elf_hwcap &= ~HWCAP_THUMB; |
@@ -893,8 +895,6 @@ void __init setup_arch(char **cmdline_p) | |||
893 | { | 895 | { |
894 | struct machine_desc *mdesc; | 896 | struct machine_desc *mdesc; |
895 | 897 | ||
896 | unwind_init(); | ||
897 | |||
898 | setup_processor(); | 898 | setup_processor(); |
899 | mdesc = setup_machine_fdt(__atags_pointer); | 899 | mdesc = setup_machine_fdt(__atags_pointer); |
900 | if (!mdesc) | 900 | if (!mdesc) |
@@ -902,6 +902,12 @@ void __init setup_arch(char **cmdline_p) | |||
902 | machine_desc = mdesc; | 902 | machine_desc = mdesc; |
903 | machine_name = mdesc->name; | 903 | machine_name = mdesc->name; |
904 | 904 | ||
905 | #ifdef CONFIG_ZONE_DMA | ||
906 | if (mdesc->dma_zone_size) { | ||
907 | extern unsigned long arm_dma_zone_size; | ||
908 | arm_dma_zone_size = mdesc->dma_zone_size; | ||
909 | } | ||
910 | #endif | ||
905 | if (mdesc->restart_mode) | 911 | if (mdesc->restart_mode) |
906 | reboot_setup(&mdesc->restart_mode); | 912 | reboot_setup(&mdesc->restart_mode); |
907 | 913 | ||
@@ -935,12 +941,6 @@ void __init setup_arch(char **cmdline_p) | |||
935 | 941 | ||
936 | tcm_init(); | 942 | tcm_init(); |
937 | 943 | ||
938 | #ifdef CONFIG_ZONE_DMA | ||
939 | if (mdesc->dma_zone_size) { | ||
940 | extern unsigned long arm_dma_zone_size; | ||
941 | arm_dma_zone_size = mdesc->dma_zone_size; | ||
942 | } | ||
943 | #endif | ||
944 | #ifdef CONFIG_MULTI_IRQ_HANDLER | 944 | #ifdef CONFIG_MULTI_IRQ_HANDLER |
945 | handle_arch_irq = mdesc->handle_irq; | 945 | handle_arch_irq = mdesc->handle_irq; |
946 | #endif | 946 | #endif |
diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 1040c00405d0..8200deaa14f6 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c | |||
@@ -43,7 +43,7 @@ | |||
43 | 43 | ||
44 | struct cputopo_arm cpu_topology[NR_CPUS]; | 44 | struct cputopo_arm cpu_topology[NR_CPUS]; |
45 | 45 | ||
46 | const struct cpumask *cpu_coregroup_mask(unsigned int cpu) | 46 | const struct cpumask *cpu_coregroup_mask(int cpu) |
47 | { | 47 | { |
48 | return &cpu_topology[cpu].core_sibling; | 48 | return &cpu_topology[cpu].core_sibling; |
49 | } | 49 | } |
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index e7e8365795c3..00df012c4678 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c | |||
@@ -67,7 +67,7 @@ EXPORT_SYMBOL(__aeabi_unwind_cpp_pr2); | |||
67 | 67 | ||
68 | struct unwind_ctrl_block { | 68 | struct unwind_ctrl_block { |
69 | unsigned long vrs[16]; /* virtual register set */ | 69 | unsigned long vrs[16]; /* virtual register set */ |
70 | unsigned long *insn; /* pointer to the current instructions word */ | 70 | const unsigned long *insn; /* pointer to the current instructions word */ |
71 | int entries; /* number of entries left to interpret */ | 71 | int entries; /* number of entries left to interpret */ |
72 | int byte; /* current byte number in the instructions word */ | 72 | int byte; /* current byte number in the instructions word */ |
73 | }; | 73 | }; |
@@ -83,8 +83,9 @@ enum regs { | |||
83 | PC = 15 | 83 | PC = 15 |
84 | }; | 84 | }; |
85 | 85 | ||
86 | extern struct unwind_idx __start_unwind_idx[]; | 86 | extern const struct unwind_idx __start_unwind_idx[]; |
87 | extern struct unwind_idx __stop_unwind_idx[]; | 87 | static const struct unwind_idx *__origin_unwind_idx; |
88 | extern const struct unwind_idx __stop_unwind_idx[]; | ||
88 | 89 | ||
89 | static DEFINE_SPINLOCK(unwind_lock); | 90 | static DEFINE_SPINLOCK(unwind_lock); |
90 | static LIST_HEAD(unwind_tables); | 91 | static LIST_HEAD(unwind_tables); |
@@ -98,45 +99,99 @@ static LIST_HEAD(unwind_tables); | |||
98 | }) | 99 | }) |
99 | 100 | ||
100 | /* | 101 | /* |
101 | * Binary search in the unwind index. The entries entries are | 102 | * Binary search in the unwind index. The entries are |
102 | * guaranteed to be sorted in ascending order by the linker. | 103 | * guaranteed to be sorted in ascending order by the linker. |
104 | * | ||
105 | * start = first entry | ||
106 | * origin = first entry with positive offset (or stop if there is no such entry) | ||
107 | * stop - 1 = last entry | ||
103 | */ | 108 | */ |
104 | static struct unwind_idx *search_index(unsigned long addr, | 109 | static const struct unwind_idx *search_index(unsigned long addr, |
105 | struct unwind_idx *first, | 110 | const struct unwind_idx *start, |
106 | struct unwind_idx *last) | 111 | const struct unwind_idx *origin, |
112 | const struct unwind_idx *stop) | ||
107 | { | 113 | { |
108 | pr_debug("%s(%08lx, %p, %p)\n", __func__, addr, first, last); | 114 | unsigned long addr_prel31; |
115 | |||
116 | pr_debug("%s(%08lx, %p, %p, %p)\n", | ||
117 | __func__, addr, start, origin, stop); | ||
118 | |||
119 | /* | ||
120 | * only search in the section with the matching sign. This way the | ||
121 | * prel31 numbers can be compared as unsigned longs. | ||
122 | */ | ||
123 | if (addr < (unsigned long)start) | ||
124 | /* negative offsets: [start; origin) */ | ||
125 | stop = origin; | ||
126 | else | ||
127 | /* positive offsets: [origin; stop) */ | ||
128 | start = origin; | ||
129 | |||
130 | /* prel31 for address relavive to start */ | ||
131 | addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff; | ||
109 | 132 | ||
110 | if (addr < first->addr) { | 133 | while (start < stop - 1) { |
134 | const struct unwind_idx *mid = start + ((stop - start) >> 1); | ||
135 | |||
136 | /* | ||
137 | * As addr_prel31 is relative to start an offset is needed to | ||
138 | * make it relative to mid. | ||
139 | */ | ||
140 | if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) < | ||
141 | mid->addr_offset) | ||
142 | stop = mid; | ||
143 | else { | ||
144 | /* keep addr_prel31 relative to start */ | ||
145 | addr_prel31 -= ((unsigned long)mid - | ||
146 | (unsigned long)start); | ||
147 | start = mid; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | if (likely(start->addr_offset <= addr_prel31)) | ||
152 | return start; | ||
153 | else { | ||
111 | pr_warning("unwind: Unknown symbol address %08lx\n", addr); | 154 | pr_warning("unwind: Unknown symbol address %08lx\n", addr); |
112 | return NULL; | 155 | return NULL; |
113 | } else if (addr >= last->addr) | 156 | } |
114 | return last; | 157 | } |
115 | 158 | ||
116 | while (first < last - 1) { | 159 | static const struct unwind_idx *unwind_find_origin( |
117 | struct unwind_idx *mid = first + ((last - first + 1) >> 1); | 160 | const struct unwind_idx *start, const struct unwind_idx *stop) |
161 | { | ||
162 | pr_debug("%s(%p, %p)\n", __func__, start, stop); | ||
163 | while (start < stop) { | ||
164 | const struct unwind_idx *mid = start + ((stop - start) >> 1); | ||
118 | 165 | ||
119 | if (addr < mid->addr) | 166 | if (mid->addr_offset >= 0x40000000) |
120 | last = mid; | 167 | /* negative offset */ |
168 | start = mid + 1; | ||
121 | else | 169 | else |
122 | first = mid; | 170 | /* positive offset */ |
171 | stop = mid; | ||
123 | } | 172 | } |
124 | 173 | pr_debug("%s -> %p\n", __func__, stop); | |
125 | return first; | 174 | return stop; |
126 | } | 175 | } |
127 | 176 | ||
128 | static struct unwind_idx *unwind_find_idx(unsigned long addr) | 177 | static const struct unwind_idx *unwind_find_idx(unsigned long addr) |
129 | { | 178 | { |
130 | struct unwind_idx *idx = NULL; | 179 | const struct unwind_idx *idx = NULL; |
131 | unsigned long flags; | 180 | unsigned long flags; |
132 | 181 | ||
133 | pr_debug("%s(%08lx)\n", __func__, addr); | 182 | pr_debug("%s(%08lx)\n", __func__, addr); |
134 | 183 | ||
135 | if (core_kernel_text(addr)) | 184 | if (core_kernel_text(addr)) { |
185 | if (unlikely(!__origin_unwind_idx)) | ||
186 | __origin_unwind_idx = | ||
187 | unwind_find_origin(__start_unwind_idx, | ||
188 | __stop_unwind_idx); | ||
189 | |||
136 | /* main unwind table */ | 190 | /* main unwind table */ |
137 | idx = search_index(addr, __start_unwind_idx, | 191 | idx = search_index(addr, __start_unwind_idx, |
138 | __stop_unwind_idx - 1); | 192 | __origin_unwind_idx, |
139 | else { | 193 | __stop_unwind_idx); |
194 | } else { | ||
140 | /* module unwind tables */ | 195 | /* module unwind tables */ |
141 | struct unwind_table *table; | 196 | struct unwind_table *table; |
142 | 197 | ||
@@ -145,7 +200,8 @@ static struct unwind_idx *unwind_find_idx(unsigned long addr) | |||
145 | if (addr >= table->begin_addr && | 200 | if (addr >= table->begin_addr && |
146 | addr < table->end_addr) { | 201 | addr < table->end_addr) { |
147 | idx = search_index(addr, table->start, | 202 | idx = search_index(addr, table->start, |
148 | table->stop - 1); | 203 | table->origin, |
204 | table->stop); | ||
149 | /* Move-to-front to exploit common traces */ | 205 | /* Move-to-front to exploit common traces */ |
150 | list_move(&table->list, &unwind_tables); | 206 | list_move(&table->list, &unwind_tables); |
151 | break; | 207 | break; |
@@ -274,7 +330,7 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) | |||
274 | int unwind_frame(struct stackframe *frame) | 330 | int unwind_frame(struct stackframe *frame) |
275 | { | 331 | { |
276 | unsigned long high, low; | 332 | unsigned long high, low; |
277 | struct unwind_idx *idx; | 333 | const struct unwind_idx *idx; |
278 | struct unwind_ctrl_block ctrl; | 334 | struct unwind_ctrl_block ctrl; |
279 | 335 | ||
280 | /* only go to a higher address on the stack */ | 336 | /* only go to a higher address on the stack */ |
@@ -399,7 +455,6 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, | |||
399 | unsigned long text_size) | 455 | unsigned long text_size) |
400 | { | 456 | { |
401 | unsigned long flags; | 457 | unsigned long flags; |
402 | struct unwind_idx *idx; | ||
403 | struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL); | 458 | struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL); |
404 | 459 | ||
405 | pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size, | 460 | pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size, |
@@ -408,15 +463,12 @@ struct unwind_table *unwind_table_add(unsigned long start, unsigned long size, | |||
408 | if (!tab) | 463 | if (!tab) |
409 | return tab; | 464 | return tab; |
410 | 465 | ||
411 | tab->start = (struct unwind_idx *)start; | 466 | tab->start = (const struct unwind_idx *)start; |
412 | tab->stop = (struct unwind_idx *)(start + size); | 467 | tab->stop = (const struct unwind_idx *)(start + size); |
468 | tab->origin = unwind_find_origin(tab->start, tab->stop); | ||
413 | tab->begin_addr = text_addr; | 469 | tab->begin_addr = text_addr; |
414 | tab->end_addr = text_addr + text_size; | 470 | tab->end_addr = text_addr + text_size; |
415 | 471 | ||
416 | /* Convert the symbol addresses to absolute values */ | ||
417 | for (idx = tab->start; idx < tab->stop; idx++) | ||
418 | idx->addr = prel31_to_addr(&idx->addr); | ||
419 | |||
420 | spin_lock_irqsave(&unwind_lock, flags); | 472 | spin_lock_irqsave(&unwind_lock, flags); |
421 | list_add_tail(&tab->list, &unwind_tables); | 473 | list_add_tail(&tab->list, &unwind_tables); |
422 | spin_unlock_irqrestore(&unwind_lock, flags); | 474 | spin_unlock_irqrestore(&unwind_lock, flags); |
@@ -437,16 +489,3 @@ void unwind_table_del(struct unwind_table *tab) | |||
437 | 489 | ||
438 | kfree(tab); | 490 | kfree(tab); |
439 | } | 491 | } |
440 | |||
441 | int __init unwind_init(void) | ||
442 | { | ||
443 | struct unwind_idx *idx; | ||
444 | |||
445 | /* Convert the symbol addresses to absolute values */ | ||
446 | for (idx = __start_unwind_idx; idx < __stop_unwind_idx; idx++) | ||
447 | idx->addr = prel31_to_addr(&idx->addr); | ||
448 | |||
449 | pr_debug("unwind: ARM stack unwinding initialised\n"); | ||
450 | |||
451 | return 0; | ||
452 | } | ||