xref: /qemu/linux-user/main.c (revision a8d25326)
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"
21*a8d25326SMarkus Armbruster #include "qemu-common.h"
22b52713c1SPhilippe Mathieu-Daudé #include "qemu/units.h"
2314a48c1dSMarkus Armbruster #include "sysemu/tcg.h"
2467a1de0dSFam Zheng #include "qemu-version.h"
25edf8e2afSMika Westerberg #include <sys/syscall.h>
26703e0e89SRichard Henderson #include <sys/resource.h>
2731e31b8aSbellard 
28daa76aa4SMarkus Armbruster #include "qapi/error.h"
293ef693a0Sbellard #include "qemu.h"
30f348b6d1SVeronia Bahaa #include "qemu/path.h"
316533dd6eSLluís Vilanova #include "qemu/config-file.h"
32f348b6d1SVeronia Bahaa #include "qemu/cutils.h"
33f5852efaSChristophe Fergeau #include "qemu/error-report.h"
34f348b6d1SVeronia Bahaa #include "qemu/help_option.h"
350b8fa32fSMarkus Armbruster #include "qemu/module.h"
362b41f10eSBlue Swirl #include "cpu.h"
3763c91552SPaolo Bonzini #include "exec/exec-all.h"
389002ec79SRichard Henderson #include "tcg.h"
391de7afc9SPaolo Bonzini #include "qemu/timer.h"
401de7afc9SPaolo Bonzini #include "qemu/envlist.h"
415ebdd774SRichard Henderson #include "qemu/guest-random.h"
42d8fd2954SPaul Brook #include "elf.h"
436533dd6eSLluís Vilanova #include "trace/control.h"
44542ca434SLaurent Vivier #include "target_elf.h"
45cd71c089SLaurent Vivier #include "cpu_loop-common.h"
46a573e9baSRichard Henderson #include "crypto/init.h"
4704a6dfebSaurel32 
48d088d664Saurel32 char *exec_path;
49d088d664Saurel32 
501b530a6dSaurel32 int singlestep;
518cb76755SStefan Weil static const char *filename;
528cb76755SStefan Weil static const char *argv0;
538cb76755SStefan Weil static int gdbstub_port;
548cb76755SStefan Weil static envlist_t *envlist;
5551fb256aSAndreas Färber static const char *cpu_model;
562278b939SIgor Mammedov static const char *cpu_type;
575ebdd774SRichard Henderson static const char *seed_optarg;
58379f6698SPaul Brook unsigned long mmap_min_addr;
59379f6698SPaul Brook unsigned long guest_base;
60379f6698SPaul Brook int have_guest_base;
61120a9848SPaolo Bonzini 
62288e65b9SAlexander Graf /*
63288e65b9SAlexander Graf  * When running 32-on-64 we should make sure we can fit all of the possible
64288e65b9SAlexander Graf  * guest address space into a contiguous chunk of virtual host memory.
65288e65b9SAlexander Graf  *
66288e65b9SAlexander Graf  * This way we will never overlap with our own libraries or binaries or stack
67288e65b9SAlexander Graf  * or anything else that QEMU maps.
6818e80c55SRichard Henderson  *
6918e80c55SRichard Henderson  * Many cpus reserve the high bit (or more than one for some 64-bit cpus)
7018e80c55SRichard Henderson  * of the address for the kernel.  Some cpus rely on this and user space
7118e80c55SRichard Henderson  * uses the high bit(s) for pointer tagging and the like.  For them, we
7218e80c55SRichard Henderson  * must preserve the expected address space.
73288e65b9SAlexander Graf  */
7418e80c55SRichard Henderson #ifndef MAX_RESERVED_VA
7518e80c55SRichard Henderson # if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
7618e80c55SRichard Henderson #  if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
7718e80c55SRichard Henderson       (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
7818e80c55SRichard Henderson /* There are a number of places where we assign reserved_va to a variable
7918e80c55SRichard Henderson    of type abi_ulong and expect it to fit.  Avoid the last page.  */
8018e80c55SRichard Henderson #   define MAX_RESERVED_VA  (0xfffffffful & TARGET_PAGE_MASK)
81314992b1SAlexander Graf #  else
8218e80c55SRichard Henderson #   define MAX_RESERVED_VA  (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
83314992b1SAlexander Graf #  endif
84288e65b9SAlexander Graf # else
8518e80c55SRichard Henderson #  define MAX_RESERVED_VA  0
8618e80c55SRichard Henderson # endif
8718e80c55SRichard Henderson #endif
8818e80c55SRichard Henderson 
8968a1c816SPaul Brook unsigned long reserved_va;
901b530a6dSaurel32 
91d03f9c32SMeador Inge static void usage(int exitcode);
92fc9c5412SJohannes Schauer 
937ee2822cSPaolo Bonzini static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
94e586822aSRiku Voipio const char *qemu_uname_release;
95586314f2Sbellard 
969de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
979de5e440Sbellard    we allocate a bigger stack. Need a better solution, for example
989de5e440Sbellard    by remapping the process stack directly at the right place */
99703e0e89SRichard Henderson unsigned long guest_stack_size = 8 * 1024 * 1024UL;
10031e31b8aSbellard 
10131e31b8aSbellard void gemu_log(const char *fmt, ...)
10231e31b8aSbellard {
10331e31b8aSbellard     va_list ap;
10431e31b8aSbellard 
10531e31b8aSbellard     va_start(ap, fmt);
10631e31b8aSbellard     vfprintf(stderr, fmt, ap);
10731e31b8aSbellard     va_end(ap);
10831e31b8aSbellard }
10931e31b8aSbellard 
1108fcd3692Sblueswir1 #if defined(TARGET_I386)
11105390248SAndreas Färber int cpu_get_pic_interrupt(CPUX86State *env)
11292ccca6aSbellard {
11392ccca6aSbellard     return -1;
11492ccca6aSbellard }
1158fcd3692Sblueswir1 #endif
11692ccca6aSbellard 
117d5975363Spbrook /***********************************************************/
118d5975363Spbrook /* Helper routines for implementing atomic operations.  */
119d5975363Spbrook 
120d5975363Spbrook /* Make sure everything is in a consistent state for calling fork().  */
121d5975363Spbrook void fork_start(void)
122d5975363Spbrook {
12306065c45SPeter Maydell     start_exclusive();
124d032d1b4SRiku Voipio     mmap_fork_start();
125024949caSPeter Maydell     cpu_list_lock();
126d5975363Spbrook }
127d5975363Spbrook 
128d5975363Spbrook void fork_end(int child)
129d5975363Spbrook {
130d032d1b4SRiku Voipio     mmap_fork_end(child);
131d5975363Spbrook     if (child) {
132bdc44640SAndreas Färber         CPUState *cpu, *next_cpu;
133d5975363Spbrook         /* Child processes created by fork() only have a single thread.
134d5975363Spbrook            Discard information about the parent threads.  */
135bdc44640SAndreas Färber         CPU_FOREACH_SAFE(cpu, next_cpu) {
136bdc44640SAndreas Färber             if (cpu != thread_cpu) {
137068a5ea0SEmilio G. Cota                 QTAILQ_REMOVE_RCU(&cpus, cpu, node);
138bdc44640SAndreas Färber             }
139bdc44640SAndreas Färber         }
140267f685bSPaolo Bonzini         qemu_init_cpu_list();
141f7ec7f7bSPeter Crosthwaite         gdbserver_fork(thread_cpu);
14206065c45SPeter Maydell         /* qemu_init_cpu_list() takes care of reinitializing the
14306065c45SPeter Maydell          * exclusive state, so we don't need to end_exclusive() here.
14406065c45SPeter Maydell          */
145d5975363Spbrook     } else {
146267f685bSPaolo Bonzini         cpu_list_unlock();
14706065c45SPeter Maydell         end_exclusive();
148d5975363Spbrook     }
149d5975363Spbrook }
150d5975363Spbrook 
151b44316fbSPeter Maydell __thread CPUState *thread_cpu;
15259faf6d6Sbellard 
153178f9429SSergey Fedorov bool qemu_cpu_is_self(CPUState *cpu)
154178f9429SSergey Fedorov {
155178f9429SSergey Fedorov     return thread_cpu == cpu;
156178f9429SSergey Fedorov }
157178f9429SSergey Fedorov 
158178f9429SSergey Fedorov void qemu_cpu_kick(CPUState *cpu)
159178f9429SSergey Fedorov {
160178f9429SSergey Fedorov     cpu_exit(cpu);
161178f9429SSergey Fedorov }
162178f9429SSergey Fedorov 
163edf8e2afSMika Westerberg void task_settid(TaskState *ts)
164edf8e2afSMika Westerberg {
165edf8e2afSMika Westerberg     if (ts->ts_tid == 0) {
166edf8e2afSMika Westerberg         ts->ts_tid = (pid_t)syscall(SYS_gettid);
167edf8e2afSMika Westerberg     }
168edf8e2afSMika Westerberg }
169edf8e2afSMika Westerberg 
170edf8e2afSMika Westerberg void stop_all_tasks(void)
171edf8e2afSMika Westerberg {
172edf8e2afSMika Westerberg     /*
173edf8e2afSMika Westerberg      * We trust that when using NPTL, start_exclusive()
174edf8e2afSMika Westerberg      * handles thread stopping correctly.
175edf8e2afSMika Westerberg      */
176edf8e2afSMika Westerberg     start_exclusive();
177edf8e2afSMika Westerberg }
178edf8e2afSMika Westerberg 
179c3a92833Spbrook /* Assumes contents are already zeroed.  */
180624f7979Spbrook void init_task_state(TaskState *ts)
181624f7979Spbrook {
182624f7979Spbrook     ts->used = 1;
183624f7979Spbrook }
1849de5e440Sbellard 
18530ba0ee5SAndreas Färber CPUArchState *cpu_copy(CPUArchState *env)
18630ba0ee5SAndreas Färber {
18729a0af61SRichard Henderson     CPUState *cpu = env_cpu(env);
1882278b939SIgor Mammedov     CPUState *new_cpu = cpu_create(cpu_type);
18961c7480fSLeon Alrae     CPUArchState *new_env = new_cpu->env_ptr;
19030ba0ee5SAndreas Färber     CPUBreakpoint *bp;
19130ba0ee5SAndreas Färber     CPUWatchpoint *wp;
19230ba0ee5SAndreas Färber 
19330ba0ee5SAndreas Färber     /* Reset non arch specific state */
19475a34036SAndreas Färber     cpu_reset(new_cpu);
19530ba0ee5SAndreas Färber 
19630ba0ee5SAndreas Färber     memcpy(new_env, env, sizeof(CPUArchState));
19730ba0ee5SAndreas Färber 
19830ba0ee5SAndreas Färber     /* Clone all break/watchpoints.
19930ba0ee5SAndreas Färber        Note: Once we support ptrace with hw-debug register access, make sure
20030ba0ee5SAndreas Färber        BP_CPU break/watchpoints are handled correctly on clone. */
2011d085f6cSThierry Bultel     QTAILQ_INIT(&new_cpu->breakpoints);
2021d085f6cSThierry Bultel     QTAILQ_INIT(&new_cpu->watchpoints);
203f0c3c505SAndreas Färber     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
204b3310ab3SAndreas Färber         cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL);
20530ba0ee5SAndreas Färber     }
206ff4700b0SAndreas Färber     QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
20705068c0dSPeter Maydell         cpu_watchpoint_insert(new_cpu, wp->vaddr, wp->len, wp->flags, NULL);
20830ba0ee5SAndreas Färber     }
20930ba0ee5SAndreas Färber 
21030ba0ee5SAndreas Färber     return new_env;
21130ba0ee5SAndreas Färber }
21230ba0ee5SAndreas Färber 
213fc9c5412SJohannes Schauer static void handle_arg_help(const char *arg)
214fc9c5412SJohannes Schauer {
2154d1275c2SRiku Voipio     usage(EXIT_SUCCESS);
216fc9c5412SJohannes Schauer }
217fc9c5412SJohannes Schauer 
218fc9c5412SJohannes Schauer static void handle_arg_log(const char *arg)
219fc9c5412SJohannes Schauer {
220fc9c5412SJohannes Schauer     int mask;
221fc9c5412SJohannes Schauer 
2224fde1ebaSPeter Maydell     mask = qemu_str_to_log_mask(arg);
223fc9c5412SJohannes Schauer     if (!mask) {
22459a6fa6eSPeter Maydell         qemu_print_log_usage(stdout);
2254d1275c2SRiku Voipio         exit(EXIT_FAILURE);
226fc9c5412SJohannes Schauer     }
227f2937a33SPaolo Bonzini     qemu_log_needs_buffers();
22824537a01SPeter Maydell     qemu_set_log(mask);
229fc9c5412SJohannes Schauer }
230fc9c5412SJohannes Schauer 
2318423fa90SAlex Bennée static void handle_arg_dfilter(const char *arg)
2328423fa90SAlex Bennée {
2338423fa90SAlex Bennée     qemu_set_dfilter_ranges(arg, NULL);
2348423fa90SAlex Bennée }
2358423fa90SAlex Bennée 
23650171d42S陳韋任 static void handle_arg_log_filename(const char *arg)
23750171d42S陳韋任 {
238daa76aa4SMarkus Armbruster     qemu_set_log_filename(arg, &error_fatal);
23950171d42S陳韋任 }
24050171d42S陳韋任 
241fc9c5412SJohannes Schauer static void handle_arg_set_env(const char *arg)
242fc9c5412SJohannes Schauer {
243fc9c5412SJohannes Schauer     char *r, *p, *token;
244fc9c5412SJohannes Schauer     r = p = strdup(arg);
245fc9c5412SJohannes Schauer     while ((token = strsep(&p, ",")) != NULL) {
246fc9c5412SJohannes Schauer         if (envlist_setenv(envlist, token) != 0) {
2474d1275c2SRiku Voipio             usage(EXIT_FAILURE);
248fc9c5412SJohannes Schauer         }
249fc9c5412SJohannes Schauer     }
250fc9c5412SJohannes Schauer     free(r);
251fc9c5412SJohannes Schauer }
252fc9c5412SJohannes Schauer 
253fc9c5412SJohannes Schauer static void handle_arg_unset_env(const char *arg)
254fc9c5412SJohannes Schauer {
255fc9c5412SJohannes Schauer     char *r, *p, *token;
256fc9c5412SJohannes Schauer     r = p = strdup(arg);
257fc9c5412SJohannes Schauer     while ((token = strsep(&p, ",")) != NULL) {
258fc9c5412SJohannes Schauer         if (envlist_unsetenv(envlist, token) != 0) {
2594d1275c2SRiku Voipio             usage(EXIT_FAILURE);
260fc9c5412SJohannes Schauer         }
261fc9c5412SJohannes Schauer     }
262fc9c5412SJohannes Schauer     free(r);
263fc9c5412SJohannes Schauer }
264fc9c5412SJohannes Schauer 
265fc9c5412SJohannes Schauer static void handle_arg_argv0(const char *arg)
266fc9c5412SJohannes Schauer {
267fc9c5412SJohannes Schauer     argv0 = strdup(arg);
268fc9c5412SJohannes Schauer }
269fc9c5412SJohannes Schauer 
270fc9c5412SJohannes Schauer static void handle_arg_stack_size(const char *arg)
271fc9c5412SJohannes Schauer {
272fc9c5412SJohannes Schauer     char *p;
273fc9c5412SJohannes Schauer     guest_stack_size = strtoul(arg, &p, 0);
274fc9c5412SJohannes Schauer     if (guest_stack_size == 0) {
2754d1275c2SRiku Voipio         usage(EXIT_FAILURE);
276fc9c5412SJohannes Schauer     }
277fc9c5412SJohannes Schauer 
278fc9c5412SJohannes Schauer     if (*p == 'M') {
279b52713c1SPhilippe Mathieu-Daudé         guest_stack_size *= MiB;
280fc9c5412SJohannes Schauer     } else if (*p == 'k' || *p == 'K') {
281b52713c1SPhilippe Mathieu-Daudé         guest_stack_size *= KiB;
282fc9c5412SJohannes Schauer     }
283fc9c5412SJohannes Schauer }
284fc9c5412SJohannes Schauer 
285fc9c5412SJohannes Schauer static void handle_arg_ld_prefix(const char *arg)
286fc9c5412SJohannes Schauer {
287fc9c5412SJohannes Schauer     interp_prefix = strdup(arg);
288fc9c5412SJohannes Schauer }
289fc9c5412SJohannes Schauer 
290fc9c5412SJohannes Schauer static void handle_arg_pagesize(const char *arg)
291fc9c5412SJohannes Schauer {
292fc9c5412SJohannes Schauer     qemu_host_page_size = atoi(arg);
293fc9c5412SJohannes Schauer     if (qemu_host_page_size == 0 ||
294fc9c5412SJohannes Schauer         (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
295fc9c5412SJohannes Schauer         fprintf(stderr, "page size must be a power of two\n");
2964d1275c2SRiku Voipio         exit(EXIT_FAILURE);
297fc9c5412SJohannes Schauer     }
298fc9c5412SJohannes Schauer }
299fc9c5412SJohannes Schauer 
3005ebdd774SRichard Henderson static void handle_arg_seed(const char *arg)
301c5e4a5a9SMagnus Reftel {
3025ebdd774SRichard Henderson     seed_optarg = arg;
303c5e4a5a9SMagnus Reftel }
304c5e4a5a9SMagnus Reftel 
305fc9c5412SJohannes Schauer static void handle_arg_gdb(const char *arg)
306fc9c5412SJohannes Schauer {
307fc9c5412SJohannes Schauer     gdbstub_port = atoi(arg);
308fc9c5412SJohannes Schauer }
309fc9c5412SJohannes Schauer 
310fc9c5412SJohannes Schauer static void handle_arg_uname(const char *arg)
311fc9c5412SJohannes Schauer {
312fc9c5412SJohannes Schauer     qemu_uname_release = strdup(arg);
313fc9c5412SJohannes Schauer }
314fc9c5412SJohannes Schauer 
315fc9c5412SJohannes Schauer static void handle_arg_cpu(const char *arg)
316fc9c5412SJohannes Schauer {
317fc9c5412SJohannes Schauer     cpu_model = strdup(arg);
318c8057f95SPeter Maydell     if (cpu_model == NULL || is_help_option(cpu_model)) {
319fc9c5412SJohannes Schauer         /* XXX: implement xxx_cpu_list for targets that still miss it */
320e916cbf8SPeter Maydell #if defined(cpu_list)
3210442428aSMarkus Armbruster         cpu_list();
322fc9c5412SJohannes Schauer #endif
3234d1275c2SRiku Voipio         exit(EXIT_FAILURE);
324fc9c5412SJohannes Schauer     }
325fc9c5412SJohannes Schauer }
326fc9c5412SJohannes Schauer 
327fc9c5412SJohannes Schauer static void handle_arg_guest_base(const char *arg)
328fc9c5412SJohannes Schauer {
329fc9c5412SJohannes Schauer     guest_base = strtol(arg, NULL, 0);
330fc9c5412SJohannes Schauer     have_guest_base = 1;
331fc9c5412SJohannes Schauer }
332fc9c5412SJohannes Schauer 
333fc9c5412SJohannes Schauer static void handle_arg_reserved_va(const char *arg)
334fc9c5412SJohannes Schauer {
335fc9c5412SJohannes Schauer     char *p;
336fc9c5412SJohannes Schauer     int shift = 0;
337fc9c5412SJohannes Schauer     reserved_va = strtoul(arg, &p, 0);
338fc9c5412SJohannes Schauer     switch (*p) {
339fc9c5412SJohannes Schauer     case 'k':
340fc9c5412SJohannes Schauer     case 'K':
341fc9c5412SJohannes Schauer         shift = 10;
342fc9c5412SJohannes Schauer         break;
343fc9c5412SJohannes Schauer     case 'M':
344fc9c5412SJohannes Schauer         shift = 20;
345fc9c5412SJohannes Schauer         break;
346fc9c5412SJohannes Schauer     case 'G':
347fc9c5412SJohannes Schauer         shift = 30;
348fc9c5412SJohannes Schauer         break;
349fc9c5412SJohannes Schauer     }
350fc9c5412SJohannes Schauer     if (shift) {
351fc9c5412SJohannes Schauer         unsigned long unshifted = reserved_va;
352fc9c5412SJohannes Schauer         p++;
353fc9c5412SJohannes Schauer         reserved_va <<= shift;
35418e80c55SRichard Henderson         if (reserved_va >> shift != unshifted
35518e80c55SRichard Henderson             || (MAX_RESERVED_VA && reserved_va > MAX_RESERVED_VA)) {
356fc9c5412SJohannes Schauer             fprintf(stderr, "Reserved virtual address too big\n");
3574d1275c2SRiku Voipio             exit(EXIT_FAILURE);
358fc9c5412SJohannes Schauer         }
359fc9c5412SJohannes Schauer     }
360fc9c5412SJohannes Schauer     if (*p) {
361fc9c5412SJohannes Schauer         fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
3624d1275c2SRiku Voipio         exit(EXIT_FAILURE);
363fc9c5412SJohannes Schauer     }
364fc9c5412SJohannes Schauer }
365fc9c5412SJohannes Schauer 
366fc9c5412SJohannes Schauer static void handle_arg_singlestep(const char *arg)
367fc9c5412SJohannes Schauer {
368fc9c5412SJohannes Schauer     singlestep = 1;
369fc9c5412SJohannes Schauer }
370fc9c5412SJohannes Schauer 
371fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg)
372fc9c5412SJohannes Schauer {
373fc9c5412SJohannes Schauer     do_strace = 1;
374fc9c5412SJohannes Schauer }
375fc9c5412SJohannes Schauer 
376fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg)
377fc9c5412SJohannes Schauer {
3787e563bfbSThomas Huth     printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION
3790781dd6eSThomas Huth            "\n" QEMU_COPYRIGHT "\n");
3804d1275c2SRiku Voipio     exit(EXIT_SUCCESS);
381fc9c5412SJohannes Schauer }
382fc9c5412SJohannes Schauer 
3836533dd6eSLluís Vilanova static char *trace_file;
3846533dd6eSLluís Vilanova static void handle_arg_trace(const char *arg)
3856533dd6eSLluís Vilanova {
3866533dd6eSLluís Vilanova     g_free(trace_file);
3876533dd6eSLluís Vilanova     trace_file = trace_opt_parse(arg);
3886533dd6eSLluís Vilanova }
3896533dd6eSLluís Vilanova 
390fc9c5412SJohannes Schauer struct qemu_argument {
391fc9c5412SJohannes Schauer     const char *argv;
392fc9c5412SJohannes Schauer     const char *env;
393fc9c5412SJohannes Schauer     bool has_arg;
394fc9c5412SJohannes Schauer     void (*handle_opt)(const char *arg);
395fc9c5412SJohannes Schauer     const char *example;
396fc9c5412SJohannes Schauer     const char *help;
397fc9c5412SJohannes Schauer };
398fc9c5412SJohannes Schauer 
39942644ceeSJim Meyering static const struct qemu_argument arg_table[] = {
400fc9c5412SJohannes Schauer     {"h",          "",                 false, handle_arg_help,
401fc9c5412SJohannes Schauer      "",           "print this help"},
402daaf8c8eSMeador Inge     {"help",       "",                 false, handle_arg_help,
403daaf8c8eSMeador Inge      "",           ""},
404fc9c5412SJohannes Schauer     {"g",          "QEMU_GDB",         true,  handle_arg_gdb,
405fc9c5412SJohannes Schauer      "port",       "wait gdb connection to 'port'"},
406fc9c5412SJohannes Schauer     {"L",          "QEMU_LD_PREFIX",   true,  handle_arg_ld_prefix,
407fc9c5412SJohannes Schauer      "path",       "set the elf interpreter prefix to 'path'"},
408fc9c5412SJohannes Schauer     {"s",          "QEMU_STACK_SIZE",  true,  handle_arg_stack_size,
409fc9c5412SJohannes Schauer      "size",       "set the stack size to 'size' bytes"},
410fc9c5412SJohannes Schauer     {"cpu",        "QEMU_CPU",         true,  handle_arg_cpu,
411c8057f95SPeter Maydell      "model",      "select CPU (-cpu help for list)"},
412fc9c5412SJohannes Schauer     {"E",          "QEMU_SET_ENV",     true,  handle_arg_set_env,
413fc9c5412SJohannes Schauer      "var=value",  "sets targets environment variable (see below)"},
414fc9c5412SJohannes Schauer     {"U",          "QEMU_UNSET_ENV",   true,  handle_arg_unset_env,
415fc9c5412SJohannes Schauer      "var",        "unsets targets environment variable (see below)"},
416fc9c5412SJohannes Schauer     {"0",          "QEMU_ARGV0",       true,  handle_arg_argv0,
417fc9c5412SJohannes Schauer      "argv0",      "forces target process argv[0] to be 'argv0'"},
418fc9c5412SJohannes Schauer     {"r",          "QEMU_UNAME",       true,  handle_arg_uname,
419fc9c5412SJohannes Schauer      "uname",      "set qemu uname release string to 'uname'"},
420fc9c5412SJohannes Schauer     {"B",          "QEMU_GUEST_BASE",  true,  handle_arg_guest_base,
421fc9c5412SJohannes Schauer      "address",    "set guest_base address to 'address'"},
422fc9c5412SJohannes Schauer     {"R",          "QEMU_RESERVED_VA", true,  handle_arg_reserved_va,
423fc9c5412SJohannes Schauer      "size",       "reserve 'size' bytes for guest virtual address space"},
424fc9c5412SJohannes Schauer     {"d",          "QEMU_LOG",         true,  handle_arg_log,
425989b697dSPeter Maydell      "item[,...]", "enable logging of specified items "
426989b697dSPeter Maydell      "(use '-d help' for a list of items)"},
4278423fa90SAlex Bennée     {"dfilter",    "QEMU_DFILTER",     true,  handle_arg_dfilter,
4288423fa90SAlex Bennée      "range[,...]","filter logging based on address range"},
42950171d42S陳韋任     {"D",          "QEMU_LOG_FILENAME", true, handle_arg_log_filename,
430989b697dSPeter Maydell      "logfile",     "write logs to 'logfile' (default stderr)"},
431fc9c5412SJohannes Schauer     {"p",          "QEMU_PAGESIZE",    true,  handle_arg_pagesize,
432fc9c5412SJohannes Schauer      "pagesize",   "set the host page size to 'pagesize'"},
433fc9c5412SJohannes Schauer     {"singlestep", "QEMU_SINGLESTEP",  false, handle_arg_singlestep,
434fc9c5412SJohannes Schauer      "",           "run in singlestep mode"},
435fc9c5412SJohannes Schauer     {"strace",     "QEMU_STRACE",      false, handle_arg_strace,
436fc9c5412SJohannes Schauer      "",           "log system calls"},
4375ebdd774SRichard Henderson     {"seed",       "QEMU_RAND_SEED",   true,  handle_arg_seed,
438c5e4a5a9SMagnus Reftel      "",           "Seed for pseudo-random number generator"},
4396533dd6eSLluís Vilanova     {"trace",      "QEMU_TRACE",       true,  handle_arg_trace,
4406533dd6eSLluís Vilanova      "",           "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
441fc9c5412SJohannes Schauer     {"version",    "QEMU_VERSION",     false, handle_arg_version,
4421386d4c0SPeter Maydell      "",           "display version information and exit"},
443fc9c5412SJohannes Schauer     {NULL, NULL, false, NULL, NULL, NULL}
444fc9c5412SJohannes Schauer };
445fc9c5412SJohannes Schauer 
446d03f9c32SMeador Inge static void usage(int exitcode)
447fc9c5412SJohannes Schauer {
44842644ceeSJim Meyering     const struct qemu_argument *arginfo;
449fc9c5412SJohannes Schauer     int maxarglen;
450fc9c5412SJohannes Schauer     int maxenvlen;
451fc9c5412SJohannes Schauer 
4522e59915dSPaolo Bonzini     printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
4532e59915dSPaolo Bonzini            "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n"
454fc9c5412SJohannes Schauer            "\n"
455fc9c5412SJohannes Schauer            "Options and associated environment variables:\n"
456fc9c5412SJohannes Schauer            "\n");
457fc9c5412SJohannes Schauer 
45863ec54d7SPeter Maydell     /* Calculate column widths. We must always have at least enough space
45963ec54d7SPeter Maydell      * for the column header.
46063ec54d7SPeter Maydell      */
46163ec54d7SPeter Maydell     maxarglen = strlen("Argument");
46263ec54d7SPeter Maydell     maxenvlen = strlen("Env-variable");
463fc9c5412SJohannes Schauer 
464fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
46563ec54d7SPeter Maydell         int arglen = strlen(arginfo->argv);
46663ec54d7SPeter Maydell         if (arginfo->has_arg) {
46763ec54d7SPeter Maydell             arglen += strlen(arginfo->example) + 1;
46863ec54d7SPeter Maydell         }
469fc9c5412SJohannes Schauer         if (strlen(arginfo->env) > maxenvlen) {
470fc9c5412SJohannes Schauer             maxenvlen = strlen(arginfo->env);
471fc9c5412SJohannes Schauer         }
47263ec54d7SPeter Maydell         if (arglen > maxarglen) {
47363ec54d7SPeter Maydell             maxarglen = arglen;
474fc9c5412SJohannes Schauer         }
475fc9c5412SJohannes Schauer     }
476fc9c5412SJohannes Schauer 
47763ec54d7SPeter Maydell     printf("%-*s %-*s Description\n", maxarglen+1, "Argument",
47863ec54d7SPeter Maydell             maxenvlen, "Env-variable");
479fc9c5412SJohannes Schauer 
480fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
481fc9c5412SJohannes Schauer         if (arginfo->has_arg) {
482fc9c5412SJohannes Schauer             printf("-%s %-*s %-*s %s\n", arginfo->argv,
48363ec54d7SPeter Maydell                    (int)(maxarglen - strlen(arginfo->argv) - 1),
48463ec54d7SPeter Maydell                    arginfo->example, maxenvlen, arginfo->env, arginfo->help);
485fc9c5412SJohannes Schauer         } else {
48663ec54d7SPeter Maydell             printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv,
487fc9c5412SJohannes Schauer                     maxenvlen, arginfo->env,
488fc9c5412SJohannes Schauer                     arginfo->help);
489fc9c5412SJohannes Schauer         }
490fc9c5412SJohannes Schauer     }
491fc9c5412SJohannes Schauer 
492fc9c5412SJohannes Schauer     printf("\n"
493fc9c5412SJohannes Schauer            "Defaults:\n"
494fc9c5412SJohannes Schauer            "QEMU_LD_PREFIX  = %s\n"
495989b697dSPeter Maydell            "QEMU_STACK_SIZE = %ld byte\n",
496fc9c5412SJohannes Schauer            interp_prefix,
497989b697dSPeter Maydell            guest_stack_size);
498fc9c5412SJohannes Schauer 
499fc9c5412SJohannes Schauer     printf("\n"
500fc9c5412SJohannes Schauer            "You can use -E and -U options or the QEMU_SET_ENV and\n"
501fc9c5412SJohannes Schauer            "QEMU_UNSET_ENV environment variables to set and unset\n"
502fc9c5412SJohannes Schauer            "environment variables for the target process.\n"
503fc9c5412SJohannes Schauer            "It is possible to provide several variables by separating them\n"
504fc9c5412SJohannes Schauer            "by commas in getsubopt(3) style. Additionally it is possible to\n"
505fc9c5412SJohannes Schauer            "provide the -E and -U options multiple times.\n"
506fc9c5412SJohannes Schauer            "The following lines are equivalent:\n"
507fc9c5412SJohannes Schauer            "    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n"
508fc9c5412SJohannes Schauer            "    -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n"
509fc9c5412SJohannes Schauer            "    QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n"
510fc9c5412SJohannes Schauer            "Note that if you provide several changes to a single variable\n"
511f5048cb7SEric Blake            "the last change will stay in effect.\n"
512f5048cb7SEric Blake            "\n"
513f5048cb7SEric Blake            QEMU_HELP_BOTTOM "\n");
514fc9c5412SJohannes Schauer 
515d03f9c32SMeador Inge     exit(exitcode);
516fc9c5412SJohannes Schauer }
517fc9c5412SJohannes Schauer 
518fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv)
519fc9c5412SJohannes Schauer {
520fc9c5412SJohannes Schauer     const char *r;
521fc9c5412SJohannes Schauer     int optind;
52242644ceeSJim Meyering     const struct qemu_argument *arginfo;
523fc9c5412SJohannes Schauer 
524fc9c5412SJohannes Schauer     for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
525fc9c5412SJohannes Schauer         if (arginfo->env == NULL) {
526fc9c5412SJohannes Schauer             continue;
527fc9c5412SJohannes Schauer         }
528fc9c5412SJohannes Schauer 
529fc9c5412SJohannes Schauer         r = getenv(arginfo->env);
530fc9c5412SJohannes Schauer         if (r != NULL) {
531fc9c5412SJohannes Schauer             arginfo->handle_opt(r);
532fc9c5412SJohannes Schauer         }
533fc9c5412SJohannes Schauer     }
534fc9c5412SJohannes Schauer 
535fc9c5412SJohannes Schauer     optind = 1;
536fc9c5412SJohannes Schauer     for (;;) {
537fc9c5412SJohannes Schauer         if (optind >= argc) {
538fc9c5412SJohannes Schauer             break;
539fc9c5412SJohannes Schauer         }
540fc9c5412SJohannes Schauer         r = argv[optind];
541fc9c5412SJohannes Schauer         if (r[0] != '-') {
542fc9c5412SJohannes Schauer             break;
543fc9c5412SJohannes Schauer         }
544fc9c5412SJohannes Schauer         optind++;
545fc9c5412SJohannes Schauer         r++;
546fc9c5412SJohannes Schauer         if (!strcmp(r, "-")) {
547fc9c5412SJohannes Schauer             break;
548fc9c5412SJohannes Schauer         }
549ba02577cSMeador Inge         /* Treat --foo the same as -foo.  */
550ba02577cSMeador Inge         if (r[0] == '-') {
551ba02577cSMeador Inge             r++;
552ba02577cSMeador Inge         }
553fc9c5412SJohannes Schauer 
554fc9c5412SJohannes Schauer         for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) {
555fc9c5412SJohannes Schauer             if (!strcmp(r, arginfo->argv)) {
5561386d4c0SPeter Maydell                 if (arginfo->has_arg) {
557fc9c5412SJohannes Schauer                     if (optind >= argc) {
558138940bfSMeador Inge                         (void) fprintf(stderr,
559138940bfSMeador Inge                             "qemu: missing argument for option '%s'\n", r);
5604d1275c2SRiku Voipio                         exit(EXIT_FAILURE);
561fc9c5412SJohannes Schauer                     }
562fc9c5412SJohannes Schauer                     arginfo->handle_opt(argv[optind]);
563fc9c5412SJohannes Schauer                     optind++;
5641386d4c0SPeter Maydell                 } else {
5651386d4c0SPeter Maydell                     arginfo->handle_opt(NULL);
566fc9c5412SJohannes Schauer                 }
567fc9c5412SJohannes Schauer                 break;
568fc9c5412SJohannes Schauer             }
569fc9c5412SJohannes Schauer         }
570fc9c5412SJohannes Schauer 
571fc9c5412SJohannes Schauer         /* no option matched the current argv */
572fc9c5412SJohannes Schauer         if (arginfo->handle_opt == NULL) {
573138940bfSMeador Inge             (void) fprintf(stderr, "qemu: unknown option '%s'\n", r);
5744d1275c2SRiku Voipio             exit(EXIT_FAILURE);
575fc9c5412SJohannes Schauer         }
576fc9c5412SJohannes Schauer     }
577fc9c5412SJohannes Schauer 
578fc9c5412SJohannes Schauer     if (optind >= argc) {
579138940bfSMeador Inge         (void) fprintf(stderr, "qemu: no user program specified\n");
5804d1275c2SRiku Voipio         exit(EXIT_FAILURE);
581fc9c5412SJohannes Schauer     }
582fc9c5412SJohannes Schauer 
583fc9c5412SJohannes Schauer     filename = argv[optind];
584fc9c5412SJohannes Schauer     exec_path = argv[optind];
585fc9c5412SJohannes Schauer 
586fc9c5412SJohannes Schauer     return optind;
587fc9c5412SJohannes Schauer }
588fc9c5412SJohannes Schauer 
589902b3d5cSmalc int main(int argc, char **argv, char **envp)
59031e31b8aSbellard {
59101ffc75bSbellard     struct target_pt_regs regs1, *regs = &regs1;
59231e31b8aSbellard     struct image_info info1, *info = &info1;
593edf8e2afSMika Westerberg     struct linux_binprm bprm;
59448e15fc2SNathan Froyd     TaskState *ts;
5959349b4f9SAndreas Färber     CPUArchState *env;
596db6b81d4SAndreas Färber     CPUState *cpu;
597586314f2Sbellard     int optind;
59804a6dfebSaurel32     char **target_environ, **wrk;
5997d8cec95Saurel32     char **target_argv;
6007d8cec95Saurel32     int target_argc;
6017d8cec95Saurel32     int i;
602fd4d81ddSArnaud Patard     int ret;
60303cfd8faSLaurent Vivier     int execfd;
60431e31b8aSbellard 
605f5852efaSChristophe Fergeau     error_init(argv[0]);
606fe4db84dSDaniel P. Berrange     module_call_init(MODULE_INIT_TRACE);
607267f685bSPaolo Bonzini     qemu_init_cpu_list();
608ce008c1fSAndreas Färber     module_call_init(MODULE_INIT_QOM);
609ce008c1fSAndreas Färber 
610ec45bbe5SSaurav Sachidanand     envlist = envlist_create();
61104a6dfebSaurel32 
61204a6dfebSaurel32     /* add current environment into the list */
61304a6dfebSaurel32     for (wrk = environ; *wrk != NULL; wrk++) {
61404a6dfebSaurel32         (void) envlist_setenv(envlist, *wrk);
61504a6dfebSaurel32     }
61604a6dfebSaurel32 
617703e0e89SRichard Henderson     /* Read the stack limit from the kernel.  If it's "unlimited",
618703e0e89SRichard Henderson        then we can do little else besides use the default.  */
619703e0e89SRichard Henderson     {
620703e0e89SRichard Henderson         struct rlimit lim;
621703e0e89SRichard Henderson         if (getrlimit(RLIMIT_STACK, &lim) == 0
62281bbe906Stakasi-y@ops.dti.ne.jp             && lim.rlim_cur != RLIM_INFINITY
62381bbe906Stakasi-y@ops.dti.ne.jp             && lim.rlim_cur == (target_long)lim.rlim_cur) {
624703e0e89SRichard Henderson             guest_stack_size = lim.rlim_cur;
625703e0e89SRichard Henderson         }
626703e0e89SRichard Henderson     }
627703e0e89SRichard Henderson 
628b1f9be31Sj_mayer     cpu_model = NULL;
629b5ec5ce0Sjohn cooper 
6306533dd6eSLluís Vilanova     qemu_add_opts(&qemu_trace_opts);
6316533dd6eSLluís Vilanova 
632fc9c5412SJohannes Schauer     optind = parse_args(argc, argv);
6334b5dfd82SPeter Maydell 
6346533dd6eSLluís Vilanova     if (!trace_init_backends()) {
6356533dd6eSLluís Vilanova         exit(1);
6366533dd6eSLluís Vilanova     }
6376533dd6eSLluís Vilanova     trace_init_file(trace_file);
6386533dd6eSLluís Vilanova 
63931e31b8aSbellard     /* Zero out regs */
64001ffc75bSbellard     memset(regs, 0, sizeof(struct target_pt_regs));
64131e31b8aSbellard 
64231e31b8aSbellard     /* Zero out image_info */
64331e31b8aSbellard     memset(info, 0, sizeof(struct image_info));
64431e31b8aSbellard 
645edf8e2afSMika Westerberg     memset(&bprm, 0, sizeof (bprm));
646edf8e2afSMika Westerberg 
64774cd30b8Sbellard     /* Scan interp_prefix dir for replacement files. */
64874cd30b8Sbellard     init_paths(interp_prefix);
64974cd30b8Sbellard 
6504a24a758SPeter Maydell     init_qemu_uname_release();
6514a24a758SPeter Maydell 
652768fe76eSYunQiang Su     execfd = qemu_getauxval(AT_EXECFD);
653768fe76eSYunQiang Su     if (execfd == 0) {
654768fe76eSYunQiang Su         execfd = open(filename, O_RDONLY);
655768fe76eSYunQiang Su         if (execfd < 0) {
656768fe76eSYunQiang Su             printf("Error while loading %s: %s\n", filename, strerror(errno));
657768fe76eSYunQiang Su             _exit(EXIT_FAILURE);
658768fe76eSYunQiang Su         }
659768fe76eSYunQiang Su     }
660768fe76eSYunQiang Su 
66146027c07Sbellard     if (cpu_model == NULL) {
662768fe76eSYunQiang Su         cpu_model = cpu_get_model(get_elf_eflags(execfd));
663aaed909aSbellard     }
664c1c8cfe5SEduardo Habkost     cpu_type = parse_cpu_option(cpu_model);
6652278b939SIgor Mammedov 
6662b5249b8SIgor Mammedov     /* init tcg before creating CPUs and to get qemu_host_page_size */
667d5ab9713SJan Kiszka     tcg_exec_init(0);
6682278b939SIgor Mammedov 
669dc18baaeSLaurent Vivier     /* Reserving *too* much vm space via mmap can run into problems
670dc18baaeSLaurent Vivier        with rlimits, oom due to page table creation, etc.  We will still try it,
671dc18baaeSLaurent Vivier        if directed by the command-line option, but not by default.  */
672dc18baaeSLaurent Vivier     if (HOST_LONG_BITS == 64 &&
673dc18baaeSLaurent Vivier         TARGET_VIRT_ADDR_SPACE_BITS <= 32 &&
674dc18baaeSLaurent Vivier         reserved_va == 0) {
675dc18baaeSLaurent Vivier         /* reserved_va must be aligned with the host page size
676dc18baaeSLaurent Vivier          * as it is used with mmap()
677dc18baaeSLaurent Vivier          */
678dc18baaeSLaurent Vivier         reserved_va = MAX_RESERVED_VA & qemu_host_page_mask;
679dc18baaeSLaurent Vivier     }
680dc18baaeSLaurent Vivier 
6812278b939SIgor Mammedov     cpu = cpu_create(cpu_type);
6822994fd96SEduardo Habkost     env = cpu->env_ptr;
6830ac46af3SAndreas Färber     cpu_reset(cpu);
684b55a37c9SBlue Swirl 
685db6b81d4SAndreas Färber     thread_cpu = cpu;
68654936004Sbellard 
687b92c47c1Sths     if (getenv("QEMU_STRACE")) {
688b92c47c1Sths         do_strace = 1;
689b92c47c1Sths     }
690b92c47c1Sths 
6915ebdd774SRichard Henderson     if (seed_optarg == NULL) {
6925ebdd774SRichard Henderson         seed_optarg = getenv("QEMU_RAND_SEED");
6935ebdd774SRichard Henderson     }
694a573e9baSRichard Henderson     {
695a573e9baSRichard Henderson         Error *err = NULL;
6965ebdd774SRichard Henderson         if (seed_optarg != NULL) {
697a573e9baSRichard Henderson             qemu_guest_random_seed_main(seed_optarg, &err);
698a573e9baSRichard Henderson         } else {
699a573e9baSRichard Henderson             qcrypto_init(&err);
700a573e9baSRichard Henderson         }
701a573e9baSRichard Henderson         if (err) {
702a573e9baSRichard Henderson             error_reportf_err(err, "cannot initialize crypto: ");
703a573e9baSRichard Henderson             exit(1);
704a573e9baSRichard Henderson         }
705c5e4a5a9SMagnus Reftel     }
706c5e4a5a9SMagnus Reftel 
70704a6dfebSaurel32     target_environ = envlist_to_environ(envlist, NULL);
70804a6dfebSaurel32     envlist_free(envlist);
709b12b6a18Sths 
710379f6698SPaul Brook     /*
7112b5249b8SIgor Mammedov      * Now that page sizes are configured in tcg_exec_init() we can do
712379f6698SPaul Brook      * proper page alignment for guest_base.
713379f6698SPaul Brook      */
714379f6698SPaul Brook     guest_base = HOST_PAGE_ALIGN(guest_base);
71568a1c816SPaul Brook 
71697cc7560SDr. David Alan Gilbert     if (reserved_va || have_guest_base) {
717806d1021SMeador Inge         guest_base = init_guest_space(guest_base, reserved_va, 0,
718806d1021SMeador Inge                                       have_guest_base);
719806d1021SMeador Inge         if (guest_base == (unsigned long)-1) {
720097b8cb8SPeter Maydell             fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address "
721097b8cb8SPeter Maydell                     "space for use as guest address space (check your virtual "
722097b8cb8SPeter Maydell                     "memory ulimit setting or reserve less using -R option)\n",
723097b8cb8SPeter Maydell                     reserved_va);
7244d1275c2SRiku Voipio             exit(EXIT_FAILURE);
72597cc7560SDr. David Alan Gilbert         }
726806d1021SMeador Inge 
727806d1021SMeador Inge         if (reserved_va) {
728806d1021SMeador Inge             mmap_next_start = reserved_va;
729806d1021SMeador Inge         }
73097cc7560SDr. David Alan Gilbert     }
731379f6698SPaul Brook 
732379f6698SPaul Brook     /*
733379f6698SPaul Brook      * Read in mmap_min_addr kernel parameter.  This value is used
734379f6698SPaul Brook      * When loading the ELF image to determine whether guest_base
73514f24e14SRichard Henderson      * is needed.  It is also used in mmap_find_vma.
736379f6698SPaul Brook      */
73714f24e14SRichard Henderson     {
738379f6698SPaul Brook         FILE *fp;
739379f6698SPaul Brook 
740379f6698SPaul Brook         if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
741379f6698SPaul Brook             unsigned long tmp;
742379f6698SPaul Brook             if (fscanf(fp, "%lu", &tmp) == 1) {
743379f6698SPaul Brook                 mmap_min_addr = tmp;
74413829020SPaolo Bonzini                 qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n", mmap_min_addr);
745379f6698SPaul Brook             }
746379f6698SPaul Brook             fclose(fp);
747379f6698SPaul Brook         }
748379f6698SPaul Brook     }
749379f6698SPaul Brook 
7507d8cec95Saurel32     /*
7517d8cec95Saurel32      * Prepare copy of argv vector for target.
7527d8cec95Saurel32      */
7537d8cec95Saurel32     target_argc = argc - optind;
7547d8cec95Saurel32     target_argv = calloc(target_argc + 1, sizeof (char *));
7557d8cec95Saurel32     if (target_argv == NULL) {
7567d8cec95Saurel32         (void) fprintf(stderr, "Unable to allocate memory for target_argv\n");
7574d1275c2SRiku Voipio         exit(EXIT_FAILURE);
7587d8cec95Saurel32     }
7597d8cec95Saurel32 
7607d8cec95Saurel32     /*
7617d8cec95Saurel32      * If argv0 is specified (using '-0' switch) we replace
7627d8cec95Saurel32      * argv[0] pointer with the given one.
7637d8cec95Saurel32      */
7647d8cec95Saurel32     i = 0;
7657d8cec95Saurel32     if (argv0 != NULL) {
7667d8cec95Saurel32         target_argv[i++] = strdup(argv0);
7677d8cec95Saurel32     }
7687d8cec95Saurel32     for (; i < target_argc; i++) {
7697d8cec95Saurel32         target_argv[i] = strdup(argv[optind + i]);
7707d8cec95Saurel32     }
7717d8cec95Saurel32     target_argv[target_argc] = NULL;
7727d8cec95Saurel32 
773c78d65e8SMarkus Armbruster     ts = g_new0(TaskState, 1);
774edf8e2afSMika Westerberg     init_task_state(ts);
775edf8e2afSMika Westerberg     /* build Task State */
776edf8e2afSMika Westerberg     ts->info = info;
777edf8e2afSMika Westerberg     ts->bprm = &bprm;
7780429a971SAndreas Färber     cpu->opaque = ts;
779edf8e2afSMika Westerberg     task_settid(ts);
780edf8e2afSMika Westerberg 
78103cfd8faSLaurent Vivier     ret = loader_exec(execfd, filename, target_argv, target_environ, regs,
782fd4d81ddSArnaud Patard         info, &bprm);
783fd4d81ddSArnaud Patard     if (ret != 0) {
784885c1d10SPeter Maydell         printf("Error while loading %s: %s\n", filename, strerror(-ret));
7854d1275c2SRiku Voipio         _exit(EXIT_FAILURE);
78631e31b8aSbellard     }
78731e31b8aSbellard 
788b12b6a18Sths     for (wrk = target_environ; *wrk; wrk++) {
789ec45bbe5SSaurav Sachidanand         g_free(*wrk);
790b12b6a18Sths     }
791b12b6a18Sths 
792ec45bbe5SSaurav Sachidanand     g_free(target_environ);
793b12b6a18Sths 
79413829020SPaolo Bonzini     if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
795379f6698SPaul Brook         qemu_log("guest_base  0x%lx\n", guest_base);
79693fcfe39Saliguori         log_page_dump();
79754936004Sbellard 
79893fcfe39Saliguori         qemu_log("start_brk   0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
79993fcfe39Saliguori         qemu_log("end_code    0x" TARGET_ABI_FMT_lx "\n", info->end_code);
8007c4ee5bcSRichard Henderson         qemu_log("start_code  0x" TARGET_ABI_FMT_lx "\n", info->start_code);
8017c4ee5bcSRichard Henderson         qemu_log("start_data  0x" TARGET_ABI_FMT_lx "\n", info->start_data);
80293fcfe39Saliguori         qemu_log("end_data    0x" TARGET_ABI_FMT_lx "\n", info->end_data);
8037c4ee5bcSRichard Henderson         qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n", info->start_stack);
80493fcfe39Saliguori         qemu_log("brk         0x" TARGET_ABI_FMT_lx "\n", info->brk);
80593fcfe39Saliguori         qemu_log("entry       0x" TARGET_ABI_FMT_lx "\n", info->entry);
8067c4ee5bcSRichard Henderson         qemu_log("argv_start  0x" TARGET_ABI_FMT_lx "\n", info->arg_start);
8077c4ee5bcSRichard Henderson         qemu_log("env_start   0x" TARGET_ABI_FMT_lx "\n",
8087c4ee5bcSRichard Henderson                  info->arg_end + (abi_ulong)sizeof(abi_ulong));
8097c4ee5bcSRichard Henderson         qemu_log("auxv_start  0x" TARGET_ABI_FMT_lx "\n", info->saved_auxv);
8102e77eac6Sblueswir1     }
81131e31b8aSbellard 
81253a5960aSpbrook     target_set_brk(info->brk);
81331e31b8aSbellard     syscall_init();
81466fb9763Sbellard     signal_init();
81531e31b8aSbellard 
8169002ec79SRichard Henderson     /* Now that we've loaded the binary, GUEST_BASE is fixed.  Delay
8179002ec79SRichard Henderson        generating the prologue until now so that the prologue can take
8189002ec79SRichard Henderson        the real value of GUEST_BASE into account.  */
819b1311c4aSEmilio G. Cota     tcg_prologue_init(tcg_ctx);
820e8feb96fSEmilio G. Cota     tcg_region_init();
8219002ec79SRichard Henderson 
822cd71c089SLaurent Vivier     target_cpu_copy_regs(env, regs);
823cd71c089SLaurent Vivier 
82474c33bedSbellard     if (gdbstub_port) {
825ff7a981aSPeter Maydell         if (gdbserver_start(gdbstub_port) < 0) {
826ff7a981aSPeter Maydell             fprintf(stderr, "qemu: could not open gdbserver on port %d\n",
827ff7a981aSPeter Maydell                     gdbstub_port);
8284d1275c2SRiku Voipio             exit(EXIT_FAILURE);
829ff7a981aSPeter Maydell         }
830db6b81d4SAndreas Färber         gdb_handlesig(cpu, 0);
8311fddef4bSbellard     }
8321b6b029eSbellard     cpu_loop(env);
8331b6b029eSbellard     /* never exits */
83431e31b8aSbellard     return 0;
83531e31b8aSbellard }
836