aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Clarke <jrtc27@jrtc27.com>2016-10-24 14:49:25 -0400
committerDavid S. Miller <davem@davemloft.net>2016-10-25 22:11:17 -0400
commit9d9fa230206a3aea6ef451646c97122f04777983 (patch)
tree75dd2bfcaaccb7a90c7e8b7dd4fd176640a06f03
parentb429ae4d5b565a71dfffd759dfcd4f6c093ced94 (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.c23
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 @@
13void arch_jump_label_transform(struct jump_entry *entry, 13void 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 }