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
handle_arg_one_insn_per_tb(const char * arg)415e99c1f89SPeter Maydell static void handle_arg_one_insn_per_tb(const char *arg)
416fc9c5412SJohannes Schauer {
4173cfb0456SPeter Maydell opt_one_insn_per_tb = true;
418fc9c5412SJohannes Schauer }
419fc9c5412SJohannes Schauer
handle_arg_strace(const char * arg)420fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg)
421fc9c5412SJohannes Schauer {
4224b25a506SJosh Kunz enable_strace = true;
423fc9c5412SJohannes Schauer }
424fc9c5412SJohannes Schauer
handle_arg_version(const char * arg)425fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg)
426fc9c5412SJohannes Schauer {
4277e563bfbSThomas Huth printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
4280781dd6eSThomas Huth "\n" QEMU_COPYRIGHT "\n");
4294d1275c2SRiku Voipio exit(EXIT_SUCCESS);
430fc9c5412SJohannes Schauer }
431fc9c5412SJohannes Schauer
handle_arg_trace(const char * arg)4326533dd6eSLluís Vilanova static void handle_arg_trace(const char *arg)
4336533dd6eSLluís Vilanova {
43492eecfffSPaolo Bonzini trace_opt_parse(arg);
4356533dd6eSLluís Vilanova }
4366533dd6eSLluís Vilanova
437130ea832SMax Filippov #if defined(TARGET_XTENSA)
handle_arg_abi_call0(const char * arg)438130ea832SMax Filippov static void handle_arg_abi_call0(const char *arg)
439130ea832SMax Filippov {
440130ea832SMax Filippov xtensa_set_abi_call0();
441130ea832SMax Filippov }
442130ea832SMax Filippov #endif
443130ea832SMax Filippov
handle_arg_perfmap(const char * arg)4445584e2dbSIlya Leoshkevich static void handle_arg_perfmap(const char *arg)
4455584e2dbSIlya Leoshkevich {
4465584e2dbSIlya Leoshkevich perf_enable_perfmap();
4475584e2dbSIlya Leoshkevich }
4485584e2dbSIlya Leoshkevich
handle_arg_jitdump(const char * arg)4495584e2dbSIlya Leoshkevich static void handle_arg_jitdump(const char *arg)
4505584e2dbSIlya Leoshkevich {
4515584e2dbSIlya Leoshkevich perf_enable_jitdump();
4525584e2dbSIlya Leoshkevich }
4535584e2dbSIlya Leoshkevich
454f308f64eSLluís Vilanova static QemuPluginList plugins = QTAILQ_HEAD_INITIALIZER(plugins);
455f308f64eSLluís Vilanova
456f308f64eSLluís Vilanova #ifdef CONFIG_PLUGIN
handle_arg_plugin(const char * arg)457f308f64eSLluís Vilanova static void handle_arg_plugin(const char *arg)
458f308f64eSLluís Vilanova {
459f308f64eSLluís Vilanova qemu_plugin_opt_parse(arg, &plugins);
460f308f64eSLluís Vilanova }
461f308f64eSLluís Vilanova #endif
462f308f64eSLluís Vilanova
463fc9c5412SJohannes Schauer struct qemu_argument {
464fc9c5412SJohannes Schauer const char *argv;
465fc9c5412SJohannes Schauer const char *env;
466fc9c5412SJohannes Schauer bool has_arg;
467fc9c5412SJohannes Schauer void (*handle_opt)(const char *arg);
468fc9c5412SJohannes Schauer const char *example;
469fc9c5412SJohannes Schauer const char *help;
470fc9c5412SJohannes Schauer };
471fc9c5412SJohannes Schauer
47242644ceeSJim Meyering static const struct qemu_argument arg_table[] = {
473fc9c5412SJohannes Schauer {"h", "", false, handle_arg_help,
474fc9c5412SJohannes Schauer "", "print this help"},
475daaf8c8eSMeador Inge {"help", "", false, handle_arg_help,
476daaf8c8eSMeador Inge "", ""},
477fc9c5412SJohannes Schauer {"g", "QEMU_GDB", true, handle_arg_gdb,
478fc9c5412SJohannes Schauer "port", "wait gdb connection to 'port'"},
479fc9c5412SJohannes Schauer {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix,
480fc9c5412SJohannes Schauer "path", "set the elf interpreter prefix to 'path'"},
481fc9c5412SJohannes Schauer {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size,
482fc9c5412SJohannes Schauer "size", "set the stack size to 'size' bytes"},
483fc9c5412SJohannes Schauer {"cpu", "QEMU_CPU", true, handle_arg_cpu,
484c8057f95SPeter Maydell "model", "select CPU (-cpu help for list)"},
485fc9c5412SJohannes Schauer {"E", "QEMU_SET_ENV", true, handle_arg_set_env,
486fc9c5412SJohannes Schauer "var=value", "sets targets environment variable (see below)"},
487fc9c5412SJohannes Schauer {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env,
488fc9c5412SJohannes Schauer "var", "unsets targets environment variable (see below)"},
489fc9c5412SJohannes Schauer {"0", "QEMU_ARGV0", true, handle_arg_argv0,
490fc9c5412SJohannes Schauer "argv0", "forces target process argv[0] to be 'argv0'"},
491fc9c5412SJohannes Schauer {"r", "QEMU_UNAME", true, handle_arg_uname,
492fc9c5412SJohannes Schauer "uname", "set qemu uname release string to 'uname'"},
493fc9c5412SJohannes Schauer {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base,
494fc9c5412SJohannes Schauer "address", "set guest_base address to 'address'"},
495fc9c5412SJohannes Schauer {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va,
496fc9c5412SJohannes Schauer "size", "reserve 'size' bytes for guest virtual address space"},
497fc9c5412SJohannes Schauer {"d", "QEMU_LOG", true, handle_arg_log,
498989b697dSPeter Maydell "item[,...]", "enable logging of specified items "
499989b697dSPeter Maydell "(use '-d help' for a list of items)"},
5008423fa90SAlex Bennée {"dfilter", "QEMU_DFILTER", true, handle_arg_dfilter,
5018423fa90SAlex Bennée "range[,...]","filter logging based on address range"},
50250171d42S陳韋任 {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
503989b697dSPeter Maydell "logfile", "write logs to 'logfile' (default stderr)"},
504fc9c5412SJohannes Schauer {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,
50501e44980SRichard Henderson "pagesize", "deprecated change to host page size"},
506e99c1f89SPeter Maydell {"one-insn-per-tb",
507e99c1f89SPeter Maydell "QEMU_ONE_INSN_PER_TB", false, handle_arg_one_insn_per_tb,
508e99c1f89SPeter Maydell "", "run with one guest instruction per emulated TB"},
509fc9c5412SJohannes Schauer {"strace", "QEMU_STRACE", false, handle_arg_strace,
510fc9c5412SJohannes Schauer "", "log system calls"},
5115ebdd774SRichard Henderson {"seed", "QEMU_RAND_SEED", true, handle_arg_seed,
512c5e4a5a9SMagnus Reftel "", "Seed for pseudo-random number generator"},
5136533dd6eSLluís Vilanova {"trace", "QEMU_TRACE", true, handle_arg_trace,
5146533dd6eSLluís Vilanova "", "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
515f308f64eSLluís Vilanova #ifdef CONFIG_PLUGIN
516f308f64eSLluís Vilanova {"plugin", "QEMU_PLUGIN", true, handle_arg_plugin,
5173a445acbSMahmoud Mandour "", "[file=]<file>[,<argname>=<argvalue>]"},
518f308f64eSLluís Vilanova #endif
519fc9c5412SJohannes Schauer {"version", "QEMU_VERSION", false, handle_arg_version,
5201386d4c0SPeter Maydell "", "display version information and exit"},
521130ea832SMax Filippov #if defined(TARGET_XTENSA)
522130ea832SMax Filippov {"xtensa-abi-call0", "QEMU_XTENSA_ABI_CALL0", false, handle_arg_abi_call0,
523130ea832SMax Filippov "", "assume CALL0 Xtensa ABI"},
524130ea832SMax Filippov #endif
5255584e2dbSIlya Leoshkevich {"perfmap", "QEMU_PERFMAP", false, handle_arg_perfmap,
5265584e2dbSIlya Leoshkevich "", "Generate a /tmp/perf-${pid}.map file for perf"},
5275584e2dbSIlya Leoshkevich {"jitdump", "QEMU_JITDUMP", false, handle_arg_jitdump,
5285584e2dbSIlya Leoshkevich "", "Generate a jit-${pid}.dump file for perf"},
529fc9c5412SJohannes Schauer {NULL, NULL, false, NULL, NULL, NULL}
530fc9c5412SJohannes Schauer };
531fc9c5412SJohannes Schauer
usage(int exitcode)532d03f9c32SMeador Inge static void usage(int exitcode)
533fc9c5412SJohannes Schauer {
53442644ceeSJim Meyering const struct qemu_argument *arginfo;
535fc9c5412SJohannes Schauer int maxarglen;
536fc9c5412SJohannes Schauer int maxenvlen;
537fc9c5412SJohannes Schauer
5382e59915dSPaolo Bonzini printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
5392e59915dSPaolo Bonzini "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n"
540fc9c5412SJohannes Schauer "\n"
541fc9c5412SJohannes Schauer "Options and associated environment variables:\n"
542fc9c5412SJohannes Schauer "\n");
543fc9c5412SJohannes Schauer
54463ec54d7SPeter Maydell /* Calculate column widths. We must always have at least enough space
54563ec54d7SPeter Maydell * for the column header.
54663ec54d7SPeter Maydell */
54763ec54d7SPeter Maydell maxarglen = strlen("Argument");
54863ec54d7SPeter Maydell maxenvlen = strlen("Env-variable");
549fc9c5412SJohannes Schauer
550fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
55163ec54d7SPeter Maydell int arglen = strlen(arginfo->argv);
55263ec54d7SPeter Maydell if (arginfo->has_arg) {
55363ec54d7SPeter Maydell arglen += strlen(arginfo->example) + 1;
55463ec54d7SPeter Maydell }
555fc9c5412SJohannes Schauer if (strlen(arginfo->env) > maxenvlen) {
556fc9c5412SJohannes Schauer maxenvlen = strlen(arginfo->env);
557fc9c5412SJohannes Schauer }
55863ec54d7SPeter Maydell if (arglen > maxarglen) {
55963ec54d7SPeter Maydell maxarglen = arglen;
560fc9c5412SJohannes Schauer }
561fc9c5412SJohannes Schauer }
562fc9c5412SJohannes Schauer
56363ec54d7SPeter Maydell printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
56463ec54d7SPeter Maydell maxenvlen, "Env-variable");
565fc9c5412SJohannes Schauer
566fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
567fc9c5412SJohannes Schauer if (arginfo->has_arg) {
568fc9c5412SJohannes Schauer printf("-%s %-*s %-*s %s\n", arginfo->argv,
56963ec54d7SPeter Maydell (int)(maxarglen - strlen(arginfo->argv) - 1),
57063ec54d7SPeter Maydell arginfo->example, maxenvlen, arginfo->env, arginfo->help);
571fc9c5412SJohannes Schauer } else {
57263ec54d7SPeter Maydell printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
573fc9c5412SJohannes Schauer maxenvlen, arginfo->env,
574fc9c5412SJohannes Schauer arginfo->help);
575fc9c5412SJohannes Schauer }
576fc9c5412SJohannes Schauer }
577fc9c5412SJohannes Schauer
578fc9c5412SJohannes Schauer printf("\n"
579fc9c5412SJohannes Schauer "Defaults:\n"
580fc9c5412SJohannes Schauer "QEMU_LD_PREFIX = %s\n"
581989b697dSPeter Maydell "QEMU_STACK_SIZE = %ld byte\n",
582fc9c5412SJohannes Schauer interp_prefix,
583989b697dSPeter Maydell guest_stack_size);
584fc9c5412SJohannes Schauer
585fc9c5412SJohannes Schauer printf("\n"
586fc9c5412SJohannes Schauer "You can use -E and -U options or the QEMU_SET_ENV and\n"
587fc9c5412SJohannes Schauer "QEMU_UNSET_ENV environment variables to set and unset\n"
588fc9c5412SJohannes Schauer "environment variables for the target process.\n"
589fc9c5412SJohannes Schauer "It is possible to provide several variables by separating them\n"
590fc9c5412SJohannes Schauer "by commas in getsubopt(3) style. Additionally it is possible to\n"
591fc9c5412SJohannes Schauer "provide the -E and -U options multiple times.\n"
592fc9c5412SJohannes Schauer "The following lines are equivalent:\n"
593fc9c5412SJohannes Schauer " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
594fc9c5412SJohannes Schauer " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
595fc9c5412SJohannes Schauer " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
596fc9c5412SJohannes Schauer "Note that if you provide several changes to a single variable\n"
597f5048cb7SEric Blake "the last change will stay in effect.\n"
598f5048cb7SEric Blake "\n"
599f5048cb7SEric Blake QEMU_HELP_BOTTOM "\n");
600fc9c5412SJohannes Schauer
601d03f9c32SMeador Inge exit(exitcode);
602fc9c5412SJohannes Schauer }
603fc9c5412SJohannes Schauer
parse_args(int argc,char ** argv)604fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv)
605fc9c5412SJohannes Schauer {
606fc9c5412SJohannes Schauer const char *r;
607fc9c5412SJohannes Schauer int optind;
60842644ceeSJim Meyering const struct qemu_argument *arginfo;
609fc9c5412SJohannes Schauer
610fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
611fc9c5412SJohannes Schauer if (arginfo->env == NULL) {
612fc9c5412SJohannes Schauer continue;
613fc9c5412SJohannes Schauer }
614fc9c5412SJohannes Schauer
615fc9c5412SJohannes Schauer r = getenv(arginfo->env);
616fc9c5412SJohannes Schauer if (r != NULL) {
617fc9c5412SJohannes Schauer arginfo->handle_opt(r);
618fc9c5412SJohannes Schauer }
619fc9c5412SJohannes Schauer }
620fc9c5412SJohannes Schauer
621fc9c5412SJohannes Schauer optind = 1;
622fc9c5412SJohannes Schauer for (;;) {
623fc9c5412SJohannes Schauer if (optind >= argc) {
624fc9c5412SJohannes Schauer break;
625fc9c5412SJohannes Schauer }
626fc9c5412SJohannes Schauer r = argv[optind];
627fc9c5412SJohannes Schauer if (r[0] != '-') {
628fc9c5412SJohannes Schauer break;
629fc9c5412SJohannes Schauer }
630fc9c5412SJohannes Schauer optind++;
631fc9c5412SJohannes Schauer r++;
632fc9c5412SJohannes Schauer if (!strcmp(r, "-")) {
633fc9c5412SJohannes Schauer break;
634fc9c5412SJohannes Schauer }
635ba02577cSMeador Inge /* Treat --foo the same as -foo. */
636ba02577cSMeador Inge if (r[0] == '-') {
637ba02577cSMeador Inge r++;
638ba02577cSMeador Inge }
639fc9c5412SJohannes Schauer
640fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
641fc9c5412SJohannes Schauer if (!strcmp(r, arginfo->argv)) {
6421386d4c0SPeter Maydell if (arginfo->has_arg) {
643fc9c5412SJohannes Schauer if (optind >= argc) {
644138940bfSMeador Inge (void) fprintf(stderr,
645138940bfSMeador Inge "qemu: missing argument for option '%s'\n", r);
6464d1275c2SRiku Voipio exit(EXIT_FAILURE);
647fc9c5412SJohannes Schauer }
648fc9c5412SJohannes Schauer arginfo->handle_opt(argv[optind]);
649fc9c5412SJohannes Schauer optind++;
6501386d4c0SPeter Maydell } else {
6511386d4c0SPeter Maydell arginfo->handle_opt(NULL);
652fc9c5412SJohannes Schauer }
653fc9c5412SJohannes Schauer break;
654fc9c5412SJohannes Schauer }
655fc9c5412SJohannes Schauer }
656fc9c5412SJohannes Schauer
657fc9c5412SJohannes Schauer /* no option matched the current argv */
658fc9c5412SJohannes Schauer if (arginfo->handle_opt == NULL) {
659138940bfSMeador Inge (void) fprintf(stderr, "qemu: unknown option '%s'\n", r);
6604d1275c2SRiku Voipio exit(EXIT_FAILURE);
661fc9c5412SJohannes Schauer }
662fc9c5412SJohannes Schauer }
663fc9c5412SJohannes Schauer
664fc9c5412SJohannes Schauer if (optind >= argc) {
665138940bfSMeador Inge (void) fprintf(stderr, "qemu: no user program specified\n");
6664d1275c2SRiku Voipio exit(EXIT_FAILURE);
667fc9c5412SJohannes Schauer }
668fc9c5412SJohannes Schauer
669fc9c5412SJohannes Schauer exec_path = argv[optind];
670fc9c5412SJohannes Schauer
671fc9c5412SJohannes Schauer return optind;
672fc9c5412SJohannes Schauer }
673fc9c5412SJohannes Schauer
main(int argc,char ** argv,char ** envp)674902b3d5cSmalc int main(int argc, char **argv, char **envp)
67531e31b8aSbellard {
67601ffc75bSbellard struct target_pt_regs regs1, *regs = ®s1;
67731e31b8aSbellard struct image_info info1, *info = &info1;
678edf8e2afSMika Westerberg struct linux_binprm bprm;
67948e15fc2SNathan Froyd TaskState *ts;
6809349b4f9SAndreas Färber CPUArchState *env;
681db6b81d4SAndreas Färber CPUState *cpu;
682586314f2Sbellard int optind;
68304a6dfebSaurel32 char **target_environ, **wrk;
6847d8cec95Saurel32 char **target_argv;
6857d8cec95Saurel32 int target_argc;
6867d8cec95Saurel32 int i;
687fd4d81ddSArnaud Patard int ret;
68803cfd8faSLaurent Vivier int execfd;
689ff8a8bbcSRichard Henderson int host_page_size;
6908f67b9c6SRichard Henderson unsigned long max_reserved_va;
6916e1c0d7bSLaurent Vivier bool preserve_argv0;
69231e31b8aSbellard
693f5852efaSChristophe Fergeau error_init(argv[0]);
694fe4db84dSDaniel P. Berrange module_call_init(MODULE_INIT_TRACE);
695267f685bSPaolo Bonzini qemu_init_cpu_list();
696ce008c1fSAndreas Färber module_call_init(MODULE_INIT_QOM);
697ce008c1fSAndreas Färber
698ec45bbe5SSaurav Sachidanand envlist = envlist_create();
69904a6dfebSaurel32
7007f750efcSAndreas Schwab /*
7017f750efcSAndreas Schwab * add current environment into the list
7027f750efcSAndreas Schwab * envlist_setenv adds to the front of the list; to preserve environ
7037f750efcSAndreas Schwab * order add from back to front
7047f750efcSAndreas Schwab */
70504a6dfebSaurel32 for (wrk = environ; *wrk != NULL; wrk++) {
7067f750efcSAndreas Schwab continue;
7077f750efcSAndreas Schwab }
7087f750efcSAndreas Schwab while (wrk != environ) {
7097f750efcSAndreas Schwab wrk--;
71004a6dfebSaurel32 (void) envlist_setenv(envlist, *wrk);
71104a6dfebSaurel32 }
71204a6dfebSaurel32
713703e0e89SRichard Henderson /* Read the stack limit from the kernel. If it's "unlimited",
714703e0e89SRichard Henderson then we can do little else besides use the default. */
715703e0e89SRichard Henderson {
716703e0e89SRichard Henderson struct rlimit lim;
717703e0e89SRichard Henderson if (getrlimit(RLIMIT_STACK, &lim) == 0
71881bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur != RLIM_INFINITY
7190a3346b5SHelge Deller && lim.rlim_cur == (target_long)lim.rlim_cur
7200a3346b5SHelge Deller && lim.rlim_cur > guest_stack_size) {
721703e0e89SRichard Henderson guest_stack_size = lim.rlim_cur;
722703e0e89SRichard Henderson }
723703e0e89SRichard Henderson }
724703e0e89SRichard Henderson
725b1f9be31Sj_mayer cpu_model = NULL;
726b5ec5ce0Sjohn cooper
7276533dd6eSLluís Vilanova qemu_add_opts(&qemu_trace_opts);
728f308f64eSLluís Vilanova qemu_plugin_add_opts();
7296533dd6eSLluís Vilanova
730fc9c5412SJohannes Schauer optind = parse_args(argc, argv);
7314b5dfd82SPeter Maydell
732b410253fSRichard Henderson qemu_set_log_filename_flags(last_log_filename,
733b410253fSRichard Henderson last_log_mask | (enable_strace * LOG_STRACE),
734b410253fSRichard Henderson &error_fatal);
7354b25a506SJosh Kunz
7366533dd6eSLluís Vilanova if (!trace_init_backends()) {
7376533dd6eSLluís Vilanova exit(1);
7386533dd6eSLluís Vilanova }
73992eecfffSPaolo Bonzini trace_init_file();
7400572f558SPaolo Bonzini qemu_plugin_load_list(&plugins, &error_fatal);
7416533dd6eSLluís Vilanova
74231e31b8aSbellard /* Zero out regs */
74301ffc75bSbellard memset(regs, 0, sizeof(struct target_pt_regs));
74431e31b8aSbellard
74531e31b8aSbellard /* Zero out image_info */
74631e31b8aSbellard memset(info, 0, sizeof(struct image_info));
74731e31b8aSbellard
748edf8e2afSMika Westerberg memset(&bprm, 0, sizeof (bprm));
749edf8e2afSMika Westerberg
75074cd30b8Sbellard /* Scan interp_prefix dir for replacement files. */
75174cd30b8Sbellard init_paths(interp_prefix);
75274cd30b8Sbellard
7534a24a758SPeter Maydell init_qemu_uname_release();
7544a24a758SPeter Maydell
7556e1c0d7bSLaurent Vivier /*
7566e1c0d7bSLaurent Vivier * Manage binfmt-misc open-binary flag
7576e1c0d7bSLaurent Vivier */
758768fe76eSYunQiang Su execfd = qemu_getauxval(AT_EXECFD);
759768fe76eSYunQiang Su if (execfd == 0) {
7609d3019bcSLaurent Vivier execfd = open(exec_path, O_RDONLY);
761768fe76eSYunQiang Su if (execfd < 0) {
7629d3019bcSLaurent Vivier printf("Error while loading %s: %s\n", exec_path, strerror(errno));
763768fe76eSYunQiang Su _exit(EXIT_FAILURE);
764768fe76eSYunQiang Su }
765768fe76eSYunQiang Su }
766768fe76eSYunQiang Su
767258bec39SHelge Deller /* Resolve executable file name to full path name */
768258bec39SHelge Deller if (realpath(exec_path, real_exec_path)) {
769258bec39SHelge Deller exec_path = real_exec_path;
770258bec39SHelge Deller }
771258bec39SHelge Deller
7726e1c0d7bSLaurent Vivier /*
7736e1c0d7bSLaurent Vivier * get binfmt_misc flags
7746e1c0d7bSLaurent Vivier */
7756e1c0d7bSLaurent Vivier preserve_argv0 = !!(qemu_getauxval(AT_FLAGS) & AT_FLAGS_PRESERVE_ARGV0);
7766e1c0d7bSLaurent Vivier
7776e1c0d7bSLaurent Vivier /*
7786e1c0d7bSLaurent Vivier * Manage binfmt-misc preserve-arg[0] flag
7796e1c0d7bSLaurent Vivier * argv[optind] full path to the binary
7806e1c0d7bSLaurent Vivier * argv[optind + 1] original argv[0]
7816e1c0d7bSLaurent Vivier */
7826e1c0d7bSLaurent Vivier if (optind + 1 < argc && preserve_argv0) {
7836e1c0d7bSLaurent Vivier optind++;
7846e1c0d7bSLaurent Vivier }
7856e1c0d7bSLaurent Vivier
78646027c07Sbellard if (cpu_model == NULL) {
787768fe76eSYunQiang Su cpu_model = cpu_get_model(get_elf_eflags(execfd));
788aaed909aSbellard }
789c1c8cfe5SEduardo Habkost cpu_type = parse_cpu_option(cpu_model);
7902278b939SIgor Mammedov
79113c13397SRichard Henderson /* init tcg before creating CPUs */
792940e43aaSClaudio Fontana {
7933cfb0456SPeter Maydell AccelState *accel = current_accel();
7943cfb0456SPeter Maydell AccelClass *ac = ACCEL_GET_CLASS(accel);
7952278b939SIgor Mammedov
796b86f59c7SClaudio Fontana accel_init_interfaces(ac);
7973cfb0456SPeter Maydell object_property_set_bool(OBJECT(accel), "one-insn-per-tb",
7983cfb0456SPeter Maydell opt_one_insn_per_tb, &error_abort);
79992242f34SClaudio Fontana ac->init_machine(NULL);
800940e43aaSClaudio Fontana }
801ff8a8bbcSRichard Henderson
802ff8a8bbcSRichard Henderson /*
803ff8a8bbcSRichard Henderson * Finalize page size before creating CPUs.
804ff8a8bbcSRichard Henderson * This will do nothing if !TARGET_PAGE_BITS_VARY.
805ff8a8bbcSRichard Henderson * The most efficient setting is to match the host.
806ff8a8bbcSRichard Henderson */
807ff8a8bbcSRichard Henderson host_page_size = qemu_real_host_page_size();
808ff8a8bbcSRichard Henderson set_preferred_target_page_bits(ctz32(host_page_size));
809ff8a8bbcSRichard Henderson finalize_target_page_bits();
810ff8a8bbcSRichard Henderson
8112278b939SIgor Mammedov cpu = cpu_create(cpu_type);
812b77af26eSRichard Henderson env = cpu_env(cpu);
8130ac46af3SAndreas Färber cpu_reset(cpu);
814db6b81d4SAndreas Färber thread_cpu = cpu;
81554936004Sbellard
8168f67b9c6SRichard Henderson /*
8178f67b9c6SRichard Henderson * Reserving too much vm space via mmap can run into problems
8188f67b9c6SRichard Henderson * with rlimits, oom due to page table creation, etc. We will
8198f67b9c6SRichard Henderson * still try it, if directed by the command-line option, but
8208f67b9c6SRichard Henderson * not by default.
8218f67b9c6SRichard Henderson */
8228f67b9c6SRichard Henderson max_reserved_va = MAX_RESERVED_VA(cpu);
8238f67b9c6SRichard Henderson if (reserved_va != 0) {
82413c13397SRichard Henderson if ((reserved_va + 1) % host_page_size) {
82513c13397SRichard Henderson char *s = size_to_str(host_page_size);
8262f7828b5SRichard Henderson fprintf(stderr, "Reserved virtual address not aligned mod %s\n", s);
8272f7828b5SRichard Henderson g_free(s);
8282f7828b5SRichard Henderson exit(EXIT_FAILURE);
8292f7828b5SRichard Henderson }
8308f67b9c6SRichard Henderson if (max_reserved_va && reserved_va > max_reserved_va) {
8318f67b9c6SRichard Henderson fprintf(stderr, "Reserved virtual address too big\n");
8328f67b9c6SRichard Henderson exit(EXIT_FAILURE);
8338f67b9c6SRichard Henderson }
8348f67b9c6SRichard Henderson } else if (HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32) {
83595059f9cSRichard Henderson /* MAX_RESERVED_VA + 1 is a large power of 2, so is aligned. */
83695059f9cSRichard Henderson reserved_va = max_reserved_va;
8378f67b9c6SRichard Henderson }
8388f67b9c6SRichard Henderson
839c8fb5cf9SRichard Henderson /*
840c8fb5cf9SRichard Henderson * Temporarily disable
841c8fb5cf9SRichard Henderson * "comparison is always false due to limited range of data type"
842c8fb5cf9SRichard Henderson * due to comparison between (possible) uint64_t and uintptr_t.
843c8fb5cf9SRichard Henderson */
844c8fb5cf9SRichard Henderson #pragma GCC diagnostic push
845c8fb5cf9SRichard Henderson #pragma GCC diagnostic ignored "-Wtype-limits"
846c8fb5cf9SRichard Henderson
847c8fb5cf9SRichard Henderson /*
848c8fb5cf9SRichard Henderson * Select an initial value for task_unmapped_base that is in range.
849c8fb5cf9SRichard Henderson */
850c8fb5cf9SRichard Henderson if (reserved_va) {
851c8fb5cf9SRichard Henderson if (TASK_UNMAPPED_BASE < reserved_va) {
852c8fb5cf9SRichard Henderson task_unmapped_base = TASK_UNMAPPED_BASE;
853c8fb5cf9SRichard Henderson } else {
854c8fb5cf9SRichard Henderson /* The most common default formula is TASK_SIZE / 3. */
855c8fb5cf9SRichard Henderson task_unmapped_base = TARGET_PAGE_ALIGN(reserved_va / 3);
856c8fb5cf9SRichard Henderson }
857c8fb5cf9SRichard Henderson } else if (TASK_UNMAPPED_BASE < UINTPTR_MAX) {
858c8fb5cf9SRichard Henderson task_unmapped_base = TASK_UNMAPPED_BASE;
859c8fb5cf9SRichard Henderson } else {
860c8fb5cf9SRichard Henderson /* 32-bit host: pick something medium size. */
861c8fb5cf9SRichard Henderson task_unmapped_base = 0x10000000;
862c8fb5cf9SRichard Henderson }
863c8fb5cf9SRichard Henderson mmap_next_start = task_unmapped_base;
864c8fb5cf9SRichard Henderson
865da2b71faSRichard Henderson /* Similarly for elf_et_dyn_base. */
866da2b71faSRichard Henderson if (reserved_va) {
867da2b71faSRichard Henderson if (ELF_ET_DYN_BASE < reserved_va) {
868da2b71faSRichard Henderson elf_et_dyn_base = ELF_ET_DYN_BASE;
869da2b71faSRichard Henderson } else {
870da2b71faSRichard Henderson /* The most common default formula is TASK_SIZE / 3 * 2. */
871da2b71faSRichard Henderson elf_et_dyn_base = TARGET_PAGE_ALIGN(reserved_va / 3) * 2;
872da2b71faSRichard Henderson }
873da2b71faSRichard Henderson } else if (ELF_ET_DYN_BASE < UINTPTR_MAX) {
874da2b71faSRichard Henderson elf_et_dyn_base = ELF_ET_DYN_BASE;
875da2b71faSRichard Henderson } else {
876da2b71faSRichard Henderson /* 32-bit host: pick something medium size. */
877da2b71faSRichard Henderson elf_et_dyn_base = 0x18000000;
878da2b71faSRichard Henderson }
879da2b71faSRichard Henderson
880c8fb5cf9SRichard Henderson #pragma GCC diagnostic pop
881c8fb5cf9SRichard Henderson
882a573e9baSRichard Henderson {
883a573e9baSRichard Henderson Error *err = NULL;
8845ebdd774SRichard Henderson if (seed_optarg != NULL) {
885a573e9baSRichard Henderson qemu_guest_random_seed_main(seed_optarg, &err);
886a573e9baSRichard Henderson } else {
887a573e9baSRichard Henderson qcrypto_init(&err);
888a573e9baSRichard Henderson }
889a573e9baSRichard Henderson if (err) {
890a573e9baSRichard Henderson error_reportf_err(err, "cannot initialize crypto: ");
891a573e9baSRichard Henderson exit(1);
892a573e9baSRichard Henderson }
893c5e4a5a9SMagnus Reftel }
894c5e4a5a9SMagnus Reftel
89504a6dfebSaurel32 target_environ = envlist_to_environ(envlist, NULL);
89604a6dfebSaurel32 envlist_free(envlist);
897b12b6a18Sths
898379f6698SPaul Brook /*
899379f6698SPaul Brook * Read in mmap_min_addr kernel parameter. This value is used
900379f6698SPaul Brook * When loading the ELF image to determine whether guest_base
90114f24e14SRichard Henderson * is needed. It is also used in mmap_find_vma.
902379f6698SPaul Brook */
90314f24e14SRichard Henderson {
904379f6698SPaul Brook FILE *fp;
905379f6698SPaul Brook
906379f6698SPaul Brook if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
907379f6698SPaul Brook unsigned long tmp;
908c9f80666SRichard Henderson if (fscanf(fp, "%lu", &tmp) == 1 && tmp != 0) {
90978b79b2cSRichard Henderson mmap_min_addr = MAX(tmp, host_page_size);
910c9f80666SRichard Henderson qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
911c9f80666SRichard Henderson mmap_min_addr);
912379f6698SPaul Brook }
913379f6698SPaul Brook fclose(fp);
914379f6698SPaul Brook }
915379f6698SPaul Brook }
916379f6698SPaul Brook
9177d8cec95Saurel32 /*
918c9f80666SRichard Henderson * We prefer to not make NULL pointers accessible to QEMU.
919c9f80666SRichard Henderson * If we're in a chroot with no /proc, fall back to 1 page.
920c9f80666SRichard Henderson */
921c9f80666SRichard Henderson if (mmap_min_addr == 0) {
922ff8a8bbcSRichard Henderson mmap_min_addr = host_page_size;
923c9f80666SRichard Henderson qemu_log_mask(CPU_LOG_PAGE,
924c9f80666SRichard Henderson "host mmap_min_addr=0x%lx (fallback)\n",
925c9f80666SRichard Henderson mmap_min_addr);
926c9f80666SRichard Henderson }
927c9f80666SRichard Henderson
928c9f80666SRichard Henderson /*
9297d8cec95Saurel32 * Prepare copy of argv vector for target.
9307d8cec95Saurel32 */
9317d8cec95Saurel32 target_argc = argc - optind;
9322ee80bceSNguyen Dinh Phi target_argv = g_new0(char *, target_argc + 1);
9337d8cec95Saurel32
9347d8cec95Saurel32 /*
9357d8cec95Saurel32 * If argv0 is specified (using '-0' switch) we replace
9367d8cec95Saurel32 * argv[0] pointer with the given one.
9377d8cec95Saurel32 */
9387d8cec95Saurel32 i = 0;
9397d8cec95Saurel32 if (argv0 != NULL) {
9407d8cec95Saurel32 target_argv[i++] = strdup(argv0);
9417d8cec95Saurel32 }
9427d8cec95Saurel32 for (; i < target_argc; i++) {
9437d8cec95Saurel32 target_argv[i] = strdup(argv[optind + i]);
9447d8cec95Saurel32 }
9457d8cec95Saurel32 target_argv[target_argc] = NULL;
9467d8cec95Saurel32
947c78d65e8SMarkus Armbruster ts = g_new0(TaskState, 1);
948edf8e2afSMika Westerberg init_task_state(ts);
949edf8e2afSMika Westerberg /* build Task State */
950edf8e2afSMika Westerberg ts->info = info;
951edf8e2afSMika Westerberg ts->bprm = &bprm;
9520429a971SAndreas Färber cpu->opaque = ts;
953edf8e2afSMika Westerberg task_settid(ts);
954edf8e2afSMika Westerberg
955c093364fSOwen Anderson fd_trans_init();
956c093364fSOwen Anderson
9579d3019bcSLaurent Vivier ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs,
958fd4d81ddSArnaud Patard info, &bprm);
959fd4d81ddSArnaud Patard if (ret != 0) {
9609d3019bcSLaurent Vivier printf("Error while loading %s: %s\n", exec_path, strerror(-ret));
9614d1275c2SRiku Voipio _exit(EXIT_FAILURE);
96231e31b8aSbellard }
96331e31b8aSbellard
964b12b6a18Sths for (wrk = target_environ; *wrk; wrk++) {
965ec45bbe5SSaurav Sachidanand g_free(*wrk);
966b12b6a18Sths }
967b12b6a18Sths
968ec45bbe5SSaurav Sachidanand g_free(target_environ);
969b12b6a18Sths
97013829020SPaolo Bonzini if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
97193756fdcSRichard Henderson FILE *f = qemu_log_trylock();
97293756fdcSRichard Henderson if (f) {
97393756fdcSRichard Henderson fprintf(f, "guest_base %p\n", (void *)guest_base);
97493756fdcSRichard Henderson fprintf(f, "page layout changed following binary load\n");
97593756fdcSRichard Henderson page_dump(f);
97654936004Sbellard
97793756fdcSRichard Henderson fprintf(f, "end_code 0x" TARGET_ABI_FMT_lx "\n",
97893756fdcSRichard Henderson info->end_code);
97993756fdcSRichard Henderson fprintf(f, "start_code 0x" TARGET_ABI_FMT_lx "\n",
98093756fdcSRichard Henderson info->start_code);
98193756fdcSRichard Henderson fprintf(f, "start_data 0x" TARGET_ABI_FMT_lx "\n",
98293756fdcSRichard Henderson info->start_data);
98393756fdcSRichard Henderson fprintf(f, "end_data 0x" TARGET_ABI_FMT_lx "\n",
98493756fdcSRichard Henderson info->end_data);
98593756fdcSRichard Henderson fprintf(f, "start_stack 0x" TARGET_ABI_FMT_lx "\n",
98693756fdcSRichard Henderson info->start_stack);
98793756fdcSRichard Henderson fprintf(f, "brk 0x" TARGET_ABI_FMT_lx "\n",
98893756fdcSRichard Henderson info->brk);
98993756fdcSRichard Henderson fprintf(f, "entry 0x" TARGET_ABI_FMT_lx "\n",
99093756fdcSRichard Henderson info->entry);
99193756fdcSRichard Henderson fprintf(f, "argv_start 0x" TARGET_ABI_FMT_lx "\n",
99260f1c801SRichard Henderson info->argv);
99393756fdcSRichard Henderson fprintf(f, "env_start 0x" TARGET_ABI_FMT_lx "\n",
99460f1c801SRichard Henderson info->envp);
99593756fdcSRichard Henderson fprintf(f, "auxv_start 0x" TARGET_ABI_FMT_lx "\n",
99693756fdcSRichard Henderson info->saved_auxv);
99793756fdcSRichard Henderson qemu_log_unlock(f);
99893756fdcSRichard Henderson }
9992e77eac6Sblueswir1 }
100031e31b8aSbellard
100153a5960aSpbrook target_set_brk(info->brk);
100231e31b8aSbellard syscall_init();
100366fb9763Sbellard signal_init();
100431e31b8aSbellard
10059002ec79SRichard Henderson /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
10069002ec79SRichard Henderson generating the prologue until now so that the prologue can take
10079002ec79SRichard Henderson the real value of GUEST_BASE into account. */
1008935f75aeSRichard Henderson tcg_prologue_init();
10099002ec79SRichard Henderson
1010cd71c089SLaurent Vivier target_cpu_copy_regs(env, regs);
1011cd71c089SLaurent Vivier
1012fcedd920SAlex Bennée if (gdbstub) {
1013fcedd920SAlex Bennée if (gdbserver_start(gdbstub) < 0) {
1014fcedd920SAlex Bennée fprintf(stderr, "qemu: could not open gdbserver on %s\n",
1015fcedd920SAlex Bennée gdbstub);
10164d1275c2SRiku Voipio exit(EXIT_FAILURE);
1017ff7a981aSPeter Maydell }
1018f84e313eSGustavo Romero gdb_handlesig(cpu, 0, NULL, NULL, 0);
10191fddef4bSbellard }
1020e4a4aaa5SRichard Henderson
1021e4a4aaa5SRichard Henderson #ifdef CONFIG_SEMIHOSTING
1022e4a4aaa5SRichard Henderson qemu_semihosting_guestfd_init();
1023e4a4aaa5SRichard Henderson #endif
1024e4a4aaa5SRichard Henderson
10251b6b029eSbellard cpu_loop(env);
10261b6b029eSbellard /* never exits */
102731e31b8aSbellard return 0;
102831e31b8aSbellard }
1029