Skip to content

Commit

Permalink
hw/ppc: Reset timebase facilities on machine reset
Browse files Browse the repository at this point in the history
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 30d0647)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
  • Loading branch information
npiggin authored and Michael Tokarev committed Sep 25, 2023
1 parent 1c2343c commit b6fa8e4
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 21 deletions.
1 change: 1 addition & 0 deletions hw/ppc/mac_oldworld.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ static void ppc_heathrow_reset(void *opaque)
{
PowerPCCPU *cpu = opaque;

cpu_ppc_tb_reset(&cpu->env);
cpu_reset(CPU(cpu));
}

Expand Down
1 change: 1 addition & 0 deletions hw/ppc/pegasos2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions hw/ppc/pnv_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
47 changes: 27 additions & 20 deletions hw/ppc/ppc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions hw/ppc/prep.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static void ppc_prep_reset(void *opaque)
PowerPCCPU *cpu = opaque;

cpu_reset(CPU(cpu));
cpu_ppc_tb_reset(&cpu->env);
}


Expand Down
2 changes: 2 additions & 0 deletions hw/ppc/spapr_cpu_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
3 changes: 2 additions & 1 deletion include/hw/ppc/ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit b6fa8e4

Please sign in to comment.