root/arch/s390/kernel/jump_label.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. jump_label_make_nop
  2. jump_label_make_branch
  3. jump_label_bug
  4. __jump_label_transform
  5. __jump_label_sync
  6. arch_jump_label_transform
  7. arch_jump_label_transform_static

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Jump label s390 support
   4  *
   5  * Copyright IBM Corp. 2011
   6  * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
   7  */
   8 #include <linux/uaccess.h>
   9 #include <linux/stop_machine.h>
  10 #include <linux/jump_label.h>
  11 #include <asm/ipl.h>
  12 
  13 struct insn {
  14         u16 opcode;
  15         s32 offset;
  16 } __packed;
  17 
  18 static void jump_label_make_nop(struct jump_entry *entry, struct insn *insn)
  19 {
  20         /* brcl 0,offset */
  21         insn->opcode = 0xc004;
  22         insn->offset = (jump_entry_target(entry) - jump_entry_code(entry)) >> 1;
  23 }
  24 
  25 static void jump_label_make_branch(struct jump_entry *entry, struct insn *insn)
  26 {
  27         /* brcl 15,offset */
  28         insn->opcode = 0xc0f4;
  29         insn->offset = (jump_entry_target(entry) - jump_entry_code(entry)) >> 1;
  30 }
  31 
  32 static void jump_label_bug(struct jump_entry *entry, struct insn *expected,
  33                            struct insn *new)
  34 {
  35         unsigned char *ipc = (unsigned char *)jump_entry_code(entry);
  36         unsigned char *ipe = (unsigned char *)expected;
  37         unsigned char *ipn = (unsigned char *)new;
  38 
  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");
  44 }
  45 
  46 static struct insn orignop = {
  47         .opcode = 0xc004,
  48         .offset = JUMP_LABEL_NOP_OFFSET >> 1,
  49 };
  50 
  51 static void __jump_label_transform(struct jump_entry *entry,
  52                                    enum jump_label_type type,
  53                                    int init)
  54 {
  55         void *code = (void *)jump_entry_code(entry);
  56         struct insn old, new;
  57 
  58         if (type == JUMP_LABEL_JMP) {
  59                 jump_label_make_nop(entry, &old);
  60                 jump_label_make_branch(entry, &new);
  61         } else {
  62                 jump_label_make_branch(entry, &old);
  63                 jump_label_make_nop(entry, &new);
  64         }
  65         if (init) {
  66                 if (memcmp(code, &orignop, sizeof(orignop)))
  67                         jump_label_bug(entry, &orignop, &new);
  68         } else {
  69                 if (memcmp(code, &old, sizeof(old)))
  70                         jump_label_bug(entry, &old, &new);
  71         }
  72         s390_kernel_write(code, &new, sizeof(new));
  73 }
  74 
  75 static void __jump_label_sync(void *dummy)
  76 {
  77 }
  78 
  79 void arch_jump_label_transform(struct jump_entry *entry,
  80                                enum jump_label_type type)
  81 {
  82         __jump_label_transform(entry, type, 0);
  83         smp_call_function(__jump_label_sync, NULL, 1);
  84 }
  85 
  86 void arch_jump_label_transform_static(struct jump_entry *entry,
  87                                       enum jump_label_type type)
  88 {
  89         __jump_label_transform(entry, type, 1);
  90 }

/* [<][>][^][v][top][bottom][index][help] */