Greg Kroah-Hartman | b244131 | 2017-11-01 15:07:57 +0100 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 2 | /* |
Hans-Joachim Picht | 155af2f | 2009-06-16 10:30:52 +0200 | [diff] [blame] | 3 | * Copyright IBM Corp. 2007, 2009 |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 4 | * Author(s): Hongjie Yang <hongjie@us.ibm.com>, |
| 5 | * Heiko Carstens <heiko.carstens@de.ibm.com> |
| 6 | */ |
| 7 | |
Hendrik Brueckner | 11af97e | 2009-09-11 10:28:53 +0200 | [diff] [blame] | 8 | #define KMSG_COMPONENT "setup" |
| 9 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
| 10 | |
Christian Borntraeger | 92e6ecf | 2009-03-26 15:23:58 +0100 | [diff] [blame] | 11 | #include <linux/compiler.h> |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 12 | #include <linux/init.h> |
| 13 | #include <linux/errno.h> |
| 14 | #include <linux/string.h> |
| 15 | #include <linux/ctype.h> |
| 16 | #include <linux/lockdep.h> |
Paul Gortmaker | dcc096c | 2016-09-19 17:54:56 -0400 | [diff] [blame] | 17 | #include <linux/extable.h> |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 18 | #include <linux/pfn.h> |
| 19 | #include <linux/uaccess.h> |
Hendrik Brueckner | 11af97e | 2009-09-11 10:28:53 +0200 | [diff] [blame] | 20 | #include <linux/kernel.h> |
Martin Schwidefsky | 1ec2772 | 2015-08-20 17:28:44 +0200 | [diff] [blame] | 21 | #include <asm/diag.h> |
Hendrik Brueckner | a0443fb | 2008-07-14 09:59:09 +0200 | [diff] [blame] | 22 | #include <asm/ebcdic.h> |
Michael Holzheu | 46b05d2 | 2007-02-21 10:55:21 +0100 | [diff] [blame] | 23 | #include <asm/ipl.h> |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 24 | #include <asm/lowcore.h> |
| 25 | #include <asm/processor.h> |
| 26 | #include <asm/sections.h> |
| 27 | #include <asm/setup.h> |
Christian Borntraeger | 92e6ecf | 2009-03-26 15:23:58 +0100 | [diff] [blame] | 28 | #include <asm/sysinfo.h> |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 29 | #include <asm/cpcmd.h> |
| 30 | #include <asm/sclp.h> |
David Howells | a0616cd | 2012-03-28 18:30:02 +0100 | [diff] [blame] | 31 | #include <asm/facility.h> |
Vasily Gorbik | 4969874 | 2018-05-15 13:28:53 +0200 | [diff] [blame] | 32 | #include <asm/boot_data.h> |
Vasily Gorbik | c231359 | 2019-11-14 14:08:28 +0100 | [diff] [blame] | 33 | #include <asm/switch_to.h> |
Heiko Carstens | a806170 | 2008-04-17 07:46:26 +0200 | [diff] [blame] | 34 | #include "entry.h" |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 35 | |
Vasily Gorbik | 2e83e0e | 2019-08-11 20:55:18 +0200 | [diff] [blame] | 36 | static void __init reset_tod_clock(void) |
| 37 | { |
| 38 | u64 time; |
| 39 | |
| 40 | if (store_tod_clock(&time) == 0) |
| 41 | return; |
| 42 | /* TOD clock not running. Set the clock to Unix Epoch. */ |
| 43 | if (set_tod_clock(TOD_UNIX_EPOCH) != 0 || store_tod_clock(&time) != 0) |
| 44 | disabled_wait(); |
| 45 | |
| 46 | memset(tod_clock_base, 0, 16); |
| 47 | *(__u64 *) &tod_clock_base[1] = TOD_UNIX_EPOCH; |
| 48 | S390_lowcore.last_update_clock = TOD_UNIX_EPOCH; |
| 49 | } |
| 50 | |
Martin Schwidefsky | b6112cc | 2009-04-14 15:36:28 +0200 | [diff] [blame] | 51 | /* |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 52 | * Initialize storage key for kernel pages |
| 53 | */ |
| 54 | static noinline __init void init_kernel_storage_key(void) |
| 55 | { |
Martin Schwidefsky | 127c1fe | 2013-10-07 12:12:32 +0200 | [diff] [blame] | 56 | #if PAGE_DEFAULT_KEY |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 57 | unsigned long end_pfn, init_pfn; |
| 58 | |
Vasily Gorbik | 320d955 | 2018-02-20 13:28:33 +0100 | [diff] [blame] | 59 | end_pfn = PFN_UP(__pa(_end)); |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 60 | |
| 61 | for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++) |
Martin Schwidefsky | e2b8d7af | 2010-10-25 16:10:14 +0200 | [diff] [blame] | 62 | page_set_storage_key(init_pfn << PAGE_SHIFT, |
| 63 | PAGE_DEFAULT_KEY, 0); |
Martin Schwidefsky | 127c1fe | 2013-10-07 12:12:32 +0200 | [diff] [blame] | 64 | #endif |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 65 | } |
| 66 | |
Heiko Carstens | fade4dc4 | 2012-09-04 14:26:03 +0200 | [diff] [blame] | 67 | static __initdata char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE); |
Christian Borntraeger | 92e6ecf | 2009-03-26 15:23:58 +0100 | [diff] [blame] | 68 | |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 69 | static noinline __init void detect_machine_type(void) |
| 70 | { |
Heiko Carstens | fade4dc4 | 2012-09-04 14:26:03 +0200 | [diff] [blame] | 71 | struct sysinfo_3_2_2 *vmms = (struct sysinfo_3_2_2 *)&sysinfo_page; |
| 72 | |
Martin Schwidefsky | 27d7160 | 2010-02-26 22:37:38 +0100 | [diff] [blame] | 73 | /* Check current-configuration-level */ |
Heiko Carstens | caf757c | 2012-09-06 14:42:13 +0200 | [diff] [blame] | 74 | if (stsi(NULL, 0, 0, 0) <= 2) { |
Martin Schwidefsky | 27d7160 | 2010-02-26 22:37:38 +0100 | [diff] [blame] | 75 | S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR; |
Christian Borntraeger | 92e6ecf | 2009-03-26 15:23:58 +0100 | [diff] [blame] | 76 | return; |
Martin Schwidefsky | 27d7160 | 2010-02-26 22:37:38 +0100 | [diff] [blame] | 77 | } |
| 78 | /* Get virtual-machine cpu information. */ |
Heiko Carstens | caf757c | 2012-09-06 14:42:13 +0200 | [diff] [blame] | 79 | if (stsi(vmms, 3, 2, 2) || !vmms->count) |
Christian Borntraeger | 92e6ecf | 2009-03-26 15:23:58 +0100 | [diff] [blame] | 80 | return; |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 81 | |
Christian Borntraeger | 03aa047 | 2018-11-09 09:21:47 +0100 | [diff] [blame] | 82 | /* Detect known hypervisors */ |
Heiko Carstens | fade4dc4 | 2012-09-04 14:26:03 +0200 | [diff] [blame] | 83 | if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3)) |
Heiko Carstens | d3135e0 | 2009-09-11 10:28:45 +0200 | [diff] [blame] | 84 | S390_lowcore.machine_flags |= MACHINE_FLAG_KVM; |
Christian Borntraeger | 03aa047 | 2018-11-09 09:21:47 +0100 | [diff] [blame] | 85 | else if (!memcmp(vmms->vm[0].cpi, "\xa9\x61\xe5\xd4", 4)) |
Heiko Carstens | d3135e0 | 2009-09-11 10:28:45 +0200 | [diff] [blame] | 86 | S390_lowcore.machine_flags |= MACHINE_FLAG_VM; |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 87 | } |
| 88 | |
Heiko Carstens | d2f0397 | 2017-03-11 11:58:27 +0100 | [diff] [blame] | 89 | /* Remove leading, trailing and double whitespace. */ |
| 90 | static inline void strim_all(char *str) |
| 91 | { |
| 92 | char *s; |
| 93 | |
| 94 | s = strim(str); |
| 95 | if (s != str) |
| 96 | memmove(str, s, strlen(s)); |
| 97 | while (*str) { |
| 98 | if (!isspace(*str++)) |
| 99 | continue; |
| 100 | if (isspace(*str)) { |
| 101 | s = skip_spaces(str); |
| 102 | memmove(str, s, strlen(s) + 1); |
| 103 | } |
| 104 | } |
| 105 | } |
| 106 | |
Christian Borntraeger | 4b8fe77 | 2016-05-24 15:23:20 +0200 | [diff] [blame] | 107 | static noinline __init void setup_arch_string(void) |
| 108 | { |
| 109 | struct sysinfo_1_1_1 *mach = (struct sysinfo_1_1_1 *)&sysinfo_page; |
Heiko Carstens | 2f8876f | 2017-03-11 12:22:11 +0100 | [diff] [blame] | 110 | struct sysinfo_3_2_2 *vm = (struct sysinfo_3_2_2 *)&sysinfo_page; |
| 111 | char mstr[80], hvstr[17]; |
Christian Borntraeger | 4b8fe77 | 2016-05-24 15:23:20 +0200 | [diff] [blame] | 112 | |
| 113 | if (stsi(mach, 1, 1, 1)) |
| 114 | return; |
| 115 | EBCASC(mach->manufacturer, sizeof(mach->manufacturer)); |
| 116 | EBCASC(mach->type, sizeof(mach->type)); |
| 117 | EBCASC(mach->model, sizeof(mach->model)); |
| 118 | EBCASC(mach->model_capacity, sizeof(mach->model_capacity)); |
Heiko Carstens | d2f0397 | 2017-03-11 11:58:27 +0100 | [diff] [blame] | 119 | sprintf(mstr, "%-16.16s %-4.4s %-16.16s %-16.16s", |
| 120 | mach->manufacturer, mach->type, |
| 121 | mach->model, mach->model_capacity); |
| 122 | strim_all(mstr); |
Heiko Carstens | 2f8876f | 2017-03-11 12:22:11 +0100 | [diff] [blame] | 123 | if (stsi(vm, 3, 2, 2) == 0 && vm->count) { |
| 124 | EBCASC(vm->vm[0].cpi, sizeof(vm->vm[0].cpi)); |
| 125 | sprintf(hvstr, "%-16.16s", vm->vm[0].cpi); |
| 126 | strim_all(hvstr); |
| 127 | } else { |
| 128 | sprintf(hvstr, "%s", |
| 129 | MACHINE_IS_LPAR ? "LPAR" : |
| 130 | MACHINE_IS_VM ? "z/VM" : |
| 131 | MACHINE_IS_KVM ? "KVM" : "unknown"); |
| 132 | } |
| 133 | dump_stack_set_arch_desc("%s (%s)", mstr, hvstr); |
Christian Borntraeger | 4b8fe77 | 2016-05-24 15:23:20 +0200 | [diff] [blame] | 134 | } |
| 135 | |
Heiko Carstens | fade4dc4 | 2012-09-04 14:26:03 +0200 | [diff] [blame] | 136 | static __init void setup_topology(void) |
| 137 | { |
Heiko Carstens | fade4dc4 | 2012-09-04 14:26:03 +0200 | [diff] [blame] | 138 | int max_mnest; |
| 139 | |
| 140 | if (!test_facility(11)) |
| 141 | return; |
| 142 | S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY; |
| 143 | for (max_mnest = 6; max_mnest > 1; max_mnest--) { |
Heiko Carstens | caf757c | 2012-09-06 14:42:13 +0200 | [diff] [blame] | 144 | if (stsi(&sysinfo_page, 15, 1, max_mnest) == 0) |
Heiko Carstens | fade4dc4 | 2012-09-04 14:26:03 +0200 | [diff] [blame] | 145 | break; |
| 146 | } |
| 147 | topology_max_mnest = max_mnest; |
Heiko Carstens | fade4dc4 | 2012-09-04 14:26:03 +0200 | [diff] [blame] | 148 | } |
| 149 | |
Michael Holzheu | a341570 | 2012-05-21 18:11:29 +0200 | [diff] [blame] | 150 | static void early_pgm_check_handler(void) |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 151 | { |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 152 | const struct exception_table_entry *fixup; |
Philipp Hachtmann | 50be634 | 2014-01-29 18:16:01 +0100 | [diff] [blame] | 153 | unsigned long cr0, cr0_new; |
Heiko Carstens | eb608fb | 2012-09-05 13:26:11 +0200 | [diff] [blame] | 154 | unsigned long addr; |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 155 | |
| 156 | addr = S390_lowcore.program_old_psw.addr; |
Gerald Schaefer | a80313f | 2019-02-03 21:37:20 +0100 | [diff] [blame] | 157 | fixup = s390_search_extables(addr); |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 158 | if (!fixup) |
Martin Schwidefsky | 98587c2 | 2019-04-30 12:33:45 +0200 | [diff] [blame] | 159 | disabled_wait(); |
Philipp Hachtmann | 50be634 | 2014-01-29 18:16:01 +0100 | [diff] [blame] | 160 | /* Disable low address protection before storing into lowcore. */ |
| 161 | __ctl_store(cr0, 0, 0); |
| 162 | cr0_new = cr0 & ~(1UL << 28); |
| 163 | __ctl_load(cr0_new, 0, 0); |
Heiko Carstens | fecc868a | 2016-01-18 12:49:44 +0100 | [diff] [blame] | 164 | S390_lowcore.program_old_psw.addr = extable_fixup(fixup); |
Philipp Hachtmann | 50be634 | 2014-01-29 18:16:01 +0100 | [diff] [blame] | 165 | __ctl_load(cr0, 0, 0); |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 166 | } |
| 167 | |
Heiko Carstens | 5f954c3 | 2009-07-24 12:39:49 +0200 | [diff] [blame] | 168 | static noinline __init void setup_lowcore_early(void) |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 169 | { |
| 170 | psw_t psw; |
| 171 | |
Martin Schwidefsky | b50511e | 2011-10-30 15:16:50 +0100 | [diff] [blame] | 172 | psw.mask = PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA; |
Heiko Carstens | fecc868a | 2016-01-18 12:49:44 +0100 | [diff] [blame] | 173 | psw.addr = (unsigned long) s390_base_ext_handler; |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 174 | S390_lowcore.external_new_psw = psw; |
Heiko Carstens | fecc868a | 2016-01-18 12:49:44 +0100 | [diff] [blame] | 175 | psw.addr = (unsigned long) s390_base_pgm_handler; |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 176 | S390_lowcore.program_new_psw = psw; |
| 177 | s390_base_pgm_handler_fn = early_pgm_check_handler; |
Martin Schwidefsky | c360192 | 2016-10-25 12:21:44 +0200 | [diff] [blame] | 178 | S390_lowcore.preempt_count = INIT_PREEMPT_COUNT; |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 179 | } |
| 180 | |
Martin Schwidefsky | 14375bc | 2010-10-25 16:10:51 +0200 | [diff] [blame] | 181 | static noinline __init void setup_facility_list(void) |
| 182 | { |
Martin Schwidefsky | cf14899 | 2018-01-16 07:03:44 +0100 | [diff] [blame] | 183 | memcpy(S390_lowcore.alt_stfle_fac_list, |
| 184 | S390_lowcore.stfle_fac_list, |
| 185 | sizeof(S390_lowcore.alt_stfle_fac_list)); |
Martin Schwidefsky | d768bd8 | 2018-01-16 07:11:45 +0100 | [diff] [blame] | 186 | if (!IS_ENABLED(CONFIG_KERNEL_NOBP)) |
| 187 | __clear_facility(82, S390_lowcore.alt_stfle_fac_list); |
Martin Schwidefsky | 14375bc | 2010-10-25 16:10:51 +0200 | [diff] [blame] | 188 | } |
| 189 | |
Heiko Carstens | 2e5061e | 2008-04-30 13:38:45 +0200 | [diff] [blame] | 190 | static __init void detect_diag9c(void) |
| 191 | { |
| 192 | unsigned int cpu_address; |
| 193 | int rc; |
| 194 | |
| 195 | cpu_address = stap(); |
Martin Schwidefsky | 1ec2772 | 2015-08-20 17:28:44 +0200 | [diff] [blame] | 196 | diag_stat_inc(DIAG_STAT_X09C); |
Heiko Carstens | 2e5061e | 2008-04-30 13:38:45 +0200 | [diff] [blame] | 197 | asm volatile( |
| 198 | " diag %2,0,0x9c\n" |
| 199 | "0: la %0,0\n" |
| 200 | "1:\n" |
| 201 | EX_TABLE(0b,1b) |
| 202 | : "=d" (rc) : "0" (-EOPNOTSUPP), "d" (cpu_address) : "cc"); |
| 203 | if (!rc) |
Heiko Carstens | d3135e0 | 2009-09-11 10:28:45 +0200 | [diff] [blame] | 204 | S390_lowcore.machine_flags |= MACHINE_FLAG_DIAG9C; |
Heiko Carstens | 2e5061e | 2008-04-30 13:38:45 +0200 | [diff] [blame] | 205 | } |
| 206 | |
Heiko Carstens | 2e5061e | 2008-04-30 13:38:45 +0200 | [diff] [blame] | 207 | static __init void detect_machine_facilities(void) |
| 208 | { |
Heiko Carstens | 3c7ef08 | 2012-09-28 15:06:41 +0200 | [diff] [blame] | 209 | if (test_facility(8)) { |
| 210 | S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT1; |
| 211 | __ctl_set_bit(0, 23); |
| 212 | } |
Heiko Carstens | 85e9d0e5 | 2012-09-27 10:45:06 +0200 | [diff] [blame] | 213 | if (test_facility(78)) |
| 214 | S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT2; |
Martin Schwidefsky | 14375bc | 2010-10-25 16:10:51 +0200 | [diff] [blame] | 215 | if (test_facility(3)) |
Heiko Carstens | d3135e0 | 2009-09-11 10:28:45 +0200 | [diff] [blame] | 216 | S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; |
Heiko Carstens | a1c5bef | 2017-11-09 12:29:34 +0100 | [diff] [blame] | 217 | if (test_facility(50) && test_facility(73)) { |
Martin Schwidefsky | d35339a | 2012-07-31 11:03:04 +0200 | [diff] [blame] | 218 | S390_lowcore.machine_flags |= MACHINE_FLAG_TE; |
Heiko Carstens | a1c5bef | 2017-11-09 12:29:34 +0100 | [diff] [blame] | 219 | __ctl_set_bit(0, 55); |
| 220 | } |
Martin Schwidefsky | 1b948d6 | 2014-04-03 13:55:01 +0200 | [diff] [blame] | 221 | if (test_facility(51)) |
| 222 | S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC; |
Hendrik Brueckner | b5510d9 | 2015-09-29 10:04:41 +0200 | [diff] [blame] | 223 | if (test_facility(129)) { |
Martin Schwidefsky | 8070361 | 2014-10-06 17:53:53 +0200 | [diff] [blame] | 224 | S390_lowcore.machine_flags |= MACHINE_FLAG_VX; |
Hendrik Brueckner | b5510d9 | 2015-09-29 10:04:41 +0200 | [diff] [blame] | 225 | __ctl_set_bit(0, 17); |
| 226 | } |
Vasily Gorbik | d3baaeb | 2019-10-22 17:37:51 +0200 | [diff] [blame] | 227 | if (test_facility(130) && !noexec_disabled) { |
Martin Schwidefsky | 57d7f93 | 2016-03-22 10:54:24 +0100 | [diff] [blame] | 228 | S390_lowcore.machine_flags |= MACHINE_FLAG_NX; |
| 229 | __ctl_set_bit(0, 20); |
| 230 | } |
Martin Schwidefsky | 916cda1 | 2016-01-26 14:10:34 +0100 | [diff] [blame] | 231 | if (test_facility(133)) |
| 232 | S390_lowcore.machine_flags |= MACHINE_FLAG_GS; |
Martin Schwidefsky | 6e2ef5e | 2016-10-27 12:41:39 +0200 | [diff] [blame] | 233 | if (test_facility(139) && (tod_clock_base[1] & 0x80)) { |
| 234 | /* Enabled signed clock comparator comparisons */ |
| 235 | S390_lowcore.machine_flags |= MACHINE_FLAG_SCC; |
| 236 | clock_comparator_max = -1ULL >> 1; |
| 237 | __ctl_set_bit(0, 53); |
| 238 | } |
Heiko Carstens | 2e5061e | 2008-04-30 13:38:45 +0200 | [diff] [blame] | 239 | } |
| 240 | |
Martin Schwidefsky | 1a36a39 | 2015-10-29 10:28:26 +0100 | [diff] [blame] | 241 | static inline void save_vector_registers(void) |
| 242 | { |
| 243 | #ifdef CONFIG_CRASH_DUMP |
| 244 | if (test_facility(129)) |
| 245 | save_vx_regs(boot_cpu_vector_save_area); |
| 246 | #endif |
| 247 | } |
| 248 | |
Vasily Gorbik | c02ee6a | 2019-11-12 17:35:28 +0100 | [diff] [blame] | 249 | static inline void setup_control_registers(void) |
| 250 | { |
| 251 | unsigned long reg; |
| 252 | |
| 253 | __ctl_store(reg, 0, 0); |
| 254 | reg |= CR0_LOW_ADDRESS_PROTECTION; |
| 255 | reg |= CR0_EMERGENCY_SIGNAL_SUBMASK; |
| 256 | reg |= CR0_EXTERNAL_CALL_SUBMASK; |
| 257 | __ctl_load(reg, 0, 0); |
| 258 | } |
| 259 | |
Vasily Gorbik | c231359 | 2019-11-14 14:08:28 +0100 | [diff] [blame] | 260 | static inline void setup_access_registers(void) |
| 261 | { |
| 262 | unsigned int acrs[NUM_ACRS] = { 0 }; |
| 263 | |
| 264 | restore_access_regs(acrs); |
| 265 | } |
| 266 | |
Hendrik Brueckner | b5510d9 | 2015-09-29 10:04:41 +0200 | [diff] [blame] | 267 | static int __init disable_vector_extension(char *str) |
| 268 | { |
| 269 | S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX; |
| 270 | __ctl_clear_bit(0, 17); |
Heiko Carstens | 673cfdd | 2017-08-11 15:54:16 +0200 | [diff] [blame] | 271 | return 0; |
Hendrik Brueckner | b5510d9 | 2015-09-29 10:04:41 +0200 | [diff] [blame] | 272 | } |
| 273 | early_param("novx", disable_vector_extension); |
| 274 | |
Martin Schwidefsky | 61b0b01 | 2015-02-19 17:53:16 +0100 | [diff] [blame] | 275 | static int __init cad_setup(char *str) |
Martin Schwidefsky | 2c72a44 | 2015-01-14 17:52:33 +0100 | [diff] [blame] | 276 | { |
Martin Schwidefsky | b13de4b | 2017-03-24 17:00:45 +0100 | [diff] [blame] | 277 | bool enabled; |
| 278 | int rc; |
Martin Schwidefsky | 61b0b01 | 2015-02-19 17:53:16 +0100 | [diff] [blame] | 279 | |
Martin Schwidefsky | b13de4b | 2017-03-24 17:00:45 +0100 | [diff] [blame] | 280 | rc = kstrtobool(str, &enabled); |
| 281 | if (!rc && enabled && test_facility(128)) |
Martin Schwidefsky | 2c72a44 | 2015-01-14 17:52:33 +0100 | [diff] [blame] | 282 | /* Enable problem state CAD. */ |
| 283 | __ctl_set_bit(2, 3); |
Martin Schwidefsky | b13de4b | 2017-03-24 17:00:45 +0100 | [diff] [blame] | 284 | return rc; |
Martin Schwidefsky | 2c72a44 | 2015-01-14 17:52:33 +0100 | [diff] [blame] | 285 | } |
Martin Schwidefsky | b13de4b | 2017-03-24 17:00:45 +0100 | [diff] [blame] | 286 | early_param("cad", cad_setup); |
Martin Schwidefsky | 2c72a44 | 2015-01-14 17:52:33 +0100 | [diff] [blame] | 287 | |
Vasily Gorbik | 4969874 | 2018-05-15 13:28:53 +0200 | [diff] [blame] | 288 | char __bootdata(early_command_line)[COMMAND_LINE_SIZE]; |
Michael Holzheu | 1fb8105 | 2011-12-27 11:25:46 +0100 | [diff] [blame] | 289 | static void __init setup_boot_command_line(void) |
| 290 | { |
Hendrik Brueckner | a0443fb | 2008-07-14 09:59:09 +0200 | [diff] [blame] | 291 | /* copy arch command line */ |
Vasily Gorbik | 4969874 | 2018-05-15 13:28:53 +0200 | [diff] [blame] | 292 | strlcpy(boot_command_line, early_command_line, ARCH_COMMAND_LINE_SIZE); |
Hendrik Brueckner | a0443fb | 2008-07-14 09:59:09 +0200 | [diff] [blame] | 293 | } |
| 294 | |
Vasily Gorbik | 627c9b6 | 2018-06-25 13:59:35 +0200 | [diff] [blame] | 295 | static void __init check_image_bootable(void) |
| 296 | { |
| 297 | if (!memcmp(EP_STRING, (void *)EP_OFFSET, strlen(EP_STRING))) |
| 298 | return; |
| 299 | |
| 300 | sclp_early_printk("Linux kernel boot failure: An attempt to boot a vmlinux ELF image failed.\n"); |
| 301 | sclp_early_printk("This image does not contain all parts necessary for starting up. Use\n"); |
| 302 | sclp_early_printk("bzImage or arch/s390/boot/compressed/vmlinux instead.\n"); |
Martin Schwidefsky | 98587c2 | 2019-04-30 12:33:45 +0200 | [diff] [blame] | 303 | disabled_wait(); |
Vasily Gorbik | 627c9b6 | 2018-06-25 13:59:35 +0200 | [diff] [blame] | 304 | } |
| 305 | |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 306 | void __init startup_init(void) |
| 307 | { |
Vasily Gorbik | 2e83e0e | 2019-08-11 20:55:18 +0200 | [diff] [blame] | 308 | reset_tod_clock(); |
Vasily Gorbik | 627c9b6 | 2018-06-25 13:59:35 +0200 | [diff] [blame] | 309 | check_image_bootable(); |
Martin Schwidefsky | b1c0854 | 2016-10-10 09:43:41 +0200 | [diff] [blame] | 310 | time_early_init(); |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 311 | init_kernel_storage_key(); |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 312 | lockdep_off(); |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 313 | setup_lowcore_early(); |
Martin Schwidefsky | 14375bc | 2010-10-25 16:10:51 +0200 | [diff] [blame] | 314 | setup_facility_list(); |
Hendrik Brueckner | a0443fb | 2008-07-14 09:59:09 +0200 | [diff] [blame] | 315 | detect_machine_type(); |
Christian Borntraeger | 4b8fe77 | 2016-05-24 15:23:20 +0200 | [diff] [blame] | 316 | setup_arch_string(); |
Hendrik Brueckner | a0443fb | 2008-07-14 09:59:09 +0200 | [diff] [blame] | 317 | setup_boot_command_line(); |
Heiko Carstens | 2e5061e | 2008-04-30 13:38:45 +0200 | [diff] [blame] | 318 | detect_diag9c(); |
Heiko Carstens | 2e5061e | 2008-04-30 13:38:45 +0200 | [diff] [blame] | 319 | detect_machine_facilities(); |
Martin Schwidefsky | 1a36a39 | 2015-10-29 10:28:26 +0100 | [diff] [blame] | 320 | save_vector_registers(); |
Heiko Carstens | fade4dc4 | 2012-09-04 14:26:03 +0200 | [diff] [blame] | 321 | setup_topology(); |
Michael Holzheu | 7b50da5 | 2013-11-13 10:38:27 +0100 | [diff] [blame] | 322 | sclp_early_detect(); |
Vasily Gorbik | c02ee6a | 2019-11-12 17:35:28 +0100 | [diff] [blame] | 323 | setup_control_registers(); |
Vasily Gorbik | c231359 | 2019-11-14 14:08:28 +0100 | [diff] [blame] | 324 | setup_access_registers(); |
Heiko Carstens | ab14de6 | 2007-02-05 21:18:37 +0100 | [diff] [blame] | 325 | lockdep_on(); |
| 326 | } |