1 /* 2 * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) 3 * Licensed under the GPL 4 */ 5 6 #include "linux/kernel.h" 7 #include "linux/sched.h" 8 #include "linux/notifier.h" 9 #include "linux/mm.h" 10 #include "linux/types.h" 11 #include "linux/tty.h" 12 #include "linux/init.h" 13 #include "linux/bootmem.h" 14 #include "linux/spinlock.h" 15 #include "linux/utsname.h" 16 #include "linux/sysrq.h" 17 #include "linux/seq_file.h" 18 #include "linux/delay.h" 19 #include "linux/module.h" 20 #include "asm/page.h" 21 #include "asm/pgtable.h" 22 #include "asm/ptrace.h" 23 #include "asm/elf.h" 24 #include "asm/user.h" 25 #include "asm/setup.h" 26 #include "ubd_user.h" 27 #include "asm/current.h" 28 #include "user_util.h" 29 #include "kern_util.h" 30 #include "kern.h" 31 #include "mem_user.h" 32 #include "mem.h" 33 #include "initrd.h" 34 #include "init.h" 35 #include "os.h" 36 #include "choose-mode.h" 37 #include "mode_kern.h" 38 #include "mode.h" 39 #ifdef UML_CONFIG_MODE_SKAS 40 #include "skas.h" 41 #endif 42 43 #define DEFAULT_COMMAND_LINE "root=98:0" 44 45 /* Changed in linux_main and setup_arch, which run before SMP is started */ 46 static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 }; 47 48 static void __init add_arg(char *arg) 49 { 50 if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { 51 printf("add_arg: Too many command line arguments!\n"); 52 exit(1); 53 } 54 if(strlen(command_line) > 0) 55 strcat(command_line, " "); 56 strcat(command_line, arg); 57 } 58 59 struct cpuinfo_um boot_cpu_data = { 60 .loops_per_jiffy = 0, 61 .ipi_pipe = { -1, -1 } 62 }; 63 64 unsigned long thread_saved_pc(struct task_struct *task) 65 { 66 return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, 67 task))); 68 } 69 70 static int show_cpuinfo(struct seq_file *m, void *v) 71 { 72 int index = 0; 73 74 #ifdef CONFIG_SMP 75 index = (struct cpuinfo_um *) v - cpu_data; 76 if (!cpu_online(index)) 77 return 0; 78 #endif 79 80 seq_printf(m, "processor\t: %d\n", index); 81 seq_printf(m, "vendor_id\t: User Mode Linux\n"); 82 seq_printf(m, "model name\t: UML\n"); 83 seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas")); 84 seq_printf(m, "host\t\t: %s\n", host_info); 85 seq_printf(m, "bogomips\t: %lu.%02lu\n\n", 86 loops_per_jiffy/(500000/HZ), 87 (loops_per_jiffy/(5000/HZ)) % 100); 88 89 return(0); 90 } 91 92 static void *c_start(struct seq_file *m, loff_t *pos) 93 { 94 return *pos < NR_CPUS ? cpu_data + *pos : NULL; 95 } 96 97 static void *c_next(struct seq_file *m, void *v, loff_t *pos) 98 { 99 ++*pos; 100 return c_start(m, pos); 101 } 102 103 static void c_stop(struct seq_file *m, void *v) 104 { 105 } 106 107 const struct seq_operations cpuinfo_op = { 108 .start = c_start, 109 .next = c_next, 110 .stop = c_stop, 111 .show = show_cpuinfo, 112 }; 113 114 /* Set in linux_main */ 115 unsigned long host_task_size; 116 unsigned long task_size; 117 118 unsigned long uml_start; 119 120 /* Set in early boot */ 121 unsigned long uml_physmem; 122 unsigned long uml_reserved; 123 unsigned long start_vm; 124 unsigned long end_vm; 125 int ncpus = 1; 126 127 #ifdef CONFIG_CMDLINE_ON_HOST 128 /* Pointer set in linux_main, the array itself is private to each thread, 129 * and changed at address space creation time so this poses no concurrency 130 * problems. 131 */ 132 static char *argv1_begin = NULL; 133 static char *argv1_end = NULL; 134 #endif 135 136 /* Set in early boot */ 137 static int have_root __initdata = 0; 138 long long physmem_size = 32 * 1024 * 1024; 139 140 void set_cmdline(char *cmd) 141 { 142 #ifdef CONFIG_CMDLINE_ON_HOST 143 char *umid, *ptr; 144 145 if(CHOOSE_MODE(honeypot, 0)) return; 146 147 umid = get_umid(); 148 if(*umid != '\0'){ 149 snprintf(argv1_begin, 150 (argv1_end - argv1_begin) * sizeof(*ptr), 151 "(%s) ", umid); 152 ptr = &argv1_begin[strlen(argv1_begin)]; 153 } 154 else ptr = argv1_begin; 155 156 snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd); 157 memset(argv1_begin + strlen(argv1_begin), '\0', 158 argv1_end - argv1_begin - strlen(argv1_begin)); 159 #endif 160 } 161 162 static char *usage_string = 163 "User Mode Linux v%s\n" 164 " available at http://user-mode-linux.sourceforge.net/\n\n"; 165 166 static int __init uml_version_setup(char *line, int *add) 167 { 168 printf("%s\n", init_utsname()->release); 169 exit(0); 170 171 return 0; 172 } 173 174 __uml_setup("--version", uml_version_setup, 175 "--version\n" 176 " Prints the version number of the kernel.\n\n" 177 ); 178 179 static int __init uml_root_setup(char *line, int *add) 180 { 181 have_root = 1; 182 return 0; 183 } 184 185 __uml_setup("root=", uml_root_setup, 186 "root=<file containing the root fs>\n" 187 " This is actually used by the generic kernel in exactly the same\n" 188 " way as in any other kernel. If you configure a number of block\n" 189 " devices and want to boot off something other than ubd0, you \n" 190 " would use something like:\n" 191 " root=/dev/ubd5\n\n" 192 ); 193 194 #ifndef CONFIG_MODE_TT 195 196 static int __init no_skas_debug_setup(char *line, int *add) 197 { 198 printf("'debug' is not necessary to gdb UML in skas mode - run \n"); 199 printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n"); 200 printf("doesn't work as expected\n"); 201 202 return 0; 203 } 204 205 __uml_setup("debug", no_skas_debug_setup, 206 "debug\n" 207 " this flag is not needed to run gdb on UML in skas mode\n\n" 208 ); 209 210 #endif 211 212 #ifdef CONFIG_SMP 213 static int __init uml_ncpus_setup(char *line, int *add) 214 { 215 if (!sscanf(line, "%d", &ncpus)) { 216 printf("Couldn't parse [%s]\n", line); 217 return -1; 218 } 219 220 return 0; 221 } 222 223 __uml_setup("ncpus=", uml_ncpus_setup, 224 "ncpus=<# of desired CPUs>\n" 225 " This tells an SMP kernel how many virtual processors to start.\n\n" 226 ); 227 #endif 228 229 static int force_tt = 0; 230 231 #if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS) 232 #define DEFAULT_TT 0 233 234 static int __init mode_tt_setup(char *line, int *add) 235 { 236 force_tt = 1; 237 return(0); 238 } 239 240 #else 241 #ifdef CONFIG_MODE_SKAS 242 243 #define DEFAULT_TT 0 244 245 static int __init mode_tt_setup(char *line, int *add) 246 { 247 printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); 248 return(0); 249 } 250 251 #else 252 #ifdef CONFIG_MODE_TT 253 254 #define DEFAULT_TT 1 255 256 static int __init mode_tt_setup(char *line, int *add) 257 { 258 printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); 259 return(0); 260 } 261 262 #endif 263 #endif 264 #endif 265 266 __uml_setup("mode=tt", mode_tt_setup, 267 "mode=tt\n" 268 " When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n" 269 " forces UML to run in tt (tracing thread) mode. It is not the default\n" 270 " because it's slower and less secure than skas mode.\n\n" 271 ); 272 273 int mode_tt = DEFAULT_TT; 274 275 static int __init Usage(char *line, int *add) 276 { 277 const char **p; 278 279 printf(usage_string, init_utsname()->release); 280 p = &__uml_help_start; 281 while (p < &__uml_help_end) { 282 printf("%s", *p); 283 p++; 284 } 285 exit(0); 286 287 return 0; 288 } 289 290 __uml_setup("--help", Usage, 291 "--help\n" 292 " Prints this message.\n\n" 293 ); 294 295 static int __init uml_checksetup(char *line, int *add) 296 { 297 struct uml_param *p; 298 299 p = &__uml_setup_start; 300 while(p < &__uml_setup_end) { 301 int n; 302 303 n = strlen(p->str); 304 if(!strncmp(line, p->str, n)){ 305 if (p->setup_func(line + n, add)) return 1; 306 } 307 p++; 308 } 309 return 0; 310 } 311 312 static void __init uml_postsetup(void) 313 { 314 initcall_t *p; 315 316 p = &__uml_postsetup_start; 317 while(p < &__uml_postsetup_end){ 318 (*p)(); 319 p++; 320 } 321 return; 322 } 323 324 /* Set during early boot */ 325 unsigned long brk_start; 326 unsigned long end_iomem; 327 EXPORT_SYMBOL(end_iomem); 328 329 #define MIN_VMALLOC (32 * 1024 * 1024) 330 331 extern char __binary_start; 332 333 int __init linux_main(int argc, char **argv) 334 { 335 unsigned long avail, diff; 336 unsigned long virtmem_size, max_physmem; 337 unsigned int i, add; 338 char * mode; 339 340 for (i = 1; i < argc; i++){ 341 if((i == 1) && (argv[i][0] == ' ')) continue; 342 add = 1; 343 uml_checksetup(argv[i], &add); 344 if (add) 345 add_arg(argv[i]); 346 } 347 if(have_root == 0) 348 add_arg(DEFAULT_COMMAND_LINE); 349 350 os_early_checks(); 351 if (force_tt) 352 clear_can_do_skas(); 353 mode_tt = force_tt ? 1 : !can_do_skas(); 354 #ifndef CONFIG_MODE_TT 355 if (mode_tt) { 356 /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So, 357 * can_do_skas() returned 0, and the message is correct. */ 358 printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n"); 359 exit(1); 360 } 361 #endif 362 363 #ifndef CONFIG_MODE_SKAS 364 mode = "TT"; 365 #else 366 /* Show to the user the result of selection */ 367 if (mode_tt) 368 mode = "TT"; 369 else if (proc_mm && ptrace_faultinfo) 370 mode = "SKAS3"; 371 else 372 mode = "SKAS0"; 373 #endif 374 375 printf("UML running in %s mode\n", mode); 376 377 uml_start = (unsigned long) &__binary_start; 378 host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt, 379 set_task_sizes_skas, &task_size); 380 381 /* 382 * Setting up handlers to 'sig_info' struct 383 */ 384 os_fill_handlinfo(handlinfo_kern); 385 386 brk_start = (unsigned long) sbrk(0); 387 CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); 388 /* Increase physical memory size for exec-shield users 389 so they actually get what they asked for. This should 390 add zero for non-exec shield users */ 391 392 diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); 393 if(diff > 1024 * 1024){ 394 printf("Adding %ld bytes to physical memory to account for " 395 "exec-shield gap\n", diff); 396 physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); 397 } 398 399 uml_physmem = uml_start & PAGE_MASK; 400 401 /* Reserve up to 4M after the current brk */ 402 uml_reserved = ROUND_4M(brk_start) + (1 << 22); 403 404 setup_machinename(init_utsname()->machine); 405 406 #ifdef CONFIG_CMDLINE_ON_HOST 407 argv1_begin = argv[1]; 408 argv1_end = &argv[1][strlen(argv[1])]; 409 #endif 410 411 highmem = 0; 412 iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; 413 max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; 414 415 /* Zones have to begin on a 1 << MAX_ORDER page boundary, 416 * so this makes sure that's true for highmem 417 */ 418 max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); 419 if(physmem_size + iomem_size > max_physmem){ 420 highmem = physmem_size + iomem_size - max_physmem; 421 physmem_size -= highmem; 422 #ifndef CONFIG_HIGHMEM 423 highmem = 0; 424 printf("CONFIG_HIGHMEM not enabled - physical memory shrunk " 425 "to %Lu bytes\n", physmem_size); 426 #endif 427 } 428 429 high_physmem = uml_physmem + physmem_size; 430 end_iomem = high_physmem + iomem_size; 431 high_memory = (void *) end_iomem; 432 433 start_vm = VMALLOC_START; 434 435 setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); 436 if(init_maps(physmem_size, iomem_size, highmem)){ 437 printf("Failed to allocate mem_map for %Lu bytes of physical " 438 "memory and %Lu bytes of highmem\n", physmem_size, 439 highmem); 440 exit(1); 441 } 442 443 virtmem_size = physmem_size; 444 avail = get_kmem_end() - start_vm; 445 if(physmem_size > avail) virtmem_size = avail; 446 end_vm = start_vm + virtmem_size; 447 448 if(virtmem_size < physmem_size) 449 printf("Kernel virtual memory size shrunk to %lu bytes\n", 450 virtmem_size); 451 452 uml_postsetup(); 453 454 task_protections((unsigned long) &init_thread_info); 455 os_flush_stdout(); 456 457 return(CHOOSE_MODE(start_uml_tt(), start_uml_skas())); 458 } 459 460 extern int uml_exitcode; 461 462 static int panic_exit(struct notifier_block *self, unsigned long unused1, 463 void *unused2) 464 { 465 bust_spinlocks(1); 466 show_regs(&(current->thread.regs)); 467 bust_spinlocks(0); 468 uml_exitcode = 1; 469 machine_halt(); 470 return(0); 471 } 472 473 static struct notifier_block panic_exit_notifier = { 474 .notifier_call = panic_exit, 475 .next = NULL, 476 .priority = 0 477 }; 478 479 void __init setup_arch(char **cmdline_p) 480 { 481 atomic_notifier_chain_register(&panic_notifier_list, 482 &panic_exit_notifier); 483 paging_init(); 484 strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); 485 *cmdline_p = command_line; 486 setup_hostinfo(); 487 } 488 489 void __init check_bugs(void) 490 { 491 arch_check_bugs(); 492 os_check_bugs(); 493 } 494 495 void apply_alternatives(struct alt_instr *start, struct alt_instr *end) 496 { 497 } 498 499 #ifdef CONFIG_SMP 500 void alternatives_smp_module_add(struct module *mod, char *name, 501 void *locks, void *locks_end, 502 void *text, void *text_end) 503 { 504 } 505 506 void alternatives_smp_module_del(struct module *mod) 507 { 508 } 509 #endif 510