1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 */ 5 6 #include <linux/cpu.h> 7 #include <linux/delay.h> 8 #include <linux/init.h> 9 #include <linux/mm.h> 10 #include <linux/ctype.h> 11 #include <linux/module.h> 12 #include <linux/panic_notifier.h> 13 #include <linux/seq_file.h> 14 #include <linux/string.h> 15 #include <linux/utsname.h> 16 #include <linux/sched.h> 17 #include <linux/sched/task.h> 18 #include <linux/kmsg_dump.h> 19 #include <linux/suspend.h> 20 #include <linux/random.h> 21 22 #include <asm/processor.h> 23 #include <asm/cpufeature.h> 24 #include <asm/sections.h> 25 #include <asm/setup.h> 26 #include <as-layout.h> 27 #include <arch.h> 28 #include <init.h> 29 #include <kern.h> 30 #include <kern_util.h> 31 #include <mem_user.h> 32 #include <os.h> 33 34 #include "um_arch.h" 35 36 #define DEFAULT_COMMAND_LINE_ROOT "root=98:0" 37 #define DEFAULT_COMMAND_LINE_CONSOLE "console=tty0" 38 39 /* Changed in add_arg and setup_arch, which run before SMP is started */ 40 static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 }; 41 42 static void __init add_arg(char *arg) 43 { 44 if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { 45 os_warn("add_arg: Too many command line arguments!\n"); 46 exit(1); 47 } 48 if (strlen(command_line) > 0) 49 strcat(command_line, " "); 50 strcat(command_line, arg); 51 } 52 53 /* 54 * These fields are initialized at boot time and not changed. 55 * XXX This structure is used only in the non-SMP case. Maybe this 56 * should be moved to smp.c. 57 */ 58 struct cpuinfo_um boot_cpu_data = { 59 .loops_per_jiffy = 0, 60 .ipi_pipe = { -1, -1 }, 61 .cache_alignment = L1_CACHE_BYTES, 62 .x86_capability = { 0 } 63 }; 64 65 EXPORT_SYMBOL(boot_cpu_data); 66 67 union thread_union cpu0_irqstack 68 __section(".data..init_irqstack") = 69 { .thread_info = INIT_THREAD_INFO(init_task) }; 70 71 /* Changed in setup_arch, which is called in early boot */ 72 static char host_info[(__NEW_UTS_LEN + 1) * 5]; 73 74 static int show_cpuinfo(struct seq_file *m, void *v) 75 { 76 int i = 0; 77 78 seq_printf(m, "processor\t: %d\n", i); 79 seq_printf(m, "vendor_id\t: User Mode Linux\n"); 80 seq_printf(m, "model name\t: UML\n"); 81 seq_printf(m, "mode\t\t: skas\n"); 82 seq_printf(m, "host\t\t: %s\n", host_info); 83 seq_printf(m, "fpu\t\t: %s\n", cpu_has(&boot_cpu_data, X86_FEATURE_FPU) ? "yes" : "no"); 84 seq_printf(m, "flags\t\t:"); 85 for (i = 0; i < 32*NCAPINTS; i++) 86 if (cpu_has(&boot_cpu_data, i) && (x86_cap_flags[i] != NULL)) 87 seq_printf(m, " %s", x86_cap_flags[i]); 88 seq_printf(m, "\n"); 89 seq_printf(m, "cache_alignment\t: %d\n", boot_cpu_data.cache_alignment); 90 seq_printf(m, "bogomips\t: %lu.%02lu\n", 91 loops_per_jiffy/(500000/HZ), 92 (loops_per_jiffy/(5000/HZ)) % 100); 93 94 95 return 0; 96 } 97 98 static void *c_start(struct seq_file *m, loff_t *pos) 99 { 100 return *pos < nr_cpu_ids ? &boot_cpu_data + *pos : NULL; 101 } 102 103 static void *c_next(struct seq_file *m, void *v, loff_t *pos) 104 { 105 ++*pos; 106 return c_start(m, pos); 107 } 108 109 static void c_stop(struct seq_file *m, void *v) 110 { 111 } 112 113 const struct seq_operations cpuinfo_op = { 114 .start = c_start, 115 .next = c_next, 116 .stop = c_stop, 117 .show = show_cpuinfo, 118 }; 119 120 /* Set in linux_main */ 121 unsigned long uml_physmem; 122 EXPORT_SYMBOL(uml_physmem); 123 124 unsigned long uml_reserved; /* Also modified in mem_init */ 125 unsigned long start_vm; 126 unsigned long end_vm; 127 128 /* Set in uml_ncpus_setup */ 129 int ncpus = 1; 130 131 /* Set in early boot */ 132 static int have_root __initdata; 133 static int have_console __initdata; 134 135 /* Set in uml_mem_setup and modified in linux_main */ 136 long long physmem_size = 64 * 1024 * 1024; 137 EXPORT_SYMBOL(physmem_size); 138 139 static const char *usage_string = 140 "User Mode Linux v%s\n" 141 " available at http://user-mode-linux.sourceforge.net/\n\n"; 142 143 static int __init uml_version_setup(char *line, int *add) 144 { 145 /* Explicitly use printf() to show version in stdout */ 146 printf("%s\n", init_utsname()->release); 147 exit(0); 148 149 return 0; 150 } 151 152 __uml_setup("--version", uml_version_setup, 153 "--version\n" 154 " Prints the version number of the kernel.\n\n" 155 ); 156 157 static int __init uml_root_setup(char *line, int *add) 158 { 159 have_root = 1; 160 return 0; 161 } 162 163 __uml_setup("root=", uml_root_setup, 164 "root=<file containing the root fs>\n" 165 " This is actually used by the generic kernel in exactly the same\n" 166 " way as in any other kernel. If you configure a number of block\n" 167 " devices and want to boot off something other than ubd0, you \n" 168 " would use something like:\n" 169 " root=/dev/ubd5\n\n" 170 ); 171 172 static int __init no_skas_debug_setup(char *line, int *add) 173 { 174 os_warn("'debug' is not necessary to gdb UML in skas mode - run\n"); 175 os_warn("'gdb linux'\n"); 176 177 return 0; 178 } 179 180 __uml_setup("debug", no_skas_debug_setup, 181 "debug\n" 182 " this flag is not needed to run gdb on UML in skas mode\n\n" 183 ); 184 185 static int __init uml_console_setup(char *line, int *add) 186 { 187 have_console = 1; 188 return 0; 189 } 190 191 __uml_setup("console=", uml_console_setup, 192 "console=<preferred console>\n" 193 " Specify the preferred console output driver\n\n" 194 ); 195 196 static int __init Usage(char *line, int *add) 197 { 198 const char **p; 199 200 printf(usage_string, init_utsname()->release); 201 p = &__uml_help_start; 202 /* Explicitly use printf() to show help in stdout */ 203 while (p < &__uml_help_end) { 204 printf("%s", *p); 205 p++; 206 } 207 exit(0); 208 return 0; 209 } 210 211 __uml_setup("--help", Usage, 212 "--help\n" 213 " Prints this message.\n\n" 214 ); 215 216 static void __init uml_checksetup(char *line, int *add) 217 { 218 struct uml_param *p; 219 220 p = &__uml_setup_start; 221 while (p < &__uml_setup_end) { 222 size_t n; 223 224 n = strlen(p->str); 225 if (!strncmp(line, p->str, n) && p->setup_func(line + n, add)) 226 return; 227 p++; 228 } 229 } 230 231 static void __init uml_postsetup(void) 232 { 233 initcall_t *p; 234 235 p = &__uml_postsetup_start; 236 while (p < &__uml_postsetup_end) { 237 (*p)(); 238 p++; 239 } 240 return; 241 } 242 243 static int panic_exit(struct notifier_block *self, unsigned long unused1, 244 void *unused2) 245 { 246 kmsg_dump(KMSG_DUMP_PANIC); 247 bust_spinlocks(1); 248 bust_spinlocks(0); 249 uml_exitcode = 1; 250 os_dump_core(); 251 252 return NOTIFY_DONE; 253 } 254 255 static struct notifier_block panic_exit_notifier = { 256 .notifier_call = panic_exit, 257 .priority = INT_MAX - 1, /* run as 2nd notifier, won't return */ 258 }; 259 260 void uml_finishsetup(void) 261 { 262 atomic_notifier_chain_register(&panic_notifier_list, 263 &panic_exit_notifier); 264 265 uml_postsetup(); 266 267 new_thread_handler(); 268 } 269 270 /* Set during early boot */ 271 unsigned long stub_start; 272 unsigned long task_size; 273 EXPORT_SYMBOL(task_size); 274 275 unsigned long host_task_size; 276 277 unsigned long brk_start; 278 unsigned long end_iomem; 279 EXPORT_SYMBOL(end_iomem); 280 281 #define MIN_VMALLOC (32 * 1024 * 1024) 282 283 static void parse_host_cpu_flags(char *line) 284 { 285 int i; 286 for (i = 0; i < 32*NCAPINTS; i++) { 287 if ((x86_cap_flags[i] != NULL) && strstr(line, x86_cap_flags[i])) 288 set_cpu_cap(&boot_cpu_data, i); 289 } 290 } 291 static void parse_cache_line(char *line) 292 { 293 long res; 294 char *to_parse = strstr(line, ":"); 295 if (to_parse) { 296 to_parse++; 297 while (*to_parse != 0 && isspace(*to_parse)) { 298 to_parse++; 299 } 300 if (kstrtoul(to_parse, 10, &res) == 0 && is_power_of_2(res)) 301 boot_cpu_data.cache_alignment = res; 302 else 303 boot_cpu_data.cache_alignment = L1_CACHE_BYTES; 304 } 305 } 306 307 int __init linux_main(int argc, char **argv) 308 { 309 unsigned long avail, diff; 310 unsigned long virtmem_size, max_physmem; 311 unsigned long stack; 312 unsigned int i; 313 int add; 314 315 for (i = 1; i < argc; i++) { 316 if ((i == 1) && (argv[i][0] == ' ')) 317 continue; 318 add = 1; 319 uml_checksetup(argv[i], &add); 320 if (add) 321 add_arg(argv[i]); 322 } 323 if (have_root == 0) 324 add_arg(DEFAULT_COMMAND_LINE_ROOT); 325 326 if (have_console == 0) 327 add_arg(DEFAULT_COMMAND_LINE_CONSOLE); 328 329 host_task_size = os_get_top_address(); 330 /* reserve a few pages for the stubs (taking care of data alignment) */ 331 /* align the data portion */ 332 BUILD_BUG_ON(!is_power_of_2(STUB_DATA_PAGES)); 333 stub_start = (host_task_size - 1) & ~(STUB_DATA_PAGES * PAGE_SIZE - 1); 334 /* another page for the code portion */ 335 stub_start -= PAGE_SIZE; 336 host_task_size = stub_start; 337 338 /* 339 * TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps 340 * out 341 */ 342 task_size = host_task_size & PGDIR_MASK; 343 344 /* OS sanity checks that need to happen before the kernel runs */ 345 os_early_checks(); 346 347 get_host_cpu_features(parse_host_cpu_flags, parse_cache_line); 348 349 brk_start = (unsigned long) sbrk(0); 350 351 /* 352 * Increase physical memory size for exec-shield users 353 * so they actually get what they asked for. This should 354 * add zero for non-exec shield users 355 */ 356 357 diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); 358 if (diff > 1024 * 1024) { 359 os_info("Adding %ld bytes to physical memory to account for " 360 "exec-shield gap\n", diff); 361 physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); 362 } 363 364 uml_physmem = (unsigned long) __binary_start & PAGE_MASK; 365 366 /* Reserve up to 4M after the current brk */ 367 uml_reserved = ROUND_4M(brk_start) + (1 << 22); 368 369 setup_machinename(init_utsname()->machine); 370 371 highmem = 0; 372 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; 373 max_physmem = TASK_SIZE - uml_physmem - iomem_size - MIN_VMALLOC; 374 375 /* 376 * Zones have to begin on a 1 << MAX_ORDER page boundary, 377 * so this makes sure that's true for highmem 378 */ 379 max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); 380 if (physmem_size + iomem_size > max_physmem) { 381 highmem = physmem_size + iomem_size - max_physmem; 382 physmem_size -= highmem; 383 } 384 385 high_physmem = uml_physmem + physmem_size; 386 end_iomem = high_physmem + iomem_size; 387 high_memory = (void *) end_iomem; 388 389 start_vm = VMALLOC_START; 390 391 virtmem_size = physmem_size; 392 stack = (unsigned long) argv; 393 stack &= ~(1024 * 1024 - 1); 394 avail = stack - start_vm; 395 if (physmem_size > avail) 396 virtmem_size = avail; 397 end_vm = start_vm + virtmem_size; 398 399 if (virtmem_size < physmem_size) 400 os_info("Kernel virtual memory size shrunk to %lu bytes\n", 401 virtmem_size); 402 403 os_flush_stdout(); 404 405 return start_uml(); 406 } 407 408 int __init __weak read_initrd(void) 409 { 410 return 0; 411 } 412 413 void __init setup_arch(char **cmdline_p) 414 { 415 u8 rng_seed[32]; 416 417 stack_protections((unsigned long) &init_thread_info); 418 setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); 419 mem_total_pages(physmem_size, iomem_size, highmem); 420 uml_dtb_init(); 421 read_initrd(); 422 423 paging_init(); 424 strscpy(boot_command_line, command_line, COMMAND_LINE_SIZE); 425 *cmdline_p = command_line; 426 setup_hostinfo(host_info, sizeof host_info); 427 428 if (os_getrandom(rng_seed, sizeof(rng_seed), 0) == sizeof(rng_seed)) { 429 add_bootloader_randomness(rng_seed, sizeof(rng_seed)); 430 memzero_explicit(rng_seed, sizeof(rng_seed)); 431 } 432 } 433 434 void __init arch_cpu_finalize_init(void) 435 { 436 arch_check_bugs(); 437 os_check_bugs(); 438 } 439 440 void apply_ibt_endbr(s32 *start, s32 *end) 441 { 442 } 443 444 void apply_retpolines(s32 *start, s32 *end) 445 { 446 } 447 448 void apply_returns(s32 *start, s32 *end) 449 { 450 } 451 452 void apply_fineibt(s32 *start_retpoline, s32 *end_retpoline, 453 s32 *start_cfi, s32 *end_cfi) 454 { 455 } 456 457 void apply_alternatives(struct alt_instr *start, struct alt_instr *end) 458 { 459 } 460 461 void *text_poke(void *addr, const void *opcode, size_t len) 462 { 463 /* 464 * In UML, the only reference to this function is in 465 * apply_relocate_add(), which shouldn't ever actually call this 466 * because UML doesn't have live patching. 467 */ 468 WARN_ON(1); 469 470 return memcpy(addr, opcode, len); 471 } 472 473 void text_poke_sync(void) 474 { 475 } 476 477 void uml_pm_wake(void) 478 { 479 pm_system_wakeup(); 480 } 481 482 #ifdef CONFIG_PM_SLEEP 483 static int um_suspend_valid(suspend_state_t state) 484 { 485 return state == PM_SUSPEND_MEM; 486 } 487 488 static int um_suspend_prepare(void) 489 { 490 um_irqs_suspend(); 491 return 0; 492 } 493 494 static int um_suspend_enter(suspend_state_t state) 495 { 496 if (WARN_ON(state != PM_SUSPEND_MEM)) 497 return -EINVAL; 498 499 /* 500 * This is identical to the idle sleep, but we've just 501 * (during suspend) turned off all interrupt sources 502 * except for the ones we want, so now we can only wake 503 * up on something we actually want to wake up on. All 504 * timing has also been suspended. 505 */ 506 um_idle_sleep(); 507 return 0; 508 } 509 510 static void um_suspend_finish(void) 511 { 512 um_irqs_resume(); 513 } 514 515 const struct platform_suspend_ops um_suspend_ops = { 516 .valid = um_suspend_valid, 517 .prepare = um_suspend_prepare, 518 .enter = um_suspend_enter, 519 .finish = um_suspend_finish, 520 }; 521 522 static int init_pm_wake_signal(void) 523 { 524 /* 525 * In external time-travel mode we can't use signals to wake up 526 * since that would mess with the scheduling. We'll have to do 527 * some additional work to support wakeup on virtio devices or 528 * similar, perhaps implementing a fake RTC controller that can 529 * trigger wakeup (and request the appropriate scheduling from 530 * the external scheduler when going to suspend.) 531 */ 532 if (time_travel_mode != TT_MODE_EXTERNAL) 533 register_pm_wake_signal(); 534 535 suspend_set_ops(&um_suspend_ops); 536 537 return 0; 538 } 539 540 late_initcall(init_pm_wake_signal); 541 #endif 542