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>
(cherry picked from commit 30d0647bcf
)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
This commit is contained in:
parent
1c2343cc61
commit
b6fa8e42d1
@ -81,6 +81,7 @@ static void ppc_heathrow_reset(void *opaque)
|
||||
{
|
||||
PowerPCCPU *cpu = opaque;
|
||||
|
||||
cpu_ppc_tb_reset(&cpu->env);
|
||||
cpu_reset(CPU(cpu));
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
47
hw/ppc/ppc.c
47
hw/ppc/ppc.c
@ -938,23 +938,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();
|
||||
@ -1056,7 +1039,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;
|
||||
@ -1076,9 +1059,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)
|
||||
|
@ -67,6 +67,7 @@ static void ppc_prep_reset(void *opaque)
|
||||
PowerPCCPU *cpu = opaque;
|
||||
|
||||
cpu_reset(CPU(cpu));
|
||||
cpu_ppc_tb_reset(&cpu->env);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user