Commit 9ae033ac authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Thomas Gleixner

jump_label: Abstract jump_entry member accessors

In preparation of allowing architectures to use relative references
in jump_label entries [which can dramatically reduce the memory
footprint], introduce abstractions for references to the 'code' and
'key' members of struct jump_entry.
Signed-off-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-s390@vger.kernel.org
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Jessica Yu <jeyu@kernel.org>
Link: https://lkml.kernel.org/r/20180919065144.25010-2-ard.biesheuvel@linaro.org
parent 6bf4ca7f
...@@ -119,6 +119,40 @@ struct static_key { ...@@ -119,6 +119,40 @@ struct static_key {
#ifdef HAVE_JUMP_LABEL #ifdef HAVE_JUMP_LABEL
#include <asm/jump_label.h> #include <asm/jump_label.h>
#ifndef __ASSEMBLY__
static inline unsigned long jump_entry_code(const struct jump_entry *entry)
{
return entry->code;
}
static inline unsigned long jump_entry_target(const struct jump_entry *entry)
{
return entry->target;
}
static inline struct static_key *jump_entry_key(const struct jump_entry *entry)
{
return (struct static_key *)((unsigned long)entry->key & ~1UL);
}
static inline bool jump_entry_is_branch(const struct jump_entry *entry)
{
return (unsigned long)entry->key & 1UL;
}
static inline bool jump_entry_is_init(const struct jump_entry *entry)
{
return entry->code == 0;
}
static inline void jump_entry_set_init(struct jump_entry *entry)
{
entry->code = 0;
}
#endif
#endif #endif
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
......
...@@ -38,10 +38,10 @@ static int jump_label_cmp(const void *a, const void *b) ...@@ -38,10 +38,10 @@ static int jump_label_cmp(const void *a, const void *b)
const struct jump_entry *jea = a; const struct jump_entry *jea = a;
const struct jump_entry *jeb = b; const struct jump_entry *jeb = b;
if (jea->key < jeb->key) if (jump_entry_key(jea) < jump_entry_key(jeb))
return -1; return -1;
if (jea->key > jeb->key) if (jump_entry_key(jea) > jump_entry_key(jeb))
return 1; return 1;
return 0; return 0;
...@@ -261,8 +261,8 @@ EXPORT_SYMBOL_GPL(jump_label_rate_limit); ...@@ -261,8 +261,8 @@ EXPORT_SYMBOL_GPL(jump_label_rate_limit);
static int addr_conflict(struct jump_entry *entry, void *start, void *end) static int addr_conflict(struct jump_entry *entry, void *start, void *end)
{ {
if (entry->code <= (unsigned long)end && if (jump_entry_code(entry) <= (unsigned long)end &&
entry->code + JUMP_LABEL_NOP_SIZE > (unsigned long)start) jump_entry_code(entry) + JUMP_LABEL_NOP_SIZE > (unsigned long)start)
return 1; return 1;
return 0; return 0;
...@@ -321,16 +321,6 @@ static inline void static_key_set_linked(struct static_key *key) ...@@ -321,16 +321,6 @@ static inline void static_key_set_linked(struct static_key *key)
key->type |= JUMP_TYPE_LINKED; key->type |= JUMP_TYPE_LINKED;
} }
static inline struct static_key *jump_entry_key(struct jump_entry *entry)
{
return (struct static_key *)((unsigned long)entry->key & ~1UL);
}
static bool jump_entry_branch(struct jump_entry *entry)
{
return (unsigned long)entry->key & 1UL;
}
/*** /***
* A 'struct static_key' uses a union such that it either points directly * A 'struct static_key' uses a union such that it either points directly
* to a table of 'struct jump_entry' or to a linked list of modules which in * to a table of 'struct jump_entry' or to a linked list of modules which in
...@@ -355,7 +345,7 @@ static enum jump_label_type jump_label_type(struct jump_entry *entry) ...@@ -355,7 +345,7 @@ static enum jump_label_type jump_label_type(struct jump_entry *entry)
{ {
struct static_key *key = jump_entry_key(entry); struct static_key *key = jump_entry_key(entry);
bool enabled = static_key_enabled(key); bool enabled = static_key_enabled(key);
bool branch = jump_entry_branch(entry); bool branch = jump_entry_is_branch(entry);
/* See the comment in linux/jump_label.h */ /* See the comment in linux/jump_label.h */
return enabled ^ branch; return enabled ^ branch;
...@@ -370,12 +360,12 @@ static void __jump_label_update(struct static_key *key, ...@@ -370,12 +360,12 @@ static void __jump_label_update(struct static_key *key,
* An entry->code of 0 indicates an entry which has been * An entry->code of 0 indicates an entry which has been
* disabled because it was in an init text area. * disabled because it was in an init text area.
*/ */
if (entry->code) { if (!jump_entry_is_init(entry)) {
if (kernel_text_address(entry->code)) if (kernel_text_address(jump_entry_code(entry)))
arch_jump_label_transform(entry, jump_label_type(entry)); arch_jump_label_transform(entry, jump_label_type(entry));
else else
WARN_ONCE(1, "can't patch jump_label at %pS", WARN_ONCE(1, "can't patch jump_label at %pS",
(void *)(unsigned long)entry->code); (void *)jump_entry_code(entry));
} }
} }
} }
...@@ -430,8 +420,8 @@ void __init jump_label_invalidate_initmem(void) ...@@ -430,8 +420,8 @@ void __init jump_label_invalidate_initmem(void)
struct jump_entry *iter; struct jump_entry *iter;
for (iter = iter_start; iter < iter_stop; iter++) { for (iter = iter_start; iter < iter_stop; iter++) {
if (init_section_contains((void *)(unsigned long)iter->code, 1)) if (init_section_contains((void *)jump_entry_code(iter), 1))
iter->code = 0; jump_entry_set_init(iter);
} }
} }
...@@ -441,7 +431,7 @@ static enum jump_label_type jump_label_init_type(struct jump_entry *entry) ...@@ -441,7 +431,7 @@ static enum jump_label_type jump_label_init_type(struct jump_entry *entry)
{ {
struct static_key *key = jump_entry_key(entry); struct static_key *key = jump_entry_key(entry);
bool type = static_key_type(key); bool type = static_key_type(key);
bool branch = jump_entry_branch(entry); bool branch = jump_entry_is_branch(entry);
/* See the comment in linux/jump_label.h */ /* See the comment in linux/jump_label.h */
return type ^ branch; return type ^ branch;
...@@ -565,7 +555,7 @@ static int jump_label_add_module(struct module *mod) ...@@ -565,7 +555,7 @@ static int jump_label_add_module(struct module *mod)
continue; continue;
key = iterk; key = iterk;
if (within_module(iter->key, mod)) { if (within_module((unsigned long)key, mod)) {
static_key_set_entries(key, iter); static_key_set_entries(key, iter);
continue; continue;
} }
...@@ -615,7 +605,7 @@ static void jump_label_del_module(struct module *mod) ...@@ -615,7 +605,7 @@ static void jump_label_del_module(struct module *mod)
key = jump_entry_key(iter); key = jump_entry_key(iter);
if (within_module(iter->key, mod)) if (within_module((unsigned long)key, mod))
continue; continue;
/* No memory during module load */ /* No memory during module load */
...@@ -659,8 +649,8 @@ static void jump_label_invalidate_module_init(struct module *mod) ...@@ -659,8 +649,8 @@ static void jump_label_invalidate_module_init(struct module *mod)
struct jump_entry *iter; struct jump_entry *iter;
for (iter = iter_start; iter < iter_stop; iter++) { for (iter = iter_start; iter < iter_stop; iter++) {
if (within_module_init(iter->code, mod)) if (within_module_init(jump_entry_code(iter), mod))
iter->code = 0; jump_entry_set_init(iter);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment