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" 44dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg.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" 575584e2dbSIlya Leoshkevich #include "accel/tcg/perf.h" 5804a6dfebSaurel32 59e4a4aaa5SRichard Henderson #ifdef CONFIG_SEMIHOSTING 60e4a4aaa5SRichard Henderson #include "semihosting/semihost.h" 61e4a4aaa5SRichard Henderson #endif 62e4a4aaa5SRichard Henderson 636e1c0d7bSLaurent Vivier #ifndef AT_FLAGS_PRESERVE_ARGV0 646e1c0d7bSLaurent Vivier #define AT_FLAGS_PRESERVE_ARGV0_BIT 0 656e1c0d7bSLaurent Vivier #define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT) 666e1c0d7bSLaurent Vivier #endif 676e1c0d7bSLaurent Vivier 68d088d664Saurel32 char *exec_path; 69258bec39SHelge Deller char real_exec_path[PATH_MAX]; 70d088d664Saurel32 711b530a6dSaurel32 int singlestep; 728cb76755SStefan Weil static const char *argv0; 73fcedd920SAlex Bennée static const char *gdbstub; 748cb76755SStefan Weil static envlist_t *envlist; 7551fb256aSAndreas Färber static const char *cpu_model; 762278b939SIgor Mammedov static const char *cpu_type; 775ebdd774SRichard Henderson static const char *seed_optarg; 78379f6698SPaul Brook unsigned long mmap_min_addr; 795ca870b9SRichard Henderson uintptr_t guest_base; 80e307c192SRichard Henderson bool have_guest_base; 81120a9848SPaolo Bonzini 82288e65b9SAlexander Graf /* 834b25a506SJosh Kunz * Used to implement backwards-compatibility for the `-strace`, and 844b25a506SJosh Kunz * QEMU_STRACE options. Without this, the QEMU_LOG can be overwritten by 854b25a506SJosh Kunz * -strace, or vice versa. 864b25a506SJosh Kunz */ 874b25a506SJosh Kunz static bool enable_strace; 884b25a506SJosh Kunz 894b25a506SJosh Kunz /* 904b25a506SJosh Kunz * The last log mask given by the user in an environment variable or argument. 914b25a506SJosh Kunz * Used to support command line arguments overriding environment variables. 924b25a506SJosh Kunz */ 934b25a506SJosh Kunz static int last_log_mask; 94b410253fSRichard Henderson static const char *last_log_filename; 954b25a506SJosh Kunz 964b25a506SJosh Kunz /* 97288e65b9SAlexander Graf * When running 32-on-64 we should make sure we can fit all of the possible 98288e65b9SAlexander Graf * guest address space into a contiguous chunk of virtual host memory. 99288e65b9SAlexander Graf * 100288e65b9SAlexander Graf * This way we will never overlap with our own libraries or binaries or stack 101288e65b9SAlexander Graf * or anything else that QEMU maps. 10218e80c55SRichard Henderson * 10318e80c55SRichard Henderson * Many cpus reserve the high bit (or more than one for some 64-bit cpus) 10418e80c55SRichard Henderson * of the address for the kernel. Some cpus rely on this and user space 10518e80c55SRichard Henderson * uses the high bit(s) for pointer tagging and the like. For them, we 10618e80c55SRichard Henderson * must preserve the expected address space. 107288e65b9SAlexander Graf */ 10818e80c55SRichard Henderson #ifndef MAX_RESERVED_VA 10918e80c55SRichard Henderson # if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS 11018e80c55SRichard Henderson # if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \ 11118e80c55SRichard Henderson (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32)) 11295059f9cSRichard Henderson # define MAX_RESERVED_VA(CPU) 0xfffffffful 113314992b1SAlexander Graf # else 11495059f9cSRichard Henderson # define MAX_RESERVED_VA(CPU) ((1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1) 115314992b1SAlexander Graf # endif 116288e65b9SAlexander Graf # else 1178f67b9c6SRichard Henderson # define MAX_RESERVED_VA(CPU) 0 11818e80c55SRichard Henderson # endif 11918e80c55SRichard Henderson #endif 12018e80c55SRichard Henderson 12168a1c816SPaul Brook unsigned long reserved_va; 1221b530a6dSaurel32 123d03f9c32SMeador Inge static void usage(int exitcode); 124fc9c5412SJohannes Schauer 1257ee2822cSPaolo Bonzini static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; 126e586822aSRiku Voipio const char *qemu_uname_release; 127586314f2Sbellard 1280a3346b5SHelge Deller #if !defined(TARGET_DEFAULT_STACK_SIZE) 1299de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so 1309de5e440Sbellard we allocate a bigger stack. Need a better solution, for example 1319de5e440Sbellard by remapping the process stack directly at the right place */ 1320a3346b5SHelge Deller #define TARGET_DEFAULT_STACK_SIZE 8 * 1024 * 1024UL 1330a3346b5SHelge Deller #endif 1340a3346b5SHelge Deller 1350a3346b5SHelge Deller unsigned long guest_stack_size = TARGET_DEFAULT_STACK_SIZE; 13631e31b8aSbellard 137d5975363Spbrook /***********************************************************/ 138d5975363Spbrook /* Helper routines for implementing atomic operations. */ 139d5975363Spbrook 140d5975363Spbrook /* Make sure everything is in a consistent state for calling fork(). */ 141d5975363Spbrook void fork_start(void) 142d5975363Spbrook { 14306065c45SPeter Maydell start_exclusive(); 144d032d1b4SRiku Voipio mmap_fork_start(); 145024949caSPeter Maydell cpu_list_lock(); 146f7e15affSAlex Bennée qemu_plugin_user_prefork_lock(); 147d5975363Spbrook } 148d5975363Spbrook 149d5975363Spbrook void fork_end(int child) 150d5975363Spbrook { 151f7e15affSAlex Bennée qemu_plugin_user_postfork(child); 152d032d1b4SRiku Voipio mmap_fork_end(child); 153d5975363Spbrook if (child) { 154bdc44640SAndreas Färber CPUState *cpu, *next_cpu; 155d5975363Spbrook /* Child processes created by fork() only have a single thread. 156d5975363Spbrook Discard information about the parent threads. */ 157bdc44640SAndreas Färber CPU_FOREACH_SAFE(cpu, next_cpu) { 158bdc44640SAndreas Färber if (cpu != thread_cpu) { 159068a5ea0SEmilio G. Cota QTAILQ_REMOVE_RCU(&cpus, cpu, node); 160bdc44640SAndreas Färber } 161bdc44640SAndreas Färber } 162267f685bSPaolo Bonzini qemu_init_cpu_list(); 163f7ec7f7bSPeter Crosthwaite gdbserver_fork(thread_cpu); 164d5975363Spbrook } else { 165267f685bSPaolo Bonzini cpu_list_unlock(); 166d5975363Spbrook } 1677de0816fSIlya Leoshkevich /* 1687de0816fSIlya Leoshkevich * qemu_init_cpu_list() reinitialized the child exclusive state, but we 1697de0816fSIlya Leoshkevich * also need to keep current_cpu consistent, so call end_exclusive() for 1707de0816fSIlya Leoshkevich * both child and parent. 1717de0816fSIlya Leoshkevich */ 1727de0816fSIlya Leoshkevich end_exclusive(); 173d5975363Spbrook } 174d5975363Spbrook 175b44316fbSPeter Maydell __thread CPUState *thread_cpu; 17659faf6d6Sbellard 177178f9429SSergey Fedorov bool qemu_cpu_is_self(CPUState *cpu) 178178f9429SSergey Fedorov { 179178f9429SSergey Fedorov return thread_cpu == cpu; 180178f9429SSergey Fedorov } 181178f9429SSergey Fedorov 182178f9429SSergey Fedorov void qemu_cpu_kick(CPUState *cpu) 183178f9429SSergey Fedorov { 184178f9429SSergey Fedorov cpu_exit(cpu); 185178f9429SSergey Fedorov } 186178f9429SSergey Fedorov 187edf8e2afSMika Westerberg void task_settid(TaskState *ts) 188edf8e2afSMika Westerberg { 189edf8e2afSMika Westerberg if (ts->ts_tid == 0) { 190edf8e2afSMika Westerberg ts->ts_tid = (pid_t)syscall(SYS_gettid); 191edf8e2afSMika Westerberg } 192edf8e2afSMika Westerberg } 193edf8e2afSMika Westerberg 194edf8e2afSMika Westerberg void stop_all_tasks(void) 195edf8e2afSMika Westerberg { 196edf8e2afSMika Westerberg /* 197edf8e2afSMika Westerberg * We trust that when using NPTL, start_exclusive() 198edf8e2afSMika Westerberg * handles thread stopping correctly. 199edf8e2afSMika Westerberg */ 200edf8e2afSMika Westerberg start_exclusive(); 201edf8e2afSMika Westerberg } 202edf8e2afSMika Westerberg 203c3a92833Spbrook /* Assumes contents are already zeroed. */ 204624f7979Spbrook void init_task_state(TaskState *ts) 205624f7979Spbrook { 206eb33cdaeSCameron Esfahani long ticks_per_sec; 207eb33cdaeSCameron Esfahani struct timespec bt; 208eb33cdaeSCameron Esfahani 209624f7979Spbrook ts->used = 1; 2105bfce0b7SPeter Maydell ts->sigaltstack_used = (struct target_sigaltstack) { 2115bfce0b7SPeter Maydell .ss_sp = 0, 2125bfce0b7SPeter Maydell .ss_size = 0, 2135bfce0b7SPeter Maydell .ss_flags = TARGET_SS_DISABLE, 2145bfce0b7SPeter Maydell }; 215eb33cdaeSCameron Esfahani 216eb33cdaeSCameron Esfahani /* Capture task start time relative to system boot */ 217eb33cdaeSCameron Esfahani 218eb33cdaeSCameron Esfahani ticks_per_sec = sysconf(_SC_CLK_TCK); 219eb33cdaeSCameron Esfahani 220eb33cdaeSCameron Esfahani if ((ticks_per_sec > 0) && !clock_gettime(CLOCK_BOOTTIME, &bt)) { 221eb33cdaeSCameron Esfahani /* start_boottime is expressed in clock ticks */ 222eb33cdaeSCameron Esfahani ts->start_boottime = bt.tv_sec * (uint64_t) ticks_per_sec; 223eb33cdaeSCameron Esfahani ts->start_boottime += bt.tv_nsec * (uint64_t) ticks_per_sec / 224eb33cdaeSCameron Esfahani NANOSECONDS_PER_SECOND; 225eb33cdaeSCameron Esfahani } 226624f7979Spbrook } 2279de5e440Sbellard 22830ba0ee5SAndreas Färber CPUArchState *cpu_copy(CPUArchState *env) 22930ba0ee5SAndreas Färber { 23029a0af61SRichard Henderson CPUState *cpu = env_cpu(env); 2312278b939SIgor Mammedov CPUState *new_cpu = cpu_create(cpu_type); 23261c7480fSLeon Alrae CPUArchState *new_env = new_cpu->env_ptr; 23330ba0ee5SAndreas Färber CPUBreakpoint *bp; 23430ba0ee5SAndreas Färber 23530ba0ee5SAndreas Färber /* Reset non arch specific state */ 23675a34036SAndreas Färber cpu_reset(new_cpu); 23730ba0ee5SAndreas Färber 2386cc9d67cSRichard Henderson new_cpu->tcg_cflags = cpu->tcg_cflags; 23930ba0ee5SAndreas Färber memcpy(new_env, env, sizeof(CPUArchState)); 2402732c739Sfanwj@mail.ustc.edu.cn #if defined(TARGET_I386) || defined(TARGET_X86_64) 2412732c739Sfanwj@mail.ustc.edu.cn new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, 2422732c739Sfanwj@mail.ustc.edu.cn PROT_READ | PROT_WRITE, 2432732c739Sfanwj@mail.ustc.edu.cn MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 2442732c739Sfanwj@mail.ustc.edu.cn memcpy(g2h_untagged(new_env->gdt.base), g2h_untagged(env->gdt.base), 2452732c739Sfanwj@mail.ustc.edu.cn sizeof(uint64_t) * TARGET_GDT_ENTRIES); 2462732c739Sfanwj@mail.ustc.edu.cn OBJECT(new_cpu)->free = OBJECT(cpu)->free; 2472732c739Sfanwj@mail.ustc.edu.cn #endif 24830ba0ee5SAndreas Färber 24930ba0ee5SAndreas Färber /* Clone all break/watchpoints. 25030ba0ee5SAndreas Färber Note: Once we support ptrace with hw-debug register access, make sure 25130ba0ee5SAndreas Färber BP_CPU break/watchpoints are handled correctly on clone. */ 2521d085f6cSThierry Bultel QTAILQ_INIT(&new_cpu->breakpoints); 253f0c3c505SAndreas Färber QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { 254b3310ab3SAndreas Färber cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL); 25530ba0ee5SAndreas Färber } 25630ba0ee5SAndreas Färber 25730ba0ee5SAndreas Färber return new_env; 25830ba0ee5SAndreas Färber } 25930ba0ee5SAndreas Färber 260fc9c5412SJohannes Schauer static void handle_arg_help(const char *arg) 261fc9c5412SJohannes Schauer { 2624d1275c2SRiku Voipio usage(EXIT_SUCCESS); 263fc9c5412SJohannes Schauer } 264fc9c5412SJohannes Schauer 265fc9c5412SJohannes Schauer static void handle_arg_log(const char *arg) 266fc9c5412SJohannes Schauer { 2674b25a506SJosh Kunz last_log_mask = qemu_str_to_log_mask(arg); 2684b25a506SJosh Kunz if (!last_log_mask) { 26959a6fa6eSPeter Maydell qemu_print_log_usage(stdout); 2704d1275c2SRiku Voipio exit(EXIT_FAILURE); 271fc9c5412SJohannes Schauer } 272fc9c5412SJohannes Schauer } 273fc9c5412SJohannes Schauer 2748423fa90SAlex Bennée static void handle_arg_dfilter(const char *arg) 2758423fa90SAlex Bennée { 2767f4341e8SAlex Bennée qemu_set_dfilter_ranges(arg, &error_fatal); 2778423fa90SAlex Bennée } 2788423fa90SAlex Bennée 27950171d42S陳韋任 static void handle_arg_log_filename(const char *arg) 28050171d42S陳韋任 { 281b410253fSRichard Henderson last_log_filename = arg; 28250171d42S陳韋任 } 28350171d42S陳韋任 284fc9c5412SJohannes Schauer static void handle_arg_set_env(const char *arg) 285fc9c5412SJohannes Schauer { 286fc9c5412SJohannes Schauer char *r, *p, *token; 287fc9c5412SJohannes Schauer r = p = strdup(arg); 288fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 289fc9c5412SJohannes Schauer if (envlist_setenv(envlist, token) != 0) { 2904d1275c2SRiku Voipio usage(EXIT_FAILURE); 291fc9c5412SJohannes Schauer } 292fc9c5412SJohannes Schauer } 293fc9c5412SJohannes Schauer free(r); 294fc9c5412SJohannes Schauer } 295fc9c5412SJohannes Schauer 296fc9c5412SJohannes Schauer static void handle_arg_unset_env(const char *arg) 297fc9c5412SJohannes Schauer { 298fc9c5412SJohannes Schauer char *r, *p, *token; 299fc9c5412SJohannes Schauer r = p = strdup(arg); 300fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 301fc9c5412SJohannes Schauer if (envlist_unsetenv(envlist, token) != 0) { 3024d1275c2SRiku Voipio usage(EXIT_FAILURE); 303fc9c5412SJohannes Schauer } 304fc9c5412SJohannes Schauer } 305fc9c5412SJohannes Schauer free(r); 306fc9c5412SJohannes Schauer } 307fc9c5412SJohannes Schauer 308fc9c5412SJohannes Schauer static void handle_arg_argv0(const char *arg) 309fc9c5412SJohannes Schauer { 310fc9c5412SJohannes Schauer argv0 = strdup(arg); 311fc9c5412SJohannes Schauer } 312fc9c5412SJohannes Schauer 313fc9c5412SJohannes Schauer static void handle_arg_stack_size(const char *arg) 314fc9c5412SJohannes Schauer { 315fc9c5412SJohannes Schauer char *p; 316fc9c5412SJohannes Schauer guest_stack_size = strtoul(arg, &p, 0); 317fc9c5412SJohannes Schauer if (guest_stack_size == 0) { 3184d1275c2SRiku Voipio usage(EXIT_FAILURE); 319fc9c5412SJohannes Schauer } 320fc9c5412SJohannes Schauer 321fc9c5412SJohannes Schauer if (*p == 'M') { 322b52713c1SPhilippe Mathieu-Daudé guest_stack_size *= MiB; 323fc9c5412SJohannes Schauer } else if (*p == 'k' || *p == 'K') { 324b52713c1SPhilippe Mathieu-Daudé guest_stack_size *= KiB; 325fc9c5412SJohannes Schauer } 326fc9c5412SJohannes Schauer } 327fc9c5412SJohannes Schauer 328fc9c5412SJohannes Schauer static void handle_arg_ld_prefix(const char *arg) 329fc9c5412SJohannes Schauer { 330fc9c5412SJohannes Schauer interp_prefix = strdup(arg); 331fc9c5412SJohannes Schauer } 332fc9c5412SJohannes Schauer 333fc9c5412SJohannes Schauer static void handle_arg_pagesize(const char *arg) 334fc9c5412SJohannes Schauer { 335fc9c5412SJohannes Schauer qemu_host_page_size = atoi(arg); 336fc9c5412SJohannes Schauer if (qemu_host_page_size == 0 || 337fc9c5412SJohannes Schauer (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { 338fc9c5412SJohannes Schauer fprintf(stderr, "page size must be a power of two\n"); 3394d1275c2SRiku Voipio exit(EXIT_FAILURE); 340fc9c5412SJohannes Schauer } 341fc9c5412SJohannes Schauer } 342fc9c5412SJohannes Schauer 3435ebdd774SRichard Henderson static void handle_arg_seed(const char *arg) 344c5e4a5a9SMagnus Reftel { 3455ebdd774SRichard Henderson seed_optarg = arg; 346c5e4a5a9SMagnus Reftel } 347c5e4a5a9SMagnus Reftel 348fc9c5412SJohannes Schauer static void handle_arg_gdb(const char *arg) 349fc9c5412SJohannes Schauer { 350fcedd920SAlex Bennée gdbstub = g_strdup(arg); 351fc9c5412SJohannes Schauer } 352fc9c5412SJohannes Schauer 353fc9c5412SJohannes Schauer static void handle_arg_uname(const char *arg) 354fc9c5412SJohannes Schauer { 355fc9c5412SJohannes Schauer qemu_uname_release = strdup(arg); 356fc9c5412SJohannes Schauer } 357fc9c5412SJohannes Schauer 358fc9c5412SJohannes Schauer static void handle_arg_cpu(const char *arg) 359fc9c5412SJohannes Schauer { 360fc9c5412SJohannes Schauer cpu_model = strdup(arg); 361c8057f95SPeter Maydell if (cpu_model == NULL || is_help_option(cpu_model)) { 362*b67e5cb4SThomas Huth list_cpus(); 3634d1275c2SRiku Voipio exit(EXIT_FAILURE); 364fc9c5412SJohannes Schauer } 365fc9c5412SJohannes Schauer } 366fc9c5412SJohannes Schauer 367fc9c5412SJohannes Schauer static void handle_arg_guest_base(const char *arg) 368fc9c5412SJohannes Schauer { 369fc9c5412SJohannes Schauer guest_base = strtol(arg, NULL, 0); 370e307c192SRichard Henderson have_guest_base = true; 371fc9c5412SJohannes Schauer } 372fc9c5412SJohannes Schauer 373fc9c5412SJohannes Schauer static void handle_arg_reserved_va(const char *arg) 374fc9c5412SJohannes Schauer { 375fc9c5412SJohannes Schauer char *p; 376fc9c5412SJohannes Schauer int shift = 0; 37795059f9cSRichard Henderson unsigned long val; 37895059f9cSRichard Henderson 37995059f9cSRichard Henderson val = strtoul(arg, &p, 0); 380fc9c5412SJohannes Schauer switch (*p) { 381fc9c5412SJohannes Schauer case 'k': 382fc9c5412SJohannes Schauer case 'K': 383fc9c5412SJohannes Schauer shift = 10; 384fc9c5412SJohannes Schauer break; 385fc9c5412SJohannes Schauer case 'M': 386fc9c5412SJohannes Schauer shift = 20; 387fc9c5412SJohannes Schauer break; 388fc9c5412SJohannes Schauer case 'G': 389fc9c5412SJohannes Schauer shift = 30; 390fc9c5412SJohannes Schauer break; 391fc9c5412SJohannes Schauer } 392fc9c5412SJohannes Schauer if (shift) { 39395059f9cSRichard Henderson unsigned long unshifted = val; 394fc9c5412SJohannes Schauer p++; 39595059f9cSRichard Henderson val <<= shift; 39695059f9cSRichard Henderson if (val >> shift != unshifted) { 397fc9c5412SJohannes Schauer fprintf(stderr, "Reserved virtual address too big\n"); 3984d1275c2SRiku Voipio exit(EXIT_FAILURE); 399fc9c5412SJohannes Schauer } 400fc9c5412SJohannes Schauer } 401fc9c5412SJohannes Schauer if (*p) { 402fc9c5412SJohannes Schauer fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p); 4034d1275c2SRiku Voipio exit(EXIT_FAILURE); 404fc9c5412SJohannes Schauer } 40595059f9cSRichard Henderson /* The representation is size - 1, with 0 remaining "default". */ 40695059f9cSRichard Henderson reserved_va = val ? val - 1 : 0; 407fc9c5412SJohannes Schauer } 408fc9c5412SJohannes Schauer 409fc9c5412SJohannes Schauer static void handle_arg_singlestep(const char *arg) 410fc9c5412SJohannes Schauer { 411fc9c5412SJohannes Schauer singlestep = 1; 412fc9c5412SJohannes Schauer } 413fc9c5412SJohannes Schauer 414fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg) 415fc9c5412SJohannes Schauer { 4164b25a506SJosh Kunz enable_strace = true; 417fc9c5412SJohannes Schauer } 418fc9c5412SJohannes Schauer 419fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg) 420fc9c5412SJohannes Schauer { 4217e563bfbSThomas Huth printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION 4220781dd6eSThomas Huth "\n" QEMU_COPYRIGHT "\n"); 4234d1275c2SRiku Voipio exit(EXIT_SUCCESS); 424fc9c5412SJohannes Schauer } 425fc9c5412SJohannes Schauer 4266533dd6eSLluís Vilanova static void handle_arg_trace(const char *arg) 4276533dd6eSLluís Vilanova { 42892eecfffSPaolo Bonzini trace_opt_parse(arg); 4296533dd6eSLluís Vilanova } 4306533dd6eSLluís Vilanova 431130ea832SMax Filippov #if defined(TARGET_XTENSA) 432130ea832SMax Filippov static void handle_arg_abi_call0(const char *arg) 433130ea832SMax Filippov { 434130ea832SMax Filippov xtensa_set_abi_call0(); 435130ea832SMax Filippov } 436130ea832SMax Filippov #endif 437130ea832SMax Filippov 4385584e2dbSIlya Leoshkevich static void handle_arg_perfmap(const char *arg) 4395584e2dbSIlya Leoshkevich { 4405584e2dbSIlya Leoshkevich perf_enable_perfmap(); 4415584e2dbSIlya Leoshkevich } 4425584e2dbSIlya Leoshkevich 4435584e2dbSIlya Leoshkevich static void handle_arg_jitdump(const char *arg) 4445584e2dbSIlya Leoshkevich { 4455584e2dbSIlya Leoshkevich perf_enable_jitdump(); 4465584e2dbSIlya Leoshkevich } 4475584e2dbSIlya Leoshkevich 448f308f64eSLluís Vilanova static QemuPluginList plugins = QTAILQ_HEAD_INITIALIZER(plugins); 449f308f64eSLluís Vilanova 450f308f64eSLluís Vilanova #ifdef CONFIG_PLUGIN 451f308f64eSLluís Vilanova static void handle_arg_plugin(const char *arg) 452f308f64eSLluís Vilanova { 453f308f64eSLluís Vilanova qemu_plugin_opt_parse(arg, &plugins); 454f308f64eSLluís Vilanova } 455f308f64eSLluís Vilanova #endif 456f308f64eSLluís Vilanova 457fc9c5412SJohannes Schauer struct qemu_argument { 458fc9c5412SJohannes Schauer const char *argv; 459fc9c5412SJohannes Schauer const char *env; 460fc9c5412SJohannes Schauer bool has_arg; 461fc9c5412SJohannes Schauer void (*handle_opt)(const char *arg); 462fc9c5412SJohannes Schauer const char *example; 463fc9c5412SJohannes Schauer const char *help; 464fc9c5412SJohannes Schauer }; 465fc9c5412SJohannes Schauer 46642644ceeSJim Meyering static const struct qemu_argument arg_table[] = { 467fc9c5412SJohannes Schauer {"h", "", false, handle_arg_help, 468fc9c5412SJohannes Schauer "", "print this help"}, 469daaf8c8eSMeador Inge {"help", "", false, handle_arg_help, 470daaf8c8eSMeador Inge "", ""}, 471fc9c5412SJohannes Schauer {"g", "QEMU_GDB", true, handle_arg_gdb, 472fc9c5412SJohannes Schauer "port", "wait gdb connection to 'port'"}, 473fc9c5412SJohannes Schauer {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix, 474fc9c5412SJohannes Schauer "path", "set the elf interpreter prefix to 'path'"}, 475fc9c5412SJohannes Schauer {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size, 476fc9c5412SJohannes Schauer "size", "set the stack size to 'size' bytes"}, 477fc9c5412SJohannes Schauer {"cpu", "QEMU_CPU", true, handle_arg_cpu, 478c8057f95SPeter Maydell "model", "select CPU (-cpu help for list)"}, 479fc9c5412SJohannes Schauer {"E", "QEMU_SET_ENV", true, handle_arg_set_env, 480fc9c5412SJohannes Schauer "var=value", "sets targets environment variable (see below)"}, 481fc9c5412SJohannes Schauer {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env, 482fc9c5412SJohannes Schauer "var", "unsets targets environment variable (see below)"}, 483fc9c5412SJohannes Schauer {"0", "QEMU_ARGV0", true, handle_arg_argv0, 484fc9c5412SJohannes Schauer "argv0", "forces target process argv[0] to be 'argv0'"}, 485fc9c5412SJohannes Schauer {"r", "QEMU_UNAME", true, handle_arg_uname, 486fc9c5412SJohannes Schauer "uname", "set qemu uname release string to 'uname'"}, 487fc9c5412SJohannes Schauer {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base, 488fc9c5412SJohannes Schauer "address", "set guest_base address to 'address'"}, 489fc9c5412SJohannes Schauer {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va, 490fc9c5412SJohannes Schauer "size", "reserve 'size' bytes for guest virtual address space"}, 491fc9c5412SJohannes Schauer {"d", "QEMU_LOG", true, handle_arg_log, 492989b697dSPeter Maydell "item[,...]", "enable logging of specified items " 493989b697dSPeter Maydell "(use '-d help' for a list of items)"}, 4948423fa90SAlex Bennée {"dfilter", "QEMU_DFILTER", true, handle_arg_dfilter, 4958423fa90SAlex Bennée "range[,...]","filter logging based on address range"}, 49650171d42S陳韋任 {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename, 497989b697dSPeter Maydell "logfile", "write logs to 'logfile' (default stderr)"}, 498fc9c5412SJohannes Schauer {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize, 499fc9c5412SJohannes Schauer "pagesize", "set the host page size to 'pagesize'"}, 500fc9c5412SJohannes Schauer {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep, 501fc9c5412SJohannes Schauer "", "run in singlestep mode"}, 502fc9c5412SJohannes Schauer {"strace", "QEMU_STRACE", false, handle_arg_strace, 503fc9c5412SJohannes Schauer "", "log system calls"}, 5045ebdd774SRichard Henderson {"seed", "QEMU_RAND_SEED", true, handle_arg_seed, 505c5e4a5a9SMagnus Reftel "", "Seed for pseudo-random number generator"}, 5066533dd6eSLluís Vilanova {"trace", "QEMU_TRACE", true, handle_arg_trace, 5076533dd6eSLluís Vilanova "", "[[enable=]<pattern>][,events=<file>][,file=<file>]"}, 508f308f64eSLluís Vilanova #ifdef CONFIG_PLUGIN 509f308f64eSLluís Vilanova {"plugin", "QEMU_PLUGIN", true, handle_arg_plugin, 5103a445acbSMahmoud Mandour "", "[file=]<file>[,<argname>=<argvalue>]"}, 511f308f64eSLluís Vilanova #endif 512fc9c5412SJohannes Schauer {"version", "QEMU_VERSION", false, handle_arg_version, 5131386d4c0SPeter Maydell "", "display version information and exit"}, 514130ea832SMax Filippov #if defined(TARGET_XTENSA) 515130ea832SMax Filippov {"xtensa-abi-call0", "QEMU_XTENSA_ABI_CALL0", false, handle_arg_abi_call0, 516130ea832SMax Filippov "", "assume CALL0 Xtensa ABI"}, 517130ea832SMax Filippov #endif 5185584e2dbSIlya Leoshkevich {"perfmap", "QEMU_PERFMAP", false, handle_arg_perfmap, 5195584e2dbSIlya Leoshkevich "", "Generate a /tmp/perf-${pid}.map file for perf"}, 5205584e2dbSIlya Leoshkevich {"jitdump", "QEMU_JITDUMP", false, handle_arg_jitdump, 5215584e2dbSIlya Leoshkevich "", "Generate a jit-${pid}.dump file for perf"}, 522fc9c5412SJohannes Schauer {NULL, NULL, false, NULL, NULL, NULL} 523fc9c5412SJohannes Schauer }; 524fc9c5412SJohannes Schauer 525d03f9c32SMeador Inge static void usage(int exitcode) 526fc9c5412SJohannes Schauer { 52742644ceeSJim Meyering const struct qemu_argument *arginfo; 528fc9c5412SJohannes Schauer int maxarglen; 529fc9c5412SJohannes Schauer int maxenvlen; 530fc9c5412SJohannes Schauer 5312e59915dSPaolo Bonzini printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n" 5322e59915dSPaolo Bonzini "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n" 533fc9c5412SJohannes Schauer "\n" 534fc9c5412SJohannes Schauer "Options and associated environment variables:\n" 535fc9c5412SJohannes Schauer "\n"); 536fc9c5412SJohannes Schauer 53763ec54d7SPeter Maydell /* Calculate column widths. We must always have at least enough space 53863ec54d7SPeter Maydell * for the column header. 53963ec54d7SPeter Maydell */ 54063ec54d7SPeter Maydell maxarglen = strlen("Argument"); 54163ec54d7SPeter Maydell maxenvlen = strlen("Env-variable"); 542fc9c5412SJohannes Schauer 543fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 54463ec54d7SPeter Maydell int arglen = strlen(arginfo->argv); 54563ec54d7SPeter Maydell if (arginfo->has_arg) { 54663ec54d7SPeter Maydell arglen += strlen(arginfo->example) + 1; 54763ec54d7SPeter Maydell } 548fc9c5412SJohannes Schauer if (strlen(arginfo->env) > maxenvlen) { 549fc9c5412SJohannes Schauer maxenvlen = strlen(arginfo->env); 550fc9c5412SJohannes Schauer } 55163ec54d7SPeter Maydell if (arglen > maxarglen) { 55263ec54d7SPeter Maydell maxarglen = arglen; 553fc9c5412SJohannes Schauer } 554fc9c5412SJohannes Schauer } 555fc9c5412SJohannes Schauer 55663ec54d7SPeter Maydell printf("%-*s %-*s Description\n", maxarglen+1, "Argument", 55763ec54d7SPeter Maydell maxenvlen, "Env-variable"); 558fc9c5412SJohannes Schauer 559fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 560fc9c5412SJohannes Schauer if (arginfo->has_arg) { 561fc9c5412SJohannes Schauer printf("-%s %-*s %-*s %s\n", arginfo->argv, 56263ec54d7SPeter Maydell (int)(maxarglen - strlen(arginfo->argv) - 1), 56363ec54d7SPeter Maydell arginfo->example, maxenvlen, arginfo->env, arginfo->help); 564fc9c5412SJohannes Schauer } else { 56563ec54d7SPeter Maydell printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv, 566fc9c5412SJohannes Schauer maxenvlen, arginfo->env, 567fc9c5412SJohannes Schauer arginfo->help); 568fc9c5412SJohannes Schauer } 569fc9c5412SJohannes Schauer } 570fc9c5412SJohannes Schauer 571fc9c5412SJohannes Schauer printf("\n" 572fc9c5412SJohannes Schauer "Defaults:\n" 573fc9c5412SJohannes Schauer "QEMU_LD_PREFIX = %s\n" 574989b697dSPeter Maydell "QEMU_STACK_SIZE = %ld byte\n", 575fc9c5412SJohannes Schauer interp_prefix, 576989b697dSPeter Maydell guest_stack_size); 577fc9c5412SJohannes Schauer 578fc9c5412SJohannes Schauer printf("\n" 579fc9c5412SJohannes Schauer "You can use -E and -U options or the QEMU_SET_ENV and\n" 580fc9c5412SJohannes Schauer "QEMU_UNSET_ENV environment variables to set and unset\n" 581fc9c5412SJohannes Schauer "environment variables for the target process.\n" 582fc9c5412SJohannes Schauer "It is possible to provide several variables by separating them\n" 583fc9c5412SJohannes Schauer "by commas in getsubopt(3) style. Additionally it is possible to\n" 584fc9c5412SJohannes Schauer "provide the -E and -U options multiple times.\n" 585fc9c5412SJohannes Schauer "The following lines are equivalent:\n" 586fc9c5412SJohannes Schauer " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n" 587fc9c5412SJohannes Schauer " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n" 588fc9c5412SJohannes Schauer " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n" 589fc9c5412SJohannes Schauer "Note that if you provide several changes to a single variable\n" 590f5048cb7SEric Blake "the last change will stay in effect.\n" 591f5048cb7SEric Blake "\n" 592f5048cb7SEric Blake QEMU_HELP_BOTTOM "\n"); 593fc9c5412SJohannes Schauer 594d03f9c32SMeador Inge exit(exitcode); 595fc9c5412SJohannes Schauer } 596fc9c5412SJohannes Schauer 597fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv) 598fc9c5412SJohannes Schauer { 599fc9c5412SJohannes Schauer const char *r; 600fc9c5412SJohannes Schauer int optind; 60142644ceeSJim Meyering const struct qemu_argument *arginfo; 602fc9c5412SJohannes Schauer 603fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 604fc9c5412SJohannes Schauer if (arginfo->env == NULL) { 605fc9c5412SJohannes Schauer continue; 606fc9c5412SJohannes Schauer } 607fc9c5412SJohannes Schauer 608fc9c5412SJohannes Schauer r = getenv(arginfo->env); 609fc9c5412SJohannes Schauer if (r != NULL) { 610fc9c5412SJohannes Schauer arginfo->handle_opt(r); 611fc9c5412SJohannes Schauer } 612fc9c5412SJohannes Schauer } 613fc9c5412SJohannes Schauer 614fc9c5412SJohannes Schauer optind = 1; 615fc9c5412SJohannes Schauer for (;;) { 616fc9c5412SJohannes Schauer if (optind >= argc) { 617fc9c5412SJohannes Schauer break; 618fc9c5412SJohannes Schauer } 619fc9c5412SJohannes Schauer r = argv[optind]; 620fc9c5412SJohannes Schauer if (r[0] != '-') { 621fc9c5412SJohannes Schauer break; 622fc9c5412SJohannes Schauer } 623fc9c5412SJohannes Schauer optind++; 624fc9c5412SJohannes Schauer r++; 625fc9c5412SJohannes Schauer if (!strcmp(r, "-")) { 626fc9c5412SJohannes Schauer break; 627fc9c5412SJohannes Schauer } 628ba02577cSMeador Inge /* Treat --foo the same as -foo. */ 629ba02577cSMeador Inge if (r[0] == '-') { 630ba02577cSMeador Inge r++; 631ba02577cSMeador Inge } 632fc9c5412SJohannes Schauer 633fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 634fc9c5412SJohannes Schauer if (!strcmp(r, arginfo->argv)) { 6351386d4c0SPeter Maydell if (arginfo->has_arg) { 636fc9c5412SJohannes Schauer if (optind >= argc) { 637138940bfSMeador Inge (void) fprintf(stderr, 638138940bfSMeador Inge "qemu: missing argument for option '%s'\n", r); 6394d1275c2SRiku Voipio exit(EXIT_FAILURE); 640fc9c5412SJohannes Schauer } 641fc9c5412SJohannes Schauer arginfo->handle_opt(argv[optind]); 642fc9c5412SJohannes Schauer optind++; 6431386d4c0SPeter Maydell } else { 6441386d4c0SPeter Maydell arginfo->handle_opt(NULL); 645fc9c5412SJohannes Schauer } 646fc9c5412SJohannes Schauer break; 647fc9c5412SJohannes Schauer } 648fc9c5412SJohannes Schauer } 649fc9c5412SJohannes Schauer 650fc9c5412SJohannes Schauer /* no option matched the current argv */ 651fc9c5412SJohannes Schauer if (arginfo->handle_opt == NULL) { 652138940bfSMeador Inge (void) fprintf(stderr, "qemu: unknown option '%s'\n", r); 6534d1275c2SRiku Voipio exit(EXIT_FAILURE); 654fc9c5412SJohannes Schauer } 655fc9c5412SJohannes Schauer } 656fc9c5412SJohannes Schauer 657fc9c5412SJohannes Schauer if (optind >= argc) { 658138940bfSMeador Inge (void) fprintf(stderr, "qemu: no user program specified\n"); 6594d1275c2SRiku Voipio exit(EXIT_FAILURE); 660fc9c5412SJohannes Schauer } 661fc9c5412SJohannes Schauer 662fc9c5412SJohannes Schauer exec_path = argv[optind]; 663fc9c5412SJohannes Schauer 664fc9c5412SJohannes Schauer return optind; 665fc9c5412SJohannes Schauer } 666fc9c5412SJohannes Schauer 667902b3d5cSmalc int main(int argc, char **argv, char **envp) 66831e31b8aSbellard { 66901ffc75bSbellard struct target_pt_regs regs1, *regs = ®s1; 67031e31b8aSbellard struct image_info info1, *info = &info1; 671edf8e2afSMika Westerberg struct linux_binprm bprm; 67248e15fc2SNathan Froyd TaskState *ts; 6739349b4f9SAndreas Färber CPUArchState *env; 674db6b81d4SAndreas Färber CPUState *cpu; 675586314f2Sbellard int optind; 67604a6dfebSaurel32 char **target_environ, **wrk; 6777d8cec95Saurel32 char **target_argv; 6787d8cec95Saurel32 int target_argc; 6797d8cec95Saurel32 int i; 680fd4d81ddSArnaud Patard int ret; 68103cfd8faSLaurent Vivier int execfd; 6828f67b9c6SRichard Henderson unsigned long max_reserved_va; 6836e1c0d7bSLaurent Vivier bool preserve_argv0; 68431e31b8aSbellard 685f5852efaSChristophe Fergeau error_init(argv[0]); 686fe4db84dSDaniel P. Berrange module_call_init(MODULE_INIT_TRACE); 687267f685bSPaolo Bonzini qemu_init_cpu_list(); 688ce008c1fSAndreas Färber module_call_init(MODULE_INIT_QOM); 689ce008c1fSAndreas Färber 690ec45bbe5SSaurav Sachidanand envlist = envlist_create(); 69104a6dfebSaurel32 69204a6dfebSaurel32 /* add current environment into the list */ 69304a6dfebSaurel32 for (wrk = environ; *wrk != NULL; wrk++) { 69404a6dfebSaurel32 (void) envlist_setenv(envlist, *wrk); 69504a6dfebSaurel32 } 69604a6dfebSaurel32 697703e0e89SRichard Henderson /* Read the stack limit from the kernel. If it's "unlimited", 698703e0e89SRichard Henderson then we can do little else besides use the default. */ 699703e0e89SRichard Henderson { 700703e0e89SRichard Henderson struct rlimit lim; 701703e0e89SRichard Henderson if (getrlimit(RLIMIT_STACK, &lim) == 0 70281bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur != RLIM_INFINITY 7030a3346b5SHelge Deller && lim.rlim_cur == (target_long)lim.rlim_cur 7040a3346b5SHelge Deller && lim.rlim_cur > guest_stack_size) { 705703e0e89SRichard Henderson guest_stack_size = lim.rlim_cur; 706703e0e89SRichard Henderson } 707703e0e89SRichard Henderson } 708703e0e89SRichard Henderson 709b1f9be31Sj_mayer cpu_model = NULL; 710b5ec5ce0Sjohn cooper 7116533dd6eSLluís Vilanova qemu_add_opts(&qemu_trace_opts); 712f308f64eSLluís Vilanova qemu_plugin_add_opts(); 7136533dd6eSLluís Vilanova 714fc9c5412SJohannes Schauer optind = parse_args(argc, argv); 7154b5dfd82SPeter Maydell 716b410253fSRichard Henderson qemu_set_log_filename_flags(last_log_filename, 717b410253fSRichard Henderson last_log_mask | (enable_strace * LOG_STRACE), 718b410253fSRichard Henderson &error_fatal); 7194b25a506SJosh Kunz 7206533dd6eSLluís Vilanova if (!trace_init_backends()) { 7216533dd6eSLluís Vilanova exit(1); 7226533dd6eSLluís Vilanova } 72392eecfffSPaolo Bonzini trace_init_file(); 7240572f558SPaolo Bonzini qemu_plugin_load_list(&plugins, &error_fatal); 7256533dd6eSLluís Vilanova 72631e31b8aSbellard /* Zero out regs */ 72701ffc75bSbellard memset(regs, 0, sizeof(struct target_pt_regs)); 72831e31b8aSbellard 72931e31b8aSbellard /* Zero out image_info */ 73031e31b8aSbellard memset(info, 0, sizeof(struct image_info)); 73131e31b8aSbellard 732edf8e2afSMika Westerberg memset(&bprm, 0, sizeof (bprm)); 733edf8e2afSMika Westerberg 73474cd30b8Sbellard /* Scan interp_prefix dir for replacement files. */ 73574cd30b8Sbellard init_paths(interp_prefix); 73674cd30b8Sbellard 7374a24a758SPeter Maydell init_qemu_uname_release(); 7384a24a758SPeter Maydell 7396e1c0d7bSLaurent Vivier /* 7406e1c0d7bSLaurent Vivier * Manage binfmt-misc open-binary flag 7416e1c0d7bSLaurent Vivier */ 742768fe76eSYunQiang Su execfd = qemu_getauxval(AT_EXECFD); 743768fe76eSYunQiang Su if (execfd == 0) { 7449d3019bcSLaurent Vivier execfd = open(exec_path, O_RDONLY); 745768fe76eSYunQiang Su if (execfd < 0) { 7469d3019bcSLaurent Vivier printf("Error while loading %s: %s\n", exec_path, strerror(errno)); 747768fe76eSYunQiang Su _exit(EXIT_FAILURE); 748768fe76eSYunQiang Su } 749768fe76eSYunQiang Su } 750768fe76eSYunQiang Su 751258bec39SHelge Deller /* Resolve executable file name to full path name */ 752258bec39SHelge Deller if (realpath(exec_path, real_exec_path)) { 753258bec39SHelge Deller exec_path = real_exec_path; 754258bec39SHelge Deller } 755258bec39SHelge Deller 7566e1c0d7bSLaurent Vivier /* 7576e1c0d7bSLaurent Vivier * get binfmt_misc flags 7586e1c0d7bSLaurent Vivier */ 7596e1c0d7bSLaurent Vivier preserve_argv0 = !!(qemu_getauxval(AT_FLAGS) & AT_FLAGS_PRESERVE_ARGV0); 7606e1c0d7bSLaurent Vivier 7616e1c0d7bSLaurent Vivier /* 7626e1c0d7bSLaurent Vivier * Manage binfmt-misc preserve-arg[0] flag 7636e1c0d7bSLaurent Vivier * argv[optind] full path to the binary 7646e1c0d7bSLaurent Vivier * argv[optind + 1] original argv[0] 7656e1c0d7bSLaurent Vivier */ 7666e1c0d7bSLaurent Vivier if (optind + 1 < argc && preserve_argv0) { 7676e1c0d7bSLaurent Vivier optind++; 7686e1c0d7bSLaurent Vivier } 7696e1c0d7bSLaurent Vivier 77046027c07Sbellard if (cpu_model == NULL) { 771768fe76eSYunQiang Su cpu_model = cpu_get_model(get_elf_eflags(execfd)); 772aaed909aSbellard } 773c1c8cfe5SEduardo Habkost cpu_type = parse_cpu_option(cpu_model); 7742278b939SIgor Mammedov 7752b5249b8SIgor Mammedov /* init tcg before creating CPUs and to get qemu_host_page_size */ 776940e43aaSClaudio Fontana { 777940e43aaSClaudio Fontana AccelClass *ac = ACCEL_GET_CLASS(current_accel()); 7782278b939SIgor Mammedov 779b86f59c7SClaudio Fontana accel_init_interfaces(ac); 78092242f34SClaudio Fontana ac->init_machine(NULL); 781940e43aaSClaudio Fontana } 7822278b939SIgor Mammedov cpu = cpu_create(cpu_type); 7832994fd96SEduardo Habkost env = cpu->env_ptr; 7840ac46af3SAndreas Färber cpu_reset(cpu); 785db6b81d4SAndreas Färber thread_cpu = cpu; 78654936004Sbellard 7878f67b9c6SRichard Henderson /* 7888f67b9c6SRichard Henderson * Reserving too much vm space via mmap can run into problems 7898f67b9c6SRichard Henderson * with rlimits, oom due to page table creation, etc. We will 7908f67b9c6SRichard Henderson * still try it, if directed by the command-line option, but 7918f67b9c6SRichard Henderson * not by default. 7928f67b9c6SRichard Henderson */ 7938f67b9c6SRichard Henderson max_reserved_va = MAX_RESERVED_VA(cpu); 7948f67b9c6SRichard Henderson if (reserved_va != 0) { 79595059f9cSRichard Henderson if ((reserved_va + 1) % qemu_host_page_size) { 7962f7828b5SRichard Henderson char *s = size_to_str(qemu_host_page_size); 7972f7828b5SRichard Henderson fprintf(stderr, "Reserved virtual address not aligned mod %s\n", s); 7982f7828b5SRichard Henderson g_free(s); 7992f7828b5SRichard Henderson exit(EXIT_FAILURE); 8002f7828b5SRichard Henderson } 8018f67b9c6SRichard Henderson if (max_reserved_va && reserved_va > max_reserved_va) { 8028f67b9c6SRichard Henderson fprintf(stderr, "Reserved virtual address too big\n"); 8038f67b9c6SRichard Henderson exit(EXIT_FAILURE); 8048f67b9c6SRichard Henderson } 8058f67b9c6SRichard Henderson } else if (HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32) { 80695059f9cSRichard Henderson /* MAX_RESERVED_VA + 1 is a large power of 2, so is aligned. */ 80795059f9cSRichard Henderson reserved_va = max_reserved_va; 8088f67b9c6SRichard Henderson } 8098f67b9c6SRichard Henderson 810a573e9baSRichard Henderson { 811a573e9baSRichard Henderson Error *err = NULL; 8125ebdd774SRichard Henderson if (seed_optarg != NULL) { 813a573e9baSRichard Henderson qemu_guest_random_seed_main(seed_optarg, &err); 814a573e9baSRichard Henderson } else { 815a573e9baSRichard Henderson qcrypto_init(&err); 816a573e9baSRichard Henderson } 817a573e9baSRichard Henderson if (err) { 818a573e9baSRichard Henderson error_reportf_err(err, "cannot initialize crypto: "); 819a573e9baSRichard Henderson exit(1); 820a573e9baSRichard Henderson } 821c5e4a5a9SMagnus Reftel } 822c5e4a5a9SMagnus Reftel 82304a6dfebSaurel32 target_environ = envlist_to_environ(envlist, NULL); 82404a6dfebSaurel32 envlist_free(envlist); 825b12b6a18Sths 826379f6698SPaul Brook /* 827379f6698SPaul Brook * Read in mmap_min_addr kernel parameter. This value is used 828379f6698SPaul Brook * When loading the ELF image to determine whether guest_base 82914f24e14SRichard Henderson * is needed. It is also used in mmap_find_vma. 830379f6698SPaul Brook */ 83114f24e14SRichard Henderson { 832379f6698SPaul Brook FILE *fp; 833379f6698SPaul Brook 834379f6698SPaul Brook if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) { 835379f6698SPaul Brook unsigned long tmp; 836c9f80666SRichard Henderson if (fscanf(fp, "%lu", &tmp) == 1 && tmp != 0) { 837379f6698SPaul Brook mmap_min_addr = tmp; 838c9f80666SRichard Henderson qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n", 839c9f80666SRichard Henderson mmap_min_addr); 840379f6698SPaul Brook } 841379f6698SPaul Brook fclose(fp); 842379f6698SPaul Brook } 843379f6698SPaul Brook } 844379f6698SPaul Brook 8457d8cec95Saurel32 /* 846c9f80666SRichard Henderson * We prefer to not make NULL pointers accessible to QEMU. 847c9f80666SRichard Henderson * If we're in a chroot with no /proc, fall back to 1 page. 848c9f80666SRichard Henderson */ 849c9f80666SRichard Henderson if (mmap_min_addr == 0) { 850c9f80666SRichard Henderson mmap_min_addr = qemu_host_page_size; 851c9f80666SRichard Henderson qemu_log_mask(CPU_LOG_PAGE, 852c9f80666SRichard Henderson "host mmap_min_addr=0x%lx (fallback)\n", 853c9f80666SRichard Henderson mmap_min_addr); 854c9f80666SRichard Henderson } 855c9f80666SRichard Henderson 856c9f80666SRichard Henderson /* 8577d8cec95Saurel32 * Prepare copy of argv vector for target. 8587d8cec95Saurel32 */ 8597d8cec95Saurel32 target_argc = argc - optind; 8607d8cec95Saurel32 target_argv = calloc(target_argc + 1, sizeof (char *)); 8617d8cec95Saurel32 if (target_argv == NULL) { 8627d8cec95Saurel32 (void) fprintf(stderr, "Unable to allocate memory for target_argv\n"); 8634d1275c2SRiku Voipio exit(EXIT_FAILURE); 8647d8cec95Saurel32 } 8657d8cec95Saurel32 8667d8cec95Saurel32 /* 8677d8cec95Saurel32 * If argv0 is specified (using '-0' switch) we replace 8687d8cec95Saurel32 * argv[0] pointer with the given one. 8697d8cec95Saurel32 */ 8707d8cec95Saurel32 i = 0; 8717d8cec95Saurel32 if (argv0 != NULL) { 8727d8cec95Saurel32 target_argv[i++] = strdup(argv0); 8737d8cec95Saurel32 } 8747d8cec95Saurel32 for (; i < target_argc; i++) { 8757d8cec95Saurel32 target_argv[i] = strdup(argv[optind + i]); 8767d8cec95Saurel32 } 8777d8cec95Saurel32 target_argv[target_argc] = NULL; 8787d8cec95Saurel32 879c78d65e8SMarkus Armbruster ts = g_new0(TaskState, 1); 880edf8e2afSMika Westerberg init_task_state(ts); 881edf8e2afSMika Westerberg /* build Task State */ 882edf8e2afSMika Westerberg ts->info = info; 883edf8e2afSMika Westerberg ts->bprm = &bprm; 8840429a971SAndreas Färber cpu->opaque = ts; 885edf8e2afSMika Westerberg task_settid(ts); 886edf8e2afSMika Westerberg 887c093364fSOwen Anderson fd_trans_init(); 888c093364fSOwen Anderson 8899d3019bcSLaurent Vivier ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs, 890fd4d81ddSArnaud Patard info, &bprm); 891fd4d81ddSArnaud Patard if (ret != 0) { 8929d3019bcSLaurent Vivier printf("Error while loading %s: %s\n", exec_path, strerror(-ret)); 8934d1275c2SRiku Voipio _exit(EXIT_FAILURE); 89431e31b8aSbellard } 89531e31b8aSbellard 896b12b6a18Sths for (wrk = target_environ; *wrk; wrk++) { 897ec45bbe5SSaurav Sachidanand g_free(*wrk); 898b12b6a18Sths } 899b12b6a18Sths 900ec45bbe5SSaurav Sachidanand g_free(target_environ); 901b12b6a18Sths 90213829020SPaolo Bonzini if (qemu_loglevel_mask(CPU_LOG_PAGE)) { 90393756fdcSRichard Henderson FILE *f = qemu_log_trylock(); 90493756fdcSRichard Henderson if (f) { 90593756fdcSRichard Henderson fprintf(f, "guest_base %p\n", (void *)guest_base); 90693756fdcSRichard Henderson fprintf(f, "page layout changed following binary load\n"); 90793756fdcSRichard Henderson page_dump(f); 90854936004Sbellard 90993756fdcSRichard Henderson fprintf(f, "start_brk 0x" TARGET_ABI_FMT_lx "\n", 91093756fdcSRichard Henderson info->start_brk); 91193756fdcSRichard Henderson fprintf(f, "end_code 0x" TARGET_ABI_FMT_lx "\n", 91293756fdcSRichard Henderson info->end_code); 91393756fdcSRichard Henderson fprintf(f, "start_code 0x" TARGET_ABI_FMT_lx "\n", 91493756fdcSRichard Henderson info->start_code); 91593756fdcSRichard Henderson fprintf(f, "start_data 0x" TARGET_ABI_FMT_lx "\n", 91693756fdcSRichard Henderson info->start_data); 91793756fdcSRichard Henderson fprintf(f, "end_data 0x" TARGET_ABI_FMT_lx "\n", 91893756fdcSRichard Henderson info->end_data); 91993756fdcSRichard Henderson fprintf(f, "start_stack 0x" TARGET_ABI_FMT_lx "\n", 92093756fdcSRichard Henderson info->start_stack); 92193756fdcSRichard Henderson fprintf(f, "brk 0x" TARGET_ABI_FMT_lx "\n", 92293756fdcSRichard Henderson info->brk); 92393756fdcSRichard Henderson fprintf(f, "entry 0x" TARGET_ABI_FMT_lx "\n", 92493756fdcSRichard Henderson info->entry); 92593756fdcSRichard Henderson fprintf(f, "argv_start 0x" TARGET_ABI_FMT_lx "\n", 92660f1c801SRichard Henderson info->argv); 92793756fdcSRichard Henderson fprintf(f, "env_start 0x" TARGET_ABI_FMT_lx "\n", 92860f1c801SRichard Henderson info->envp); 92993756fdcSRichard Henderson fprintf(f, "auxv_start 0x" TARGET_ABI_FMT_lx "\n", 93093756fdcSRichard Henderson info->saved_auxv); 93193756fdcSRichard Henderson qemu_log_unlock(f); 93293756fdcSRichard Henderson } 9332e77eac6Sblueswir1 } 93431e31b8aSbellard 93553a5960aSpbrook target_set_brk(info->brk); 93631e31b8aSbellard syscall_init(); 93766fb9763Sbellard signal_init(); 93831e31b8aSbellard 9399002ec79SRichard Henderson /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay 9409002ec79SRichard Henderson generating the prologue until now so that the prologue can take 9419002ec79SRichard Henderson the real value of GUEST_BASE into account. */ 942b1311c4aSEmilio G. Cota tcg_prologue_init(tcg_ctx); 9439002ec79SRichard Henderson 944cd71c089SLaurent Vivier target_cpu_copy_regs(env, regs); 945cd71c089SLaurent Vivier 946fcedd920SAlex Bennée if (gdbstub) { 947fcedd920SAlex Bennée if (gdbserver_start(gdbstub) < 0) { 948fcedd920SAlex Bennée fprintf(stderr, "qemu: could not open gdbserver on %s\n", 949fcedd920SAlex Bennée gdbstub); 9504d1275c2SRiku Voipio exit(EXIT_FAILURE); 951ff7a981aSPeter Maydell } 952db6b81d4SAndreas Färber gdb_handlesig(cpu, 0); 9531fddef4bSbellard } 954e4a4aaa5SRichard Henderson 955e4a4aaa5SRichard Henderson #ifdef CONFIG_SEMIHOSTING 956e4a4aaa5SRichard Henderson qemu_semihosting_guestfd_init(); 957e4a4aaa5SRichard Henderson #endif 958e4a4aaa5SRichard Henderson 9591b6b029eSbellard cpu_loop(env); 9601b6b029eSbellard /* never exits */ 96131e31b8aSbellard return 0; 96231e31b8aSbellard } 963