forked from luck/tmp_suning_uos_patched
d590284419
- Add support for IBM z15 machines. - Add SHA3 and CCA AES cipher key support in zcrypt and pkey refactoring. - Move to arch_stack_walk infrastructure for the stack unwinder. - Various kasan fixes and improvements. - Various command line parsing fixes. - Improve decompressor phase debuggability. - Lift no bss usage restriction for the early code. - Use refcount_t for reference counters for couple of places in mm code. - Logging improvements and return code fix in vfio-ccw code. - Couple of zpci fixes and minor refactoring. - Remove some outdated documentation. - Fix secure boot detection. - Other various minor code clean ups. -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEE3QHqV+H2a8xAv27vjYWKoQLXFBgFAl1/pRoACgkQjYWKoQLX FBjxLQf/Y1nlmoc8URLqaqfNTczIvUzdfXuahI7L75RoIIiqHtcHBrVwauSr7Lma XVRzK/+6q0UPISrOIZEEtQKsMMM7rGuUv/+XTyrOB/Tsc31kN2EIRXltfXI/lkb8 BZdgch4Xs2rOD7y6TvqpYJsXYXsnLMWwCk8V+48V/pok4sEgMDgh0bTQRHPHYmZ6 1cv8ZQ0AeuVxC6ChM30LhajGRPkYd8RQ82K7fU7jxT0Tjzu66SyrW3pTwA5empBD RI2yBZJ8EXwJyTCpvN8NKiBgihDs9oUZl61Dyq3j64Mb1OuNUhxXA/8jmtnGn0ok O9vtImCWzExhjSMkvotuhHEC05nEEQ== =LCgE -----END PGP SIGNATURE----- Merge tag 's390-5.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux Pull s390 updates from Vasily Gorbik: - Add support for IBM z15 machines. - Add SHA3 and CCA AES cipher key support in zcrypt and pkey refactoring. - Move to arch_stack_walk infrastructure for the stack unwinder. - Various kasan fixes and improvements. - Various command line parsing fixes. - Improve decompressor phase debuggability. - Lift no bss usage restriction for the early code. - Use refcount_t for reference counters for couple of places in mm code. - Logging improvements and return code fix in vfio-ccw code. - Couple of zpci fixes and minor refactoring. - Remove some outdated documentation. - Fix secure boot detection. - Other various minor code clean ups. * tag 's390-5.4-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (48 commits) s390: remove pointless drivers-y in drivers/s390/Makefile s390/cpum_sf: Fix line length and format string s390/pci: fix MSI message data s390: add support for IBM z15 machines s390/crypto: Support for SHA3 via CPACF (MSA6) s390/startup: add pgm check info printing s390/crypto: xts-aes-s390 fix extra run-time crypto self tests finding vfio-ccw: fix error return code in vfio_ccw_sch_init() s390: vfio-ap: fix warning reset not completed s390/base: remove unused s390_base_mcck_handler s390/sclp: Fix bit checked for has_sipl s390/zcrypt: fix wrong handling of cca cipher keygenflags s390/kasan: add kdump support s390/setup: avoid using strncmp with hardcoded length s390/sclp: avoid using strncmp with hardcoded length s390/module: avoid using strncmp with hardcoded length s390/pci: avoid using strncmp with hardcoded length s390/kaslr: reserve memory for kasan usage s390/mem_detect: provide single get_mem_detect_end s390/cmma: reuse kstrtobool for option value parsing ...
260 lines
5.7 KiB
C
260 lines
5.7 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/ctype.h>
|
|
#include <asm/ebcdic.h>
|
|
#include <asm/sclp.h>
|
|
#include <asm/sections.h>
|
|
#include <asm/boot_data.h>
|
|
#include <asm/facility.h>
|
|
#include <asm/pgtable.h>
|
|
#include <asm/uv.h>
|
|
#include "boot.h"
|
|
|
|
char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
|
|
struct ipl_parameter_block __bootdata_preserved(ipl_block);
|
|
int __bootdata_preserved(ipl_block_valid);
|
|
|
|
unsigned long __bootdata(vmalloc_size) = VMALLOC_DEFAULT_SIZE;
|
|
unsigned long __bootdata(memory_end);
|
|
int __bootdata(memory_end_set);
|
|
int __bootdata(noexec_disabled);
|
|
|
|
int kaslr_enabled __section(.data);
|
|
|
|
static inline int __diag308(unsigned long subcode, void *addr)
|
|
{
|
|
register unsigned long _addr asm("0") = (unsigned long)addr;
|
|
register unsigned long _rc asm("1") = 0;
|
|
unsigned long reg1, reg2;
|
|
psw_t old = S390_lowcore.program_new_psw;
|
|
|
|
asm volatile(
|
|
" epsw %0,%1\n"
|
|
" st %0,%[psw_pgm]\n"
|
|
" st %1,%[psw_pgm]+4\n"
|
|
" larl %0,1f\n"
|
|
" stg %0,%[psw_pgm]+8\n"
|
|
" diag %[addr],%[subcode],0x308\n"
|
|
"1: nopr %%r7\n"
|
|
: "=&d" (reg1), "=&a" (reg2),
|
|
[psw_pgm] "=Q" (S390_lowcore.program_new_psw),
|
|
[addr] "+d" (_addr), "+d" (_rc)
|
|
: [subcode] "d" (subcode)
|
|
: "cc", "memory");
|
|
S390_lowcore.program_new_psw = old;
|
|
return _rc;
|
|
}
|
|
|
|
void store_ipl_parmblock(void)
|
|
{
|
|
int rc;
|
|
|
|
rc = __diag308(DIAG308_STORE, &ipl_block);
|
|
if (rc == DIAG308_RC_OK &&
|
|
ipl_block.hdr.version <= IPL_MAX_SUPPORTED_VERSION)
|
|
ipl_block_valid = 1;
|
|
}
|
|
|
|
static size_t scpdata_length(const u8 *buf, size_t count)
|
|
{
|
|
while (count) {
|
|
if (buf[count - 1] != '\0' && buf[count - 1] != ' ')
|
|
break;
|
|
count--;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
static size_t ipl_block_get_ascii_scpdata(char *dest, size_t size,
|
|
const struct ipl_parameter_block *ipb)
|
|
{
|
|
size_t count;
|
|
size_t i;
|
|
int has_lowercase;
|
|
|
|
count = min(size - 1, scpdata_length(ipb->fcp.scp_data,
|
|
ipb->fcp.scp_data_len));
|
|
if (!count)
|
|
goto out;
|
|
|
|
has_lowercase = 0;
|
|
for (i = 0; i < count; i++) {
|
|
if (!isascii(ipb->fcp.scp_data[i])) {
|
|
count = 0;
|
|
goto out;
|
|
}
|
|
if (!has_lowercase && islower(ipb->fcp.scp_data[i]))
|
|
has_lowercase = 1;
|
|
}
|
|
|
|
if (has_lowercase)
|
|
memcpy(dest, ipb->fcp.scp_data, count);
|
|
else
|
|
for (i = 0; i < count; i++)
|
|
dest[i] = tolower(ipb->fcp.scp_data[i]);
|
|
out:
|
|
dest[count] = '\0';
|
|
return count;
|
|
}
|
|
|
|
static void append_ipl_block_parm(void)
|
|
{
|
|
char *parm, *delim;
|
|
size_t len, rc = 0;
|
|
|
|
len = strlen(early_command_line);
|
|
|
|
delim = early_command_line + len; /* '\0' character position */
|
|
parm = early_command_line + len + 1; /* append right after '\0' */
|
|
|
|
switch (ipl_block.pb0_hdr.pbt) {
|
|
case IPL_PBT_CCW:
|
|
rc = ipl_block_get_ascii_vmparm(
|
|
parm, COMMAND_LINE_SIZE - len - 1, &ipl_block);
|
|
break;
|
|
case IPL_PBT_FCP:
|
|
rc = ipl_block_get_ascii_scpdata(
|
|
parm, COMMAND_LINE_SIZE - len - 1, &ipl_block);
|
|
break;
|
|
}
|
|
if (rc) {
|
|
if (*parm == '=')
|
|
memmove(early_command_line, parm + 1, rc);
|
|
else
|
|
*delim = ' '; /* replace '\0' with space */
|
|
}
|
|
}
|
|
|
|
static inline int has_ebcdic_char(const char *str)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; str[i]; i++)
|
|
if (str[i] & 0x80)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
void setup_boot_command_line(void)
|
|
{
|
|
COMMAND_LINE[ARCH_COMMAND_LINE_SIZE - 1] = 0;
|
|
/* convert arch command line to ascii if necessary */
|
|
if (has_ebcdic_char(COMMAND_LINE))
|
|
EBCASC(COMMAND_LINE, ARCH_COMMAND_LINE_SIZE);
|
|
/* copy arch command line */
|
|
strcpy(early_command_line, strim(COMMAND_LINE));
|
|
|
|
/* append IPL PARM data to the boot command line */
|
|
if (!is_prot_virt_guest() && ipl_block_valid)
|
|
append_ipl_block_parm();
|
|
}
|
|
|
|
static void modify_facility(unsigned long nr, bool clear)
|
|
{
|
|
if (clear)
|
|
__clear_facility(nr, S390_lowcore.stfle_fac_list);
|
|
else
|
|
__set_facility(nr, S390_lowcore.stfle_fac_list);
|
|
}
|
|
|
|
static void check_cleared_facilities(void)
|
|
{
|
|
unsigned long als[] = { FACILITIES_ALS };
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(als); i++) {
|
|
if ((S390_lowcore.stfle_fac_list[i] & als[i]) != als[i]) {
|
|
sclp_early_printk("Warning: The Linux kernel requires facilities cleared via command line option\n");
|
|
print_missing_facilities();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void modify_fac_list(char *str)
|
|
{
|
|
unsigned long val, endval;
|
|
char *endp;
|
|
bool clear;
|
|
|
|
while (*str) {
|
|
clear = false;
|
|
if (*str == '!') {
|
|
clear = true;
|
|
str++;
|
|
}
|
|
val = simple_strtoull(str, &endp, 0);
|
|
if (str == endp)
|
|
break;
|
|
str = endp;
|
|
if (*str == '-') {
|
|
str++;
|
|
endval = simple_strtoull(str, &endp, 0);
|
|
if (str == endp)
|
|
break;
|
|
str = endp;
|
|
while (val <= endval) {
|
|
modify_facility(val, clear);
|
|
val++;
|
|
}
|
|
} else {
|
|
modify_facility(val, clear);
|
|
}
|
|
if (*str != ',')
|
|
break;
|
|
str++;
|
|
}
|
|
check_cleared_facilities();
|
|
}
|
|
|
|
static char command_line_buf[COMMAND_LINE_SIZE] __section(.data);
|
|
void parse_boot_command_line(void)
|
|
{
|
|
char *param, *val;
|
|
bool enabled;
|
|
char *args;
|
|
int rc;
|
|
|
|
kaslr_enabled = IS_ENABLED(CONFIG_RANDOMIZE_BASE);
|
|
args = strcpy(command_line_buf, early_command_line);
|
|
while (*args) {
|
|
args = next_arg(args, ¶m, &val);
|
|
|
|
if (!strcmp(param, "mem") && val) {
|
|
memory_end = round_down(memparse(val, NULL), PAGE_SIZE);
|
|
memory_end_set = 1;
|
|
}
|
|
|
|
if (!strcmp(param, "vmalloc") && val)
|
|
vmalloc_size = round_up(memparse(val, NULL), PAGE_SIZE);
|
|
|
|
if (!strcmp(param, "noexec")) {
|
|
rc = kstrtobool(val, &enabled);
|
|
if (!rc && !enabled)
|
|
noexec_disabled = 1;
|
|
}
|
|
|
|
if (!strcmp(param, "facilities") && val)
|
|
modify_fac_list(val);
|
|
|
|
if (!strcmp(param, "nokaslr"))
|
|
kaslr_enabled = 0;
|
|
}
|
|
}
|
|
|
|
void setup_memory_end(void)
|
|
{
|
|
#ifdef CONFIG_CRASH_DUMP
|
|
if (OLDMEM_BASE) {
|
|
kaslr_enabled = 0;
|
|
} else if (ipl_block_valid &&
|
|
ipl_block.pb0_hdr.pbt == IPL_PBT_FCP &&
|
|
ipl_block.fcp.opt == IPL_PB0_FCP_OPT_DUMP) {
|
|
kaslr_enabled = 0;
|
|
if (!sclp_early_get_hsa_size(&memory_end) && memory_end)
|
|
memory_end_set = 1;
|
|
}
|
|
#endif
|
|
}
|