Commit a0443fbb authored by Hendrik Brueckner's avatar Hendrik Brueckner Committed by Heiko Carstens

[S390] Extra Kernel Parameters via VMPARM

Now it is possible to specify additional kernel parameters on the IPL
command line using the IPL PARM option.
If the Linux system is already running, the new reipl sysfs attribute
'parm' can be used to change kernel parameters for the next reboot.
Examples:
  IPL    C PARM dasd=1234 root=/dev/dasda1
  IPL 1234 PARM savesys=mylnxnss
  echo "init=/bin/bash" > /sys/firmware/reipl/ccw/parm
Signed-off-by: default avatarHendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
parent fe137230
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/pfn.h> #include <linux/pfn.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm/ebcdic.h>
#include <asm/ipl.h> #include <asm/ipl.h>
#include <asm/lowcore.h> #include <asm/lowcore.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -26,12 +27,40 @@ ...@@ -26,12 +27,40 @@
/* /*
* Create a Kernel NSS if the SAVESYS= parameter is defined * Create a Kernel NSS if the SAVESYS= parameter is defined
*/ */
#define DEFSYS_CMD_SIZE 96 #define DEFSYS_CMD_SIZE 128
#define SAVESYS_CMD_SIZE 32 #define SAVESYS_CMD_SIZE 32
char kernel_nss_name[NSS_NAME_SIZE + 1]; char kernel_nss_name[NSS_NAME_SIZE + 1];
static void __init setup_boot_command_line(void);
#ifdef CONFIG_SHARED_KERNEL #ifdef CONFIG_SHARED_KERNEL
int __init savesys_ipl_nss(char *cmd, const int cmdlen);
asm(
" .section .init.text,\"ax\",@progbits\n"
" .align 4\n"
" .type savesys_ipl_nss, @function\n"
"savesys_ipl_nss:\n"
#ifdef CONFIG_64BIT
" stmg 6,15,48(15)\n"
" lgr 14,3\n"
" sam31\n"
" diag 2,14,0x8\n"
" sam64\n"
" lgr 2,14\n"
" lmg 6,15,48(15)\n"
#else
" stm 6,15,24(15)\n"
" lr 14,3\n"
" diag 2,14,0x8\n"
" lr 2,14\n"
" lm 6,15,24(15)\n"
#endif
" br 14\n"
" .size savesys_ipl_nss, .-savesys_ipl_nss\n");
static noinline __init void create_kernel_nss(void) static noinline __init void create_kernel_nss(void)
{ {
unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size; unsigned int i, stext_pfn, eshared_pfn, end_pfn, min_size;
...@@ -39,6 +68,7 @@ static noinline __init void create_kernel_nss(void) ...@@ -39,6 +68,7 @@ static noinline __init void create_kernel_nss(void)
unsigned int sinitrd_pfn, einitrd_pfn; unsigned int sinitrd_pfn, einitrd_pfn;
#endif #endif
int response; int response;
size_t len;
char *savesys_ptr; char *savesys_ptr;
char upper_command_line[COMMAND_LINE_SIZE]; char upper_command_line[COMMAND_LINE_SIZE];
char defsys_cmd[DEFSYS_CMD_SIZE]; char defsys_cmd[DEFSYS_CMD_SIZE];
...@@ -49,8 +79,8 @@ static noinline __init void create_kernel_nss(void) ...@@ -49,8 +79,8 @@ static noinline __init void create_kernel_nss(void)
return; return;
/* Convert COMMAND_LINE to upper case */ /* Convert COMMAND_LINE to upper case */
for (i = 0; i < strlen(COMMAND_LINE); i++) for (i = 0; i < strlen(boot_command_line); i++)
upper_command_line[i] = toupper(COMMAND_LINE[i]); upper_command_line[i] = toupper(boot_command_line[i]);
savesys_ptr = strstr(upper_command_line, "SAVESYS="); savesys_ptr = strstr(upper_command_line, "SAVESYS=");
...@@ -83,7 +113,8 @@ static noinline __init void create_kernel_nss(void) ...@@ -83,7 +113,8 @@ static noinline __init void create_kernel_nss(void)
} }
#endif #endif
sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK", defsys_cmd, min_size); sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK PARMREGS=0-13",
defsys_cmd, min_size);
sprintf(savesys_cmd, "SAVESYS %s \n IPL %s", sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
kernel_nss_name, kernel_nss_name); kernel_nss_name, kernel_nss_name);
...@@ -94,13 +125,24 @@ static noinline __init void create_kernel_nss(void) ...@@ -94,13 +125,24 @@ static noinline __init void create_kernel_nss(void)
return; return;
} }
__cpcmd(savesys_cmd, NULL, 0, &response); len = strlen(savesys_cmd);
ASCEBC(savesys_cmd, len);
response = savesys_ipl_nss(savesys_cmd, len);
if (response != strlen(savesys_cmd)) { /* On success: response is equal to the command size,
* max SAVESYS_CMD_SIZE
* On error: response contains the numeric portion of cp error message.
* for SAVESYS it will be >= 263
*/
if (response > SAVESYS_CMD_SIZE) {
kernel_nss_name[0] = '\0'; kernel_nss_name[0] = '\0';
return; return;
} }
/* re-setup boot command line with new ipl vm parms */
ipl_update_parameters();
setup_boot_command_line();
ipl_flags = IPL_NSS_VALID; ipl_flags = IPL_NSS_VALID;
} }
...@@ -397,6 +439,26 @@ static __init void rescue_initrd(void) ...@@ -397,6 +439,26 @@ static __init void rescue_initrd(void)
#endif #endif
} }
/* Set up boot command line */
static void __init setup_boot_command_line(void)
{
char *parm = NULL;
/* copy arch command line */
strlcpy(boot_command_line, COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
boot_command_line[ARCH_COMMAND_LINE_SIZE - 1] = 0;
/* append IPL PARM data to the boot command line */
if (MACHINE_IS_VM) {
parm = boot_command_line + strlen(boot_command_line);
*parm++ = ' ';
get_ipl_vmparm(parm);
if (parm[0] == '=')
memmove(boot_command_line, parm + 1, strlen(parm));
}
}
/* /*
* Save ipl parameters, clear bss memory, initialize storage keys * Save ipl parameters, clear bss memory, initialize storage keys
* and create a kernel NSS at startup if the SAVESYS= parm is defined * and create a kernel NSS at startup if the SAVESYS= parm is defined
...@@ -411,10 +473,12 @@ void __init startup_init(void) ...@@ -411,10 +473,12 @@ void __init startup_init(void)
init_kernel_storage_key(); init_kernel_storage_key();
lockdep_init(); lockdep_init();
lockdep_off(); lockdep_off();
detect_machine_type();
create_kernel_nss();
sort_main_extable(); sort_main_extable();
setup_lowcore_early(); setup_lowcore_early();
detect_machine_type();
ipl_update_parameters();
setup_boot_command_line();
create_kernel_nss();
detect_mvpg(); detect_mvpg();
detect_ieee(); detect_ieee();
detect_csp(); detect_csp();
......
This diff is collapsed.
...@@ -221,18 +221,17 @@ static void __init conmode_default(void) ...@@ -221,18 +221,17 @@ static void __init conmode_default(void)
#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE) #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
static void __init setup_zfcpdump(unsigned int console_devno) static void __init setup_zfcpdump(unsigned int console_devno)
{ {
static char str[64]; static char str[41];
if (ipl_info.type != IPL_TYPE_FCP_DUMP) if (ipl_info.type != IPL_TYPE_FCP_DUMP)
return; return;
if (console_devno != -1) if (console_devno != -1)
sprintf(str, "cio_ignore=all,!0.0.%04x,!0.0.%04x", sprintf(str, " cio_ignore=all,!0.0.%04x,!0.0.%04x",
ipl_info.data.fcp.dev_id.devno, console_devno); ipl_info.data.fcp.dev_id.devno, console_devno);
else else
sprintf(str, "cio_ignore=all,!0.0.%04x", sprintf(str, " cio_ignore=all,!0.0.%04x",
ipl_info.data.fcp.dev_id.devno); ipl_info.data.fcp.dev_id.devno);
strcat(COMMAND_LINE, " "); strcat(boot_command_line, str);
strcat(COMMAND_LINE, str);
console_loglevel = 2; console_loglevel = 2;
} }
#else #else
...@@ -778,11 +777,9 @@ setup_arch(char **cmdline_p) ...@@ -778,11 +777,9 @@ setup_arch(char **cmdline_p)
printk("We are running native (64 bit mode)\n"); printk("We are running native (64 bit mode)\n");
#endif /* CONFIG_64BIT */ #endif /* CONFIG_64BIT */
/* Save unparsed command line copy for /proc/cmdline */ /* Have one command line that is parsed and saved in /proc/cmdline */
strlcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); /* boot_command_line has been already set up in early.c */
*cmdline_p = boot_command_line;
*cmdline_p = COMMAND_LINE;
*(*cmdline_p + COMMAND_LINE_SIZE - 1) = '\0';
ROOT_DEV = Root_RAM0; ROOT_DEV = Root_RAM0;
......
...@@ -56,15 +56,19 @@ struct ipl_block_fcp { ...@@ -56,15 +56,19 @@ struct ipl_block_fcp {
u8 scp_data[]; u8 scp_data[];
} __attribute__((packed)); } __attribute__((packed));
#define DIAG308_VMPARM_SIZE 64
struct ipl_block_ccw { struct ipl_block_ccw {
u8 load_param[8]; u8 load_parm[8];
u8 reserved1[84]; u8 reserved1[84];
u8 reserved2[2]; u8 reserved2[2];
u16 devno; u16 devno;
u8 vm_flags; u8 vm_flags;
u8 reserved3[3]; u8 reserved3[3];
u32 vm_parm_len; u32 vm_parm_len;
u8 reserved4[80]; u8 nss_name[8];
u8 vm_parm[DIAG308_VMPARM_SIZE];
u8 reserved4[8];
} __attribute__((packed)); } __attribute__((packed));
struct ipl_parameter_block { struct ipl_parameter_block {
...@@ -73,7 +77,7 @@ struct ipl_parameter_block { ...@@ -73,7 +77,7 @@ struct ipl_parameter_block {
struct ipl_block_fcp fcp; struct ipl_block_fcp fcp;
struct ipl_block_ccw ccw; struct ipl_block_ccw ccw;
} ipl_info; } ipl_info;
} __attribute__((packed)); } __attribute__((packed,aligned(4096)));
/* /*
* IPL validity flags * IPL validity flags
...@@ -86,6 +90,8 @@ extern void do_reipl(void); ...@@ -86,6 +90,8 @@ extern void do_reipl(void);
extern void do_halt(void); extern void do_halt(void);
extern void do_poff(void); extern void do_poff(void);
extern void ipl_save_parameters(void); extern void ipl_save_parameters(void);
extern void ipl_update_parameters(void);
extern void get_ipl_vmparm(char *);
enum { enum {
IPL_DEVNO_VALID = 1, IPL_DEVNO_VALID = 1,
...@@ -147,6 +153,11 @@ enum diag308_flags { ...@@ -147,6 +153,11 @@ enum diag308_flags {
DIAG308_FLAGS_LP_VALID = 0x80, DIAG308_FLAGS_LP_VALID = 0x80,
}; };
enum diag308_vm_flags {
DIAG308_VM_FLAGS_NSS_VALID = 0x80,
DIAG308_VM_FLAGS_VP_VALID = 0x40,
};
enum diag308_rc { enum diag308_rc {
DIAG308_RC_OK = 1, DIAG308_RC_OK = 1,
}; };
......
...@@ -8,7 +8,9 @@ ...@@ -8,7 +8,9 @@
#ifndef _ASM_S390_SETUP_H #ifndef _ASM_S390_SETUP_H
#define _ASM_S390_SETUP_H #define _ASM_S390_SETUP_H
#define COMMAND_LINE_SIZE 896 #define COMMAND_LINE_SIZE 1024
#define ARCH_COMMAND_LINE_SIZE 896
#ifdef __KERNEL__ #ifdef __KERNEL__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment