xref: /qemu/linux-user/main.c (revision 85b4fa0c)
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"
21a8d25326SMarkus Armbruster #include "qemu-common.h"
22b52713c1SPhilippe Mathieu-Daudé #include "qemu/units.h"
23940e43aaSClaudio Fontana #include "qemu/accel.h"
2414a48c1dSMarkus Armbruster #include "sysemu/tcg.h"
2567a1de0dSFam Zheng #include "qemu-version.h"
26edf8e2afSMika Westerberg #include <sys/syscall.h>
27703e0e89SRichard Henderson #include <sys/resource.h>
28ee947430SAlex Bennée #include <sys/shm.h>
296e1c0d7bSLaurent Vivier #include <linux/binfmts.h>
3031e31b8aSbellard 
31daa76aa4SMarkus Armbruster #include "qapi/error.h"
323ef693a0Sbellard #include "qemu.h"
333b249d26SPeter Maydell #include "user-internals.h"
34f348b6d1SVeronia Bahaa #include "qemu/path.h"
35dc5e9ac7SMarkus Armbruster #include "qemu/queue.h"
366533dd6eSLluís Vilanova #include "qemu/config-file.h"
37f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
38f5852efaSChristophe Fergeau #include "qemu/error-report.h"
39f348b6d1SVeronia Bahaa #include "qemu/help_option.h"
400b8fa32fSMarkus Armbruster #include "qemu/module.h"
41f308f64eSLluís Vilanova #include "qemu/plugin.h"
4263c91552SPaolo Bonzini #include "exec/exec-all.h"
43*85b4fa0cSPeter Maydell #include "exec/gdbstub.h"
44dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg.h"
451de7afc9SPaolo Bonzini #include "qemu/timer.h"
461de7afc9SPaolo Bonzini #include "qemu/envlist.h"
475ebdd774SRichard Henderson #include "qemu/guest-random.h"
48d8fd2954SPaul Brook #include "elf.h"
496533dd6eSLluís Vilanova #include "trace/control.h"
50542ca434SLaurent Vivier #include "target_elf.h"
51cd71c089SLaurent Vivier #include "cpu_loop-common.h"
52a573e9baSRichard Henderson #include "crypto/init.h"
53c093364fSOwen Anderson #include "fd-trans.h"
542113aed6SPeter Maydell #include "signal-common.h"
553ad0a769SPeter Maydell #include "loader.h"
565423e6d3SPeter Maydell #include "user-mmap.h"
5704a6dfebSaurel32 
586e1c0d7bSLaurent Vivier #ifndef AT_FLAGS_PRESERVE_ARGV0
596e1c0d7bSLaurent Vivier #define AT_FLAGS_PRESERVE_ARGV0_BIT 0
606e1c0d7bSLaurent Vivier #define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
616e1c0d7bSLaurent Vivier #endif
626e1c0d7bSLaurent Vivier 
63d088d664Saurel32 char *exec_path;
64d088d664Saurel32 
651b530a6dSaurel32 int singlestep;
668cb76755SStefan Weil static const char *argv0;
67fcedd920SAlex Bennée static const char *gdbstub;
688cb76755SStefan Weil static envlist_t *envlist;
6951fb256aSAndreas Färber static const char *cpu_model;
702278b939SIgor Mammedov static const char *cpu_type;
715ebdd774SRichard Henderson static const char *seed_optarg;
72379f6698SPaul Brook unsigned long mmap_min_addr;
735ca870b9SRichard Henderson uintptr_t guest_base;
74e307c192SRichard Henderson bool have_guest_base;
75120a9848SPaolo Bonzini 
76288e65b9SAlexander Graf /*
774b25a506SJosh Kunz  * Used to implement backwards-compatibility for the `-strace`, and
784b25a506SJosh Kunz  * QEMU_STRACE options. Without this, the QEMU_LOG can be overwritten by
794b25a506SJosh Kunz  * -strace, or vice versa.
804b25a506SJosh Kunz  */
814b25a506SJosh Kunz static bool enable_strace;
824b25a506SJosh Kunz 
834b25a506SJosh Kunz /*
844b25a506SJosh Kunz  * The last log mask given by the user in an environment variable or argument.
854b25a506SJosh Kunz  * Used to support command line arguments overriding environment variables.
864b25a506SJosh Kunz  */
874b25a506SJosh Kunz static int last_log_mask;
884b25a506SJosh Kunz 
894b25a506SJosh Kunz /*
90288e65b9SAlexander Graf  * When running 32-on-64 we should make sure we can fit all of the possible
91288e65b9SAlexander Graf  * guest address space into a contiguous chunk of virtual host memory.
92288e65b9SAlexander Graf  *
93288e65b9SAlexander Graf  * This way we will never overlap with our own libraries or binaries or stack
94288e65b9SAlexander Graf  * or anything else that QEMU maps.
9518e80c55SRichard Henderson  *
9618e80c55SRichard Henderson  * Many cpus reserve the high bit (or more than one for some 64-bit cpus)
9718e80c55SRichard Henderson  * of the address for the kernel.  Some cpus rely on this and user space
9818e80c55SRichard Henderson  * uses the high bit(s) for pointer tagging and the like.  For them, we
9918e80c55SRichard Henderson  * must preserve the expected address space.
100288e65b9SAlexander Graf  */
10118e80c55SRichard Henderson #ifndef MAX_RESERVED_VA
10218e80c55SRichard Henderson # if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
10318e80c55SRichard Henderson #  if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
10418e80c55SRichard Henderson       (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
10518e80c55SRichard Henderson /* There are a number of places where we assign reserved_va to a variable
10618e80c55SRichard Henderson    of type abi_ulong and expect it to fit.  Avoid the last page.  */
1078f67b9c6SRichard Henderson #   define MAX_RESERVED_VA(CPU)  (0xfffffffful & TARGET_PAGE_MASK)
108314992b1SAlexander Graf #  else
1098f67b9c6SRichard Henderson #   define MAX_RESERVED_VA(CPU)  (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
110314992b1SAlexander Graf #  endif
111288e65b9SAlexander Graf # else
1128f67b9c6SRichard Henderson #  define MAX_RESERVED_VA(CPU)  0
11318e80c55SRichard Henderson # endif
11418e80c55SRichard Henderson #endif
11518e80c55SRichard Henderson 
11668a1c816SPaul Brook unsigned long reserved_va;
1171b530a6dSaurel32 
118d03f9c32SMeador Inge static void usage(int exitcode);
119fc9c5412SJohannes Schauer 
1207ee2822cSPaolo Bonzini static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
121e586822aSRiku Voipio const char *qemu_uname_release;
122586314f2Sbellard 
1239de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
1249de5e440Sbellard    we allocate a bigger stack. Need a better solution, for example
1259de5e440Sbellard    by remapping the process stack directly at the right place */
126703e0e89SRichard Henderson unsigned long guest_stack_size = 8 * 1024 * 1024UL;
12731e31b8aSbellard 
1288fcd3692Sblueswir1 #if defined(TARGET_I386)
12905390248SAndreas Färber int cpu_get_pic_interrupt(CPUX86State *env)
13092ccca6aSbellard {
13192ccca6aSbellard     return -1;
13292ccca6aSbellard }
1338fcd3692Sblueswir1 #endif
13492ccca6aSbellard 
135d5975363Spbrook /***********************************************************/
136d5975363Spbrook /* Helper routines for implementing atomic operations.  */
137d5975363Spbrook 
138d5975363Spbrook /* Make sure everything is in a consistent state for calling fork().  */
139d5975363Spbrook void fork_start(void)
140d5975363Spbrook {
14106065c45SPeter Maydell     start_exclusive();
142d032d1b4SRiku Voipio     mmap_fork_start();
143024949caSPeter Maydell     cpu_list_lock();
144d5975363Spbrook }
145d5975363Spbrook 
146d5975363Spbrook void fork_end(int child)
147d5975363Spbrook {
148d032d1b4SRiku Voipio     mmap_fork_end(child);
149d5975363Spbrook     if (child) {
150bdc44640SAndreas Färber         CPUState *cpu, *next_cpu;
151d5975363Spbrook         /* Child processes created by fork() only have a single thread.
152d5975363Spbrook            Discard information about the parent threads.  */
153bdc44640SAndreas Färber         CPU_FOREACH_SAFE(cpu, next_cpu) {
154bdc44640SAndreas Färber             if (cpu != thread_cpu) {
155068a5ea0SEmilio G. Cota                 QTAILQ_REMOVE_RCU(&cpus, cpu, node);
156bdc44640SAndreas Färber             }
157bdc44640SAndreas Färber         }
158267f685bSPaolo Bonzini         qemu_init_cpu_list();
159f7ec7f7bSPeter Crosthwaite         gdbserver_fork(thread_cpu);
16006065c45SPeter Maydell         /* qemu_init_cpu_list() takes care of reinitializing the
16106065c45SPeter Maydell          * exclusive state, so we don't need to end_exclusive() here.
16206065c45SPeter Maydell          */
163d5975363Spbrook     } else {
164267f685bSPaolo Bonzini         cpu_list_unlock();
16506065c45SPeter Maydell         end_exclusive();
166d5975363Spbrook     }
167d5975363Spbrook }
168d5975363Spbrook 
169b44316fbSPeter Maydell __thread CPUState *thread_cpu;
17059faf6d6Sbellard 
171178f9429SSergey Fedorov bool qemu_cpu_is_self(CPUState *cpu)
172178f9429SSergey Fedorov {
173178f9429SSergey Fedorov     return thread_cpu == cpu;
174178f9429SSergey Fedorov }
175178f9429SSergey Fedorov 
176178f9429SSergey Fedorov void qemu_cpu_kick(CPUState *cpu)
177178f9429SSergey Fedorov {
178178f9429SSergey Fedorov     cpu_exit(cpu);
179178f9429SSergey Fedorov }
180178f9429SSergey Fedorov 
181edf8e2afSMika Westerberg void task_settid(TaskState *ts)
182edf8e2afSMika Westerberg {
183edf8e2afSMika Westerberg     if (ts->ts_tid == 0) {
184edf8e2afSMika Westerberg         ts->ts_tid = (pid_t)syscall(SYS_gettid);
185edf8e2afSMika Westerberg     }
186edf8e2afSMika Westerberg }
187edf8e2afSMika Westerberg 
188edf8e2afSMika Westerberg void stop_all_tasks(void)
189edf8e2afSMika Westerberg {
190edf8e2afSMika Westerberg     /*
191edf8e2afSMika Westerberg      * We trust that when using NPTL, start_exclusive()
192edf8e2afSMika Westerberg      * handles thread stopping correctly.
193edf8e2afSMika Westerberg      */
194edf8e2afSMika Westerberg     start_exclusive();
195edf8e2afSMika Westerberg }
196edf8e2afSMika Westerberg 
197c3a92833Spbrook /* Assumes contents are already zeroed.  */
198624f7979Spbrook void init_task_state(TaskState *ts)
199624f7979Spbrook {
200624f7979Spbrook     ts->used = 1;
2015bfce0b7SPeter Maydell     ts->sigaltstack_used = (struct target_sigaltstack) {
2025bfce0b7SPeter Maydell         .ss_sp = 0,
2035bfce0b7SPeter Maydell         .ss_size = 0,
2045bfce0b7SPeter Maydell         .ss_flags = TARGET_SS_DISABLE,
2055bfce0b7SPeter Maydell     };
206624f7979Spbrook }
2079de5e440Sbellard 
20830ba0ee5SAndreas Färber CPUArchState *cpu_copy(CPUArchState *env)
20930ba0ee5SAndreas Färber {
21029a0af61SRichard Henderson     CPUState *cpu = env_cpu(env);
2112278b939SIgor Mammedov     CPUState *new_cpu = cpu_create(cpu_type);
21261c7480fSLeon Alrae     CPUArchState *new_env = new_cpu->env_ptr;
21330ba0ee5SAndreas Färber     CPUBreakpoint *bp;
21430ba0ee5SAndreas Färber 
21530ba0ee5SAndreas Färber     /* Reset non arch specific state */
21675a34036SAndreas Färber     cpu_reset(new_cpu);
21730ba0ee5SAndreas Färber 
2186cc9d67cSRichard Henderson     new_cpu->tcg_cflags = cpu->tcg_cflags;
21930ba0ee5SAndreas Färber     memcpy(new_env, env, sizeof(CPUArchState));
22030ba0ee5SAndreas Färber 
22130ba0ee5SAndreas Färber     /* Clone all break/watchpoints.
22230ba0ee5SAndreas Färber        Note: Once we support ptrace with hw-debug register access, make sure
22330ba0ee5SAndreas Färber        BP_CPU break/watchpoints are handled correctly on clone. */
2241d085f6cSThierry Bultel     QTAILQ_INIT(&new_cpu->breakpoints);
225f0c3c505SAndreas Färber     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
226b3310ab3SAndreas Färber         cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL);
22730ba0ee5SAndreas Färber     }
22830ba0ee5SAndreas Färber 
22930ba0ee5SAndreas Färber     return new_env;
23030ba0ee5SAndreas Färber }
23130ba0ee5SAndreas Färber 
232fc9c5412SJohannes Schauer static void handle_arg_help(const char *arg)
233fc9c5412SJohannes Schauer {
2344d1275c2SRiku Voipio     usage(EXIT_SUCCESS);
235fc9c5412SJohannes Schauer }
236fc9c5412SJohannes Schauer 
237fc9c5412SJohannes Schauer static void handle_arg_log(const char *arg)
238fc9c5412SJohannes Schauer {
2394b25a506SJosh Kunz     last_log_mask = qemu_str_to_log_mask(arg);
2404b25a506SJosh Kunz     if (!last_log_mask) {
24159a6fa6eSPeter Maydell         qemu_print_log_usage(stdout);
2424d1275c2SRiku Voipio         exit(EXIT_FAILURE);
243fc9c5412SJohannes Schauer     }
244fc9c5412SJohannes Schauer }
245fc9c5412SJohannes Schauer 
2468423fa90SAlex Bennée static void handle_arg_dfilter(const char *arg)
2478423fa90SAlex Bennée {
2487f4341e8SAlex Bennée     qemu_set_dfilter_ranges(arg, &error_fatal);
2498423fa90SAlex Bennée }
2508423fa90SAlex Bennée 
25150171d42S陳韋任 static void handle_arg_log_filename(const char *arg)
25250171d42S陳韋任 {
253daa76aa4SMarkus Armbruster     qemu_set_log_filename(arg, &error_fatal);
25450171d42S陳韋任 }
25550171d42S陳韋任 
256fc9c5412SJohannes Schauer static void handle_arg_set_env(const char *arg)
257fc9c5412SJohannes Schauer {
258fc9c5412SJohannes Schauer     char *r, *p, *token;
259fc9c5412SJohannes Schauer     r = p = strdup(arg);
260fc9c5412SJohannes Schauer     while ((token = strsep(&p, ",")) != NULL) {
261fc9c5412SJohannes Schauer         if (envlist_setenv(envlist, token) != 0) {
2624d1275c2SRiku Voipio             usage(EXIT_FAILURE);
263fc9c5412SJohannes Schauer         }
264fc9c5412SJohannes Schauer     }
265fc9c5412SJohannes Schauer     free(r);
266fc9c5412SJohannes Schauer }
267fc9c5412SJohannes Schauer 
268fc9c5412SJohannes Schauer static void handle_arg_unset_env(const char *arg)
269fc9c5412SJohannes Schauer {
270fc9c5412SJohannes Schauer     char *r, *p, *token;
271fc9c5412SJohannes Schauer     r = p = strdup(arg);
272fc9c5412SJohannes Schauer     while ((token = strsep(&p, ",")) != NULL) {
273fc9c5412SJohannes Schauer         if (envlist_unsetenv(envlist, token) != 0) {
2744d1275c2SRiku Voipio             usage(EXIT_FAILURE);
275fc9c5412SJohannes Schauer         }
276fc9c5412SJohannes Schauer     }
277fc9c5412SJohannes Schauer     free(r);
278fc9c5412SJohannes Schauer }
279fc9c5412SJohannes Schauer 
280fc9c5412SJohannes Schauer static void handle_arg_argv0(const char *arg)
281fc9c5412SJohannes Schauer {
282fc9c5412SJohannes Schauer     argv0 = strdup(arg);
283fc9c5412SJohannes Schauer }
284fc9c5412SJohannes Schauer 
285fc9c5412SJohannes Schauer static void handle_arg_stack_size(const char *arg)
286fc9c5412SJohannes Schauer {
287fc9c5412SJohannes Schauer     char *p;
288fc9c5412SJohannes Schauer     guest_stack_size = strtoul(arg, &p, 0);
289fc9c5412SJohannes Schauer     if (guest_stack_size == 0) {
2904d1275c2SRiku Voipio         usage(EXIT_FAILURE);
291fc9c5412SJohannes Schauer     }
292fc9c5412SJohannes Schauer 
293fc9c5412SJohannes Schauer     if (*p == 'M') {
294b52713c1SPhilippe Mathieu-Daudé         guest_stack_size *= MiB;
295fc9c5412SJohannes Schauer     } else if (*p == 'k' || *p == 'K') {
296b52713c1SPhilippe Mathieu-Daudé         guest_stack_size *= KiB;
297fc9c5412SJohannes Schauer     }
298fc9c5412SJohannes Schauer }
299fc9c5412SJohannes Schauer 
300fc9c5412SJohannes Schauer static void handle_arg_ld_prefix(const char *arg)
301fc9c5412SJohannes Schauer {
302fc9c5412SJohannes Schauer     interp_prefix = strdup(arg);
303fc9c5412SJohannes Schauer }
304fc9c5412SJohannes Schauer 
305fc9c5412SJohannes Schauer static void handle_arg_pagesize(const char *arg)
306fc9c5412SJohannes Schauer {
307fc9c5412SJohannes Schauer     qemu_host_page_size = atoi(arg);
308fc9c5412SJohannes Schauer     if (qemu_host_page_size == 0 ||
309fc9c5412SJohannes Schauer         (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
310fc9c5412SJohannes Schauer         fprintf(stderr, "page size must be a power of two\n");
3114d1275c2SRiku Voipio         exit(EXIT_FAILURE);
312fc9c5412SJohannes Schauer     }
313fc9c5412SJohannes Schauer }
314fc9c5412SJohannes Schauer 
3155ebdd774SRichard Henderson static void handle_arg_seed(const char *arg)
316c5e4a5a9SMagnus Reftel {
3175ebdd774SRichard Henderson     seed_optarg = arg;
318c5e4a5a9SMagnus Reftel }
319c5e4a5a9SMagnus Reftel 
320fc9c5412SJohannes Schauer static void handle_arg_gdb(const char *arg)
321fc9c5412SJohannes Schauer {
322fcedd920SAlex Bennée     gdbstub = g_strdup(arg);
323fc9c5412SJohannes Schauer }
324fc9c5412SJohannes Schauer 
325fc9c5412SJohannes Schauer static void handle_arg_uname(const char *arg)
326fc9c5412SJohannes Schauer {
327fc9c5412SJohannes Schauer     qemu_uname_release = strdup(arg);
328fc9c5412SJohannes Schauer }
329fc9c5412SJohannes Schauer 
330fc9c5412SJohannes Schauer static void handle_arg_cpu(const char *arg)
331fc9c5412SJohannes Schauer {
332fc9c5412SJohannes Schauer     cpu_model = strdup(arg);
333c8057f95SPeter Maydell     if (cpu_model == NULL || is_help_option(cpu_model)) {
334fc9c5412SJohannes Schauer         /* XXX: implement xxx_cpu_list for targets that still miss it */
335e916cbf8SPeter Maydell #if defined(cpu_list)
3360442428aSMarkus Armbruster         cpu_list();
337fc9c5412SJohannes Schauer #endif
3384d1275c2SRiku Voipio         exit(EXIT_FAILURE);
339fc9c5412SJohannes Schauer     }
340fc9c5412SJohannes Schauer }
341fc9c5412SJohannes Schauer 
342fc9c5412SJohannes Schauer static void handle_arg_guest_base(const char *arg)
343fc9c5412SJohannes Schauer {
344fc9c5412SJohannes Schauer     guest_base = strtol(arg, NULL, 0);
345e307c192SRichard Henderson     have_guest_base = true;
346fc9c5412SJohannes Schauer }
347fc9c5412SJohannes Schauer 
348fc9c5412SJohannes Schauer static void handle_arg_reserved_va(const char *arg)
349fc9c5412SJohannes Schauer {
350fc9c5412SJohannes Schauer     char *p;
351fc9c5412SJohannes Schauer     int shift = 0;
352fc9c5412SJohannes Schauer     reserved_va = strtoul(arg, &p, 0);
353fc9c5412SJohannes Schauer     switch (*p) {
354fc9c5412SJohannes Schauer     case 'k':
355fc9c5412SJohannes Schauer     case 'K':
356fc9c5412SJohannes Schauer         shift = 10;
357fc9c5412SJohannes Schauer         break;
358fc9c5412SJohannes Schauer     case 'M':
359fc9c5412SJohannes Schauer         shift = 20;
360fc9c5412SJohannes Schauer         break;
361fc9c5412SJohannes Schauer     case 'G':
362fc9c5412SJohannes Schauer         shift = 30;
363fc9c5412SJohannes Schauer         break;
364fc9c5412SJohannes Schauer     }
365fc9c5412SJohannes Schauer     if (shift) {
366fc9c5412SJohannes Schauer         unsigned long unshifted = reserved_va;
367fc9c5412SJohannes Schauer         p++;
368fc9c5412SJohannes Schauer         reserved_va <<= shift;
3698f67b9c6SRichard Henderson         if (reserved_va >> shift != unshifted) {
370fc9c5412SJohannes Schauer             fprintf(stderr, "Reserved virtual address too big\n");
3714d1275c2SRiku Voipio             exit(EXIT_FAILURE);
372fc9c5412SJohannes Schauer         }
373fc9c5412SJohannes Schauer     }
374fc9c5412SJohannes Schauer     if (*p) {
375fc9c5412SJohannes Schauer         fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
3764d1275c2SRiku Voipio         exit(EXIT_FAILURE);
377fc9c5412SJohannes Schauer     }
378fc9c5412SJohannes Schauer }
379fc9c5412SJohannes Schauer 
380fc9c5412SJohannes Schauer static void handle_arg_singlestep(const char *arg)
381fc9c5412SJohannes Schauer {
382fc9c5412SJohannes Schauer     singlestep = 1;
383fc9c5412SJohannes Schauer }
384fc9c5412SJohannes Schauer 
385fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg)
386fc9c5412SJohannes Schauer {
3874b25a506SJosh Kunz     enable_strace = true;
388fc9c5412SJohannes Schauer }
389fc9c5412SJohannes Schauer 
390fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg)
391fc9c5412SJohannes Schauer {
3927e563bfbSThomas Huth     printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
3930781dd6eSThomas Huth            "\n" QEMU_COPYRIGHT "\n");
3944d1275c2SRiku Voipio     exit(EXIT_SUCCESS);
395fc9c5412SJohannes Schauer }
396fc9c5412SJohannes Schauer 
3976533dd6eSLluís Vilanova static void handle_arg_trace(const char *arg)
3986533dd6eSLluís Vilanova {
39992eecfffSPaolo Bonzini     trace_opt_parse(arg);
4006533dd6eSLluís Vilanova }
4016533dd6eSLluís Vilanova 
402130ea832SMax Filippov #if defined(TARGET_XTENSA)
403130ea832SMax Filippov static void handle_arg_abi_call0(const char *arg)
404130ea832SMax Filippov {
405130ea832SMax Filippov     xtensa_set_abi_call0();
406130ea832SMax Filippov }
407130ea832SMax Filippov #endif
408130ea832SMax Filippov 
409f308f64eSLluís Vilanova static QemuPluginList plugins = QTAILQ_HEAD_INITIALIZER(plugins);
410f308f64eSLluís Vilanova 
411f308f64eSLluís Vilanova #ifdef CONFIG_PLUGIN
412f308f64eSLluís Vilanova static void handle_arg_plugin(const char *arg)
413f308f64eSLluís Vilanova {
414f308f64eSLluís Vilanova     qemu_plugin_opt_parse(arg, &plugins);
415f308f64eSLluís Vilanova }
416f308f64eSLluís Vilanova #endif
417f308f64eSLluís Vilanova 
418fc9c5412SJohannes Schauer struct qemu_argument {
419fc9c5412SJohannes Schauer     const char *argv;
420fc9c5412SJohannes Schauer     const char *env;
421fc9c5412SJohannes Schauer     bool has_arg;
422fc9c5412SJohannes Schauer     void (*handle_opt)(const char *arg);
423fc9c5412SJohannes Schauer     const char *example;
424fc9c5412SJohannes Schauer     const char *help;
425fc9c5412SJohannes Schauer };
426fc9c5412SJohannes Schauer 
42742644ceeSJim Meyering static const struct qemu_argument arg_table[] = {
428fc9c5412SJohannes Schauer     {"h",          "",                 false, handle_arg_help,
429fc9c5412SJohannes Schauer      "",           "print this help"},
430daaf8c8eSMeador Inge     {"help",       "",                 false, handle_arg_help,
431daaf8c8eSMeador Inge      "",           ""},
432fc9c5412SJohannes Schauer     {"g",          "QEMU_GDB",         true,  handle_arg_gdb,
433fc9c5412SJohannes Schauer      "port",       "wait gdb connection to 'port'"},
434fc9c5412SJohannes Schauer     {"L",          "QEMU_LD_PREFIX",   true,  handle_arg_ld_prefix,
435fc9c5412SJohannes Schauer      "path",       "set the elf interpreter prefix to 'path'"},
436fc9c5412SJohannes Schauer     {"s",          "QEMU_STACK_SIZE",  true,  handle_arg_stack_size,
437fc9c5412SJohannes Schauer      "size",       "set the stack size to 'size' bytes"},
438fc9c5412SJohannes Schauer     {"cpu",        "QEMU_CPU",         true,  handle_arg_cpu,
439c8057f95SPeter Maydell      "model",      "select CPU (-cpu help for list)"},
440fc9c5412SJohannes Schauer     {"E",          "QEMU_SET_ENV",     true,  handle_arg_set_env,
441fc9c5412SJohannes Schauer      "var=value",  "sets targets environment variable (see below)"},
442fc9c5412SJohannes Schauer     {"U",          "QEMU_UNSET_ENV",   true,  handle_arg_unset_env,
443fc9c5412SJohannes Schauer      "var",        "unsets targets environment variable (see below)"},
444fc9c5412SJohannes Schauer     {"0",          "QEMU_ARGV0",       true,  handle_arg_argv0,
445fc9c5412SJohannes Schauer      "argv0",      "forces target process argv[0] to be 'argv0'"},
446fc9c5412SJohannes Schauer     {"r",          "QEMU_UNAME",       true,  handle_arg_uname,
447fc9c5412SJohannes Schauer      "uname",      "set qemu uname release string to 'uname'"},
448fc9c5412SJohannes Schauer     {"B",          "QEMU_GUEST_BASE",  true,  handle_arg_guest_base,
449fc9c5412SJohannes Schauer      "address",    "set guest_base address to 'address'"},
450fc9c5412SJohannes Schauer     {"R",          "QEMU_RESERVED_VA", true,  handle_arg_reserved_va,
451fc9c5412SJohannes Schauer      "size",       "reserve 'size' bytes for guest virtual address space"},
452fc9c5412SJohannes Schauer     {"d",          "QEMU_LOG",         true,  handle_arg_log,
453989b697dSPeter Maydell      "item[,...]", "enable logging of specified items "
454989b697dSPeter Maydell      "(use '-d help' for a list of items)"},
4558423fa90SAlex Bennée     {"dfilter",    "QEMU_DFILTER",     true,  handle_arg_dfilter,
4568423fa90SAlex Bennée      "range[,...]","filter logging based on address range"},
45750171d42S陳韋任     {"D",          "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
458989b697dSPeter Maydell      "logfile",     "write logs to 'logfile' (default stderr)"},
459fc9c5412SJohannes Schauer     {"p",          "QEMU_PAGESIZE",    true,  handle_arg_pagesize,
460fc9c5412SJohannes Schauer      "pagesize",   "set the host page size to 'pagesize'"},
461fc9c5412SJohannes Schauer     {"singlestep", "QEMU_SINGLESTEP",  false, handle_arg_singlestep,
462fc9c5412SJohannes Schauer      "",           "run in singlestep mode"},
463fc9c5412SJohannes Schauer     {"strace",     "QEMU_STRACE",      false, handle_arg_strace,
464fc9c5412SJohannes Schauer      "",           "log system calls"},
4655ebdd774SRichard Henderson     {"seed",       "QEMU_RAND_SEED",   true,  handle_arg_seed,
466c5e4a5a9SMagnus Reftel      "",           "Seed for pseudo-random number generator"},
4676533dd6eSLluís Vilanova     {"trace",      "QEMU_TRACE",       true,  handle_arg_trace,
4686533dd6eSLluís Vilanova      "",           "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
469f308f64eSLluís Vilanova #ifdef CONFIG_PLUGIN
470f308f64eSLluís Vilanova     {"plugin",     "QEMU_PLUGIN",      true,  handle_arg_plugin,
4713a445acbSMahmoud Mandour      "",           "[file=]<file>[,<argname>=<argvalue>]"},
472f308f64eSLluís Vilanova #endif
473fc9c5412SJohannes Schauer     {"version",    "QEMU_VERSION",     false, handle_arg_version,
4741386d4c0SPeter Maydell      "",           "display version information and exit"},
475130ea832SMax Filippov #if defined(TARGET_XTENSA)
476130ea832SMax Filippov     {"xtensa-abi-call0", "QEMU_XTENSA_ABI_CALL0", false, handle_arg_abi_call0,
477130ea832SMax Filippov      "",           "assume CALL0 Xtensa ABI"},
478130ea832SMax Filippov #endif
479fc9c5412SJohannes Schauer     {NULL, NULL, false, NULL, NULL, NULL}
480fc9c5412SJohannes Schauer };
481fc9c5412SJohannes Schauer 
482d03f9c32SMeador Inge static void usage(int exitcode)
483fc9c5412SJohannes Schauer {
48442644ceeSJim Meyering     const struct qemu_argument *arginfo;
485fc9c5412SJohannes Schauer     int maxarglen;
486fc9c5412SJohannes Schauer     int maxenvlen;
487fc9c5412SJohannes Schauer 
4882e59915dSPaolo Bonzini     printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
4892e59915dSPaolo Bonzini            "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n"
490fc9c5412SJohannes Schauer            "\n"
491fc9c5412SJohannes Schauer            "Options and associated environment variables:\n"
492fc9c5412SJohannes Schauer            "\n");
493fc9c5412SJohannes Schauer 
49463ec54d7SPeter Maydell     /* Calculate column widths. We must always have at least enough space
49563ec54d7SPeter Maydell      * for the column header.
49663ec54d7SPeter Maydell      */
49763ec54d7SPeter Maydell     maxarglen = strlen("Argument");
49863ec54d7SPeter Maydell     maxenvlen = strlen("Env-variable");
499fc9c5412SJohannes Schauer 
500fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
50163ec54d7SPeter Maydell         int arglen = strlen(arginfo->argv);
50263ec54d7SPeter Maydell         if (arginfo->has_arg) {
50363ec54d7SPeter Maydell             arglen += strlen(arginfo->example) + 1;
50463ec54d7SPeter Maydell         }
505fc9c5412SJohannes Schauer         if (strlen(arginfo->env) > maxenvlen) {
506fc9c5412SJohannes Schauer             maxenvlen = strlen(arginfo->env);
507fc9c5412SJohannes Schauer         }
50863ec54d7SPeter Maydell         if (arglen > maxarglen) {
50963ec54d7SPeter Maydell             maxarglen = arglen;
510fc9c5412SJohannes Schauer         }
511fc9c5412SJohannes Schauer     }
512fc9c5412SJohannes Schauer 
51363ec54d7SPeter Maydell     printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
51463ec54d7SPeter Maydell             maxenvlen, "Env-variable");
515fc9c5412SJohannes Schauer 
516fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
517fc9c5412SJohannes Schauer         if (arginfo->has_arg) {
518fc9c5412SJohannes Schauer             printf("-%s %-*s %-*s %s\n", arginfo->argv,
51963ec54d7SPeter Maydell                    (int)(maxarglen - strlen(arginfo->argv) - 1),
52063ec54d7SPeter Maydell                    arginfo->example, maxenvlen, arginfo->env, arginfo->help);
521fc9c5412SJohannes Schauer         } else {
52263ec54d7SPeter Maydell             printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
523fc9c5412SJohannes Schauer                     maxenvlen, arginfo->env,
524fc9c5412SJohannes Schauer                     arginfo->help);
525fc9c5412SJohannes Schauer         }
526fc9c5412SJohannes Schauer     }
527fc9c5412SJohannes Schauer 
528fc9c5412SJohannes Schauer     printf("\n"
529fc9c5412SJohannes Schauer            "Defaults:\n"
530fc9c5412SJohannes Schauer            "QEMU_LD_PREFIX  = %s\n"
531989b697dSPeter Maydell            "QEMU_STACK_SIZE = %ld byte\n",
532fc9c5412SJohannes Schauer            interp_prefix,
533989b697dSPeter Maydell            guest_stack_size);
534fc9c5412SJohannes Schauer 
535fc9c5412SJohannes Schauer     printf("\n"
536fc9c5412SJohannes Schauer            "You can use -E and -U options or the QEMU_SET_ENV and\n"
537fc9c5412SJohannes Schauer            "QEMU_UNSET_ENV environment variables to set and unset\n"
538fc9c5412SJohannes Schauer            "environment variables for the target process.\n"
539fc9c5412SJohannes Schauer            "It is possible to provide several variables by separating them\n"
540fc9c5412SJohannes Schauer            "by commas in getsubopt(3) style. Additionally it is possible to\n"
541fc9c5412SJohannes Schauer            "provide the -E and -U options multiple times.\n"
542fc9c5412SJohannes Schauer            "The following lines are equivalent:\n"
543fc9c5412SJohannes Schauer            "    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
544fc9c5412SJohannes Schauer            "    -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
545fc9c5412SJohannes Schauer            "    QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
546fc9c5412SJohannes Schauer            "Note that if you provide several changes to a single variable\n"
547f5048cb7SEric Blake            "the last change will stay in effect.\n"
548f5048cb7SEric Blake            "\n"
549f5048cb7SEric Blake            QEMU_HELP_BOTTOM "\n");
550fc9c5412SJohannes Schauer 
551d03f9c32SMeador Inge     exit(exitcode);
552fc9c5412SJohannes Schauer }
553fc9c5412SJohannes Schauer 
554fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv)
555fc9c5412SJohannes Schauer {
556fc9c5412SJohannes Schauer     const char *r;
557fc9c5412SJohannes Schauer     int optind;
55842644ceeSJim Meyering     const struct qemu_argument *arginfo;
559fc9c5412SJohannes Schauer 
560fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
561fc9c5412SJohannes Schauer         if (arginfo->env == NULL) {
562fc9c5412SJohannes Schauer             continue;
563fc9c5412SJohannes Schauer         }
564fc9c5412SJohannes Schauer 
565fc9c5412SJohannes Schauer         r = getenv(arginfo->env);
566fc9c5412SJohannes Schauer         if (r != NULL) {
567fc9c5412SJohannes Schauer             arginfo->handle_opt(r);
568fc9c5412SJohannes Schauer         }
569fc9c5412SJohannes Schauer     }
570fc9c5412SJohannes Schauer 
571fc9c5412SJohannes Schauer     optind = 1;
572fc9c5412SJohannes Schauer     for (;;) {
573fc9c5412SJohannes Schauer         if (optind >= argc) {
574fc9c5412SJohannes Schauer             break;
575fc9c5412SJohannes Schauer         }
576fc9c5412SJohannes Schauer         r = argv[optind];
577fc9c5412SJohannes Schauer         if (r[0] != '-') {
578fc9c5412SJohannes Schauer             break;
579fc9c5412SJohannes Schauer         }
580fc9c5412SJohannes Schauer         optind++;
581fc9c5412SJohannes Schauer         r++;
582fc9c5412SJohannes Schauer         if (!strcmp(r, "-")) {
583fc9c5412SJohannes Schauer             break;
584fc9c5412SJohannes Schauer         }
585ba02577cSMeador Inge         /* Treat --foo the same as -foo.  */
586ba02577cSMeador Inge         if (r[0] == '-') {
587ba02577cSMeador Inge             r++;
588ba02577cSMeador Inge         }
589fc9c5412SJohannes Schauer 
590fc9c5412SJohannes Schauer         for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
591fc9c5412SJohannes Schauer             if (!strcmp(r, arginfo->argv)) {
5921386d4c0SPeter Maydell                 if (arginfo->has_arg) {
593fc9c5412SJohannes Schauer                     if (optind >= argc) {
594138940bfSMeador Inge                         (void) fprintf(stderr,
595138940bfSMeador Inge                             "qemu: missing argument for option '%s'\n", r);
5964d1275c2SRiku Voipio                         exit(EXIT_FAILURE);
597fc9c5412SJohannes Schauer                     }
598fc9c5412SJohannes Schauer                     arginfo->handle_opt(argv[optind]);
599fc9c5412SJohannes Schauer                     optind++;
6001386d4c0SPeter Maydell                 } else {
6011386d4c0SPeter Maydell                     arginfo->handle_opt(NULL);
602fc9c5412SJohannes Schauer                 }
603fc9c5412SJohannes Schauer                 break;
604fc9c5412SJohannes Schauer             }
605fc9c5412SJohannes Schauer         }
606fc9c5412SJohannes Schauer 
607fc9c5412SJohannes Schauer         /* no option matched the current argv */
608fc9c5412SJohannes Schauer         if (arginfo->handle_opt == NULL) {
609138940bfSMeador Inge             (void) fprintf(stderr, "qemu: unknown option '%s'\n", r);
6104d1275c2SRiku Voipio             exit(EXIT_FAILURE);
611fc9c5412SJohannes Schauer         }
612fc9c5412SJohannes Schauer     }
613fc9c5412SJohannes Schauer 
614fc9c5412SJohannes Schauer     if (optind >= argc) {
615138940bfSMeador Inge         (void) fprintf(stderr, "qemu: no user program specified\n");
6164d1275c2SRiku Voipio         exit(EXIT_FAILURE);
617fc9c5412SJohannes Schauer     }
618fc9c5412SJohannes Schauer 
619fc9c5412SJohannes Schauer     exec_path = argv[optind];
620fc9c5412SJohannes Schauer 
621fc9c5412SJohannes Schauer     return optind;
622fc9c5412SJohannes Schauer }
623fc9c5412SJohannes Schauer 
624902b3d5cSmalc int main(int argc, char **argv, char **envp)
62531e31b8aSbellard {
62601ffc75bSbellard     struct target_pt_regs regs1, *regs = &regs1;
62731e31b8aSbellard     struct image_info info1, *info = &info1;
628edf8e2afSMika Westerberg     struct linux_binprm bprm;
62948e15fc2SNathan Froyd     TaskState *ts;
6309349b4f9SAndreas Färber     CPUArchState *env;
631db6b81d4SAndreas Färber     CPUState *cpu;
632586314f2Sbellard     int optind;
63304a6dfebSaurel32     char **target_environ, **wrk;
6347d8cec95Saurel32     char **target_argv;
6357d8cec95Saurel32     int target_argc;
6367d8cec95Saurel32     int i;
637fd4d81ddSArnaud Patard     int ret;
63803cfd8faSLaurent Vivier     int execfd;
6394b25a506SJosh Kunz     int log_mask;
6408f67b9c6SRichard Henderson     unsigned long max_reserved_va;
6416e1c0d7bSLaurent Vivier     bool preserve_argv0;
64231e31b8aSbellard 
643f5852efaSChristophe Fergeau     error_init(argv[0]);
644fe4db84dSDaniel P. Berrange     module_call_init(MODULE_INIT_TRACE);
645267f685bSPaolo Bonzini     qemu_init_cpu_list();
646ce008c1fSAndreas Färber     module_call_init(MODULE_INIT_QOM);
647ce008c1fSAndreas Färber 
648ec45bbe5SSaurav Sachidanand     envlist = envlist_create();
64904a6dfebSaurel32 
65004a6dfebSaurel32     /* add current environment into the list */
65104a6dfebSaurel32     for (wrk = environ; *wrk != NULL; wrk++) {
65204a6dfebSaurel32         (void) envlist_setenv(envlist, *wrk);
65304a6dfebSaurel32     }
65404a6dfebSaurel32 
655703e0e89SRichard Henderson     /* Read the stack limit from the kernel.  If it's "unlimited",
656703e0e89SRichard Henderson        then we can do little else besides use the default.  */
657703e0e89SRichard Henderson     {
658703e0e89SRichard Henderson         struct rlimit lim;
659703e0e89SRichard Henderson         if (getrlimit(RLIMIT_STACK, &lim) == 0
66081bbe906Stakasi-y@ops.dti.ne.jp             && lim.rlim_cur != RLIM_INFINITY
66181bbe906Stakasi-y@ops.dti.ne.jp             && lim.rlim_cur == (target_long)lim.rlim_cur) {
662703e0e89SRichard Henderson             guest_stack_size = lim.rlim_cur;
663703e0e89SRichard Henderson         }
664703e0e89SRichard Henderson     }
665703e0e89SRichard Henderson 
666b1f9be31Sj_mayer     cpu_model = NULL;
667b5ec5ce0Sjohn cooper 
6686533dd6eSLluís Vilanova     qemu_add_opts(&qemu_trace_opts);
669f308f64eSLluís Vilanova     qemu_plugin_add_opts();
6706533dd6eSLluís Vilanova 
671fc9c5412SJohannes Schauer     optind = parse_args(argc, argv);
6724b5dfd82SPeter Maydell 
6734b25a506SJosh Kunz     log_mask = last_log_mask | (enable_strace ? LOG_STRACE : 0);
6744b25a506SJosh Kunz     if (log_mask) {
6754b25a506SJosh Kunz         qemu_log_needs_buffers();
6764b25a506SJosh Kunz         qemu_set_log(log_mask);
6774b25a506SJosh Kunz     }
6784b25a506SJosh Kunz 
6796533dd6eSLluís Vilanova     if (!trace_init_backends()) {
6806533dd6eSLluís Vilanova         exit(1);
6816533dd6eSLluís Vilanova     }
68292eecfffSPaolo Bonzini     trace_init_file();
6830572f558SPaolo Bonzini     qemu_plugin_load_list(&plugins, &error_fatal);
6846533dd6eSLluís Vilanova 
68531e31b8aSbellard     /* Zero out regs */
68601ffc75bSbellard     memset(regs, 0, sizeof(struct target_pt_regs));
68731e31b8aSbellard 
68831e31b8aSbellard     /* Zero out image_info */
68931e31b8aSbellard     memset(info, 0, sizeof(struct image_info));
69031e31b8aSbellard 
691edf8e2afSMika Westerberg     memset(&bprm, 0, sizeof (bprm));
692edf8e2afSMika Westerberg 
69374cd30b8Sbellard     /* Scan interp_prefix dir for replacement files. */
69474cd30b8Sbellard     init_paths(interp_prefix);
69574cd30b8Sbellard 
6964a24a758SPeter Maydell     init_qemu_uname_release();
6974a24a758SPeter Maydell 
6986e1c0d7bSLaurent Vivier     /*
6996e1c0d7bSLaurent Vivier      * Manage binfmt-misc open-binary flag
7006e1c0d7bSLaurent Vivier      */
701768fe76eSYunQiang Su     execfd = qemu_getauxval(AT_EXECFD);
702768fe76eSYunQiang Su     if (execfd == 0) {
7039d3019bcSLaurent Vivier         execfd = open(exec_path, O_RDONLY);
704768fe76eSYunQiang Su         if (execfd < 0) {
7059d3019bcSLaurent Vivier             printf("Error while loading %s: %s\n", exec_path, strerror(errno));
706768fe76eSYunQiang Su             _exit(EXIT_FAILURE);
707768fe76eSYunQiang Su         }
708768fe76eSYunQiang Su     }
709768fe76eSYunQiang Su 
7106e1c0d7bSLaurent Vivier     /*
7116e1c0d7bSLaurent Vivier      * get binfmt_misc flags
7126e1c0d7bSLaurent Vivier      */
7136e1c0d7bSLaurent Vivier     preserve_argv0 = !!(qemu_getauxval(AT_FLAGS) & AT_FLAGS_PRESERVE_ARGV0);
7146e1c0d7bSLaurent Vivier 
7156e1c0d7bSLaurent Vivier     /*
7166e1c0d7bSLaurent Vivier      * Manage binfmt-misc preserve-arg[0] flag
7176e1c0d7bSLaurent Vivier      *    argv[optind]     full path to the binary
7186e1c0d7bSLaurent Vivier      *    argv[optind + 1] original argv[0]
7196e1c0d7bSLaurent Vivier      */
7206e1c0d7bSLaurent Vivier     if (optind + 1 < argc && preserve_argv0) {
7216e1c0d7bSLaurent Vivier         optind++;
7226e1c0d7bSLaurent Vivier     }
7236e1c0d7bSLaurent Vivier 
72446027c07Sbellard     if (cpu_model == NULL) {
725768fe76eSYunQiang Su         cpu_model = cpu_get_model(get_elf_eflags(execfd));
726aaed909aSbellard     }
727c1c8cfe5SEduardo Habkost     cpu_type = parse_cpu_option(cpu_model);
7282278b939SIgor Mammedov 
7292b5249b8SIgor Mammedov     /* init tcg before creating CPUs and to get qemu_host_page_size */
730940e43aaSClaudio Fontana     {
731940e43aaSClaudio Fontana         AccelClass *ac = ACCEL_GET_CLASS(current_accel());
7322278b939SIgor Mammedov 
733b86f59c7SClaudio Fontana         accel_init_interfaces(ac);
73492242f34SClaudio Fontana         ac->init_machine(NULL);
735940e43aaSClaudio Fontana     }
7362278b939SIgor Mammedov     cpu = cpu_create(cpu_type);
7372994fd96SEduardo Habkost     env = cpu->env_ptr;
7380ac46af3SAndreas Färber     cpu_reset(cpu);
739db6b81d4SAndreas Färber     thread_cpu = cpu;
74054936004Sbellard 
7418f67b9c6SRichard Henderson     /*
7428f67b9c6SRichard Henderson      * Reserving too much vm space via mmap can run into problems
7438f67b9c6SRichard Henderson      * with rlimits, oom due to page table creation, etc.  We will
7448f67b9c6SRichard Henderson      * still try it, if directed by the command-line option, but
7458f67b9c6SRichard Henderson      * not by default.
7468f67b9c6SRichard Henderson      */
7478f67b9c6SRichard Henderson     max_reserved_va = MAX_RESERVED_VA(cpu);
7488f67b9c6SRichard Henderson     if (reserved_va != 0) {
7498f67b9c6SRichard Henderson         if (max_reserved_va && reserved_va > max_reserved_va) {
7508f67b9c6SRichard Henderson             fprintf(stderr, "Reserved virtual address too big\n");
7518f67b9c6SRichard Henderson             exit(EXIT_FAILURE);
7528f67b9c6SRichard Henderson         }
7538f67b9c6SRichard Henderson     } else if (HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32) {
7548f67b9c6SRichard Henderson         /*
7558f67b9c6SRichard Henderson          * reserved_va must be aligned with the host page size
7568f67b9c6SRichard Henderson          * as it is used with mmap()
7578f67b9c6SRichard Henderson          */
7588f67b9c6SRichard Henderson         reserved_va = max_reserved_va & qemu_host_page_mask;
7598f67b9c6SRichard Henderson     }
7608f67b9c6SRichard Henderson 
761a573e9baSRichard Henderson     {
762a573e9baSRichard Henderson         Error *err = NULL;
7635ebdd774SRichard Henderson         if (seed_optarg != NULL) {
764a573e9baSRichard Henderson             qemu_guest_random_seed_main(seed_optarg, &err);
765a573e9baSRichard Henderson         } else {
766a573e9baSRichard Henderson             qcrypto_init(&err);
767a573e9baSRichard Henderson         }
768a573e9baSRichard Henderson         if (err) {
769a573e9baSRichard Henderson             error_reportf_err(err, "cannot initialize crypto: ");
770a573e9baSRichard Henderson             exit(1);
771a573e9baSRichard Henderson         }
772c5e4a5a9SMagnus Reftel     }
773c5e4a5a9SMagnus Reftel 
77404a6dfebSaurel32     target_environ = envlist_to_environ(envlist, NULL);
77504a6dfebSaurel32     envlist_free(envlist);
776b12b6a18Sths 
777379f6698SPaul Brook     /*
778379f6698SPaul Brook      * Read in mmap_min_addr kernel parameter.  This value is used
779379f6698SPaul Brook      * When loading the ELF image to determine whether guest_base
78014f24e14SRichard Henderson      * is needed.  It is also used in mmap_find_vma.
781379f6698SPaul Brook      */
78214f24e14SRichard Henderson     {
783379f6698SPaul Brook         FILE *fp;
784379f6698SPaul Brook 
785379f6698SPaul Brook         if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
786379f6698SPaul Brook             unsigned long tmp;
787c9f80666SRichard Henderson             if (fscanf(fp, "%lu", &tmp) == 1 && tmp != 0) {
788379f6698SPaul Brook                 mmap_min_addr = tmp;
789c9f80666SRichard Henderson                 qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
790c9f80666SRichard Henderson                               mmap_min_addr);
791379f6698SPaul Brook             }
792379f6698SPaul Brook             fclose(fp);
793379f6698SPaul Brook         }
794379f6698SPaul Brook     }
795379f6698SPaul Brook 
7967d8cec95Saurel32     /*
797c9f80666SRichard Henderson      * We prefer to not make NULL pointers accessible to QEMU.
798c9f80666SRichard Henderson      * If we're in a chroot with no /proc, fall back to 1 page.
799c9f80666SRichard Henderson      */
800c9f80666SRichard Henderson     if (mmap_min_addr == 0) {
801c9f80666SRichard Henderson         mmap_min_addr = qemu_host_page_size;
802c9f80666SRichard Henderson         qemu_log_mask(CPU_LOG_PAGE,
803c9f80666SRichard Henderson                       "host mmap_min_addr=0x%lx (fallback)\n",
804c9f80666SRichard Henderson                       mmap_min_addr);
805c9f80666SRichard Henderson     }
806c9f80666SRichard Henderson 
807c9f80666SRichard Henderson     /*
8087d8cec95Saurel32      * Prepare copy of argv vector for target.
8097d8cec95Saurel32      */
8107d8cec95Saurel32     target_argc = argc - optind;
8117d8cec95Saurel32     target_argv = calloc(target_argc + 1, sizeof (char *));
8127d8cec95Saurel32     if (target_argv == NULL) {
8137d8cec95Saurel32         (void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
8144d1275c2SRiku Voipio         exit(EXIT_FAILURE);
8157d8cec95Saurel32     }
8167d8cec95Saurel32 
8177d8cec95Saurel32     /*
8187d8cec95Saurel32      * If argv0 is specified (using '-0' switch) we replace
8197d8cec95Saurel32      * argv[0] pointer with the given one.
8207d8cec95Saurel32      */
8217d8cec95Saurel32     i = 0;
8227d8cec95Saurel32     if (argv0 != NULL) {
8237d8cec95Saurel32         target_argv[i++] = strdup(argv0);
8247d8cec95Saurel32     }
8257d8cec95Saurel32     for (; i < target_argc; i++) {
8267d8cec95Saurel32         target_argv[i] = strdup(argv[optind + i]);
8277d8cec95Saurel32     }
8287d8cec95Saurel32     target_argv[target_argc] = NULL;
8297d8cec95Saurel32 
830c78d65e8SMarkus Armbruster     ts = g_new0(TaskState, 1);
831edf8e2afSMika Westerberg     init_task_state(ts);
832edf8e2afSMika Westerberg     /* build Task State */
833edf8e2afSMika Westerberg     ts->info = info;
834edf8e2afSMika Westerberg     ts->bprm = &bprm;
8350429a971SAndreas Färber     cpu->opaque = ts;
836edf8e2afSMika Westerberg     task_settid(ts);
837edf8e2afSMika Westerberg 
838c093364fSOwen Anderson     fd_trans_init();
839c093364fSOwen Anderson 
8409d3019bcSLaurent Vivier     ret = loader_exec(execfd, exec_path, target_argv, target_environ, regs,
841fd4d81ddSArnaud Patard         info, &bprm);
842fd4d81ddSArnaud Patard     if (ret != 0) {
8439d3019bcSLaurent Vivier         printf("Error while loading %s: %s\n", exec_path, strerror(-ret));
8444d1275c2SRiku Voipio         _exit(EXIT_FAILURE);
84531e31b8aSbellard     }
84631e31b8aSbellard 
847b12b6a18Sths     for (wrk = target_environ; *wrk; wrk++) {
848ec45bbe5SSaurav Sachidanand         g_free(*wrk);
849b12b6a18Sths     }
850b12b6a18Sths 
851ec45bbe5SSaurav Sachidanand     g_free(target_environ);
852b12b6a18Sths 
85313829020SPaolo Bonzini     if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
8545ca870b9SRichard Henderson         qemu_log("guest_base  %p\n", (void *)guest_base);
85510d0d505SAlex Bennée         log_page_dump("binary load");
85654936004Sbellard 
85793fcfe39Saliguori         qemu_log("start_brk   0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
85893fcfe39Saliguori         qemu_log("end_code    0x" TARGET_ABI_FMT_lx "\n", info->end_code);
8597c4ee5bcSRichard Henderson         qemu_log("start_code  0x" TARGET_ABI_FMT_lx "\n", info->start_code);
8607c4ee5bcSRichard Henderson         qemu_log("start_data  0x" TARGET_ABI_FMT_lx "\n", info->start_data);
86193fcfe39Saliguori         qemu_log("end_data    0x" TARGET_ABI_FMT_lx "\n", info->end_data);
8627c4ee5bcSRichard Henderson         qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n", info->start_stack);
86393fcfe39Saliguori         qemu_log("brk         0x" TARGET_ABI_FMT_lx "\n", info->brk);
86493fcfe39Saliguori         qemu_log("entry       0x" TARGET_ABI_FMT_lx "\n", info->entry);
8657c4ee5bcSRichard Henderson         qemu_log("argv_start  0x" TARGET_ABI_FMT_lx "\n", info->arg_start);
8667c4ee5bcSRichard Henderson         qemu_log("env_start   0x" TARGET_ABI_FMT_lx "\n",
8677c4ee5bcSRichard Henderson                  info->arg_end + (abi_ulong)sizeof(abi_ulong));
8687c4ee5bcSRichard Henderson         qemu_log("auxv_start  0x" TARGET_ABI_FMT_lx "\n", info->saved_auxv);
8692e77eac6Sblueswir1     }
87031e31b8aSbellard 
87153a5960aSpbrook     target_set_brk(info->brk);
87231e31b8aSbellard     syscall_init();
87366fb9763Sbellard     signal_init();
87431e31b8aSbellard 
8759002ec79SRichard Henderson     /* Now that we've loaded the binary, GUEST_BASE is fixed.  Delay
8769002ec79SRichard Henderson        generating the prologue until now so that the prologue can take
8779002ec79SRichard Henderson        the real value of GUEST_BASE into account.  */
878b1311c4aSEmilio G. Cota     tcg_prologue_init(tcg_ctx);
8799002ec79SRichard Henderson 
880cd71c089SLaurent Vivier     target_cpu_copy_regs(env, regs);
881cd71c089SLaurent Vivier 
882fcedd920SAlex Bennée     if (gdbstub) {
883fcedd920SAlex Bennée         if (gdbserver_start(gdbstub) < 0) {
884fcedd920SAlex Bennée             fprintf(stderr, "qemu: could not open gdbserver on %s\n",
885fcedd920SAlex Bennée                     gdbstub);
8864d1275c2SRiku Voipio             exit(EXIT_FAILURE);
887ff7a981aSPeter Maydell         }
888db6b81d4SAndreas Färber         gdb_handlesig(cpu, 0);
8891fddef4bSbellard     }
8901b6b029eSbellard     cpu_loop(env);
8911b6b029eSbellard     /* never exits */
89231e31b8aSbellard     return 0;
89331e31b8aSbellard }
894