mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 's390-6.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull more s390 updates from Vasily Gorbik: - Fix KMSAN build breakage caused by the conflict between s390 and mm-stable trees - Add KMSAN page markers for ptdump - Add runtime constant support - Fix __pa/__va for modules under non-GPL licenses by exporting necessary vm_layout struct with EXPORT_SYMBOL to prevent linkage problems - Fix an endless loop in the CF_DIAG event stop in the CPU Measurement Counter Facility code when the counter set size is zero - Remove the PROTECTED_VIRTUALIZATION_GUEST config option and enable its functionality by default - Support allocation of multiple MSI interrupts per device and improve logging of architecture-specific limitations - Add support for lowcore relocation as a debugging feature to catch all null ptr dereferences in the kernel address space, improving detection beyond the current implementation's limited write access protection - Clean up and rework CPU alternatives to allow for callbacks and early patching for the lowcore relocation * tag 's390-6.11-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (39 commits) s390: Remove protvirt and kvm config guards for uv code s390/boot: Add cmdline option to relocate lowcore s390/kdump: Make kdump ready for lowcore relocation s390/entry: Make system_call() ready for lowcore relocation s390/entry: Make ret_from_fork() ready for lowcore relocation s390/entry: Make __switch_to() ready for lowcore relocation s390/entry: Make restart_int_handler() ready for lowcore relocation s390/entry: Make mchk_int_handler() ready for lowcore relocation s390/entry: Make int handlers ready for lowcore relocation s390/entry: Make pgm_check_handler() ready for lowcore relocation s390/entry: Add base register to CHECK_VMAP_STACK/CHECK_STACK macro s390/entry: Add base register to SIEEXIT macro s390/entry: Add base register to MBEAR macro s390/entry: Make __sie64a() ready for lowcore relocation s390/head64: Make startup code ready for lowcore relocation s390: Add infrastructure to patch lowcore accesses s390/atomic_ops: Disable flag outputs constraint for GCC versions below 14.2.0 s390/entry: Move SIE indicator flag to thread info s390/nmi: Simplify ptregs setup s390/alternatives: Remove alternative facility list ...
This commit is contained in:
@@ -3830,9 +3830,6 @@
|
||||
|
||||
noalign [KNL,ARM]
|
||||
|
||||
noaltinstr [S390,EARLY] Disables alternative instructions
|
||||
patching (CPU alternatives feature).
|
||||
|
||||
noapic [SMP,APIC,EARLY] Tells the kernel to not make use of any
|
||||
IOAPICs that may be present in the system.
|
||||
|
||||
|
||||
@@ -799,17 +799,6 @@ config HAVE_PNETID
|
||||
|
||||
menu "Virtualization"
|
||||
|
||||
config PROTECTED_VIRTUALIZATION_GUEST
|
||||
def_bool n
|
||||
prompt "Protected virtualization guest support"
|
||||
help
|
||||
Select this option, if you want to be able to run this
|
||||
kernel as a protected virtualization KVM guest.
|
||||
Protected virtualization capable machines have a mini hypervisor
|
||||
located at machine level (an ultravisor). With help of the
|
||||
Ultravisor, KVM will be able to run "protected" VMs, special
|
||||
VMs whose memory and management data are unavailable to KVM.
|
||||
|
||||
config PFAULT
|
||||
def_bool y
|
||||
prompt "Pseudo page fault support"
|
||||
|
||||
@@ -39,8 +39,7 @@ CFLAGS_sclp_early_core.o += -I$(srctree)/drivers/s390/char
|
||||
|
||||
obj-y := head.o als.o startup.o physmem_info.o ipl_parm.o ipl_report.o vmem.o
|
||||
obj-y += string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o
|
||||
obj-y += version.o pgm_check_info.o ctype.o ipl_data.o relocs.o
|
||||
obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_PGSTE)) += uv.o
|
||||
obj-y += version.o pgm_check_info.o ctype.o ipl_data.o relocs.o alternative.o uv.o
|
||||
obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
|
||||
obj-y += $(if $(CONFIG_KERNEL_UNCOMPRESSED),,decompressor.o) info.o
|
||||
obj-$(CONFIG_KERNEL_ZSTD) += clz_ctz.o
|
||||
|
||||
3
arch/s390/boot/alternative.c
Normal file
3
arch/s390/boot/alternative.c
Normal file
@@ -0,0 +1,3 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include "../kernel/alternative.c"
|
||||
@@ -30,6 +30,8 @@ struct vmlinux_info {
|
||||
unsigned long init_mm_off;
|
||||
unsigned long swapper_pg_dir_off;
|
||||
unsigned long invalid_pg_dir_off;
|
||||
unsigned long alt_instructions;
|
||||
unsigned long alt_instructions_end;
|
||||
#ifdef CONFIG_KASAN
|
||||
unsigned long kasan_early_shadow_page_off;
|
||||
unsigned long kasan_early_shadow_pte_off;
|
||||
@@ -89,8 +91,10 @@ extern char _end[], _decompressor_end[];
|
||||
extern unsigned char _compressed_start[];
|
||||
extern unsigned char _compressed_end[];
|
||||
extern struct vmlinux_info _vmlinux_info;
|
||||
|
||||
#define vmlinux _vmlinux_info
|
||||
|
||||
#define __lowcore_pa(x) ((unsigned long)(x) % sizeof(struct lowcore))
|
||||
#define __abs_lowcore_pa(x) (((unsigned long)(x) - __abs_lowcore) % sizeof(struct lowcore))
|
||||
#define __kernel_va(x) ((void *)((unsigned long)(x) - __kaslr_offset_phys + __kaslr_offset))
|
||||
#define __kernel_pa(x) ((unsigned long)(x) - __kaslr_offset + __kaslr_offset_phys)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/pgtable.h>
|
||||
#include <asm/abs_lowcore.h>
|
||||
#include <asm/page-states.h>
|
||||
#include <asm/ebcdic.h>
|
||||
#include <asm/sclp.h>
|
||||
@@ -310,5 +311,7 @@ void parse_boot_command_line(void)
|
||||
prot_virt_host = 1;
|
||||
}
|
||||
#endif
|
||||
if (!strcmp(param, "relocate_lowcore") && test_facility(193))
|
||||
relocate_lowcore = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ unsigned long __bootdata_preserved(vmemmap_size);
|
||||
unsigned long __bootdata_preserved(MODULES_VADDR);
|
||||
unsigned long __bootdata_preserved(MODULES_END);
|
||||
unsigned long __bootdata_preserved(max_mappable);
|
||||
int __bootdata_preserved(relocate_lowcore);
|
||||
|
||||
u64 __bootdata_preserved(stfle_fac_list[16]);
|
||||
struct oldmem_data __bootdata_preserved(oldmem_data);
|
||||
@@ -376,6 +377,8 @@ static void kaslr_adjust_vmlinux_info(long offset)
|
||||
vmlinux.init_mm_off += offset;
|
||||
vmlinux.swapper_pg_dir_off += offset;
|
||||
vmlinux.invalid_pg_dir_off += offset;
|
||||
vmlinux.alt_instructions += offset;
|
||||
vmlinux.alt_instructions_end += offset;
|
||||
#ifdef CONFIG_KASAN
|
||||
vmlinux.kasan_early_shadow_page_off += offset;
|
||||
vmlinux.kasan_early_shadow_pte_off += offset;
|
||||
@@ -478,8 +481,12 @@ void startup_kernel(void)
|
||||
* before the kernel started. Therefore, in case the two sections
|
||||
* overlap there is no risk of corrupting any data.
|
||||
*/
|
||||
if (kaslr_enabled())
|
||||
amode31_lma = randomize_within_range(vmlinux.amode31_size, PAGE_SIZE, 0, SZ_2G);
|
||||
if (kaslr_enabled()) {
|
||||
unsigned long amode31_min;
|
||||
|
||||
amode31_min = (unsigned long)_decompressor_end;
|
||||
amode31_lma = randomize_within_range(vmlinux.amode31_size, PAGE_SIZE, amode31_min, SZ_2G);
|
||||
}
|
||||
if (!amode31_lma)
|
||||
amode31_lma = __kaslr_offset_phys - vmlinux.amode31_size;
|
||||
physmem_reserve(RR_AMODE31, amode31_lma, vmlinux.amode31_size);
|
||||
@@ -503,6 +510,9 @@ void startup_kernel(void)
|
||||
kaslr_adjust_got(__kaslr_offset);
|
||||
setup_vmem(__kaslr_offset, __kaslr_offset + kernel_size, asce_limit);
|
||||
copy_bootdata();
|
||||
__apply_alternatives((struct alt_instr *)_vmlinux_info.alt_instructions,
|
||||
(struct alt_instr *)_vmlinux_info.alt_instructions_end,
|
||||
ALT_CTX_EARLY);
|
||||
|
||||
/*
|
||||
* Save KASLR offset for early dumps, before vmcore_info is set.
|
||||
|
||||
@@ -8,12 +8,8 @@
|
||||
#include "uv.h"
|
||||
|
||||
/* will be used in arch/s390/kernel/uv.c */
|
||||
#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
|
||||
int __bootdata_preserved(prot_virt_guest);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_KVM)
|
||||
int __bootdata_preserved(prot_virt_host);
|
||||
#endif
|
||||
struct uv_info __bootdata_preserved(uv_info);
|
||||
|
||||
void uv_query_info(void)
|
||||
@@ -53,14 +49,11 @@ void uv_query_info(void)
|
||||
uv_info.max_secrets = uvcb.max_secrets;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
|
||||
if (test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list) &&
|
||||
test_bit_inv(BIT_UVC_CMD_REMOVE_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list))
|
||||
prot_virt_guest = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_KVM)
|
||||
unsigned long adjust_to_uv_max(unsigned long limit)
|
||||
{
|
||||
if (is_prot_virt_host() && uv_info.max_sec_stor_addr)
|
||||
@@ -92,4 +85,3 @@ void sanitize_prot_virt_host(void)
|
||||
{
|
||||
prot_virt_host = is_prot_virt_host_capable();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2,21 +2,8 @@
|
||||
#ifndef BOOT_UV_H
|
||||
#define BOOT_UV_H
|
||||
|
||||
#if IS_ENABLED(CONFIG_KVM)
|
||||
unsigned long adjust_to_uv_max(unsigned long limit);
|
||||
void sanitize_prot_virt_host(void);
|
||||
#else
|
||||
static inline unsigned long adjust_to_uv_max(unsigned long limit)
|
||||
{
|
||||
return limit;
|
||||
}
|
||||
static inline void sanitize_prot_virt_host(void) {}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || IS_ENABLED(CONFIG_KVM)
|
||||
void uv_query_info(void);
|
||||
#else
|
||||
static inline void uv_query_info(void) {}
|
||||
#endif
|
||||
|
||||
#endif /* BOOT_UV_H */
|
||||
|
||||
@@ -26,6 +26,7 @@ atomic_long_t __bootdata_preserved(direct_pages_count[PG_DIRECT_MAP_MAX]);
|
||||
enum populate_mode {
|
||||
POPULATE_NONE,
|
||||
POPULATE_DIRECT,
|
||||
POPULATE_LOWCORE,
|
||||
POPULATE_ABS_LOWCORE,
|
||||
POPULATE_IDENTITY,
|
||||
POPULATE_KERNEL,
|
||||
@@ -242,6 +243,8 @@ static unsigned long _pa(unsigned long addr, unsigned long size, enum populate_m
|
||||
return -1;
|
||||
case POPULATE_DIRECT:
|
||||
return addr;
|
||||
case POPULATE_LOWCORE:
|
||||
return __lowcore_pa(addr);
|
||||
case POPULATE_ABS_LOWCORE:
|
||||
return __abs_lowcore_pa(addr);
|
||||
case POPULATE_KERNEL:
|
||||
@@ -418,6 +421,7 @@ static void pgtable_populate(unsigned long addr, unsigned long end, enum populat
|
||||
|
||||
void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned long asce_limit)
|
||||
{
|
||||
unsigned long lowcore_address = 0;
|
||||
unsigned long start, end;
|
||||
unsigned long asce_type;
|
||||
unsigned long asce_bits;
|
||||
@@ -455,12 +459,17 @@ void setup_vmem(unsigned long kernel_start, unsigned long kernel_end, unsigned l
|
||||
__arch_set_page_dat((void *)swapper_pg_dir, 1UL << CRST_ALLOC_ORDER);
|
||||
__arch_set_page_dat((void *)invalid_pg_dir, 1UL << CRST_ALLOC_ORDER);
|
||||
|
||||
if (relocate_lowcore)
|
||||
lowcore_address = LOWCORE_ALT_ADDRESS;
|
||||
|
||||
/*
|
||||
* To allow prefixing the lowcore must be mapped with 4KB pages.
|
||||
* To prevent creation of a large page at address 0 first map
|
||||
* the lowcore and create the identity mapping only afterwards.
|
||||
*/
|
||||
pgtable_populate(0, sizeof(struct lowcore), POPULATE_DIRECT);
|
||||
pgtable_populate(lowcore_address,
|
||||
lowcore_address + sizeof(struct lowcore),
|
||||
POPULATE_LOWCORE);
|
||||
for_each_physmem_usable_range(i, &start, &end) {
|
||||
pgtable_populate((unsigned long)__identity_va(start),
|
||||
(unsigned long)__identity_va(end),
|
||||
|
||||
@@ -55,7 +55,6 @@ CONFIG_EXPOLINE_AUTO=y
|
||||
CONFIG_CHSC_SCH=y
|
||||
CONFIG_VFIO_CCW=m
|
||||
CONFIG_VFIO_AP=m
|
||||
CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
|
||||
CONFIG_CMM=m
|
||||
CONFIG_APPLDATA_BASE=y
|
||||
CONFIG_S390_HYPFS_FS=y
|
||||
|
||||
@@ -53,7 +53,6 @@ CONFIG_EXPOLINE_AUTO=y
|
||||
CONFIG_CHSC_SCH=y
|
||||
CONFIG_VFIO_CCW=m
|
||||
CONFIG_VFIO_AP=m
|
||||
CONFIG_PROTECTED_VIRTUALIZATION_GUEST=y
|
||||
CONFIG_CMM=m
|
||||
CONFIG_APPLDATA_BASE=y
|
||||
CONFIG_S390_HYPFS_FS=y
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#ifndef _ASM_S390_ABS_LOWCORE_H
|
||||
#define _ASM_S390_ABS_LOWCORE_H
|
||||
|
||||
#include <asm/sections.h>
|
||||
#include <asm/lowcore.h>
|
||||
|
||||
#define ABS_LOWCORE_MAP_SIZE (NR_CPUS * sizeof(struct lowcore))
|
||||
@@ -24,4 +25,11 @@ static inline void put_abs_lowcore(struct lowcore *lc)
|
||||
put_cpu();
|
||||
}
|
||||
|
||||
extern int __bootdata_preserved(relocate_lowcore);
|
||||
|
||||
static inline int have_relocated_lowcore(void)
|
||||
{
|
||||
return relocate_lowcore;
|
||||
}
|
||||
|
||||
#endif /* _ASM_S390_ABS_LOWCORE_H */
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ASM_S390_ALTERNATIVE_ASM_H
|
||||
#define _ASM_S390_ALTERNATIVE_ASM_H
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
/*
|
||||
* Issue one struct alt_instr descriptor entry (need to put it into
|
||||
* the section .altinstructions, see below). This entry contains
|
||||
* enough information for the alternatives patching code to patch an
|
||||
* instruction. See apply_alternatives().
|
||||
*/
|
||||
.macro alt_entry orig_start, orig_end, alt_start, alt_end, feature
|
||||
.long \orig_start - .
|
||||
.long \alt_start - .
|
||||
.word \feature
|
||||
.byte \orig_end - \orig_start
|
||||
.org . - ( \orig_end - \orig_start ) & 1
|
||||
.org . - ( \orig_end - \orig_start ) + ( \alt_end - \alt_start )
|
||||
.org . - ( \alt_end - \alt_start ) + ( \orig_end - \orig_start )
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Define an alternative between two instructions. If @feature is
|
||||
* present, early code in apply_alternatives() replaces @oldinstr with
|
||||
* @newinstr.
|
||||
*/
|
||||
.macro ALTERNATIVE oldinstr, newinstr, feature
|
||||
.pushsection .altinstr_replacement,"ax"
|
||||
770: \newinstr
|
||||
771: .popsection
|
||||
772: \oldinstr
|
||||
773: .pushsection .altinstructions,"a"
|
||||
alt_entry 772b, 773b, 770b, 771b, \feature
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Define an alternative between two instructions. If @feature is
|
||||
* present, early code in apply_alternatives() replaces @oldinstr with
|
||||
* @newinstr.
|
||||
*/
|
||||
.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
|
||||
.pushsection .altinstr_replacement,"ax"
|
||||
770: \newinstr1
|
||||
771: \newinstr2
|
||||
772: .popsection
|
||||
773: \oldinstr
|
||||
774: .pushsection .altinstructions,"a"
|
||||
alt_entry 773b, 774b, 770b, 771b,\feature1
|
||||
alt_entry 773b, 774b, 771b, 772b,\feature2
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_S390_ALTERNATIVE_ASM_H */
|
||||
@@ -2,6 +2,58 @@
|
||||
#ifndef _ASM_S390_ALTERNATIVE_H
|
||||
#define _ASM_S390_ALTERNATIVE_H
|
||||
|
||||
/*
|
||||
* Each alternative comes with a 32 bit feature field:
|
||||
* union {
|
||||
* u32 feature;
|
||||
* struct {
|
||||
* u32 ctx : 4;
|
||||
* u32 type : 8;
|
||||
* u32 data : 20;
|
||||
* };
|
||||
* }
|
||||
*
|
||||
* @ctx is a bitfield, where only one bit must be set. Each bit defines
|
||||
* in which context an alternative is supposed to be applied to the
|
||||
* kernel image:
|
||||
*
|
||||
* - from the decompressor before the kernel itself is executed
|
||||
* - from early kernel code from within the kernel
|
||||
*
|
||||
* @type is a number which defines the type and with that the type
|
||||
* specific alternative patching.
|
||||
*
|
||||
* @data is additional type specific information which defines if an
|
||||
* alternative should be applied.
|
||||
*/
|
||||
|
||||
#define ALT_CTX_EARLY 1
|
||||
#define ALT_CTX_LATE 2
|
||||
#define ALT_CTX_ALL (ALT_CTX_EARLY | ALT_CTX_LATE)
|
||||
|
||||
#define ALT_TYPE_FACILITY 0
|
||||
#define ALT_TYPE_SPEC 1
|
||||
#define ALT_TYPE_LOWCORE 2
|
||||
|
||||
#define ALT_DATA_SHIFT 0
|
||||
#define ALT_TYPE_SHIFT 20
|
||||
#define ALT_CTX_SHIFT 28
|
||||
|
||||
#define ALT_FACILITY_EARLY(facility) (ALT_CTX_EARLY << ALT_CTX_SHIFT | \
|
||||
ALT_TYPE_FACILITY << ALT_TYPE_SHIFT | \
|
||||
(facility) << ALT_DATA_SHIFT)
|
||||
|
||||
#define ALT_FACILITY(facility) (ALT_CTX_LATE << ALT_CTX_SHIFT | \
|
||||
ALT_TYPE_FACILITY << ALT_TYPE_SHIFT | \
|
||||
(facility) << ALT_DATA_SHIFT)
|
||||
|
||||
#define ALT_SPEC(facility) (ALT_CTX_LATE << ALT_CTX_SHIFT | \
|
||||
ALT_TYPE_SPEC << ALT_TYPE_SHIFT | \
|
||||
(facility) << ALT_DATA_SHIFT)
|
||||
|
||||
#define ALT_LOWCORE (ALT_CTX_EARLY << ALT_CTX_SHIFT | \
|
||||
ALT_TYPE_LOWCORE << ALT_TYPE_SHIFT)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/types.h>
|
||||
@@ -11,12 +63,30 @@
|
||||
struct alt_instr {
|
||||
s32 instr_offset; /* original instruction */
|
||||
s32 repl_offset; /* offset to replacement instruction */
|
||||
u16 facility; /* facility bit set for replacement */
|
||||
union {
|
||||
u32 feature; /* feature required for replacement */
|
||||
struct {
|
||||
u32 ctx : 4; /* context */
|
||||
u32 type : 8; /* type of alternative */
|
||||
u32 data : 20; /* patching information */
|
||||
};
|
||||
};
|
||||
u8 instrlen; /* length of original instruction */
|
||||
} __packed;
|
||||
|
||||
void apply_alternative_instructions(void);
|
||||
void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
|
||||
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
|
||||
|
||||
void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsigned int ctx);
|
||||
|
||||
static inline void apply_alternative_instructions(void)
|
||||
{
|
||||
__apply_alternatives(__alt_instructions, __alt_instructions_end, ALT_CTX_LATE);
|
||||
}
|
||||
|
||||
static inline void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
|
||||
{
|
||||
__apply_alternatives(start, end, ALT_CTX_ALL);
|
||||
}
|
||||
|
||||
/*
|
||||
* +---------------------------------+
|
||||
@@ -48,10 +118,10 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
|
||||
#define OLDINSTR(oldinstr) \
|
||||
"661:\n\t" oldinstr "\n662:\n"
|
||||
|
||||
#define ALTINSTR_ENTRY(facility, num) \
|
||||
#define ALTINSTR_ENTRY(feature, num) \
|
||||
"\t.long 661b - .\n" /* old instruction */ \
|
||||
"\t.long " b_altinstr(num)"b - .\n" /* alt instruction */ \
|
||||
"\t.word " __stringify(facility) "\n" /* facility bit */ \
|
||||
"\t.long " __stringify(feature) "\n" /* feature */ \
|
||||
"\t.byte " oldinstr_len "\n" /* instruction len */ \
|
||||
"\t.org . - (" oldinstr_len ") & 1\n" \
|
||||
"\t.org . - (" oldinstr_len ") + (" altinstr_len(num) ")\n" \
|
||||
@@ -61,24 +131,24 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
|
||||
b_altinstr(num)":\n\t" altinstr "\n" e_altinstr(num) ":\n"
|
||||
|
||||
/* alternative assembly primitive: */
|
||||
#define ALTERNATIVE(oldinstr, altinstr, facility) \
|
||||
#define ALTERNATIVE(oldinstr, altinstr, feature) \
|
||||
".pushsection .altinstr_replacement, \"ax\"\n" \
|
||||
ALTINSTR_REPLACEMENT(altinstr, 1) \
|
||||
".popsection\n" \
|
||||
OLDINSTR(oldinstr) \
|
||||
".pushsection .altinstructions,\"a\"\n" \
|
||||
ALTINSTR_ENTRY(facility, 1) \
|
||||
ALTINSTR_ENTRY(feature, 1) \
|
||||
".popsection\n"
|
||||
|
||||
#define ALTERNATIVE_2(oldinstr, altinstr1, facility1, altinstr2, facility2)\
|
||||
#define ALTERNATIVE_2(oldinstr, altinstr1, feature1, altinstr2, feature2)\
|
||||
".pushsection .altinstr_replacement, \"ax\"\n" \
|
||||
ALTINSTR_REPLACEMENT(altinstr1, 1) \
|
||||
ALTINSTR_REPLACEMENT(altinstr2, 2) \
|
||||
".popsection\n" \
|
||||
OLDINSTR(oldinstr) \
|
||||
".pushsection .altinstructions,\"a\"\n" \
|
||||
ALTINSTR_ENTRY(facility1, 1) \
|
||||
ALTINSTR_ENTRY(facility2, 2) \
|
||||
ALTINSTR_ENTRY(feature1, 1) \
|
||||
ALTINSTR_ENTRY(feature2, 2) \
|
||||
".popsection\n"
|
||||
|
||||
/*
|
||||
@@ -93,12 +163,12 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
|
||||
* For non barrier like inlines please define new variants
|
||||
* without volatile and memory clobber.
|
||||
*/
|
||||
#define alternative(oldinstr, altinstr, facility) \
|
||||
asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, facility) : : : "memory")
|
||||
#define alternative(oldinstr, altinstr, feature) \
|
||||
asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, feature) : : : "memory")
|
||||
|
||||
#define alternative_2(oldinstr, altinstr1, facility1, altinstr2, facility2) \
|
||||
asm_inline volatile(ALTERNATIVE_2(oldinstr, altinstr1, facility1, \
|
||||
altinstr2, facility2) ::: "memory")
|
||||
#define alternative_2(oldinstr, altinstr1, feature1, altinstr2, feature2) \
|
||||
asm_inline volatile(ALTERNATIVE_2(oldinstr, altinstr1, feature1, \
|
||||
altinstr2, feature2) ::: "memory")
|
||||
|
||||
/* Alternative inline assembly with input. */
|
||||
#define alternative_input(oldinstr, newinstr, feature, input...) \
|
||||
@@ -106,8 +176,8 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
|
||||
: : input)
|
||||
|
||||
/* Like alternative_input, but with a single output argument */
|
||||
#define alternative_io(oldinstr, altinstr, facility, output, input...) \
|
||||
asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, facility) \
|
||||
#define alternative_io(oldinstr, altinstr, feature, output, input...) \
|
||||
asm_inline volatile(ALTERNATIVE(oldinstr, altinstr, feature) \
|
||||
: output : input)
|
||||
|
||||
/* Use this macro if more than one output parameter is needed. */
|
||||
@@ -116,6 +186,56 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
|
||||
/* Use this macro if clobbers are needed without inputs. */
|
||||
#define ASM_NO_INPUT_CLOBBER(clobber...) : clobber
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
* Issue one struct alt_instr descriptor entry (need to put it into
|
||||
* the section .altinstructions, see below). This entry contains
|
||||
* enough information for the alternatives patching code to patch an
|
||||
* instruction. See apply_alternatives().
|
||||
*/
|
||||
.macro alt_entry orig_start, orig_end, alt_start, alt_end, feature
|
||||
.long \orig_start - .
|
||||
.long \alt_start - .
|
||||
.long \feature
|
||||
.byte \orig_end - \orig_start
|
||||
.org . - ( \orig_end - \orig_start ) & 1
|
||||
.org . - ( \orig_end - \orig_start ) + ( \alt_end - \alt_start )
|
||||
.org . - ( \alt_end - \alt_start ) + ( \orig_end - \orig_start )
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Define an alternative between two instructions. If @feature is
|
||||
* present, early code in apply_alternatives() replaces @oldinstr with
|
||||
* @newinstr.
|
||||
*/
|
||||
.macro ALTERNATIVE oldinstr, newinstr, feature
|
||||
.pushsection .altinstr_replacement,"ax"
|
||||
770: \newinstr
|
||||
771: .popsection
|
||||
772: \oldinstr
|
||||
773: .pushsection .altinstructions,"a"
|
||||
alt_entry 772b, 773b, 770b, 771b, \feature
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Define an alternative between two instructions. If @feature is
|
||||
* present, early code in apply_alternatives() replaces @oldinstr with
|
||||
* @newinstr.
|
||||
*/
|
||||
.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
|
||||
.pushsection .altinstr_replacement,"ax"
|
||||
770: \newinstr1
|
||||
771: \newinstr2
|
||||
772: .popsection
|
||||
773: \oldinstr
|
||||
774: .pushsection .altinstructions,"a"
|
||||
alt_entry 773b, 774b, 770b, 771b,\feature1
|
||||
alt_entry 773b, 774b, 771b, 772b,\feature2
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_S390_ALTERNATIVE_H */
|
||||
|
||||
@@ -188,7 +188,8 @@ static __always_inline long __atomic64_cmpxchg(long *ptr, long old, long new)
|
||||
return old;
|
||||
}
|
||||
|
||||
#ifdef __GCC_ASM_FLAG_OUTPUTS__
|
||||
/* GCC versions before 14.2.0 may die with an ICE in some configurations. */
|
||||
#if defined(__GCC_ASM_FLAG_OUTPUTS__) && !(IS_ENABLED(CONFIG_CC_IS_GCC) && (GCC_VERSION < 140200))
|
||||
|
||||
static __always_inline bool __atomic_cmpxchg_bool(int *ptr, int old, int new)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#define MAX_FACILITY_BIT (sizeof(stfle_fac_list) * 8)
|
||||
|
||||
extern u64 stfle_fac_list[16];
|
||||
extern u64 alt_stfle_fac_list[16];
|
||||
|
||||
static inline void __set_facility(unsigned long nr, void *facilities)
|
||||
{
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
|
||||
static inline bool is_lowcore_addr(void *addr)
|
||||
{
|
||||
return addr >= (void *)&S390_lowcore &&
|
||||
addr < (void *)(&S390_lowcore + 1);
|
||||
return addr >= (void *)get_lowcore() &&
|
||||
addr < (void *)(get_lowcore() + 1);
|
||||
}
|
||||
|
||||
static inline void *arch_kmsan_get_meta_or_null(void *addr, bool is_origin)
|
||||
@@ -25,7 +25,7 @@ static inline void *arch_kmsan_get_meta_or_null(void *addr, bool is_origin)
|
||||
* order to get a distinct struct page.
|
||||
*/
|
||||
addr += (void *)lowcore_ptr[raw_smp_processor_id()] -
|
||||
(void *)&S390_lowcore;
|
||||
(void *)get_lowcore();
|
||||
if (KMSAN_WARN_ON(is_lowcore_addr(addr)))
|
||||
return NULL;
|
||||
return kmsan_get_metadata(addr, is_origin);
|
||||
|
||||
@@ -14,10 +14,15 @@
|
||||
#include <asm/ctlreg.h>
|
||||
#include <asm/cpu.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm/alternative.h>
|
||||
|
||||
#define LC_ORDER 1
|
||||
#define LC_PAGES 2
|
||||
|
||||
#define LOWCORE_ALT_ADDRESS _AC(0x70000, UL)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
struct pgm_tdb {
|
||||
u64 data[32];
|
||||
};
|
||||
@@ -97,8 +102,7 @@ struct lowcore {
|
||||
__u64 save_area_async[8]; /* 0x0240 */
|
||||
__u64 save_area_restart[1]; /* 0x0280 */
|
||||
|
||||
/* CPU flags. */
|
||||
__u64 cpu_flags; /* 0x0288 */
|
||||
__u64 pcpu; /* 0x0288 */
|
||||
|
||||
/* Return psws. */
|
||||
psw_t return_psw; /* 0x0290 */
|
||||
@@ -215,7 +219,14 @@ struct lowcore {
|
||||
|
||||
static __always_inline struct lowcore *get_lowcore(void)
|
||||
{
|
||||
return NULL;
|
||||
struct lowcore *lc;
|
||||
|
||||
if (__is_defined(__DECOMPRESSOR))
|
||||
return NULL;
|
||||
asm(ALTERNATIVE("llilh %[lc],0", "llilh %[lc],%[alt]", ALT_LOWCORE)
|
||||
: [lc] "=d" (lc)
|
||||
: [alt] "i" (LOWCORE_ALT_ADDRESS >> 16));
|
||||
return lc;
|
||||
}
|
||||
|
||||
extern struct lowcore *lowcore_ptr[];
|
||||
@@ -225,4 +236,19 @@ static inline void set_prefix(__u32 address)
|
||||
asm volatile("spx %0" : : "Q" (address) : "memory");
|
||||
}
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
.macro GET_LC reg
|
||||
ALTERNATIVE "llilh \reg,0", \
|
||||
__stringify(llilh \reg, LOWCORE_ALT_ADDRESS >> 16), \
|
||||
ALT_LOWCORE
|
||||
.endm
|
||||
|
||||
.macro STMG_LC start, end, savearea
|
||||
ALTERNATIVE "stmg \start, \end, \savearea", \
|
||||
__stringify(stmg \start, \end, LOWCORE_ALT_ADDRESS + \savearea), \
|
||||
ALT_LOWCORE
|
||||
.endm
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* _ASM_S390_LOWCORE_H */
|
||||
|
||||
@@ -5,8 +5,17 @@
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/facility.h>
|
||||
|
||||
extern int nospec_disable;
|
||||
extern int nobp;
|
||||
|
||||
static inline bool nobp_enabled(void)
|
||||
{
|
||||
if (__is_defined(__DECOMPRESSOR))
|
||||
return false;
|
||||
return nobp && test_facility(82);
|
||||
}
|
||||
|
||||
void nospec_init_branches(void);
|
||||
void nospec_auto_detect(void);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user