Commit 46589e29 authored by Jon Medhurst's avatar Jon Medhurst Committed by Russell King

ARM: 7174/1: Fix build error in kprobes test code on Thumb2 kernels

When compiling kprobes-test-thumb.c an error like below may occur:

/tmp/ccKcuJcG.s:19179: Error: offset out of range

This is caused by the compiler underestimating the size of the inline
assembler instructions containing ".space 0x1000" and failing to spill
the literal pool in time to prevent the generation of PC relative load
instruction with invalid offsets.

The fix implemented by this patch is to replace a single large .space
directive by a number of 4 byte .space's. This requires splitting the
macros which generate test cases for branch instructions into two forms:
one with, and one without support for inserting extra code between
branch and target.
Acked-by: default avatarNicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: default avatarJon Medhurst <jon.medhurst@linaro.org>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent ea2e7057
......@@ -222,8 +222,8 @@ void kprobe_thumb16_test_cases(void)
DONT_TEST_IN_ITBLOCK(
TEST_BF_R( "cbnz r",0,0, ", 2f")
TEST_BF_R( "cbz r",2,-1,", 2f")
TEST_BF_RX( "cbnz r",4,1, ", 2f",0x20)
TEST_BF_RX( "cbz r",7,0, ", 2f",0x40)
TEST_BF_RX( "cbnz r",4,1, ", 2f", SPACE_0x20)
TEST_BF_RX( "cbz r",7,0, ", 2f", SPACE_0x40)
)
TEST_R("sxth r0, r",7, HH1,"")
TEST_R("sxth r7, r",0, HH2,"")
......@@ -246,7 +246,7 @@ DONT_TEST_IN_ITBLOCK(
TESTCASE_START(code) \
TEST_ARG_PTR(13, offset) \
TEST_ARG_END("") \
TEST_BRANCH_F(code,0) \
TEST_BRANCH_F(code) \
TESTCASE_END
TEST("push {r0}")
......@@ -319,8 +319,8 @@ CONDITION_INSTRUCTIONS(8,
TEST_BF( "b 2f")
TEST_BB( "b 2b")
TEST_BF_X("b 2f", 0x400)
TEST_BB_X("b 2b", 0x400)
TEST_BF_X("b 2f", SPACE_0x400)
TEST_BB_X("b 2b", SPACE_0x400)
TEST_GROUP("Testing instructions in IT blocks")
......@@ -746,7 +746,7 @@ CONDITION_INSTRUCTIONS(22,
TEST_BB("bne.w 2b")
TEST_BF("bgt.w 2f")
TEST_BB("blt.w 2b")
TEST_BF_X("bpl.w 2f",0x1000)
TEST_BF_X("bpl.w 2f", SPACE_0x1000)
)
TEST_UNSUPPORTED("msr cpsr, r0")
......@@ -786,11 +786,11 @@ CONDITION_INSTRUCTIONS(22,
TEST_BF( "b.w 2f")
TEST_BB( "b.w 2b")
TEST_BF_X("b.w 2f", 0x1000)
TEST_BF_X("b.w 2f", SPACE_0x1000)
TEST_BF( "bl.w 2f")
TEST_BB( "bl.w 2b")
TEST_BB_X("bl.w 2b", 0x1000)
TEST_BB_X("bl.w 2b", SPACE_0x1000)
TEST_X( "blx __dummy_arm_subroutine",
".arm \n\t"
......
......@@ -149,23 +149,31 @@ struct test_arg_end {
"1: "instruction" \n\t" \
" nop \n\t"
#define TEST_BRANCH_F(instruction, xtra_dist) \
#define TEST_BRANCH_F(instruction) \
TEST_INSTRUCTION(instruction) \
".if "#xtra_dist" \n\t" \
" b 99f \n\t" \
".space "#xtra_dist" \n\t" \
".endif \n\t" \
"2: nop \n\t"
#define TEST_BRANCH_B(instruction) \
" b 50f \n\t" \
" b 99f \n\t" \
"2: nop \n\t" \
" b 99f \n\t" \
TEST_INSTRUCTION(instruction)
#define TEST_BRANCH_FX(instruction, codex) \
TEST_INSTRUCTION(instruction) \
" b 99f \n\t" \
codex" \n\t" \
" b 99f \n\t" \
"2: nop \n\t"
#define TEST_BRANCH_B(instruction, xtra_dist) \
#define TEST_BRANCH_BX(instruction, codex) \
" b 50f \n\t" \
" b 99f \n\t" \
"2: nop \n\t" \
" b 99f \n\t" \
".if "#xtra_dist" \n\t" \
".space "#xtra_dist" \n\t" \
".endif \n\t" \
codex" \n\t" \
TEST_INSTRUCTION(instruction)
#define TESTCASE_END \
......@@ -301,47 +309,60 @@ struct test_arg_end {
TESTCASE_START(code1 #reg1 code2) \
TEST_ARG_PTR(reg1, val1) \
TEST_ARG_END("") \
TEST_BRANCH_F(code1 #reg1 code2, 0) \
TEST_BRANCH_F(code1 #reg1 code2) \
TESTCASE_END
#define TEST_BF_X(code, xtra_dist) \
#define TEST_BF(code) \
TESTCASE_START(code) \
TEST_ARG_END("") \
TEST_BRANCH_F(code, xtra_dist) \
TEST_BRANCH_F(code) \
TESTCASE_END
#define TEST_BB_X(code, xtra_dist) \
#define TEST_BB(code) \
TESTCASE_START(code) \
TEST_ARG_END("") \
TEST_BRANCH_B(code, xtra_dist) \
TEST_BRANCH_B(code) \
TESTCASE_END
#define TEST_BF_RX(code1, reg, val, code2, xtra_dist) \
TESTCASE_START(code1 #reg code2) \
TEST_ARG_REG(reg, val) \
TEST_ARG_END("") \
TEST_BRANCH_F(code1 #reg code2, xtra_dist) \
#define TEST_BF_R(code1, reg, val, code2) \
TESTCASE_START(code1 #reg code2) \
TEST_ARG_REG(reg, val) \
TEST_ARG_END("") \
TEST_BRANCH_F(code1 #reg code2) \
TESTCASE_END
#define TEST_BB_RX(code1, reg, val, code2, xtra_dist) \
TESTCASE_START(code1 #reg code2) \
TEST_ARG_REG(reg, val) \
TEST_ARG_END("") \
TEST_BRANCH_B(code1 #reg code2, xtra_dist) \
#define TEST_BB_R(code1, reg, val, code2) \
TESTCASE_START(code1 #reg code2) \
TEST_ARG_REG(reg, val) \
TEST_ARG_END("") \
TEST_BRANCH_B(code1 #reg code2) \
TESTCASE_END
#define TEST_BF(code) TEST_BF_X(code, 0)
#define TEST_BB(code) TEST_BB_X(code, 0)
#define TEST_BF_R(code1, reg, val, code2) TEST_BF_RX(code1, reg, val, code2, 0)
#define TEST_BB_R(code1, reg, val, code2) TEST_BB_RX(code1, reg, val, code2, 0)
#define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3) \
TESTCASE_START(code1 #reg1 code2 #reg2 code3) \
TEST_ARG_REG(reg1, val1) \
TEST_ARG_REG(reg2, val2) \
TEST_ARG_END("") \
TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3, 0) \
TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3) \
TESTCASE_END
#define TEST_BF_X(code, codex) \
TESTCASE_START(code) \
TEST_ARG_END("") \
TEST_BRANCH_FX(code, codex) \
TESTCASE_END
#define TEST_BB_X(code, codex) \
TESTCASE_START(code) \
TEST_ARG_END("") \
TEST_BRANCH_BX(code, codex) \
TESTCASE_END
#define TEST_BF_RX(code1, reg, val, code2, codex) \
TESTCASE_START(code1 #reg code2) \
TEST_ARG_REG(reg, val) \
TEST_ARG_END("") \
TEST_BRANCH_FX(code1 #reg code2, codex) \
TESTCASE_END
#define TEST_X(code, codex) \
......@@ -372,6 +393,25 @@ struct test_arg_end {
TESTCASE_END
/*
* Macros for defining space directives spread over multiple lines.
* These are required so the compiler guesses better the length of inline asm
* code and will spill the literal pool early enough to avoid generating PC
* relative loads with out of range offsets.
*/
#define TWICE(x) x x
#define SPACE_0x8 TWICE(".space 4\n\t")
#define SPACE_0x10 TWICE(SPACE_0x8)
#define SPACE_0x20 TWICE(SPACE_0x10)
#define SPACE_0x40 TWICE(SPACE_0x20)
#define SPACE_0x80 TWICE(SPACE_0x40)
#define SPACE_0x100 TWICE(SPACE_0x80)
#define SPACE_0x200 TWICE(SPACE_0x100)
#define SPACE_0x400 TWICE(SPACE_0x200)
#define SPACE_0x800 TWICE(SPACE_0x400)
#define SPACE_0x1000 TWICE(SPACE_0x800)
/* Various values used in test cases... */
#define N(val) (val ^ 0xffffffff)
#define VAL1 0x12345678
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment