* [PATCH v2 0/2] ppc: Fix migration issue with quiesced state
@ 2025-12-17 16:45 Fabiano Rosas
2025-12-17 16:45 ` [PATCH v2 1/2] target/ppc: Fix env->quiesced migration Fabiano Rosas
2025-12-17 16:45 ` [PATCH v2 2/2] tests/functional: Add a OS level migration test for pseries Fabiano Rosas
0 siblings, 2 replies; 7+ messages in thread
From: Fabiano Rosas @ 2025-12-17 16:45 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth, peterx
A while back, Fabian reported two issues with migration on ppc64le,
one of which was already fixed. There remains this one from the
previous series:
pseries migration causes a guest hang after migration due to a new
variable used to track the stopped state of vcpus, which is not
migrated. Fix is to migrate the new variable. To avoid breaking
backward migration, a compat property is added. For forward migration,
a heuritics based on the known QEMU code is used.
Thanks
CI run: https://gitlab.com/farosas/qemu/-/pipelines/2220496446
v1:
https://lore.kernel.org/r/20250819223905.2247-1-farosas@suse.de
Fabiano Rosas (2):
target/ppc: Fix env->quiesced migration
tests/functional: Add a OS level migration test for pseries
hw/ppc/spapr.c | 6 +++
target/ppc/cpu.h | 1 +
target/ppc/cpu_init.c | 7 +++
target/ppc/machine.c | 63 ++++++++++++++++++++++++
tests/functional/ppc64/test_migration.py | 12 +++++
tests/functional/ppc64/test_pseries.py | 35 +++++++++++++
6 files changed, 124 insertions(+)
--
2.51.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/2] target/ppc: Fix env->quiesced migration
2025-12-17 16:45 [PATCH v2 0/2] ppc: Fix migration issue with quiesced state Fabiano Rosas
@ 2025-12-17 16:45 ` Fabiano Rosas
2026-01-05 9:00 ` Harsh Prateek Bora
2025-12-17 16:45 ` [PATCH v2 2/2] tests/functional: Add a OS level migration test for pseries Fabiano Rosas
1 sibling, 1 reply; 7+ messages in thread
From: Fabiano Rosas @ 2025-12-17 16:45 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, peterx, Fabian Vogt, Nicholas Piggin, Harsh Prateek Bora,
Chinmay Rath
The commit referenced (from QEMU 10.0) has changed the way the pseries
machine marks a cpu as quiesced. Previously, the cpu->halted value
from QEMU common cpu code was (incorrectly) used. With the fix, the
env->quiesced variable starts being used, which improves on the
original situation, but also causes a side effect after migration:
The env->quiesced is set at reset and never migrated, which causes the
destination QEMU to stop delivering interrupts and hang the machine.
To fix the issue from this point on, start migrating the env->quiesced
value.
For QEMU versions < 10.0, sending the new element on the stream would
cause migration to be aborted, so add the appropriate compatibility
property to omit the new subsection.
Independently of this patch, all migrations from QEMU versions < 10.0
would result in a hang since the older QEMU never migrates
env->quiesced. This is bad because it leaves machines already running
on the old QEMU without a migration path into newer versions.
As a workaround, use a few heuristics to infer the new value of
env->quiesced based on cpu->halted, LPCR and PSSCR bits that are
usually set/cleared along with quiesced.
Note that this was tested with -cpu power9 and -machine ic-mode=xive
due to another bug affecting migration of XICS guests. Tested both
forward and backward migration and savevm/loadvm from 9.2 and 10.0.
Also tested loadvm of a savevm image that contains a mix of cpus both
halted and not halted.
Reported-by: Fabian Vogt <fvogt@suse.de>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3079
Fixes: fb802acdc8b ("ppc/spapr: Fix RTAS stopped state")
Signed-off-by: Fabiano Rosas <farosas@suse.de>
---
hw/ppc/spapr.c | 6 +++++
target/ppc/cpu.h | 1 +
target/ppc/cpu_init.c | 7 +++++
target/ppc/machine.c | 63 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 77 insertions(+)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 99b843ba2f..9dde61a667 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4776,8 +4776,14 @@ DEFINE_SPAPR_MACHINE(10, 1);
*/
static void spapr_machine_10_0_class_options(MachineClass *mc)
{
+ static GlobalProperty spapr_compat_10_0[] = {
+ { TYPE_POWERPC_CPU, "rtas-stopped-state", "false" },
+ };
+
spapr_machine_10_1_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_10_0, hw_compat_10_0_len);
+ compat_props_add(mc->compat_props, spapr_compat_10_0,
+ G_N_ELEMENTS(spapr_compat_10_0));
}
DEFINE_SPAPR_MACHINE(10, 0);
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 787020f6f9..bbd661e96c 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1529,6 +1529,7 @@ struct ArchCPU {
void *machine_data;
int32_t node_id; /* NUMA node this CPU belongs to */
PPCHash64Options *hash64_opts;
+ bool rtas_stopped_state;
/* Those resources are used only during code translation */
/* opcode handlers */
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 86ead740ee..8dac1cd812 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -55,6 +55,11 @@
/* #define PPC_DEBUG_SPR */
/* #define USE_APPLE_GDB */
+static const Property powerpc_cpu_properties[] = {
+ DEFINE_PROP_BOOL("rtas-stopped-state", PowerPCCPU,
+ rtas_stopped_state, true),
+};
+
static inline void vscr_init(CPUPPCState *env, uint32_t val)
{
/* Altivec always uses round-to-nearest */
@@ -7529,6 +7534,8 @@ static void ppc_cpu_class_init(ObjectClass *oc, const void *data)
&pcc->parent_unrealize);
pcc->pvr_match = ppc_pvr_match_default;
+ device_class_set_props(dc, powerpc_cpu_properties);
+
resettable_class_set_parent_phases(rc, NULL, ppc_cpu_reset_hold, NULL,
&pcc->parent_phases);
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index d72e5ecb94..ba63a7debb 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -6,6 +6,7 @@
#include "mmu-hash64.h"
#include "migration/cpu.h"
#include "qapi/error.h"
+#include "qemu/error-report.h"
#include "kvm_ppc.h"
#include "power8-pmu.h"
#include "system/replay.h"
@@ -257,6 +258,45 @@ static int cpu_post_load(void *opaque, int version_id)
ppc_store_sdr1(env, env->spr[SPR_SDR1]);
}
+ if (!cpu->rtas_stopped_state) {
+ /*
+ * The source QEMU doesn't have fb802acdc8 and still uses halt +
+ * PM bits in LPCR to implement RTAS stopped state. The new (this)
+ * QEMU will have put the secondary vcpus in stopped state,
+ * waiting for the start-cpu RTAS call. That call will never come
+ * if the source cpus were already running. Try to infer the cpus
+ * state and set env->quiesced accordingly.
+ *
+ * env->quiesced = true ==> the cpu is waiting to start
+ * env->quiesced = false ==> the cpu is running (unless halted)
+ */
+
+ /*
+ * Halted _could_ mean quiesced, but it could also be cede,
+ * confer_self, power management, etc.
+ */
+ if (CPU(cpu)->halted) {
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ /*
+ * Both the PSSCR_EC bit and LPCR PM bits set at cpu reset
+ * and rtas_stop and cleared at rtas_start, it's a good
+ * heuristic.
+ */
+ if ((env->spr[SPR_PSSCR] & PSSCR_EC) &&
+ (env->spr[SPR_LPCR] & pcc->lpcr_pm)) {
+ env->quiesced = true;
+ } else {
+ env->quiesced = false;
+ }
+ } else {
+ /*
+ * Old QEMU sets halted during rtas_stop_self. Not halted,
+ * therefore definitely not quiesced.
+ */
+ env->quiesced = false;
+ }
+ }
+
post_load_update_msr(env);
if (tcg_enabled()) {
@@ -649,6 +689,28 @@ static const VMStateDescription vmstate_reservation = {
}
};
+static bool rtas_stopped_needed(void *opaque)
+{
+ PowerPCCPU *cpu = opaque;
+
+ return cpu->rtas_stopped_state;
+}
+
+static const VMStateDescription vmstate_rtas_stopped = {
+ .name = "cpu/rtas_stopped",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = rtas_stopped_needed,
+ .fields = (const VMStateField[]) {
+ /*
+ * "RTAS stopped" state, independent of halted state. For QEMU
+ * < 10.0, this is taken from cpu->halted at cpu_post_load()
+ */
+ VMSTATE_BOOL(env.quiesced, PowerPCCPU),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
#ifdef TARGET_PPC64
static bool bhrb_needed(void *opaque)
{
@@ -715,6 +777,7 @@ const VMStateDescription vmstate_ppc_cpu = {
&vmstate_tlbmas,
&vmstate_compat,
&vmstate_reservation,
+ &vmstate_rtas_stopped,
NULL
}
};
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] tests/functional: Add a OS level migration test for pseries
2025-12-17 16:45 [PATCH v2 0/2] ppc: Fix migration issue with quiesced state Fabiano Rosas
2025-12-17 16:45 ` [PATCH v2 1/2] target/ppc: Fix env->quiesced migration Fabiano Rosas
@ 2025-12-17 16:45 ` Fabiano Rosas
2026-01-05 10:05 ` Thomas Huth
1 sibling, 1 reply; 7+ messages in thread
From: Fabiano Rosas @ 2025-12-17 16:45 UTC (permalink / raw)
To: qemu-devel; +Cc: thuth, peterx, Nicholas Piggin, Harsh Prateek Bora
There's currently no OS level test for ppc64le. Add one such test by
reusing the boot level tests that are already present.
The test boots the source machine, waits for it to reach a mid-boot
message, migrates and checks that the destination has reached the
final boot message (VFS error due to no disk).
Signed-off-by: Fabiano Rosas <farosas@suse.de>
---
tests/functional/ppc64/test_migration.py | 12 ++++++++
tests/functional/ppc64/test_pseries.py | 35 ++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/tests/functional/ppc64/test_migration.py b/tests/functional/ppc64/test_migration.py
index 5dfdaaf709..a3b819680b 100755
--- a/tests/functional/ppc64/test_migration.py
+++ b/tests/functional/ppc64/test_migration.py
@@ -4,6 +4,7 @@
#
# ppc migration test
+from qemu_test.ports import Ports
from migration import MigrationTest
@@ -21,6 +22,17 @@ def test_migration_with_exec(self):
self.set_machine('mac99')
self.migration_with_exec()
+ def do_migrate_ppc64_linux(self, source_vm, dest_vm):
+ with Ports() as ports:
+ port = ports.find_free_port()
+ if port is None:
+ self.skipTest('Failed to find a free port')
+ uri = 'tcp:localhost:%u' % port
+
+ dest_vm.qmp('migrate-incoming', uri=uri)
+ source_vm.qmp('migrate', uri=uri)
+ self.assert_migration(source_vm, dest_vm)
+
if __name__ == '__main__':
MigrationTest.main()
diff --git a/tests/functional/ppc64/test_pseries.py b/tests/functional/ppc64/test_pseries.py
index 7840c4e3ff..e15a8956a5 100755
--- a/tests/functional/ppc64/test_pseries.py
+++ b/tests/functional/ppc64/test_pseries.py
@@ -9,6 +9,7 @@
from qemu_test import QemuSystemTest, Asset
from qemu_test import wait_for_console_pattern
+from test_migration import PpcMigrationTest
class PseriesMachine(QemuSystemTest):
@@ -87,5 +88,39 @@ def test_ppc64_linux_big_boot(self):
wait_for_console_pattern(self, console_pattern, self.panic_message)
wait_for_console_pattern(self, self.good_message, self.panic_message)
+ def test_ppc64_linux_migration(self):
+ kernel_path = self.ASSET_KERNEL.fetch()
+ kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE
+
+ self.set_machine('pseries')
+
+ dest_vm = self.get_vm(name="dest-qemu")
+ dest_vm.add_args('-incoming', 'defer')
+ dest_vm.add_args('-smp', '4')
+ dest_vm.add_args('-nodefaults')
+ dest_vm.add_args('-kernel', kernel_path,
+ '-append', kernel_command_line)
+ dest_vm.set_console()
+ dest_vm.launch()
+
+ source_vm = self.get_vm(name="source-qemu")
+ source_vm.add_args('-smp', '4')
+ source_vm.add_args('-nodefaults')
+ source_vm.add_args('-kernel', kernel_path,
+ '-append', kernel_command_line)
+ source_vm.set_console()
+ source_vm.launch()
+
+ # ensure the boot has reached Linux
+ console_pattern = 'smp: Brought up 1 node, 4 CPUs'
+ wait_for_console_pattern(self, console_pattern, self.panic_message,
+ vm=source_vm)
+
+ PpcMigrationTest().do_migrate_ppc64_linux(source_vm, dest_vm);
+
+ # ensure the boot proceeds after migration
+ wait_for_console_pattern(self, self.good_message, self.panic_message,
+ vm=dest_vm)
+
if __name__ == '__main__':
QemuSystemTest.main()
--
2.51.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] target/ppc: Fix env->quiesced migration
2025-12-17 16:45 ` [PATCH v2 1/2] target/ppc: Fix env->quiesced migration Fabiano Rosas
@ 2026-01-05 9:00 ` Harsh Prateek Bora
2026-01-08 6:27 ` Harsh Prateek Bora
0 siblings, 1 reply; 7+ messages in thread
From: Harsh Prateek Bora @ 2026-01-05 9:00 UTC (permalink / raw)
To: Fabiano Rosas, qemu-devel
Cc: thuth, peterx, Fabian Vogt, Nicholas Piggin, Chinmay Rath, gautam
+ Gautam - FYI
Thanks Fabiano for addressing Thomas's review comments.
Thomas,
Do you have any further review comments on this patchset or may provide
an ack?
Looks good to me though.
regards,
Harsh
On 17/12/25 10:15 pm, Fabiano Rosas wrote:
> The commit referenced (from QEMU 10.0) has changed the way the pseries
> machine marks a cpu as quiesced. Previously, the cpu->halted value
> from QEMU common cpu code was (incorrectly) used. With the fix, the
> env->quiesced variable starts being used, which improves on the
> original situation, but also causes a side effect after migration:
>
> The env->quiesced is set at reset and never migrated, which causes the
> destination QEMU to stop delivering interrupts and hang the machine.
>
> To fix the issue from this point on, start migrating the env->quiesced
> value.
>
> For QEMU versions < 10.0, sending the new element on the stream would
> cause migration to be aborted, so add the appropriate compatibility
> property to omit the new subsection.
>
> Independently of this patch, all migrations from QEMU versions < 10.0
> would result in a hang since the older QEMU never migrates
> env->quiesced. This is bad because it leaves machines already running
> on the old QEMU without a migration path into newer versions.
>
> As a workaround, use a few heuristics to infer the new value of
> env->quiesced based on cpu->halted, LPCR and PSSCR bits that are
> usually set/cleared along with quiesced.
>
> Note that this was tested with -cpu power9 and -machine ic-mode=xive
> due to another bug affecting migration of XICS guests. Tested both
> forward and backward migration and savevm/loadvm from 9.2 and 10.0.
>
> Also tested loadvm of a savevm image that contains a mix of cpus both
> halted and not halted.
>
> Reported-by: Fabian Vogt <fvogt@suse.de>
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3079
> Fixes: fb802acdc8b ("ppc/spapr: Fix RTAS stopped state")
> Signed-off-by: Fabiano Rosas <farosas@suse.de>
> ---
> hw/ppc/spapr.c | 6 +++++
> target/ppc/cpu.h | 1 +
> target/ppc/cpu_init.c | 7 +++++
> target/ppc/machine.c | 63 +++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 77 insertions(+)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 99b843ba2f..9dde61a667 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -4776,8 +4776,14 @@ DEFINE_SPAPR_MACHINE(10, 1);
> */
> static void spapr_machine_10_0_class_options(MachineClass *mc)
> {
> + static GlobalProperty spapr_compat_10_0[] = {
> + { TYPE_POWERPC_CPU, "rtas-stopped-state", "false" },
> + };
> +
> spapr_machine_10_1_class_options(mc);
> compat_props_add(mc->compat_props, hw_compat_10_0, hw_compat_10_0_len);
> + compat_props_add(mc->compat_props, spapr_compat_10_0,
> + G_N_ELEMENTS(spapr_compat_10_0));
> }
>
> DEFINE_SPAPR_MACHINE(10, 0);
> diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
> index 787020f6f9..bbd661e96c 100644
> --- a/target/ppc/cpu.h
> +++ b/target/ppc/cpu.h
> @@ -1529,6 +1529,7 @@ struct ArchCPU {
> void *machine_data;
> int32_t node_id; /* NUMA node this CPU belongs to */
> PPCHash64Options *hash64_opts;
> + bool rtas_stopped_state;
>
> /* Those resources are used only during code translation */
> /* opcode handlers */
> diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
> index 86ead740ee..8dac1cd812 100644
> --- a/target/ppc/cpu_init.c
> +++ b/target/ppc/cpu_init.c
> @@ -55,6 +55,11 @@
> /* #define PPC_DEBUG_SPR */
> /* #define USE_APPLE_GDB */
>
> +static const Property powerpc_cpu_properties[] = {
> + DEFINE_PROP_BOOL("rtas-stopped-state", PowerPCCPU,
> + rtas_stopped_state, true),
> +};
> +
> static inline void vscr_init(CPUPPCState *env, uint32_t val)
> {
> /* Altivec always uses round-to-nearest */
> @@ -7529,6 +7534,8 @@ static void ppc_cpu_class_init(ObjectClass *oc, const void *data)
> &pcc->parent_unrealize);
> pcc->pvr_match = ppc_pvr_match_default;
>
> + device_class_set_props(dc, powerpc_cpu_properties);
> +
> resettable_class_set_parent_phases(rc, NULL, ppc_cpu_reset_hold, NULL,
> &pcc->parent_phases);
>
> diff --git a/target/ppc/machine.c b/target/ppc/machine.c
> index d72e5ecb94..ba63a7debb 100644
> --- a/target/ppc/machine.c
> +++ b/target/ppc/machine.c
> @@ -6,6 +6,7 @@
> #include "mmu-hash64.h"
> #include "migration/cpu.h"
> #include "qapi/error.h"
> +#include "qemu/error-report.h"
> #include "kvm_ppc.h"
> #include "power8-pmu.h"
> #include "system/replay.h"
> @@ -257,6 +258,45 @@ static int cpu_post_load(void *opaque, int version_id)
> ppc_store_sdr1(env, env->spr[SPR_SDR1]);
> }
>
> + if (!cpu->rtas_stopped_state) {
> + /*
> + * The source QEMU doesn't have fb802acdc8 and still uses halt +
> + * PM bits in LPCR to implement RTAS stopped state. The new (this)
> + * QEMU will have put the secondary vcpus in stopped state,
> + * waiting for the start-cpu RTAS call. That call will never come
> + * if the source cpus were already running. Try to infer the cpus
> + * state and set env->quiesced accordingly.
> + *
> + * env->quiesced = true ==> the cpu is waiting to start
> + * env->quiesced = false ==> the cpu is running (unless halted)
> + */
> +
> + /*
> + * Halted _could_ mean quiesced, but it could also be cede,
> + * confer_self, power management, etc.
> + */
> + if (CPU(cpu)->halted) {
> + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
> + /*
> + * Both the PSSCR_EC bit and LPCR PM bits set at cpu reset
> + * and rtas_stop and cleared at rtas_start, it's a good
> + * heuristic.
> + */
> + if ((env->spr[SPR_PSSCR] & PSSCR_EC) &&
> + (env->spr[SPR_LPCR] & pcc->lpcr_pm)) {
> + env->quiesced = true;
> + } else {
> + env->quiesced = false;
> + }
> + } else {
> + /*
> + * Old QEMU sets halted during rtas_stop_self. Not halted,
> + * therefore definitely not quiesced.
> + */
> + env->quiesced = false;
> + }
> + }
> +
> post_load_update_msr(env);
>
> if (tcg_enabled()) {
> @@ -649,6 +689,28 @@ static const VMStateDescription vmstate_reservation = {
> }
> };
>
> +static bool rtas_stopped_needed(void *opaque)
> +{
> + PowerPCCPU *cpu = opaque;
> +
> + return cpu->rtas_stopped_state;
> +}
> +
> +static const VMStateDescription vmstate_rtas_stopped = {
> + .name = "cpu/rtas_stopped",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .needed = rtas_stopped_needed,
> + .fields = (const VMStateField[]) {
> + /*
> + * "RTAS stopped" state, independent of halted state. For QEMU
> + * < 10.0, this is taken from cpu->halted at cpu_post_load()
> + */
> + VMSTATE_BOOL(env.quiesced, PowerPCCPU),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> #ifdef TARGET_PPC64
> static bool bhrb_needed(void *opaque)
> {
> @@ -715,6 +777,7 @@ const VMStateDescription vmstate_ppc_cpu = {
> &vmstate_tlbmas,
> &vmstate_compat,
> &vmstate_reservation,
> + &vmstate_rtas_stopped,
> NULL
> }
> };
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 2/2] tests/functional: Add a OS level migration test for pseries
2025-12-17 16:45 ` [PATCH v2 2/2] tests/functional: Add a OS level migration test for pseries Fabiano Rosas
@ 2026-01-05 10:05 ` Thomas Huth
0 siblings, 0 replies; 7+ messages in thread
From: Thomas Huth @ 2026-01-05 10:05 UTC (permalink / raw)
To: Fabiano Rosas, qemu-devel; +Cc: peterx, Nicholas Piggin, Harsh Prateek Bora
On 17/12/2025 17.45, Fabiano Rosas wrote:
> There's currently no OS level test for ppc64le. Add one such test by
> reusing the boot level tests that are already present.
>
> The test boots the source machine, waits for it to reach a mid-boot
> message, migrates and checks that the destination has reached the
> final boot message (VFS error due to no disk).
>
> Signed-off-by: Fabiano Rosas <farosas@suse.de>
> ---
> tests/functional/ppc64/test_migration.py | 12 ++++++++
> tests/functional/ppc64/test_pseries.py | 35 ++++++++++++++++++++++++
> 2 files changed, 47 insertions(+)
>
> diff --git a/tests/functional/ppc64/test_migration.py b/tests/functional/ppc64/test_migration.py
> index 5dfdaaf709..a3b819680b 100755
> --- a/tests/functional/ppc64/test_migration.py
> +++ b/tests/functional/ppc64/test_migration.py
> @@ -4,6 +4,7 @@
> #
> # ppc migration test
>
> +from qemu_test.ports import Ports
> from migration import MigrationTest
>
>
> @@ -21,6 +22,17 @@ def test_migration_with_exec(self):
> self.set_machine('mac99')
> self.migration_with_exec()
>
> + def do_migrate_ppc64_linux(self, source_vm, dest_vm):
> + with Ports() as ports:
> + port = ports.find_free_port()
> + if port is None:
> + self.skipTest('Failed to find a free port')
> + uri = 'tcp:localhost:%u' % port
> +
> + dest_vm.qmp('migrate-incoming', uri=uri)
> + source_vm.qmp('migrate', uri=uri)
> + self.assert_migration(source_vm, dest_vm)
> +
>
> if __name__ == '__main__':
> MigrationTest.main()
> diff --git a/tests/functional/ppc64/test_pseries.py b/tests/functional/ppc64/test_pseries.py
> index 7840c4e3ff..e15a8956a5 100755
> --- a/tests/functional/ppc64/test_pseries.py
> +++ b/tests/functional/ppc64/test_pseries.py
> @@ -9,6 +9,7 @@
>
> from qemu_test import QemuSystemTest, Asset
> from qemu_test import wait_for_console_pattern
> +from test_migration import PpcMigrationTest
>
> class PseriesMachine(QemuSystemTest):
>
> @@ -87,5 +88,39 @@ def test_ppc64_linux_big_boot(self):
> wait_for_console_pattern(self, console_pattern, self.panic_message)
> wait_for_console_pattern(self, self.good_message, self.panic_message)
>
> + def test_ppc64_linux_migration(self):
> + kernel_path = self.ASSET_KERNEL.fetch()
> + kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE
> +
> + self.set_machine('pseries')
It's slightly better to do set_machine() first, before the ASSET_* lines, so
that the test is skipped without fetching the assets in case the pseries
machine is not available.
With that nit fixed:
Reviewed-by: Thomas Huth <thuth@redhat.com>
> + dest_vm = self.get_vm(name="dest-qemu")
> + dest_vm.add_args('-incoming', 'defer')
> + dest_vm.add_args('-smp', '4')
> + dest_vm.add_args('-nodefaults')
> + dest_vm.add_args('-kernel', kernel_path,
> + '-append', kernel_command_line)
> + dest_vm.set_console()
> + dest_vm.launch()
> +
> + source_vm = self.get_vm(name="source-qemu")
> + source_vm.add_args('-smp', '4')
> + source_vm.add_args('-nodefaults')
> + source_vm.add_args('-kernel', kernel_path,
> + '-append', kernel_command_line)
> + source_vm.set_console()
> + source_vm.launch()
> +
> + # ensure the boot has reached Linux
> + console_pattern = 'smp: Brought up 1 node, 4 CPUs'
> + wait_for_console_pattern(self, console_pattern, self.panic_message,
> + vm=source_vm)
> +
> + PpcMigrationTest().do_migrate_ppc64_linux(source_vm, dest_vm);
> +
> + # ensure the boot proceeds after migration
> + wait_for_console_pattern(self, self.good_message, self.panic_message,
> + vm=dest_vm)
> +
> if __name__ == '__main__':
> QemuSystemTest.main()
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] target/ppc: Fix env->quiesced migration
2026-01-05 9:00 ` Harsh Prateek Bora
@ 2026-01-08 6:27 ` Harsh Prateek Bora
2026-01-08 12:56 ` Fabiano Rosas
0 siblings, 1 reply; 7+ messages in thread
From: Harsh Prateek Bora @ 2026-01-08 6:27 UTC (permalink / raw)
To: Fabiano Rosas, qemu-devel
Cc: thuth, peterx, Fabian Vogt, Nicholas Piggin, Chinmay Rath, gautam
One minor comment below:
<snip>
On 05/01/26 2:30 pm, Harsh Prateek Bora wrote:
>> diff --git a/target/ppc/machine.c b/target/ppc/machine.c
>> index d72e5ecb94..ba63a7debb 100644
>> --- a/target/ppc/machine.c
>> +++ b/target/ppc/machine.c
>> @@ -6,6 +6,7 @@
>> #include "mmu-hash64.h"
>> #include "migration/cpu.h"
>> #include "qapi/error.h"
>> +#include "qemu/error-report.h"
I do not see any error reporting being added in the patch below.
Does this header inclusion need to be removed ?
regards,
Harsh
>> #include "kvm_ppc.h"
>> #include "power8-pmu.h"
>> #include "system/replay.h"
>> @@ -257,6 +258,45 @@ static int cpu_post_load(void *opaque, int
>> version_id)
>> ppc_store_sdr1(env, env->spr[SPR_SDR1]);
>> }
>> + if (!cpu->rtas_stopped_state) {
>> + /*
>> + * The source QEMU doesn't have fb802acdc8 and still uses halt +
>> + * PM bits in LPCR to implement RTAS stopped state. The new
>> (this)
>> + * QEMU will have put the secondary vcpus in stopped state,
>> + * waiting for the start-cpu RTAS call. That call will never
>> come
>> + * if the source cpus were already running. Try to infer the
>> cpus
>> + * state and set env->quiesced accordingly.
>> + *
>> + * env->quiesced = true ==> the cpu is waiting to start
>> + * env->quiesced = false ==> the cpu is running (unless halted)
>> + */
>> +
>> + /*
>> + * Halted _could_ mean quiesced, but it could also be cede,
>> + * confer_self, power management, etc.
>> + */
>> + if (CPU(cpu)->halted) {
>> + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
>> + /*
>> + * Both the PSSCR_EC bit and LPCR PM bits set at cpu reset
>> + * and rtas_stop and cleared at rtas_start, it's a good
>> + * heuristic.
>> + */
>> + if ((env->spr[SPR_PSSCR] & PSSCR_EC) &&
>> + (env->spr[SPR_LPCR] & pcc->lpcr_pm)) {
>> + env->quiesced = true;
>> + } else {
>> + env->quiesced = false;
>> + }
>> + } else {
>> + /*
>> + * Old QEMU sets halted during rtas_stop_self. Not halted,
>> + * therefore definitely not quiesced.
>> + */
>> + env->quiesced = false;
>> + }
>> + }
>> +
>> post_load_update_msr(env);
>> if (tcg_enabled()) {
>> @@ -649,6 +689,28 @@ static const VMStateDescription
>> vmstate_reservation = {
>> }
>> };
>> +static bool rtas_stopped_needed(void *opaque)
>> +{
>> + PowerPCCPU *cpu = opaque;
>> +
>> + return cpu->rtas_stopped_state;
>> +}
>> +
>> +static const VMStateDescription vmstate_rtas_stopped = {
>> + .name = "cpu/rtas_stopped",
>> + .version_id = 1,
>> + .minimum_version_id = 1,
>> + .needed = rtas_stopped_needed,
>> + .fields = (const VMStateField[]) {
>> + /*
>> + * "RTAS stopped" state, independent of halted state. For QEMU
>> + * < 10.0, this is taken from cpu->halted at cpu_post_load()
>> + */
>> + VMSTATE_BOOL(env.quiesced, PowerPCCPU),
>> + VMSTATE_END_OF_LIST()
>> + }
>> +};
>> +
>> #ifdef TARGET_PPC64
>> static bool bhrb_needed(void *opaque)
>> {
>> @@ -715,6 +777,7 @@ const VMStateDescription vmstate_ppc_cpu = {
>> &vmstate_tlbmas,
>> &vmstate_compat,
>> &vmstate_reservation,
>> + &vmstate_rtas_stopped,
>> NULL
>> }
>> };
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2 1/2] target/ppc: Fix env->quiesced migration
2026-01-08 6:27 ` Harsh Prateek Bora
@ 2026-01-08 12:56 ` Fabiano Rosas
0 siblings, 0 replies; 7+ messages in thread
From: Fabiano Rosas @ 2026-01-08 12:56 UTC (permalink / raw)
To: Harsh Prateek Bora, qemu-devel
Cc: thuth, peterx, Fabian Vogt, Nicholas Piggin, Chinmay Rath, gautam
Harsh Prateek Bora <harshpb@linux.ibm.com> writes:
> One minor comment below:
>
> <snip>
>
> On 05/01/26 2:30 pm, Harsh Prateek Bora wrote:
>>> diff --git a/target/ppc/machine.c b/target/ppc/machine.c
>>> index d72e5ecb94..ba63a7debb 100644
>>> --- a/target/ppc/machine.c
>>> +++ b/target/ppc/machine.c
>>> @@ -6,6 +6,7 @@
>>> #include "mmu-hash64.h"
>>> #include "migration/cpu.h"
>>> #include "qapi/error.h"
>>> +#include "qemu/error-report.h"
>
> I do not see any error reporting being added in the patch below.
> Does this header inclusion need to be removed ?
>
Well spotted, that's a leftover from a previous implementation.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-01-08 12:57 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-17 16:45 [PATCH v2 0/2] ppc: Fix migration issue with quiesced state Fabiano Rosas
2025-12-17 16:45 ` [PATCH v2 1/2] target/ppc: Fix env->quiesced migration Fabiano Rosas
2026-01-05 9:00 ` Harsh Prateek Bora
2026-01-08 6:27 ` Harsh Prateek Bora
2026-01-08 12:56 ` Fabiano Rosas
2025-12-17 16:45 ` [PATCH v2 2/2] tests/functional: Add a OS level migration test for pseries Fabiano Rosas
2026-01-05 10:05 ` Thomas Huth
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.