xref: /qemu/linux-user/main.c (revision 13c13397)
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"
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 
713cfb0456SPeter Maydell static bool opt_one_insn_per_tb;
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) {
1593c55dd58SPhilippe Mathieu-Daudé                 QTAILQ_REMOVE_RCU(&cpus_queue, 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);
232b77af26eSRichard Henderson     CPUArchState *new_env = cpu_env(new_cpu);
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)) {
362b67e5cb4SThomas 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 
409e99c1f89SPeter Maydell static void handle_arg_one_insn_per_tb(const char *arg)
410fc9c5412SJohannes Schauer {
4113cfb0456SPeter Maydell     opt_one_insn_per_tb = true;
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'"},
500e99c1f89SPeter Maydell     {"one-insn-per-tb",
501e99c1f89SPeter Maydell                    "QEMU_ONE_INSN_PER_TB",  false, handle_arg_one_insn_per_tb,
502e99c1f89SPeter Maydell      "",           "run with one guest instruction per emulated TB"},
503fc9c5412SJohannes Schauer     {"strace",     "QEMU_STRACE",      false, handle_arg_strace,
504fc9c5412SJohannes Schauer      "",           "log system calls"},
5055ebdd774SRichard Henderson     {"seed",       "QEMU_RAND_SEED",   true,  handle_arg_seed,
506c5e4a5a9SMagnus Reftel      "",           "Seed for pseudo-random number generator"},
5076533dd6eSLluís Vilanova     {"trace",      "QEMU_TRACE",       true,  handle_arg_trace,
5086533dd6eSLluís Vilanova      "",           "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
509f308f64eSLluís Vilanova #ifdef CONFIG_PLUGIN
510f308f64eSLluís Vilanova     {"plugin",     "QEMU_PLUGIN",      true,  handle_arg_plugin,
5113a445acbSMahmoud Mandour      "",           "[file=]<file>[,<argname>=<argvalue>]"},
512f308f64eSLluís Vilanova #endif
513fc9c5412SJohannes Schauer     {"version",    "QEMU_VERSION",     false, handle_arg_version,
5141386d4c0SPeter Maydell      "",           "display version information and exit"},
515130ea832SMax Filippov #if defined(TARGET_XTENSA)
516130ea832SMax Filippov     {"xtensa-abi-call0", "QEMU_XTENSA_ABI_CALL0", false, handle_arg_abi_call0,
517130ea832SMax Filippov      "",           "assume CALL0 Xtensa ABI"},
518130ea832SMax Filippov #endif
5195584e2dbSIlya Leoshkevich     {"perfmap",    "QEMU_PERFMAP",     false, handle_arg_perfmap,
5205584e2dbSIlya Leoshkevich      "",           "Generate a /tmp/perf-${pid}.map file for perf"},
5215584e2dbSIlya Leoshkevich     {"jitdump",    "QEMU_JITDUMP",     false, handle_arg_jitdump,
5225584e2dbSIlya Leoshkevich      "",           "Generate a jit-${pid}.dump file for perf"},
523fc9c5412SJohannes Schauer     {NULL, NULL, false, NULL, NULL, NULL}
524fc9c5412SJohannes Schauer };
525fc9c5412SJohannes Schauer 
526d03f9c32SMeador Inge static void usage(int exitcode)
527fc9c5412SJohannes Schauer {
52842644ceeSJim Meyering     const struct qemu_argument *arginfo;
529fc9c5412SJohannes Schauer     int maxarglen;
530fc9c5412SJohannes Schauer     int maxenvlen;
531fc9c5412SJohannes Schauer 
5322e59915dSPaolo Bonzini     printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
5332e59915dSPaolo Bonzini            "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n"
534fc9c5412SJohannes Schauer            "\n"
535fc9c5412SJohannes Schauer            "Options and associated environment variables:\n"
536fc9c5412SJohannes Schauer            "\n");
537fc9c5412SJohannes Schauer 
53863ec54d7SPeter Maydell     /* Calculate column widths. We must always have at least enough space
53963ec54d7SPeter Maydell      * for the column header.
54063ec54d7SPeter Maydell      */
54163ec54d7SPeter Maydell     maxarglen = strlen("Argument");
54263ec54d7SPeter Maydell     maxenvlen = strlen("Env-variable");
543fc9c5412SJohannes Schauer 
544fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
54563ec54d7SPeter Maydell         int arglen = strlen(arginfo->argv);
54663ec54d7SPeter Maydell         if (arginfo->has_arg) {
54763ec54d7SPeter Maydell             arglen += strlen(arginfo->example) + 1;
54863ec54d7SPeter Maydell         }
549fc9c5412SJohannes Schauer         if (strlen(arginfo->env) > maxenvlen) {
550fc9c5412SJohannes Schauer             maxenvlen = strlen(arginfo->env);
551fc9c5412SJohannes Schauer         }
55263ec54d7SPeter Maydell         if (arglen > maxarglen) {
55363ec54d7SPeter Maydell             maxarglen = arglen;
554fc9c5412SJohannes Schauer         }
555fc9c5412SJohannes Schauer     }
556fc9c5412SJohannes Schauer 
55763ec54d7SPeter Maydell     printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
55863ec54d7SPeter Maydell             maxenvlen, "Env-variable");
559fc9c5412SJohannes Schauer 
560fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
561fc9c5412SJohannes Schauer         if (arginfo->has_arg) {
562fc9c5412SJohannes Schauer             printf("-%s %-*s %-*s %s\n", arginfo->argv,
56363ec54d7SPeter Maydell                    (int)(maxarglen - strlen(arginfo->argv) - 1),
56463ec54d7SPeter Maydell                    arginfo->example, maxenvlen, arginfo->env, arginfo->help);
565fc9c5412SJohannes Schauer         } else {
56663ec54d7SPeter Maydell             printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
567fc9c5412SJohannes Schauer                     maxenvlen, arginfo->env,
568fc9c5412SJohannes Schauer                     arginfo->help);
569fc9c5412SJohannes Schauer         }
570fc9c5412SJohannes Schauer     }
571fc9c5412SJohannes Schauer 
572fc9c5412SJohannes Schauer     printf("\n"
573fc9c5412SJohannes Schauer            "Defaults:\n"
574fc9c5412SJohannes Schauer            "QEMU_LD_PREFIX  = %s\n"
575989b697dSPeter Maydell            "QEMU_STACK_SIZE = %ld byte\n",
576fc9c5412SJohannes Schauer            interp_prefix,
577989b697dSPeter Maydell            guest_stack_size);
578fc9c5412SJohannes Schauer 
579fc9c5412SJohannes Schauer     printf("\n"
580fc9c5412SJohannes Schauer            "You can use -E and -U options or the QEMU_SET_ENV and\n"
581fc9c5412SJohannes Schauer            "QEMU_UNSET_ENV environment variables to set and unset\n"
582fc9c5412SJohannes Schauer            "environment variables for the target process.\n"
583fc9c5412SJohannes Schauer            "It is possible to provide several variables by separating them\n"
584fc9c5412SJohannes Schauer            "by commas in getsubopt(3) style. Additionally it is possible to\n"
585fc9c5412SJohannes Schauer            "provide the -E and -U options multiple times.\n"
586fc9c5412SJohannes Schauer            "The following lines are equivalent:\n"
587fc9c5412SJohannes Schauer            "    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
588fc9c5412SJohannes Schauer            "    -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
589fc9c5412SJohannes Schauer            "    QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
590fc9c5412SJohannes Schauer            "Note that if you provide several changes to a single variable\n"
591f5048cb7SEric Blake            "the last change will stay in effect.\n"
592f5048cb7SEric Blake            "\n"
593f5048cb7SEric Blake            QEMU_HELP_BOTTOM "\n");
594fc9c5412SJohannes Schauer 
595d03f9c32SMeador Inge     exit(exitcode);
596fc9c5412SJohannes Schauer }
597fc9c5412SJohannes Schauer 
598fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv)
599fc9c5412SJohannes Schauer {
600fc9c5412SJohannes Schauer     const char *r;
601fc9c5412SJohannes Schauer     int optind;
60242644ceeSJim Meyering     const struct qemu_argument *arginfo;
603fc9c5412SJohannes Schauer 
604fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
605fc9c5412SJohannes Schauer         if (arginfo->env == NULL) {
606fc9c5412SJohannes Schauer             continue;
607fc9c5412SJohannes Schauer         }
608fc9c5412SJohannes Schauer 
609fc9c5412SJohannes Schauer         r = getenv(arginfo->env);
610fc9c5412SJohannes Schauer         if (r != NULL) {
611fc9c5412SJohannes Schauer             arginfo->handle_opt(r);
612fc9c5412SJohannes Schauer         }
613fc9c5412SJohannes Schauer     }
614fc9c5412SJohannes Schauer 
615fc9c5412SJohannes Schauer     optind = 1;
616fc9c5412SJohannes Schauer     for (;;) {
617fc9c5412SJohannes Schauer         if (optind >= argc) {
618fc9c5412SJohannes Schauer             break;
619fc9c5412SJohannes Schauer         }
620fc9c5412SJohannes Schauer         r = argv[optind];
621fc9c5412SJohannes Schauer         if (r[0] != '-') {
622fc9c5412SJohannes Schauer             break;
623fc9c5412SJohannes Schauer         }
624fc9c5412SJohannes Schauer         optind++;
625fc9c5412SJohannes Schauer         r++;
626fc9c5412SJohannes Schauer         if (!strcmp(r, "-")) {
627fc9c5412SJohannes Schauer             break;
628fc9c5412SJohannes Schauer         }
629ba02577cSMeador Inge         /* Treat --foo the same as -foo.  */
630ba02577cSMeador Inge         if (r[0] == '-') {
631ba02577cSMeador Inge             r++;
632ba02577cSMeador Inge         }
633fc9c5412SJohannes Schauer 
634fc9c5412SJohannes Schauer         for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
635fc9c5412SJohannes Schauer             if (!strcmp(r, arginfo->argv)) {
6361386d4c0SPeter Maydell                 if (arginfo->has_arg) {
637fc9c5412SJohannes Schauer                     if (optind >= argc) {
638138940bfSMeador Inge                         (void) fprintf(stderr,
639138940bfSMeador Inge                             "qemu: missing argument for option '%s'\n", r);
6404d1275c2SRiku Voipio                         exit(EXIT_FAILURE);
641fc9c5412SJohannes Schauer                     }
642fc9c5412SJohannes Schauer                     arginfo->handle_opt(argv[optind]);
643fc9c5412SJohannes Schauer                     optind++;
6441386d4c0SPeter Maydell                 } else {
6451386d4c0SPeter Maydell                     arginfo->handle_opt(NULL);
646fc9c5412SJohannes Schauer                 }
647fc9c5412SJohannes Schauer                 break;
648fc9c5412SJohannes Schauer             }
649fc9c5412SJohannes Schauer         }
650fc9c5412SJohannes Schauer 
651fc9c5412SJohannes Schauer         /* no option matched the current argv */
652fc9c5412SJohannes Schauer         if (arginfo->handle_opt == NULL) {
653138940bfSMeador Inge             (void) fprintf(stderr, "qemu: unknown option '%s'\n", r);
6544d1275c2SRiku Voipio             exit(EXIT_FAILURE);
655fc9c5412SJohannes Schauer         }
656fc9c5412SJohannes Schauer     }
657fc9c5412SJohannes Schauer 
658fc9c5412SJohannes Schauer     if (optind >= argc) {
659138940bfSMeador Inge         (void) fprintf(stderr, "qemu: no user program specified\n");
6604d1275c2SRiku Voipio         exit(EXIT_FAILURE);
661fc9c5412SJohannes Schauer     }
662fc9c5412SJohannes Schauer 
663fc9c5412SJohannes Schauer     exec_path = argv[optind];
664fc9c5412SJohannes Schauer 
665fc9c5412SJohannes Schauer     return optind;
666fc9c5412SJohannes Schauer }
667fc9c5412SJohannes Schauer 
668902b3d5cSmalc int main(int argc, char **argv, char **envp)
66931e31b8aSbellard {
67001ffc75bSbellard     struct target_pt_regs regs1, *regs = &regs1;
67131e31b8aSbellard     struct image_info info1, *info = &info1;
672edf8e2afSMika Westerberg     struct linux_binprm bprm;
67348e15fc2SNathan Froyd     TaskState *ts;
6749349b4f9SAndreas Färber     CPUArchState *env;
675db6b81d4SAndreas Färber     CPUState *cpu;
676586314f2Sbellard     int optind;
67704a6dfebSaurel32     char **target_environ, **wrk;
6787d8cec95Saurel32     char **target_argv;
6797d8cec95Saurel32     int target_argc;
6807d8cec95Saurel32     int i;
681fd4d81ddSArnaud Patard     int ret;
68203cfd8faSLaurent Vivier     int execfd;
6838f67b9c6SRichard Henderson     unsigned long max_reserved_va;
6846e1c0d7bSLaurent Vivier     bool preserve_argv0;
68531e31b8aSbellard 
686f5852efaSChristophe Fergeau     error_init(argv[0]);
687fe4db84dSDaniel P. Berrange     module_call_init(MODULE_INIT_TRACE);
688267f685bSPaolo Bonzini     qemu_init_cpu_list();
689ce008c1fSAndreas Färber     module_call_init(MODULE_INIT_QOM);
690ce008c1fSAndreas Färber 
691ec45bbe5SSaurav Sachidanand     envlist = envlist_create();
69204a6dfebSaurel32 
6937f750efcSAndreas Schwab     /*
6947f750efcSAndreas Schwab      * add current environment into the list
6957f750efcSAndreas Schwab      * envlist_setenv adds to the front of the list; to preserve environ
6967f750efcSAndreas Schwab      * order add from back to front
6977f750efcSAndreas Schwab      */
69804a6dfebSaurel32     for (wrk = environ; *wrk != NULL; wrk++) {
6997f750efcSAndreas Schwab         continue;
7007f750efcSAndreas Schwab     }
7017f750efcSAndreas Schwab     while (wrk != environ) {
7027f750efcSAndreas Schwab         wrk--;
70304a6dfebSaurel32         (void) envlist_setenv(envlist, *wrk);
70404a6dfebSaurel32     }
70504a6dfebSaurel32 
706703e0e89SRichard Henderson     /* Read the stack limit from the kernel.  If it's "unlimited",
707703e0e89SRichard Henderson        then we can do little else besides use the default.  */
708703e0e89SRichard Henderson     {
709703e0e89SRichard Henderson         struct rlimit lim;
710703e0e89SRichard Henderson         if (getrlimit(RLIMIT_STACK, &lim) == 0
71181bbe906Stakasi-y@ops.dti.ne.jp             && lim.rlim_cur != RLIM_INFINITY
7120a3346b5SHelge Deller             && lim.rlim_cur == (target_long)lim.rlim_cur
7130a3346b5SHelge Deller             && lim.rlim_cur > guest_stack_size) {
714703e0e89SRichard Henderson             guest_stack_size = lim.rlim_cur;
715703e0e89SRichard Henderson         }
716703e0e89SRichard Henderson     }
717703e0e89SRichard Henderson 
718b1f9be31Sj_mayer     cpu_model = NULL;
719b5ec5ce0Sjohn cooper 
7206533dd6eSLluís Vilanova     qemu_add_opts(&qemu_trace_opts);
721f308f64eSLluís Vilanova     qemu_plugin_add_opts();
7226533dd6eSLluís Vilanova 
723fc9c5412SJohannes Schauer     optind = parse_args(argc, argv);
7244b5dfd82SPeter Maydell 
725b410253fSRichard Henderson     qemu_set_log_filename_flags(last_log_filename,
726b410253fSRichard Henderson                                 last_log_mask | (enable_strace * LOG_STRACE),
727b410253fSRichard Henderson                                 &error_fatal);
7284b25a506SJosh Kunz 
7296533dd6eSLluís Vilanova     if (!trace_init_backends()) {
7306533dd6eSLluís Vilanova         exit(1);
7316533dd6eSLluís Vilanova     }
73292eecfffSPaolo Bonzini     trace_init_file();
7330572f558SPaolo Bonzini     qemu_plugin_load_list(&plugins, &error_fatal);
7346533dd6eSLluís Vilanova 
73531e31b8aSbellard     /* Zero out regs */
73601ffc75bSbellard     memset(regs, 0, sizeof(struct target_pt_regs));
73731e31b8aSbellard 
73831e31b8aSbellard     /* Zero out image_info */
73931e31b8aSbellard     memset(info, 0, sizeof(struct image_info));
74031e31b8aSbellard 
741edf8e2afSMika Westerberg     memset(&bprm, 0, sizeof (bprm));
742edf8e2afSMika Westerberg 
74374cd30b8Sbellard     /* Scan interp_prefix dir for replacement files. */
74474cd30b8Sbellard     init_paths(interp_prefix);
74574cd30b8Sbellard 
7464a24a758SPeter Maydell     init_qemu_uname_release();
7474a24a758SPeter Maydell 
7486e1c0d7bSLaurent Vivier     /*
7496e1c0d7bSLaurent Vivier      * Manage binfmt-misc open-binary flag
7506e1c0d7bSLaurent Vivier      */
751768fe76eSYunQiang Su     execfd = qemu_getauxval(AT_EXECFD);
752768fe76eSYunQiang Su     if (execfd == 0) {
7539d3019bcSLaurent Vivier         execfd = open(exec_path, O_RDONLY);
754768fe76eSYunQiang Su         if (execfd < 0) {
7559d3019bcSLaurent Vivier             printf("Error while loading %s: %s\n", exec_path, strerror(errno));
756768fe76eSYunQiang Su             _exit(EXIT_FAILURE);
757768fe76eSYunQiang Su         }
758768fe76eSYunQiang Su     }
759768fe76eSYunQiang Su 
760258bec39SHelge Deller     /* Resolve executable file name to full path name */
761258bec39SHelge Deller     if (realpath(exec_path, real_exec_path)) {
762258bec39SHelge Deller         exec_path = real_exec_path;
763258bec39SHelge Deller     }
764258bec39SHelge Deller 
7656e1c0d7bSLaurent Vivier     /*
7666e1c0d7bSLaurent Vivier      * get binfmt_misc flags
7676e1c0d7bSLaurent Vivier      */
7686e1c0d7bSLaurent Vivier     preserve_argv0 = !!(qemu_getauxval(AT_FLAGS) & AT_FLAGS_PRESERVE_ARGV0);
7696e1c0d7bSLaurent Vivier 
7706e1c0d7bSLaurent Vivier     /*
7716e1c0d7bSLaurent Vivier      * Manage binfmt-misc preserve-arg[0] flag
7726e1c0d7bSLaurent Vivier      *    argv[optind]     full path to the binary
7736e1c0d7bSLaurent Vivier      *    argv[optind + 1] original argv[0]
7746e1c0d7bSLaurent Vivier      */
7756e1c0d7bSLaurent Vivier     if (optind + 1 < argc && preserve_argv0) {
7766e1c0d7bSLaurent Vivier         optind++;
7776e1c0d7bSLaurent Vivier     }
7786e1c0d7bSLaurent Vivier 
77946027c07Sbellard     if (cpu_model == NULL) {
780768fe76eSYunQiang Su         cpu_model = cpu_get_model(get_elf_eflags(execfd));
781aaed909aSbellard     }
782c1c8cfe5SEduardo Habkost     cpu_type = parse_cpu_option(cpu_model);
7832278b939SIgor Mammedov 
784*13c13397SRichard Henderson     /* init tcg before creating CPUs */
785940e43aaSClaudio Fontana     {
7863cfb0456SPeter Maydell         AccelState *accel = current_accel();
7873cfb0456SPeter Maydell         AccelClass *ac = ACCEL_GET_CLASS(accel);
7882278b939SIgor Mammedov 
789b86f59c7SClaudio Fontana         accel_init_interfaces(ac);
7903cfb0456SPeter Maydell         object_property_set_bool(OBJECT(accel), "one-insn-per-tb",
7913cfb0456SPeter Maydell                                  opt_one_insn_per_tb, &error_abort);
79292242f34SClaudio Fontana         ac->init_machine(NULL);
793940e43aaSClaudio Fontana     }
7942278b939SIgor Mammedov     cpu = cpu_create(cpu_type);
795b77af26eSRichard Henderson     env = cpu_env(cpu);
7960ac46af3SAndreas Färber     cpu_reset(cpu);
797db6b81d4SAndreas Färber     thread_cpu = cpu;
79854936004Sbellard 
7998f67b9c6SRichard Henderson     /*
8008f67b9c6SRichard Henderson      * Reserving too much vm space via mmap can run into problems
8018f67b9c6SRichard Henderson      * with rlimits, oom due to page table creation, etc.  We will
8028f67b9c6SRichard Henderson      * still try it, if directed by the command-line option, but
8038f67b9c6SRichard Henderson      * not by default.
8048f67b9c6SRichard Henderson      */
8058f67b9c6SRichard Henderson     max_reserved_va = MAX_RESERVED_VA(cpu);
8068f67b9c6SRichard Henderson     if (reserved_va != 0) {
807*13c13397SRichard Henderson         int host_page_size = qemu_real_host_page_size();
808*13c13397SRichard Henderson 
809*13c13397SRichard Henderson         if ((reserved_va + 1) % host_page_size) {
810*13c13397SRichard Henderson             char *s = size_to_str(host_page_size);
8112f7828b5SRichard Henderson             fprintf(stderr, "Reserved virtual address not aligned mod %s\n", s);
8122f7828b5SRichard Henderson             g_free(s);
8132f7828b5SRichard Henderson             exit(EXIT_FAILURE);
8142f7828b5SRichard Henderson         }
8158f67b9c6SRichard Henderson         if (max_reserved_va && reserved_va > max_reserved_va) {
8168f67b9c6SRichard Henderson             fprintf(stderr, "Reserved virtual address too big\n");
8178f67b9c6SRichard Henderson             exit(EXIT_FAILURE);
8188f67b9c6SRichard Henderson         }
8198f67b9c6SRichard Henderson     } else if (HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32) {
82095059f9cSRichard Henderson         /* MAX_RESERVED_VA + 1 is a large power of 2, so is aligned. */
82195059f9cSRichard Henderson         reserved_va = max_reserved_va;
8228f67b9c6SRichard Henderson     }
8238f67b9c6SRichard Henderson 
824c8fb5cf9SRichard Henderson     /*
825c8fb5cf9SRichard Henderson      * Temporarily disable
826c8fb5cf9SRichard Henderson      *   "comparison is always false due to limited range of data type"
827c8fb5cf9SRichard Henderson      * due to comparison between (possible) uint64_t and uintptr_t.
828c8fb5cf9SRichard Henderson      */
829c8fb5cf9SRichard Henderson #pragma GCC diagnostic push
830c8fb5cf9SRichard Henderson #pragma GCC diagnostic ignored "-Wtype-limits"
831c8fb5cf9SRichard Henderson 
832c8fb5cf9SRichard Henderson     /*
833c8fb5cf9SRichard Henderson      * Select an initial value for task_unmapped_base that is in range.
834c8fb5cf9SRichard Henderson      */
835c8fb5cf9SRichard Henderson     if (reserved_va) {
836c8fb5cf9SRichard Henderson         if (TASK_UNMAPPED_BASE < reserved_va) {
837c8fb5cf9SRichard Henderson             task_unmapped_base = TASK_UNMAPPED_BASE;
838c8fb5cf9SRichard Henderson         } else {
839c8fb5cf9SRichard Henderson             /* The most common default formula is TASK_SIZE / 3. */
840c8fb5cf9SRichard Henderson             task_unmapped_base = TARGET_PAGE_ALIGN(reserved_va / 3);
841c8fb5cf9SRichard Henderson         }
842c8fb5cf9SRichard Henderson     } else if (TASK_UNMAPPED_BASE < UINTPTR_MAX) {
843c8fb5cf9SRichard Henderson         task_unmapped_base = TASK_UNMAPPED_BASE;
844c8fb5cf9SRichard Henderson     } else {
845c8fb5cf9SRichard Henderson         /* 32-bit host: pick something medium size. */
846c8fb5cf9SRichard Henderson         task_unmapped_base = 0x10000000;
847c8fb5cf9SRichard Henderson     }
848c8fb5cf9SRichard Henderson     mmap_next_start = task_unmapped_base;
849c8fb5cf9SRichard Henderson 
850da2b71faSRichard Henderson     /* Similarly for elf_et_dyn_base. */
851da2b71faSRichard Henderson     if (reserved_va) {
852da2b71faSRichard Henderson         if (ELF_ET_DYN_BASE < reserved_va) {
853da2b71faSRichard Henderson             elf_et_dyn_base = ELF_ET_DYN_BASE;
854da2b71faSRichard Henderson         } else {
855da2b71faSRichard Henderson             /* The most common default formula is TASK_SIZE / 3 * 2. */
856da2b71faSRichard Henderson             elf_et_dyn_base = TARGET_PAGE_ALIGN(reserved_va / 3) * 2;
857da2b71faSRichard Henderson         }
858da2b71faSRichard Henderson     } else if (ELF_ET_DYN_BASE < UINTPTR_MAX) {
859da2b71faSRichard Henderson         elf_et_dyn_base = ELF_ET_DYN_BASE;
860da2b71faSRichard Henderson     } else {
861da2b71faSRichard Henderson         /* 32-bit host: pick something medium size. */
862da2b71faSRichard Henderson         elf_et_dyn_base = 0x18000000;
863da2b71faSRichard Henderson     }
864da2b71faSRichard Henderson 
865c8fb5cf9SRichard Henderson #pragma GCC diagnostic pop
866c8fb5cf9SRichard Henderson 
867a573e9baSRichard Henderson     {
868a573e9baSRichard Henderson         Error *err = NULL;
8695ebdd774SRichard Henderson         if (seed_optarg != NULL) {
870a573e9baSRichard Henderson             qemu_guest_random_seed_main(seed_optarg, &err);
871a573e9baSRichard Henderson         } else {
872a573e9baSRichard Henderson             qcrypto_init(&err);
873a573e9baSRichard Henderson         }
874a573e9baSRichard Henderson         if (err) {
875a573e9baSRichard Henderson             error_reportf_err(err, "cannot initialize crypto: ");
876a573e9baSRichard Henderson             exit(1);
877a573e9baSRichard Henderson         }
878c5e4a5a9SMagnus Reftel     }
879c5e4a5a9SMagnus Reftel 
88004a6dfebSaurel32     target_environ = envlist_to_environ(envlist, NULL);
88104a6dfebSaurel32     envlist_free(envlist);
882b12b6a18Sths 
883379f6698SPaul Brook     /*
884379f6698SPaul Brook      * Read in mmap_min_addr kernel parameter.  This value is used
885379f6698SPaul Brook      * When loading the ELF image to determine whether guest_base
88614f24e14SRichard Henderson      * is needed.  It is also used in mmap_find_vma.
887379f6698SPaul Brook      */
88814f24e14SRichard Henderson     {
889379f6698SPaul Brook         FILE *fp;
890379f6698SPaul Brook 
891379f6698SPaul Brook         if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
892379f6698SPaul Brook             unsigned long tmp;
893c9f80666SRichard Henderson             if (fscanf(fp, "%lu", &tmp) == 1 && tmp != 0) {
894379f6698SPaul Brook                 mmap_min_addr = tmp;
895c9f80666SRichard Henderson                 qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
896c9f80666SRichard Henderson                               mmap_min_addr);
897379f6698SPaul Brook             }
898379f6698SPaul Brook             fclose(fp);
899379f6698SPaul Brook         }
900379f6698SPaul Brook     }
901379f6698SPaul Brook 
9027d8cec95Saurel32     /*
903c9f80666SRichard Henderson      * We prefer to not make NULL pointers accessible to QEMU.
904c9f80666SRichard Henderson      * If we're in a chroot with no /proc, fall back to 1 page.
905c9f80666SRichard Henderson      */
906c9f80666SRichard Henderson     if (mmap_min_addr == 0) {
907*13c13397SRichard Henderson         mmap_min_addr = qemu_real_host_page_size();
908c9f80666SRichard Henderson         qemu_log_mask(CPU_LOG_PAGE,
909c9f80666SRichard Henderson                       "host mmap_min_addr=0x%lx (fallback)\n",
910c9f80666SRichard Henderson                       mmap_min_addr);
911c9f80666SRichard Henderson     }
912c9f80666SRichard Henderson 
913c9f80666SRichard Henderson     /*
9147d8cec95Saurel32      * Prepare copy of argv vector for target.
9157d8cec95Saurel32      */
9167d8cec95Saurel32     target_argc = argc - optind;
9177d8cec95Saurel32     target_argv = calloc(target_argc + 1, sizeof (char *));
9187d8cec95Saurel32     if (target_argv == NULL) {
9197d8cec95Saurel32         (void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
9204d1275c2SRiku Voipio         exit(EXIT_FAILURE);
9217d8cec95Saurel32     }
9227d8cec95Saurel32 
9237d8cec95Saurel32     /*
9247d8cec95Saurel32      * If argv0 is specified (using '-0' switch) we replace
9257d8cec95Saurel32      * argv[0] pointer with the given one.
9267d8cec95Saurel32      */
9277d8cec95Saurel32     i = 0;
9287d8cec95Saurel32     if (argv0 != NULL) {
9297d8cec95Saurel32         target_argv[i++] = strdup(argv0);
9307d8cec95Saurel32     }
9317d8cec95Saurel32     for (; i < target_argc; i++) {
9327d8cec95Saurel32         target_argv[i] = strdup(argv[optind + i]);
9337d8cec95Saurel32     }
9347d8cec95Saurel32     target_argv[target_argc] = NULL;
9357d8cec95Saurel32 
936c78d65e8SMarkus Armbruster     ts = g_new0(TaskState, 1);
937edf8e2afSMika Westerberg     init_task_state(ts);
938edf8e2afSMika Westerberg     /* build Task State */
939edf8e2afSMika Westerberg     ts->info = info;
940edf8e2afSMika Westerberg     ts->bprm = &bprm;
9410429a971SAndreas Färber     cpu->opaque = ts;
942edf8e2afSMika Westerberg     task_settid(ts);
943edf8e2afSMika Westerberg 
944c093364fSOwen Anderson     fd_trans_init();
945c093364fSOwen Anderson 
9469d3019bcSLaurent Vivier     ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs,
947fd4d81ddSArnaud Patard         info, &bprm);
948fd4d81ddSArnaud Patard     if (ret != 0) {
9499d3019bcSLaurent Vivier         printf("Error while loading %s: %s\n", exec_path, strerror(-ret));
9504d1275c2SRiku Voipio         _exit(EXIT_FAILURE);
95131e31b8aSbellard     }
95231e31b8aSbellard 
953b12b6a18Sths     for (wrk = target_environ; *wrk; wrk++) {
954ec45bbe5SSaurav Sachidanand         g_free(*wrk);
955b12b6a18Sths     }
956b12b6a18Sths 
957ec45bbe5SSaurav Sachidanand     g_free(target_environ);
958b12b6a18Sths 
95913829020SPaolo Bonzini     if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
96093756fdcSRichard Henderson         FILE *f = qemu_log_trylock();
96193756fdcSRichard Henderson         if (f) {
96293756fdcSRichard Henderson             fprintf(f, "guest_base  %p\n", (void *)guest_base);
96393756fdcSRichard Henderson             fprintf(f, "page layout changed following binary load\n");
96493756fdcSRichard Henderson             page_dump(f);
96554936004Sbellard 
96693756fdcSRichard Henderson             fprintf(f, "end_code    0x" TARGET_ABI_FMT_lx "\n",
96793756fdcSRichard Henderson                     info->end_code);
96893756fdcSRichard Henderson             fprintf(f, "start_code  0x" TARGET_ABI_FMT_lx "\n",
96993756fdcSRichard Henderson                     info->start_code);
97093756fdcSRichard Henderson             fprintf(f, "start_data  0x" TARGET_ABI_FMT_lx "\n",
97193756fdcSRichard Henderson                     info->start_data);
97293756fdcSRichard Henderson             fprintf(f, "end_data    0x" TARGET_ABI_FMT_lx "\n",
97393756fdcSRichard Henderson                     info->end_data);
97493756fdcSRichard Henderson             fprintf(f, "start_stack 0x" TARGET_ABI_FMT_lx "\n",
97593756fdcSRichard Henderson                     info->start_stack);
97693756fdcSRichard Henderson             fprintf(f, "brk         0x" TARGET_ABI_FMT_lx "\n",
97793756fdcSRichard Henderson                     info->brk);
97893756fdcSRichard Henderson             fprintf(f, "entry       0x" TARGET_ABI_FMT_lx "\n",
97993756fdcSRichard Henderson                     info->entry);
98093756fdcSRichard Henderson             fprintf(f, "argv_start  0x" TARGET_ABI_FMT_lx "\n",
98160f1c801SRichard Henderson                     info->argv);
98293756fdcSRichard Henderson             fprintf(f, "env_start   0x" TARGET_ABI_FMT_lx "\n",
98360f1c801SRichard Henderson                     info->envp);
98493756fdcSRichard Henderson             fprintf(f, "auxv_start  0x" TARGET_ABI_FMT_lx "\n",
98593756fdcSRichard Henderson                     info->saved_auxv);
98693756fdcSRichard Henderson             qemu_log_unlock(f);
98793756fdcSRichard Henderson         }
9882e77eac6Sblueswir1     }
98931e31b8aSbellard 
99053a5960aSpbrook     target_set_brk(info->brk);
99131e31b8aSbellard     syscall_init();
99266fb9763Sbellard     signal_init();
99331e31b8aSbellard 
9949002ec79SRichard Henderson     /* Now that we've loaded the binary, GUEST_BASE is fixed.  Delay
9959002ec79SRichard Henderson        generating the prologue until now so that the prologue can take
9969002ec79SRichard Henderson        the real value of GUEST_BASE into account.  */
997935f75aeSRichard Henderson     tcg_prologue_init();
9989002ec79SRichard Henderson 
999cd71c089SLaurent Vivier     target_cpu_copy_regs(env, regs);
1000cd71c089SLaurent Vivier 
1001fcedd920SAlex Bennée     if (gdbstub) {
1002fcedd920SAlex Bennée         if (gdbserver_start(gdbstub) < 0) {
1003fcedd920SAlex Bennée             fprintf(stderr, "qemu: could not open gdbserver on %s\n",
1004fcedd920SAlex Bennée                     gdbstub);
10054d1275c2SRiku Voipio             exit(EXIT_FAILURE);
1006ff7a981aSPeter Maydell         }
1007db6b81d4SAndreas Färber         gdb_handlesig(cpu, 0);
10081fddef4bSbellard     }
1009e4a4aaa5SRichard Henderson 
1010e4a4aaa5SRichard Henderson #ifdef CONFIG_SEMIHOSTING
1011e4a4aaa5SRichard Henderson     qemu_semihosting_guestfd_init();
1012e4a4aaa5SRichard Henderson #endif
1013e4a4aaa5SRichard Henderson 
10141b6b029eSbellard     cpu_loop(env);
10151b6b029eSbellard     /* never exits */
101631e31b8aSbellard     return 0;
101731e31b8aSbellard }
1018