hw/ppc: Reset timebase facilities on machine reset

Lower interrupts, delete timers, and set time facility registers
back to initial state on machine reset.

This is not so important for record-replay since timebase and
decrementer are migrated, but it gives a cleaner reset state.

Cc: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Cc: BALATON Zoltan <balaton@eik.bme.hu>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
[ clg: checkpatch.pl fixes ]
Signed-off-by: Cédric Le Goater <clg@kaod.org>
master
Nicholas Piggin 2023-08-08 14:19:53 +10:00 committed by Cédric Le Goater
parent 578912ad73
commit 30d0647bcf
7 changed files with 36 additions and 21 deletions

View File

@ -81,6 +81,7 @@ static void ppc_heathrow_reset(void *opaque)
{
PowerPCCPU *cpu = opaque;
cpu_ppc_tb_reset(&cpu->env);
cpu_reset(CPU(cpu));
}

View File

@ -99,6 +99,7 @@ static void pegasos2_cpu_reset(void *opaque)
cpu->env.gpr[1] = 2 * VOF_STACK_SIZE - 0x20;
cpu->env.nip = 0x100;
}
cpu_ppc_tb_reset(&cpu->env);
}
static void pegasos2_pci_irq(void *opaque, int n, int level)

View File

@ -61,6 +61,8 @@ static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu)
hreg_compute_hflags(env);
ppc_maybe_interrupt(env);
cpu_ppc_tb_reset(env);
pcc->intc_reset(pc->chip, cpu);
}

View File

@ -942,23 +942,6 @@ void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value)
&tb_env->purr_offset, value);
}
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
{
CPUPPCState *env = opaque;
PowerPCCPU *cpu = env_archcpu(env);
ppc_tb_t *tb_env = env->tb_env;
tb_env->tb_freq = freq;
tb_env->decr_freq = freq;
/* There is a bug in Linux 2.4 kernels:
* if a decrementer exception is pending when it enables msr_ee at startup,
* it's not ready to handle it...
*/
_cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 32);
_cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 32);
cpu_ppc_store_purr(env, 0x0000000000000000ULL);
}
static void timebase_save(PPCTimebase *tb)
{
uint64_t ticks = cpu_get_host_ticks();
@ -1060,7 +1043,7 @@ const VMStateDescription vmstate_ppc_timebase = {
};
/* Set up (once) timebase frequency (in Hz) */
clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
void cpu_ppc_tb_init(CPUPPCState *env, uint32_t freq)
{
PowerPCCPU *cpu = env_archcpu(env);
ppc_tb_t *tb_env;
@ -1081,9 +1064,33 @@ clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
} else {
tb_env->hdecr_timer = NULL;
}
cpu_ppc_set_tb_clk(env, freq);
return &cpu_ppc_set_tb_clk;
tb_env->tb_freq = freq;
tb_env->decr_freq = freq;
}
void cpu_ppc_tb_reset(CPUPPCState *env)
{
PowerPCCPU *cpu = env_archcpu(env);
ppc_tb_t *tb_env = env->tb_env;
timer_del(tb_env->decr_timer);
ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 0);
tb_env->decr_next = 0;
if (tb_env->hdecr_timer != NULL) {
timer_del(tb_env->hdecr_timer);
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 0);
tb_env->hdecr_next = 0;
}
/*
* There is a bug in Linux 2.4 kernels:
* if a decrementer exception is pending when it enables msr_ee at startup,
* it's not ready to handle it...
*/
cpu_ppc_store_decr(env, -1);
cpu_ppc_store_hdecr(env, -1);
cpu_ppc_store_purr(env, 0x0000000000000000ULL);
}
void cpu_ppc_tb_free(CPUPPCState *env)

View File

@ -67,6 +67,7 @@ static void ppc_prep_reset(void *opaque)
PowerPCCPU *cpu = opaque;
cpu_reset(CPU(cpu));
cpu_ppc_tb_reset(&cpu->env);
}

View File

@ -74,6 +74,8 @@ static void spapr_reset_vcpu(PowerPCCPU *cpu)
kvm_check_mmu(cpu, &error_fatal);
cpu_ppc_tb_reset(env);
spapr_irq_cpu_intc_reset(spapr, cpu);
}

View File

@ -54,7 +54,8 @@ struct ppc_tb_t {
*/
uint64_t cpu_ppc_get_tb(ppc_tb_t *tb_env, uint64_t vmclk, int64_t tb_offset);
clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq);
void cpu_ppc_tb_init(CPUPPCState *env, uint32_t freq);
void cpu_ppc_tb_reset(CPUPPCState *env);
void cpu_ppc_tb_free(CPUPPCState *env);
void cpu_ppc_hdecr_init(CPUPPCState *env);
void cpu_ppc_hdecr_exit(CPUPPCState *env);