diff options
author | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2011-09-29 13:58:46 -0400 |
---|---|---|
committer | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2011-10-25 14:54:37 -0400 |
commit | 61f42183fd15d5e666236f474d73b3555c7b83d1 (patch) | |
tree | 74895442aa5e3f43e3ab0a533a9c36b00687709b /arch/s390 | |
parent | 20284aa77c0f6227da4783a920b72dc61d4bcc09 (diff) |
s390/jump-label: add arch_jump_label_transform_static()
This allows jump-label entries to be cheaply updated on code which is
not yet live.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Acked-by: Jason Baron <jbaron@redhat.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Jan Glauber <jang@linux.vnet.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/kernel/jump_label.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/arch/s390/kernel/jump_label.c b/arch/s390/kernel/jump_label.c index 44cc06bedf77..b987ab2c1541 100644 --- a/arch/s390/kernel/jump_label.c +++ b/arch/s390/kernel/jump_label.c | |||
@@ -18,26 +18,15 @@ struct insn { | |||
18 | } __packed; | 18 | } __packed; |
19 | 19 | ||
20 | struct insn_args { | 20 | struct insn_args { |
21 | unsigned long *target; | 21 | struct jump_entry *entry; |
22 | struct insn *insn; | 22 | enum jump_label_type type; |
23 | ssize_t size; | ||
24 | }; | 23 | }; |
25 | 24 | ||
26 | static int __arch_jump_label_transform(void *data) | 25 | static void __jump_label_transform(struct jump_entry *entry, |
26 | enum jump_label_type type) | ||
27 | { | 27 | { |
28 | struct insn_args *args = data; | ||
29 | int rc; | ||
30 | |||
31 | rc = probe_kernel_write(args->target, args->insn, args->size); | ||
32 | WARN_ON_ONCE(rc < 0); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | void arch_jump_label_transform(struct jump_entry *entry, | ||
37 | enum jump_label_type type) | ||
38 | { | ||
39 | struct insn_args args; | ||
40 | struct insn insn; | 28 | struct insn insn; |
29 | int rc; | ||
41 | 30 | ||
42 | if (type == JUMP_LABEL_ENABLE) { | 31 | if (type == JUMP_LABEL_ENABLE) { |
43 | /* brcl 15,offset */ | 32 | /* brcl 15,offset */ |
@@ -49,11 +38,33 @@ void arch_jump_label_transform(struct jump_entry *entry, | |||
49 | insn.offset = 0; | 38 | insn.offset = 0; |
50 | } | 39 | } |
51 | 40 | ||
52 | args.target = (void *) entry->code; | 41 | rc = probe_kernel_write((void *)entry->code, &insn, JUMP_LABEL_NOP_SIZE); |
53 | args.insn = &insn; | 42 | WARN_ON_ONCE(rc < 0); |
54 | args.size = JUMP_LABEL_NOP_SIZE; | 43 | } |
55 | 44 | ||
56 | stop_machine(__arch_jump_label_transform, &args, NULL); | 45 | static int __sm_arch_jump_label_transform(void *data) |
46 | { | ||
47 | struct insn_args *args = data; | ||
48 | |||
49 | __jump_label_transform(args->entry, args->type); | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | void arch_jump_label_transform(struct jump_entry *entry, | ||
54 | enum jump_label_type type) | ||
55 | { | ||
56 | struct insn_args args; | ||
57 | |||
58 | args.entry = entry; | ||
59 | args.type = type; | ||
60 | |||
61 | stop_machine(__sm_arch_jump_label_transform, &args, NULL); | ||
62 | } | ||
63 | |||
64 | void arch_jump_label_transform_static(struct jump_entry *entry, | ||
65 | enum jump_label_type type) | ||
66 | { | ||
67 | __jump_label_transform(entry, type); | ||
57 | } | 68 | } |
58 | 69 | ||
59 | #endif | 70 | #endif |