1 // SPDX-License-Identifier: GPL-2.0
3 * Jump label s390 support
5 * Copyright IBM Corp. 2011
6 * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
8 #include <linux/uaccess.h>
9 #include <linux/stop_machine.h>
10 #include <linux/jump_label.h>
18 static void jump_label_make_nop(struct jump_entry
*entry
, struct insn
*insn
)
21 insn
->opcode
= 0xc004;
22 insn
->offset
= (jump_entry_target(entry
) - jump_entry_code(entry
)) >> 1;
25 static void jump_label_make_branch(struct jump_entry
*entry
, struct insn
*insn
)
28 insn
->opcode
= 0xc0f4;
29 insn
->offset
= (jump_entry_target(entry
) - jump_entry_code(entry
)) >> 1;
32 static void jump_label_bug(struct jump_entry
*entry
, struct insn
*expected
,
35 unsigned char *ipc
= (unsigned char *)jump_entry_code(entry
);
36 unsigned char *ipe
= (unsigned char *)expected
;
37 unsigned char *ipn
= (unsigned char *)new;
39 pr_emerg("Jump label code mismatch at %pS [%p]\n", ipc
, ipc
);
40 pr_emerg("Found: %6ph\n", ipc
);
41 pr_emerg("Expected: %6ph\n", ipe
);
42 pr_emerg("New: %6ph\n", ipn
);
43 panic("Corrupted kernel text");
46 static struct insn orignop
= {
48 .offset
= JUMP_LABEL_NOP_OFFSET
>> 1,
51 static void __jump_label_transform(struct jump_entry
*entry
,
52 enum jump_label_type type
,
55 void *code
= (void *)jump_entry_code(entry
);
58 if (type
== JUMP_LABEL_JMP
) {
59 jump_label_make_nop(entry
, &old
);
60 jump_label_make_branch(entry
, &new);
62 jump_label_make_branch(entry
, &old
);
63 jump_label_make_nop(entry
, &new);
66 if (memcmp(code
, &orignop
, sizeof(orignop
)))
67 jump_label_bug(entry
, &orignop
, &new);
69 if (memcmp(code
, &old
, sizeof(old
)))
70 jump_label_bug(entry
, &old
, &new);
72 s390_kernel_write(code
, &new, sizeof(new));
75 static void __jump_label_sync(void *dummy
)
79 void arch_jump_label_transform(struct jump_entry
*entry
,
80 enum jump_label_type type
)
82 __jump_label_transform(entry
, type
, 0);
83 smp_call_function(__jump_label_sync
, NULL
, 1);
86 void arch_jump_label_transform_static(struct jump_entry
*entry
,
87 enum jump_label_type type
)
89 __jump_label_transform(entry
, type
, 1);