2018-07-19 13:11:28 +02:00
// SPDX-License-Identifier: GPL-2.0
# include <linux/string.h>
2019-02-03 21:35:45 +01:00
# include <linux/elf.h>
2020-10-19 11:01:33 +02:00
# include <asm/boot_data.h>
2019-02-03 21:37:20 +01:00
# include <asm/sections.h>
2022-12-11 08:18:57 +01:00
# include <asm/maccess.h>
2020-10-09 17:14:02 +02:00
# include <asm/cpu_mf.h>
2018-04-11 11:56:55 +02:00
# include <asm/setup.h>
2020-10-06 22:12:39 +02:00
# include <asm/kasan.h>
2019-02-03 21:35:45 +01:00
# include <asm/kexec.h>
2018-07-25 15:01:11 +02:00
# include <asm/sclp.h>
2019-02-03 21:37:20 +01:00
# include <asm/diag.h>
2019-04-01 19:11:03 +02:00
# include <asm/uv.h>
2022-07-20 08:22:01 +02:00
# include <asm/abs_lowcore.h>
2022-12-13 11:35:11 +01:00
# include <asm/mem_detect.h>
2022-04-23 21:31:22 +02:00
# include "decompressor.h"
2018-07-19 13:11:28 +02:00
# include "boot.h"
2021-07-05 19:33:27 +02:00
# include "uv.h"
2018-07-19 13:11:28 +02:00
2019-02-03 21:37:20 +01:00
unsigned long __bootdata_preserved ( __kaslr_offset ) ;
2022-07-20 08:22:01 +02:00
unsigned long __bootdata_preserved ( __abs_lowcore ) ;
2022-07-24 15:02:16 +02:00
unsigned long __bootdata_preserved ( __memcpy_real_area ) ;
2022-12-11 08:18:57 +01:00
pte_t * __bootdata_preserved ( memcpy_real_ptep ) ;
2021-09-27 14:18:26 +02:00
unsigned long __bootdata ( __amode31_base ) ;
2020-10-06 22:12:39 +02:00
unsigned long __bootdata_preserved ( VMALLOC_START ) ;
unsigned long __bootdata_preserved ( VMALLOC_END ) ;
struct page * __bootdata_preserved ( vmemmap ) ;
unsigned long __bootdata_preserved ( vmemmap_size ) ;
unsigned long __bootdata_preserved ( MODULES_VADDR ) ;
unsigned long __bootdata_preserved ( MODULES_END ) ;
2020-10-19 11:01:33 +02:00
unsigned long __bootdata ( ident_map_size ) ;
2021-06-15 14:15:07 +02:00
struct initrd_data __bootdata ( initrd_data ) ;
2018-04-10 14:14:02 +02:00
2021-05-05 22:01:10 +02:00
u64 __bootdata_preserved ( stfle_fac_list [ 16 ] ) ;
u64 __bootdata_preserved ( alt_stfle_fac_list [ 16 ] ) ;
2021-06-15 14:25:41 +02:00
struct oldmem_data __bootdata_preserved ( oldmem_data ) ;
2021-05-05 22:01:10 +02:00
2022-12-04 21:15:41 +01:00
struct machine_info machine ;
2018-07-25 15:01:11 +02:00
void error ( char * x )
{
sclp_early_printk ( " \n \n " ) ;
sclp_early_printk ( x ) ;
sclp_early_printk ( " \n \n -- System halted " ) ;
2019-04-30 12:33:45 +02:00
disabled_wait ( ) ;
2018-07-25 15:01:11 +02:00
}
2022-12-04 21:15:41 +01:00
static void detect_facilities ( void )
{
if ( test_facility ( 8 ) ) {
machine . has_edat1 = 1 ;
__ctl_set_bit ( 0 , 23 ) ;
}
if ( test_facility ( 78 ) )
machine . has_edat2 = 1 ;
if ( ! noexec_disabled & & test_facility ( 130 ) ) {
machine . has_nx = 1 ;
__ctl_set_bit ( 0 , 20 ) ;
}
}
2020-10-09 17:14:02 +02:00
static void setup_lpp ( void )
{
S390_lowcore . current_pid = 0 ;
S390_lowcore . lpp = LPP_MAGIC ;
if ( test_facility ( 40 ) )
lpp ( & S390_lowcore . lpp ) ;
}
2018-04-11 11:56:55 +02:00
# ifdef CONFIG_KERNEL_UNCOMPRESSED
unsigned long mem_safe_offset ( void )
{
return vmlinux . default_lma + vmlinux . image_size + vmlinux . bss_size ;
}
# endif
2023-01-23 12:49:47 +01:00
static unsigned long rescue_initrd ( unsigned long safe_addr )
2018-04-11 11:56:55 +02:00
{
if ( ! IS_ENABLED ( CONFIG_BLK_DEV_INITRD ) )
2023-01-23 12:49:47 +01:00
return safe_addr ;
2021-06-15 14:15:07 +02:00
if ( ! initrd_data . start | | ! initrd_data . size )
2023-01-23 12:49:47 +01:00
return safe_addr ;
if ( initrd_data . start < safe_addr ) {
memmove ( ( void * ) safe_addr , ( void * ) initrd_data . start , initrd_data . size ) ;
initrd_data . start = safe_addr ;
}
return initrd_data . start + initrd_data . size ;
2018-04-11 11:56:55 +02:00
}
2018-04-10 14:14:02 +02:00
static void copy_bootdata ( void )
{
if ( __boot_data_end - __boot_data_start ! = vmlinux . bootdata_size )
error ( " .boot.data section size mismatch " ) ;
memcpy ( ( void * ) vmlinux . bootdata_off , __boot_data_start , vmlinux . bootdata_size ) ;
2019-04-01 19:10:45 +02:00
if ( __boot_data_preserved_end - __boot_data_preserved_start ! = vmlinux . bootdata_preserved_size )
error ( " .boot.preserved.data section size mismatch " ) ;
memcpy ( ( void * ) vmlinux . bootdata_preserved_off , __boot_data_preserved_start , vmlinux . bootdata_preserved_size ) ;
2018-04-10 14:14:02 +02:00
}
2019-02-03 21:35:45 +01:00
static void handle_relocs ( unsigned long offset )
{
Elf64_Rela * rela_start , * rela_end , * rela ;
int r_type , r_sym , rc ;
Elf64_Addr loc , val ;
Elf64_Sym * dynsym ;
rela_start = ( Elf64_Rela * ) vmlinux . rela_dyn_start ;
rela_end = ( Elf64_Rela * ) vmlinux . rela_dyn_end ;
dynsym = ( Elf64_Sym * ) vmlinux . dynsym_start ;
for ( rela = rela_start ; rela < rela_end ; rela + + ) {
loc = rela - > r_offset + offset ;
2019-10-21 19:56:00 +02:00
val = rela - > r_addend ;
2019-02-03 21:35:45 +01:00
r_sym = ELF64_R_SYM ( rela - > r_info ) ;
2019-10-21 19:56:00 +02:00
if ( r_sym ) {
if ( dynsym [ r_sym ] . st_shndx ! = SHN_UNDEF )
val + = dynsym [ r_sym ] . st_value + offset ;
} else {
/*
* 0 = = undefined symbol table index ( STN_UNDEF ) ,
* used for R_390_RELATIVE , only add KASLR offset
*/
val + = offset ;
}
2019-02-03 21:35:45 +01:00
r_type = ELF64_R_TYPE ( rela - > r_info ) ;
rc = arch_kexec_do_relocs ( r_type , ( void * ) loc , val , 0 ) ;
if ( rc )
error ( " Unknown relocation type " ) ;
}
}
2020-10-19 11:01:33 +02:00
/*
* Merge information from several sources into a single ident_map_size value .
* " ident_map_size " represents the upper limit of physical memory we may ever
* reach . It might not be all online memory , but also include standby ( offline )
* memory . " ident_map_size " could be lower then actual standby or even online
* memory present , due to limiting factors . We should never go above this limit .
* It is the size of our identity mapping .
*
* Consider the following factors :
* 1. max_physmem_end - end of physical memory online or standby .
* Always < = end of the last online memory block ( get_mem_detect_end ( ) ) .
* 2. CONFIG_MAX_PHYSMEM_BITS - the maximum size of physical memory the
* kernel is able to support .
* 3. " mem= " kernel command line option which limits physical memory usage .
* 4. OLDMEM_BASE which is a kdump memory limit when the kernel is executed as
* crash kernel .
* 5. " hsa " size which is a memory limit when the kernel is executed during
* zfcp / nvme dump .
*/
static void setup_ident_map_size ( unsigned long max_physmem_end )
{
unsigned long hsa_size ;
ident_map_size = max_physmem_end ;
if ( memory_limit )
ident_map_size = min ( ident_map_size , memory_limit ) ;
ident_map_size = min ( ident_map_size , 1UL < < MAX_PHYSMEM_BITS ) ;
# ifdef CONFIG_CRASH_DUMP
2021-06-15 14:25:41 +02:00
if ( oldmem_data . start ) {
2020-10-19 11:01:33 +02:00
kaslr_enabled = 0 ;
2021-06-15 14:25:41 +02:00
ident_map_size = min ( ident_map_size , oldmem_data . size ) ;
2020-10-19 11:01:33 +02:00
} else if ( ipl_block_valid & & is_ipl_block_dump ( ) ) {
kaslr_enabled = 0 ;
if ( ! sclp_early_get_hsa_size ( & hsa_size ) & & hsa_size )
ident_map_size = min ( ident_map_size , hsa_size ) ;
}
# endif
}
2022-12-13 11:35:11 +01:00
static unsigned long setup_kernel_memory_layout ( void )
2020-10-06 22:12:39 +02:00
{
2021-10-14 13:53:54 +02:00
unsigned long vmemmap_start ;
2022-12-13 11:35:11 +01:00
unsigned long asce_limit ;
2020-10-06 22:12:39 +02:00
unsigned long rte_size ;
unsigned long pages ;
2022-05-26 07:57:36 +02:00
unsigned long vmax ;
2020-10-06 22:12:39 +02:00
pages = ident_map_size / PAGE_SIZE ;
/* vmemmap contains a multiple of PAGES_PER_SECTION struct pages */
vmemmap_size = SECTION_ALIGN_UP ( pages ) * sizeof ( struct page ) ;
/* choose kernel address space layout: 4 or 3 levels. */
2021-10-14 13:53:54 +02:00
vmemmap_start = round_up ( ident_map_size , _REGION3_SIZE ) ;
2020-10-06 22:12:39 +02:00
if ( IS_ENABLED ( CONFIG_KASAN ) | |
vmalloc_size > _REGION2_SIZE | |
2021-10-14 13:53:54 +02:00
vmemmap_start + vmemmap_size + vmalloc_size + MODULES_LEN >
_REGION2_SIZE ) {
2022-12-13 11:35:11 +01:00
asce_limit = _REGION1_SIZE ;
2021-10-14 13:53:54 +02:00
rte_size = _REGION2_SIZE ;
2020-10-06 22:12:39 +02:00
} else {
2022-12-13 11:35:11 +01:00
asce_limit = _REGION2_SIZE ;
2021-10-14 13:53:54 +02:00
rte_size = _REGION3_SIZE ;
2020-10-06 22:12:39 +02:00
}
2021-10-14 13:53:54 +02:00
/*
* forcing modules and vmalloc area under the ultravisor
* secure storage limit , so that any vmalloc allocation
* we do could be used to back secure guest storage .
*/
2022-12-13 11:35:11 +01:00
vmax = adjust_to_uv_max ( asce_limit ) ;
2021-10-14 13:53:54 +02:00
# ifdef CONFIG_KASAN
/* force vmalloc and modules below kasan shadow */
2022-05-26 07:57:36 +02:00
vmax = min ( vmax , KASAN_SHADOW_START ) ;
2020-10-06 22:12:39 +02:00
# endif
2022-07-24 15:02:16 +02:00
__memcpy_real_area = round_down ( vmax - PAGE_SIZE , PAGE_SIZE ) ;
__abs_lowcore = round_down ( __memcpy_real_area - ABS_LOWCORE_MAP_SIZE ,
sizeof ( struct lowcore ) ) ;
2022-07-20 08:22:01 +02:00
MODULES_END = round_down ( __abs_lowcore , _SEGMENT_SIZE ) ;
2020-10-06 22:12:39 +02:00
MODULES_VADDR = MODULES_END - MODULES_LEN ;
VMALLOC_END = MODULES_VADDR ;
2021-10-14 13:53:54 +02:00
/* allow vmalloc area to occupy up to about 1/2 of the rest virtual space left */
vmalloc_size = min ( vmalloc_size , round_down ( VMALLOC_END / 2 , _REGION3_SIZE ) ) ;
VMALLOC_START = VMALLOC_END - vmalloc_size ;
2020-10-06 22:12:39 +02:00
2021-10-14 13:53:54 +02:00
/* split remaining virtual space between 1:1 mapping & vmemmap array */
pages = VMALLOC_START / ( PAGE_SIZE + sizeof ( struct page ) ) ;
2020-10-06 22:12:39 +02:00
pages = SECTION_ALIGN_UP ( pages ) ;
2021-10-14 13:53:54 +02:00
/* keep vmemmap_start aligned to a top level region table entry */
vmemmap_start = round_down ( VMALLOC_START - pages * sizeof ( struct page ) , rte_size ) ;
/* vmemmap_start is the future VMEM_MAX_PHYS, make sure it is within MAX_PHYSMEM */
vmemmap_start = min ( vmemmap_start , 1UL < < MAX_PHYSMEM_BITS ) ;
/* make sure identity map doesn't overlay with vmemmap */
ident_map_size = min ( ident_map_size , vmemmap_start ) ;
2020-10-06 22:12:39 +02:00
vmemmap_size = SECTION_ALIGN_UP ( ident_map_size / PAGE_SIZE ) * sizeof ( struct page ) ;
2021-10-14 13:53:54 +02:00
/* make sure vmemmap doesn't overlay with vmalloc area */
VMALLOC_START = max ( vmemmap_start + vmemmap_size , VMALLOC_START ) ;
vmemmap = ( struct page * ) vmemmap_start ;
2022-12-13 11:35:11 +01:00
return asce_limit ;
2020-10-06 22:12:39 +02:00
}
2020-09-02 16:52:06 +02:00
/*
* This function clears the BSS section of the decompressed Linux kernel and NOT the decompressor ' s .
*/
2019-08-11 20:55:18 +02:00
static void clear_bss_section ( void )
{
memset ( ( void * ) vmlinux . default_lma + vmlinux . image_size , 0 , vmlinux . bss_size ) ;
}
2020-09-18 12:25:37 +02:00
/*
* Set vmalloc area size to an 8 th of ( potential ) physical memory
* size , unless size has been set by kernel command line parameter .
*/
static void setup_vmalloc_size ( void )
{
unsigned long size ;
if ( vmalloc_size_set )
return ;
2020-10-19 11:01:33 +02:00
size = round_up ( ident_map_size / 8 , _SEGMENT_SIZE ) ;
2020-09-18 12:25:37 +02:00
vmalloc_size = max ( size , vmalloc_size ) ;
}
2021-08-06 12:55:09 +02:00
static void offset_vmlinux_info ( unsigned long offset )
{
vmlinux . default_lma + = offset ;
* ( unsigned long * ) ( & vmlinux . entry ) + = offset ;
vmlinux . bootdata_off + = offset ;
vmlinux . bootdata_preserved_off + = offset ;
vmlinux . rela_dyn_start + = offset ;
vmlinux . rela_dyn_end + = offset ;
vmlinux . dynsym_start + = offset ;
2022-12-13 11:35:11 +01:00
vmlinux . init_mm_off + = offset ;
vmlinux . swapper_pg_dir_off + = offset ;
vmlinux . invalid_pg_dir_off + = offset ;
2021-08-06 12:55:09 +02:00
}
2021-09-27 14:18:26 +02:00
static unsigned long reserve_amode31 ( unsigned long safe_addr )
{
__amode31_base = PAGE_ALIGN ( safe_addr ) ;
2023-02-02 19:22:35 +01:00
return __amode31_base + vmlinux . amode31_size ;
2021-09-27 14:18:26 +02:00
}
2018-07-19 13:11:28 +02:00
void startup_kernel ( void )
{
2023-01-23 12:49:47 +01:00
unsigned long max_physmem_end ;
2019-02-03 21:37:20 +01:00
unsigned long random_lma ;
2019-02-21 14:23:04 +01:00
unsigned long safe_addr ;
2022-12-13 11:35:11 +01:00
unsigned long asce_limit ;
2018-07-19 16:51:25 +02:00
void * img ;
2022-12-13 11:35:11 +01:00
psw_t psw ;
2018-07-19 13:11:28 +02:00
2021-06-15 14:15:07 +02:00
initrd_data . start = parmarea . initrd_start ;
initrd_data . size = parmarea . initrd_size ;
2021-06-15 14:25:41 +02:00
oldmem_data . start = parmarea . oldmem_base ;
oldmem_data . size = parmarea . oldmem_size ;
2021-06-15 14:15:07 +02:00
2020-10-09 17:14:02 +02:00
setup_lpp ( ) ;
2019-02-21 14:23:04 +01:00
store_ipl_parmblock ( ) ;
safe_addr = mem_safe_offset ( ) ;
2021-09-27 14:18:26 +02:00
safe_addr = reserve_amode31 ( safe_addr ) ;
2019-02-21 14:23:04 +01:00
safe_addr = read_ipl_report ( safe_addr ) ;
2019-04-01 19:11:03 +02:00
uv_query_info ( ) ;
2023-01-23 12:49:47 +01:00
safe_addr = rescue_initrd ( safe_addr ) ;
2018-05-23 11:07:13 +02:00
sclp_early_read_info ( ) ;
2018-05-15 13:28:53 +02:00
setup_boot_command_line ( ) ;
2019-02-27 16:52:42 +01:00
parse_boot_command_line ( ) ;
2023-02-02 19:21:38 +01:00
detect_facilities ( ) ;
2021-07-05 19:37:25 +02:00
sanitize_prot_virt_host ( ) ;
2023-01-23 12:49:47 +01:00
max_physmem_end = detect_memory ( & safe_addr ) ;
setup_ident_map_size ( max_physmem_end ) ;
2020-09-18 12:25:37 +02:00
setup_vmalloc_size ( ) ;
2022-12-13 11:35:11 +01:00
asce_limit = setup_kernel_memory_layout ( ) ;
2023-02-10 15:47:06 +01:00
mem_detect_set_usable_limit ( ident_map_size ) ;
2019-02-03 21:37:20 +01:00
if ( IS_ENABLED ( CONFIG_RANDOMIZE_BASE ) & & kaslr_enabled ) {
random_lma = get_random_base ( safe_addr ) ;
if ( random_lma ) {
__kaslr_offset = random_lma - vmlinux . default_lma ;
img = ( void * ) vmlinux . default_lma ;
2021-08-06 12:55:09 +02:00
offset_vmlinux_info ( __kaslr_offset ) ;
2019-02-03 21:37:20 +01:00
}
}
2018-07-19 13:11:28 +02:00
if ( ! IS_ENABLED ( CONFIG_KERNEL_UNCOMPRESSED ) ) {
2018-07-19 16:51:25 +02:00
img = decompress_kernel ( ) ;
memmove ( ( void * ) vmlinux . default_lma , img , vmlinux . image_size ) ;
2019-02-03 21:37:20 +01:00
} else if ( __kaslr_offset )
memcpy ( ( void * ) vmlinux . default_lma , img , vmlinux . image_size ) ;
2022-12-13 11:35:11 +01:00
/*
* The order of the following operations is important :
*
* - handle_relocs ( ) must follow clear_bss_section ( ) to establish static
* memory references to data in . bss to be used by setup_vmem ( )
* ( i . e init_mm . pgd )
*
* - setup_vmem ( ) must follow handle_relocs ( ) to be able using
* static memory references to data in . bss ( i . e init_mm . pgd )
*
* - copy_bootdata ( ) must follow setup_vmem ( ) to propagate changes to
* bootdata made by setup_vmem ( )
*/
2019-08-11 20:55:18 +02:00
clear_bss_section ( ) ;
2022-10-30 19:22:02 +01:00
handle_relocs ( __kaslr_offset ) ;
2023-01-28 23:55:04 +01:00
setup_vmem ( asce_limit ) ;
2022-12-13 11:35:11 +01:00
copy_bootdata ( ) ;
2019-02-03 21:37:20 +01:00
if ( __kaslr_offset ) {
s390/kaslr: store KASLR offset for early dumps
The KASLR offset is added to vmcoreinfo in arch_crash_save_vmcoreinfo(),
so that it can be found by crash when processing kernel dumps.
However, arch_crash_save_vmcoreinfo() is called during a subsys_initcall,
so if the kernel crashes before that, we have no vmcoreinfo and no KASLR
offset.
Fix this by storing the KASLR offset in the lowcore, where the vmcore_info
pointer will be stored, and where it can be found by crash. In order to
make it distinguishable from a real vmcore_info pointer, mark it as uneven
(KASLR offset itself is aligned to THREAD_SIZE).
When arch_crash_save_vmcoreinfo() stores the real vmcore_info pointer in
the lowcore, it overwrites the KASLR offset. At that point, the KASLR
offset is not yet added to vmcoreinfo, so we also need to move the
mem_assign_absolute() behind the vmcoreinfo_append_str().
Fixes: b2d24b97b2a9 ("s390/kernel: add support for kernel address space layout randomization (KASLR)")
Cc: <stable@vger.kernel.org> # v5.2+
Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
2019-11-19 12:30:53 +01:00
/*
* Save KASLR offset for early dumps , before vmcore_info is set .
* Mark as uneven to distinguish from real vmcore_info pointer .
*/
S390_lowcore . vmcore_info = __kaslr_offset | 0x1UL ;
2019-02-03 21:37:20 +01:00
/* Clear non-relocated kernel */
if ( IS_ENABLED ( CONFIG_KERNEL_UNCOMPRESSED ) )
memset ( img , 0 , vmlinux . image_size ) ;
}
2022-12-13 11:35:11 +01:00
/*
* Jump to the decompressed kernel entry point and switch DAT mode on .
*/
psw . addr = vmlinux . entry ;
psw . mask = PSW_KERNEL_BITS ;
__load_psw ( psw ) ;
2018-07-19 13:11:28 +02:00
}