2017-12-04 10:39:38 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
s390: introduce CPU alternatives
Implement CPU alternatives, which allows to optionally patch newer
instructions at runtime, based on CPU facilities availability.
A new kernel boot parameter "noaltinstr" disables patching.
Current implementation is derived from x86 alternatives. Although
ideal instructions padding (when altinstr is longer then oldinstr)
is added at compile time, and no oldinstr nops optimization has to be
done at runtime. Also couple of compile time sanity checks are done:
1. oldinstr and altinstr must be <= 254 bytes long,
2. oldinstr and altinstr must not have an odd length.
alternative(oldinstr, altinstr, facility);
alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2);
Both compile time and runtime padding consists of either 6/4/2 bytes nop
or a jump (brcl) + 2 bytes nop filler if padding is longer then 6 bytes.
.altinstructions and .altinstr_replacement sections are part of
__init_begin : __init_end region and are freed after initialization.
Signed-off-by: Vasily Gorbik <gor@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
2017-10-12 13:01:47 +02:00
|
|
|
#include <linux/module.h>
|
2021-10-01 12:47:01 +02:00
|
|
|
#include <linux/cpu.h>
|
|
|
|
#include <linux/smp.h>
|
|
|
|
#include <asm/text-patching.h>
|
s390: introduce CPU alternatives
Implement CPU alternatives, which allows to optionally patch newer
instructions at runtime, based on CPU facilities availability.
A new kernel boot parameter "noaltinstr" disables patching.
Current implementation is derived from x86 alternatives. Although
ideal instructions padding (when altinstr is longer then oldinstr)
is added at compile time, and no oldinstr nops optimization has to be
done at runtime. Also couple of compile time sanity checks are done:
1. oldinstr and altinstr must be <= 254 bytes long,
2. oldinstr and altinstr must not have an odd length.
alternative(oldinstr, altinstr, facility);
alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2);
Both compile time and runtime padding consists of either 6/4/2 bytes nop
or a jump (brcl) + 2 bytes nop filler if padding is longer then 6 bytes.
.altinstructions and .altinstr_replacement sections are part of
__init_begin : __init_end region and are freed after initialization.
Signed-off-by: Vasily Gorbik <gor@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
2017-10-12 13:01:47 +02:00
|
|
|
#include <asm/alternative.h>
|
|
|
|
#include <asm/facility.h>
|
2018-03-23 13:04:49 +01:00
|
|
|
#include <asm/nospec-branch.h>
|
s390: introduce CPU alternatives
Implement CPU alternatives, which allows to optionally patch newer
instructions at runtime, based on CPU facilities availability.
A new kernel boot parameter "noaltinstr" disables patching.
Current implementation is derived from x86 alternatives. Although
ideal instructions padding (when altinstr is longer then oldinstr)
is added at compile time, and no oldinstr nops optimization has to be
done at runtime. Also couple of compile time sanity checks are done:
1. oldinstr and altinstr must be <= 254 bytes long,
2. oldinstr and altinstr must not have an odd length.
alternative(oldinstr, altinstr, facility);
alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2);
Both compile time and runtime padding consists of either 6/4/2 bytes nop
or a jump (brcl) + 2 bytes nop filler if padding is longer then 6 bytes.
.altinstructions and .altinstr_replacement sections are part of
__init_begin : __init_end region and are freed after initialization.
Signed-off-by: Vasily Gorbik <gor@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
2017-10-12 13:01:47 +02:00
|
|
|
|
|
|
|
static int __initdata_or_module alt_instr_disabled;
|
|
|
|
|
|
|
|
static int __init disable_alternative_instructions(char *str)
|
|
|
|
{
|
|
|
|
alt_instr_disabled = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
early_param("noaltinstr", disable_alternative_instructions);
|
|
|
|
|
|
|
|
static void __init_or_module __apply_alternatives(struct alt_instr *start,
|
|
|
|
struct alt_instr *end)
|
|
|
|
{
|
|
|
|
struct alt_instr *a;
|
|
|
|
u8 *instr, *replacement;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The scan order should be from start to end. A later scanned
|
|
|
|
* alternative code can overwrite previously scanned alternative code.
|
|
|
|
*/
|
|
|
|
for (a = start; a < end; a++) {
|
|
|
|
instr = (u8 *)&a->instr_offset + a->instr_offset;
|
|
|
|
replacement = (u8 *)&a->repl_offset + a->repl_offset;
|
|
|
|
|
2021-05-05 22:01:10 +02:00
|
|
|
if (!__test_facility(a->facility, alt_stfle_fac_list))
|
s390: introduce CPU alternatives
Implement CPU alternatives, which allows to optionally patch newer
instructions at runtime, based on CPU facilities availability.
A new kernel boot parameter "noaltinstr" disables patching.
Current implementation is derived from x86 alternatives. Although
ideal instructions padding (when altinstr is longer then oldinstr)
is added at compile time, and no oldinstr nops optimization has to be
done at runtime. Also couple of compile time sanity checks are done:
1. oldinstr and altinstr must be <= 254 bytes long,
2. oldinstr and altinstr must not have an odd length.
alternative(oldinstr, altinstr, facility);
alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2);
Both compile time and runtime padding consists of either 6/4/2 bytes nop
or a jump (brcl) + 2 bytes nop filler if padding is longer then 6 bytes.
.altinstructions and .altinstr_replacement sections are part of
__init_begin : __init_end region and are freed after initialization.
Signed-off-by: Vasily Gorbik <gor@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
2017-10-12 13:01:47 +02:00
|
|
|
continue;
|
2022-05-11 14:05:26 +02:00
|
|
|
s390_kernel_write(instr, replacement, a->instrlen);
|
s390: introduce CPU alternatives
Implement CPU alternatives, which allows to optionally patch newer
instructions at runtime, based on CPU facilities availability.
A new kernel boot parameter "noaltinstr" disables patching.
Current implementation is derived from x86 alternatives. Although
ideal instructions padding (when altinstr is longer then oldinstr)
is added at compile time, and no oldinstr nops optimization has to be
done at runtime. Also couple of compile time sanity checks are done:
1. oldinstr and altinstr must be <= 254 bytes long,
2. oldinstr and altinstr must not have an odd length.
alternative(oldinstr, altinstr, facility);
alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2);
Both compile time and runtime padding consists of either 6/4/2 bytes nop
or a jump (brcl) + 2 bytes nop filler if padding is longer then 6 bytes.
.altinstructions and .altinstr_replacement sections are part of
__init_begin : __init_end region and are freed after initialization.
Signed-off-by: Vasily Gorbik <gor@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
2017-10-12 13:01:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void __init_or_module apply_alternatives(struct alt_instr *start,
|
|
|
|
struct alt_instr *end)
|
|
|
|
{
|
|
|
|
if (!alt_instr_disabled)
|
|
|
|
__apply_alternatives(start, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
|
|
|
|
void __init apply_alternative_instructions(void)
|
|
|
|
{
|
|
|
|
apply_alternatives(__alt_instructions, __alt_instructions_end);
|
|
|
|
}
|
2021-10-01 12:47:01 +02:00
|
|
|
|
|
|
|
static void do_sync_core(void *info)
|
|
|
|
{
|
|
|
|
sync_core();
|
|
|
|
}
|
|
|
|
|
|
|
|
void text_poke_sync(void)
|
|
|
|
{
|
|
|
|
on_each_cpu(do_sync_core, NULL, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void text_poke_sync_lock(void)
|
|
|
|
{
|
|
|
|
cpus_read_lock();
|
|
|
|
text_poke_sync();
|
|
|
|
cpus_read_unlock();
|
|
|
|
}
|