Message ID | ZylIIkk7k69QIBmn@p100 (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [v2] target/hppa: Add CPU reset method | expand |
On Mon, 4 Nov 2024 at 22:18, Helge Deller <deller@kernel.org> wrote: > > Add the CPU reset method, which resets all CPU registers and the TLB to > zero. Then the CPU will switch to 32-bit mode (PSW_W bit is not set) and > start execution at address 0xf0000004. > Although we currently want to zero out all values in the CPUHPPAState > struct, add the end_reset_fields marker in case the state structs gets > extended with other variables later on which should not be reset. > > Signed-off-by: Helge Deller <deller@gmx.de> > > V2: (based on feedback by Peter Maydell) > - Add end_reset_fields marker > - call reset function in hppa_cpu_initfn() > > diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c > index c38439c180..d12bf65021 100644 > --- a/target/hppa/cpu.c > +++ b/target/hppa/cpu.c > @@ -194,13 +194,8 @@ static void hppa_cpu_realizefn(DeviceState *dev, Error **errp) > > static void hppa_cpu_initfn(Object *obj) > { > - CPUState *cs = CPU(obj); > - HPPACPU *cpu = HPPA_CPU(obj); > - CPUHPPAState *env = &cpu->env; > - > - cs->exception_index = -1; > - cpu_hppa_loaded_fr0(env); > - cpu_hppa_put_psw(env, PSW_W); > + /* inital values loaded via reset in hppa_cpu_reset_hold() */ > + resettable_reset(obj, RESET_TYPE_COLD); You can't call reset from the CPU initfn (among other things, the CPU object isn't fully constructed until its realize method has been called). CPU reset is rather awkward at the moment because it doesn't happen automatically (because CPUs are not subtypes of Device). So generally the way it works at the moment is that the machine model code arranges to reset the CPU object "manually". For Arm we do this as part of setting up the CPU for however we're booting the kernel in hw/arm/boot.c. It looks to me like for HPPA the best place would be to call cpu_reset() in hppa_machine_reset(), in the loop just before doing the other CPU setup like calling cpu_set_pc(). > } Otherwise this looks good. thanks -- PMM
diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index c38439c180..d12bf65021 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -194,13 +194,8 @@ static void hppa_cpu_realizefn(DeviceState *dev, Error **errp) static void hppa_cpu_initfn(Object *obj) { - CPUState *cs = CPU(obj); - HPPACPU *cpu = HPPA_CPU(obj); - CPUHPPAState *env = &cpu->env; - - cs->exception_index = -1; - cpu_hppa_loaded_fr0(env); - cpu_hppa_put_psw(env, PSW_W); + /* inital values loaded via reset in hppa_cpu_reset_hold() */ + resettable_reset(obj, RESET_TYPE_COLD); } static ObjectClass *hppa_cpu_class_by_name(const char *cpu_model) @@ -235,15 +230,39 @@ static const TCGCPUOps hppa_tcg_ops = { #endif /* !CONFIG_USER_ONLY */ }; +static void hppa_cpu_reset_hold(Object *obj, ResetType type) +{ + HPPACPU *cpu = HPPA_CPU(obj); + HPPACPUClass *scc = HPPA_CPU_GET_CLASS(cpu); + CPUHPPAState *env = &cpu->env; + CPUState *cs = CPU(cpu); + + if (scc->parent_phases.hold) { + scc->parent_phases.hold(obj, type); + } + + memset(env, 0, offsetof(CPUHPPAState, end_reset_fields)); + cpu_set_pc(cs, 0xf0000004); + cpu_hppa_put_psw(env, hppa_is_pa20(env) ? PSW_W : 0); + cpu_hppa_loaded_fr0(env); + + cs->exception_index = -1; + cs->halted = 0; +} + static void hppa_cpu_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); CPUClass *cc = CPU_CLASS(oc); HPPACPUClass *acc = HPPA_CPU_CLASS(oc); + ResettableClass *rc = RESETTABLE_CLASS(oc); device_class_set_parent_realize(dc, hppa_cpu_realizefn, &acc->parent_realize); + resettable_class_set_parent_phases(rc, NULL, hppa_cpu_reset_hold, NULL, + &acc->parent_phases); + cc->class_by_name = hppa_cpu_class_by_name; cc->has_work = hppa_cpu_has_work; cc->mmu_index = hppa_cpu_mmu_index; diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index e45ba50a59..32a674a8b8 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -263,6 +263,9 @@ typedef struct CPUArchState { IntervalTreeRoot tlb_root; HPPATLBEntry tlb[HPPA_TLB_ENTRIES]; + + /* Fields up to this point are cleared by a CPU reset */ + struct {} end_reset_fields; } CPUHPPAState; /** @@ -281,6 +284,7 @@ struct ArchCPU { /** * HPPACPUClass: * @parent_realize: The parent class' realize handler. + * @parent_phases: The parent class' reset phase handlers. * * An HPPA CPU model. */ @@ -288,6 +292,7 @@ struct HPPACPUClass { CPUClass parent_class; DeviceRealize parent_realize; + ResettablePhases parent_phases; }; #include "exec/cpu-all.h"
Add the CPU reset method, which resets all CPU registers and the TLB to zero. Then the CPU will switch to 32-bit mode (PSW_W bit is not set) and start execution at address 0xf0000004. Although we currently want to zero out all values in the CPUHPPAState struct, add the end_reset_fields marker in case the state structs gets extended with other variables later on which should not be reset. Signed-off-by: Helge Deller <deller@gmx.de> V2: (based on feedback by Peter Maydell) - Add end_reset_fields marker - call reset function in hppa_cpu_initfn()