.. | .. |
---|
29 | 29 | #include <asm/cpcmd.h> |
---|
30 | 30 | #include <asm/sclp.h> |
---|
31 | 31 | #include <asm/facility.h> |
---|
| 32 | +#include <asm/boot_data.h> |
---|
| 33 | +#include <asm/switch_to.h> |
---|
32 | 34 | #include "entry.h" |
---|
33 | 35 | |
---|
34 | | -static void __init setup_boot_command_line(void); |
---|
| 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 | +} |
---|
35 | 50 | |
---|
36 | 51 | /* |
---|
37 | 52 | * Initialize storage key for kernel pages |
---|
.. | .. |
---|
139 | 154 | unsigned long addr; |
---|
140 | 155 | |
---|
141 | 156 | addr = S390_lowcore.program_old_psw.addr; |
---|
142 | | - fixup = search_exception_tables(addr); |
---|
| 157 | + fixup = s390_search_extables(addr); |
---|
143 | 158 | if (!fixup) |
---|
144 | | - disabled_wait(0); |
---|
| 159 | + disabled_wait(); |
---|
145 | 160 | /* Disable low address protection before storing into lowcore. */ |
---|
146 | 161 | __ctl_store(cr0, 0, 0); |
---|
147 | 162 | cr0_new = cr0 & ~(1UL << 28); |
---|
.. | .. |
---|
167 | 182 | |
---|
168 | 183 | static noinline __init void setup_facility_list(void) |
---|
169 | 184 | { |
---|
170 | | - stfle(S390_lowcore.stfle_fac_list, |
---|
171 | | - ARRAY_SIZE(S390_lowcore.stfle_fac_list)); |
---|
172 | 185 | memcpy(S390_lowcore.alt_stfle_fac_list, |
---|
173 | 186 | S390_lowcore.stfle_fac_list, |
---|
174 | 187 | sizeof(S390_lowcore.alt_stfle_fac_list)); |
---|
.. | .. |
---|
193 | 206 | S390_lowcore.machine_flags |= MACHINE_FLAG_DIAG9C; |
---|
194 | 207 | } |
---|
195 | 208 | |
---|
196 | | -static __init void detect_diag44(void) |
---|
197 | | -{ |
---|
198 | | - int rc; |
---|
199 | | - |
---|
200 | | - diag_stat_inc(DIAG_STAT_X044); |
---|
201 | | - asm volatile( |
---|
202 | | - " diag 0,0,0x44\n" |
---|
203 | | - "0: la %0,0\n" |
---|
204 | | - "1:\n" |
---|
205 | | - EX_TABLE(0b,1b) |
---|
206 | | - : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc"); |
---|
207 | | - if (!rc) |
---|
208 | | - S390_lowcore.machine_flags |= MACHINE_FLAG_DIAG44; |
---|
209 | | -} |
---|
210 | | - |
---|
211 | 209 | static __init void detect_machine_facilities(void) |
---|
212 | 210 | { |
---|
213 | 211 | if (test_facility(8)) { |
---|
.. | .. |
---|
228 | 226 | S390_lowcore.machine_flags |= MACHINE_FLAG_VX; |
---|
229 | 227 | __ctl_set_bit(0, 17); |
---|
230 | 228 | } |
---|
231 | | - if (test_facility(130)) { |
---|
| 229 | + if (test_facility(130) && !noexec_disabled) { |
---|
232 | 230 | S390_lowcore.machine_flags |= MACHINE_FLAG_NX; |
---|
233 | 231 | __ctl_set_bit(0, 20); |
---|
234 | 232 | } |
---|
.. | .. |
---|
240 | 238 | clock_comparator_max = -1ULL >> 1; |
---|
241 | 239 | __ctl_set_bit(0, 53); |
---|
242 | 240 | } |
---|
| 241 | + if (IS_ENABLED(CONFIG_PCI) && test_facility(153)) { |
---|
| 242 | + S390_lowcore.machine_flags |= MACHINE_FLAG_PCI_MIO; |
---|
| 243 | + /* the control bit is set during PCI initialization */ |
---|
| 244 | + } |
---|
243 | 245 | } |
---|
244 | 246 | |
---|
245 | 247 | static inline void save_vector_registers(void) |
---|
.. | .. |
---|
250 | 252 | #endif |
---|
251 | 253 | } |
---|
252 | 254 | |
---|
| 255 | +static inline void setup_control_registers(void) |
---|
| 256 | +{ |
---|
| 257 | + unsigned long reg; |
---|
| 258 | + |
---|
| 259 | + __ctl_store(reg, 0, 0); |
---|
| 260 | + reg |= CR0_LOW_ADDRESS_PROTECTION; |
---|
| 261 | + reg |= CR0_EMERGENCY_SIGNAL_SUBMASK; |
---|
| 262 | + reg |= CR0_EXTERNAL_CALL_SUBMASK; |
---|
| 263 | + __ctl_load(reg, 0, 0); |
---|
| 264 | +} |
---|
| 265 | + |
---|
| 266 | +static inline void setup_access_registers(void) |
---|
| 267 | +{ |
---|
| 268 | + unsigned int acrs[NUM_ACRS] = { 0 }; |
---|
| 269 | + |
---|
| 270 | + restore_access_regs(acrs); |
---|
| 271 | +} |
---|
| 272 | + |
---|
253 | 273 | static int __init disable_vector_extension(char *str) |
---|
254 | 274 | { |
---|
255 | 275 | S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX; |
---|
.. | .. |
---|
258 | 278 | } |
---|
259 | 279 | early_param("novx", disable_vector_extension); |
---|
260 | 280 | |
---|
261 | | -static int __init noexec_setup(char *str) |
---|
262 | | -{ |
---|
263 | | - bool enabled; |
---|
264 | | - int rc; |
---|
265 | | - |
---|
266 | | - rc = kstrtobool(str, &enabled); |
---|
267 | | - if (!rc && !enabled) { |
---|
268 | | - /* Disable no-execute support */ |
---|
269 | | - S390_lowcore.machine_flags &= ~MACHINE_FLAG_NX; |
---|
270 | | - __ctl_clear_bit(0, 20); |
---|
271 | | - } |
---|
272 | | - return rc; |
---|
273 | | -} |
---|
274 | | -early_param("noexec", noexec_setup); |
---|
275 | | - |
---|
276 | | -static int __init cad_setup(char *str) |
---|
277 | | -{ |
---|
278 | | - bool enabled; |
---|
279 | | - int rc; |
---|
280 | | - |
---|
281 | | - rc = kstrtobool(str, &enabled); |
---|
282 | | - if (!rc && enabled && test_facility(128)) |
---|
283 | | - /* Enable problem state CAD. */ |
---|
284 | | - __ctl_set_bit(2, 3); |
---|
285 | | - return rc; |
---|
286 | | -} |
---|
287 | | -early_param("cad", cad_setup); |
---|
288 | | - |
---|
289 | | -/* Set up boot command line */ |
---|
290 | | -static void __init append_to_cmdline(size_t (*ipl_data)(char *, size_t)) |
---|
291 | | -{ |
---|
292 | | - char *parm, *delim; |
---|
293 | | - size_t rc, len; |
---|
294 | | - |
---|
295 | | - len = strlen(boot_command_line); |
---|
296 | | - |
---|
297 | | - delim = boot_command_line + len; /* '\0' character position */ |
---|
298 | | - parm = boot_command_line + len + 1; /* append right after '\0' */ |
---|
299 | | - |
---|
300 | | - rc = ipl_data(parm, COMMAND_LINE_SIZE - len - 1); |
---|
301 | | - if (rc) { |
---|
302 | | - if (*parm == '=') |
---|
303 | | - memmove(boot_command_line, parm + 1, rc); |
---|
304 | | - else |
---|
305 | | - *delim = ' '; /* replace '\0' with space */ |
---|
306 | | - } |
---|
307 | | -} |
---|
308 | | - |
---|
309 | | -static inline int has_ebcdic_char(const char *str) |
---|
310 | | -{ |
---|
311 | | - int i; |
---|
312 | | - |
---|
313 | | - for (i = 0; str[i]; i++) |
---|
314 | | - if (str[i] & 0x80) |
---|
315 | | - return 1; |
---|
316 | | - return 0; |
---|
317 | | -} |
---|
318 | | - |
---|
| 281 | +char __bootdata(early_command_line)[COMMAND_LINE_SIZE]; |
---|
319 | 282 | static void __init setup_boot_command_line(void) |
---|
320 | 283 | { |
---|
321 | | - COMMAND_LINE[ARCH_COMMAND_LINE_SIZE - 1] = 0; |
---|
322 | | - /* convert arch command line to ascii if necessary */ |
---|
323 | | - if (has_ebcdic_char(COMMAND_LINE)) |
---|
324 | | - EBCASC(COMMAND_LINE, ARCH_COMMAND_LINE_SIZE); |
---|
325 | 284 | /* copy arch command line */ |
---|
326 | | - strlcpy(boot_command_line, strstrip(COMMAND_LINE), |
---|
327 | | - ARCH_COMMAND_LINE_SIZE); |
---|
328 | | - |
---|
329 | | - /* append IPL PARM data to the boot command line */ |
---|
330 | | - if (MACHINE_IS_VM) |
---|
331 | | - append_to_cmdline(append_ipl_vmparm); |
---|
332 | | - |
---|
333 | | - append_to_cmdline(append_ipl_scpdata); |
---|
| 285 | + strlcpy(boot_command_line, early_command_line, ARCH_COMMAND_LINE_SIZE); |
---|
334 | 286 | } |
---|
335 | 287 | |
---|
336 | 288 | static void __init check_image_bootable(void) |
---|
.. | .. |
---|
341 | 293 | sclp_early_printk("Linux kernel boot failure: An attempt to boot a vmlinux ELF image failed.\n"); |
---|
342 | 294 | sclp_early_printk("This image does not contain all parts necessary for starting up. Use\n"); |
---|
343 | 295 | sclp_early_printk("bzImage or arch/s390/boot/compressed/vmlinux instead.\n"); |
---|
344 | | - disabled_wait(0xbadb007); |
---|
| 296 | + disabled_wait(); |
---|
345 | 297 | } |
---|
346 | 298 | |
---|
347 | 299 | void __init startup_init(void) |
---|
348 | 300 | { |
---|
| 301 | + reset_tod_clock(); |
---|
349 | 302 | check_image_bootable(); |
---|
350 | 303 | time_early_init(); |
---|
351 | 304 | init_kernel_storage_key(); |
---|
.. | .. |
---|
354 | 307 | setup_facility_list(); |
---|
355 | 308 | detect_machine_type(); |
---|
356 | 309 | setup_arch_string(); |
---|
357 | | - ipl_store_parameters(); |
---|
358 | 310 | setup_boot_command_line(); |
---|
359 | 311 | detect_diag9c(); |
---|
360 | | - detect_diag44(); |
---|
361 | 312 | detect_machine_facilities(); |
---|
362 | 313 | save_vector_registers(); |
---|
363 | 314 | setup_topology(); |
---|
364 | 315 | sclp_early_detect(); |
---|
| 316 | + setup_control_registers(); |
---|
| 317 | + setup_access_registers(); |
---|
365 | 318 | lockdep_on(); |
---|
366 | 319 | } |
---|