um_arch.c 12 KB

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