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 196fbd55779SJeff Dike #ifndef CONFIG_MODE_TT 197fbd55779SJeff Dike 198fbd55779SJeff Dike static int __init no_skas_debug_setup(char *line, int *add) 199fbd55779SJeff Dike { 200fbd55779SJeff Dike printf("'debug' is not necessary to gdb UML in skas mode - run \n"); 201fbd55779SJeff Dike printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n"); 202fbd55779SJeff Dike printf("doesn't work as expected\n"); 203fbd55779SJeff Dike 204fbd55779SJeff Dike return 0; 205fbd55779SJeff Dike } 206fbd55779SJeff Dike 207fbd55779SJeff Dike __uml_setup("debug", no_skas_debug_setup, 208fbd55779SJeff Dike "debug\n" 209fbd55779SJeff Dike " this flag is not needed to run gdb on UML in skas mode\n\n" 210fbd55779SJeff Dike ); 211fbd55779SJeff Dike 212fbd55779SJeff Dike #endif 213fbd55779SJeff Dike 2141da177e4SLinus Torvalds #ifdef CONFIG_SMP 2151da177e4SLinus Torvalds static int __init uml_ncpus_setup(char *line, int *add) 2161da177e4SLinus Torvalds { 2171da177e4SLinus Torvalds if (!sscanf(line, "%d", &ncpus)) { 2181da177e4SLinus Torvalds printf("Couldn't parse [%s]\n", line); 2191da177e4SLinus Torvalds return -1; 2201da177e4SLinus Torvalds } 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds return 0; 2231da177e4SLinus Torvalds } 2241da177e4SLinus Torvalds 2251da177e4SLinus Torvalds __uml_setup("ncpus=", uml_ncpus_setup, 2261da177e4SLinus Torvalds "ncpus=<# of desired CPUs>\n" 2271da177e4SLinus Torvalds " This tells an SMP kernel how many virtual processors to start.\n\n" 2281da177e4SLinus Torvalds ); 2291da177e4SLinus Torvalds #endif 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds static int force_tt = 0; 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds #if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS) 2341da177e4SLinus Torvalds #define DEFAULT_TT 0 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds static int __init mode_tt_setup(char *line, int *add) 2371da177e4SLinus Torvalds { 2381da177e4SLinus Torvalds force_tt = 1; 2391da177e4SLinus Torvalds return(0); 2401da177e4SLinus Torvalds } 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds #else 2431da177e4SLinus Torvalds #ifdef CONFIG_MODE_SKAS 2441da177e4SLinus Torvalds 2451da177e4SLinus Torvalds #define DEFAULT_TT 0 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds static int __init mode_tt_setup(char *line, int *add) 2481da177e4SLinus Torvalds { 2491da177e4SLinus Torvalds printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); 2501da177e4SLinus Torvalds return(0); 2511da177e4SLinus Torvalds } 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds #else 2541da177e4SLinus Torvalds #ifdef CONFIG_MODE_TT 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds #define DEFAULT_TT 1 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds static int __init mode_tt_setup(char *line, int *add) 2591da177e4SLinus Torvalds { 2601da177e4SLinus Torvalds printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); 2611da177e4SLinus Torvalds return(0); 2621da177e4SLinus Torvalds } 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds #endif 2651da177e4SLinus Torvalds #endif 2661da177e4SLinus Torvalds #endif 2671da177e4SLinus Torvalds 2681da177e4SLinus Torvalds __uml_setup("mode=tt", mode_tt_setup, 2691da177e4SLinus Torvalds "mode=tt\n" 2701da177e4SLinus Torvalds " When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n" 2711da177e4SLinus Torvalds " forces UML to run in tt (tracing thread) mode. It is not the default\n" 2721da177e4SLinus Torvalds " because it's slower and less secure than skas mode.\n\n" 2731da177e4SLinus Torvalds ); 2741da177e4SLinus Torvalds 2751da177e4SLinus Torvalds int mode_tt = DEFAULT_TT; 2761da177e4SLinus Torvalds 2771da177e4SLinus Torvalds static int __init Usage(char *line, int *add) 2781da177e4SLinus Torvalds { 2791da177e4SLinus Torvalds const char **p; 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds printf(usage_string, system_utsname.release); 2821da177e4SLinus Torvalds p = &__uml_help_start; 2831da177e4SLinus Torvalds while (p < &__uml_help_end) { 2841da177e4SLinus Torvalds printf("%s", *p); 2851da177e4SLinus Torvalds p++; 2861da177e4SLinus Torvalds } 2871da177e4SLinus Torvalds exit(0); 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds return 0; 2901da177e4SLinus Torvalds } 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds __uml_setup("--help", Usage, 2931da177e4SLinus Torvalds "--help\n" 2941da177e4SLinus Torvalds " Prints this message.\n\n" 2951da177e4SLinus Torvalds ); 2961da177e4SLinus Torvalds 2971da177e4SLinus Torvalds static int __init uml_checksetup(char *line, int *add) 2981da177e4SLinus Torvalds { 2991da177e4SLinus Torvalds struct uml_param *p; 3001da177e4SLinus Torvalds 3011da177e4SLinus Torvalds p = &__uml_setup_start; 3021da177e4SLinus Torvalds while(p < &__uml_setup_end) { 3031da177e4SLinus Torvalds int n; 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds n = strlen(p->str); 3061da177e4SLinus Torvalds if(!strncmp(line, p->str, n)){ 3071da177e4SLinus Torvalds if (p->setup_func(line + n, add)) return 1; 3081da177e4SLinus Torvalds } 3091da177e4SLinus Torvalds p++; 3101da177e4SLinus Torvalds } 3111da177e4SLinus Torvalds return 0; 3121da177e4SLinus Torvalds } 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds static void __init uml_postsetup(void) 3151da177e4SLinus Torvalds { 3161da177e4SLinus Torvalds initcall_t *p; 3171da177e4SLinus Torvalds 3181da177e4SLinus Torvalds p = &__uml_postsetup_start; 3191da177e4SLinus Torvalds while(p < &__uml_postsetup_end){ 3201da177e4SLinus Torvalds (*p)(); 3211da177e4SLinus Torvalds p++; 3221da177e4SLinus Torvalds } 3231da177e4SLinus Torvalds return; 3241da177e4SLinus Torvalds } 3251da177e4SLinus Torvalds 3261da177e4SLinus Torvalds /* Set during early boot */ 3271da177e4SLinus Torvalds unsigned long brk_start; 3281da177e4SLinus Torvalds unsigned long end_iomem; 3291da177e4SLinus Torvalds EXPORT_SYMBOL(end_iomem); 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds #define MIN_VMALLOC (32 * 1024 * 1024) 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds int linux_main(int argc, char **argv) 3341da177e4SLinus Torvalds { 3351da177e4SLinus Torvalds unsigned long avail, diff; 3361da177e4SLinus Torvalds unsigned long virtmem_size, max_physmem; 3371da177e4SLinus Torvalds unsigned int i, add; 338cb66504dSPaolo 'Blaisorblade' Giarrusso char * mode; 3391da177e4SLinus Torvalds 3401da177e4SLinus Torvalds for (i = 1; i < argc; i++){ 3411da177e4SLinus Torvalds if((i == 1) && (argv[i][0] == ' ')) continue; 3421da177e4SLinus Torvalds add = 1; 3431da177e4SLinus Torvalds uml_checksetup(argv[i], &add); 3441da177e4SLinus Torvalds if (add) 3451da177e4SLinus Torvalds add_arg(argv[i]); 3461da177e4SLinus Torvalds } 3471da177e4SLinus Torvalds if(have_root == 0) 3481da177e4SLinus Torvalds add_arg(DEFAULT_COMMAND_LINE); 3491da177e4SLinus Torvalds 35060d339f6SGennady Sharapov os_early_checks(); 3518923648cSPaolo 'Blaisorblade' Giarrusso if (force_tt) 3528923648cSPaolo 'Blaisorblade' Giarrusso clear_can_do_skas(); 3531da177e4SLinus Torvalds mode_tt = force_tt ? 1 : !can_do_skas(); 3541da177e4SLinus Torvalds #ifndef CONFIG_MODE_TT 3551da177e4SLinus Torvalds if (mode_tt) { 3561da177e4SLinus Torvalds /*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So, 3571da177e4SLinus Torvalds * can_do_skas() returned 0, and the message is correct. */ 3581da177e4SLinus Torvalds printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n"); 3591da177e4SLinus Torvalds exit(1); 3601da177e4SLinus Torvalds } 3611da177e4SLinus Torvalds #endif 362cb66504dSPaolo 'Blaisorblade' Giarrusso 363cb66504dSPaolo 'Blaisorblade' Giarrusso #ifndef CONFIG_MODE_SKAS 364cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "TT"; 365cb66504dSPaolo 'Blaisorblade' Giarrusso #else 366cb66504dSPaolo 'Blaisorblade' Giarrusso /* Show to the user the result of selection */ 367cb66504dSPaolo 'Blaisorblade' Giarrusso if (mode_tt) 368cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "TT"; 369cb66504dSPaolo 'Blaisorblade' Giarrusso else if (proc_mm && ptrace_faultinfo) 370cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "SKAS3"; 371cb66504dSPaolo 'Blaisorblade' Giarrusso else 372cb66504dSPaolo 'Blaisorblade' Giarrusso mode = "SKAS0"; 373cb66504dSPaolo 'Blaisorblade' Giarrusso #endif 374cb66504dSPaolo 'Blaisorblade' Giarrusso 375cb66504dSPaolo 'Blaisorblade' Giarrusso printf("UML running in %s mode\n", mode); 376cb66504dSPaolo 'Blaisorblade' Giarrusso 3771da177e4SLinus Torvalds uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, 3781da177e4SLinus Torvalds &host_task_size, &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 3981da177e4SLinus Torvalds uml_physmem = uml_start; 3991da177e4SLinus Torvalds 4001da177e4SLinus Torvalds /* Reserve up to 4M after the current brk */ 4011da177e4SLinus Torvalds uml_reserved = ROUND_4M(brk_start) + (1 << 22); 4021da177e4SLinus Torvalds 4031da177e4SLinus Torvalds setup_machinename(system_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 4561da177e4SLinus Torvalds 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(); 4691da177e4SLinus Torvalds 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 { 4801da177e4SLinus Torvalds notifier_chain_register(&panic_notifier_list, &panic_exit_notifier); 4811da177e4SLinus Torvalds paging_init(); 4821da177e4SLinus Torvalds strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE); 4831da177e4SLinus Torvalds *cmdline_p = command_line; 4841da177e4SLinus Torvalds setup_hostinfo(); 4851da177e4SLinus Torvalds } 4861da177e4SLinus Torvalds 4871da177e4SLinus Torvalds void __init check_bugs(void) 4881da177e4SLinus Torvalds { 4891da177e4SLinus Torvalds arch_check_bugs(); 4901da177e4SLinus Torvalds check_sigio(); 4911da177e4SLinus Torvalds check_devanon(); 4921da177e4SLinus Torvalds } 4931da177e4SLinus Torvalds 4949a0b5817SGerd Hoffmann void apply_alternatives(struct alt_instr *start, struct alt_instr *end) 4959a0b5817SGerd Hoffmann { 4969a0b5817SGerd Hoffmann } 4979a0b5817SGerd Hoffmann 4989a0b5817SGerd Hoffmann void alternatives_smp_module_add(struct module *mod, char *name, 4999a0b5817SGerd Hoffmann void *locks, void *locks_end, 5009a0b5817SGerd Hoffmann void *text, void *text_end) 5019a0b5817SGerd Hoffmann { 5029a0b5817SGerd Hoffmann } 5039a0b5817SGerd Hoffmann 5049a0b5817SGerd Hoffmann void alternatives_smp_module_del(struct module *mod) 5051da177e4SLinus Torvalds { 5061da177e4SLinus Torvalds } 507