2010-09-17 11:09:22 -04:00
# ifndef _ASM_X86_JUMP_LABEL_H
# define _ASM_X86_JUMP_LABEL_H
2015-11-12 12:59:02 -08:00
# ifndef HAVE_JUMP_LABEL
/*
* For better or for worse , if jump labels ( the gcc extension ) are missing ,
* then the entire static branch patching infrastructure is compiled out .
* If that happens , the code in here will malfunction . Raise a compiler
* error instead .
*
* In theory , jump labels and the static branch patching infrastructure
* could be decoupled to fix this .
*/
# error asm / jump_label.h included on a non-jump-label kernel
# endif
2010-09-17 11:09:22 -04:00
# define JUMP_LABEL_NOP_SIZE 5
2012-01-26 18:06:45 -05:00
# ifdef CONFIG_X86_64
# define STATIC_KEY_INIT_NOP P6_NOP5_ATOMIC
# else
# define STATIC_KEY_INIT_NOP GENERIC_NOP5_ATOMIC
# endif
2011-03-16 17:29:47 -04:00
2015-11-12 12:59:03 -08:00
# include <asm/asm.h>
# include <asm/nops.h>
# ifndef __ASSEMBLY__
# include <linux/stringify.h>
# include <linux/types.h>
2015-07-24 15:09:55 +02:00
static __always_inline bool arch_static_branch ( struct static_key * key , bool branch )
2011-03-16 17:29:47 -04:00
{
2013-10-10 10:16:30 +02:00
asm_volatile_goto ( " 1: "
2012-01-26 18:06:45 -05:00
" .byte " __stringify ( STATIC_KEY_INIT_NOP ) " \n \t "
2011-03-16 17:29:47 -04:00
" .pushsection __jump_table, \" aw \" \n \t "
2011-03-16 15:58:27 -04:00
_ASM_ALIGN " \n \t "
2015-08-12 21:04:22 +02:00
_ASM_PTR " 1b, %l[l_yes], %c0 + %c1 \n \t "
2011-03-16 17:29:47 -04:00
" .popsection \n \t "
2015-08-12 21:04:22 +02:00
: : " i " ( key ) , " i " ( branch ) : : l_yes ) ;
2015-07-24 15:09:55 +02:00
return false ;
l_yes :
return true ;
}
static __always_inline bool arch_static_branch_jump ( struct static_key * key , bool branch )
{
asm_volatile_goto ( " 1: "
" .byte 0xe9 \n \t .long %l[l_yes] - 2f \n \t "
" 2: \n \t "
" .pushsection __jump_table, \" aw \" \n \t "
_ASM_ALIGN " \n \t "
2015-08-12 21:04:22 +02:00
_ASM_PTR " 1b, %l[l_yes], %c0 + %c1 \n \t "
2015-07-24 15:09:55 +02:00
" .popsection \n \t "
2015-08-12 21:04:22 +02:00
: : " i " ( key ) , " i " ( branch ) : : l_yes ) ;
2015-07-24 15:09:55 +02:00
2011-03-16 17:29:47 -04:00
return false ;
l_yes :
return true ;
}
2010-09-17 11:09:22 -04:00
# ifdef CONFIG_X86_64
typedef u64 jump_label_t ;
# else
typedef u32 jump_label_t ;
2010-09-22 17:37:43 -04:00
# endif
2010-09-17 11:09:22 -04:00
struct jump_entry {
jump_label_t code ;
jump_label_t target ;
jump_label_t key ;
} ;
2015-11-12 12:59:03 -08:00
# else /* __ASSEMBLY__ */
. macro STATIC_JUMP_IF_TRUE target , key , def
. Lstatic_jump_ \ @ :
. if \ def
/* Equivalent to "jmp.d32 \target" */
. byte 0xe9
. long \ target - . Lstatic_jump_after_ \ @
. Lstatic_jump_after_ \ @ :
. else
. byte STATIC_KEY_INIT_NOP
. endif
. pushsection __jump_table , " aw "
_ASM_ALIGN
_ASM_PTR . Lstatic_jump_ \ @ , \ target , \ key
. popsection
. endm
. macro STATIC_JUMP_IF_FALSE target , key , def
. Lstatic_jump_ \ @ :
. if \ def
. byte STATIC_KEY_INIT_NOP
. else
/* Equivalent to "jmp.d32 \target" */
. byte 0xe9
. long \ target - . Lstatic_jump_after_ \ @
. Lstatic_jump_after_ \ @ :
. endif
. pushsection __jump_table , " aw "
_ASM_ALIGN
_ASM_PTR . Lstatic_jump_ \ @ , \ target , \ key + 1
. popsection
. endm
# endif /* __ASSEMBLY__ */
2010-09-17 11:09:22 -04:00
# endif