#include "exec/exec-all.h"
#include "exec/gdbstub.h"
#include "gdbstub/user.h"
-#include "tcg/tcg.h"
+#include "tcg/startup.h"
#include "qemu/timer.h"
#include "qemu/envlist.h"
#include "qemu/guest-random.h"
char *exec_path;
char real_exec_path[PATH_MAX];
-int singlestep;
+static bool opt_one_insn_per_tb;
static const char *argv0;
static const char *gdbstub;
static envlist_t *envlist;
# if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
# if TARGET_VIRT_ADDR_SPACE_BITS == 32 && \
(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(CPU) (0xfffffffful & TARGET_PAGE_MASK)
+# define MAX_RESERVED_VA(CPU) 0xfffffffful
# else
-# define MAX_RESERVED_VA(CPU) (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
+# define MAX_RESERVED_VA(CPU) ((1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1)
# endif
# else
# define MAX_RESERVED_VA(CPU) 0
Discard information about the parent threads. */
CPU_FOREACH_SAFE(cpu, next_cpu) {
if (cpu != thread_cpu) {
- QTAILQ_REMOVE_RCU(&cpus, cpu, node);
+ QTAILQ_REMOVE_RCU(&cpus_queue, cpu, node);
}
}
qemu_init_cpu_list();
{
CPUState *cpu = env_cpu(env);
CPUState *new_cpu = cpu_create(cpu_type);
- CPUArchState *new_env = new_cpu->env_ptr;
+ CPUArchState *new_env = cpu_env(new_cpu);
CPUBreakpoint *bp;
/* Reset non arch specific state */
{
cpu_model = strdup(arg);
if (cpu_model == NULL || is_help_option(cpu_model)) {
- /* XXX: implement xxx_cpu_list for targets that still miss it */
-#if defined(cpu_list)
- cpu_list();
-#endif
+ list_cpus();
exit(EXIT_FAILURE);
}
}
{
char *p;
int shift = 0;
- reserved_va = strtoul(arg, &p, 0);
+ unsigned long val;
+
+ val = strtoul(arg, &p, 0);
switch (*p) {
case 'k':
case 'K':
break;
}
if (shift) {
- unsigned long unshifted = reserved_va;
+ unsigned long unshifted = val;
p++;
- reserved_va <<= shift;
- if (reserved_va >> shift != unshifted) {
+ val <<= shift;
+ if (val >> shift != unshifted) {
fprintf(stderr, "Reserved virtual address too big\n");
exit(EXIT_FAILURE);
}
fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
exit(EXIT_FAILURE);
}
+ /* The representation is size - 1, with 0 remaining "default". */
+ reserved_va = val ? val - 1 : 0;
}
-static void handle_arg_singlestep(const char *arg)
+static void handle_arg_one_insn_per_tb(const char *arg)
{
- singlestep = 1;
+ opt_one_insn_per_tb = true;
}
static void handle_arg_strace(const char *arg)
"logfile", "write logs to 'logfile' (default stderr)"},
{"p", "QEMU_PAGESIZE", true, handle_arg_pagesize,
"pagesize", "set the host page size to 'pagesize'"},
- {"singlestep", "QEMU_SINGLESTEP", false, handle_arg_singlestep,
- "", "run in singlestep mode"},
+ {"one-insn-per-tb",
+ "QEMU_ONE_INSN_PER_TB", false, handle_arg_one_insn_per_tb,
+ "", "run with one guest instruction per emulated TB"},
{"strace", "QEMU_STRACE", false, handle_arg_strace,
"", "log system calls"},
{"seed", "QEMU_RAND_SEED", true, handle_arg_seed,
envlist = envlist_create();
- /* add current environment into the list */
+ /*
+ * add current environment into the list
+ * envlist_setenv adds to the front of the list; to preserve environ
+ * order add from back to front
+ */
for (wrk = environ; *wrk != NULL; wrk++) {
+ continue;
+ }
+ while (wrk != environ) {
+ wrk--;
(void) envlist_setenv(envlist, *wrk);
}
/* init tcg before creating CPUs and to get qemu_host_page_size */
{
- AccelClass *ac = ACCEL_GET_CLASS(current_accel());
+ AccelState *accel = current_accel();
+ AccelClass *ac = ACCEL_GET_CLASS(accel);
accel_init_interfaces(ac);
+ object_property_set_bool(OBJECT(accel), "one-insn-per-tb",
+ opt_one_insn_per_tb, &error_abort);
ac->init_machine(NULL);
}
cpu = cpu_create(cpu_type);
- env = cpu->env_ptr;
+ env = cpu_env(cpu);
cpu_reset(cpu);
thread_cpu = cpu;
*/
max_reserved_va = MAX_RESERVED_VA(cpu);
if (reserved_va != 0) {
- if (reserved_va % qemu_host_page_size) {
+ if ((reserved_va + 1) % qemu_host_page_size) {
char *s = size_to_str(qemu_host_page_size);
fprintf(stderr, "Reserved virtual address not aligned mod %s\n", s);
g_free(s);
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;
+ /* MAX_RESERVED_VA + 1 is a large power of 2, so is aligned. */
+ reserved_va = max_reserved_va;
}
+ /*
+ * Temporarily disable
+ * "comparison is always false due to limited range of data type"
+ * due to comparison between (possible) uint64_t and uintptr_t.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits"
+
+ /*
+ * Select an initial value for task_unmapped_base that is in range.
+ */
+ if (reserved_va) {
+ if (TASK_UNMAPPED_BASE < reserved_va) {
+ task_unmapped_base = TASK_UNMAPPED_BASE;
+ } else {
+ /* The most common default formula is TASK_SIZE / 3. */
+ task_unmapped_base = TARGET_PAGE_ALIGN(reserved_va / 3);
+ }
+ } else if (TASK_UNMAPPED_BASE < UINTPTR_MAX) {
+ task_unmapped_base = TASK_UNMAPPED_BASE;
+ } else {
+ /* 32-bit host: pick something medium size. */
+ task_unmapped_base = 0x10000000;
+ }
+ mmap_next_start = task_unmapped_base;
+
+ /* Similarly for elf_et_dyn_base. */
+ if (reserved_va) {
+ if (ELF_ET_DYN_BASE < reserved_va) {
+ elf_et_dyn_base = ELF_ET_DYN_BASE;
+ } else {
+ /* The most common default formula is TASK_SIZE / 3 * 2. */
+ elf_et_dyn_base = TARGET_PAGE_ALIGN(reserved_va / 3) * 2;
+ }
+ } else if (ELF_ET_DYN_BASE < UINTPTR_MAX) {
+ elf_et_dyn_base = ELF_ET_DYN_BASE;
+ } else {
+ /* 32-bit host: pick something medium size. */
+ elf_et_dyn_base = 0x18000000;
+ }
+
+#pragma GCC diagnostic pop
+
{
Error *err = NULL;
if (seed_optarg != NULL) {
fprintf(f, "page layout changed following binary load\n");
page_dump(f);
- fprintf(f, "start_brk 0x" TARGET_ABI_FMT_lx "\n",
- info->start_brk);
fprintf(f, "end_code 0x" TARGET_ABI_FMT_lx "\n",
info->end_code);
fprintf(f, "start_code 0x" TARGET_ABI_FMT_lx "\n",
/* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
generating the prologue until now so that the prologue can take
the real value of GUEST_BASE into account. */
- tcg_prologue_init(tcg_ctx);
+ tcg_prologue_init();
target_cpu_copy_regs(env, regs);