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 */ 19d39594e9SPeter Maydell #include "qemu/osdep.h" 20*b52713c1SPhilippe Mathieu-Daudé #include "qemu/units.h" 2167a1de0dSFam Zheng #include "qemu-version.h" 22edf8e2afSMika Westerberg #include <sys/syscall.h> 23703e0e89SRichard Henderson #include <sys/resource.h> 2431e31b8aSbellard 25daa76aa4SMarkus Armbruster #include "qapi/error.h" 263ef693a0Sbellard #include "qemu.h" 27f348b6d1SVeronia Bahaa #include "qemu/path.h" 286533dd6eSLluís Vilanova #include "qemu/config-file.h" 29f348b6d1SVeronia Bahaa #include "qemu/cutils.h" 30f348b6d1SVeronia Bahaa #include "qemu/help_option.h" 312b41f10eSBlue Swirl #include "cpu.h" 3263c91552SPaolo Bonzini #include "exec/exec-all.h" 339002ec79SRichard Henderson #include "tcg.h" 341de7afc9SPaolo Bonzini #include "qemu/timer.h" 351de7afc9SPaolo Bonzini #include "qemu/envlist.h" 36d8fd2954SPaul Brook #include "elf.h" 376533dd6eSLluís Vilanova #include "trace/control.h" 38542ca434SLaurent Vivier #include "target_elf.h" 39cd71c089SLaurent Vivier #include "cpu_loop-common.h" 4004a6dfebSaurel32 41d088d664Saurel32 char *exec_path; 42d088d664Saurel32 431b530a6dSaurel32 int singlestep; 448cb76755SStefan Weil static const char *filename; 458cb76755SStefan Weil static const char *argv0; 468cb76755SStefan Weil static int gdbstub_port; 478cb76755SStefan Weil static envlist_t *envlist; 4851fb256aSAndreas Färber static const char *cpu_model; 492278b939SIgor Mammedov static const char *cpu_type; 50379f6698SPaul Brook unsigned long mmap_min_addr; 51379f6698SPaul Brook unsigned long guest_base; 52379f6698SPaul Brook int have_guest_base; 53120a9848SPaolo Bonzini 54288e65b9SAlexander Graf /* 55288e65b9SAlexander Graf * When running 32-on-64 we should make sure we can fit all of the possible 56288e65b9SAlexander Graf * guest address space into a contiguous chunk of virtual host memory. 57288e65b9SAlexander Graf * 58288e65b9SAlexander Graf * This way we will never overlap with our own libraries or binaries or stack 59288e65b9SAlexander Graf * or anything else that QEMU maps. 6018e80c55SRichard Henderson * 6118e80c55SRichard Henderson * Many cpus reserve the high bit (or more than one for some 64-bit cpus) 6218e80c55SRichard Henderson * of the address for the kernel. Some cpus rely on this and user space 6318e80c55SRichard Henderson * uses the high bit(s) for pointer tagging and the like. For them, we 6418e80c55SRichard Henderson * must preserve the expected address space. 65288e65b9SAlexander Graf */ 6618e80c55SRichard Henderson #ifndef MAX_RESERVED_VA 6718e80c55SRichard Henderson # if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS 6818e80c55SRichard Henderson # if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \ 6918e80c55SRichard Henderson (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32)) 7018e80c55SRichard Henderson /* There are a number of places where we assign reserved_va to a variable 7118e80c55SRichard Henderson of type abi_ulong and expect it to fit. Avoid the last page. */ 7218e80c55SRichard Henderson # define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK) 73314992b1SAlexander Graf # else 7418e80c55SRichard Henderson # define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS) 75314992b1SAlexander Graf # endif 76288e65b9SAlexander Graf # else 7718e80c55SRichard Henderson # define MAX_RESERVED_VA 0 7818e80c55SRichard Henderson # endif 7918e80c55SRichard Henderson #endif 8018e80c55SRichard Henderson 8118e80c55SRichard Henderson /* That said, reserving *too* much vm space via mmap can run into problems 8218e80c55SRichard Henderson with rlimits, oom due to page table creation, etc. We will still try it, 8318e80c55SRichard Henderson if directed by the command-line option, but not by default. */ 8418e80c55SRichard Henderson #if HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32 8518e80c55SRichard Henderson unsigned long reserved_va = MAX_RESERVED_VA; 8618e80c55SRichard Henderson #else 8768a1c816SPaul Brook unsigned long reserved_va; 88379f6698SPaul Brook #endif 891b530a6dSaurel32 90d03f9c32SMeador Inge static void usage(int exitcode); 91fc9c5412SJohannes Schauer 927ee2822cSPaolo Bonzini static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; 93e586822aSRiku Voipio const char *qemu_uname_release; 94586314f2Sbellard 959de5e440Sbellard /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so 969de5e440Sbellard we allocate a bigger stack. Need a better solution, for example 979de5e440Sbellard by remapping the process stack directly at the right place */ 98703e0e89SRichard Henderson unsigned long guest_stack_size = 8 * 1024 * 1024UL; 9931e31b8aSbellard 10031e31b8aSbellard void gemu_log(const char *fmt, ...) 10131e31b8aSbellard { 10231e31b8aSbellard va_list ap; 10331e31b8aSbellard 10431e31b8aSbellard va_start(ap, fmt); 10531e31b8aSbellard vfprintf(stderr, fmt, ap); 10631e31b8aSbellard va_end(ap); 10731e31b8aSbellard } 10831e31b8aSbellard 1098fcd3692Sblueswir1 #if defined(TARGET_I386) 11005390248SAndreas Färber int cpu_get_pic_interrupt(CPUX86State *env) 11192ccca6aSbellard { 11292ccca6aSbellard return -1; 11392ccca6aSbellard } 1148fcd3692Sblueswir1 #endif 11592ccca6aSbellard 116d5975363Spbrook /***********************************************************/ 117d5975363Spbrook /* Helper routines for implementing atomic operations. */ 118d5975363Spbrook 119d5975363Spbrook /* Make sure everything is in a consistent state for calling fork(). */ 120d5975363Spbrook void fork_start(void) 121d5975363Spbrook { 12206065c45SPeter Maydell start_exclusive(); 123d032d1b4SRiku Voipio mmap_fork_start(); 124024949caSPeter Maydell cpu_list_lock(); 125d5975363Spbrook } 126d5975363Spbrook 127d5975363Spbrook void fork_end(int child) 128d5975363Spbrook { 129d032d1b4SRiku Voipio mmap_fork_end(child); 130d5975363Spbrook if (child) { 131bdc44640SAndreas Färber CPUState *cpu, *next_cpu; 132d5975363Spbrook /* Child processes created by fork() only have a single thread. 133d5975363Spbrook Discard information about the parent threads. */ 134bdc44640SAndreas Färber CPU_FOREACH_SAFE(cpu, next_cpu) { 135bdc44640SAndreas Färber if (cpu != thread_cpu) { 136014628a7SPeter Maydell QTAILQ_REMOVE(&cpus, cpu, node); 137bdc44640SAndreas Färber } 138bdc44640SAndreas Färber } 139267f685bSPaolo Bonzini qemu_init_cpu_list(); 140f7ec7f7bSPeter Crosthwaite gdbserver_fork(thread_cpu); 14106065c45SPeter Maydell /* qemu_init_cpu_list() takes care of reinitializing the 14206065c45SPeter Maydell * exclusive state, so we don't need to end_exclusive() here. 14306065c45SPeter Maydell */ 144d5975363Spbrook } else { 145267f685bSPaolo Bonzini cpu_list_unlock(); 14606065c45SPeter Maydell end_exclusive(); 147d5975363Spbrook } 148d5975363Spbrook } 149d5975363Spbrook 150b44316fbSPeter Maydell __thread CPUState *thread_cpu; 15159faf6d6Sbellard 152178f9429SSergey Fedorov bool qemu_cpu_is_self(CPUState *cpu) 153178f9429SSergey Fedorov { 154178f9429SSergey Fedorov return thread_cpu == cpu; 155178f9429SSergey Fedorov } 156178f9429SSergey Fedorov 157178f9429SSergey Fedorov void qemu_cpu_kick(CPUState *cpu) 158178f9429SSergey Fedorov { 159178f9429SSergey Fedorov cpu_exit(cpu); 160178f9429SSergey Fedorov } 161178f9429SSergey Fedorov 162edf8e2afSMika Westerberg void task_settid(TaskState *ts) 163edf8e2afSMika Westerberg { 164edf8e2afSMika Westerberg if (ts->ts_tid == 0) { 165edf8e2afSMika Westerberg ts->ts_tid = (pid_t)syscall(SYS_gettid); 166edf8e2afSMika Westerberg } 167edf8e2afSMika Westerberg } 168edf8e2afSMika Westerberg 169edf8e2afSMika Westerberg void stop_all_tasks(void) 170edf8e2afSMika Westerberg { 171edf8e2afSMika Westerberg /* 172edf8e2afSMika Westerberg * We trust that when using NPTL, start_exclusive() 173edf8e2afSMika Westerberg * handles thread stopping correctly. 174edf8e2afSMika Westerberg */ 175edf8e2afSMika Westerberg start_exclusive(); 176edf8e2afSMika Westerberg } 177edf8e2afSMika Westerberg 178c3a92833Spbrook /* Assumes contents are already zeroed. */ 179624f7979Spbrook void init_task_state(TaskState *ts) 180624f7979Spbrook { 181624f7979Spbrook ts->used = 1; 182624f7979Spbrook } 1839de5e440Sbellard 18430ba0ee5SAndreas Färber CPUArchState *cpu_copy(CPUArchState *env) 18530ba0ee5SAndreas Färber { 186ff4700b0SAndreas Färber CPUState *cpu = ENV_GET_CPU(env); 1872278b939SIgor Mammedov CPUState *new_cpu = cpu_create(cpu_type); 18861c7480fSLeon Alrae CPUArchState *new_env = new_cpu->env_ptr; 18930ba0ee5SAndreas Färber CPUBreakpoint *bp; 19030ba0ee5SAndreas Färber CPUWatchpoint *wp; 19130ba0ee5SAndreas Färber 19230ba0ee5SAndreas Färber /* Reset non arch specific state */ 19375a34036SAndreas Färber cpu_reset(new_cpu); 19430ba0ee5SAndreas Färber 19530ba0ee5SAndreas Färber memcpy(new_env, env, sizeof(CPUArchState)); 19630ba0ee5SAndreas Färber 19730ba0ee5SAndreas Färber /* Clone all break/watchpoints. 19830ba0ee5SAndreas Färber Note: Once we support ptrace with hw-debug register access, make sure 19930ba0ee5SAndreas Färber BP_CPU break/watchpoints are handled correctly on clone. */ 2001d085f6cSThierry Bultel QTAILQ_INIT(&new_cpu->breakpoints); 2011d085f6cSThierry Bultel QTAILQ_INIT(&new_cpu->watchpoints); 202f0c3c505SAndreas Färber QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { 203b3310ab3SAndreas Färber cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL); 20430ba0ee5SAndreas Färber } 205ff4700b0SAndreas Färber QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { 20605068c0dSPeter Maydell cpu_watchpoint_insert(new_cpu, wp->vaddr, wp->len, wp->flags, NULL); 20730ba0ee5SAndreas Färber } 20830ba0ee5SAndreas Färber 20930ba0ee5SAndreas Färber return new_env; 21030ba0ee5SAndreas Färber } 21130ba0ee5SAndreas Färber 212fc9c5412SJohannes Schauer static void handle_arg_help(const char *arg) 213fc9c5412SJohannes Schauer { 2144d1275c2SRiku Voipio usage(EXIT_SUCCESS); 215fc9c5412SJohannes Schauer } 216fc9c5412SJohannes Schauer 217fc9c5412SJohannes Schauer static void handle_arg_log(const char *arg) 218fc9c5412SJohannes Schauer { 219fc9c5412SJohannes Schauer int mask; 220fc9c5412SJohannes Schauer 2214fde1ebaSPeter Maydell mask = qemu_str_to_log_mask(arg); 222fc9c5412SJohannes Schauer if (!mask) { 22359a6fa6eSPeter Maydell qemu_print_log_usage(stdout); 2244d1275c2SRiku Voipio exit(EXIT_FAILURE); 225fc9c5412SJohannes Schauer } 226f2937a33SPaolo Bonzini qemu_log_needs_buffers(); 22724537a01SPeter Maydell qemu_set_log(mask); 228fc9c5412SJohannes Schauer } 229fc9c5412SJohannes Schauer 2308423fa90SAlex Bennée static void handle_arg_dfilter(const char *arg) 2318423fa90SAlex Bennée { 2328423fa90SAlex Bennée qemu_set_dfilter_ranges(arg, NULL); 2338423fa90SAlex Bennée } 2348423fa90SAlex Bennée 23550171d42S陳韋任 static void handle_arg_log_filename(const char *arg) 23650171d42S陳韋任 { 237daa76aa4SMarkus Armbruster qemu_set_log_filename(arg, &error_fatal); 23850171d42S陳韋任 } 23950171d42S陳韋任 240fc9c5412SJohannes Schauer static void handle_arg_set_env(const char *arg) 241fc9c5412SJohannes Schauer { 242fc9c5412SJohannes Schauer char *r, *p, *token; 243fc9c5412SJohannes Schauer r = p = strdup(arg); 244fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 245fc9c5412SJohannes Schauer if (envlist_setenv(envlist, token) != 0) { 2464d1275c2SRiku Voipio usage(EXIT_FAILURE); 247fc9c5412SJohannes Schauer } 248fc9c5412SJohannes Schauer } 249fc9c5412SJohannes Schauer free(r); 250fc9c5412SJohannes Schauer } 251fc9c5412SJohannes Schauer 252fc9c5412SJohannes Schauer static void handle_arg_unset_env(const char *arg) 253fc9c5412SJohannes Schauer { 254fc9c5412SJohannes Schauer char *r, *p, *token; 255fc9c5412SJohannes Schauer r = p = strdup(arg); 256fc9c5412SJohannes Schauer while ((token = strsep(&p, ",")) != NULL) { 257fc9c5412SJohannes Schauer if (envlist_unsetenv(envlist, token) != 0) { 2584d1275c2SRiku Voipio usage(EXIT_FAILURE); 259fc9c5412SJohannes Schauer } 260fc9c5412SJohannes Schauer } 261fc9c5412SJohannes Schauer free(r); 262fc9c5412SJohannes Schauer } 263fc9c5412SJohannes Schauer 264fc9c5412SJohannes Schauer static void handle_arg_argv0(const char *arg) 265fc9c5412SJohannes Schauer { 266fc9c5412SJohannes Schauer argv0 = strdup(arg); 267fc9c5412SJohannes Schauer } 268fc9c5412SJohannes Schauer 269fc9c5412SJohannes Schauer static void handle_arg_stack_size(const char *arg) 270fc9c5412SJohannes Schauer { 271fc9c5412SJohannes Schauer char *p; 272fc9c5412SJohannes Schauer guest_stack_size = strtoul(arg, &p, 0); 273fc9c5412SJohannes Schauer if (guest_stack_size == 0) { 2744d1275c2SRiku Voipio usage(EXIT_FAILURE); 275fc9c5412SJohannes Schauer } 276fc9c5412SJohannes Schauer 277fc9c5412SJohannes Schauer if (*p == 'M') { 278*b52713c1SPhilippe Mathieu-Daudé guest_stack_size *= MiB; 279fc9c5412SJohannes Schauer } else if (*p == 'k' || *p == 'K') { 280*b52713c1SPhilippe Mathieu-Daudé guest_stack_size *= KiB; 281fc9c5412SJohannes Schauer } 282fc9c5412SJohannes Schauer } 283fc9c5412SJohannes Schauer 284fc9c5412SJohannes Schauer static void handle_arg_ld_prefix(const char *arg) 285fc9c5412SJohannes Schauer { 286fc9c5412SJohannes Schauer interp_prefix = strdup(arg); 287fc9c5412SJohannes Schauer } 288fc9c5412SJohannes Schauer 289fc9c5412SJohannes Schauer static void handle_arg_pagesize(const char *arg) 290fc9c5412SJohannes Schauer { 291fc9c5412SJohannes Schauer qemu_host_page_size = atoi(arg); 292fc9c5412SJohannes Schauer if (qemu_host_page_size == 0 || 293fc9c5412SJohannes Schauer (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { 294fc9c5412SJohannes Schauer fprintf(stderr, "page size must be a power of two\n"); 2954d1275c2SRiku Voipio exit(EXIT_FAILURE); 296fc9c5412SJohannes Schauer } 297fc9c5412SJohannes Schauer } 298fc9c5412SJohannes Schauer 299c5e4a5a9SMagnus Reftel static void handle_arg_randseed(const char *arg) 300c5e4a5a9SMagnus Reftel { 301c5e4a5a9SMagnus Reftel unsigned long long seed; 302c5e4a5a9SMagnus Reftel 303c5e4a5a9SMagnus Reftel if (parse_uint_full(arg, &seed, 0) != 0 || seed > UINT_MAX) { 304c5e4a5a9SMagnus Reftel fprintf(stderr, "Invalid seed number: %s\n", arg); 3054d1275c2SRiku Voipio exit(EXIT_FAILURE); 306c5e4a5a9SMagnus Reftel } 307c5e4a5a9SMagnus Reftel srand(seed); 308c5e4a5a9SMagnus Reftel } 309c5e4a5a9SMagnus Reftel 310fc9c5412SJohannes Schauer static void handle_arg_gdb(const char *arg) 311fc9c5412SJohannes Schauer { 312fc9c5412SJohannes Schauer gdbstub_port = atoi(arg); 313fc9c5412SJohannes Schauer } 314fc9c5412SJohannes Schauer 315fc9c5412SJohannes Schauer static void handle_arg_uname(const char *arg) 316fc9c5412SJohannes Schauer { 317fc9c5412SJohannes Schauer qemu_uname_release = strdup(arg); 318fc9c5412SJohannes Schauer } 319fc9c5412SJohannes Schauer 320fc9c5412SJohannes Schauer static void handle_arg_cpu(const char *arg) 321fc9c5412SJohannes Schauer { 322fc9c5412SJohannes Schauer cpu_model = strdup(arg); 323c8057f95SPeter Maydell if (cpu_model == NULL || is_help_option(cpu_model)) { 324fc9c5412SJohannes Schauer /* XXX: implement xxx_cpu_list for targets that still miss it */ 325e916cbf8SPeter Maydell #if defined(cpu_list) 326e916cbf8SPeter Maydell cpu_list(stdout, &fprintf); 327fc9c5412SJohannes Schauer #endif 3284d1275c2SRiku Voipio exit(EXIT_FAILURE); 329fc9c5412SJohannes Schauer } 330fc9c5412SJohannes Schauer } 331fc9c5412SJohannes Schauer 332fc9c5412SJohannes Schauer static void handle_arg_guest_base(const char *arg) 333fc9c5412SJohannes Schauer { 334fc9c5412SJohannes Schauer guest_base = strtol(arg, NULL, 0); 335fc9c5412SJohannes Schauer have_guest_base = 1; 336fc9c5412SJohannes Schauer } 337fc9c5412SJohannes Schauer 338fc9c5412SJohannes Schauer static void handle_arg_reserved_va(const char *arg) 339fc9c5412SJohannes Schauer { 340fc9c5412SJohannes Schauer char *p; 341fc9c5412SJohannes Schauer int shift = 0; 342fc9c5412SJohannes Schauer reserved_va = strtoul(arg, &p, 0); 343fc9c5412SJohannes Schauer switch (*p) { 344fc9c5412SJohannes Schauer case 'k': 345fc9c5412SJohannes Schauer case 'K': 346fc9c5412SJohannes Schauer shift = 10; 347fc9c5412SJohannes Schauer break; 348fc9c5412SJohannes Schauer case 'M': 349fc9c5412SJohannes Schauer shift = 20; 350fc9c5412SJohannes Schauer break; 351fc9c5412SJohannes Schauer case 'G': 352fc9c5412SJohannes Schauer shift = 30; 353fc9c5412SJohannes Schauer break; 354fc9c5412SJohannes Schauer } 355fc9c5412SJohannes Schauer if (shift) { 356fc9c5412SJohannes Schauer unsigned long unshifted = reserved_va; 357fc9c5412SJohannes Schauer p++; 358fc9c5412SJohannes Schauer reserved_va <<= shift; 35918e80c55SRichard Henderson if (reserved_va >> shift != unshifted 36018e80c55SRichard Henderson || (MAX_RESERVED_VA && reserved_va > MAX_RESERVED_VA)) { 361fc9c5412SJohannes Schauer fprintf(stderr, "Reserved virtual address too big\n"); 3624d1275c2SRiku Voipio exit(EXIT_FAILURE); 363fc9c5412SJohannes Schauer } 364fc9c5412SJohannes Schauer } 365fc9c5412SJohannes Schauer if (*p) { 366fc9c5412SJohannes Schauer fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p); 3674d1275c2SRiku Voipio exit(EXIT_FAILURE); 368fc9c5412SJohannes Schauer } 369fc9c5412SJohannes Schauer } 370fc9c5412SJohannes Schauer 371fc9c5412SJohannes Schauer static void handle_arg_singlestep(const char *arg) 372fc9c5412SJohannes Schauer { 373fc9c5412SJohannes Schauer singlestep = 1; 374fc9c5412SJohannes Schauer } 375fc9c5412SJohannes Schauer 376fc9c5412SJohannes Schauer static void handle_arg_strace(const char *arg) 377fc9c5412SJohannes Schauer { 378fc9c5412SJohannes Schauer do_strace = 1; 379fc9c5412SJohannes Schauer } 380fc9c5412SJohannes Schauer 381fc9c5412SJohannes Schauer static void handle_arg_version(const char *arg) 382fc9c5412SJohannes Schauer { 3837e563bfbSThomas Huth printf("qemu-" TARGET_NAME " version " QEMU_FULL_VERSION 3840781dd6eSThomas Huth "\n" QEMU_COPYRIGHT "\n"); 3854d1275c2SRiku Voipio exit(EXIT_SUCCESS); 386fc9c5412SJohannes Schauer } 387fc9c5412SJohannes Schauer 3886533dd6eSLluís Vilanova static char *trace_file; 3896533dd6eSLluís Vilanova static void handle_arg_trace(const char *arg) 3906533dd6eSLluís Vilanova { 3916533dd6eSLluís Vilanova g_free(trace_file); 3926533dd6eSLluís Vilanova trace_file = trace_opt_parse(arg); 3936533dd6eSLluís Vilanova } 3946533dd6eSLluís Vilanova 395fc9c5412SJohannes Schauer struct qemu_argument { 396fc9c5412SJohannes Schauer const char *argv; 397fc9c5412SJohannes Schauer const char *env; 398fc9c5412SJohannes Schauer bool has_arg; 399fc9c5412SJohannes Schauer void (*handle_opt)(const char *arg); 400fc9c5412SJohannes Schauer const char *example; 401fc9c5412SJohannes Schauer const char *help; 402fc9c5412SJohannes Schauer }; 403fc9c5412SJohannes Schauer 40442644ceeSJim Meyering static const struct qemu_argument arg_table[] = { 405fc9c5412SJohannes Schauer {"h", "", false, handle_arg_help, 406fc9c5412SJohannes Schauer "", "print this help"}, 407daaf8c8eSMeador Inge {"help", "", false, handle_arg_help, 408daaf8c8eSMeador Inge "", ""}, 409fc9c5412SJohannes Schauer {"g", "QEMU_GDB", true, handle_arg_gdb, 410fc9c5412SJohannes Schauer "port", "wait gdb connection to 'port'"}, 411fc9c5412SJohannes Schauer {"L", "QEMU_LD_PREFIX", true, handle_arg_ld_prefix, 412fc9c5412SJohannes Schauer "path", "set the elf interpreter prefix to 'path'"}, 413fc9c5412SJohannes Schauer {"s", "QEMU_STACK_SIZE", true, handle_arg_stack_size, 414fc9c5412SJohannes Schauer "size", "set the stack size to 'size' bytes"}, 415fc9c5412SJohannes Schauer {"cpu", "QEMU_CPU", true, handle_arg_cpu, 416c8057f95SPeter Maydell "model", "select CPU (-cpu help for list)"}, 417fc9c5412SJohannes Schauer {"E", "QEMU_SET_ENV", true, handle_arg_set_env, 418fc9c5412SJohannes Schauer "var=value", "sets targets environment variable (see below)"}, 419fc9c5412SJohannes Schauer {"U", "QEMU_UNSET_ENV", true, handle_arg_unset_env, 420fc9c5412SJohannes Schauer "var", "unsets targets environment variable (see below)"}, 421fc9c5412SJohannes Schauer {"0", "QEMU_ARGV0", true, handle_arg_argv0, 422fc9c5412SJohannes Schauer "argv0", "forces target process argv[0] to be 'argv0'"}, 423fc9c5412SJohannes Schauer {"r", "QEMU_UNAME", true, handle_arg_uname, 424fc9c5412SJohannes Schauer "uname", "set qemu uname release string to 'uname'"}, 425fc9c5412SJohannes Schauer {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base, 426fc9c5412SJohannes Schauer "address", "set guest_base address to 'address'"}, 427fc9c5412SJohannes Schauer {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va, 428fc9c5412SJohannes Schauer "size", "reserve 'size' bytes for guest virtual address space"}, 429fc9c5412SJohannes Schauer {"d", "QEMU_LOG", true, handle_arg_log, 430989b697dSPeter Maydell "item[,...]", "enable logging of specified items " 431989b697dSPeter Maydell "(use '-d help' for a list of items)"}, 4328423fa90SAlex Bennée {"dfilter", "QEMU_DFILTER", true, handle_arg_dfilter, 4338423fa90SAlex Bennée "range[,...]","filter logging based on address range"}, 43450171d42S陳韋任 {"D", "QEMU_LOG_FILENAME", true, handle_arg_log_filename, 435989b697dSPeter Maydell "logfile", "write logs to 'logfile' (default stderr)"}, 436fc9c5412SJohannes Schauer {"p", "QEMU_PAGESIZE", true, handle_arg_pagesize, 437fc9c5412SJohannes Schauer "pagesize", "set the host page size to 'pagesize'"}, 438fc9c5412SJohannes Schauer {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep, 439fc9c5412SJohannes Schauer "", "run in singlestep mode"}, 440fc9c5412SJohannes Schauer {"strace", "QEMU_STRACE", false, handle_arg_strace, 441fc9c5412SJohannes Schauer "", "log system calls"}, 442c5e4a5a9SMagnus Reftel {"seed", "QEMU_RAND_SEED", true, handle_arg_randseed, 443c5e4a5a9SMagnus Reftel "", "Seed for pseudo-random number generator"}, 4446533dd6eSLluís Vilanova {"trace", "QEMU_TRACE", true, handle_arg_trace, 4456533dd6eSLluís Vilanova "", "[[enable=]<pattern>][,events=<file>][,file=<file>]"}, 446fc9c5412SJohannes Schauer {"version", "QEMU_VERSION", false, handle_arg_version, 4471386d4c0SPeter Maydell "", "display version information and exit"}, 448fc9c5412SJohannes Schauer {NULL, NULL, false, NULL, NULL, NULL} 449fc9c5412SJohannes Schauer }; 450fc9c5412SJohannes Schauer 451d03f9c32SMeador Inge static void usage(int exitcode) 452fc9c5412SJohannes Schauer { 45342644ceeSJim Meyering const struct qemu_argument *arginfo; 454fc9c5412SJohannes Schauer int maxarglen; 455fc9c5412SJohannes Schauer int maxenvlen; 456fc9c5412SJohannes Schauer 4572e59915dSPaolo Bonzini printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n" 4582e59915dSPaolo Bonzini "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n" 459fc9c5412SJohannes Schauer "\n" 460fc9c5412SJohannes Schauer "Options and associated environment variables:\n" 461fc9c5412SJohannes Schauer "\n"); 462fc9c5412SJohannes Schauer 46363ec54d7SPeter Maydell /* Calculate column widths. We must always have at least enough space 46463ec54d7SPeter Maydell * for the column header. 46563ec54d7SPeter Maydell */ 46663ec54d7SPeter Maydell maxarglen = strlen("Argument"); 46763ec54d7SPeter Maydell maxenvlen = strlen("Env-variable"); 468fc9c5412SJohannes Schauer 469fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 47063ec54d7SPeter Maydell int arglen = strlen(arginfo->argv); 47163ec54d7SPeter Maydell if (arginfo->has_arg) { 47263ec54d7SPeter Maydell arglen += strlen(arginfo->example) + 1; 47363ec54d7SPeter Maydell } 474fc9c5412SJohannes Schauer if (strlen(arginfo->env) > maxenvlen) { 475fc9c5412SJohannes Schauer maxenvlen = strlen(arginfo->env); 476fc9c5412SJohannes Schauer } 47763ec54d7SPeter Maydell if (arglen > maxarglen) { 47863ec54d7SPeter Maydell maxarglen = arglen; 479fc9c5412SJohannes Schauer } 480fc9c5412SJohannes Schauer } 481fc9c5412SJohannes Schauer 48263ec54d7SPeter Maydell printf("%-*s %-*s Description\n", maxarglen+1, "Argument", 48363ec54d7SPeter Maydell maxenvlen, "Env-variable"); 484fc9c5412SJohannes Schauer 485fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 486fc9c5412SJohannes Schauer if (arginfo->has_arg) { 487fc9c5412SJohannes Schauer printf("-%s %-*s %-*s %s\n", arginfo->argv, 48863ec54d7SPeter Maydell (int)(maxarglen - strlen(arginfo->argv) - 1), 48963ec54d7SPeter Maydell arginfo->example, maxenvlen, arginfo->env, arginfo->help); 490fc9c5412SJohannes Schauer } else { 49163ec54d7SPeter Maydell printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv, 492fc9c5412SJohannes Schauer maxenvlen, arginfo->env, 493fc9c5412SJohannes Schauer arginfo->help); 494fc9c5412SJohannes Schauer } 495fc9c5412SJohannes Schauer } 496fc9c5412SJohannes Schauer 497fc9c5412SJohannes Schauer printf("\n" 498fc9c5412SJohannes Schauer "Defaults:\n" 499fc9c5412SJohannes Schauer "QEMU_LD_PREFIX = %s\n" 500989b697dSPeter Maydell "QEMU_STACK_SIZE = %ld byte\n", 501fc9c5412SJohannes Schauer interp_prefix, 502989b697dSPeter Maydell guest_stack_size); 503fc9c5412SJohannes Schauer 504fc9c5412SJohannes Schauer printf("\n" 505fc9c5412SJohannes Schauer "You can use -E and -U options or the QEMU_SET_ENV and\n" 506fc9c5412SJohannes Schauer "QEMU_UNSET_ENV environment variables to set and unset\n" 507fc9c5412SJohannes Schauer "environment variables for the target process.\n" 508fc9c5412SJohannes Schauer "It is possible to provide several variables by separating them\n" 509fc9c5412SJohannes Schauer "by commas in getsubopt(3) style. Additionally it is possible to\n" 510fc9c5412SJohannes Schauer "provide the -E and -U options multiple times.\n" 511fc9c5412SJohannes Schauer "The following lines are equivalent:\n" 512fc9c5412SJohannes Schauer " -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n" 513fc9c5412SJohannes Schauer " -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n" 514fc9c5412SJohannes Schauer " QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n" 515fc9c5412SJohannes Schauer "Note that if you provide several changes to a single variable\n" 516f5048cb7SEric Blake "the last change will stay in effect.\n" 517f5048cb7SEric Blake "\n" 518f5048cb7SEric Blake QEMU_HELP_BOTTOM "\n"); 519fc9c5412SJohannes Schauer 520d03f9c32SMeador Inge exit(exitcode); 521fc9c5412SJohannes Schauer } 522fc9c5412SJohannes Schauer 523fc9c5412SJohannes Schauer static int parse_args(int argc, char **argv) 524fc9c5412SJohannes Schauer { 525fc9c5412SJohannes Schauer const char *r; 526fc9c5412SJohannes Schauer int optind; 52742644ceeSJim Meyering const struct qemu_argument *arginfo; 528fc9c5412SJohannes Schauer 529fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 530fc9c5412SJohannes Schauer if (arginfo->env == NULL) { 531fc9c5412SJohannes Schauer continue; 532fc9c5412SJohannes Schauer } 533fc9c5412SJohannes Schauer 534fc9c5412SJohannes Schauer r = getenv(arginfo->env); 535fc9c5412SJohannes Schauer if (r != NULL) { 536fc9c5412SJohannes Schauer arginfo->handle_opt(r); 537fc9c5412SJohannes Schauer } 538fc9c5412SJohannes Schauer } 539fc9c5412SJohannes Schauer 540fc9c5412SJohannes Schauer optind = 1; 541fc9c5412SJohannes Schauer for (;;) { 542fc9c5412SJohannes Schauer if (optind >= argc) { 543fc9c5412SJohannes Schauer break; 544fc9c5412SJohannes Schauer } 545fc9c5412SJohannes Schauer r = argv[optind]; 546fc9c5412SJohannes Schauer if (r[0] != '-') { 547fc9c5412SJohannes Schauer break; 548fc9c5412SJohannes Schauer } 549fc9c5412SJohannes Schauer optind++; 550fc9c5412SJohannes Schauer r++; 551fc9c5412SJohannes Schauer if (!strcmp(r, "-")) { 552fc9c5412SJohannes Schauer break; 553fc9c5412SJohannes Schauer } 554ba02577cSMeador Inge /* Treat --foo the same as -foo. */ 555ba02577cSMeador Inge if (r[0] == '-') { 556ba02577cSMeador Inge r++; 557ba02577cSMeador Inge } 558fc9c5412SJohannes Schauer 559fc9c5412SJohannes Schauer for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { 560fc9c5412SJohannes Schauer if (!strcmp(r, arginfo->argv)) { 5611386d4c0SPeter Maydell if (arginfo->has_arg) { 562fc9c5412SJohannes Schauer if (optind >= argc) { 563138940bfSMeador Inge (void) fprintf(stderr, 564138940bfSMeador Inge "qemu: missing argument for option '%s'\n", r); 5654d1275c2SRiku Voipio exit(EXIT_FAILURE); 566fc9c5412SJohannes Schauer } 567fc9c5412SJohannes Schauer arginfo->handle_opt(argv[optind]); 568fc9c5412SJohannes Schauer optind++; 5691386d4c0SPeter Maydell } else { 5701386d4c0SPeter Maydell arginfo->handle_opt(NULL); 571fc9c5412SJohannes Schauer } 572fc9c5412SJohannes Schauer break; 573fc9c5412SJohannes Schauer } 574fc9c5412SJohannes Schauer } 575fc9c5412SJohannes Schauer 576fc9c5412SJohannes Schauer /* no option matched the current argv */ 577fc9c5412SJohannes Schauer if (arginfo->handle_opt == NULL) { 578138940bfSMeador Inge (void) fprintf(stderr, "qemu: unknown option '%s'\n", r); 5794d1275c2SRiku Voipio exit(EXIT_FAILURE); 580fc9c5412SJohannes Schauer } 581fc9c5412SJohannes Schauer } 582fc9c5412SJohannes Schauer 583fc9c5412SJohannes Schauer if (optind >= argc) { 584138940bfSMeador Inge (void) fprintf(stderr, "qemu: no user program specified\n"); 5854d1275c2SRiku Voipio exit(EXIT_FAILURE); 586fc9c5412SJohannes Schauer } 587fc9c5412SJohannes Schauer 588fc9c5412SJohannes Schauer filename = argv[optind]; 589fc9c5412SJohannes Schauer exec_path = argv[optind]; 590fc9c5412SJohannes Schauer 591fc9c5412SJohannes Schauer return optind; 592fc9c5412SJohannes Schauer } 593fc9c5412SJohannes Schauer 594902b3d5cSmalc int main(int argc, char **argv, char **envp) 59531e31b8aSbellard { 59601ffc75bSbellard struct target_pt_regs regs1, *regs = ®s1; 59731e31b8aSbellard struct image_info info1, *info = &info1; 598edf8e2afSMika Westerberg struct linux_binprm bprm; 59948e15fc2SNathan Froyd TaskState *ts; 6009349b4f9SAndreas Färber CPUArchState *env; 601db6b81d4SAndreas Färber CPUState *cpu; 602586314f2Sbellard int optind; 60304a6dfebSaurel32 char **target_environ, **wrk; 6047d8cec95Saurel32 char **target_argv; 6057d8cec95Saurel32 int target_argc; 6067d8cec95Saurel32 int i; 607fd4d81ddSArnaud Patard int ret; 60803cfd8faSLaurent Vivier int execfd; 60931e31b8aSbellard 610fe4db84dSDaniel P. Berrange module_call_init(MODULE_INIT_TRACE); 611267f685bSPaolo Bonzini qemu_init_cpu_list(); 612ce008c1fSAndreas Färber module_call_init(MODULE_INIT_QOM); 613ce008c1fSAndreas Färber 614ec45bbe5SSaurav Sachidanand envlist = envlist_create(); 61504a6dfebSaurel32 61604a6dfebSaurel32 /* add current environment into the list */ 61704a6dfebSaurel32 for (wrk = environ; *wrk != NULL; wrk++) { 61804a6dfebSaurel32 (void) envlist_setenv(envlist, *wrk); 61904a6dfebSaurel32 } 62004a6dfebSaurel32 621703e0e89SRichard Henderson /* Read the stack limit from the kernel. If it's "unlimited", 622703e0e89SRichard Henderson then we can do little else besides use the default. */ 623703e0e89SRichard Henderson { 624703e0e89SRichard Henderson struct rlimit lim; 625703e0e89SRichard Henderson if (getrlimit(RLIMIT_STACK, &lim) == 0 62681bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur != RLIM_INFINITY 62781bbe906Stakasi-y@ops.dti.ne.jp && lim.rlim_cur == (target_long)lim.rlim_cur) { 628703e0e89SRichard Henderson guest_stack_size = lim.rlim_cur; 629703e0e89SRichard Henderson } 630703e0e89SRichard Henderson } 631703e0e89SRichard Henderson 632b1f9be31Sj_mayer cpu_model = NULL; 633b5ec5ce0Sjohn cooper 634c5e4a5a9SMagnus Reftel srand(time(NULL)); 635c5e4a5a9SMagnus Reftel 6366533dd6eSLluís Vilanova qemu_add_opts(&qemu_trace_opts); 6376533dd6eSLluís Vilanova 638fc9c5412SJohannes Schauer optind = parse_args(argc, argv); 6394b5dfd82SPeter Maydell 6406533dd6eSLluís Vilanova if (!trace_init_backends()) { 6416533dd6eSLluís Vilanova exit(1); 6426533dd6eSLluís Vilanova } 6436533dd6eSLluís Vilanova trace_init_file(trace_file); 6446533dd6eSLluís Vilanova 64531e31b8aSbellard /* Zero out regs */ 64601ffc75bSbellard memset(regs, 0, sizeof(struct target_pt_regs)); 64731e31b8aSbellard 64831e31b8aSbellard /* Zero out image_info */ 64931e31b8aSbellard memset(info, 0, sizeof(struct image_info)); 65031e31b8aSbellard 651edf8e2afSMika Westerberg memset(&bprm, 0, sizeof (bprm)); 652edf8e2afSMika Westerberg 65374cd30b8Sbellard /* Scan interp_prefix dir for replacement files. */ 65474cd30b8Sbellard init_paths(interp_prefix); 65574cd30b8Sbellard 6564a24a758SPeter Maydell init_qemu_uname_release(); 6574a24a758SPeter Maydell 658768fe76eSYunQiang Su execfd = qemu_getauxval(AT_EXECFD); 659768fe76eSYunQiang Su if (execfd == 0) { 660768fe76eSYunQiang Su execfd = open(filename, O_RDONLY); 661768fe76eSYunQiang Su if (execfd < 0) { 662768fe76eSYunQiang Su printf("Error while loading %s: %s\n", filename, strerror(errno)); 663768fe76eSYunQiang Su _exit(EXIT_FAILURE); 664768fe76eSYunQiang Su } 665768fe76eSYunQiang Su } 666768fe76eSYunQiang Su 66746027c07Sbellard if (cpu_model == NULL) { 668768fe76eSYunQiang Su cpu_model = cpu_get_model(get_elf_eflags(execfd)); 669aaed909aSbellard } 6702278b939SIgor Mammedov cpu_type = parse_cpu_model(cpu_model); 6712278b939SIgor Mammedov 6722b5249b8SIgor Mammedov /* init tcg before creating CPUs and to get qemu_host_page_size */ 673d5ab9713SJan Kiszka tcg_exec_init(0); 6742278b939SIgor Mammedov 6752278b939SIgor Mammedov cpu = cpu_create(cpu_type); 6762994fd96SEduardo Habkost env = cpu->env_ptr; 6770ac46af3SAndreas Färber cpu_reset(cpu); 678b55a37c9SBlue Swirl 679db6b81d4SAndreas Färber thread_cpu = cpu; 68054936004Sbellard 681b92c47c1Sths if (getenv("QEMU_STRACE")) { 682b92c47c1Sths do_strace = 1; 683b92c47c1Sths } 684b92c47c1Sths 685c5e4a5a9SMagnus Reftel if (getenv("QEMU_RAND_SEED")) { 686c5e4a5a9SMagnus Reftel handle_arg_randseed(getenv("QEMU_RAND_SEED")); 687c5e4a5a9SMagnus Reftel } 688c5e4a5a9SMagnus Reftel 68904a6dfebSaurel32 target_environ = envlist_to_environ(envlist, NULL); 69004a6dfebSaurel32 envlist_free(envlist); 691b12b6a18Sths 692379f6698SPaul Brook /* 6932b5249b8SIgor Mammedov * Now that page sizes are configured in tcg_exec_init() we can do 694379f6698SPaul Brook * proper page alignment for guest_base. 695379f6698SPaul Brook */ 696379f6698SPaul Brook guest_base = HOST_PAGE_ALIGN(guest_base); 69768a1c816SPaul Brook 69897cc7560SDr. David Alan Gilbert if (reserved_va || have_guest_base) { 699806d1021SMeador Inge guest_base = init_guest_space(guest_base, reserved_va, 0, 700806d1021SMeador Inge have_guest_base); 701806d1021SMeador Inge if (guest_base == (unsigned long)-1) { 702097b8cb8SPeter Maydell fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address " 703097b8cb8SPeter Maydell "space for use as guest address space (check your virtual " 704097b8cb8SPeter Maydell "memory ulimit setting or reserve less using -R option)\n", 705097b8cb8SPeter Maydell reserved_va); 7064d1275c2SRiku Voipio exit(EXIT_FAILURE); 70797cc7560SDr. David Alan Gilbert } 708806d1021SMeador Inge 709806d1021SMeador Inge if (reserved_va) { 710806d1021SMeador Inge mmap_next_start = reserved_va; 711806d1021SMeador Inge } 71297cc7560SDr. David Alan Gilbert } 713379f6698SPaul Brook 714379f6698SPaul Brook /* 715379f6698SPaul Brook * Read in mmap_min_addr kernel parameter. This value is used 716379f6698SPaul Brook * When loading the ELF image to determine whether guest_base 71714f24e14SRichard Henderson * is needed. It is also used in mmap_find_vma. 718379f6698SPaul Brook */ 71914f24e14SRichard Henderson { 720379f6698SPaul Brook FILE *fp; 721379f6698SPaul Brook 722379f6698SPaul Brook if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) { 723379f6698SPaul Brook unsigned long tmp; 724379f6698SPaul Brook if (fscanf(fp, "%lu", &tmp) == 1) { 725379f6698SPaul Brook mmap_min_addr = tmp; 72613829020SPaolo Bonzini qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n", mmap_min_addr); 727379f6698SPaul Brook } 728379f6698SPaul Brook fclose(fp); 729379f6698SPaul Brook } 730379f6698SPaul Brook } 731379f6698SPaul Brook 7327d8cec95Saurel32 /* 7337d8cec95Saurel32 * Prepare copy of argv vector for target. 7347d8cec95Saurel32 */ 7357d8cec95Saurel32 target_argc = argc - optind; 7367d8cec95Saurel32 target_argv = calloc(target_argc + 1, sizeof (char *)); 7377d8cec95Saurel32 if (target_argv == NULL) { 7387d8cec95Saurel32 (void) fprintf(stderr, "Unable to allocate memory for target_argv\n"); 7394d1275c2SRiku Voipio exit(EXIT_FAILURE); 7407d8cec95Saurel32 } 7417d8cec95Saurel32 7427d8cec95Saurel32 /* 7437d8cec95Saurel32 * If argv0 is specified (using '-0' switch) we replace 7447d8cec95Saurel32 * argv[0] pointer with the given one. 7457d8cec95Saurel32 */ 7467d8cec95Saurel32 i = 0; 7477d8cec95Saurel32 if (argv0 != NULL) { 7487d8cec95Saurel32 target_argv[i++] = strdup(argv0); 7497d8cec95Saurel32 } 7507d8cec95Saurel32 for (; i < target_argc; i++) { 7517d8cec95Saurel32 target_argv[i] = strdup(argv[optind + i]); 7527d8cec95Saurel32 } 7537d8cec95Saurel32 target_argv[target_argc] = NULL; 7547d8cec95Saurel32 755c78d65e8SMarkus Armbruster ts = g_new0(TaskState, 1); 756edf8e2afSMika Westerberg init_task_state(ts); 757edf8e2afSMika Westerberg /* build Task State */ 758edf8e2afSMika Westerberg ts->info = info; 759edf8e2afSMika Westerberg ts->bprm = &bprm; 7600429a971SAndreas Färber cpu->opaque = ts; 761edf8e2afSMika Westerberg task_settid(ts); 762edf8e2afSMika Westerberg 76303cfd8faSLaurent Vivier ret = loader_exec(execfd, filename, target_argv, target_environ, regs, 764fd4d81ddSArnaud Patard info, &bprm); 765fd4d81ddSArnaud Patard if (ret != 0) { 766885c1d10SPeter Maydell printf("Error while loading %s: %s\n", filename, strerror(-ret)); 7674d1275c2SRiku Voipio _exit(EXIT_FAILURE); 76831e31b8aSbellard } 76931e31b8aSbellard 770b12b6a18Sths for (wrk = target_environ; *wrk; wrk++) { 771ec45bbe5SSaurav Sachidanand g_free(*wrk); 772b12b6a18Sths } 773b12b6a18Sths 774ec45bbe5SSaurav Sachidanand g_free(target_environ); 775b12b6a18Sths 77613829020SPaolo Bonzini if (qemu_loglevel_mask(CPU_LOG_PAGE)) { 777379f6698SPaul Brook qemu_log("guest_base 0x%lx\n", guest_base); 77893fcfe39Saliguori log_page_dump(); 77954936004Sbellard 78093fcfe39Saliguori qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); 78193fcfe39Saliguori qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code); 7827c4ee5bcSRichard Henderson qemu_log("start_code 0x" TARGET_ABI_FMT_lx "\n", info->start_code); 7837c4ee5bcSRichard Henderson qemu_log("start_data 0x" TARGET_ABI_FMT_lx "\n", info->start_data); 78493fcfe39Saliguori qemu_log("end_data 0x" TARGET_ABI_FMT_lx "\n", info->end_data); 7857c4ee5bcSRichard Henderson qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n", info->start_stack); 78693fcfe39Saliguori qemu_log("brk 0x" TARGET_ABI_FMT_lx "\n", info->brk); 78793fcfe39Saliguori qemu_log("entry 0x" TARGET_ABI_FMT_lx "\n", info->entry); 7887c4ee5bcSRichard Henderson qemu_log("argv_start 0x" TARGET_ABI_FMT_lx "\n", info->arg_start); 7897c4ee5bcSRichard Henderson qemu_log("env_start 0x" TARGET_ABI_FMT_lx "\n", 7907c4ee5bcSRichard Henderson info->arg_end + (abi_ulong)sizeof(abi_ulong)); 7917c4ee5bcSRichard Henderson qemu_log("auxv_start 0x" TARGET_ABI_FMT_lx "\n", info->saved_auxv); 7922e77eac6Sblueswir1 } 79331e31b8aSbellard 79453a5960aSpbrook target_set_brk(info->brk); 79531e31b8aSbellard syscall_init(); 79666fb9763Sbellard signal_init(); 79731e31b8aSbellard 7989002ec79SRichard Henderson /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay 7999002ec79SRichard Henderson generating the prologue until now so that the prologue can take 8009002ec79SRichard Henderson the real value of GUEST_BASE into account. */ 801b1311c4aSEmilio G. Cota tcg_prologue_init(tcg_ctx); 802e8feb96fSEmilio G. Cota tcg_region_init(); 8039002ec79SRichard Henderson 804cd71c089SLaurent Vivier target_cpu_copy_regs(env, regs); 805cd71c089SLaurent Vivier 80674c33bedSbellard if (gdbstub_port) { 807ff7a981aSPeter Maydell if (gdbserver_start(gdbstub_port) < 0) { 808ff7a981aSPeter Maydell fprintf(stderr, "qemu: could not open gdbserver on port %d\n", 809ff7a981aSPeter Maydell gdbstub_port); 8104d1275c2SRiku Voipio exit(EXIT_FAILURE); 811ff7a981aSPeter Maydell } 812db6b81d4SAndreas Färber gdb_handlesig(cpu, 0); 8131fddef4bSbellard } 8141b6b029eSbellard cpu_loop(env); 8151b6b029eSbellard /* never exits */ 81631e31b8aSbellard return 0; 81731e31b8aSbellard } 818