aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2012-05-10 15:32:50 +0000
committerPeter Maydell <peter.maydell@linaro.org>2012-05-10 15:32:50 +0000
commitad41b6e360202138f6641219e1ffe01ab7e874b6 (patch)
tree432e98730ee35ad14bb4f6d75d5c4c221aa1547f
parent9f34841a812dc622f8de98bc6141925c22f0ee93 (diff)
qom/cpu: Add copy methodcpu-copy-method
Add a copy method to the QOM CPUClass, which creates a new CPU object as a copy of an existing one. This replaces the direct call to cpu_copy() made in linux-user when handling creating a new pthread; the motivation is to allow target-specific CPU subclasses to override the copy method if there is something in their CPUState which cannot be handled with a shallow copy. In particular we will use this to avoid leaking the hashtable used for ARM's new cp15 implementation. Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--cpu-all.h1
-rw-r--r--exec.c9
-rw-r--r--include/qemu/cpu.h16
-rw-r--r--linux-user/syscall.c2
-rw-r--r--qom/cpu.c7
-rw-r--r--target-alpha/cpu-qom.h2
-rw-r--r--target-arm/cpu-qom.h1
-rw-r--r--target-cris/cpu-qom.h1
-rw-r--r--target-i386/cpu-qom.h1
-rw-r--r--target-lm32/cpu-qom.h1
-rw-r--r--target-m68k/cpu-qom.h1
-rw-r--r--target-microblaze/cpu-qom.h1
-rw-r--r--target-mips/cpu-qom.h1
-rw-r--r--target-ppc/cpu-qom.h1
-rw-r--r--target-s390x/cpu-qom.h1
-rw-r--r--target-sh4/cpu-qom.h1
-rw-r--r--target-sparc/cpu-qom.h1
-rw-r--r--target-unicore32/cpu-qom.h1
-rw-r--r--target-xtensa/cpu-qom.h1
19 files changed, 45 insertions, 5 deletions
diff --git a/cpu-all.h b/cpu-all.h
index 028528f0be..1b39fc9251 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -332,7 +332,6 @@ void page_set_flags(target_ulong start, target_ulong end, int flags);
int page_check_range(target_ulong start, target_ulong len, int flags);
#endif
-CPUArchState *cpu_copy(CPUArchState *env);
CPUArchState *qemu_get_cpu(int cpu);
#define CPU_DUMP_CODE 0x00010000
diff --git a/exec.c b/exec.c
index 0607c9b6aa..f567a386fe 100644
--- a/exec.c
+++ b/exec.c
@@ -1876,8 +1876,13 @@ void cpu_abort(CPUArchState *env, const char *fmt, ...)
abort();
}
-CPUArchState *cpu_copy(CPUArchState *env)
+/* Note that this function is suitable for use as the CPUClass copy
+ * callback if your CPUArchState has no members which are unsuitable
+ * for simple shallow copy via memcpy().
+ */
+CPUState *cpu_default_copy(CPUState *oldcpu)
{
+ CPUArchState *env = CPU_GET_ENV(oldcpu);
CPUArchState *new_env = cpu_init(env->cpu_model_str);
CPUArchState *next_cpu = new_env->next_cpu;
int cpu_index = new_env->cpu_index;
@@ -1907,7 +1912,7 @@ CPUArchState *cpu_copy(CPUArchState *env)
}
#endif
- return new_env;
+ return ENV_GET_CPU(new_env);
}
#if !defined(CONFIG_USER_ONLY)
diff --git a/include/qemu/cpu.h b/include/qemu/cpu.h
index 78b65b35fc..e24d116c51 100644
--- a/include/qemu/cpu.h
+++ b/include/qemu/cpu.h
@@ -40,6 +40,7 @@ typedef struct CPUState CPUState;
/**
* CPUClass:
* @reset: Callback to reset the #CPUState to its initial state.
+ * @copy: Callback to create a new #CPUState as a copy of this one.
*
* Represents a CPU family or model.
*/
@@ -49,6 +50,7 @@ typedef struct CPUClass {
/*< public >*/
void (*reset)(CPUState *cpu);
+ CPUState *(*copy)(CPUState *cpu);
} CPUClass;
/**
@@ -71,5 +73,19 @@ struct CPUState {
*/
void cpu_reset(CPUState *cpu);
+/**
+ * cpu_copy:
+ * @cpu: The CPU whose state is to be copied to create a new CPU state.
+ */
+CPUState *cpu_copy(CPUState *cpu);
+
+/**
+ * cpu_default_copy:
+ * An implementation of the cpu_copy method suitable for
+ * use if the CPUClass subclass:
+ * (a) provides CPU_GET_ENV/ENV_GET_CPU macros in its cpu.h
+ * (b) has only members which can be safely shallow copied.
+ */
+CPUState *cpu_default_copy(CPUState *oldcpu);
#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 20d2a74877..bdae3274b3 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4260,7 +4260,7 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
ts = g_malloc0(sizeof(TaskState));
init_task_state(ts);
/* we create a new CPU instance. */
- new_env = cpu_copy(env);
+ new_env = CPU_GET_ENV(cpu_copy(ENV_GET_CPU(env)));
#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
cpu_state_reset(new_env);
#endif
diff --git a/qom/cpu.c b/qom/cpu.c
index 5b360469c5..5d8a4770b9 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -30,6 +30,12 @@ void cpu_reset(CPUState *cpu)
}
}
+CPUState *cpu_copy(CPUState *cpu)
+{
+ CPUClass *klass = CPU_GET_CLASS(cpu);
+ return (*klass->copy)(cpu);
+}
+
static void cpu_common_reset(CPUState *cpu)
{
}
@@ -39,6 +45,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
CPUClass *k = CPU_CLASS(klass);
k->reset = cpu_common_reset;
+ k->copy = cpu_default_copy;
}
static TypeInfo cpu_type_info = {
diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h
index 6b4ca6d1d1..5de9a4830b 100644
--- a/target-alpha/cpu-qom.h
+++ b/target-alpha/cpu-qom.h
@@ -66,6 +66,6 @@ static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env)
}
#define ENV_GET_CPU(e) CPU(alpha_env_get_cpu(e))
-
+#define CPU_GET_ENV(c) (&ALPHA_CPU(c)->env)
#endif
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index a61c68d21b..d9cf6d1a99 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -102,6 +102,7 @@ static inline ARMCPU *arm_env_get_cpu(CPUARMState *env)
}
#define ENV_GET_CPU(e) CPU(arm_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&ARM_CPU(c)->env)
void arm_cpu_realize(ARMCPU *cpu);
diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h
index d0e5f04f78..a5ee514020 100644
--- a/target-cris/cpu-qom.h
+++ b/target-cris/cpu-qom.h
@@ -65,6 +65,7 @@ static inline CRISCPU *cris_env_get_cpu(CPUCRISState *env)
}
#define ENV_GET_CPU(e) CPU(cris_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&CRIS_CPU(c)->env)
#endif
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 40635c4b1c..c223d545ff 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -70,6 +70,7 @@ static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
}
#define ENV_GET_CPU(e) CPU(x86_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&X86_CPU(c)->env)
#endif
diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h
index 4ae2eddafb..7a6f8e8f12 100644
--- a/target-lm32/cpu-qom.h
+++ b/target-lm32/cpu-qom.h
@@ -66,6 +66,7 @@ static inline LM32CPU *lm32_env_get_cpu(CPULM32State *env)
}
#define ENV_GET_CPU(e) CPU(lm32_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&LM32_CPU(c)->env)
#endif
diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h
index 805786b04d..d007cfe23b 100644
--- a/target-m68k/cpu-qom.h
+++ b/target-m68k/cpu-qom.h
@@ -65,6 +65,7 @@ static inline M68kCPU *m68k_env_get_cpu(CPUM68KState *env)
}
#define ENV_GET_CPU(e) CPU(m68k_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&M68K_CPU(c)->env)
#endif
diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h
index 4b23303b6d..c4a5f04304 100644
--- a/target-microblaze/cpu-qom.h
+++ b/target-microblaze/cpu-qom.h
@@ -65,6 +65,7 @@ static inline MicroBlazeCPU *mb_env_get_cpu(CPUMBState *env)
}
#define ENV_GET_CPU(e) CPU(mb_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&MICROBLAZE_CPU(c)->env)
#endif
diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h
index 6e2237123a..796c4e5848 100644
--- a/target-mips/cpu-qom.h
+++ b/target-mips/cpu-qom.h
@@ -69,6 +69,7 @@ static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env)
}
#define ENV_GET_CPU(e) CPU(mips_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&MIPS_CPU(c)->env)
#endif
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
index fef6f95a04..e2c4450b90 100644
--- a/target-ppc/cpu-qom.h
+++ b/target-ppc/cpu-qom.h
@@ -72,6 +72,7 @@ static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
}
#define ENV_GET_CPU(e) CPU(ppc_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&POWERPC_CPU(c)->env)
#endif
diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h
index 6fa55a80a5..d5779c8278 100644
--- a/target-s390x/cpu-qom.h
+++ b/target-s390x/cpu-qom.h
@@ -66,6 +66,7 @@ static inline S390CPU *s390_env_get_cpu(CPUS390XState *env)
}
#define ENV_GET_CPU(e) CPU(s390_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&S390_CPU(c)->env)
#endif
diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h
index c41164aa22..6a9b57e78a 100644
--- a/target-sh4/cpu-qom.h
+++ b/target-sh4/cpu-qom.h
@@ -65,6 +65,7 @@ static inline SuperHCPU *sh_env_get_cpu(CPUSH4State *env)
}
#define ENV_GET_CPU(e) CPU(sh_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&SUPERH_CPU(c)->env)
#endif
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
index 3d3ac0fcef..2362ecebac 100644
--- a/target-sparc/cpu-qom.h
+++ b/target-sparc/cpu-qom.h
@@ -70,6 +70,7 @@ static inline SPARCCPU *sparc_env_get_cpu(CPUSPARCState *env)
}
#define ENV_GET_CPU(e) CPU(sparc_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&SPARC_CPU(c)->env)
#endif
diff --git a/target-unicore32/cpu-qom.h b/target-unicore32/cpu-qom.h
index 342d85e39b..3e653d7b3a 100644
--- a/target-unicore32/cpu-qom.h
+++ b/target-unicore32/cpu-qom.h
@@ -54,6 +54,7 @@ static inline UniCore32CPU *uc32_env_get_cpu(CPUUniCore32State *env)
}
#define ENV_GET_CPU(e) CPU(uc32_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&UNICORE32_CPU(c)->env)
#endif
diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h
index 1fd2f274a1..826483ea5b 100644
--- a/target-xtensa/cpu-qom.h
+++ b/target-xtensa/cpu-qom.h
@@ -75,6 +75,7 @@ static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env)
}
#define ENV_GET_CPU(e) CPU(xtensa_env_get_cpu(e))
+#define CPU_GET_ENV(c) (&XTENSA_CPU(c)->env)
#endif