131e31b8aSbellard /* 293ac68bcSbellard * qemu user main 331e31b8aSbellard * 468d0f70eSbellard * Copyright (c) 2003-2008 Fabrice Bellard 531e31b8aSbellard * 631e31b8aSbellard * This program is free software; you can redistribute it and/or modify 731e31b8aSbellard * it under the terms of the GNU General Public License as published by 831e31b8aSbellard * the Free Software Foundation; either version 2 of the License, or 931e31b8aSbellard * (at your option) any later version. 1031e31b8aSbellard * 1131e31b8aSbellard * This program is distributed in the hope that it will be useful, 1231e31b8aSbellard * but WITHOUT ANY WARRANTY; without even the implied warranty of 1331e31b8aSbellard * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1431e31b8aSbellard * GNU General Public License for more details. 1531e31b8aSbellard * 1631e31b8aSbellard * You should have received a copy of the GNU General Public License 178167ee88SBlue Swirl * along with this program; if not, see <http://www.gnu.org/licenses/>. 1831e31b8aSbellard */ 1914a48c1dSMarkus Armbruster 20d39594e9SPeter Maydell #include "qemu/osdep.h" 2149f95221SMarc-André Lureau #include "qemu/help-texts.h" 22b52713c1SPhilippe Mathieu-Daudé #include "qemu/units.h" 23940e43aaSClaudio Fontana #include "qemu/accel.h" 2467a1de0dSFam Zheng #include "qemu-version.h" 25edf8e2afSMika Westerberg #include <sys/syscall.h> 26703e0e89SRichard Henderson #include <sys/resource.h> 27ee947430SAlex Bennée #include <sys/shm.h> 286e1c0d7bSLaurent Vivier #include <linux/binfmts.h> 2931e31b8aSbellard 30daa76aa4SMarkus Armbruster #include "qapi/error.h" 313ef693a0Sbellard #include "qemu.h" 323b249d26SPeter Maydell #include "user-internals.h" 33f348b6d1SVeronia Bahaa #include "qemu/path.h" 34dc5e9ac7SMarkus Armbruster #include "qemu/queue.h" 356533dd6eSLluís Vilanova #include "qemu/config-file.h" 36f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 37f5852efaSChristophe Fergeau #include "qemu/error-report.h" 38f348b6d1SVeronia Bahaa #include "qemu/help_option.h" 390b8fa32fSMarkus Armbruster #include "qemu/module.h" 40f308f64eSLluís Vilanova #include "qemu/plugin.h" 4163c91552SPaolo Bonzini #include "exec/exec-all.h" 4285b4fa0cSPeter Maydell #include "exec/gdbstub.h" 43d96bf49bSAlex Bennée #include "gdbstub/user.h" 44d7ec12f8SRichard Henderson #include "tcg/startup.h" 451de7afc9SPaolo Bonzini #include "qemu/timer.h" 461de7afc9SPaolo Bonzini #include "qemu/envlist.h" 475ebdd774SRichard Henderson #include "qemu/guest-random.h" 48d8fd2954SPaul Brook #include "elf.h" 496533dd6eSLluís Vilanova #include "trace/control.h" 50542ca434SLaurent Vivier #include "target_elf.h" 51cd71c089SLaurent Vivier #include "cpu_loop-common.h" 52a573e9baSRichard Henderson #include "crypto/init.h" 53c093364fSOwen Anderson #include "fd-trans.h" 542113aed6SPeter Maydell #include "signal-common.h" 553ad0a769SPeter Maydell #include "loader.h" 565423e6d3SPeter Maydell #include "user-mmap.h" 57327b75a4SIlya Leoshkevich #include "tcg/perf.h" 58ff8a8bbcSRichard Henderson #include "exec/page-vary.h" 5904a6dfebSaurel32 60e4a4aaa5SRichard Henderson #ifdef CONFIG_SEMIHOSTING 61e4a4aaa5SRichard Henderson #include "semihosting/semihost.h" 62e4a4aaa5SRichard Henderson #endif 63e4a4aaa5SRichard Henderson 646e1c0d7bSLaurent Vivier #ifndef AT_FLAGS_PRESERVE_ARGV0 656e1c0d7bSLaurent Vivier #define AT_FLAGS_PRESERVE_ARGV0_BIT 0 666e1c0d7bSLaurent Vivier #define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT) 676e1c0d7bSLaurent Vivier #endif 686e1c0d7bSLaurent Vivier 69d088d664Saurel32 char *exec_path; 70258bec39SHelge Deller char real_exec_path[PATH_MAX]; 71d088d664Saurel32 723cfb0456SPeter Maydell static bool opt_one_insn_per_tb; 738cb76755SStefan Weil static const char *argv0; 74fcedd920SAlex Bennée static const char *gdbstub; 758cb76755SStefan Weil static envlist_t *envlist; 7651fb256aSAndreas Färber static const char *cpu_model; 772278b939SIgor Mammedov static const char *cpu_type; 785ebdd774SRichard Henderson static const char *seed_optarg; 79379f6698SPaul Brook unsigned long mmap_min_addr; 805ca870b9SRichard Henderson uintptr_t guest_base; 81e307c192SRichard Henderson bool have_guest_base; 82120a9848SPaolo Bonzini 83288e65b9SAlexander Graf /* 844b25a506SJosh Kunz * Used to implement backwards-compatibility for the `-strace`, and 854b25a506SJosh Kunz * QEMU_STRACE options. Without this, the QEMU_LOG can be overwritten by 864b25a506SJosh Kunz * -strace, or vice versa. 874b25a506SJosh Kunz */ 884b25a506SJosh Kunz static bool enable_strace; 894b25a506SJosh Kunz 904b25a506SJosh Kunz /* 914b25a506SJosh Kunz * The last log mask given by the user in an environment variable or argument. 924b25a506SJosh Kunz * Used to support command line arguments overriding environment variables. 934b25a506SJosh Kunz */ 944b25a506SJosh Kunz static int last_log_mask; 95b410253fSRichard Henderson static const char *last_log_filename; 964b25a506SJosh Kunz 974b25a506SJosh Kunz /* 98288e65b9SAlexander Graf * When running 32-on-64 we should make sure we can fit all of the possible 99288e65b9SAlexander Graf * guest address space into a contiguous chunk of virtual host memory. 100288e65b9SAlexander Graf * 101288e65b9SAlexander Graf * This way we will never overlap with our own libraries or binaries or stack 102288e65b9SAlexander Graf * or anything else that QEMU maps. 10318e80c55SRichard Henderson * 10418e80c55SRichard Henderson * Many cpus reserve the high bit (or more than one for some 64-bit cpus) 10518e80c55SRichard Henderson * of the address for the kernel. Some cpus rely on this and user space 10618e80c55SRichard Henderson * uses the high bit(s) for pointer tagging and the like. For them, we 10718e80c55SRichard Henderson * must preserve the expected address space. 108288e65b9SAlexander Graf */ 10918e80c55SRichard Henderson #ifndef MAX_RESERVED_VA 11018e80c55SRichard Henderson # if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS 11118e80c55SRichard Henderson # if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \ 11218e80c55SRichard Henderson (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32)) 11395059f9cSRichard Henderson # define MAX_RESERVED_VA(CPU) 0xfffffffful 114314992b1SAlexander Graf # else 11595059f9cSRichard Henderson # define MAX_RESERVED_VA(CPU) ((1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1) 116314992b1SAlexander Graf # endif 117288e65b9SAlexander Graf # else 1188f67b9c6SRichard Henderson # define MAX_RESERVED_VA(CPU) 0 11918e80c55SRichard Henderson # endif 12018e80c55SRichard Henderson #endif 12118e80c55SRichard Henderson 12268a1c816SPaul Brook unsigned long reserved_va; 1231b530a6dSaurel32 124d03f9c32SMeador Inge static void usage(int exitcode); 125fc9c5412SJohannes Schauer 1267ee2822cSPaolo Bonzini static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; 127e586822aSRiku Voipio const char *qemu_uname_release; 128586314f2Sbellard 1290a3346b5SHelge Deller #if !defined(TARGET_DEFAULT_STACK_SIZE) 1309de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so 1319de5e440Sbellard we allocate a bigger stack. Need a better solution, for example 1329de5e440Sbellard by remapping the process stack directly at the right place */ 1330a3346b5SHelge Deller #define TARGET_DEFAULT_STACK_SIZE 8 * 1024 * 1024UL 1340a3346b5SHelge Deller #endif 1350a3346b5SHelge Deller 1360a3346b5SHelge Deller unsigned long guest_stack_size = TARGET_DEFAULT_STACK_SIZE; 13731e31b8aSbellard 138d5975363Spbrook /***********************************************************/ 139d5975363Spbrook /* Helper routines for implementing atomic operations. */ 140d5975363Spbrook 141d5975363Spbrook /* Make sure everything is in a consistent state for calling fork(). */ 142d5975363Spbrook void fork_start(void) 143d5975363Spbrook { 14406065c45SPeter Maydell start_exclusive(); 145d032d1b4SRiku Voipio mmap_fork_start(); 146024949caSPeter Maydell cpu_list_lock(); 147f7e15affSAlex Bennée qemu_plugin_user_prefork_lock(); 148d5975363Spbrook } 149d5975363Spbrook 150d5975363Spbrook void fork_end(int child) 151d5975363Spbrook { 152f7e15affSAlex Bennée qemu_plugin_user_postfork(child); 153d032d1b4SRiku Voipio mmap_fork_end(child); 154d5975363Spbrook if (child) { 155bdc44640SAndreas Färber CPUState *cpu, *next_cpu; 156d5975363Spbrook /* Child processes created by fork() only have a single thread. 157d5975363Spbrook Discard information about the parent threads. */ 158bdc44640SAndreas Färber CPU_FOREACH_SAFE(cpu, next_cpu) { 159bdc44640SAndreas Färber if (cpu != thread_cpu) { 1603c55dd58SPhilippe Mathieu-Daudé QTAILQ_REMOVE_RCU(&cpus_queue, cpu, node); 161bdc44640SAndreas Färber } 162bdc44640SAndreas Färber } 163267f685bSPaolo Bonzini qemu_init_cpu_list(); 164f7ec7f7bSPeter Crosthwaite gdbserver_fork(thread_cpu); 165d5975363Spbrook } else { 166267f685bSPaolo Bonzini cpu_list_unlock(); 167d5975363Spbrook } 1687de0816fSIlya Leoshkevich /* 1697de0816fSIlya Leoshkevich * qemu_init_cpu_list() reinitialized the child exclusive state, but we 1707de0816fSIlya Leoshkevich * also need to keep current_cpu consistent, so call end_exclusive() for 1717de0816fSIlya Leoshkevich * both child and parent. 1727de0816fSIlya Leoshkevich */ 1737de0816fSIlya Leoshkevich end_exclusive(); 174d5975363Spbrook } 175d5975363Spbrook 176b44316fbSPeter Maydell __thread CPUState *thread_cpu; 17759faf6d6Sbellard 178178f9429SSergey Fedorov bool qemu_cpu_is_self(CPUState *cpu) 179178f9429SSergey Fedorov { 180178f9429SSergey Fedorov return thread_cpu == cpu; 181178f9429SSergey Fedorov } 182178f9429SSergey Fedorov 183178f9429SSergey Fedorov void qemu_cpu_kick(CPUState *cpu) 184178f9429SSergey Fedorov { 185178f9429SSergey Fedorov cpu_exit(cpu); 186178f9429SSergey Fedorov } 187178f9429SSergey Fedorov 188edf8e2afSMika Westerberg void task_settid(TaskState *ts) 189edf8e2afSMika Westerberg { 190edf8e2afSMika Westerberg if (ts->ts_tid == 0) { 191edf8e2afSMika Westerberg ts->ts_tid = (pid_t)syscall(SYS_gettid); 192edf8e2afSMika Westerberg } 193edf8e2afSMika Westerberg } 194edf8e2afSMika Westerberg 195edf8e2afSMika Westerberg void stop_all_tasks(void) 196edf8e2afSMika Westerberg { 197edf8e2afSMika Westerberg /* 198edf8e2afSMika Westerberg * We trust that when using NPTL, start_exclusive() 199edf8e2afSMika Westerberg * handles thread stopping correctly. 200edf8e2afSMika Westerberg */ 201edf8e2afSMika Westerberg start_exclusive(); 202edf8e2afSMika Westerberg } 203edf8e2afSMika Westerberg 204c3a92833Spbrook /* Assumes contents are already zeroed. */ 205624f7979Spbrook void init_task_state(TaskState *ts) 206624f7979Spbrook { 207eb33cdaeSCameron Esfahani long ticks_per_sec; 208eb33cdaeSCameron Esfahani struct timespec bt; 209eb33cdaeSCameron Esfahani 210624f7979Spbrook ts->used = 1; 2115bfce0b7SPeter Maydell ts->sigaltstack_used = (struct target_sigaltstack) { 2125bfce0b7SPeter Maydell .ss_sp = 0, 2135bfce0b7SPeter Maydell .ss_size = 0, 2145bfce0b7SPeter Maydell .ss_flags = TARGET_SS_DISABLE, 2155bfce0b7SPeter Maydell }; 216eb33cdaeSCameron Esfahani 217eb33cdaeSCameron Esfahani /* Capture task start time relative to system boot */ 218eb33cdaeSCameron Esfahani 219eb33cdaeSCameron Esfahani ticks_per_sec = sysconf(_SC_CLK_TCK); 220eb33cdaeSCameron Esfahani 221eb33cdaeSCameron Esfahani if ((ticks_per_sec > 0) && !clock_gettime(CLOCK_BOOTTIME, &bt)) { 222eb33cdaeSCameron Esfahani /* start_boottime is expressed in clock ticks */ 223eb33cdaeSCameron Esfahani ts->start_boottime = bt.tv_sec * (uint64_t) ticks_per_sec; 224eb33cdaeSCameron Esfahani ts->start_boottime += bt.tv_nsec * (uint64_t) ticks_per_sec / 225eb33cdaeSCameron Esfahani NANOSECONDS_PER_SECOND; 226eb33cdaeSCameron Esfahani } 227624f7979Spbrook } 2289de5e440Sbellard 22930ba0ee5SAndreas Färber CPUArchState *cpu_copy(CPUArchState *env) 23030ba0ee5SAndreas Färber { 23129a0af61SRichard Henderson CPUState *cpu = env_cpu(env); 2322278b939SIgor Mammedov CPUState *new_cpu = cpu_create(cpu_type); 233b77af26eSRichard Henderson CPUArchState *new_env = cpu_env(new_cpu); 23430ba0ee5SAndreas Färber CPUBreakpoint *bp; 23530ba0ee5SAndreas Färber 23630ba0ee5SAndreas Färber /* Reset non arch specific state */ 23775a34036SAndreas Färber cpu_reset(new_cpu); 23830ba0ee5SAndreas Färber 2396cc9d67cSRichard Henderson new_cpu->tcg_cflags = cpu->tcg_cflags; 24030ba0ee5SAndreas Färber memcpy(new_env, env, sizeof(CPUArchState)); 2412732c739Sfanwj@mail.ustc.edu.cn #if defined(TARGET_I386) || defined(TARGET_X86_64) 2422732c739Sfanwj@mail.ustc.edu.cn new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, 2432732c739Sfanwj@mail.ustc.edu.cn PROT_READ | PROT_WRITE, 2442732c739Sfanwj@mail.ustc.edu.cn MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 2452732c739Sfanwj@mail.ustc.edu.cn memcpy(g2h_untagged(new_env->gdt.base), g2h_untagged(env->gdt.base), 2462732c739Sfanwj@mail.ustc.edu.cn sizeof(uint64_t) * TARGET_GDT_ENTRIES); 2472732c739Sfanwj@mail.ustc.edu.cn OBJECT(new_cpu)->free = OBJECT(cpu)->free; 2482732c739Sfanwj@mail.ustc.edu.cn #endif 24930ba0ee5SAndreas Färber 25030ba0ee5SAndreas Färber /* Clone all break/watchpoints. 25130ba0ee5SAndreas Färber Note: Once we support ptrace with hw-debug register access, make sure 25230ba0ee5SAndreas Färber BP_CPU break/watchpoints are handled correctly on clone. */ 2531d085f6cSThierry Bultel QTAILQ_INIT(&new_cpu->breakpoints); 254f0c3c505SAndreas Färber QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { 255b3310ab3SAndreas Färber cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL); 25630ba0ee5SAndreas Färber } 25730ba0ee5SAndreas Färber 25830ba0ee5SAndreas Färber return new_env; 25930ba0ee5SAndreas Färber } 26030ba0ee5SAndreas Färber 261fc9c5412SJohannes Schauer static void handle_arg_help(const char *arg) 262fc9c5412SJohannes Schauer { 2634d1275c2SRiku Voipio usage(EXIT_SUCCESS); 264fc9c5412SJohannes Schauer } 265fc9c5412SJohannes Schauer 266fc9c5412SJohannes Schauer static void handle_arg_log(const char *arg) 267fc9c5412SJohannes Schauer { 2684b25a506SJosh Kunz last_log_mask = qemu_str_to_log_mask(arg); 2694b25a506SJosh Kunz if (!last_log_mask) { 27059a6fa6eSPeter Maydell qemu_print_log_usage(stdout); 2714d1275c2SRiku Voipio exit(EXIT_FAILURE); 272fc9c5412SJohannes Schauer } 273fc9c5412SJohannes Schauer } 274fc9c5412SJohannes Schauer 2758423fa90SAlex Bennée static void handle_arg_dfilter(const char *arg) 2768423fa90SAlex Bennée { 2777f4341e8SAlex Bennée qemu_set_dfilter_ranges(arg, &error_fatal); 2788423fa90SAlex Bennée } 2798423fa90SAlex Bennée 28050171d42S陳韋任 static void handle_arg_log_filename(const char *arg) 28150171d42S陳韋任 { 282b410253fSRichard Henderson last_log_filename = arg; 28350171d42S陳韋任 } 28450171d42S陳韋任 285fc9c5412SJohannes Schauer static void handle_arg_set_env(const char *arg) 286fc9c5412SJohannes Schauer { 287fc9c5412SJohannes Schauer char *r, *p, *token; 288fc9c5412SJohannes Schauer r = p = strdup(arg); 289fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 290fc9c5412SJohannes Schauer if (envlist_setenv(envlist, token) != 0) { 2914d1275c2SRiku Voipio usage(EXIT_FAILURE); 292fc9c5412SJohannes Schauer } 293fc9c5412SJohannes Schauer } 294fc9c5412SJohannes Schauer free(r); 295fc9c5412SJohannes Schauer } 296fc9c5412SJohannes Schauer 297fc9c5412SJohannes Schauer static void handle_arg_unset_env(const char *arg) 298fc9c5412SJohannes Schauer { 299fc9c5412SJohannes Schauer char *r, *p, *token; 300fc9c5412SJohannes Schauer r = p = strdup(arg); 301fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 302fc9c5412SJohannes Schauer if (envlist_unsetenv(envlist, token) != 0) { 3034d1275c2SRiku Voipio usage(EXIT_FAILURE); 304fc9c5412SJohannes Schauer } 305fc9c5412SJohannes Schauer } 306fc9c5412SJohannes Schauer free(r); 307fc9c5412SJohannes Schauer } 308fc9c5412SJohannes Schauer 309fc9c5412SJohannes Schauer static void handle_arg_argv0(const char *arg) 310fc9c5412SJohannes Schauer { 311fc9c5412SJohannes Schauer argv0 = strdup(arg); 312fc9c5412SJohannes Schauer } 313fc9c5412SJohannes Schauer 314fc9c5412SJohannes Schauer static void handle_arg_stack_size(const char *arg) 315fc9c5412SJohannes Schauer { 316fc9c5412SJohannes Schauer char *p; 317fc9c5412SJohannes Schauer guest_stack_size = strtoul(arg, &p, 0); 318fc9c5412SJohannes Schauer if (guest_stack_size == 0) { 3194d1275c2SRiku Voipio usage(EXIT_FAILURE); 320fc9c5412SJohannes Schauer } 321fc9c5412SJohannes Schauer 322fc9c5412SJohannes Schauer if (*p == 'M') { 323b52713c1SPhilippe Mathieu-Daudé guest_stack_size *= MiB; 324fc9c5412SJohannes Schauer } else if (*p == 'k' || *p == 'K') { 325b52713c1SPhilippe Mathieu-Daudé guest_stack_size *= KiB; 326fc9c5412SJohannes Schauer } 327fc9c5412SJohannes Schauer } 328fc9c5412SJohannes Schauer 329fc9c5412SJohannes Schauer static void handle_arg_ld_prefix(const char *arg) 330fc9c5412SJohannes Schauer { 331fc9c5412SJohannes Schauer interp_prefix = strdup(arg); 332fc9c5412SJohannes Schauer } 333fc9c5412SJohannes Schauer 334fc9c5412SJohannes Schauer static void handle_arg_pagesize(const char *arg) 335fc9c5412SJohannes Schauer { 33601e44980SRichard Henderson unsigned size, want = qemu_real_host_page_size(); 33701e44980SRichard Henderson 33801e44980SRichard Henderson if (qemu_strtoui(arg, NULL, 10, &size) || size != want) { 33901e44980SRichard Henderson warn_report("Deprecated page size option cannot " 34001e44980SRichard Henderson "change host page size (%u)", want); 341fc9c5412SJohannes Schauer } 342fc9c5412SJohannes Schauer } 343fc9c5412SJohannes Schauer 3445ebdd774SRichard Henderson static void handle_arg_seed(const char *arg) 345c5e4a5a9SMagnus Reftel { 3465ebdd774SRichard Henderson seed_optarg = arg; 347c5e4a5a9SMagnus Reftel } 348c5e4a5a9SMagnus Reftel 349fc9c5412SJohannes Schauer static void handle_arg_gdb(const char *arg) 350fc9c5412SJohannes Schauer { 351fcedd920SAlex Bennée gdbstub = g_strdup(arg); 352fc9c5412SJohannes Schauer } 353fc9c5412SJohannes Schauer 354fc9c5412SJohannes Schauer static void handle_arg_uname(const char *arg) 355fc9c5412SJohannes Schauer { 356fc9c5412SJohannes Schauer qemu_uname_release = strdup(arg); 357fc9c5412SJohannes Schauer } 358fc9c5412SJohannes Schauer 359fc9c5412SJohannes Schauer static void handle_arg_cpu(const char *arg) 360fc9c5412SJohannes Schauer { 361fc9c5412SJohannes Schauer cpu_model = strdup(arg); 362c8057f95SPeter Maydell if (cpu_model == NULL || is_help_option(cpu_model)) { 363b67e5cb4SThomas Huth list_cpus(); 3644d1275c2SRiku Voipio exit(EXIT_FAILURE); 365fc9c5412SJohannes Schauer } 366fc9c5412SJohannes Schauer } 367fc9c5412SJohannes Schauer 368fc9c5412SJohannes Schauer static void handle_arg_guest_base(const char *arg) 369fc9c5412SJohannes Schauer { 370fc9c5412SJohannes Schauer guest_base = strtol(arg, NULL, 0); 371e307c192SRichard Henderson have_guest_base = true; 372fc9c5412SJohannes Schauer } 373fc9c5412SJohannes Schauer 374fc9c5412SJohannes Schauer static void handle_arg_reserved_va(const char *arg) 375fc9c5412SJohannes Schauer { 376fc9c5412SJohannes Schauer char *p; 377fc9c5412SJohannes Schauer int shift = 0; 37895059f9cSRichard Henderson unsigned long val; 37995059f9cSRichard Henderson 38095059f9cSRichard Henderson val = strtoul(arg, &p, 0); 381fc9c5412SJohannes Schauer switch (*p) { 382fc9c5412SJohannes Schauer case 'k': 383fc9c5412SJohannes Schauer case 'K': 384fc9c5412SJohannes Schauer shift = 10; 385fc9c5412SJohannes Schauer break; 386fc9c5412SJohannes Schauer case 'M': 387fc9c5412SJohannes Schauer shift = 20; 388fc9c5412SJohannes Schauer break; 389fc9c5412SJohannes Schauer case 'G': 390fc9c5412SJohannes Schauer shift = 30; 391fc9c5412SJohannes Schauer break; 392fc9c5412SJohannes Schauer } 393fc9c5412SJohannes Schauer if (shift) { 39495059f9cSRichard Henderson unsigned long unshifted = val; 395fc9c5412SJohannes Schauer p++; 39695059f9cSRichard Henderson val <<= shift; 39795059f9cSRichard Henderson if (val >> shift != unshifted) { 398fc9c5412SJohannes Schauer fprintf(stderr, "Reserved virtual address too big\n"); 3994d1275c2SRiku Voipio exit(EXIT_FAILURE); 400fc9c5412SJohannes Schauer } 401fc9c5412SJohannes Schauer } 402fc9c5412SJohannes Schauer if (*p) { 403fc9c5412SJohannes Schauer fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p); 4044d1275c2SRiku Voipio exit(EXIT_FAILURE); 405fc9c5412SJohannes Schauer } 40695059f9cSRichard Henderson /* The representation is size - 1, with 0 remaining "default". */ 40795059f9cSRichard Henderson reserved_va = val ? val - 1 : 0; 408fc9c5412SJohannes Schauer } 409fc9c5412SJohannes Schauer 410e99c1f89SPeter Maydell static void handle_arg_one_insn_per_tb(const char *arg) 411fc9c5412SJohannes Schauer { 4123cfb0456SPeter Maydell opt_one_insn_per_tb = true; 413fc9c5412SJohannes Schauer } 414fc9c5412SJohannes Schauer 415fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg) 416fc9c5412SJohannes Schauer { 4174b25a506SJosh Kunz enable_strace = true; 418fc9c5412SJohannes Schauer } 419fc9c5412SJohannes Schauer 420fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg) 421fc9c5412SJohannes Schauer { 4227e563bfbSThomas Huth printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION 4230781dd6eSThomas Huth "\n" QEMU_COPYRIGHT "\n"); 4244d1275c2SRiku Voipio exit(EXIT_SUCCESS); 425fc9c5412SJohannes Schauer } 426fc9c5412SJohannes Schauer 4276533dd6eSLluís Vilanova static void handle_arg_trace(const char *arg) 4286533dd6eSLluís Vilanova { 42992eecfffSPaolo Bonzini trace_opt_parse(arg); 4306533dd6eSLluís Vilanova } 4316533dd6eSLluís Vilanova 432130ea832SMax Filippov #if defined(TARGET_XTENSA) 433130ea832SMax Filippov static void handle_arg_abi_call0(const char *arg) 434130ea832SMax Filippov { 435130ea832SMax Filippov xtensa_set_abi_call0(); 436130ea832SMax Filippov } 437130ea832SMax Filippov #endif 438130ea832SMax Filippov 4395584e2dbSIlya Leoshkevich static void handle_arg_perfmap(const char *arg) 4405584e2dbSIlya Leoshkevich { 4415584e2dbSIlya Leoshkevich perf_enable_perfmap(); 4425584e2dbSIlya Leoshkevich } 4435584e2dbSIlya Leoshkevich 4445584e2dbSIlya Leoshkevich static void handle_arg_jitdump(const char *arg) 4455584e2dbSIlya Leoshkevich { 4465584e2dbSIlya Leoshkevich perf_enable_jitdump(); 4475584e2dbSIlya Leoshkevich } 4485584e2dbSIlya Leoshkevich 449f308f64eSLluís Vilanova static QemuPluginList plugins = QTAILQ_HEAD_INITIALIZER(plugins); 450f308f64eSLluís Vilanova 451f308f64eSLluís Vilanova #ifdef CONFIG_PLUGIN 452f308f64eSLluís Vilanova static void handle_arg_plugin(const char *arg) 453f308f64eSLluís Vilanova { 454f308f64eSLluís Vilanova qemu_plugin_opt_parse(arg, &plugins); 455f308f64eSLluís Vilanova } 456f308f64eSLluís Vilanova #endif 457f308f64eSLluís Vilanova 458fc9c5412SJohannes Schauer struct qemu_argument { 459fc9c5412SJohannes Schauer const char *argv; 460fc9c5412SJohannes Schauer const char *env; 461fc9c5412SJohannes Schauer bool has_arg; 462fc9c5412SJohannes Schauer void (*handle_opt)(const char *arg); 463fc9c5412SJohannes Schauer const char *example; 464fc9c5412SJohannes Schauer const char *help; 465fc9c5412SJohannes Schauer }; 466fc9c5412SJohannes Schauer 46742644ceeSJim Meyering static const struct qemu_argument arg_table[] = { 468fc9c5412SJohannes Schauer {"h", "", false, handle_arg_help, 469fc9c5412SJohannes Schauer "", "print this help"}, 470daaf8c8eSMeador Inge {"help", "", false, handle_arg_help, 471daaf8c8eSMeador Inge "", ""}, 472fc9c5412SJohannes Schauer {"g", "QEMU_GDB", true, handle_arg_gdb, 473fc9c5412SJohannes Schauer "port", "wait gdb connection to 'port'"}, 474fc9c5412SJohannes Schauer {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix, 475fc9c5412SJohannes Schauer "path", "set the elf interpreter prefix to 'path'"}, 476fc9c5412SJohannes Schauer {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size, 477fc9c5412SJohannes Schauer "size", "set the stack size to 'size' bytes"}, 478fc9c5412SJohannes Schauer {"cpu", "QEMU_CPU", true, handle_arg_cpu, 479c8057f95SPeter Maydell "model", "select CPU (-cpu help for list)"}, 480fc9c5412SJohannes Schauer {"E", "QEMU_SET_ENV", true, handle_arg_set_env, 481fc9c5412SJohannes Schauer "var=value", "sets targets environment variable (see below)"}, 482fc9c5412SJohannes Schauer {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env, 483fc9c5412SJohannes Schauer "var", "unsets targets environment variable (see below)"}, 484fc9c5412SJohannes Schauer {"0", "QEMU_ARGV0", true, handle_arg_argv0, 485fc9c5412SJohannes Schauer "argv0", "forces target process argv[0] to be 'argv0'"}, 486fc9c5412SJohannes Schauer {"r", "QEMU_UNAME", true, handle_arg_uname, 487fc9c5412SJohannes Schauer "uname", "set qemu uname release string to 'uname'"}, 488fc9c5412SJohannes Schauer {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base, 489fc9c5412SJohannes Schauer "address", "set guest_base address to 'address'"}, 490fc9c5412SJohannes Schauer {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va, 491fc9c5412SJohannes Schauer "size", "reserve 'size' bytes for guest virtual address space"}, 492fc9c5412SJohannes Schauer {"d", "QEMU_LOG", true, handle_arg_log, 493989b697dSPeter Maydell "item[,...]", "enable logging of specified items " 494989b697dSPeter Maydell "(use '-d help' for a list of items)"}, 4958423fa90SAlex Bennée {"dfilter", "QEMU_DFILTER", true, handle_arg_dfilter, 4968423fa90SAlex Bennée "range[,...]","filter logging based on address range"}, 49750171d42S陳韋任 {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename, 498989b697dSPeter Maydell "logfile", "write logs to 'logfile' (default stderr)"}, 499fc9c5412SJohannes Schauer {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize, 50001e44980SRichard Henderson "pagesize", "deprecated change to host page size"}, 501e99c1f89SPeter Maydell {"one-insn-per-tb", 502e99c1f89SPeter Maydell "QEMU_ONE_INSN_PER_TB", false, handle_arg_one_insn_per_tb, 503e99c1f89SPeter Maydell "", "run with one guest instruction per emulated TB"}, 504fc9c5412SJohannes Schauer {"strace", "QEMU_STRACE", false, handle_arg_strace, 505fc9c5412SJohannes Schauer "", "log system calls"}, 5065ebdd774SRichard Henderson {"seed", "QEMU_RAND_SEED", true, handle_arg_seed, 507c5e4a5a9SMagnus Reftel "", "Seed for pseudo-random number generator"}, 5086533dd6eSLluís Vilanova {"trace", "QEMU_TRACE", true, handle_arg_trace, 5096533dd6eSLluís Vilanova "", "[[enable=]<pattern>][,events=<file>][,file=<file>]"}, 510f308f64eSLluís Vilanova #ifdef CONFIG_PLUGIN 511f308f64eSLluís Vilanova {"plugin", "QEMU_PLUGIN", true, handle_arg_plugin, 5123a445acbSMahmoud Mandour "", "[file=]<file>[,<argname>=<argvalue>]"}, 513f308f64eSLluís Vilanova #endif 514fc9c5412SJohannes Schauer {"version", "QEMU_VERSION", false, handle_arg_version, 5151386d4c0SPeter Maydell "", "display version information and exit"}, 516130ea832SMax Filippov #if defined(TARGET_XTENSA) 517130ea832SMax Filippov {"xtensa-abi-call0", "QEMU_XTENSA_ABI_CALL0", false, handle_arg_abi_call0, 518130ea832SMax Filippov "", "assume CALL0 Xtensa ABI"}, 519130ea832SMax Filippov #endif 5205584e2dbSIlya Leoshkevich {"perfmap", "QEMU_PERFMAP", false, handle_arg_perfmap, 5215584e2dbSIlya Leoshkevich "", "Generate a /tmp/perf-${pid}.map file for perf"}, 5225584e2dbSIlya Leoshkevich {"jitdump", "QEMU_JITDUMP", false, handle_arg_jitdump, 5235584e2dbSIlya Leoshkevich "", "Generate a jit-${pid}.dump file for perf"}, 524fc9c5412SJohannes Schauer {NULL, NULL, false, NULL, NULL, NULL} 525fc9c5412SJohannes Schauer }; 526fc9c5412SJohannes Schauer 527d03f9c32SMeador Inge static void usage(int exitcode) 528fc9c5412SJohannes Schauer { 52942644ceeSJim Meyering const struct qemu_argument *arginfo; 530fc9c5412SJohannes Schauer int maxarglen; 531fc9c5412SJohannes Schauer int maxenvlen; 532fc9c5412SJohannes Schauer 5332e59915dSPaolo Bonzini printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n" 5342e59915dSPaolo Bonzini "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n" 535fc9c5412SJohannes Schauer "\n" 536fc9c5412SJohannes Schauer "Options and associated environment variables:\n" 537fc9c5412SJohannes Schauer "\n"); 538fc9c5412SJohannes Schauer 53963ec54d7SPeter Maydell /* Calculate column widths. We must always have at least enough space 54063ec54d7SPeter Maydell * for the column header. 54163ec54d7SPeter Maydell */ 54263ec54d7SPeter Maydell maxarglen = strlen("Argument"); 54363ec54d7SPeter Maydell maxenvlen = strlen("Env-variable"); 544fc9c5412SJohannes Schauer 545fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 54663ec54d7SPeter Maydell int arglen = strlen(arginfo->argv); 54763ec54d7SPeter Maydell if (arginfo->has_arg) { 54863ec54d7SPeter Maydell arglen += strlen(arginfo->example) + 1; 54963ec54d7SPeter Maydell } 550fc9c5412SJohannes Schauer if (strlen(arginfo->env) > maxenvlen) { 551fc9c5412SJohannes Schauer maxenvlen = strlen(arginfo->env); 552fc9c5412SJohannes Schauer } 55363ec54d7SPeter Maydell if (arglen > maxarglen) { 55463ec54d7SPeter Maydell maxarglen = arglen; 555fc9c5412SJohannes Schauer } 556fc9c5412SJohannes Schauer } 557fc9c5412SJohannes Schauer 55863ec54d7SPeter Maydell printf("%-*s %-*s Description\n", maxarglen+1, "Argument", 55963ec54d7SPeter Maydell maxenvlen, "Env-variable"); 560fc9c5412SJohannes Schauer 561fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 562fc9c5412SJohannes Schauer if (arginfo->has_arg) { 563fc9c5412SJohannes Schauer printf("-%s %-*s %-*s %s\n", arginfo->argv, 56463ec54d7SPeter Maydell (int)(maxarglen - strlen(arginfo->argv) - 1), 56563ec54d7SPeter Maydell arginfo->example, maxenvlen, arginfo->env, arginfo->help); 566fc9c5412SJohannes Schauer } else { 56763ec54d7SPeter Maydell printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv, 568fc9c5412SJohannes Schauer maxenvlen, arginfo->env, 569fc9c5412SJohannes Schauer arginfo->help); 570fc9c5412SJohannes Schauer } 571fc9c5412SJohannes Schauer } 572fc9c5412SJohannes Schauer 573fc9c5412SJohannes Schauer printf("\n" 574fc9c5412SJohannes Schauer "Defaults:\n" 575fc9c5412SJohannes Schauer "QEMU_LD_PREFIX = %s\n" 576989b697dSPeter Maydell "QEMU_STACK_SIZE = %ld byte\n", 577fc9c5412SJohannes Schauer interp_prefix, 578989b697dSPeter Maydell guest_stack_size); 579fc9c5412SJohannes Schauer 580fc9c5412SJohannes Schauer printf("\n" 581fc9c5412SJohannes Schauer "You can use -E and -U options or the QEMU_SET_ENV and\n" 582fc9c5412SJohannes Schauer "QEMU_UNSET_ENV environment variables to set and unset\n" 583fc9c5412SJohannes Schauer "environment variables for the target process.\n" 584fc9c5412SJohannes Schauer "It is possible to provide several variables by separating them\n" 585fc9c5412SJohannes Schauer "by commas in getsubopt(3) style. Additionally it is possible to\n" 586fc9c5412SJohannes Schauer "provide the -E and -U options multiple times.\n" 587fc9c5412SJohannes Schauer "The following lines are equivalent:\n" 588fc9c5412SJohannes Schauer " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n" 589fc9c5412SJohannes Schauer " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n" 590fc9c5412SJohannes Schauer " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n" 591fc9c5412SJohannes Schauer "Note that if you provide several changes to a single variable\n" 592f5048cb7SEric Blake "the last change will stay in effect.\n" 593f5048cb7SEric Blake "\n" 594f5048cb7SEric Blake QEMU_HELP_BOTTOM "\n"); 595fc9c5412SJohannes Schauer 596d03f9c32SMeador Inge exit(exitcode); 597fc9c5412SJohannes Schauer } 598fc9c5412SJohannes Schauer 599fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv) 600fc9c5412SJohannes Schauer { 601fc9c5412SJohannes Schauer const char *r; 602fc9c5412SJohannes Schauer int optind; 60342644ceeSJim Meyering const struct qemu_argument *arginfo; 604fc9c5412SJohannes Schauer 605fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 606fc9c5412SJohannes Schauer if (arginfo->env == NULL) { 607fc9c5412SJohannes Schauer continue; 608fc9c5412SJohannes Schauer } 609fc9c5412SJohannes Schauer 610fc9c5412SJohannes Schauer r = getenv(arginfo->env); 611fc9c5412SJohannes Schauer if (r != NULL) { 612fc9c5412SJohannes Schauer arginfo->handle_opt(r); 613fc9c5412SJohannes Schauer } 614fc9c5412SJohannes Schauer } 615fc9c5412SJohannes Schauer 616fc9c5412SJohannes Schauer optind = 1; 617fc9c5412SJohannes Schauer for (;;) { 618fc9c5412SJohannes Schauer if (optind >= argc) { 619fc9c5412SJohannes Schauer break; 620fc9c5412SJohannes Schauer } 621fc9c5412SJohannes Schauer r = argv[optind]; 622fc9c5412SJohannes Schauer if (r[0] != '-') { 623fc9c5412SJohannes Schauer break; 624fc9c5412SJohannes Schauer } 625fc9c5412SJohannes Schauer optind++; 626fc9c5412SJohannes Schauer r++; 627fc9c5412SJohannes Schauer if (!strcmp(r, "-")) { 628fc9c5412SJohannes Schauer break; 629fc9c5412SJohannes Schauer } 630ba02577cSMeador Inge /* Treat --foo the same as -foo. */ 631ba02577cSMeador Inge if (r[0] == '-') { 632ba02577cSMeador Inge r++; 633ba02577cSMeador Inge } 634fc9c5412SJohannes Schauer 635fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 636fc9c5412SJohannes Schauer if (!strcmp(r, arginfo->argv)) { 6371386d4c0SPeter Maydell if (arginfo->has_arg) { 638fc9c5412SJohannes Schauer if (optind >= argc) { 639138940bfSMeador Inge (void) fprintf(stderr, 640138940bfSMeador Inge "qemu: missing argument for option '%s'\n", r); 6414d1275c2SRiku Voipio exit(EXIT_FAILURE); 642fc9c5412SJohannes Schauer } 643fc9c5412SJohannes Schauer arginfo->handle_opt(argv[optind]); 644fc9c5412SJohannes Schauer optind++; 6451386d4c0SPeter Maydell } else { 6461386d4c0SPeter Maydell arginfo->handle_opt(NULL); 647fc9c5412SJohannes Schauer } 648fc9c5412SJohannes Schauer break; 649fc9c5412SJohannes Schauer } 650fc9c5412SJohannes Schauer } 651fc9c5412SJohannes Schauer 652fc9c5412SJohannes Schauer /* no option matched the current argv */ 653fc9c5412SJohannes Schauer if (arginfo->handle_opt == NULL) { 654138940bfSMeador Inge (void) fprintf(stderr, "qemu: unknown option '%s'\n", r); 6554d1275c2SRiku Voipio exit(EXIT_FAILURE); 656fc9c5412SJohannes Schauer } 657fc9c5412SJohannes Schauer } 658fc9c5412SJohannes Schauer 659fc9c5412SJohannes Schauer if (optind >= argc) { 660138940bfSMeador Inge (void) fprintf(stderr, "qemu: no user program specified\n"); 6614d1275c2SRiku Voipio exit(EXIT_FAILURE); 662fc9c5412SJohannes Schauer } 663fc9c5412SJohannes Schauer 664fc9c5412SJohannes Schauer exec_path = argv[optind]; 665fc9c5412SJohannes Schauer 666fc9c5412SJohannes Schauer return optind; 667fc9c5412SJohannes Schauer } 668fc9c5412SJohannes Schauer 669902b3d5cSmalc int main(int argc, char **argv, char **envp) 67031e31b8aSbellard { 67101ffc75bSbellard struct target_pt_regs regs1, *regs = ®s1; 67231e31b8aSbellard struct image_info info1, *info = &info1; 673edf8e2afSMika Westerberg struct linux_binprm bprm; 67448e15fc2SNathan Froyd TaskState *ts; 6759349b4f9SAndreas Färber CPUArchState *env; 676db6b81d4SAndreas Färber CPUState *cpu; 677586314f2Sbellard int optind; 67804a6dfebSaurel32 char **target_environ, **wrk; 6797d8cec95Saurel32 char **target_argv; 6807d8cec95Saurel32 int target_argc; 6817d8cec95Saurel32 int i; 682fd4d81ddSArnaud Patard int ret; 68303cfd8faSLaurent Vivier int execfd; 684ff8a8bbcSRichard Henderson int host_page_size; 6858f67b9c6SRichard Henderson unsigned long max_reserved_va; 6866e1c0d7bSLaurent Vivier bool preserve_argv0; 68731e31b8aSbellard 688f5852efaSChristophe Fergeau error_init(argv[0]); 689fe4db84dSDaniel P. Berrange module_call_init(MODULE_INIT_TRACE); 690267f685bSPaolo Bonzini qemu_init_cpu_list(); 691ce008c1fSAndreas Färber module_call_init(MODULE_INIT_QOM); 692ce008c1fSAndreas Färber 693ec45bbe5SSaurav Sachidanand envlist = envlist_create(); 69404a6dfebSaurel32 6957f750efcSAndreas Schwab /* 6967f750efcSAndreas Schwab * add current environment into the list 6977f750efcSAndreas Schwab * envlist_setenv adds to the front of the list; to preserve environ 6987f750efcSAndreas Schwab * order add from back to front 6997f750efcSAndreas Schwab */ 70004a6dfebSaurel32 for (wrk = environ; *wrk != NULL; wrk++) { 7017f750efcSAndreas Schwab continue; 7027f750efcSAndreas Schwab } 7037f750efcSAndreas Schwab while (wrk != environ) { 7047f750efcSAndreas Schwab wrk--; 70504a6dfebSaurel32 (void) envlist_setenv(envlist, *wrk); 70604a6dfebSaurel32 } 70704a6dfebSaurel32 708703e0e89SRichard Henderson /* Read the stack limit from the kernel. If it's "unlimited", 709703e0e89SRichard Henderson then we can do little else besides use the default. */ 710703e0e89SRichard Henderson { 711703e0e89SRichard Henderson struct rlimit lim; 712703e0e89SRichard Henderson if (getrlimit(RLIMIT_STACK, &lim) == 0 71381bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur != RLIM_INFINITY 7140a3346b5SHelge Deller && lim.rlim_cur == (target_long)lim.rlim_cur 7150a3346b5SHelge Deller && lim.rlim_cur > guest_stack_size) { 716703e0e89SRichard Henderson guest_stack_size = lim.rlim_cur; 717703e0e89SRichard Henderson } 718703e0e89SRichard Henderson } 719703e0e89SRichard Henderson 720b1f9be31Sj_mayer cpu_model = NULL; 721b5ec5ce0Sjohn cooper 7226533dd6eSLluís Vilanova qemu_add_opts(&qemu_trace_opts); 723f308f64eSLluís Vilanova qemu_plugin_add_opts(); 7246533dd6eSLluís Vilanova 725fc9c5412SJohannes Schauer optind = parse_args(argc, argv); 7264b5dfd82SPeter Maydell 727b410253fSRichard Henderson qemu_set_log_filename_flags(last_log_filename, 728b410253fSRichard Henderson last_log_mask | (enable_strace * LOG_STRACE), 729b410253fSRichard Henderson &error_fatal); 7304b25a506SJosh Kunz 7316533dd6eSLluís Vilanova if (!trace_init_backends()) { 7326533dd6eSLluís Vilanova exit(1); 7336533dd6eSLluís Vilanova } 73492eecfffSPaolo Bonzini trace_init_file(); 7350572f558SPaolo Bonzini qemu_plugin_load_list(&plugins, &error_fatal); 7366533dd6eSLluís Vilanova 73731e31b8aSbellard /* Zero out regs */ 73801ffc75bSbellard memset(regs, 0, sizeof(struct target_pt_regs)); 73931e31b8aSbellard 74031e31b8aSbellard /* Zero out image_info */ 74131e31b8aSbellard memset(info, 0, sizeof(struct image_info)); 74231e31b8aSbellard 743edf8e2afSMika Westerberg memset(&bprm, 0, sizeof (bprm)); 744edf8e2afSMika Westerberg 74574cd30b8Sbellard /* Scan interp_prefix dir for replacement files. */ 74674cd30b8Sbellard init_paths(interp_prefix); 74774cd30b8Sbellard 7484a24a758SPeter Maydell init_qemu_uname_release(); 7494a24a758SPeter Maydell 7506e1c0d7bSLaurent Vivier /* 7516e1c0d7bSLaurent Vivier * Manage binfmt-misc open-binary flag 7526e1c0d7bSLaurent Vivier */ 753768fe76eSYunQiang Su execfd = qemu_getauxval(AT_EXECFD); 754768fe76eSYunQiang Su if (execfd == 0) { 7559d3019bcSLaurent Vivier execfd = open(exec_path, O_RDONLY); 756768fe76eSYunQiang Su if (execfd < 0) { 7579d3019bcSLaurent Vivier printf("Error while loading %s: %s\n", exec_path, strerror(errno)); 758768fe76eSYunQiang Su _exit(EXIT_FAILURE); 759768fe76eSYunQiang Su } 760768fe76eSYunQiang Su } 761768fe76eSYunQiang Su 762258bec39SHelge Deller /* Resolve executable file name to full path name */ 763258bec39SHelge Deller if (realpath(exec_path, real_exec_path)) { 764258bec39SHelge Deller exec_path = real_exec_path; 765258bec39SHelge Deller } 766258bec39SHelge Deller 7676e1c0d7bSLaurent Vivier /* 7686e1c0d7bSLaurent Vivier * get binfmt_misc flags 7696e1c0d7bSLaurent Vivier */ 7706e1c0d7bSLaurent Vivier preserve_argv0 = !!(qemu_getauxval(AT_FLAGS) & AT_FLAGS_PRESERVE_ARGV0); 7716e1c0d7bSLaurent Vivier 7726e1c0d7bSLaurent Vivier /* 7736e1c0d7bSLaurent Vivier * Manage binfmt-misc preserve-arg[0] flag 7746e1c0d7bSLaurent Vivier * argv[optind] full path to the binary 7756e1c0d7bSLaurent Vivier * argv[optind + 1] original argv[0] 7766e1c0d7bSLaurent Vivier */ 7776e1c0d7bSLaurent Vivier if (optind + 1 < argc && preserve_argv0) { 7786e1c0d7bSLaurent Vivier optind++; 7796e1c0d7bSLaurent Vivier } 7806e1c0d7bSLaurent Vivier 78146027c07Sbellard if (cpu_model == NULL) { 782768fe76eSYunQiang Su cpu_model = cpu_get_model(get_elf_eflags(execfd)); 783aaed909aSbellard } 784c1c8cfe5SEduardo Habkost cpu_type = parse_cpu_option(cpu_model); 7852278b939SIgor Mammedov 78613c13397SRichard Henderson /* init tcg before creating CPUs */ 787940e43aaSClaudio Fontana { 7883cfb0456SPeter Maydell AccelState *accel = current_accel(); 7893cfb0456SPeter Maydell AccelClass *ac = ACCEL_GET_CLASS(accel); 7902278b939SIgor Mammedov 791b86f59c7SClaudio Fontana accel_init_interfaces(ac); 7923cfb0456SPeter Maydell object_property_set_bool(OBJECT(accel), "one-insn-per-tb", 7933cfb0456SPeter Maydell opt_one_insn_per_tb, &error_abort); 79492242f34SClaudio Fontana ac->init_machine(NULL); 795940e43aaSClaudio Fontana } 796ff8a8bbcSRichard Henderson 797ff8a8bbcSRichard Henderson /* 798ff8a8bbcSRichard Henderson * Finalize page size before creating CPUs. 799ff8a8bbcSRichard Henderson * This will do nothing if !TARGET_PAGE_BITS_VARY. 800ff8a8bbcSRichard Henderson * The most efficient setting is to match the host. 801ff8a8bbcSRichard Henderson */ 802ff8a8bbcSRichard Henderson host_page_size = qemu_real_host_page_size(); 803ff8a8bbcSRichard Henderson set_preferred_target_page_bits(ctz32(host_page_size)); 804ff8a8bbcSRichard Henderson finalize_target_page_bits(); 805ff8a8bbcSRichard Henderson 8062278b939SIgor Mammedov cpu = cpu_create(cpu_type); 807b77af26eSRichard Henderson env = cpu_env(cpu); 8080ac46af3SAndreas Färber cpu_reset(cpu); 809db6b81d4SAndreas Färber thread_cpu = cpu; 81054936004Sbellard 8118f67b9c6SRichard Henderson /* 8128f67b9c6SRichard Henderson * Reserving too much vm space via mmap can run into problems 8138f67b9c6SRichard Henderson * with rlimits, oom due to page table creation, etc. We will 8148f67b9c6SRichard Henderson * still try it, if directed by the command-line option, but 8158f67b9c6SRichard Henderson * not by default. 8168f67b9c6SRichard Henderson */ 8178f67b9c6SRichard Henderson max_reserved_va = MAX_RESERVED_VA(cpu); 8188f67b9c6SRichard Henderson if (reserved_va != 0) { 81913c13397SRichard Henderson if ((reserved_va + 1) % host_page_size) { 82013c13397SRichard Henderson char *s = size_to_str(host_page_size); 8212f7828b5SRichard Henderson fprintf(stderr, "Reserved virtual address not aligned mod %s\n", s); 8222f7828b5SRichard Henderson g_free(s); 8232f7828b5SRichard Henderson exit(EXIT_FAILURE); 8242f7828b5SRichard Henderson } 8258f67b9c6SRichard Henderson if (max_reserved_va && reserved_va > max_reserved_va) { 8268f67b9c6SRichard Henderson fprintf(stderr, "Reserved virtual address too big\n"); 8278f67b9c6SRichard Henderson exit(EXIT_FAILURE); 8288f67b9c6SRichard Henderson } 8298f67b9c6SRichard Henderson } else if (HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32) { 83095059f9cSRichard Henderson /* MAX_RESERVED_VA + 1 is a large power of 2, so is aligned. */ 83195059f9cSRichard Henderson reserved_va = max_reserved_va; 8328f67b9c6SRichard Henderson } 8338f67b9c6SRichard Henderson 834c8fb5cf9SRichard Henderson /* 835c8fb5cf9SRichard Henderson * Temporarily disable 836c8fb5cf9SRichard Henderson * "comparison is always false due to limited range of data type" 837c8fb5cf9SRichard Henderson * due to comparison between (possible) uint64_t and uintptr_t. 838c8fb5cf9SRichard Henderson */ 839c8fb5cf9SRichard Henderson #pragma GCC diagnostic push 840c8fb5cf9SRichard Henderson #pragma GCC diagnostic ignored "-Wtype-limits" 841c8fb5cf9SRichard Henderson 842c8fb5cf9SRichard Henderson /* 843c8fb5cf9SRichard Henderson * Select an initial value for task_unmapped_base that is in range. 844c8fb5cf9SRichard Henderson */ 845c8fb5cf9SRichard Henderson if (reserved_va) { 846c8fb5cf9SRichard Henderson if (TASK_UNMAPPED_BASE < reserved_va) { 847c8fb5cf9SRichard Henderson task_unmapped_base = TASK_UNMAPPED_BASE; 848c8fb5cf9SRichard Henderson } else { 849c8fb5cf9SRichard Henderson /* The most common default formula is TASK_SIZE / 3. */ 850c8fb5cf9SRichard Henderson task_unmapped_base = TARGET_PAGE_ALIGN(reserved_va / 3); 851c8fb5cf9SRichard Henderson } 852c8fb5cf9SRichard Henderson } else if (TASK_UNMAPPED_BASE < UINTPTR_MAX) { 853c8fb5cf9SRichard Henderson task_unmapped_base = TASK_UNMAPPED_BASE; 854c8fb5cf9SRichard Henderson } else { 855c8fb5cf9SRichard Henderson /* 32-bit host: pick something medium size. */ 856c8fb5cf9SRichard Henderson task_unmapped_base = 0x10000000; 857c8fb5cf9SRichard Henderson } 858c8fb5cf9SRichard Henderson mmap_next_start = task_unmapped_base; 859c8fb5cf9SRichard Henderson 860da2b71faSRichard Henderson /* Similarly for elf_et_dyn_base. */ 861da2b71faSRichard Henderson if (reserved_va) { 862da2b71faSRichard Henderson if (ELF_ET_DYN_BASE < reserved_va) { 863da2b71faSRichard Henderson elf_et_dyn_base = ELF_ET_DYN_BASE; 864da2b71faSRichard Henderson } else { 865da2b71faSRichard Henderson /* The most common default formula is TASK_SIZE / 3 * 2. */ 866da2b71faSRichard Henderson elf_et_dyn_base = TARGET_PAGE_ALIGN(reserved_va / 3) * 2; 867da2b71faSRichard Henderson } 868da2b71faSRichard Henderson } else if (ELF_ET_DYN_BASE < UINTPTR_MAX) { 869da2b71faSRichard Henderson elf_et_dyn_base = ELF_ET_DYN_BASE; 870da2b71faSRichard Henderson } else { 871da2b71faSRichard Henderson /* 32-bit host: pick something medium size. */ 872da2b71faSRichard Henderson elf_et_dyn_base = 0x18000000; 873da2b71faSRichard Henderson } 874da2b71faSRichard Henderson 875c8fb5cf9SRichard Henderson #pragma GCC diagnostic pop 876c8fb5cf9SRichard Henderson 877a573e9baSRichard Henderson { 878a573e9baSRichard Henderson Error *err = NULL; 8795ebdd774SRichard Henderson if (seed_optarg != NULL) { 880a573e9baSRichard Henderson qemu_guest_random_seed_main(seed_optarg, &err); 881a573e9baSRichard Henderson } else { 882a573e9baSRichard Henderson qcrypto_init(&err); 883a573e9baSRichard Henderson } 884a573e9baSRichard Henderson if (err) { 885a573e9baSRichard Henderson error_reportf_err(err, "cannot initialize crypto: "); 886a573e9baSRichard Henderson exit(1); 887a573e9baSRichard Henderson } 888c5e4a5a9SMagnus Reftel } 889c5e4a5a9SMagnus Reftel 89004a6dfebSaurel32 target_environ = envlist_to_environ(envlist, NULL); 89104a6dfebSaurel32 envlist_free(envlist); 892b12b6a18Sths 893379f6698SPaul Brook /* 894379f6698SPaul Brook * Read in mmap_min_addr kernel parameter. This value is used 895379f6698SPaul Brook * When loading the ELF image to determine whether guest_base 89614f24e14SRichard Henderson * is needed. It is also used in mmap_find_vma. 897379f6698SPaul Brook */ 89814f24e14SRichard Henderson { 899379f6698SPaul Brook FILE *fp; 900379f6698SPaul Brook 901379f6698SPaul Brook if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) { 902379f6698SPaul Brook unsigned long tmp; 903c9f80666SRichard Henderson if (fscanf(fp, "%lu", &tmp) == 1 && tmp != 0) { 904*78b79b2cSRichard Henderson mmap_min_addr = MAX(tmp, host_page_size); 905c9f80666SRichard Henderson qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n", 906c9f80666SRichard Henderson mmap_min_addr); 907379f6698SPaul Brook } 908379f6698SPaul Brook fclose(fp); 909379f6698SPaul Brook } 910379f6698SPaul Brook } 911379f6698SPaul Brook 9127d8cec95Saurel32 /* 913c9f80666SRichard Henderson * We prefer to not make NULL pointers accessible to QEMU. 914c9f80666SRichard Henderson * If we're in a chroot with no /proc, fall back to 1 page. 915c9f80666SRichard Henderson */ 916c9f80666SRichard Henderson if (mmap_min_addr == 0) { 917ff8a8bbcSRichard Henderson mmap_min_addr = host_page_size; 918c9f80666SRichard Henderson qemu_log_mask(CPU_LOG_PAGE, 919c9f80666SRichard Henderson "host mmap_min_addr=0x%lx (fallback)\n", 920c9f80666SRichard Henderson mmap_min_addr); 921c9f80666SRichard Henderson } 922c9f80666SRichard Henderson 923c9f80666SRichard Henderson /* 9247d8cec95Saurel32 * Prepare copy of argv vector for target. 9257d8cec95Saurel32 */ 9267d8cec95Saurel32 target_argc = argc - optind; 9277d8cec95Saurel32 target_argv = calloc(target_argc + 1, sizeof (char *)); 9287d8cec95Saurel32 if (target_argv == NULL) { 9297d8cec95Saurel32 (void) fprintf(stderr, "Unable to allocate memory for target_argv\n"); 9304d1275c2SRiku Voipio exit(EXIT_FAILURE); 9317d8cec95Saurel32 } 9327d8cec95Saurel32 9337d8cec95Saurel32 /* 9347d8cec95Saurel32 * If argv0 is specified (using '-0' switch) we replace 9357d8cec95Saurel32 * argv[0] pointer with the given one. 9367d8cec95Saurel32 */ 9377d8cec95Saurel32 i = 0; 9387d8cec95Saurel32 if (argv0 != NULL) { 9397d8cec95Saurel32 target_argv[i++] = strdup(argv0); 9407d8cec95Saurel32 } 9417d8cec95Saurel32 for (; i < target_argc; i++) { 9427d8cec95Saurel32 target_argv[i] = strdup(argv[optind + i]); 9437d8cec95Saurel32 } 9447d8cec95Saurel32 target_argv[target_argc] = NULL; 9457d8cec95Saurel32 946c78d65e8SMarkus Armbruster ts = g_new0(TaskState, 1); 947edf8e2afSMika Westerberg init_task_state(ts); 948edf8e2afSMika Westerberg /* build Task State */ 949edf8e2afSMika Westerberg ts->info = info; 950edf8e2afSMika Westerberg ts->bprm = &bprm; 9510429a971SAndreas Färber cpu->opaque = ts; 952edf8e2afSMika Westerberg task_settid(ts); 953edf8e2afSMika Westerberg 954c093364fSOwen Anderson fd_trans_init(); 955c093364fSOwen Anderson 9569d3019bcSLaurent Vivier ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs, 957fd4d81ddSArnaud Patard info, &bprm); 958fd4d81ddSArnaud Patard if (ret != 0) { 9599d3019bcSLaurent Vivier printf("Error while loading %s: %s\n", exec_path, strerror(-ret)); 9604d1275c2SRiku Voipio _exit(EXIT_FAILURE); 96131e31b8aSbellard } 96231e31b8aSbellard 963b12b6a18Sths for (wrk = target_environ; *wrk; wrk++) { 964ec45bbe5SSaurav Sachidanand g_free(*wrk); 965b12b6a18Sths } 966b12b6a18Sths 967ec45bbe5SSaurav Sachidanand g_free(target_environ); 968b12b6a18Sths 96913829020SPaolo Bonzini if (qemu_loglevel_mask(CPU_LOG_PAGE)) { 97093756fdcSRichard Henderson FILE *f = qemu_log_trylock(); 97193756fdcSRichard Henderson if (f) { 97293756fdcSRichard Henderson fprintf(f, "guest_base %p\n", (void *)guest_base); 97393756fdcSRichard Henderson fprintf(f, "page layout changed following binary load\n"); 97493756fdcSRichard Henderson page_dump(f); 97554936004Sbellard 97693756fdcSRichard Henderson fprintf(f, "end_code 0x" TARGET_ABI_FMT_lx "\n", 97793756fdcSRichard Henderson info->end_code); 97893756fdcSRichard Henderson fprintf(f, "start_code 0x" TARGET_ABI_FMT_lx "\n", 97993756fdcSRichard Henderson info->start_code); 98093756fdcSRichard Henderson fprintf(f, "start_data 0x" TARGET_ABI_FMT_lx "\n", 98193756fdcSRichard Henderson info->start_data); 98293756fdcSRichard Henderson fprintf(f, "end_data 0x" TARGET_ABI_FMT_lx "\n", 98393756fdcSRichard Henderson info->end_data); 98493756fdcSRichard Henderson fprintf(f, "start_stack 0x" TARGET_ABI_FMT_lx "\n", 98593756fdcSRichard Henderson info->start_stack); 98693756fdcSRichard Henderson fprintf(f, "brk 0x" TARGET_ABI_FMT_lx "\n", 98793756fdcSRichard Henderson info->brk); 98893756fdcSRichard Henderson fprintf(f, "entry 0x" TARGET_ABI_FMT_lx "\n", 98993756fdcSRichard Henderson info->entry); 99093756fdcSRichard Henderson fprintf(f, "argv_start 0x" TARGET_ABI_FMT_lx "\n", 99160f1c801SRichard Henderson info->argv); 99293756fdcSRichard Henderson fprintf(f, "env_start 0x" TARGET_ABI_FMT_lx "\n", 99360f1c801SRichard Henderson info->envp); 99493756fdcSRichard Henderson fprintf(f, "auxv_start 0x" TARGET_ABI_FMT_lx "\n", 99593756fdcSRichard Henderson info->saved_auxv); 99693756fdcSRichard Henderson qemu_log_unlock(f); 99793756fdcSRichard Henderson } 9982e77eac6Sblueswir1 } 99931e31b8aSbellard 100053a5960aSpbrook target_set_brk(info->brk); 100131e31b8aSbellard syscall_init(); 100266fb9763Sbellard signal_init(); 100331e31b8aSbellard 10049002ec79SRichard Henderson /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay 10059002ec79SRichard Henderson generating the prologue until now so that the prologue can take 10069002ec79SRichard Henderson the real value of GUEST_BASE into account. */ 1007935f75aeSRichard Henderson tcg_prologue_init(); 10089002ec79SRichard Henderson 1009cd71c089SLaurent Vivier target_cpu_copy_regs(env, regs); 1010cd71c089SLaurent Vivier 1011fcedd920SAlex Bennée if (gdbstub) { 1012fcedd920SAlex Bennée if (gdbserver_start(gdbstub) < 0) { 1013fcedd920SAlex Bennée fprintf(stderr, "qemu: could not open gdbserver on %s\n", 1014fcedd920SAlex Bennée gdbstub); 10154d1275c2SRiku Voipio exit(EXIT_FAILURE); 1016ff7a981aSPeter Maydell } 1017db6b81d4SAndreas Färber gdb_handlesig(cpu, 0); 10181fddef4bSbellard } 1019e4a4aaa5SRichard Henderson 1020e4a4aaa5SRichard Henderson #ifdef CONFIG_SEMIHOSTING 1021e4a4aaa5SRichard Henderson qemu_semihosting_guestfd_init(); 1022e4a4aaa5SRichard Henderson #endif 1023e4a4aaa5SRichard Henderson 10241b6b029eSbellard cpu_loop(env); 10251b6b029eSbellard /* never exits */ 102631e31b8aSbellard return 0; 102731e31b8aSbellard } 1028