Jason Baron | d9f5ab7 | 2010-09-17 11:09:22 -0400 | [diff] [blame] | 1 | #ifndef _ASM_X86_JUMP_LABEL_H |
| 2 | #define _ASM_X86_JUMP_LABEL_H |
| 3 | |
Andy Lutomirski | c284543 | 2015-11-12 12:59:02 -0800 | [diff] [blame] | 4 | #ifndef HAVE_JUMP_LABEL |
| 5 | /* |
| 6 | * For better or for worse, if jump labels (the gcc extension) are missing, |
| 7 | * then the entire static branch patching infrastructure is compiled out. |
| 8 | * If that happens, the code in here will malfunction. Raise a compiler |
| 9 | * error instead. |
| 10 | * |
| 11 | * In theory, jump labels and the static branch patching infrastructure |
| 12 | * could be decoupled to fix this. |
| 13 | */ |
| 14 | #error asm/jump_label.h included on a non-jump-label kernel |
| 15 | #endif |
| 16 | |
Jason Baron | d9f5ab7 | 2010-09-17 11:09:22 -0400 | [diff] [blame] | 17 | #define JUMP_LABEL_NOP_SIZE 5 |
| 18 | |
Steven Rostedt | c3c7f14 | 2012-01-26 18:06:45 -0500 | [diff] [blame] | 19 | #ifdef CONFIG_X86_64 |
| 20 | # define STATIC_KEY_INIT_NOP P6_NOP5_ATOMIC |
| 21 | #else |
| 22 | # define STATIC_KEY_INIT_NOP GENERIC_NOP5_ATOMIC |
| 23 | #endif |
Jason Baron | d9f5ab7 | 2010-09-17 11:09:22 -0400 | [diff] [blame] | 24 | |
Andy Lutomirski | 2671c3e4 | 2015-11-12 12:59:03 -0800 | [diff] [blame] | 25 | #include <asm/asm.h> |
| 26 | #include <asm/nops.h> |
| 27 | |
| 28 | #ifndef __ASSEMBLY__ |
| 29 | |
| 30 | #include <linux/stringify.h> |
| 31 | #include <linux/types.h> |
| 32 | |
Peter Zijlstra | 11276d5 | 2015-07-24 15:09:55 +0200 | [diff] [blame] | 33 | static __always_inline bool arch_static_branch(struct static_key *key, bool branch) |
Jason Baron | d430d3d | 2011-03-16 17:29:47 -0400 | [diff] [blame] | 34 | { |
Ingo Molnar | 3f0116c | 2013-10-10 10:16:30 +0200 | [diff] [blame] | 35 | asm_volatile_goto("1:" |
Steven Rostedt | c3c7f14 | 2012-01-26 18:06:45 -0500 | [diff] [blame] | 36 | ".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t" |
Jason Baron | d430d3d | 2011-03-16 17:29:47 -0400 | [diff] [blame] | 37 | ".pushsection __jump_table, \"aw\" \n\t" |
Jason Baron | ef64789 | 2011-03-16 15:58:27 -0400 | [diff] [blame] | 38 | _ASM_ALIGN "\n\t" |
Peter Zijlstra | d420acd | 2015-08-12 21:04:22 +0200 | [diff] [blame] | 39 | _ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t" |
Jason Baron | d430d3d | 2011-03-16 17:29:47 -0400 | [diff] [blame] | 40 | ".popsection \n\t" |
Peter Zijlstra | d420acd | 2015-08-12 21:04:22 +0200 | [diff] [blame] | 41 | : : "i" (key), "i" (branch) : : l_yes); |
Peter Zijlstra | 11276d5 | 2015-07-24 15:09:55 +0200 | [diff] [blame] | 42 | |
| 43 | return false; |
| 44 | l_yes: |
| 45 | return true; |
| 46 | } |
| 47 | |
| 48 | static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) |
| 49 | { |
| 50 | asm_volatile_goto("1:" |
| 51 | ".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t" |
| 52 | "2:\n\t" |
| 53 | ".pushsection __jump_table, \"aw\" \n\t" |
| 54 | _ASM_ALIGN "\n\t" |
Peter Zijlstra | d420acd | 2015-08-12 21:04:22 +0200 | [diff] [blame] | 55 | _ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t" |
Peter Zijlstra | 11276d5 | 2015-07-24 15:09:55 +0200 | [diff] [blame] | 56 | ".popsection \n\t" |
Peter Zijlstra | d420acd | 2015-08-12 21:04:22 +0200 | [diff] [blame] | 57 | : : "i" (key), "i" (branch) : : l_yes); |
Peter Zijlstra | 11276d5 | 2015-07-24 15:09:55 +0200 | [diff] [blame] | 58 | |
Jason Baron | d430d3d | 2011-03-16 17:29:47 -0400 | [diff] [blame] | 59 | return false; |
| 60 | l_yes: |
| 61 | return true; |
| 62 | } |
Jason Baron | d9f5ab7 | 2010-09-17 11:09:22 -0400 | [diff] [blame] | 63 | |
Jason Baron | d9f5ab7 | 2010-09-17 11:09:22 -0400 | [diff] [blame] | 64 | #ifdef CONFIG_X86_64 |
Jason Baron | d9f5ab7 | 2010-09-17 11:09:22 -0400 | [diff] [blame] | 65 | typedef u64 jump_label_t; |
Jason Baron | d9f5ab7 | 2010-09-17 11:09:22 -0400 | [diff] [blame] | 66 | #else |
Jason Baron | d9f5ab7 | 2010-09-17 11:09:22 -0400 | [diff] [blame] | 67 | typedef u32 jump_label_t; |
Steven Rostedt | 95fccd4 | 2010-09-22 17:37:43 -0400 | [diff] [blame] | 68 | #endif |
Jason Baron | d9f5ab7 | 2010-09-17 11:09:22 -0400 | [diff] [blame] | 69 | |
| 70 | struct jump_entry { |
| 71 | jump_label_t code; |
| 72 | jump_label_t target; |
| 73 | jump_label_t key; |
| 74 | }; |
| 75 | |
Andy Lutomirski | 2671c3e4 | 2015-11-12 12:59:03 -0800 | [diff] [blame] | 76 | #else /* __ASSEMBLY__ */ |
| 77 | |
| 78 | .macro STATIC_JUMP_IF_TRUE target, key, def |
| 79 | .Lstatic_jump_\@: |
| 80 | .if \def |
| 81 | /* Equivalent to "jmp.d32 \target" */ |
| 82 | .byte 0xe9 |
| 83 | .long \target - .Lstatic_jump_after_\@ |
| 84 | .Lstatic_jump_after_\@: |
| 85 | .else |
| 86 | .byte STATIC_KEY_INIT_NOP |
| 87 | .endif |
| 88 | .pushsection __jump_table, "aw" |
| 89 | _ASM_ALIGN |
| 90 | _ASM_PTR .Lstatic_jump_\@, \target, \key |
| 91 | .popsection |
| 92 | .endm |
| 93 | |
| 94 | .macro STATIC_JUMP_IF_FALSE target, key, def |
| 95 | .Lstatic_jump_\@: |
| 96 | .if \def |
| 97 | .byte STATIC_KEY_INIT_NOP |
| 98 | .else |
| 99 | /* Equivalent to "jmp.d32 \target" */ |
| 100 | .byte 0xe9 |
| 101 | .long \target - .Lstatic_jump_after_\@ |
| 102 | .Lstatic_jump_after_\@: |
| 103 | .endif |
| 104 | .pushsection __jump_table, "aw" |
| 105 | _ASM_ALIGN |
| 106 | _ASM_PTR .Lstatic_jump_\@, \target, \key + 1 |
| 107 | .popsection |
| 108 | .endm |
| 109 | |
| 110 | #endif /* __ASSEMBLY__ */ |
| 111 | |
Jason Baron | d9f5ab7 | 2010-09-17 11:09:22 -0400 | [diff] [blame] | 112 | #endif |