#include "qemu-version.h"
#include <sys/syscall.h>
#include <sys/resource.h>
+#include <sys/shm.h>
#include "qapi/error.h"
#include "qemu.h"
#include "qemu/error-report.h"
#include "qemu/help_option.h"
#include "qemu/module.h"
+#include "qemu/plugin.h"
#include "cpu.h"
#include "exec/exec-all.h"
-#include "tcg.h"
+#include "tcg/tcg.h"
#include "qemu/timer.h"
#include "qemu/envlist.h"
#include "qemu/guest-random.h"
int singlestep;
static const char *argv0;
-static int gdbstub_port;
+static const char *gdbstub;
static envlist_t *envlist;
static const char *cpu_model;
static const char *cpu_type;
static const char *seed_optarg;
unsigned long mmap_min_addr;
unsigned long guest_base;
-int have_guest_base;
+bool have_guest_base;
+
+/*
+ * Used to implement backwards-compatibility for the `-strace`, and
+ * QEMU_STRACE options. Without this, the QEMU_LOG can be overwritten by
+ * -strace, or vice versa.
+ */
+static bool enable_strace;
+
+/*
+ * The last log mask given by the user in an environment variable or argument.
+ * Used to support command line arguments overriding environment variables.
+ */
+static int last_log_mask;
/*
* When running 32-on-64 we should make sure we can fit all of the possible
(TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
/* There are a number of places where we assign reserved_va to a variable
of type abi_ulong and expect it to fit. Avoid the last page. */
-# define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK)
+# define MAX_RESERVED_VA(CPU) (0xfffffffful & TARGET_PAGE_MASK)
# else
-# define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
+# define MAX_RESERVED_VA(CPU) (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
# endif
# else
-# define MAX_RESERVED_VA 0
+# define MAX_RESERVED_VA(CPU) 0
# endif
#endif
by remapping the process stack directly at the right place */
unsigned long guest_stack_size = 8 * 1024 * 1024UL;
-void gemu_log(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-}
-
#if defined(TARGET_I386)
int cpu_get_pic_interrupt(CPUX86State *env)
{
static void handle_arg_log(const char *arg)
{
- int mask;
-
- mask = qemu_str_to_log_mask(arg);
- if (!mask) {
+ last_log_mask = qemu_str_to_log_mask(arg);
+ if (!last_log_mask) {
qemu_print_log_usage(stdout);
exit(EXIT_FAILURE);
}
- qemu_log_needs_buffers();
- qemu_set_log(mask);
}
static void handle_arg_dfilter(const char *arg)
{
- qemu_set_dfilter_ranges(arg, NULL);
+ qemu_set_dfilter_ranges(arg, &error_fatal);
}
static void handle_arg_log_filename(const char *arg)
static void handle_arg_gdb(const char *arg)
{
- gdbstub_port = atoi(arg);
+ gdbstub = g_strdup(arg);
}
static void handle_arg_uname(const char *arg)
static void handle_arg_guest_base(const char *arg)
{
guest_base = strtol(arg, NULL, 0);
- have_guest_base = 1;
+ have_guest_base = true;
}
static void handle_arg_reserved_va(const char *arg)
unsigned long unshifted = reserved_va;
p++;
reserved_va <<= shift;
- if (reserved_va >> shift != unshifted
- || (MAX_RESERVED_VA && reserved_va > MAX_RESERVED_VA)) {
+ if (reserved_va >> shift != unshifted) {
fprintf(stderr, "Reserved virtual address too big\n");
exit(EXIT_FAILURE);
}
static void handle_arg_strace(const char *arg)
{
- do_strace = 1;
+ enable_strace = true;
}
static void handle_arg_version(const char *arg)
trace_file = trace_opt_parse(arg);
}
+#if defined(TARGET_XTENSA)
+static void handle_arg_abi_call0(const char *arg)
+{
+ xtensa_set_abi_call0();
+}
+#endif
+
+static QemuPluginList plugins = QTAILQ_HEAD_INITIALIZER(plugins);
+
+#ifdef CONFIG_PLUGIN
+static void handle_arg_plugin(const char *arg)
+{
+ qemu_plugin_opt_parse(arg, &plugins);
+}
+#endif
+
struct qemu_argument {
const char *argv;
const char *env;
"", "Seed for pseudo-random number generator"},
{"trace", "QEMU_TRACE", true, handle_arg_trace,
"", "[[enable=]<pattern>][,events=<file>][,file=<file>]"},
+#ifdef CONFIG_PLUGIN
+ {"plugin", "QEMU_PLUGIN", true, handle_arg_plugin,
+ "", "[file=]<file>[,arg=<string>]"},
+#endif
{"version", "QEMU_VERSION", false, handle_arg_version,
"", "display version information and exit"},
+#if defined(TARGET_XTENSA)
+ {"xtensa-abi-call0", "QEMU_XTENSA_ABI_CALL0", false, handle_arg_abi_call0,
+ "", "assume CALL0 Xtensa ABI"},
+#endif
{NULL, NULL, false, NULL, NULL, NULL}
};
int i;
int ret;
int execfd;
+ int log_mask;
+ unsigned long max_reserved_va;
error_init(argv[0]);
module_call_init(MODULE_INIT_TRACE);
cpu_model = NULL;
qemu_add_opts(&qemu_trace_opts);
+ qemu_plugin_add_opts();
optind = parse_args(argc, argv);
+ log_mask = last_log_mask | (enable_strace ? LOG_STRACE : 0);
+ if (log_mask) {
+ qemu_log_needs_buffers();
+ qemu_set_log(log_mask);
+ }
+
if (!trace_init_backends()) {
exit(1);
}
trace_init_file(trace_file);
+ if (qemu_plugin_load_list(&plugins)) {
+ exit(1);
+ }
/* Zero out regs */
memset(regs, 0, sizeof(struct target_pt_regs));
/* init tcg before creating CPUs and to get qemu_host_page_size */
tcg_exec_init(0);
- /* Reserving *too* much vm space via mmap can run into problems
- with rlimits, oom due to page table creation, etc. We will still try it,
- if directed by the command-line option, but not by default. */
- if (HOST_LONG_BITS == 64 &&
- TARGET_VIRT_ADDR_SPACE_BITS <= 32 &&
- reserved_va == 0) {
- /* reserved_va must be aligned with the host page size
- * as it is used with mmap()
- */
- reserved_va = MAX_RESERVED_VA & qemu_host_page_mask;
- }
-
cpu = cpu_create(cpu_type);
env = cpu->env_ptr;
cpu_reset(cpu);
-
thread_cpu = cpu;
- if (getenv("QEMU_STRACE")) {
- do_strace = 1;
+ /*
+ * Reserving too much vm space via mmap can run into problems
+ * with rlimits, oom due to page table creation, etc. We will
+ * still try it, if directed by the command-line option, but
+ * not by default.
+ */
+ max_reserved_va = MAX_RESERVED_VA(cpu);
+ if (reserved_va != 0) {
+ if (max_reserved_va && reserved_va > max_reserved_va) {
+ fprintf(stderr, "Reserved virtual address too big\n");
+ exit(EXIT_FAILURE);
+ }
+ } else if (HOST_LONG_BITS == 64 && TARGET_VIRT_ADDR_SPACE_BITS <= 32) {
+ /*
+ * reserved_va must be aligned with the host page size
+ * as it is used with mmap()
+ */
+ reserved_va = max_reserved_va & qemu_host_page_mask;
}
- if (seed_optarg == NULL) {
- seed_optarg = getenv("QEMU_RAND_SEED");
- }
{
Error *err = NULL;
if (seed_optarg != NULL) {
target_environ = envlist_to_environ(envlist, NULL);
envlist_free(envlist);
- /*
- * Now that page sizes are configured in tcg_exec_init() we can do
- * proper page alignment for guest_base.
- */
- guest_base = HOST_PAGE_ALIGN(guest_base);
-
- if (reserved_va || have_guest_base) {
- guest_base = init_guest_space(guest_base, reserved_va, 0,
- have_guest_base);
- if (guest_base == (unsigned long)-1) {
- fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address "
- "space for use as guest address space (check your virtual "
- "memory ulimit setting or reserve less using -R option)\n",
- reserved_va);
- exit(EXIT_FAILURE);
- }
-
- if (reserved_va) {
- mmap_next_start = reserved_va;
- }
- }
-
/*
* Read in mmap_min_addr kernel parameter. This value is used
* When loading the ELF image to determine whether guest_base
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
qemu_log("guest_base 0x%lx\n", guest_base);
- log_page_dump();
+ log_page_dump("binary load");
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
target_cpu_copy_regs(env, regs);
- if (gdbstub_port) {
- if (gdbserver_start(gdbstub_port) < 0) {
- fprintf(stderr, "qemu: could not open gdbserver on port %d\n",
- gdbstub_port);
+ if (gdbstub) {
+ if (gdbserver_start(gdbstub) < 0) {
+ fprintf(stderr, "qemu: could not open gdbserver on %s\n",
+ gdbstub);
exit(EXIT_FAILURE);
}
gdb_handlesig(cpu, 0);