11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) 31da177e4SLinus Torvalds * Licensed under the GPL 41da177e4SLinus Torvalds */ 51da177e4SLinus Torvalds 61da177e4SLinus Torvalds #include "linux/config.h" 71da177e4SLinus Torvalds #include "linux/kernel.h" 81da177e4SLinus Torvalds #include "linux/sched.h" 91da177e4SLinus Torvalds #include "linux/notifier.h" 101da177e4SLinus Torvalds #include "linux/mm.h" 111da177e4SLinus Torvalds #include "linux/types.h" 121da177e4SLinus Torvalds #include "linux/tty.h" 131da177e4SLinus Torvalds #include "linux/init.h" 141da177e4SLinus Torvalds #include "linux/bootmem.h" 151da177e4SLinus Torvalds #include "linux/spinlock.h" 161da177e4SLinus Torvalds #include "linux/utsname.h" 171da177e4SLinus Torvalds #include "linux/sysrq.h" 181da177e4SLinus Torvalds #include "linux/seq_file.h" 191da177e4SLinus Torvalds #include "linux/delay.h" 201da177e4SLinus Torvalds #include "linux/module.h" 211da177e4SLinus Torvalds #include "asm/page.h" 221da177e4SLinus Torvalds #include "asm/pgtable.h" 231da177e4SLinus Torvalds #include "asm/ptrace.h" 241da177e4SLinus Torvalds #include "asm/elf.h" 251da177e4SLinus Torvalds #include "asm/user.h" 2616c11163SJeff Dike #include "asm/setup.h" 271da177e4SLinus Torvalds #include "ubd_user.h" 281da177e4SLinus Torvalds #include "asm/current.h" 291da177e4SLinus Torvalds #include "user_util.h" 301da177e4SLinus Torvalds #include "kern_util.h" 311da177e4SLinus Torvalds #include "kern.h" 321da177e4SLinus Torvalds #include "mem_user.h" 331da177e4SLinus Torvalds #include "mem.h" 341da177e4SLinus Torvalds #include "umid.h" 351da177e4SLinus Torvalds #include "initrd.h" 361da177e4SLinus Torvalds #include "init.h" 371da177e4SLinus Torvalds #include "os.h" 381da177e4SLinus Torvalds #include "choose-mode.h" 391da177e4SLinus Torvalds #include "mode_kern.h" 401da177e4SLinus Torvalds #include "mode.h" 41cb66504dSPaolo 'Blaisorblade' Giarrusso #ifdef UML_CONFIG_MODE_SKAS 42cb66504dSPaolo 'Blaisorblade' Giarrusso #include "skas.h" 43cb66504dSPaolo 'Blaisorblade' Giarrusso #endif 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds #define DEFAULT_COMMAND_LINE "root=98:0" 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds /* Changed in linux_main and setup_arch, which run before SMP is started */ 4816c11163SJeff Dike static char command_line[COMMAND_LINE_SIZE] = { 0 }; 491da177e4SLinus Torvalds 5016c11163SJeff Dike static void add_arg(char *arg) 511da177e4SLinus Torvalds { 521da177e4SLinus Torvalds if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { 531da177e4SLinus Torvalds printf("add_arg: Too many command line arguments!\n"); 541da177e4SLinus Torvalds exit(1); 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds if(strlen(command_line) > 0) 571da177e4SLinus Torvalds strcat(command_line, " "); 581da177e4SLinus Torvalds strcat(command_line, arg); 591da177e4SLinus Torvalds } 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds struct cpuinfo_um boot_cpu_data = { 621da177e4SLinus Torvalds .loops_per_jiffy = 0, 631da177e4SLinus Torvalds .ipi_pipe = { -1, -1 } 641da177e4SLinus Torvalds }; 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds unsigned long thread_saved_pc(struct task_struct *task) 671da177e4SLinus Torvalds { 681da177e4SLinus Torvalds return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, 691da177e4SLinus Torvalds task))); 701da177e4SLinus Torvalds } 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds static int show_cpuinfo(struct seq_file *m, void *v) 731da177e4SLinus Torvalds { 741da177e4SLinus Torvalds int index = 0; 751da177e4SLinus Torvalds 761da177e4SLinus Torvalds #ifdef CONFIG_SMP 771da177e4SLinus Torvalds index = (struct cpuinfo_um *) v - cpu_data; 781da177e4SLinus Torvalds if (!cpu_online(index)) 791da177e4SLinus Torvalds return 0; 801da177e4SLinus Torvalds #endif 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds seq_printf(m, "processor\t: %d\n", index); 831da177e4SLinus Torvalds seq_printf(m, "vendor_id\t: User Mode Linux\n"); 841da177e4SLinus Torvalds seq_printf(m, "model name\t: UML\n"); 851da177e4SLinus Torvalds seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas")); 861da177e4SLinus Torvalds seq_printf(m, "host\t\t: %s\n", host_info); 871da177e4SLinus Torvalds seq_printf(m, "bogomips\t: %lu.%02lu\n\n", 881da177e4SLinus Torvalds loops_per_jiffy/(500000/HZ), 891da177e4SLinus Torvalds (loops_per_jiffy/(5000/HZ)) % 100); 901da177e4SLinus Torvalds 911da177e4SLinus Torvalds return(0); 921da177e4SLinus Torvalds } 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds static void *c_start(struct seq_file *m, loff_t *pos) 951da177e4SLinus Torvalds { 961da177e4SLinus Torvalds return *pos < NR_CPUS ? cpu_data + *pos : NULL; 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds static void *c_next(struct seq_file *m, void *v, loff_t *pos) 1001da177e4SLinus Torvalds { 1011da177e4SLinus Torvalds ++*pos; 1021da177e4SLinus Torvalds return c_start(m, pos); 1031da177e4SLinus Torvalds } 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds static void c_stop(struct seq_file *m, void *v) 1061da177e4SLinus Torvalds { 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds struct seq_operations cpuinfo_op = { 1101da177e4SLinus Torvalds .start = c_start, 1111da177e4SLinus Torvalds .next = c_next, 1121da177e4SLinus Torvalds .stop = c_stop, 1131da177e4SLinus Torvalds .show = show_cpuinfo, 1141da177e4SLinus Torvalds }; 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds /* Set in linux_main */ 1171da177e4SLinus Torvalds unsigned long host_task_size; 1181da177e4SLinus Torvalds unsigned long task_size; 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds unsigned long uml_start; 1211da177e4SLinus Torvalds 1221da177e4SLinus Torvalds /* Set in early boot */ 1231da177e4SLinus Torvalds unsigned long uml_physmem; 1241da177e4SLinus Torvalds unsigned long uml_reserved; 1251da177e4SLinus Torvalds unsigned long start_vm; 1261da177e4SLinus Torvalds unsigned long end_vm; 1271da177e4SLinus Torvalds int ncpus = 1; 1281da177e4SLinus Torvalds 12902215759SPaolo 'Blaisorblade' Giarrusso #ifdef CONFIG_CMDLINE_ON_HOST 1301da177e4SLinus Torvalds /* Pointer set in linux_main, the array itself is private to each thread, 1311da177e4SLinus Torvalds * and changed at address space creation time so this poses no concurrency 1321da177e4SLinus Torvalds * problems. 1331da177e4SLinus Torvalds */ 1341da177e4SLinus Torvalds static char *argv1_begin = NULL; 1351da177e4SLinus Torvalds static char *argv1_end = NULL; 1361da177e4SLinus Torvalds #endif 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds /* Set in early boot */ 1391da177e4SLinus Torvalds static int have_root __initdata = 0; 140ae173816SJeff Dike long long physmem_size = 32 * 1024 * 1024; 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds void set_cmdline(char *cmd) 1431da177e4SLinus Torvalds { 14402215759SPaolo 'Blaisorblade' Giarrusso #ifdef CONFIG_CMDLINE_ON_HOST 1451da177e4SLinus Torvalds char *umid, *ptr; 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds if(CHOOSE_MODE(honeypot, 0)) return; 1481da177e4SLinus Torvalds 1497eebe8a9SJeff Dike umid = get_umid(); 1507eebe8a9SJeff Dike if(*umid != '\0'){ 1511da177e4SLinus Torvalds snprintf(argv1_begin, 1521da177e4SLinus Torvalds (argv1_end - argv1_begin) * sizeof(*ptr), 1531da177e4SLinus Torvalds "(%s) ", umid); 1541da177e4SLinus Torvalds ptr = &argv1_begin[strlen(argv1_begin)]; 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds else ptr = argv1_begin; 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd); 1591da177e4SLinus Torvalds memset(argv1_begin + strlen(argv1_begin), '\0', 1601da177e4SLinus Torvalds argv1_end - argv1_begin - strlen(argv1_begin)); 1611da177e4SLinus Torvalds #endif 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds static char *usage_string = 1651da177e4SLinus Torvalds "User Mode Linux v%s\n" 1661da177e4SLinus Torvalds " available at http://user-mode-linux.sourceforge.net/\n\n"; 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds static int __init uml_version_setup(char *line, int *add) 1691da177e4SLinus Torvalds { 1701da177e4SLinus Torvalds printf("%s\n", system_utsname.release); 1711da177e4SLinus Torvalds exit(0); 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds return 0; 1741da177e4SLinus Torvalds } 1751da177e4SLinus Torvalds 1761da177e4SLinus Torvalds __uml_setup("--version", uml_version_setup, 1771da177e4SLinus Torvalds "--version\n" 1781da177e4SLinus Torvalds " Prints the version number of the kernel.\n\n" 1791da177e4SLinus Torvalds ); 1801da177e4SLinus Torvalds 1811da177e4SLinus Torvalds static int __init uml_root_setup(char *line, int *add) 1821da177e4SLinus Torvalds { 1831da177e4SLinus Torvalds have_root = 1; 1841da177e4SLinus Torvalds return 0; 1851da177e4SLinus Torvalds } 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds __uml_setup("root=", uml_root_setup, 1881da177e4SLinus Torvalds "root=<file containing the root fs>\n" 1891da177e4SLinus Torvalds " This is actually used by the generic kernel in exactly the same\n" 1901da177e4SLinus Torvalds " way as in any other kernel. If you configure a number of block\n" 1911da177e4SLinus Torvalds " devices and want to boot off something other than ubd0, you \n" 1921da177e4SLinus Torvalds " would use something like:\n" 1931da177e4SLinus Torvalds " root=/dev/ubd5\n\n" 1941da177e4SLinus Torvalds ); 1951da177e4SLinus Torvalds 1961da177e4SLinus Torvalds #ifdef CONFIG_SMP 1971da177e4SLinus Torvalds static int __init uml_ncpus_setup(char *line, int *add) 1981da177e4SLinus Torvalds { 1991da177e4SLinus Torvalds if (!sscanf(line, "%d", &ncpus)) { 2001da177e4SLinus Torvalds printf("Couldn't parse [%s]\n", line); 2011da177e4SLinus Torvalds return -1; 2021da177e4SLinus Torvalds } 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds return 0; 2051da177e4SLinus Torvalds } 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds __uml_setup("ncpus=", uml_ncpus_setup, 2081da177e4SLinus Torvalds "ncpus=<# of desired CPUs>\n" 2091da177e4SLinus Torvalds " This tells an SMP kernel how many virtual processors to start.\n\n" 2101da177e4SLinus Torvalds ); 2111da177e4SLinus Torvalds #endif 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds static int force_tt = 0; 2141da177e4SLinus Torvalds 2151da177e4SLinus Torvalds #if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS) 2161da177e4SLinus Torvalds #define DEFAULT_TT 0 2171da177e4SLinus Torvalds 2181da177e4SLinus Torvalds static int __init mode_tt_setup(char *line, int *add) 2191da177e4SLinus Torvalds { 2201da177e4SLinus Torvalds force_tt = 1; 2211da177e4SLinus Torvalds return(0); 2221da177e4SLinus Torvalds } 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds #else 2251da177e4SLinus Torvalds #ifdef CONFIG_MODE_SKAS 2261da177e4SLinus Torvalds 2271da177e4SLinus Torvalds #define DEFAULT_TT 0 2281da177e4SLinus Torvalds 2291da177e4SLinus Torvalds static int __init mode_tt_setup(char *line, int *add) 2301da177e4SLinus Torvalds { 2311da177e4SLinus Torvalds printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); 2321da177e4SLinus Torvalds return(0); 2331da177e4SLinus Torvalds } 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds #else 2361da177e4SLinus Torvalds #ifdef CONFIG_MODE_TT 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds #define DEFAULT_TT 1 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds static int __init mode_tt_setup(char *line, int *add) 2411da177e4SLinus Torvalds { 2421da177e4SLinus Torvalds printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); 2431da177e4SLinus Torvalds return(0); 2441da177e4SLinus Torvalds } 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds #else 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds #error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled 2491da177e4SLinus Torvalds 2501da177e4SLinus Torvalds #endif 2511da177e4SLinus Torvalds #endif 2521da177e4SLinus Torvalds #endif 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds __uml_setup("mode=tt", mode_tt_setup, 2551da177e4SLinus Torvalds "mode=tt\n" 2561da177e4SLinus Torvalds " When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n" 2571da177e4SLinus Torvalds " forces UML to run in tt (tracing thread) mode. It is not the default\n" 2581da177e4SLinus Torvalds " because it's slower and less secure than skas mode.\n\n" 2591da177e4SLinus Torvalds ); 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds int mode_tt = DEFAULT_TT; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds static int __init Usage(char *line, int *add) 2641da177e4SLinus Torvalds { 2651da177e4SLinus Torvalds const char **p; 2661da177e4SLinus Torvalds 2671da177e4SLinus Torvalds printf(usage_string, system_utsname.release); 2681da177e4SLinus Torvalds p = &__uml_help_start; 2691da177e4SLinus Torvalds while (p < &__uml_help_end) { 2701da177e4SLinus Torvalds printf("%s", *p); 2711da177e4SLinus Torvalds p++; 2721da177e4SLinus Torvalds } 2731da177e4SLinus Torvalds exit(0); 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds return 0; 2761da177e4SLinus Torvalds } 2771da177e4SLinus Torvalds 2781da177e4SLinus Torvalds __uml_setup("--help", Usage, 2791da177e4SLinus Torvalds "--help\n" 2801da177e4SLinus Torvalds " Prints this message.\n\n" 2811da177e4SLinus Torvalds ); 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds static int __init uml_checksetup(char *line, int *add) 2841da177e4SLinus Torvalds { 2851da177e4SLinus Torvalds struct uml_param *p; 2861da177e4SLinus Torvalds 2871da177e4SLinus Torvalds p = &__uml_setup_start; 2881da177e4SLinus Torvalds while(p < &__uml_setup_end) { 2891da177e4SLinus Torvalds int n; 2901da177e4SLinus Torvalds 2911da177e4SLinus Torvalds n = strlen(p->str); 2921da177e4SLinus Torvalds if(!strncmp(line, p->str, n)){ 2931da177e4SLinus Torvalds if (p->setup_func(line + n, add)) return 1; 2941da177e4SLinus Torvalds } 2951da177e4SLinus Torvalds p++; 2961da177e4SLinus Torvalds } 2971da177e4SLinus Torvalds return 0; 2981da177e4SLinus Torvalds } 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds static void __init uml_postsetup(void) 3011da177e4SLinus Torvalds { 3021da177e4SLinus Torvalds initcall_t *p; 3031da177e4SLinus Torvalds 3041da177e4SLinus Torvalds p = &__uml_postsetup_start; 3051da177e4SLinus Torvalds while(p < &__uml_postsetup_end){ 3061da177e4SLinus Torvalds (*p)(); 3071da177e4SLinus Torvalds p++; 3081da177e4SLinus Torvalds } 3091da177e4SLinus Torvalds return; 3101da177e4SLinus Torvalds } 3111da177e4SLinus Torvalds 3121da177e4SLinus Torvalds /* Set during early boot */ 3131da177e4SLinus Torvalds unsigned long brk_start; 3141da177e4SLinus Torvalds unsigned long end_iomem; 3151da177e4SLinus Torvalds EXPORT_SYMBOL(end_iomem); 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds #define MIN_VMALLOC (32 * 1024 * 1024) 3181da177e4SLinus Torvalds 3191da177e4SLinus Torvalds int linux_main(int argc, char **argv) 3201da177e4SLinus Torvalds { 3211da177e4SLinus Torvalds unsigned long avail, diff; 3221da177e4SLinus Torvalds unsigned long virtmem_size, max_physmem; 3231da177e4SLinus Torvalds unsigned int i, add; 324cb66504dSPaolo 'Blaisorblade' Giarrusso char * mode; 3251da177e4SLinus Torvalds 3261da177e4SLinus Torvalds for (i = 1; i < argc; i++){ 3271da177e4SLinus Torvalds if((i == 1) && (argv[i][0] == ' ')) continue; 3281da177e4SLinus Torvalds add = 1; 3291da177e4SLinus Torvalds uml_checksetup(argv[i], &add); 3301da177e4SLinus Torvalds if (add) 3311da177e4SLinus Torvalds add_arg(argv[i]); 3321da177e4SLinus Torvalds } 3331da177e4SLinus Torvalds if(have_root == 0) 3341da177e4SLinus Torvalds add_arg(DEFAULT_COMMAND_LINE); 3351da177e4SLinus Torvalds 33660d339f6SGennady Sharapov os_early_checks(); 3378923648cSPaolo 'Blaisorblade' Giarrusso if (force_tt) 3388923648cSPaolo 'Blaisorblade' Giarrusso clear_can_do_skas(); 3391da177e4SLinus Torvalds mode_tt = force_tt ? 1 : !can_do_skas(); 3401da177e4SLinus Torvalds #ifndef CONFIG_MODE_TT 3411da177e4SLinus Torvalds if (mode_tt) { 3421da177e4SLinus Torvalds /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So, 3431da177e4SLinus Torvalds * can_do_skas() returned 0, and the message is correct. */ 3441da177e4SLinus Torvalds printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n"); 3451da177e4SLinus Torvalds exit(1); 3461da177e4SLinus Torvalds } 3471da177e4SLinus Torvalds #endif 348cb66504dSPaolo 'Blaisorblade' Giarrusso 349cb66504dSPaolo 'Blaisorblade' Giarrusso #ifndef CONFIG_MODE_SKAS 350cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "TT"; 351cb66504dSPaolo 'Blaisorblade' Giarrusso #else 352cb66504dSPaolo 'Blaisorblade' Giarrusso /* Show to the user the result of selection */ 353cb66504dSPaolo 'Blaisorblade' Giarrusso if (mode_tt) 354cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "TT"; 355cb66504dSPaolo 'Blaisorblade' Giarrusso else if (proc_mm && ptrace_faultinfo) 356cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "SKAS3"; 357cb66504dSPaolo 'Blaisorblade' Giarrusso else 358cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "SKAS0"; 359cb66504dSPaolo 'Blaisorblade' Giarrusso #endif 360cb66504dSPaolo 'Blaisorblade' Giarrusso 361cb66504dSPaolo 'Blaisorblade' Giarrusso printf("UML running in %s mode\n", mode); 362cb66504dSPaolo 'Blaisorblade' Giarrusso 3631da177e4SLinus Torvalds uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, 3641da177e4SLinus Torvalds &host_task_size, &task_size); 3651da177e4SLinus Torvalds 3661da177e4SLinus Torvalds brk_start = (unsigned long) sbrk(0); 3671da177e4SLinus Torvalds CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); 3681da177e4SLinus Torvalds /* Increase physical memory size for exec-shield users 3691da177e4SLinus Torvalds so they actually get what they asked for. This should 3701da177e4SLinus Torvalds add zero for non-exec shield users */ 3711da177e4SLinus Torvalds 3721da177e4SLinus Torvalds diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); 3731da177e4SLinus Torvalds if(diff > 1024 * 1024){ 3741da177e4SLinus Torvalds printf("Adding %ld bytes to physical memory to account for " 3751da177e4SLinus Torvalds "exec-shield gap\n", diff); 3761da177e4SLinus Torvalds physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); 3771da177e4SLinus Torvalds } 3781da177e4SLinus Torvalds 3791da177e4SLinus Torvalds uml_physmem = uml_start; 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds /* Reserve up to 4M after the current brk */ 3821da177e4SLinus Torvalds uml_reserved = ROUND_4M(brk_start) + (1 << 22); 3831da177e4SLinus Torvalds 3841da177e4SLinus Torvalds setup_machinename(system_utsname.machine); 3851da177e4SLinus Torvalds 38602215759SPaolo 'Blaisorblade' Giarrusso #ifdef CONFIG_CMDLINE_ON_HOST 3871da177e4SLinus Torvalds argv1_begin = argv[1]; 3881da177e4SLinus Torvalds argv1_end = &argv[1][strlen(argv[1])]; 3891da177e4SLinus Torvalds #endif 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds highmem = 0; 3921da177e4SLinus Torvalds iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; 3931da177e4SLinus Torvalds max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; 3941da177e4SLinus Torvalds 3951da177e4SLinus Torvalds /* Zones have to begin on a 1 << MAX_ORDER page boundary, 3961da177e4SLinus Torvalds * so this makes sure that's true for highmem 3971da177e4SLinus Torvalds */ 3981da177e4SLinus Torvalds max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); 3991da177e4SLinus Torvalds if(physmem_size + iomem_size > max_physmem){ 4001da177e4SLinus Torvalds highmem = physmem_size + iomem_size - max_physmem; 4011da177e4SLinus Torvalds physmem_size -= highmem; 4021da177e4SLinus Torvalds #ifndef CONFIG_HIGHMEM 4031da177e4SLinus Torvalds highmem = 0; 4041da177e4SLinus Torvalds printf("CONFIG_HIGHMEM not enabled - physical memory shrunk " 405ae173816SJeff Dike "to %lu bytes\n", physmem_size); 4061da177e4SLinus Torvalds #endif 4071da177e4SLinus Torvalds } 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds high_physmem = uml_physmem + physmem_size; 4101da177e4SLinus Torvalds end_iomem = high_physmem + iomem_size; 4111da177e4SLinus Torvalds high_memory = (void *) end_iomem; 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvalds start_vm = VMALLOC_START; 4141da177e4SLinus Torvalds 4151da177e4SLinus Torvalds setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); 4161da177e4SLinus Torvalds if(init_maps(physmem_size, iomem_size, highmem)){ 417ae173816SJeff Dike printf("Failed to allocate mem_map for %lu bytes of physical " 418ae173816SJeff Dike "memory and %lu bytes of highmem\n", physmem_size, 4191da177e4SLinus Torvalds highmem); 4201da177e4SLinus Torvalds exit(1); 4211da177e4SLinus Torvalds } 4221da177e4SLinus Torvalds 4231da177e4SLinus Torvalds virtmem_size = physmem_size; 4241da177e4SLinus Torvalds avail = get_kmem_end() - start_vm; 4251da177e4SLinus Torvalds if(physmem_size > avail) virtmem_size = avail; 4261da177e4SLinus Torvalds end_vm = start_vm + virtmem_size; 4271da177e4SLinus Torvalds 4281da177e4SLinus Torvalds if(virtmem_size < physmem_size) 429ae173816SJeff Dike printf("Kernel virtual memory size shrunk to %lu bytes\n", 4301da177e4SLinus Torvalds virtmem_size); 4311da177e4SLinus Torvalds 4321da177e4SLinus Torvalds uml_postsetup(); 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds task_protections((unsigned long) &init_thread_info); 4351da177e4SLinus Torvalds os_flush_stdout(); 4361da177e4SLinus Torvalds 4371da177e4SLinus Torvalds return(CHOOSE_MODE(start_uml_tt(), start_uml_skas())); 4381da177e4SLinus Torvalds } 4391da177e4SLinus Torvalds 4401da177e4SLinus Torvalds extern int uml_exitcode; 4411da177e4SLinus Torvalds 4421da177e4SLinus Torvalds static int panic_exit(struct notifier_block *self, unsigned long unused1, 4431da177e4SLinus Torvalds void *unused2) 4441da177e4SLinus Torvalds { 4451da177e4SLinus Torvalds bust_spinlocks(1); 4461da177e4SLinus Torvalds show_regs(&(current->thread.regs)); 4471da177e4SLinus Torvalds bust_spinlocks(0); 4481da177e4SLinus Torvalds uml_exitcode = 1; 4491da177e4SLinus Torvalds machine_halt(); 4501da177e4SLinus Torvalds return(0); 4511da177e4SLinus Torvalds } 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds static struct notifier_block panic_exit_notifier = { 4541da177e4SLinus Torvalds .notifier_call = panic_exit, 4551da177e4SLinus Torvalds .next = NULL, 4561da177e4SLinus Torvalds .priority = 0 4571da177e4SLinus Torvalds }; 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds void __init setup_arch(char **cmdline_p) 4601da177e4SLinus Torvalds { 4611da177e4SLinus Torvalds notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); 4621da177e4SLinus Torvalds paging_init(); 4631da177e4SLinus Torvalds strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); 4641da177e4SLinus Torvalds *cmdline_p = command_line; 4651da177e4SLinus Torvalds setup_hostinfo(); 4661da177e4SLinus Torvalds } 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds void __init check_bugs(void) 4691da177e4SLinus Torvalds { 4701da177e4SLinus Torvalds arch_check_bugs(); 4711da177e4SLinus Torvalds check_sigio(); 4721da177e4SLinus Torvalds check_devanon(); 4731da177e4SLinus Torvalds } 4741da177e4SLinus Torvalds 4751da177e4SLinus Torvalds void apply_alternatives(void *start, void *end) 4761da177e4SLinus Torvalds { 4771da177e4SLinus Torvalds } 478