Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
  • Loading branch information
npiggin authored and legoater committed Sep 4, 2023
1 parent 4a90d95 commit 7b13088
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 21 deletions.
1 change: 1 addition & 0 deletions hw/ppc/mac_oldworld.c
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
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
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
46 changes: 26 additions & 20 deletions hw/ppc/ppc.c
Expand Up @@ -944,23 +944,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 @@ -1062,7 +1045,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 @@ -1083,9 +1066,32 @@ 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
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
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
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 7b13088

Please sign in to comment.