s390/cmma: move parsing of cmma kernel parameter to early boot code
The "cmma=" kernel command line parameter needs to be parsed early for upcoming changes. Therefore move the parsing code. Note that EX_TABLE handling of cmma_test_essa() needs to be open-coded, since the early boot code doesn't have infrastructure for handling expected exceptions. Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
92b519f3bc
commit
468a3bc2b7
7 changed files with 58 additions and 42 deletions
|
@ -3,6 +3,7 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/pgtable.h>
|
#include <linux/pgtable.h>
|
||||||
|
#include <asm/page-states.h>
|
||||||
#include <asm/ebcdic.h>
|
#include <asm/ebcdic.h>
|
||||||
#include <asm/sclp.h>
|
#include <asm/sclp.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
|
@ -24,6 +25,7 @@ unsigned int __bootdata_preserved(zlib_dfltcc_support) = ZLIB_DFLTCC_FULL;
|
||||||
struct ipl_parameter_block __bootdata_preserved(ipl_block);
|
struct ipl_parameter_block __bootdata_preserved(ipl_block);
|
||||||
int __bootdata_preserved(ipl_block_valid);
|
int __bootdata_preserved(ipl_block_valid);
|
||||||
int __bootdata_preserved(__kaslr_enabled);
|
int __bootdata_preserved(__kaslr_enabled);
|
||||||
|
int __bootdata_preserved(cmma_flag) = 1;
|
||||||
|
|
||||||
unsigned long vmalloc_size = VMALLOC_DEFAULT_SIZE;
|
unsigned long vmalloc_size = VMALLOC_DEFAULT_SIZE;
|
||||||
unsigned long memory_limit;
|
unsigned long memory_limit;
|
||||||
|
@ -295,6 +297,12 @@ void parse_boot_command_line(void)
|
||||||
if (!strcmp(param, "nokaslr"))
|
if (!strcmp(param, "nokaslr"))
|
||||||
__kaslr_enabled = 0;
|
__kaslr_enabled = 0;
|
||||||
|
|
||||||
|
if (!strcmp(param, "cmma")) {
|
||||||
|
rc = kstrtobool(val, &enabled);
|
||||||
|
if (!rc && !enabled)
|
||||||
|
cmma_flag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_KVM)
|
#if IS_ENABLED(CONFIG_KVM)
|
||||||
if (!strcmp(param, "prot_virt")) {
|
if (!strcmp(param, "prot_virt")) {
|
||||||
rc = kstrtobool(val, &enabled);
|
rc = kstrtobool(val, &enabled);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/elf.h>
|
#include <linux/elf.h>
|
||||||
|
#include <asm/page-states.h>
|
||||||
#include <asm/boot_data.h>
|
#include <asm/boot_data.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
#include <asm/maccess.h>
|
#include <asm/maccess.h>
|
||||||
|
@ -57,6 +58,48 @@ static void detect_facilities(void)
|
||||||
machine.has_nx = 1;
|
machine.has_nx = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cmma_test_essa(void)
|
||||||
|
{
|
||||||
|
unsigned long reg1, reg2, tmp = 0;
|
||||||
|
int rc = 1;
|
||||||
|
psw_t old;
|
||||||
|
|
||||||
|
/* Test ESSA_GET_STATE */
|
||||||
|
asm volatile(
|
||||||
|
" mvc 0(16,%[psw_old]),0(%[psw_pgm])\n"
|
||||||
|
" epsw %[reg1],%[reg2]\n"
|
||||||
|
" st %[reg1],0(%[psw_pgm])\n"
|
||||||
|
" st %[reg2],4(%[psw_pgm])\n"
|
||||||
|
" larl %[reg1],1f\n"
|
||||||
|
" stg %[reg1],8(%[psw_pgm])\n"
|
||||||
|
" .insn rrf,0xb9ab0000,%[tmp],%[tmp],%[cmd],0\n"
|
||||||
|
" la %[rc],0\n"
|
||||||
|
"1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n"
|
||||||
|
: [reg1] "=&d" (reg1),
|
||||||
|
[reg2] "=&a" (reg2),
|
||||||
|
[rc] "+&d" (rc),
|
||||||
|
[tmp] "=&d" (tmp),
|
||||||
|
"+Q" (S390_lowcore.program_new_psw),
|
||||||
|
"=Q" (old)
|
||||||
|
: [psw_old] "a" (&old),
|
||||||
|
[psw_pgm] "a" (&S390_lowcore.program_new_psw),
|
||||||
|
[cmd] "i" (ESSA_GET_STATE)
|
||||||
|
: "cc", "memory");
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmma_init(void)
|
||||||
|
{
|
||||||
|
if (!cmma_flag)
|
||||||
|
return;
|
||||||
|
if (cmma_test_essa()) {
|
||||||
|
cmma_flag = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (test_facility(147))
|
||||||
|
cmma_flag = 2;
|
||||||
|
}
|
||||||
|
|
||||||
static void setup_lpp(void)
|
static void setup_lpp(void)
|
||||||
{
|
{
|
||||||
S390_lowcore.current_pid = 0;
|
S390_lowcore.current_pid = 0;
|
||||||
|
@ -306,6 +349,7 @@ void startup_kernel(void)
|
||||||
setup_boot_command_line();
|
setup_boot_command_line();
|
||||||
parse_boot_command_line();
|
parse_boot_command_line();
|
||||||
detect_facilities();
|
detect_facilities();
|
||||||
|
cmma_init();
|
||||||
sanitize_prot_virt_host();
|
sanitize_prot_virt_host();
|
||||||
max_physmem_end = detect_max_physmem_end();
|
max_physmem_end = detect_max_physmem_end();
|
||||||
setup_ident_map_size(max_physmem_end);
|
setup_ident_map_size(max_physmem_end);
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#ifndef PAGE_STATES_H
|
#ifndef PAGE_STATES_H
|
||||||
#define PAGE_STATES_H
|
#define PAGE_STATES_H
|
||||||
|
|
||||||
|
#include <asm/sections.h>
|
||||||
|
|
||||||
#define ESSA_GET_STATE 0
|
#define ESSA_GET_STATE 0
|
||||||
#define ESSA_SET_STABLE 1
|
#define ESSA_SET_STABLE 1
|
||||||
#define ESSA_SET_UNUSED 2
|
#define ESSA_SET_UNUSED 2
|
||||||
|
@ -18,4 +20,6 @@
|
||||||
|
|
||||||
#define ESSA_MAX ESSA_SET_STABLE_NODAT
|
#define ESSA_MAX ESSA_SET_STABLE_NODAT
|
||||||
|
|
||||||
|
extern int __bootdata_preserved(cmma_flag);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -125,7 +125,6 @@ static inline void vmcp_cma_reserve(void) { }
|
||||||
|
|
||||||
void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault);
|
void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault);
|
||||||
|
|
||||||
void cmma_init(void);
|
|
||||||
void cmma_init_nodat(void);
|
void cmma_init_nodat(void);
|
||||||
|
|
||||||
extern void (*_machine_restart)(char *command);
|
extern void (*_machine_restart)(char *command);
|
||||||
|
|
|
@ -46,6 +46,7 @@ decompressor_handled_param(vmalloc);
|
||||||
decompressor_handled_param(dfltcc);
|
decompressor_handled_param(dfltcc);
|
||||||
decompressor_handled_param(facilities);
|
decompressor_handled_param(facilities);
|
||||||
decompressor_handled_param(nokaslr);
|
decompressor_handled_param(nokaslr);
|
||||||
|
decompressor_handled_param(cmma);
|
||||||
#if IS_ENABLED(CONFIG_KVM)
|
#if IS_ENABLED(CONFIG_KVM)
|
||||||
decompressor_handled_param(prot_virt);
|
decompressor_handled_param(prot_virt);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -164,8 +164,6 @@ void __init mem_init(void)
|
||||||
|
|
||||||
pv_init();
|
pv_init();
|
||||||
kfence_split_mapping();
|
kfence_split_mapping();
|
||||||
/* Setup guest page hinting */
|
|
||||||
cmma_init();
|
|
||||||
|
|
||||||
/* this will put all low memory onto the freelists */
|
/* this will put all low memory onto the freelists */
|
||||||
memblock_free_all();
|
memblock_free_all();
|
||||||
|
|
|
@ -18,45 +18,7 @@
|
||||||
#include <asm/facility.h>
|
#include <asm/facility.h>
|
||||||
#include <asm/page-states.h>
|
#include <asm/page-states.h>
|
||||||
|
|
||||||
static int cmma_flag = 1;
|
int __bootdata_preserved(cmma_flag);
|
||||||
|
|
||||||
static int __init cmma(char *str)
|
|
||||||
{
|
|
||||||
bool enabled;
|
|
||||||
|
|
||||||
if (!kstrtobool(str, &enabled))
|
|
||||||
cmma_flag = enabled;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
__setup("cmma=", cmma);
|
|
||||||
|
|
||||||
static inline int cmma_test_essa(void)
|
|
||||||
{
|
|
||||||
unsigned long tmp = 0;
|
|
||||||
int rc = -EOPNOTSUPP;
|
|
||||||
|
|
||||||
/* test ESSA_GET_STATE */
|
|
||||||
asm volatile(
|
|
||||||
" .insn rrf,0xb9ab0000,%[tmp],%[tmp],%[cmd],0\n"
|
|
||||||
"0: la %[rc],0\n"
|
|
||||||
"1:\n"
|
|
||||||
EX_TABLE(0b, 1b)
|
|
||||||
: [rc] "+&d" (rc), [tmp] "+&d" (tmp)
|
|
||||||
: [cmd] "i" (ESSA_GET_STATE));
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __init cmma_init(void)
|
|
||||||
{
|
|
||||||
if (!cmma_flag)
|
|
||||||
return;
|
|
||||||
if (cmma_test_essa()) {
|
|
||||||
cmma_flag = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (test_facility(147))
|
|
||||||
cmma_flag = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static __always_inline void essa(unsigned long paddr, unsigned char cmd)
|
static __always_inline void essa(unsigned long paddr, unsigned char cmd)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue