]> Pileus Git - ~andy/linux/blob - arch/x86/kernel/jump_label.c
x86: Make jump_label use int3-based patching
[~andy/linux] / arch / x86 / kernel / jump_label.c
1 /*
2  * jump label x86 support
3  *
4  * Copyright (C) 2009 Jason Baron <jbaron@redhat.com>
5  *
6  */
7 #include <linux/jump_label.h>
8 #include <linux/memory.h>
9 #include <linux/uaccess.h>
10 #include <linux/module.h>
11 #include <linux/list.h>
12 #include <linux/jhash.h>
13 #include <linux/cpu.h>
14 #include <asm/kprobes.h>
15 #include <asm/alternative.h>
16
17 #ifdef HAVE_JUMP_LABEL
18
19 union jump_code_union {
20         char code[JUMP_LABEL_NOP_SIZE];
21         struct {
22                 char jump;
23                 int offset;
24         } __attribute__((packed));
25 };
26
27 static void __jump_label_transform(struct jump_entry *entry,
28                                    enum jump_label_type type,
29                                    void *(*poker)(void *, const void *, size_t))
30 {
31         union jump_code_union code;
32
33         if (type == JUMP_LABEL_ENABLE) {
34                 code.jump = 0xe9;
35                 code.offset = entry->target -
36                                 (entry->code + JUMP_LABEL_NOP_SIZE);
37         } else
38                 memcpy(&code, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE);
39
40         /*
41          * Make text_poke_bp() a default fallback poker.
42          *
43          * At the time the change is being done, just ignore whether we
44          * are doing nop -> jump or jump -> nop transition, and assume
45          * always nop being the 'currently valid' instruction
46          *
47          */
48         if (poker)
49                 (*poker)((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
50         else
51                 text_poke_bp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE,
52                              (void *)entry->code + JUMP_LABEL_NOP_SIZE);
53 }
54
55 void arch_jump_label_transform(struct jump_entry *entry,
56                                enum jump_label_type type)
57 {
58         get_online_cpus();
59         mutex_lock(&text_mutex);
60         __jump_label_transform(entry, type, NULL);
61         mutex_unlock(&text_mutex);
62         put_online_cpus();
63 }
64
65 __init_or_module void arch_jump_label_transform_static(struct jump_entry *entry,
66                                       enum jump_label_type type)
67 {
68         __jump_label_transform(entry, type, text_poke_early);
69 }
70
71 #endif