diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2012-05-10 15:32:50 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2012-05-10 15:32:50 +0000 |
commit | ad41b6e360202138f6641219e1ffe01ab7e874b6 (patch) | |
tree | 432e98730ee35ad14bb4f6d75d5c4c221aa1547f | |
parent | 9f34841a812dc622f8de98bc6141925c22f0ee93 (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.h | 1 | ||||
-rw-r--r-- | exec.c | 9 | ||||
-rw-r--r-- | include/qemu/cpu.h | 16 | ||||
-rw-r--r-- | linux-user/syscall.c | 2 | ||||
-rw-r--r-- | qom/cpu.c | 7 | ||||
-rw-r--r-- | target-alpha/cpu-qom.h | 2 | ||||
-rw-r--r-- | target-arm/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-cris/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-i386/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-lm32/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-m68k/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-microblaze/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-mips/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-ppc/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-s390x/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-sh4/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-sparc/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-unicore32/cpu-qom.h | 1 | ||||
-rw-r--r-- | target-xtensa/cpu-qom.h | 1 |
19 files changed, 45 insertions, 5 deletions
@@ -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 @@ -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 @@ -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 |