aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpu-all.h2
-rw-r--r--exec.c12
-rw-r--r--linux-user/syscall.c3
3 files changed, 15 insertions, 2 deletions
diff --git a/cpu-all.h b/cpu-all.h
index 8a4730d..0ad50e8 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -754,6 +754,8 @@ void page_unprotect_range(target_ulong data, target_ulong data_size);
#endif /* SINGLE_CPU_DEFINES */
+CPUState *cpu_copy(CPUState *env);
+
void cpu_dump_state(CPUState *env, FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
int flags);
diff --git a/exec.c b/exec.c
index 2e09b4b..37d58a4 100644
--- a/exec.c
+++ b/exec.c
@@ -1222,6 +1222,18 @@ void cpu_abort(CPUState *env, const char *fmt, ...)
abort();
}
+CPUState *cpu_copy(CPUState *env)
+{
+ CPUState *new_env = cpu_init();
+ /* preserve chaining and index */
+ CPUState *next_cpu = new_env->next_cpu;
+ int cpu_index = new_env->cpu_index;
+ memcpy(new_env, env, sizeof(CPUState));
+ new_env->next_cpu = next_cpu;
+ new_env->cpu_index = cpu_index;
+ return new_env;
+}
+
#if !defined(CONFIG_USER_ONLY)
/* NOTE: if flush_global is true, also flush global entries (not
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f3f97b0..76b3652 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1720,8 +1720,7 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp)
ts->next = first_task_state;
first_task_state = ts;
/* we create a new CPU instance. */
- new_env = cpu_init();
- memcpy(new_env, env, sizeof(CPUState));
+ new_env = cpu_copy(env);
#if defined(TARGET_I386)
if (!newsp)
newsp = env->regs[R_ESP];