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/kernel.h" 71da177e4SLinus Torvalds #include "linux/sched.h" 81da177e4SLinus Torvalds #include "linux/notifier.h" 91da177e4SLinus Torvalds #include "linux/mm.h" 101da177e4SLinus Torvalds #include "linux/types.h" 111da177e4SLinus Torvalds #include "linux/tty.h" 121da177e4SLinus Torvalds #include "linux/init.h" 131da177e4SLinus Torvalds #include "linux/bootmem.h" 141da177e4SLinus Torvalds #include "linux/spinlock.h" 151da177e4SLinus Torvalds #include "linux/utsname.h" 161da177e4SLinus Torvalds #include "linux/sysrq.h" 171da177e4SLinus Torvalds #include "linux/seq_file.h" 181da177e4SLinus Torvalds #include "linux/delay.h" 191da177e4SLinus Torvalds #include "linux/module.h" 201da177e4SLinus Torvalds #include "asm/page.h" 211da177e4SLinus Torvalds #include "asm/pgtable.h" 221da177e4SLinus Torvalds #include "asm/ptrace.h" 231da177e4SLinus Torvalds #include "asm/elf.h" 241da177e4SLinus Torvalds #include "asm/user.h" 2516c11163SJeff Dike #include "asm/setup.h" 261da177e4SLinus Torvalds #include "ubd_user.h" 271da177e4SLinus Torvalds #include "asm/current.h" 281da177e4SLinus Torvalds #include "user_util.h" 291da177e4SLinus Torvalds #include "kern_util.h" 301da177e4SLinus Torvalds #include "kern.h" 311da177e4SLinus Torvalds #include "mem_user.h" 321da177e4SLinus Torvalds #include "mem.h" 331da177e4SLinus Torvalds #include "initrd.h" 341da177e4SLinus Torvalds #include "init.h" 351da177e4SLinus Torvalds #include "os.h" 361da177e4SLinus Torvalds #include "choose-mode.h" 371da177e4SLinus Torvalds #include "mode_kern.h" 381da177e4SLinus Torvalds #include "mode.h" 39cb66504dSPaolo 'Blaisorblade' Giarrusso #ifdef UML_CONFIG_MODE_SKAS 40cb66504dSPaolo 'Blaisorblade' Giarrusso #include "skas.h" 41cb66504dSPaolo 'Blaisorblade' Giarrusso #endif 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds #define DEFAULT_COMMAND_LINE "root=98:0" 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds /* Changed in linux_main and setup_arch, which run before SMP is started */ 467a3a06d0SAlon Bar-Lev static char __initdata command_line[COMMAND_LINE_SIZE] = { 0 }; 471da177e4SLinus Torvalds 487a3a06d0SAlon Bar-Lev static void __init add_arg(char *arg) 491da177e4SLinus Torvalds { 501da177e4SLinus Torvalds if (strlen(command_line) + strlen(arg) + 1 > COMMAND_LINE_SIZE) { 511da177e4SLinus Torvalds printf("add_arg: Too many command line arguments!\n"); 521da177e4SLinus Torvalds exit(1); 531da177e4SLinus Torvalds } 541da177e4SLinus Torvalds if(strlen(command_line) > 0) 551da177e4SLinus Torvalds strcat(command_line, " "); 561da177e4SLinus Torvalds strcat(command_line, arg); 571da177e4SLinus Torvalds } 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds struct cpuinfo_um boot_cpu_data = { 601da177e4SLinus Torvalds .loops_per_jiffy = 0, 611da177e4SLinus Torvalds .ipi_pipe = { -1, -1 } 621da177e4SLinus Torvalds }; 631da177e4SLinus Torvalds 641da177e4SLinus Torvalds unsigned long thread_saved_pc(struct task_struct *task) 651da177e4SLinus Torvalds { 66a5ed1ffaSJeff Dike return os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, 67a5ed1ffaSJeff Dike task)); 681da177e4SLinus Torvalds } 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds static int show_cpuinfo(struct seq_file *m, void *v) 711da177e4SLinus Torvalds { 721da177e4SLinus Torvalds int index = 0; 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds #ifdef CONFIG_SMP 751da177e4SLinus Torvalds index = (struct cpuinfo_um *) v - cpu_data; 761da177e4SLinus Torvalds if (!cpu_online(index)) 771da177e4SLinus Torvalds return 0; 781da177e4SLinus Torvalds #endif 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds seq_printf(m, "processor\t: %d\n", index); 811da177e4SLinus Torvalds seq_printf(m, "vendor_id\t: User Mode Linux\n"); 821da177e4SLinus Torvalds seq_printf(m, "model name\t: UML\n"); 831da177e4SLinus Torvalds seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas")); 841da177e4SLinus Torvalds seq_printf(m, "host\t\t: %s\n", host_info); 851da177e4SLinus Torvalds seq_printf(m, "bogomips\t: %lu.%02lu\n\n", 861da177e4SLinus Torvalds loops_per_jiffy/(500000/HZ), 871da177e4SLinus Torvalds (loops_per_jiffy/(5000/HZ)) % 100); 881da177e4SLinus Torvalds 89a5ed1ffaSJeff Dike return 0; 901da177e4SLinus Torvalds } 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds static void *c_start(struct seq_file *m, loff_t *pos) 931da177e4SLinus Torvalds { 941da177e4SLinus Torvalds return *pos < NR_CPUS ? cpu_data + *pos : NULL; 951da177e4SLinus Torvalds } 961da177e4SLinus Torvalds 971da177e4SLinus Torvalds static void *c_next(struct seq_file *m, void *v, loff_t *pos) 981da177e4SLinus Torvalds { 991da177e4SLinus Torvalds ++*pos; 1001da177e4SLinus Torvalds return c_start(m, pos); 1011da177e4SLinus Torvalds } 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds static void c_stop(struct seq_file *m, void *v) 1041da177e4SLinus Torvalds { 1051da177e4SLinus Torvalds } 1061da177e4SLinus Torvalds 1075e7672ecSJeff Dike const struct seq_operations cpuinfo_op = { 1081da177e4SLinus Torvalds .start = c_start, 1091da177e4SLinus Torvalds .next = c_next, 1101da177e4SLinus Torvalds .stop = c_stop, 1111da177e4SLinus Torvalds .show = show_cpuinfo, 1121da177e4SLinus Torvalds }; 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds /* Set in linux_main */ 1151da177e4SLinus Torvalds unsigned long host_task_size; 1161da177e4SLinus Torvalds unsigned long task_size; 1171da177e4SLinus Torvalds 1181da177e4SLinus Torvalds unsigned long uml_start; 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds /* Set in early boot */ 1211da177e4SLinus Torvalds unsigned long uml_physmem; 1221da177e4SLinus Torvalds unsigned long uml_reserved; 1231da177e4SLinus Torvalds unsigned long start_vm; 1241da177e4SLinus Torvalds unsigned long end_vm; 1251da177e4SLinus Torvalds int ncpus = 1; 1261da177e4SLinus Torvalds 12702215759SPaolo 'Blaisorblade' Giarrusso #ifdef CONFIG_CMDLINE_ON_HOST 1281da177e4SLinus Torvalds /* Pointer set in linux_main, the array itself is private to each thread, 1291da177e4SLinus Torvalds * and changed at address space creation time so this poses no concurrency 1301da177e4SLinus Torvalds * problems. 1311da177e4SLinus Torvalds */ 1321da177e4SLinus Torvalds static char *argv1_begin = NULL; 1331da177e4SLinus Torvalds static char *argv1_end = NULL; 1341da177e4SLinus Torvalds #endif 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds /* Set in early boot */ 1371da177e4SLinus Torvalds static int have_root __initdata = 0; 138ae173816SJeff Dike long long physmem_size = 32 * 1024 * 1024; 1391da177e4SLinus Torvalds 1401da177e4SLinus Torvalds void set_cmdline(char *cmd) 1411da177e4SLinus Torvalds { 14202215759SPaolo 'Blaisorblade' Giarrusso #ifdef CONFIG_CMDLINE_ON_HOST 1431da177e4SLinus Torvalds char *umid, *ptr; 1441da177e4SLinus Torvalds 1451da177e4SLinus Torvalds if(CHOOSE_MODE(honeypot, 0)) return; 1461da177e4SLinus Torvalds 1477eebe8a9SJeff Dike umid = get_umid(); 1487eebe8a9SJeff Dike if(*umid != '\0'){ 1491da177e4SLinus Torvalds snprintf(argv1_begin, 1501da177e4SLinus Torvalds (argv1_end - argv1_begin) * sizeof(*ptr), 1511da177e4SLinus Torvalds "(%s) ", umid); 1521da177e4SLinus Torvalds ptr = &argv1_begin[strlen(argv1_begin)]; 1531da177e4SLinus Torvalds } 1541da177e4SLinus Torvalds else ptr = argv1_begin; 1551da177e4SLinus Torvalds 1561da177e4SLinus Torvalds snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd); 1571da177e4SLinus Torvalds memset(argv1_begin + strlen(argv1_begin), '\0', 1581da177e4SLinus Torvalds argv1_end - argv1_begin - strlen(argv1_begin)); 1591da177e4SLinus Torvalds #endif 1601da177e4SLinus Torvalds } 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds static char *usage_string = 1631da177e4SLinus Torvalds "User Mode Linux v%s\n" 1641da177e4SLinus Torvalds " available at http://user-mode-linux.sourceforge.net/\n\n"; 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds static int __init uml_version_setup(char *line, int *add) 1671da177e4SLinus Torvalds { 16896b644bdSSerge E. Hallyn printf("%s\n", init_utsname()->release); 1691da177e4SLinus Torvalds exit(0); 1701da177e4SLinus Torvalds 1711da177e4SLinus Torvalds return 0; 1721da177e4SLinus Torvalds } 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds __uml_setup("--version", uml_version_setup, 1751da177e4SLinus Torvalds "--version\n" 1761da177e4SLinus Torvalds " Prints the version number of the kernel.\n\n" 1771da177e4SLinus Torvalds ); 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds static int __init uml_root_setup(char *line, int *add) 1801da177e4SLinus Torvalds { 1811da177e4SLinus Torvalds have_root = 1; 1821da177e4SLinus Torvalds return 0; 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds 1851da177e4SLinus Torvalds __uml_setup("root=", uml_root_setup, 1861da177e4SLinus Torvalds "root=<file containing the root fs>\n" 1871da177e4SLinus Torvalds " This is actually used by the generic kernel in exactly the same\n" 1881da177e4SLinus Torvalds " way as in any other kernel. If you configure a number of block\n" 1891da177e4SLinus Torvalds " devices and want to boot off something other than ubd0, you \n" 1901da177e4SLinus Torvalds " would use something like:\n" 1911da177e4SLinus Torvalds " root=/dev/ubd5\n\n" 1921da177e4SLinus Torvalds ); 1931da177e4SLinus Torvalds 194fbd55779SJeff Dike #ifndef CONFIG_MODE_TT 195fbd55779SJeff Dike 196fbd55779SJeff Dike static int __init no_skas_debug_setup(char *line, int *add) 197fbd55779SJeff Dike { 198fbd55779SJeff Dike printf("'debug' is not necessary to gdb UML in skas mode - run \n"); 199fbd55779SJeff Dike printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n"); 200fbd55779SJeff Dike printf("doesn't work as expected\n"); 201fbd55779SJeff Dike 202fbd55779SJeff Dike return 0; 203fbd55779SJeff Dike } 204fbd55779SJeff Dike 205fbd55779SJeff Dike __uml_setup("debug", no_skas_debug_setup, 206fbd55779SJeff Dike "debug\n" 207fbd55779SJeff Dike " this flag is not needed to run gdb on UML in skas mode\n\n" 208fbd55779SJeff Dike ); 209fbd55779SJeff Dike 210fbd55779SJeff Dike #endif 211fbd55779SJeff Dike 2121da177e4SLinus Torvalds #ifdef CONFIG_SMP 2131da177e4SLinus Torvalds static int __init uml_ncpus_setup(char *line, int *add) 2141da177e4SLinus Torvalds { 2151da177e4SLinus Torvalds if (!sscanf(line, "%d", &ncpus)) { 2161da177e4SLinus Torvalds printf("Couldn't parse [%s]\n", line); 2171da177e4SLinus Torvalds return -1; 2181da177e4SLinus Torvalds } 2191da177e4SLinus Torvalds 2201da177e4SLinus Torvalds return 0; 2211da177e4SLinus Torvalds } 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds __uml_setup("ncpus=", uml_ncpus_setup, 2241da177e4SLinus Torvalds "ncpus=<# of desired CPUs>\n" 2251da177e4SLinus Torvalds " This tells an SMP kernel how many virtual processors to start.\n\n" 2261da177e4SLinus Torvalds ); 2271da177e4SLinus Torvalds #endif 2281da177e4SLinus Torvalds 2291da177e4SLinus Torvalds static int force_tt = 0; 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds #if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS) 2321da177e4SLinus Torvalds #define DEFAULT_TT 0 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds static int __init mode_tt_setup(char *line, int *add) 2351da177e4SLinus Torvalds { 2361da177e4SLinus Torvalds force_tt = 1; 237a5ed1ffaSJeff Dike return 0; 2381da177e4SLinus Torvalds } 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds #else 2411da177e4SLinus Torvalds #ifdef CONFIG_MODE_SKAS 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds #define DEFAULT_TT 0 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds static int __init mode_tt_setup(char *line, int *add) 2461da177e4SLinus Torvalds { 2471da177e4SLinus Torvalds printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); 248a5ed1ffaSJeff Dike return 0; 2491da177e4SLinus Torvalds } 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds #else 2521da177e4SLinus Torvalds #ifdef CONFIG_MODE_TT 2531da177e4SLinus Torvalds 2541da177e4SLinus Torvalds #define DEFAULT_TT 1 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds static int __init mode_tt_setup(char *line, int *add) 2571da177e4SLinus Torvalds { 2581da177e4SLinus Torvalds printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); 259a5ed1ffaSJeff Dike return 0; 2601da177e4SLinus Torvalds } 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds #endif 2631da177e4SLinus Torvalds #endif 2641da177e4SLinus Torvalds #endif 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds __uml_setup("mode=tt", mode_tt_setup, 2671da177e4SLinus Torvalds "mode=tt\n" 2681da177e4SLinus Torvalds " When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n" 2691da177e4SLinus Torvalds " forces UML to run in tt (tracing thread) mode. It is not the default\n" 2701da177e4SLinus Torvalds " because it's slower and less secure than skas mode.\n\n" 2711da177e4SLinus Torvalds ); 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds int mode_tt = DEFAULT_TT; 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds static int __init Usage(char *line, int *add) 2761da177e4SLinus Torvalds { 2771da177e4SLinus Torvalds const char **p; 2781da177e4SLinus Torvalds 27996b644bdSSerge E. Hallyn printf(usage_string, init_utsname()->release); 2801da177e4SLinus Torvalds p = &__uml_help_start; 2811da177e4SLinus Torvalds while (p < &__uml_help_end) { 2821da177e4SLinus Torvalds printf("%s", *p); 2831da177e4SLinus Torvalds p++; 2841da177e4SLinus Torvalds } 2851da177e4SLinus Torvalds exit(0); 2861da177e4SLinus Torvalds return 0; 2871da177e4SLinus Torvalds } 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds __uml_setup("--help", Usage, 2901da177e4SLinus Torvalds "--help\n" 2911da177e4SLinus Torvalds " Prints this message.\n\n" 2921da177e4SLinus Torvalds ); 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds static int __init uml_checksetup(char *line, int *add) 2951da177e4SLinus Torvalds { 2961da177e4SLinus Torvalds struct uml_param *p; 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds p = &__uml_setup_start; 2991da177e4SLinus Torvalds while(p < &__uml_setup_end) { 3001da177e4SLinus Torvalds int n; 3011da177e4SLinus Torvalds 3021da177e4SLinus Torvalds n = strlen(p->str); 3031da177e4SLinus Torvalds if(!strncmp(line, p->str, n)){ 3041da177e4SLinus Torvalds if (p->setup_func(line + n, add)) return 1; 3051da177e4SLinus Torvalds } 3061da177e4SLinus Torvalds p++; 3071da177e4SLinus Torvalds } 3081da177e4SLinus Torvalds return 0; 3091da177e4SLinus Torvalds } 3101da177e4SLinus Torvalds 3111da177e4SLinus Torvalds static void __init uml_postsetup(void) 3121da177e4SLinus Torvalds { 3131da177e4SLinus Torvalds initcall_t *p; 3141da177e4SLinus Torvalds 3151da177e4SLinus Torvalds p = &__uml_postsetup_start; 3161da177e4SLinus Torvalds while(p < &__uml_postsetup_end){ 3171da177e4SLinus Torvalds (*p)(); 3181da177e4SLinus Torvalds p++; 3191da177e4SLinus Torvalds } 3201da177e4SLinus Torvalds return; 3211da177e4SLinus Torvalds } 3221da177e4SLinus Torvalds 3231da177e4SLinus Torvalds /* Set during early boot */ 3241da177e4SLinus Torvalds unsigned long brk_start; 3251da177e4SLinus Torvalds unsigned long end_iomem; 3261da177e4SLinus Torvalds EXPORT_SYMBOL(end_iomem); 3271da177e4SLinus Torvalds 3281da177e4SLinus Torvalds #define MIN_VMALLOC (32 * 1024 * 1024) 3291da177e4SLinus Torvalds 33023bbd586SJeff Dike extern char __binary_start; 33123bbd586SJeff Dike 3327a3a06d0SAlon Bar-Lev int __init linux_main(int argc, char **argv) 3331da177e4SLinus Torvalds { 3341da177e4SLinus Torvalds unsigned long avail, diff; 3351da177e4SLinus Torvalds unsigned long virtmem_size, max_physmem; 3361da177e4SLinus Torvalds unsigned int i, add; 337cb66504dSPaolo 'Blaisorblade' Giarrusso char * mode; 3381da177e4SLinus Torvalds 3391da177e4SLinus Torvalds for (i = 1; i < argc; i++){ 3401da177e4SLinus Torvalds if((i == 1) && (argv[i][0] == ' ')) continue; 3411da177e4SLinus Torvalds add = 1; 3421da177e4SLinus Torvalds uml_checksetup(argv[i], &add); 3431da177e4SLinus Torvalds if (add) 3441da177e4SLinus Torvalds add_arg(argv[i]); 3451da177e4SLinus Torvalds } 3461da177e4SLinus Torvalds if(have_root == 0) 3471da177e4SLinus Torvalds add_arg(DEFAULT_COMMAND_LINE); 3481da177e4SLinus Torvalds 34960d339f6SGennady Sharapov os_early_checks(); 3508923648cSPaolo 'Blaisorblade' Giarrusso if (force_tt) 3518923648cSPaolo 'Blaisorblade' Giarrusso clear_can_do_skas(); 3521da177e4SLinus Torvalds mode_tt = force_tt ? 1 : !can_do_skas(); 3531da177e4SLinus Torvalds #ifndef CONFIG_MODE_TT 3541da177e4SLinus Torvalds if (mode_tt) { 3551da177e4SLinus Torvalds /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So, 3561da177e4SLinus Torvalds * can_do_skas() returned 0, and the message is correct. */ 3571da177e4SLinus Torvalds printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n"); 3581da177e4SLinus Torvalds exit(1); 3591da177e4SLinus Torvalds } 3601da177e4SLinus Torvalds #endif 361cb66504dSPaolo 'Blaisorblade' Giarrusso 362cb66504dSPaolo 'Blaisorblade' Giarrusso #ifndef CONFIG_MODE_SKAS 363cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "TT"; 364cb66504dSPaolo 'Blaisorblade' Giarrusso #else 365cb66504dSPaolo 'Blaisorblade' Giarrusso /* Show to the user the result of selection */ 366cb66504dSPaolo 'Blaisorblade' Giarrusso if (mode_tt) 367cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "TT"; 368cb66504dSPaolo 'Blaisorblade' Giarrusso else if (proc_mm && ptrace_faultinfo) 369cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "SKAS3"; 370cb66504dSPaolo 'Blaisorblade' Giarrusso else 371cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "SKAS0"; 372cb66504dSPaolo 'Blaisorblade' Giarrusso #endif 373cb66504dSPaolo 'Blaisorblade' Giarrusso 374cb66504dSPaolo 'Blaisorblade' Giarrusso printf("UML running in %s mode\n", mode); 375cb66504dSPaolo 'Blaisorblade' Giarrusso 37623bbd586SJeff Dike uml_start = (unsigned long) &__binary_start; 37723bbd586SJeff Dike host_task_size = CHOOSE_MODE_PROC(set_task_sizes_tt, 37823bbd586SJeff Dike set_task_sizes_skas, &task_size); 379ea2ba7dcSGennady Sharapov 380ea2ba7dcSGennady Sharapov /* 381ea2ba7dcSGennady Sharapov * Setting up handlers to 'sig_info' struct 382ea2ba7dcSGennady Sharapov */ 383ea2ba7dcSGennady Sharapov os_fill_handlinfo(handlinfo_kern); 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds brk_start = (unsigned long) sbrk(0); 3861da177e4SLinus Torvalds CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); 3871da177e4SLinus Torvalds /* Increase physical memory size for exec-shield users 3881da177e4SLinus Torvalds so they actually get what they asked for. This should 3891da177e4SLinus Torvalds add zero for non-exec shield users */ 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds diff = UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); 3921da177e4SLinus Torvalds if(diff > 1024 * 1024){ 3931da177e4SLinus Torvalds printf("Adding %ld bytes to physical memory to account for " 3941da177e4SLinus Torvalds "exec-shield gap\n", diff); 3951da177e4SLinus Torvalds physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); 3961da177e4SLinus Torvalds } 3971da177e4SLinus Torvalds 39823bbd586SJeff Dike uml_physmem = uml_start & PAGE_MASK; 3991da177e4SLinus Torvalds 4001da177e4SLinus Torvalds /* Reserve up to 4M after the current brk */ 4011da177e4SLinus Torvalds uml_reserved = ROUND_4M(brk_start) + (1 << 22); 4021da177e4SLinus Torvalds 40396b644bdSSerge E. Hallyn setup_machinename(init_utsname()->machine); 4041da177e4SLinus Torvalds 40502215759SPaolo 'Blaisorblade' Giarrusso #ifdef CONFIG_CMDLINE_ON_HOST 4061da177e4SLinus Torvalds argv1_begin = argv[1]; 4071da177e4SLinus Torvalds argv1_end = &argv[1][strlen(argv[1])]; 4081da177e4SLinus Torvalds #endif 4091da177e4SLinus Torvalds 4101da177e4SLinus Torvalds highmem = 0; 4111da177e4SLinus Torvalds iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; 4121da177e4SLinus Torvalds max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; 4131da177e4SLinus Torvalds 4141da177e4SLinus Torvalds /* Zones have to begin on a 1 << MAX_ORDER page boundary, 4151da177e4SLinus Torvalds * so this makes sure that's true for highmem 4161da177e4SLinus Torvalds */ 4171da177e4SLinus Torvalds max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); 4181da177e4SLinus Torvalds if(physmem_size + iomem_size > max_physmem){ 4191da177e4SLinus Torvalds highmem = physmem_size + iomem_size - max_physmem; 4201da177e4SLinus Torvalds physmem_size -= highmem; 4211da177e4SLinus Torvalds #ifndef CONFIG_HIGHMEM 4221da177e4SLinus Torvalds highmem = 0; 4231da177e4SLinus Torvalds printf("CONFIG_HIGHMEM not enabled - physical memory shrunk " 424d9f8b62aSJeff Dike "to %Lu bytes\n", physmem_size); 4251da177e4SLinus Torvalds #endif 4261da177e4SLinus Torvalds } 4271da177e4SLinus Torvalds 4281da177e4SLinus Torvalds high_physmem = uml_physmem + physmem_size; 4291da177e4SLinus Torvalds end_iomem = high_physmem + iomem_size; 4301da177e4SLinus Torvalds high_memory = (void *) end_iomem; 4311da177e4SLinus Torvalds 4321da177e4SLinus Torvalds start_vm = VMALLOC_START; 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); 4351da177e4SLinus Torvalds if(init_maps(physmem_size, iomem_size, highmem)){ 436d9f8b62aSJeff Dike printf("Failed to allocate mem_map for %Lu bytes of physical " 437d9f8b62aSJeff Dike "memory and %Lu bytes of highmem\n", physmem_size, 4381da177e4SLinus Torvalds highmem); 4391da177e4SLinus Torvalds exit(1); 4401da177e4SLinus Torvalds } 4411da177e4SLinus Torvalds 4421da177e4SLinus Torvalds virtmem_size = physmem_size; 4431da177e4SLinus Torvalds avail = get_kmem_end() - start_vm; 4441da177e4SLinus Torvalds if(physmem_size > avail) virtmem_size = avail; 4451da177e4SLinus Torvalds end_vm = start_vm + virtmem_size; 4461da177e4SLinus Torvalds 4471da177e4SLinus Torvalds if(virtmem_size < physmem_size) 448ae173816SJeff Dike printf("Kernel virtual memory size shrunk to %lu bytes\n", 4491da177e4SLinus Torvalds virtmem_size); 4501da177e4SLinus Torvalds 4511da177e4SLinus Torvalds uml_postsetup(); 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds task_protections((unsigned long) &init_thread_info); 4541da177e4SLinus Torvalds os_flush_stdout(); 4551da177e4SLinus Torvalds 456a5ed1ffaSJeff Dike return CHOOSE_MODE(start_uml_tt(), start_uml_skas()); 4571da177e4SLinus Torvalds } 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds extern int uml_exitcode; 4601da177e4SLinus Torvalds 4611da177e4SLinus Torvalds static int panic_exit(struct notifier_block *self, unsigned long unused1, 4621da177e4SLinus Torvalds void *unused2) 4631da177e4SLinus Torvalds { 4641da177e4SLinus Torvalds bust_spinlocks(1); 4651da177e4SLinus Torvalds show_regs(&(current->thread.regs)); 4661da177e4SLinus Torvalds bust_spinlocks(0); 4671da177e4SLinus Torvalds uml_exitcode = 1; 4681da177e4SLinus Torvalds machine_halt(); 469a5ed1ffaSJeff Dike return 0; 4701da177e4SLinus Torvalds } 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds static struct notifier_block panic_exit_notifier = { 4731da177e4SLinus Torvalds .notifier_call = panic_exit, 4741da177e4SLinus Torvalds .next = NULL, 4751da177e4SLinus Torvalds .priority = 0 4761da177e4SLinus Torvalds }; 4771da177e4SLinus Torvalds 4781da177e4SLinus Torvalds void __init setup_arch(char **cmdline_p) 4791da177e4SLinus Torvalds { 480e041c683SAlan Stern atomic_notifier_chain_register(&panic_notifier_list, 481e041c683SAlan Stern &panic_exit_notifier); 4821da177e4SLinus Torvalds paging_init(); 48319bf7e7aSAlon Bar-Lev strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); 4841da177e4SLinus Torvalds *cmdline_p = command_line; 4851da177e4SLinus Torvalds setup_hostinfo(); 4861da177e4SLinus Torvalds } 4871da177e4SLinus Torvalds 4881da177e4SLinus Torvalds void __init check_bugs(void) 4891da177e4SLinus Torvalds { 4901da177e4SLinus Torvalds arch_check_bugs(); 4918e367065SJeff Dike os_check_bugs(); 4921da177e4SLinus Torvalds } 4931da177e4SLinus Torvalds 4949a0b5817SGerd Hoffmann void apply_alternatives(struct alt_instr *start, struct alt_instr *end) 4959a0b5817SGerd Hoffmann { 4969a0b5817SGerd Hoffmann } 4979a0b5817SGerd Hoffmann 498c61a8416STheodore Tso #ifdef CONFIG_SMP 4999a0b5817SGerd Hoffmann void alternatives_smp_module_add(struct module *mod, char *name, 5009a0b5817SGerd Hoffmann void *locks, void *locks_end, 5019a0b5817SGerd Hoffmann void *text, void *text_end) 5029a0b5817SGerd Hoffmann { 5039a0b5817SGerd Hoffmann } 5049a0b5817SGerd Hoffmann 5059a0b5817SGerd Hoffmann void alternatives_smp_module_del(struct module *mod) 5061da177e4SLinus Torvalds { 5071da177e4SLinus Torvalds } 508c61a8416STheodore Tso #endif 509