diff options
author | James Clarke <jrtc27@jrtc27.com> | 2016-10-24 14:49:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-10-25 22:11:17 -0400 |
commit | 9d9fa230206a3aea6ef451646c97122f04777983 (patch) | |
tree | 75dd2bfcaaccb7a90c7e8b7dd4fd176640a06f03 | |
parent | b429ae4d5b565a71dfffd759dfcd4f6c093ced94 (diff) |
sparc: Handle negative offsets in arch_jump_label_transform
Additionally, if the offset will overflow the immediate for a ba,pt
instruction, fall back on a standard ba to get an extra 3 bits.
Signed-off-by: James Clarke <jrtc27@jrtc27.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc/kernel/jump_label.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/arch/sparc/kernel/jump_label.c b/arch/sparc/kernel/jump_label.c index 59bbeff55024..07933b9e9ce0 100644 --- a/arch/sparc/kernel/jump_label.c +++ b/arch/sparc/kernel/jump_label.c | |||
@@ -13,19 +13,30 @@ | |||
13 | void arch_jump_label_transform(struct jump_entry *entry, | 13 | void arch_jump_label_transform(struct jump_entry *entry, |
14 | enum jump_label_type type) | 14 | enum jump_label_type type) |
15 | { | 15 | { |
16 | u32 val; | ||
17 | u32 *insn = (u32 *) (unsigned long) entry->code; | 16 | u32 *insn = (u32 *) (unsigned long) entry->code; |
17 | u32 val; | ||
18 | 18 | ||
19 | if (type == JUMP_LABEL_JMP) { | 19 | if (type == JUMP_LABEL_JMP) { |
20 | s32 off = (s32)entry->target - (s32)entry->code; | 20 | s32 off = (s32)entry->target - (s32)entry->code; |
21 | bool use_v9_branch = false; | ||
22 | |||
23 | BUG_ON(off & 3); | ||
21 | 24 | ||
22 | #ifdef CONFIG_SPARC64 | 25 | #ifdef CONFIG_SPARC64 |
23 | /* ba,pt %xcc, . + (off << 2) */ | 26 | if (off <= 0xfffff && off >= -0x100000) |
24 | val = 0x10680000 | ((u32) off >> 2); | 27 | use_v9_branch = true; |
25 | #else | ||
26 | /* ba . + (off << 2) */ | ||
27 | val = 0x10800000 | ((u32) off >> 2); | ||
28 | #endif | 28 | #endif |
29 | if (use_v9_branch) { | ||
30 | /* WDISP19 - target is . + immed << 2 */ | ||
31 | /* ba,pt %xcc, . + off */ | ||
32 | val = 0x10680000 | (((u32) off >> 2) & 0x7ffff); | ||
33 | } else { | ||
34 | /* WDISP22 - target is . + immed << 2 */ | ||
35 | BUG_ON(off > 0x7fffff); | ||
36 | BUG_ON(off < -0x800000); | ||
37 | /* ba . + off */ | ||
38 | val = 0x10800000 | (((u32) off >> 2) & 0x3fffff); | ||
39 | } | ||
29 | } else { | 40 | } else { |
30 | val = 0x01000000; | 41 | val = 0x01000000; |
31 | } | 42 | } |