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 /arch/sparc/kernel | |
| 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>
Diffstat (limited to 'arch/sparc/kernel')
| -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 | } |
