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"
4116aa8eaaSPhilippe Mathieu-Daudé #include "user/guest-base.h"
4263c91552SPaolo Bonzini #include "exec/exec-all.h"
4385b4fa0cSPeter Maydell #include "exec/gdbstub.h"
44d96bf49bSAlex Bennée #include "gdbstub/user.h"
45d7ec12f8SRichard Henderson #include "tcg/startup.h"
461de7afc9SPaolo Bonzini #include "qemu/timer.h"
471de7afc9SPaolo Bonzini #include "qemu/envlist.h"
485ebdd774SRichard Henderson #include "qemu/guest-random.h"
49d8fd2954SPaul Brook #include "elf.h"
506533dd6eSLluís Vilanova #include "trace/control.h"
51542ca434SLaurent Vivier #include "target_elf.h"
52cd71c089SLaurent Vivier #include "cpu_loop-common.h"
53a573e9baSRichard Henderson #include "crypto/init.h"
54c093364fSOwen Anderson #include "fd-trans.h"
552113aed6SPeter Maydell #include "signal-common.h"
563ad0a769SPeter Maydell #include "loader.h"
575423e6d3SPeter Maydell #include "user-mmap.h"
58327b75a4SIlya Leoshkevich #include "tcg/perf.h"
59ff8a8bbcSRichard Henderson #include "exec/page-vary.h"
6004a6dfebSaurel32
61e4a4aaa5SRichard Henderson #ifdef CONFIG_SEMIHOSTING
62e4a4aaa5SRichard Henderson #include "semihosting/semihost.h"
63e4a4aaa5SRichard Henderson #endif
64e4a4aaa5SRichard Henderson
656e1c0d7bSLaurent Vivier #ifndef AT_FLAGS_PRESERVE_ARGV0
666e1c0d7bSLaurent Vivier #define AT_FLAGS_PRESERVE_ARGV0_BIT 0
676e1c0d7bSLaurent Vivier #define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
686e1c0d7bSLaurent Vivier #endif
696e1c0d7bSLaurent Vivier
70d088d664Saurel32 char *exec_path;
71258bec39SHelge Deller char real_exec_path[PATH_MAX];
72d088d664Saurel32
733cfb0456SPeter Maydell static bool opt_one_insn_per_tb;
748cb76755SStefan Weil static const char *argv0;
75fcedd920SAlex Bennée static const char *gdbstub;
768cb76755SStefan Weil static envlist_t *envlist;
7751fb256aSAndreas Färber static const char *cpu_model;
782278b939SIgor Mammedov static const char *cpu_type;
795ebdd774SRichard Henderson static const char *seed_optarg;
80379f6698SPaul Brook unsigned long mmap_min_addr;
815ca870b9SRichard Henderson uintptr_t guest_base;
82e307c192SRichard Henderson bool have_guest_base;
83120a9848SPaolo Bonzini
84288e65b9SAlexander Graf /*
854b25a506SJosh Kunz * Used to implement backwards-compatibility for the `-strace`, and
864b25a506SJosh Kunz * QEMU_STRACE options. Without this, the QEMU_LOG can be overwritten by
874b25a506SJosh Kunz * -strace, or vice versa.
884b25a506SJosh Kunz */
894b25a506SJosh Kunz static bool enable_strace;
904b25a506SJosh Kunz
914b25a506SJosh Kunz /*
924b25a506SJosh Kunz * The last log mask given by the user in an environment variable or argument.
934b25a506SJosh Kunz * Used to support command line arguments overriding environment variables.
944b25a506SJosh Kunz */
954b25a506SJosh Kunz static int last_log_mask;
96b410253fSRichard Henderson static const char *last_log_filename;
974b25a506SJosh Kunz
984b25a506SJosh Kunz /*
99288e65b9SAlexander Graf * When running 32-on-64 we should make sure we can fit all of the possible
100288e65b9SAlexander Graf * guest address space into a contiguous chunk of virtual host memory.
101288e65b9SAlexander Graf *
102288e65b9SAlexander Graf * This way we will never overlap with our own libraries or binaries or stack
103288e65b9SAlexander Graf * or anything else that QEMU maps.
10418e80c55SRichard Henderson *
10518e80c55SRichard Henderson * Many cpus reserve the high bit (or more than one for some 64-bit cpus)
10618e80c55SRichard Henderson * of the address for the kernel. Some cpus rely on this and user space
10718e80c55SRichard Henderson * uses the high bit(s) for pointer tagging and the like. For them, we
10818e80c55SRichard Henderson * must preserve the expected address space.
109288e65b9SAlexander Graf */
11018e80c55SRichard Henderson #ifndef MAX_RESERVED_VA
11118e80c55SRichard Henderson # if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
11218e80c55SRichard Henderson # if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
11318e80c55SRichard Henderson (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
11495059f9cSRichard Henderson # define MAX_RESERVED_VA(CPU) 0xfffffffful
115314992b1SAlexander Graf # else
11695059f9cSRichard Henderson # define MAX_RESERVED_VA(CPU) ((1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1)
117314992b1SAlexander Graf # endif
118288e65b9SAlexander Graf # else
1198f67b9c6SRichard Henderson # define MAX_RESERVED_VA(CPU) 0
12018e80c55SRichard Henderson # endif
12118e80c55SRichard Henderson #endif
12218e80c55SRichard Henderson
12368a1c816SPaul Brook unsigned long reserved_va;
1241b530a6dSaurel32
125d03f9c32SMeador Inge static void usage(int exitcode);
126fc9c5412SJohannes Schauer
1277ee2822cSPaolo Bonzini static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
128e586822aSRiku Voipio const char *qemu_uname_release;
129586314f2Sbellard
1300a3346b5SHelge Deller #if !defined(TARGET_DEFAULT_STACK_SIZE)
1319de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
1329de5e440Sbellard we allocate a bigger stack. Need a better solution, for example
1339de5e440Sbellard by remapping the process stack directly at the right place */
1340a3346b5SHelge Deller #define TARGET_DEFAULT_STACK_SIZE 8 * 1024 * 1024UL
1350a3346b5SHelge Deller #endif
1360a3346b5SHelge Deller
1370a3346b5SHelge Deller unsigned long guest_stack_size = TARGET_DEFAULT_STACK_SIZE;
13831e31b8aSbellard
139d5975363Spbrook /***********************************************************/
140d5975363Spbrook /* Helper routines for implementing atomic operations. */
141d5975363Spbrook
142d5975363Spbrook /* Make sure everything is in a consistent state for calling fork(). */
fork_start(void)143d5975363Spbrook void fork_start(void)
144d5975363Spbrook {
14506065c45SPeter Maydell start_exclusive();
146d032d1b4SRiku Voipio mmap_fork_start();
147024949caSPeter Maydell cpu_list_lock();
148f7e15affSAlex Bennée qemu_plugin_user_prefork_lock();
1493d6ed98dSIlya Leoshkevich gdbserver_fork_start();
150d5975363Spbrook }
151d5975363Spbrook
fork_end(pid_t pid)1524edc98fcSIlya Leoshkevich void fork_end(pid_t pid)
153d5975363Spbrook {
1544edc98fcSIlya Leoshkevich bool child = pid == 0;
1554edc98fcSIlya Leoshkevich
156f7e15affSAlex Bennée qemu_plugin_user_postfork(child);
157d032d1b4SRiku Voipio mmap_fork_end(child);
158d5975363Spbrook if (child) {
159bdc44640SAndreas Färber CPUState *cpu, *next_cpu;
160d5975363Spbrook /* Child processes created by fork() only have a single thread.
161d5975363Spbrook Discard information about the parent threads. */
162bdc44640SAndreas Färber CPU_FOREACH_SAFE(cpu, next_cpu) {
163bdc44640SAndreas Färber if (cpu != thread_cpu) {
1643c55dd58SPhilippe Mathieu-Daudé QTAILQ_REMOVE_RCU(&cpus_queue, cpu, node);
165bdc44640SAndreas Färber }
166bdc44640SAndreas Färber }
167267f685bSPaolo Bonzini qemu_init_cpu_list();
168d4e1369aSIlya Leoshkevich get_task_state(thread_cpu)->ts_tid = qemu_get_thread_id();
169d5975363Spbrook } else {
170267f685bSPaolo Bonzini cpu_list_unlock();
171d5975363Spbrook }
1726604b057SIlya Leoshkevich gdbserver_fork_end(thread_cpu, pid);
1737de0816fSIlya Leoshkevich /*
1747de0816fSIlya Leoshkevich * qemu_init_cpu_list() reinitialized the child exclusive state, but we
1757de0816fSIlya Leoshkevich * also need to keep current_cpu consistent, so call end_exclusive() for
1767de0816fSIlya Leoshkevich * both child and parent.
1777de0816fSIlya Leoshkevich */
1787de0816fSIlya Leoshkevich end_exclusive();
179d5975363Spbrook }
180d5975363Spbrook
181b44316fbSPeter Maydell __thread CPUState *thread_cpu;
18259faf6d6Sbellard
qemu_cpu_is_self(CPUState * cpu)183178f9429SSergey Fedorov bool qemu_cpu_is_self(CPUState *cpu)
184178f9429SSergey Fedorov {
185178f9429SSergey Fedorov return thread_cpu == cpu;
186178f9429SSergey Fedorov }
187178f9429SSergey Fedorov
qemu_cpu_kick(CPUState * cpu)188178f9429SSergey Fedorov void qemu_cpu_kick(CPUState *cpu)
189178f9429SSergey Fedorov {
190178f9429SSergey Fedorov cpu_exit(cpu);
191178f9429SSergey Fedorov }
192178f9429SSergey Fedorov
task_settid(TaskState * ts)193edf8e2afSMika Westerberg void task_settid(TaskState *ts)
194edf8e2afSMika Westerberg {
195edf8e2afSMika Westerberg if (ts->ts_tid == 0) {
196edf8e2afSMika Westerberg ts->ts_tid = (pid_t)syscall(SYS_gettid);
197edf8e2afSMika Westerberg }
198edf8e2afSMika Westerberg }
199edf8e2afSMika Westerberg
stop_all_tasks(void)200edf8e2afSMika Westerberg void stop_all_tasks(void)
201edf8e2afSMika Westerberg {
202edf8e2afSMika Westerberg /*
203edf8e2afSMika Westerberg * We trust that when using NPTL, start_exclusive()
204edf8e2afSMika Westerberg * handles thread stopping correctly.
205edf8e2afSMika Westerberg */
206edf8e2afSMika Westerberg start_exclusive();
207edf8e2afSMika Westerberg }
208edf8e2afSMika Westerberg
209c3a92833Spbrook /* Assumes contents are already zeroed. */
init_task_state(TaskState * ts)210624f7979Spbrook void init_task_state(TaskState *ts)
211624f7979Spbrook {
212eb33cdaeSCameron Esfahani long ticks_per_sec;
213eb33cdaeSCameron Esfahani struct timespec bt;
214eb33cdaeSCameron Esfahani
215624f7979Spbrook ts->used = 1;
2165bfce0b7SPeter Maydell ts->sigaltstack_used = (struct target_sigaltstack) {
2175bfce0b7SPeter Maydell .ss_sp = 0,
2185bfce0b7SPeter Maydell .ss_size = 0,
2195bfce0b7SPeter Maydell .ss_flags = TARGET_SS_DISABLE,
2205bfce0b7SPeter Maydell };
221eb33cdaeSCameron Esfahani
222eb33cdaeSCameron Esfahani /* Capture task start time relative to system boot */
223eb33cdaeSCameron Esfahani
224eb33cdaeSCameron Esfahani ticks_per_sec = sysconf(_SC_CLK_TCK);
225eb33cdaeSCameron Esfahani
226eb33cdaeSCameron Esfahani if ((ticks_per_sec > 0) && !clock_gettime(CLOCK_BOOTTIME, &bt)) {
227eb33cdaeSCameron Esfahani /* start_boottime is expressed in clock ticks */
228eb33cdaeSCameron Esfahani ts->start_boottime = bt.tv_sec * (uint64_t) ticks_per_sec;
229eb33cdaeSCameron Esfahani ts->start_boottime += bt.tv_nsec * (uint64_t) ticks_per_sec /
230eb33cdaeSCameron Esfahani NANOSECONDS_PER_SECOND;
231eb33cdaeSCameron Esfahani }
232624f7979Spbrook }
2339de5e440Sbellard
cpu_copy(CPUArchState * env)23430ba0ee5SAndreas Färber CPUArchState *cpu_copy(CPUArchState *env)
23530ba0ee5SAndreas Färber {
23629a0af61SRichard Henderson CPUState *cpu = env_cpu(env);
2372278b939SIgor Mammedov CPUState *new_cpu = cpu_create(cpu_type);
238b77af26eSRichard Henderson CPUArchState *new_env = cpu_env(new_cpu);
23930ba0ee5SAndreas Färber CPUBreakpoint *bp;
24030ba0ee5SAndreas Färber
24130ba0ee5SAndreas Färber /* Reset non arch specific state */
24275a34036SAndreas Färber cpu_reset(new_cpu);
24330ba0ee5SAndreas Färber
2446cc9d67cSRichard Henderson new_cpu->tcg_cflags = cpu->tcg_cflags;
24530ba0ee5SAndreas Färber memcpy(new_env, env, sizeof(CPUArchState));
2462732c739Sfanwj@mail.ustc.edu.cn #if defined(TARGET_I386) || defined(TARGET_X86_64)
2472732c739Sfanwj@mail.ustc.edu.cn new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
2482732c739Sfanwj@mail.ustc.edu.cn PROT_READ | PROT_WRITE,
2492732c739Sfanwj@mail.ustc.edu.cn MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
2502732c739Sfanwj@mail.ustc.edu.cn memcpy(g2h_untagged(new_env->gdt.base), g2h_untagged(env->gdt.base),
2512732c739Sfanwj@mail.ustc.edu.cn sizeof(uint64_t) * TARGET_GDT_ENTRIES);
2522732c739Sfanwj@mail.ustc.edu.cn OBJECT(new_cpu)->free = OBJECT(cpu)->free;
2532732c739Sfanwj@mail.ustc.edu.cn #endif
25430ba0ee5SAndreas Färber
25530ba0ee5SAndreas Färber /* Clone all break/watchpoints.
25630ba0ee5SAndreas Färber Note: Once we support ptrace with hw-debug register access, make sure
25730ba0ee5SAndreas Färber BP_CPU break/watchpoints are handled correctly on clone. */
2581d085f6cSThierry Bultel QTAILQ_INIT(&new_cpu->breakpoints);
259f0c3c505SAndreas Färber QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
260b3310ab3SAndreas Färber cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL);
26130ba0ee5SAndreas Färber }
26230ba0ee5SAndreas Färber
26330ba0ee5SAndreas Färber return new_env;
26430ba0ee5SAndreas Färber }
26530ba0ee5SAndreas Färber
handle_arg_help(const char * arg)266fc9c5412SJohannes Schauer static void handle_arg_help(const char *arg)
267fc9c5412SJohannes Schauer {
2684d1275c2SRiku Voipio usage(EXIT_SUCCESS);
269fc9c5412SJohannes Schauer }
270fc9c5412SJohannes Schauer
handle_arg_log(const char * arg)271fc9c5412SJohannes Schauer static void handle_arg_log(const char *arg)
272fc9c5412SJohannes Schauer {
2734b25a506SJosh Kunz last_log_mask = qemu_str_to_log_mask(arg);
2744b25a506SJosh Kunz if (!last_log_mask) {
27559a6fa6eSPeter Maydell qemu_print_log_usage(stdout);
2764d1275c2SRiku Voipio exit(EXIT_FAILURE);
277fc9c5412SJohannes Schauer }
278fc9c5412SJohannes Schauer }
279fc9c5412SJohannes Schauer
handle_arg_dfilter(const char * arg)2808423fa90SAlex Bennée static void handle_arg_dfilter(const char *arg)
2818423fa90SAlex Bennée {
2827f4341e8SAlex Bennée qemu_set_dfilter_ranges(arg, &error_fatal);
2838423fa90SAlex Bennée }
2848423fa90SAlex Bennée
handle_arg_log_filename(const char * arg)28550171d42S陳韋任 static void handle_arg_log_filename(const char *arg)
28650171d42S陳韋任 {
287b410253fSRichard Henderson last_log_filename = arg;
28850171d42S陳韋任 }
28950171d42S陳韋任
handle_arg_set_env(const char * arg)290fc9c5412SJohannes Schauer static void handle_arg_set_env(const char *arg)
291fc9c5412SJohannes Schauer {
292fc9c5412SJohannes Schauer char *r, *p, *token;
293fc9c5412SJohannes Schauer r = p = strdup(arg);
294fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) {
295fc9c5412SJohannes Schauer if (envlist_setenv(envlist, token) != 0) {
2964d1275c2SRiku Voipio usage(EXIT_FAILURE);
297fc9c5412SJohannes Schauer }
298fc9c5412SJohannes Schauer }
299fc9c5412SJohannes Schauer free(r);
300fc9c5412SJohannes Schauer }
301fc9c5412SJohannes Schauer
handle_arg_unset_env(const char * arg)302fc9c5412SJohannes Schauer static void handle_arg_unset_env(const char *arg)
303fc9c5412SJohannes Schauer {
304fc9c5412SJohannes Schauer char *r, *p, *token;
305fc9c5412SJohannes Schauer r = p = strdup(arg);
306fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) {
307fc9c5412SJohannes Schauer if (envlist_unsetenv(envlist, token) != 0) {
3084d1275c2SRiku Voipio usage(EXIT_FAILURE);
309fc9c5412SJohannes Schauer }
310fc9c5412SJohannes Schauer }
311fc9c5412SJohannes Schauer free(r);
312fc9c5412SJohannes Schauer }
313fc9c5412SJohannes Schauer
handle_arg_argv0(const char * arg)314fc9c5412SJohannes Schauer static void handle_arg_argv0(const char *arg)
315fc9c5412SJohannes Schauer {
316fc9c5412SJohannes Schauer argv0 = strdup(arg);
317fc9c5412SJohannes Schauer }
318fc9c5412SJohannes Schauer
handle_arg_stack_size(const char * arg)319fc9c5412SJohannes Schauer static void handle_arg_stack_size(const char *arg)
320fc9c5412SJohannes Schauer {
321fc9c5412SJohannes Schauer char *p;
322fc9c5412SJohannes Schauer guest_stack_size = strtoul(arg, &p, 0);
323fc9c5412SJohannes Schauer if (guest_stack_size == 0) {
3244d1275c2SRiku Voipio usage(EXIT_FAILURE);
325fc9c5412SJohannes Schauer }
326fc9c5412SJohannes Schauer
327fc9c5412SJohannes Schauer if (*p == 'M') {
328b52713c1SPhilippe Mathieu-Daudé guest_stack_size *= MiB;
329fc9c5412SJohannes Schauer } else if (*p == 'k' || *p == 'K') {
330b52713c1SPhilippe Mathieu-Daudé guest_stack_size *= KiB;
331fc9c5412SJohannes Schauer }
332fc9c5412SJohannes Schauer }
333fc9c5412SJohannes Schauer
handle_arg_ld_prefix(const char * arg)334fc9c5412SJohannes Schauer static void handle_arg_ld_prefix(const char *arg)
335fc9c5412SJohannes Schauer {
336fc9c5412SJohannes Schauer interp_prefix = strdup(arg);
337fc9c5412SJohannes Schauer }
338fc9c5412SJohannes Schauer
handle_arg_pagesize(const char * arg)339fc9c5412SJohannes Schauer static void handle_arg_pagesize(const char *arg)
340fc9c5412SJohannes Schauer {
34101e44980SRichard Henderson unsigned size, want = qemu_real_host_page_size();
34201e44980SRichard Henderson
34301e44980SRichard Henderson if (qemu_strtoui(arg, NULL, 10, &size) || size != want) {
34401e44980SRichard Henderson warn_report("Deprecated page size option cannot "
34501e44980SRichard Henderson "change host page size (%u)", want);
346fc9c5412SJohannes Schauer }
347fc9c5412SJohannes Schauer }
348fc9c5412SJohannes Schauer
handle_arg_seed(const char * arg)3495ebdd774SRichard Henderson static void handle_arg_seed(const char *arg)
350c5e4a5a9SMagnus Reftel {
3515ebdd774SRichard Henderson seed_optarg = arg;
352c5e4a5a9SMagnus Reftel }
353c5e4a5a9SMagnus Reftel
handle_arg_gdb(const char * arg)354fc9c5412SJohannes Schauer static void handle_arg_gdb(const char *arg)
355fc9c5412SJohannes Schauer {
356fcedd920SAlex Bennée gdbstub = g_strdup(arg);
357fc9c5412SJohannes Schauer }
358fc9c5412SJohannes Schauer
handle_arg_uname(const char * arg)359fc9c5412SJohannes Schauer static void handle_arg_uname(const char *arg)
360fc9c5412SJohannes Schauer {
361fc9c5412SJohannes Schauer qemu_uname_release = strdup(arg);
362fc9c5412SJohannes Schauer }
363fc9c5412SJohannes Schauer
handle_arg_cpu(const char * arg)364fc9c5412SJohannes Schauer static void handle_arg_cpu(const char *arg)
365fc9c5412SJohannes Schauer {
366fc9c5412SJohannes Schauer cpu_model = strdup(arg);
367c8057f95SPeter Maydell if (cpu_model == NULL || is_help_option(cpu_model)) {
368b67e5cb4SThomas Huth list_cpus();
3694d1275c2SRiku Voipio exit(EXIT_FAILURE);
370fc9c5412SJohannes Schauer }
371fc9c5412SJohannes Schauer }
372fc9c5412SJohannes Schauer
handle_arg_guest_base(const char * arg)373fc9c5412SJohannes Schauer static void handle_arg_guest_base(const char *arg)
374fc9c5412SJohannes Schauer {
375fc9c5412SJohannes Schauer guest_base = strtol(arg, NULL, 0);
376e307c192SRichard Henderson have_guest_base = true;
377fc9c5412SJohannes Schauer }
378fc9c5412SJohannes Schauer
handle_arg_reserved_va(const char * arg)379fc9c5412SJohannes Schauer static void handle_arg_reserved_va(const char *arg)
380fc9c5412SJohannes Schauer {
381fc9c5412SJohannes Schauer char *p;
382fc9c5412SJohannes Schauer int shift = 0;
38395059f9cSRichard Henderson unsigned long val;
38495059f9cSRichard Henderson
38595059f9cSRichard Henderson val = strtoul(arg, &p, 0);
386fc9c5412SJohannes Schauer switch (*p) {
387fc9c5412SJohannes Schauer case 'k':
388fc9c5412SJohannes Schauer case 'K':
389fc9c5412SJohannes Schauer shift = 10;
390fc9c5412SJohannes Schauer break;
391fc9c5412SJohannes Schauer case 'M':
392fc9c5412SJohannes Schauer shift = 20;
393fc9c5412SJohannes Schauer break;
394fc9c5412SJohannes Schauer case 'G':
395fc9c5412SJohannes Schauer shift = 30;
396fc9c5412SJohannes Schauer break;
397fc9c5412SJohannes Schauer }
398fc9c5412SJohannes Schauer if (shift) {
39995059f9cSRichard Henderson unsigned long unshifted = val;
400fc9c5412SJohannes Schauer p++;
40195059f9cSRichard Henderson val <<= shift;
40295059f9cSRichard Henderson if (val >> shift != unshifted) {
403fc9c5412SJohannes Schauer fprintf(stderr, "Reserved virtual address too big\n");
4044d1275c2SRiku Voipio exit(EXIT_FAILURE);
405fc9c5412SJohannes Schauer }
406fc9c5412SJohannes Schauer }
407fc9c5412SJohannes Schauer if (*p) {
408fc9c5412SJohannes Schauer fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
4094d1275c2SRiku Voipio exit(EXIT_FAILURE);
410fc9c5412SJohannes Schauer }
41195059f9cSRichard Henderson /* The representation is size - 1, with 0 remaining "default". */
41295059f9cSRichard Henderson reserved_va = val ? val - 1 : 0;
413fc9c5412SJohannes Schauer }
414fc9c5412SJohannes Schauer
415*c107521eSIlya Leoshkevich static const char *rtsig_map = CONFIG_QEMU_RTSIG_MAP;
416*c107521eSIlya Leoshkevich
handle_arg_rtsig_map(const char * arg)417*c107521eSIlya Leoshkevich static void handle_arg_rtsig_map(const char *arg)
418*c107521eSIlya Leoshkevich {
419*c107521eSIlya Leoshkevich rtsig_map = arg;
420*c107521eSIlya Leoshkevich }
421*c107521eSIlya Leoshkevich
handle_arg_one_insn_per_tb(const char * arg)422e99c1f89SPeter Maydell static void handle_arg_one_insn_per_tb(const char *arg)
423fc9c5412SJohannes Schauer {
4243cfb0456SPeter Maydell opt_one_insn_per_tb = true;
425fc9c5412SJohannes Schauer }
426fc9c5412SJohannes Schauer
handle_arg_strace(const char * arg)427fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg)
428fc9c5412SJohannes Schauer {
4294b25a506SJosh Kunz enable_strace = true;
430fc9c5412SJohannes Schauer }
431fc9c5412SJohannes Schauer
handle_arg_version(const char * arg)432fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg)
433fc9c5412SJohannes Schauer {
4347e563bfbSThomas Huth printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
4350781dd6eSThomas Huth "\n" QEMU_COPYRIGHT "\n");
4364d1275c2SRiku Voipio exit(EXIT_SUCCESS);
437fc9c5412SJohannes Schauer }
438fc9c5412SJohannes Schauer
handle_arg_trace(const char * arg)4396533dd6eSLluís Vilanova static void handle_arg_trace(const char *arg)
4406533dd6eSLluís Vilanova {
44192eecfffSPaolo Bonzini trace_opt_parse(arg);
4426533dd6eSLluís Vilanova }
4436533dd6eSLluís Vilanova
444130ea832SMax Filippov #if defined(TARGET_XTENSA)
handle_arg_abi_call0(const char * arg)445130ea832SMax Filippov static void handle_arg_abi_call0(const char *arg)
446130ea832SMax Filippov {
447130ea832SMax Filippov xtensa_set_abi_call0();
448130ea832SMax Filippov }
449130ea832SMax Filippov #endif
450130ea832SMax Filippov
handle_arg_perfmap(const char * arg)4515584e2dbSIlya Leoshkevich static void handle_arg_perfmap(const char *arg)
4525584e2dbSIlya Leoshkevich {
4535584e2dbSIlya Leoshkevich perf_enable_perfmap();
4545584e2dbSIlya Leoshkevich }
4555584e2dbSIlya Leoshkevich
handle_arg_jitdump(const char * arg)4565584e2dbSIlya Leoshkevich static void handle_arg_jitdump(const char *arg)
4575584e2dbSIlya Leoshkevich {
4585584e2dbSIlya Leoshkevich perf_enable_jitdump();
4595584e2dbSIlya Leoshkevich }
4605584e2dbSIlya Leoshkevich
461f308f64eSLluís Vilanova static QemuPluginList plugins = QTAILQ_HEAD_INITIALIZER(plugins);
462f308f64eSLluís Vilanova
463f308f64eSLluís Vilanova #ifdef CONFIG_PLUGIN
handle_arg_plugin(const char * arg)464f308f64eSLluís Vilanova static void handle_arg_plugin(const char *arg)
465f308f64eSLluís Vilanova {
466f308f64eSLluís Vilanova qemu_plugin_opt_parse(arg, &plugins);
467f308f64eSLluís Vilanova }
468f308f64eSLluís Vilanova #endif
469f308f64eSLluís Vilanova
470fc9c5412SJohannes Schauer struct qemu_argument {
471fc9c5412SJohannes Schauer const char *argv;
472fc9c5412SJohannes Schauer const char *env;
473fc9c5412SJohannes Schauer bool has_arg;
474fc9c5412SJohannes Schauer void (*handle_opt)(const char *arg);
475fc9c5412SJohannes Schauer const char *example;
476fc9c5412SJohannes Schauer const char *help;
477fc9c5412SJohannes Schauer };
478fc9c5412SJohannes Schauer
47942644ceeSJim Meyering static const struct qemu_argument arg_table[] = {
480fc9c5412SJohannes Schauer {"h", "", false, handle_arg_help,
481fc9c5412SJohannes Schauer "", "print this help"},
482daaf8c8eSMeador Inge {"help", "", false, handle_arg_help,
483daaf8c8eSMeador Inge "", ""},
484fc9c5412SJohannes Schauer {"g", "QEMU_GDB", true, handle_arg_gdb,
485fc9c5412SJohannes Schauer "port", "wait gdb connection to 'port'"},
486fc9c5412SJohannes Schauer {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix,
487fc9c5412SJohannes Schauer "path", "set the elf interpreter prefix to 'path'"},
488fc9c5412SJohannes Schauer {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size,
489fc9c5412SJohannes Schauer "size", "set the stack size to 'size' bytes"},
490fc9c5412SJohannes Schauer {"cpu", "QEMU_CPU", true, handle_arg_cpu,
491c8057f95SPeter Maydell "model", "select CPU (-cpu help for list)"},
492fc9c5412SJohannes Schauer {"E", "QEMU_SET_ENV", true, handle_arg_set_env,
493fc9c5412SJohannes Schauer "var=value", "sets targets environment variable (see below)"},
494fc9c5412SJohannes Schauer {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env,
495fc9c5412SJohannes Schauer "var", "unsets targets environment variable (see below)"},
496fc9c5412SJohannes Schauer {"0", "QEMU_ARGV0", true, handle_arg_argv0,
497fc9c5412SJohannes Schauer "argv0", "forces target process argv[0] to be 'argv0'"},
498fc9c5412SJohannes Schauer {"r", "QEMU_UNAME", true, handle_arg_uname,
499fc9c5412SJohannes Schauer "uname", "set qemu uname release string to 'uname'"},
500fc9c5412SJohannes Schauer {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base,
501fc9c5412SJohannes Schauer "address", "set guest_base address to 'address'"},
502fc9c5412SJohannes Schauer {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
503fc9c5412SJohannes Schauer "size", "reserve 'size' bytes for guest virtual address space"},
504*c107521eSIlya Leoshkevich {"t", "QEMU_RTSIG_MAP", true, handle_arg_rtsig_map,
505*c107521eSIlya Leoshkevich "tsig hsig n[,...]",
506*c107521eSIlya Leoshkevich "map target rt signals [tsig,tsig+n) to [hsig,hsig+n]"},
507fc9c5412SJohannes Schauer {"d", "QEMU_LOG", true, handle_arg_log,
508989b697dSPeter Maydell "item[,...]", "enable logging of specified items "
509989b697dSPeter Maydell "(use '-d help' for a list of items)"},
5108423fa90SAlex Bennée {"dfilter", "QEMU_DFILTER", true, handle_arg_dfilter,
5118423fa90SAlex Bennée "range[,...]","filter logging based on address range"},
51250171d42S陳韋任 {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
513989b697dSPeter Maydell "logfile", "write logs to 'logfile' (default stderr)"},
514fc9c5412SJohannes Schauer {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,
51501e44980SRichard Henderson "pagesize", "deprecated change to host page size"},
516e99c1f89SPeter Maydell {"one-insn-per-tb",
517e99c1f89SPeter Maydell "QEMU_ONE_INSN_PER_TB", false, handle_arg_one_insn_per_tb,
518e99c1f89SPeter Maydell "", "run with one guest instruction per emulated TB"},
519fc9c5412SJohannes Schauer {"strace", "QEMU_STRACE", false, handle_arg_strace,
520fc9c5412SJohannes Schauer "", "log system calls"},
5215ebdd774SRichard Henderson {"seed", "QEMU_RAND_SEED", true, handle_arg_seed,
522c5e4a5a9SMagnus Reftel "", "Seed for pseudo-random number generator"},
5236533dd6eSLluís Vilanova {"trace", "QEMU_TRACE", true, handle_arg_trace,
5246533dd6eSLluís Vilanova "", "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
525f308f64eSLluís Vilanova #ifdef CONFIG_PLUGIN
526f308f64eSLluís Vilanova {"plugin", "QEMU_PLUGIN", true, handle_arg_plugin,
5273a445acbSMahmoud Mandour "", "[file=]<file>[,<argname>=<argvalue>]"},
528f308f64eSLluís Vilanova #endif
529fc9c5412SJohannes Schauer {"version", "QEMU_VERSION", false, handle_arg_version,
5301386d4c0SPeter Maydell "", "display version information and exit"},
531130ea832SMax Filippov #if defined(TARGET_XTENSA)
532130ea832SMax Filippov {"xtensa-abi-call0", "QEMU_XTENSA_ABI_CALL0", false, handle_arg_abi_call0,
533130ea832SMax Filippov "", "assume CALL0 Xtensa ABI"},
534130ea832SMax Filippov #endif
5355584e2dbSIlya Leoshkevich {"perfmap", "QEMU_PERFMAP", false, handle_arg_perfmap,
5365584e2dbSIlya Leoshkevich "", "Generate a /tmp/perf-${pid}.map file for perf"},
5375584e2dbSIlya Leoshkevich {"jitdump", "QEMU_JITDUMP", false, handle_arg_jitdump,
5385584e2dbSIlya Leoshkevich "", "Generate a jit-${pid}.dump file for perf"},
539fc9c5412SJohannes Schauer {NULL, NULL, false, NULL, NULL, NULL}
540fc9c5412SJohannes Schauer };
541fc9c5412SJohannes Schauer
usage(int exitcode)542d03f9c32SMeador Inge static void usage(int exitcode)
543fc9c5412SJohannes Schauer {
54442644ceeSJim Meyering const struct qemu_argument *arginfo;
545fc9c5412SJohannes Schauer int maxarglen;
546fc9c5412SJohannes Schauer int maxenvlen;
547fc9c5412SJohannes Schauer
5482e59915dSPaolo Bonzini printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
5492e59915dSPaolo Bonzini "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n"
550fc9c5412SJohannes Schauer "\n"
551fc9c5412SJohannes Schauer "Options and associated environment variables:\n"
552fc9c5412SJohannes Schauer "\n");
553fc9c5412SJohannes Schauer
55463ec54d7SPeter Maydell /* Calculate column widths. We must always have at least enough space
55563ec54d7SPeter Maydell * for the column header.
55663ec54d7SPeter Maydell */
55763ec54d7SPeter Maydell maxarglen = strlen("Argument");
55863ec54d7SPeter Maydell maxenvlen = strlen("Env-variable");
559fc9c5412SJohannes Schauer
560fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
56163ec54d7SPeter Maydell int arglen = strlen(arginfo->argv);
56263ec54d7SPeter Maydell if (arginfo->has_arg) {
56363ec54d7SPeter Maydell arglen += strlen(arginfo->example) + 1;
56463ec54d7SPeter Maydell }
565fc9c5412SJohannes Schauer if (strlen(arginfo->env) > maxenvlen) {
566fc9c5412SJohannes Schauer maxenvlen = strlen(arginfo->env);
567fc9c5412SJohannes Schauer }
56863ec54d7SPeter Maydell if (arglen > maxarglen) {
56963ec54d7SPeter Maydell maxarglen = arglen;
570fc9c5412SJohannes Schauer }
571fc9c5412SJohannes Schauer }
572fc9c5412SJohannes Schauer
57363ec54d7SPeter Maydell printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
57463ec54d7SPeter Maydell maxenvlen, "Env-variable");
575fc9c5412SJohannes Schauer
576fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
577fc9c5412SJohannes Schauer if (arginfo->has_arg) {
578fc9c5412SJohannes Schauer printf("-%s %-*s %-*s %s\n", arginfo->argv,
57963ec54d7SPeter Maydell (int)(maxarglen - strlen(arginfo->argv) - 1),
58063ec54d7SPeter Maydell arginfo->example, maxenvlen, arginfo->env, arginfo->help);
581fc9c5412SJohannes Schauer } else {
58263ec54d7SPeter Maydell printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
583fc9c5412SJohannes Schauer maxenvlen, arginfo->env,
584fc9c5412SJohannes Schauer arginfo->help);
585fc9c5412SJohannes Schauer }
586fc9c5412SJohannes Schauer }
587fc9c5412SJohannes Schauer
588fc9c5412SJohannes Schauer printf("\n"
589fc9c5412SJohannes Schauer "Defaults:\n"
590fc9c5412SJohannes Schauer "QEMU_LD_PREFIX = %s\n"
591989b697dSPeter Maydell "QEMU_STACK_SIZE = %ld byte\n",
592fc9c5412SJohannes Schauer interp_prefix,
593989b697dSPeter Maydell guest_stack_size);
594fc9c5412SJohannes Schauer
595fc9c5412SJohannes Schauer printf("\n"
596fc9c5412SJohannes Schauer "You can use -E and -U options or the QEMU_SET_ENV and\n"
597fc9c5412SJohannes Schauer "QEMU_UNSET_ENV environment variables to set and unset\n"
598fc9c5412SJohannes Schauer "environment variables for the target process.\n"
599fc9c5412SJohannes Schauer "It is possible to provide several variables by separating them\n"
600fc9c5412SJohannes Schauer "by commas in getsubopt(3) style. Additionally it is possible to\n"
601fc9c5412SJohannes Schauer "provide the -E and -U options multiple times.\n"
602fc9c5412SJohannes Schauer "The following lines are equivalent:\n"
603fc9c5412SJohannes Schauer " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
604fc9c5412SJohannes Schauer " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
605fc9c5412SJohannes Schauer " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
606fc9c5412SJohannes Schauer "Note that if you provide several changes to a single variable\n"
607f5048cb7SEric Blake "the last change will stay in effect.\n"
608f5048cb7SEric Blake "\n"
609f5048cb7SEric Blake QEMU_HELP_BOTTOM "\n");
610fc9c5412SJohannes Schauer
611d03f9c32SMeador Inge exit(exitcode);
612fc9c5412SJohannes Schauer }
613fc9c5412SJohannes Schauer
parse_args(int argc,char ** argv)614fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv)
615fc9c5412SJohannes Schauer {
616fc9c5412SJohannes Schauer const char *r;
617fc9c5412SJohannes Schauer int optind;
61842644ceeSJim Meyering const struct qemu_argument *arginfo;
619fc9c5412SJohannes Schauer
620fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
621fc9c5412SJohannes Schauer if (arginfo->env == NULL) {
622fc9c5412SJohannes Schauer continue;
623fc9c5412SJohannes Schauer }
624fc9c5412SJohannes Schauer
625fc9c5412SJohannes Schauer r = getenv(arginfo->env);
626fc9c5412SJohannes Schauer if (r != NULL) {
627fc9c5412SJohannes Schauer arginfo->handle_opt(r);
628fc9c5412SJohannes Schauer }
629fc9c5412SJohannes Schauer }
630fc9c5412SJohannes Schauer
631fc9c5412SJohannes Schauer optind = 1;
632fc9c5412SJohannes Schauer for (;;) {
633fc9c5412SJohannes Schauer if (optind >= argc) {
634fc9c5412SJohannes Schauer break;
635fc9c5412SJohannes Schauer }
636fc9c5412SJohannes Schauer r = argv[optind];
637fc9c5412SJohannes Schauer if (r[0] != '-') {
638fc9c5412SJohannes Schauer break;
639fc9c5412SJohannes Schauer }
640fc9c5412SJohannes Schauer optind++;
641fc9c5412SJohannes Schauer r++;
642fc9c5412SJohannes Schauer if (!strcmp(r, "-")) {
643fc9c5412SJohannes Schauer break;
644fc9c5412SJohannes Schauer }
645ba02577cSMeador Inge /* Treat --foo the same as -foo. */
646ba02577cSMeador Inge if (r[0] == '-') {
647ba02577cSMeador Inge r++;
648ba02577cSMeador Inge }
649fc9c5412SJohannes Schauer
650fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
651fc9c5412SJohannes Schauer if (!strcmp(r, arginfo->argv)) {
6521386d4c0SPeter Maydell if (arginfo->has_arg) {
653fc9c5412SJohannes Schauer if (optind >= argc) {
654138940bfSMeador Inge (void) fprintf(stderr,
655138940bfSMeador Inge "qemu: missing argument for option '%s'\n", r);
6564d1275c2SRiku Voipio exit(EXIT_FAILURE);
657fc9c5412SJohannes Schauer }
658fc9c5412SJohannes Schauer arginfo->handle_opt(argv[optind]);
659fc9c5412SJohannes Schauer optind++;
6601386d4c0SPeter Maydell } else {
6611386d4c0SPeter Maydell arginfo->handle_opt(NULL);
662fc9c5412SJohannes Schauer }
663fc9c5412SJohannes Schauer break;
664fc9c5412SJohannes Schauer }
665fc9c5412SJohannes Schauer }
666fc9c5412SJohannes Schauer
667fc9c5412SJohannes Schauer /* no option matched the current argv */
668fc9c5412SJohannes Schauer if (arginfo->handle_opt == NULL) {
669138940bfSMeador Inge (void) fprintf(stderr, "qemu: unknown option '%s'\n", r);
6704d1275c2SRiku Voipio exit(EXIT_FAILURE);
671fc9c5412SJohannes Schauer }
672fc9c5412SJohannes Schauer }
673fc9c5412SJohannes Schauer
674fc9c5412SJohannes Schauer if (optind >= argc) {
675138940bfSMeador Inge (void) fprintf(stderr, "qemu: no user program specified\n");
6764d1275c2SRiku Voipio exit(EXIT_FAILURE);
677fc9c5412SJohannes Schauer }
678fc9c5412SJohannes Schauer
679fc9c5412SJohannes Schauer exec_path = argv[optind];
680fc9c5412SJohannes Schauer
681fc9c5412SJohannes Schauer return optind;
682fc9c5412SJohannes Schauer }
683fc9c5412SJohannes Schauer
main(int argc,char ** argv,char ** envp)684902b3d5cSmalc int main(int argc, char **argv, char **envp)
68531e31b8aSbellard {
68601ffc75bSbellard struct target_pt_regs regs1, *regs = ®s1;
68731e31b8aSbellard struct image_info info1, *info = &info1;
688edf8e2afSMika Westerberg struct linux_binprm bprm;
68948e15fc2SNathan Froyd TaskState *ts;
6909349b4f9SAndreas Färber CPUArchState *env;
691db6b81d4SAndreas Färber CPUState *cpu;
692586314f2Sbellard int optind;
69304a6dfebSaurel32 char **target_environ, **wrk;
6947d8cec95Saurel32 char **target_argv;
6957d8cec95Saurel32 int target_argc;
6967d8cec95Saurel32 int i;
697fd4d81ddSArnaud Patard int ret;
69803cfd8faSLaurent Vivier int execfd;
699ff8a8bbcSRichard Henderson int host_page_size;
7008f67b9c6SRichard Henderson unsigned long max_reserved_va;
7016e1c0d7bSLaurent Vivier bool preserve_argv0;
70231e31b8aSbellard
703f5852efaSChristophe Fergeau error_init(argv[0]);
704fe4db84dSDaniel P. Berrange module_call_init(MODULE_INIT_TRACE);
705267f685bSPaolo Bonzini qemu_init_cpu_list();
706ce008c1fSAndreas Färber module_call_init(MODULE_INIT_QOM);
707ce008c1fSAndreas Färber
708ec45bbe5SSaurav Sachidanand envlist = envlist_create();
70904a6dfebSaurel32
7107f750efcSAndreas Schwab /*
7117f750efcSAndreas Schwab * add current environment into the list
7127f750efcSAndreas Schwab * envlist_setenv adds to the front of the list; to preserve environ
7137f750efcSAndreas Schwab * order add from back to front
7147f750efcSAndreas Schwab */
71504a6dfebSaurel32 for (wrk = environ; *wrk != NULL; wrk++) {
7167f750efcSAndreas Schwab continue;
7177f750efcSAndreas Schwab }
7187f750efcSAndreas Schwab while (wrk != environ) {
7197f750efcSAndreas Schwab wrk--;
72004a6dfebSaurel32 (void) envlist_setenv(envlist, *wrk);
72104a6dfebSaurel32 }
72204a6dfebSaurel32
723703e0e89SRichard Henderson /* Read the stack limit from the kernel. If it's "unlimited",
724703e0e89SRichard Henderson then we can do little else besides use the default. */
725703e0e89SRichard Henderson {
726703e0e89SRichard Henderson struct rlimit lim;
727703e0e89SRichard Henderson if (getrlimit(RLIMIT_STACK, &lim) == 0
72881bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur != RLIM_INFINITY
7290a3346b5SHelge Deller && lim.rlim_cur == (target_long)lim.rlim_cur
7300a3346b5SHelge Deller && lim.rlim_cur > guest_stack_size) {
731703e0e89SRichard Henderson guest_stack_size = lim.rlim_cur;
732703e0e89SRichard Henderson }
733703e0e89SRichard Henderson }
734703e0e89SRichard Henderson
735b1f9be31Sj_mayer cpu_model = NULL;
736b5ec5ce0Sjohn cooper
7376533dd6eSLluís Vilanova qemu_add_opts(&qemu_trace_opts);
738f308f64eSLluís Vilanova qemu_plugin_add_opts();
7396533dd6eSLluís Vilanova
740fc9c5412SJohannes Schauer optind = parse_args(argc, argv);
7414b5dfd82SPeter Maydell
742b410253fSRichard Henderson qemu_set_log_filename_flags(last_log_filename,
743b410253fSRichard Henderson last_log_mask | (enable_strace * LOG_STRACE),
744b410253fSRichard Henderson &error_fatal);
7454b25a506SJosh Kunz
7466533dd6eSLluís Vilanova if (!trace_init_backends()) {
7476533dd6eSLluís Vilanova exit(1);
7486533dd6eSLluís Vilanova }
74992eecfffSPaolo Bonzini trace_init_file();
7500572f558SPaolo Bonzini qemu_plugin_load_list(&plugins, &error_fatal);
7516533dd6eSLluís Vilanova
75231e31b8aSbellard /* Zero out regs */
75301ffc75bSbellard memset(regs, 0, sizeof(struct target_pt_regs));
75431e31b8aSbellard
75531e31b8aSbellard /* Zero out image_info */
75631e31b8aSbellard memset(info, 0, sizeof(struct image_info));
75731e31b8aSbellard
758edf8e2afSMika Westerberg memset(&bprm, 0, sizeof (bprm));
759edf8e2afSMika Westerberg
76074cd30b8Sbellard /* Scan interp_prefix dir for replacement files. */
76174cd30b8Sbellard init_paths(interp_prefix);
76274cd30b8Sbellard
7634a24a758SPeter Maydell init_qemu_uname_release();
7644a24a758SPeter Maydell
7656e1c0d7bSLaurent Vivier /*
7666e1c0d7bSLaurent Vivier * Manage binfmt-misc open-binary flag
7676e1c0d7bSLaurent Vivier */
76825268a18SVivian Wang errno = 0;
769768fe76eSYunQiang Su execfd = qemu_getauxval(AT_EXECFD);
77025268a18SVivian Wang if (errno != 0) {
7719d3019bcSLaurent Vivier execfd = open(exec_path, O_RDONLY);
772768fe76eSYunQiang Su if (execfd < 0) {
7739d3019bcSLaurent Vivier printf("Error while loading %s: %s\n", exec_path, strerror(errno));
774768fe76eSYunQiang Su _exit(EXIT_FAILURE);
775768fe76eSYunQiang Su }
776768fe76eSYunQiang Su }
777768fe76eSYunQiang Su
778258bec39SHelge Deller /* Resolve executable file name to full path name */
779258bec39SHelge Deller if (realpath(exec_path, real_exec_path)) {
780258bec39SHelge Deller exec_path = real_exec_path;
781258bec39SHelge Deller }
782258bec39SHelge Deller
7836e1c0d7bSLaurent Vivier /*
7846e1c0d7bSLaurent Vivier * get binfmt_misc flags
7856e1c0d7bSLaurent Vivier */
7866e1c0d7bSLaurent Vivier preserve_argv0 = !!(qemu_getauxval(AT_FLAGS) & AT_FLAGS_PRESERVE_ARGV0);
7876e1c0d7bSLaurent Vivier
7886e1c0d7bSLaurent Vivier /*
7896e1c0d7bSLaurent Vivier * Manage binfmt-misc preserve-arg[0] flag
7906e1c0d7bSLaurent Vivier * argv[optind] full path to the binary
7916e1c0d7bSLaurent Vivier * argv[optind + 1] original argv[0]
7926e1c0d7bSLaurent Vivier */
7936e1c0d7bSLaurent Vivier if (optind + 1 < argc && preserve_argv0) {
7946e1c0d7bSLaurent Vivier optind++;
7956e1c0d7bSLaurent Vivier }
7966e1c0d7bSLaurent Vivier
79746027c07Sbellard if (cpu_model == NULL) {
798768fe76eSYunQiang Su cpu_model = cpu_get_model(get_elf_eflags(execfd));
799aaed909aSbellard }
800c1c8cfe5SEduardo Habkost cpu_type = parse_cpu_option(cpu_model);
8012278b939SIgor Mammedov
80213c13397SRichard Henderson /* init tcg before creating CPUs */
803940e43aaSClaudio Fontana {
8043cfb0456SPeter Maydell AccelState *accel = current_accel();
8053cfb0456SPeter Maydell AccelClass *ac = ACCEL_GET_CLASS(accel);
8062278b939SIgor Mammedov
807b86f59c7SClaudio Fontana accel_init_interfaces(ac);
8083cfb0456SPeter Maydell object_property_set_bool(OBJECT(accel), "one-insn-per-tb",
8093cfb0456SPeter Maydell opt_one_insn_per_tb, &error_abort);
81092242f34SClaudio Fontana ac->init_machine(NULL);
811940e43aaSClaudio Fontana }
812ff8a8bbcSRichard Henderson
813ff8a8bbcSRichard Henderson /*
814ff8a8bbcSRichard Henderson * Finalize page size before creating CPUs.
815ff8a8bbcSRichard Henderson * This will do nothing if !TARGET_PAGE_BITS_VARY.
816ff8a8bbcSRichard Henderson * The most efficient setting is to match the host.
817ff8a8bbcSRichard Henderson */
818ff8a8bbcSRichard Henderson host_page_size = qemu_real_host_page_size();
819ff8a8bbcSRichard Henderson set_preferred_target_page_bits(ctz32(host_page_size));
820ff8a8bbcSRichard Henderson finalize_target_page_bits();
821ff8a8bbcSRichard Henderson
8222278b939SIgor Mammedov cpu = cpu_create(cpu_type);
823b77af26eSRichard Henderson env = cpu_env(cpu);
8240ac46af3SAndreas Färber cpu_reset(cpu);
825db6b81d4SAndreas Färber thread_cpu = cpu;
82654936004Sbellard
8278f67b9c6SRichard Henderson /*
8281b6f1b2eSWarner Losh * Reserving too much vm space via mmap can run into problems with rlimits,
8291b6f1b2eSWarner Losh * oom due to page table creation, etc. We will still try it, if directed
8301b6f1b2eSWarner Losh * by the command-line option, but not by default. Unless we're running a
8311b6f1b2eSWarner Losh * target address space of 32 or fewer bits on a host with 64 bits.
8328f67b9c6SRichard Henderson */
8338f67b9c6SRichard Henderson max_reserved_va = MAX_RESERVED_VA(cpu);
8348f67b9c6SRichard Henderson if (reserved_va != 0) {
83513c13397SRichard Henderson if ((reserved_va + 1) % host_page_size) {
83613c13397SRichard Henderson char *s = size_to_str(host_page_size);
8372f7828b5SRichard Henderson fprintf(stderr, "Reserved virtual address not aligned mod %s\n", s);
8382f7828b5SRichard Henderson g_free(s);
8392f7828b5SRichard Henderson exit(EXIT_FAILURE);
8402f7828b5SRichard Henderson }
8418f67b9c6SRichard Henderson if (max_reserved_va && reserved_va > max_reserved_va) {
8428f67b9c6SRichard Henderson fprintf(stderr, "Reserved virtual address too big\n");
8438f67b9c6SRichard Henderson exit(EXIT_FAILURE);
8448f67b9c6SRichard Henderson }
8458f67b9c6SRichard Henderson } else if (HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32) {
84695059f9cSRichard Henderson /* MAX_RESERVED_VA + 1 is a large power of 2, so is aligned. */
84795059f9cSRichard Henderson reserved_va = max_reserved_va;
8488f67b9c6SRichard Henderson }
8498f67b9c6SRichard Henderson
850c8fb5cf9SRichard Henderson /*
851c8fb5cf9SRichard Henderson * Temporarily disable
852c8fb5cf9SRichard Henderson * "comparison is always false due to limited range of data type"
853c8fb5cf9SRichard Henderson * due to comparison between (possible) uint64_t and uintptr_t.
854c8fb5cf9SRichard Henderson */
855c8fb5cf9SRichard Henderson #pragma GCC diagnostic push
856c8fb5cf9SRichard Henderson #pragma GCC diagnostic ignored "-Wtype-limits"
857f324a03eSRichard Henderson #pragma GCC diagnostic ignored "-Wtautological-compare"
858c8fb5cf9SRichard Henderson
859c8fb5cf9SRichard Henderson /*
860c8fb5cf9SRichard Henderson * Select an initial value for task_unmapped_base that is in range.
861c8fb5cf9SRichard Henderson */
862c8fb5cf9SRichard Henderson if (reserved_va) {
863c8fb5cf9SRichard Henderson if (TASK_UNMAPPED_BASE < reserved_va) {
864c8fb5cf9SRichard Henderson task_unmapped_base = TASK_UNMAPPED_BASE;
865c8fb5cf9SRichard Henderson } else {
866c8fb5cf9SRichard Henderson /* The most common default formula is TASK_SIZE / 3. */
867c8fb5cf9SRichard Henderson task_unmapped_base = TARGET_PAGE_ALIGN(reserved_va / 3);
868c8fb5cf9SRichard Henderson }
869c8fb5cf9SRichard Henderson } else if (TASK_UNMAPPED_BASE < UINTPTR_MAX) {
870c8fb5cf9SRichard Henderson task_unmapped_base = TASK_UNMAPPED_BASE;
871c8fb5cf9SRichard Henderson } else {
872c8fb5cf9SRichard Henderson /* 32-bit host: pick something medium size. */
873c8fb5cf9SRichard Henderson task_unmapped_base = 0x10000000;
874c8fb5cf9SRichard Henderson }
875c8fb5cf9SRichard Henderson mmap_next_start = task_unmapped_base;
876c8fb5cf9SRichard Henderson
877da2b71faSRichard Henderson /* Similarly for elf_et_dyn_base. */
878da2b71faSRichard Henderson if (reserved_va) {
879da2b71faSRichard Henderson if (ELF_ET_DYN_BASE < reserved_va) {
880da2b71faSRichard Henderson elf_et_dyn_base = ELF_ET_DYN_BASE;
881da2b71faSRichard Henderson } else {
882da2b71faSRichard Henderson /* The most common default formula is TASK_SIZE / 3 * 2. */
883da2b71faSRichard Henderson elf_et_dyn_base = TARGET_PAGE_ALIGN(reserved_va / 3) * 2;
884da2b71faSRichard Henderson }
885da2b71faSRichard Henderson } else if (ELF_ET_DYN_BASE < UINTPTR_MAX) {
886da2b71faSRichard Henderson elf_et_dyn_base = ELF_ET_DYN_BASE;
887da2b71faSRichard Henderson } else {
888da2b71faSRichard Henderson /* 32-bit host: pick something medium size. */
889da2b71faSRichard Henderson elf_et_dyn_base = 0x18000000;
890da2b71faSRichard Henderson }
891da2b71faSRichard Henderson
892c8fb5cf9SRichard Henderson #pragma GCC diagnostic pop
893c8fb5cf9SRichard Henderson
894a573e9baSRichard Henderson {
895a573e9baSRichard Henderson Error *err = NULL;
8965ebdd774SRichard Henderson if (seed_optarg != NULL) {
897a573e9baSRichard Henderson qemu_guest_random_seed_main(seed_optarg, &err);
898a573e9baSRichard Henderson } else {
899a573e9baSRichard Henderson qcrypto_init(&err);
900a573e9baSRichard Henderson }
901a573e9baSRichard Henderson if (err) {
902a573e9baSRichard Henderson error_reportf_err(err, "cannot initialize crypto: ");
903a573e9baSRichard Henderson exit(1);
904a573e9baSRichard Henderson }
905c5e4a5a9SMagnus Reftel }
906c5e4a5a9SMagnus Reftel
90704a6dfebSaurel32 target_environ = envlist_to_environ(envlist, NULL);
90804a6dfebSaurel32 envlist_free(envlist);
909b12b6a18Sths
910379f6698SPaul Brook /*
911379f6698SPaul Brook * Read in mmap_min_addr kernel parameter. This value is used
912379f6698SPaul Brook * When loading the ELF image to determine whether guest_base
91314f24e14SRichard Henderson * is needed. It is also used in mmap_find_vma.
914379f6698SPaul Brook */
91514f24e14SRichard Henderson {
916379f6698SPaul Brook FILE *fp;
917379f6698SPaul Brook
918379f6698SPaul Brook if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
919379f6698SPaul Brook unsigned long tmp;
920c9f80666SRichard Henderson if (fscanf(fp, "%lu", &tmp) == 1 && tmp != 0) {
92178b79b2cSRichard Henderson mmap_min_addr = MAX(tmp, host_page_size);
922c9f80666SRichard Henderson qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
923c9f80666SRichard Henderson mmap_min_addr);
924379f6698SPaul Brook }
925379f6698SPaul Brook fclose(fp);
926379f6698SPaul Brook }
927379f6698SPaul Brook }
928379f6698SPaul Brook
9297d8cec95Saurel32 /*
930c9f80666SRichard Henderson * We prefer to not make NULL pointers accessible to QEMU.
931c9f80666SRichard Henderson * If we're in a chroot with no /proc, fall back to 1 page.
932c9f80666SRichard Henderson */
933c9f80666SRichard Henderson if (mmap_min_addr == 0) {
934ff8a8bbcSRichard Henderson mmap_min_addr = host_page_size;
935c9f80666SRichard Henderson qemu_log_mask(CPU_LOG_PAGE,
936c9f80666SRichard Henderson "host mmap_min_addr=0x%lx (fallback)\n",
937c9f80666SRichard Henderson mmap_min_addr);
938c9f80666SRichard Henderson }
939c9f80666SRichard Henderson
940c9f80666SRichard Henderson /*
9417d8cec95Saurel32 * Prepare copy of argv vector for target.
9427d8cec95Saurel32 */
9437d8cec95Saurel32 target_argc = argc - optind;
9442ee80bceSNguyen Dinh Phi target_argv = g_new0(char *, target_argc + 1);
9457d8cec95Saurel32
9467d8cec95Saurel32 /*
9477d8cec95Saurel32 * If argv0 is specified (using '-0' switch) we replace
9487d8cec95Saurel32 * argv[0] pointer with the given one.
9497d8cec95Saurel32 */
9507d8cec95Saurel32 i = 0;
9517d8cec95Saurel32 if (argv0 != NULL) {
9527d8cec95Saurel32 target_argv[i++] = strdup(argv0);
9537d8cec95Saurel32 }
9547d8cec95Saurel32 for (; i < target_argc; i++) {
9557d8cec95Saurel32 target_argv[i] = strdup(argv[optind + i]);
9567d8cec95Saurel32 }
9577d8cec95Saurel32 target_argv[target_argc] = NULL;
9587d8cec95Saurel32
959c78d65e8SMarkus Armbruster ts = g_new0(TaskState, 1);
960edf8e2afSMika Westerberg init_task_state(ts);
961edf8e2afSMika Westerberg /* build Task State */
962edf8e2afSMika Westerberg ts->info = info;
963edf8e2afSMika Westerberg ts->bprm = &bprm;
9640429a971SAndreas Färber cpu->opaque = ts;
965edf8e2afSMika Westerberg task_settid(ts);
966edf8e2afSMika Westerberg
967c093364fSOwen Anderson fd_trans_init();
968c093364fSOwen Anderson
9699d3019bcSLaurent Vivier ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs,
970fd4d81ddSArnaud Patard info, &bprm);
971fd4d81ddSArnaud Patard if (ret != 0) {
9729d3019bcSLaurent Vivier printf("Error while loading %s: %s\n", exec_path, strerror(-ret));
9734d1275c2SRiku Voipio _exit(EXIT_FAILURE);
97431e31b8aSbellard }
97531e31b8aSbellard
976b12b6a18Sths for (wrk = target_environ; *wrk; wrk++) {
977ec45bbe5SSaurav Sachidanand g_free(*wrk);
978b12b6a18Sths }
979b12b6a18Sths
980ec45bbe5SSaurav Sachidanand g_free(target_environ);
981b12b6a18Sths
98213829020SPaolo Bonzini if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
98393756fdcSRichard Henderson FILE *f = qemu_log_trylock();
98493756fdcSRichard Henderson if (f) {
98593756fdcSRichard Henderson fprintf(f, "guest_base %p\n", (void *)guest_base);
98693756fdcSRichard Henderson fprintf(f, "page layout changed following binary load\n");
98793756fdcSRichard Henderson page_dump(f);
98854936004Sbellard
98993756fdcSRichard Henderson fprintf(f, "end_code 0x" TARGET_ABI_FMT_lx "\n",
99093756fdcSRichard Henderson info->end_code);
99193756fdcSRichard Henderson fprintf(f, "start_code 0x" TARGET_ABI_FMT_lx "\n",
99293756fdcSRichard Henderson info->start_code);
99393756fdcSRichard Henderson fprintf(f, "start_data 0x" TARGET_ABI_FMT_lx "\n",
99493756fdcSRichard Henderson info->start_data);
99593756fdcSRichard Henderson fprintf(f, "end_data 0x" TARGET_ABI_FMT_lx "\n",
99693756fdcSRichard Henderson info->end_data);
99793756fdcSRichard Henderson fprintf(f, "start_stack 0x" TARGET_ABI_FMT_lx "\n",
99893756fdcSRichard Henderson info->start_stack);
99993756fdcSRichard Henderson fprintf(f, "brk 0x" TARGET_ABI_FMT_lx "\n",
100093756fdcSRichard Henderson info->brk);
100193756fdcSRichard Henderson fprintf(f, "entry 0x" TARGET_ABI_FMT_lx "\n",
100293756fdcSRichard Henderson info->entry);
100393756fdcSRichard Henderson fprintf(f, "argv_start 0x" TARGET_ABI_FMT_lx "\n",
100460f1c801SRichard Henderson info->argv);
100593756fdcSRichard Henderson fprintf(f, "env_start 0x" TARGET_ABI_FMT_lx "\n",
100660f1c801SRichard Henderson info->envp);
100793756fdcSRichard Henderson fprintf(f, "auxv_start 0x" TARGET_ABI_FMT_lx "\n",
100893756fdcSRichard Henderson info->saved_auxv);
100993756fdcSRichard Henderson qemu_log_unlock(f);
101093756fdcSRichard Henderson }
10112e77eac6Sblueswir1 }
101231e31b8aSbellard
101353a5960aSpbrook target_set_brk(info->brk);
101431e31b8aSbellard syscall_init();
1015*c107521eSIlya Leoshkevich signal_init(rtsig_map);
101631e31b8aSbellard
10179002ec79SRichard Henderson /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
10189002ec79SRichard Henderson generating the prologue until now so that the prologue can take
10199002ec79SRichard Henderson the real value of GUEST_BASE into account. */
1020935f75aeSRichard Henderson tcg_prologue_init();
10219002ec79SRichard Henderson
1022cd71c089SLaurent Vivier target_cpu_copy_regs(env, regs);
1023cd71c089SLaurent Vivier
1024fcedd920SAlex Bennée if (gdbstub) {
1025fcedd920SAlex Bennée if (gdbserver_start(gdbstub) < 0) {
1026fcedd920SAlex Bennée fprintf(stderr, "qemu: could not open gdbserver on %s\n",
1027fcedd920SAlex Bennée gdbstub);
10284d1275c2SRiku Voipio exit(EXIT_FAILURE);
1029ff7a981aSPeter Maydell }
1030f84e313eSGustavo Romero gdb_handlesig(cpu, 0, NULL, NULL, 0);
10311fddef4bSbellard }
1032e4a4aaa5SRichard Henderson
1033e4a4aaa5SRichard Henderson #ifdef CONFIG_SEMIHOSTING
1034e4a4aaa5SRichard Henderson qemu_semihosting_guestfd_init();
1035e4a4aaa5SRichard Henderson #endif
1036e4a4aaa5SRichard Henderson
10371b6b029eSbellard cpu_loop(env);
10381b6b029eSbellard /* never exits */
103931e31b8aSbellard return 0;
104031e31b8aSbellard }
1041