Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Jump label s390 support
0004  *
0005  * Copyright IBM Corp. 2011
0006  * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
0007  */
0008 #include <linux/uaccess.h>
0009 #include <linux/jump_label.h>
0010 #include <linux/module.h>
0011 #include <asm/text-patching.h>
0012 #include <asm/ipl.h>
0013 
0014 struct insn {
0015     u16 opcode;
0016     s32 offset;
0017 } __packed;
0018 
0019 static void jump_label_make_nop(struct jump_entry *entry, struct insn *insn)
0020 {
0021     /* brcl 0,offset */
0022     insn->opcode = 0xc004;
0023     insn->offset = (jump_entry_target(entry) - jump_entry_code(entry)) >> 1;
0024 }
0025 
0026 static void jump_label_make_branch(struct jump_entry *entry, struct insn *insn)
0027 {
0028     /* brcl 15,offset */
0029     insn->opcode = 0xc0f4;
0030     insn->offset = (jump_entry_target(entry) - jump_entry_code(entry)) >> 1;
0031 }
0032 
0033 static void jump_label_bug(struct jump_entry *entry, struct insn *expected,
0034                struct insn *new)
0035 {
0036     unsigned char *ipc = (unsigned char *)jump_entry_code(entry);
0037     unsigned char *ipe = (unsigned char *)expected;
0038     unsigned char *ipn = (unsigned char *)new;
0039 
0040     pr_emerg("Jump label code mismatch at %pS [%px]\n", ipc, ipc);
0041     pr_emerg("Found:    %6ph\n", ipc);
0042     pr_emerg("Expected: %6ph\n", ipe);
0043     pr_emerg("New:      %6ph\n", ipn);
0044     panic("Corrupted kernel text");
0045 }
0046 
0047 static void jump_label_transform(struct jump_entry *entry,
0048                  enum jump_label_type type)
0049 {
0050     void *code = (void *)jump_entry_code(entry);
0051     struct insn old, new;
0052 
0053     if (type == JUMP_LABEL_JMP) {
0054         jump_label_make_nop(entry, &old);
0055         jump_label_make_branch(entry, &new);
0056     } else {
0057         jump_label_make_branch(entry, &old);
0058         jump_label_make_nop(entry, &new);
0059     }
0060     if (memcmp(code, &old, sizeof(old)))
0061         jump_label_bug(entry, &old, &new);
0062     s390_kernel_write(code, &new, sizeof(new));
0063 }
0064 
0065 void arch_jump_label_transform(struct jump_entry *entry,
0066                    enum jump_label_type type)
0067 {
0068     jump_label_transform(entry, type);
0069     text_poke_sync();
0070 }
0071 
0072 bool arch_jump_label_transform_queue(struct jump_entry *entry,
0073                      enum jump_label_type type)
0074 {
0075     jump_label_transform(entry, type);
0076     return true;
0077 }
0078 
0079 void arch_jump_label_transform_apply(void)
0080 {
0081     text_poke_sync();
0082 }