1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright IBM Corp. 2007, 2009 4 * Author(s): Hongjie Yang <hongjie@us.ibm.com>, 5 */ 6 7 #define KMSG_COMPONENT "setup" 8 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 9 10 #include <linux/compiler.h> 11 #include <linux/init.h> 12 #include <linux/errno.h> 13 #include <linux/string.h> 14 #include <linux/ctype.h> 15 #include <linux/lockdep.h> 16 #include <linux/extable.h> 17 #include <linux/pfn.h> 18 #include <linux/uaccess.h> 19 #include <linux/kernel.h> 20 #include <asm/asm-extable.h> 21 #include <linux/memblock.h> 22 #include <asm/diag.h> 23 #include <asm/ebcdic.h> 24 #include <asm/ipl.h> 25 #include <asm/lowcore.h> 26 #include <asm/processor.h> 27 #include <asm/sections.h> 28 #include <asm/setup.h> 29 #include <asm/sysinfo.h> 30 #include <asm/cpcmd.h> 31 #include <asm/sclp.h> 32 #include <asm/facility.h> 33 #include <asm/boot_data.h> 34 #include <asm/switch_to.h> 35 #include "entry.h" 36 37 int __bootdata(is_full_image); 38 39 #define decompressor_handled_param(param) \ 40 static int __init ignore_decompressor_param_##param(char *s) \ 41 { \ 42 return 0; \ 43 } \ 44 early_param(#param, ignore_decompressor_param_##param) 45 46 decompressor_handled_param(mem); 47 decompressor_handled_param(vmalloc); 48 decompressor_handled_param(dfltcc); 49 decompressor_handled_param(noexec); 50 decompressor_handled_param(facilities); 51 decompressor_handled_param(nokaslr); 52 #if IS_ENABLED(CONFIG_KVM) 53 decompressor_handled_param(prot_virt); 54 #endif 55 56 static void __init reset_tod_clock(void) 57 { 58 union tod_clock clk; 59 60 if (store_tod_clock_ext_cc(&clk) == 0) 61 return; 62 /* TOD clock not running. Set the clock to Unix Epoch. */ 63 if (set_tod_clock(TOD_UNIX_EPOCH) || store_tod_clock_ext_cc(&clk)) 64 disabled_wait(); 65 66 memset(&tod_clock_base, 0, sizeof(tod_clock_base)); 67 tod_clock_base.tod = TOD_UNIX_EPOCH; 68 S390_lowcore.last_update_clock = TOD_UNIX_EPOCH; 69 } 70 71 /* 72 * Initialize storage key for kernel pages 73 */ 74 static noinline __init void init_kernel_storage_key(void) 75 { 76 #if PAGE_DEFAULT_KEY 77 unsigned long end_pfn, init_pfn; 78 79 end_pfn = PFN_UP(__pa(_end)); 80 81 for (init_pfn = 0 ; init_pfn < end_pfn; init_pfn++) 82 page_set_storage_key(init_pfn << PAGE_SHIFT, 83 PAGE_DEFAULT_KEY, 0); 84 #endif 85 } 86 87 static __initdata char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE); 88 89 static noinline __init void detect_machine_type(void) 90 { 91 struct sysinfo_3_2_2 *vmms = (struct sysinfo_3_2_2 *)&sysinfo_page; 92 93 /* Check current-configuration-level */ 94 if (stsi(NULL, 0, 0, 0) <= 2) { 95 S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR; 96 return; 97 } 98 /* Get virtual-machine cpu information. */ 99 if (stsi(vmms, 3, 2, 2) || !vmms->count) 100 return; 101 102 /* Detect known hypervisors */ 103 if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3)) 104 S390_lowcore.machine_flags |= MACHINE_FLAG_KVM; 105 else if (!memcmp(vmms->vm[0].cpi, "\xa9\x61\xe5\xd4", 4)) 106 S390_lowcore.machine_flags |= MACHINE_FLAG_VM; 107 } 108 109 /* Remove leading, trailing and double whitespace. */ 110 static inline void strim_all(char *str) 111 { 112 char *s; 113 114 s = strim(str); 115 if (s != str) 116 memmove(str, s, strlen(s)); 117 while (*str) { 118 if (!isspace(*str++)) 119 continue; 120 if (isspace(*str)) { 121 s = skip_spaces(str); 122 memmove(str, s, strlen(s) + 1); 123 } 124 } 125 } 126 127 static noinline __init void setup_arch_string(void) 128 { 129 struct sysinfo_1_1_1 *mach = (struct sysinfo_1_1_1 *)&sysinfo_page; 130 struct sysinfo_3_2_2 *vm = (struct sysinfo_3_2_2 *)&sysinfo_page; 131 char mstr[80], hvstr[17]; 132 133 if (stsi(mach, 1, 1, 1)) 134 return; 135 EBCASC(mach->manufacturer, sizeof(mach->manufacturer)); 136 EBCASC(mach->type, sizeof(mach->type)); 137 EBCASC(mach->model, sizeof(mach->model)); 138 EBCASC(mach->model_capacity, sizeof(mach->model_capacity)); 139 sprintf(mstr, "%-16.16s %-4.4s %-16.16s %-16.16s", 140 mach->manufacturer, mach->type, 141 mach->model, mach->model_capacity); 142 strim_all(mstr); 143 if (stsi(vm, 3, 2, 2) == 0 && vm->count) { 144 EBCASC(vm->vm[0].cpi, sizeof(vm->vm[0].cpi)); 145 sprintf(hvstr, "%-16.16s", vm->vm[0].cpi); 146 strim_all(hvstr); 147 } else { 148 sprintf(hvstr, "%s", 149 MACHINE_IS_LPAR ? "LPAR" : 150 MACHINE_IS_VM ? "z/VM" : 151 MACHINE_IS_KVM ? "KVM" : "unknown"); 152 } 153 dump_stack_set_arch_desc("%s (%s)", mstr, hvstr); 154 } 155 156 static __init void setup_topology(void) 157 { 158 int max_mnest; 159 160 if (!test_facility(11)) 161 return; 162 S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY; 163 for (max_mnest = 6; max_mnest > 1; max_mnest--) { 164 if (stsi(&sysinfo_page, 15, 1, max_mnest) == 0) 165 break; 166 } 167 topology_max_mnest = max_mnest; 168 } 169 170 void __do_early_pgm_check(struct pt_regs *regs) 171 { 172 if (!fixup_exception(regs)) 173 disabled_wait(); 174 } 175 176 static noinline __init void setup_lowcore_early(void) 177 { 178 psw_t psw; 179 180 psw.addr = (unsigned long)early_pgm_check_handler; 181 psw.mask = PSW_KERNEL_BITS; 182 S390_lowcore.program_new_psw = psw; 183 S390_lowcore.preempt_count = INIT_PREEMPT_COUNT; 184 } 185 186 static noinline __init void setup_facility_list(void) 187 { 188 memcpy(alt_stfle_fac_list, stfle_fac_list, sizeof(alt_stfle_fac_list)); 189 if (!IS_ENABLED(CONFIG_KERNEL_NOBP)) 190 __clear_facility(82, alt_stfle_fac_list); 191 } 192 193 static __init void detect_diag9c(void) 194 { 195 unsigned int cpu_address; 196 int rc; 197 198 cpu_address = stap(); 199 diag_stat_inc(DIAG_STAT_X09C); 200 asm volatile( 201 " diag %2,0,0x9c\n" 202 "0: la %0,0\n" 203 "1:\n" 204 EX_TABLE(0b,1b) 205 : "=d" (rc) : "0" (-EOPNOTSUPP), "d" (cpu_address) : "cc"); 206 if (!rc) 207 S390_lowcore.machine_flags |= MACHINE_FLAG_DIAG9C; 208 } 209 210 static __init void detect_machine_facilities(void) 211 { 212 if (test_facility(8)) { 213 S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT1; 214 __ctl_set_bit(0, 23); 215 } 216 if (test_facility(78)) 217 S390_lowcore.machine_flags |= MACHINE_FLAG_EDAT2; 218 if (test_facility(3)) 219 S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; 220 if (test_facility(50) && test_facility(73)) { 221 S390_lowcore.machine_flags |= MACHINE_FLAG_TE; 222 __ctl_set_bit(0, 55); 223 } 224 if (test_facility(51)) 225 S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC; 226 if (test_facility(129)) { 227 S390_lowcore.machine_flags |= MACHINE_FLAG_VX; 228 __ctl_set_bit(0, 17); 229 } 230 if (test_facility(130) && !noexec_disabled) { 231 S390_lowcore.machine_flags |= MACHINE_FLAG_NX; 232 __ctl_set_bit(0, 20); 233 } 234 if (test_facility(133)) 235 S390_lowcore.machine_flags |= MACHINE_FLAG_GS; 236 if (test_facility(139) && (tod_clock_base.tod >> 63)) { 237 /* Enabled signed clock comparator comparisons */ 238 S390_lowcore.machine_flags |= MACHINE_FLAG_SCC; 239 clock_comparator_max = -1ULL >> 1; 240 __ctl_set_bit(0, 53); 241 } 242 if (IS_ENABLED(CONFIG_PCI) && test_facility(153)) { 243 S390_lowcore.machine_flags |= MACHINE_FLAG_PCI_MIO; 244 /* the control bit is set during PCI initialization */ 245 } 246 if (test_facility(194)) 247 S390_lowcore.machine_flags |= MACHINE_FLAG_RDP; 248 } 249 250 static inline void save_vector_registers(void) 251 { 252 #ifdef CONFIG_CRASH_DUMP 253 if (test_facility(129)) 254 save_vx_regs(boot_cpu_vector_save_area); 255 #endif 256 } 257 258 static inline void setup_control_registers(void) 259 { 260 unsigned long reg; 261 262 __ctl_store(reg, 0, 0); 263 reg |= CR0_LOW_ADDRESS_PROTECTION; 264 reg |= CR0_EMERGENCY_SIGNAL_SUBMASK; 265 reg |= CR0_EXTERNAL_CALL_SUBMASK; 266 __ctl_load(reg, 0, 0); 267 } 268 269 static inline void setup_access_registers(void) 270 { 271 unsigned int acrs[NUM_ACRS] = { 0 }; 272 273 restore_access_regs(acrs); 274 } 275 276 static int __init disable_vector_extension(char *str) 277 { 278 S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX; 279 __ctl_clear_bit(0, 17); 280 return 0; 281 } 282 early_param("novx", disable_vector_extension); 283 284 char __bootdata(early_command_line)[COMMAND_LINE_SIZE]; 285 static void __init setup_boot_command_line(void) 286 { 287 /* copy arch command line */ 288 strscpy(boot_command_line, early_command_line, COMMAND_LINE_SIZE); 289 } 290 291 static void __init check_image_bootable(void) 292 { 293 if (is_full_image) 294 return; 295 296 sclp_early_printk("Linux kernel boot failure: An attempt to boot a vmlinux ELF image failed.\n"); 297 sclp_early_printk("This image does not contain all parts necessary for starting up. Use\n"); 298 sclp_early_printk("bzImage or arch/s390/boot/compressed/vmlinux instead.\n"); 299 disabled_wait(); 300 } 301 302 static void __init sort_amode31_extable(void) 303 { 304 sort_extable(__start_amode31_ex_table, __stop_amode31_ex_table); 305 } 306 307 void __init startup_init(void) 308 { 309 reset_tod_clock(); 310 check_image_bootable(); 311 time_early_init(); 312 init_kernel_storage_key(); 313 lockdep_off(); 314 sort_amode31_extable(); 315 setup_lowcore_early(); 316 setup_facility_list(); 317 detect_machine_type(); 318 setup_arch_string(); 319 setup_boot_command_line(); 320 detect_diag9c(); 321 detect_machine_facilities(); 322 save_vector_registers(); 323 setup_topology(); 324 sclp_early_detect(); 325 setup_control_registers(); 326 setup_access_registers(); 327 lockdep_on(); 328 } 329