Skip to content

Commit

Permalink
target/ppc: Fix CPU reservation migration for record-replay
Browse files Browse the repository at this point in the history
ppc only migrates reserve_addr, so the destination machine can get a
valid reservation with an incorrect reservation value of 0. Prior to
commit 392d328 ("target/ppc: Ensure stcx size matches larx"),
this could permit a stcx. to incorrectly succeed. That commit
inadvertently fixed that bug because the target machine starts with an
impossible reservation size of 0, so any stcx. will fail.

This behaviour is permitted by the ISA because reservation loss may
have implementation-dependent cause. What's more, with KVM machines it
is impossible save or reasonably restore reservation state. However if
the vmstate is being used for record-replay, the reservation must be
saved and restored exactly in order for execution from snapshot to
match the record.

This patch deprecates the existing incomplete reserve_addr vmstate,
and adds a new vmstate subsection with complete reservation state.
The new vmstate is needed only when record-replay mode is active.

Acked-by: Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
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 fb7e46c commit ea9159c
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 2 deletions.
2 changes: 2 additions & 0 deletions target/ppc/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,9 @@ struct CPUArchState {
target_ulong reserve_addr; /* Reservation address */
target_ulong reserve_length; /* Reservation larx op size (bytes) */
target_ulong reserve_val; /* Reservation value */
#if defined(TARGET_PPC64)
target_ulong reserve_val2;
#endif

/* These are used in supervisor mode only */
target_ulong msr; /* machine state register */
Expand Down
26 changes: 24 additions & 2 deletions target/ppc/machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "qemu/main-loop.h"
#include "kvm_ppc.h"
#include "power8-pmu.h"
#include "sysemu/replay.h"

static void post_load_update_msr(CPUPPCState *env)
{
Expand Down Expand Up @@ -690,6 +691,27 @@ static const VMStateDescription vmstate_compat = {
}
};

static bool reservation_needed(void *opaque)
{
return (replay_mode != REPLAY_MODE_NONE);
}

static const VMStateDescription vmstate_reservation = {
.name = "cpu/reservation",
.version_id = 1,
.minimum_version_id = 1,
.needed = reservation_needed,
.fields = (VMStateField[]) {
VMSTATE_UINTTL(env.reserve_addr, PowerPCCPU),
VMSTATE_UINTTL(env.reserve_length, PowerPCCPU),
VMSTATE_UINTTL(env.reserve_val, PowerPCCPU),
#if defined(TARGET_PPC64)
VMSTATE_UINTTL(env.reserve_val2, PowerPCCPU),
#endif
VMSTATE_END_OF_LIST()
}
};

const VMStateDescription vmstate_ppc_cpu = {
.name = "cpu",
.version_id = 5,
Expand All @@ -711,8 +733,7 @@ const VMStateDescription vmstate_ppc_cpu = {
VMSTATE_UINTTL_ARRAY(env.spr, PowerPCCPU, 1024),
VMSTATE_UINT64(env.spe_acc, PowerPCCPU),

/* Reservation */
VMSTATE_UINTTL(env.reserve_addr, PowerPCCPU),
VMSTATE_UNUSED(sizeof(target_ulong)), /* was env.reserve_addr */

/* Supervisor mode architected state */
VMSTATE_UINTTL(env.msr, PowerPCCPU),
Expand Down Expand Up @@ -741,6 +762,7 @@ const VMStateDescription vmstate_ppc_cpu = {
&vmstate_tlbemb,
&vmstate_tlbmas,
&vmstate_compat,
&vmstate_reservation,
NULL
}
};
4 changes: 4 additions & 0 deletions target/ppc/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ static TCGv cpu_xer, cpu_so, cpu_ov, cpu_ca, cpu_ov32, cpu_ca32;
static TCGv cpu_reserve;
static TCGv cpu_reserve_length;
static TCGv cpu_reserve_val;
#if defined(TARGET_PPC64)
static TCGv cpu_reserve_val2;
#endif
static TCGv cpu_fpscr;
static TCGv_i32 cpu_access_type;

Expand Down Expand Up @@ -151,9 +153,11 @@ void ppc_translate_init(void)
cpu_reserve_val = tcg_global_mem_new(cpu_env,
offsetof(CPUPPCState, reserve_val),
"reserve_val");
#if defined(TARGET_PPC64)
cpu_reserve_val2 = tcg_global_mem_new(cpu_env,
offsetof(CPUPPCState, reserve_val2),
"reserve_val2");
#endif

cpu_fpscr = tcg_global_mem_new(cpu_env,
offsetof(CPUPPCState, fpscr), "fpscr");
Expand Down

0 comments on commit ea9159c

Please sign in to comment.