Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/s390/kernel/jump_label.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Jump label s390 support
4
*
5
* Copyright IBM Corp. 2011
6
* Author(s): Jan Glauber <[email protected]>
7
*/
8
#include <linux/uaccess.h>
9
#include <linux/jump_label.h>
10
#include <linux/module.h>
11
#include <asm/text-patching.h>
12
#include <asm/ipl.h>
13
14
struct insn {
15
u16 opcode;
16
s32 offset;
17
} __packed;
18
19
static void jump_label_make_nop(struct jump_entry *entry, struct insn *insn)
20
{
21
/* brcl 0,offset */
22
insn->opcode = 0xc004;
23
insn->offset = (jump_entry_target(entry) - jump_entry_code(entry)) >> 1;
24
}
25
26
static void jump_label_make_branch(struct jump_entry *entry, struct insn *insn)
27
{
28
/* brcl 15,offset */
29
insn->opcode = 0xc0f4;
30
insn->offset = (jump_entry_target(entry) - jump_entry_code(entry)) >> 1;
31
}
32
33
static void jump_label_bug(struct jump_entry *entry, struct insn *expected,
34
struct insn *new)
35
{
36
unsigned char *ipc = (unsigned char *)jump_entry_code(entry);
37
unsigned char *ipe = (unsigned char *)expected;
38
unsigned char *ipn = (unsigned char *)new;
39
40
pr_emerg("Jump label code mismatch at %pS [%px]\n", ipc, ipc);
41
pr_emerg("Found: %6ph\n", ipc);
42
pr_emerg("Expected: %6ph\n", ipe);
43
pr_emerg("New: %6ph\n", ipn);
44
panic("Corrupted kernel text");
45
}
46
47
static void jump_label_transform(struct jump_entry *entry,
48
enum jump_label_type type)
49
{
50
void *code = (void *)jump_entry_code(entry);
51
struct insn old, new;
52
53
if (type == JUMP_LABEL_JMP) {
54
jump_label_make_nop(entry, &old);
55
jump_label_make_branch(entry, &new);
56
} else {
57
jump_label_make_branch(entry, &old);
58
jump_label_make_nop(entry, &new);
59
}
60
if (memcmp(code, &old, sizeof(old)))
61
jump_label_bug(entry, &old, &new);
62
s390_kernel_write(code, &new, sizeof(new));
63
}
64
65
void arch_jump_label_transform(struct jump_entry *entry,
66
enum jump_label_type type)
67
{
68
jump_label_transform(entry, type);
69
text_poke_sync();
70
}
71
72
bool arch_jump_label_transform_queue(struct jump_entry *entry,
73
enum jump_label_type type)
74
{
75
jump_label_transform(entry, type);
76
return true;
77
}
78
79
void arch_jump_label_transform_apply(void)
80
{
81
text_poke_sync();
82
}
83
84