Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/module.h>
0003 #include <linux/cpu.h>
0004 #include <linux/smp.h>
0005 #include <asm/text-patching.h>
0006 #include <asm/alternative.h>
0007 #include <asm/facility.h>
0008 #include <asm/nospec-branch.h>
0009 
0010 static int __initdata_or_module alt_instr_disabled;
0011 
0012 static int __init disable_alternative_instructions(char *str)
0013 {
0014     alt_instr_disabled = 1;
0015     return 0;
0016 }
0017 
0018 early_param("noaltinstr", disable_alternative_instructions);
0019 
0020 static void __init_or_module __apply_alternatives(struct alt_instr *start,
0021                           struct alt_instr *end)
0022 {
0023     struct alt_instr *a;
0024     u8 *instr, *replacement;
0025 
0026     /*
0027      * The scan order should be from start to end. A later scanned
0028      * alternative code can overwrite previously scanned alternative code.
0029      */
0030     for (a = start; a < end; a++) {
0031         instr = (u8 *)&a->instr_offset + a->instr_offset;
0032         replacement = (u8 *)&a->repl_offset + a->repl_offset;
0033 
0034         if (!__test_facility(a->facility, alt_stfle_fac_list))
0035             continue;
0036 
0037         if (unlikely(a->instrlen % 2)) {
0038             WARN_ONCE(1, "cpu alternatives instructions length is "
0039                      "odd, skipping patching\n");
0040             continue;
0041         }
0042 
0043         s390_kernel_write(instr, replacement, a->instrlen);
0044     }
0045 }
0046 
0047 void __init_or_module apply_alternatives(struct alt_instr *start,
0048                      struct alt_instr *end)
0049 {
0050     if (!alt_instr_disabled)
0051         __apply_alternatives(start, end);
0052 }
0053 
0054 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
0055 void __init apply_alternative_instructions(void)
0056 {
0057     apply_alternatives(__alt_instructions, __alt_instructions_end);
0058 }
0059 
0060 static void do_sync_core(void *info)
0061 {
0062     sync_core();
0063 }
0064 
0065 void text_poke_sync(void)
0066 {
0067     on_each_cpu(do_sync_core, NULL, 1);
0068 }
0069 
0070 void text_poke_sync_lock(void)
0071 {
0072     cpus_read_lock();
0073     text_poke_sync();
0074     cpus_read_unlock();
0075 }