From: Peter Xu <peterx@redhat.com>
To: Steve Sistare <steven.sistare@oracle.com>
Cc: qemu-devel@nongnu.org, "Juan Quintela" <quintela@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Thomas Huth" <thuth@redhat.com>,
"Daniel P. Berrangé" <berrange@redhat.com>
Subject: Re: [PATCH V1 3/3] tests/qtest: live migration suspended state
Date: Wed, 21 Jun 2023 12:45:09 -0400 [thread overview]
Message-ID: <ZJMpFfetFkZ/QjfT@x1n> (raw)
In-Reply-To: <1686860800-34667-4-git-send-email-steven.sistare@oracle.com>
On Thu, Jun 15, 2023 at 01:26:40PM -0700, Steve Sistare wrote:
> Add a test case to verify that the suspended state is handled correctly in
> live migration. The test suspends the src, migrates, then wakes the dest.
>
> Add an option to suspend the src in a-b-bootblock.S, which puts the guest
> in S3 state after one round of writing to memory. The option is enabled by
> poking a 1 into the suspend_me word in the boot block prior to starting the
> src vm. Generate symbol offsets in a-b-bootblock.h so that the suspend_me
> offset is known.
>
> Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
Thanks for the test case, mostly good to me, a few trivial comments /
questions below.
> ---
> tests/migration/i386/Makefile | 5 ++--
> tests/migration/i386/a-b-bootblock.S | 49 +++++++++++++++++++++++++++++++++---
> tests/migration/i386/a-b-bootblock.h | 22 ++++++++++------
> tests/qtest/migration-helpers.c | 2 +-
> tests/qtest/migration-test.c | 31 +++++++++++++++++++++--
> 5 files changed, 92 insertions(+), 17 deletions(-)
>
> diff --git a/tests/migration/i386/Makefile b/tests/migration/i386/Makefile
> index 5c03241..37a72ae 100644
> --- a/tests/migration/i386/Makefile
> +++ b/tests/migration/i386/Makefile
> @@ -4,9 +4,10 @@
> .PHONY: all clean
> all: a-b-bootblock.h
>
> -a-b-bootblock.h: x86.bootsect
> +a-b-bootblock.h: x86.bootsect x86.o
> echo "$$__note" > header.tmp
> xxd -i $< | sed -e 's/.*int.*//' >> header.tmp
> + nm x86.o | awk '{print "#define SYM_"$$3" 0x"$$1}' >> header.tmp
> mv header.tmp $@
>
> x86.bootsect: x86.boot
> @@ -16,7 +17,7 @@ x86.boot: x86.o
> $(CROSS_PREFIX)objcopy -O binary $< $@
>
> x86.o: a-b-bootblock.S
> - $(CROSS_PREFIX)gcc -m32 -march=i486 -c $< -o $@
> + $(CROSS_PREFIX)gcc -I.. -m32 -march=i486 -c $< -o $@
>
> clean:
> @rm -rf *.boot *.o *.bootsect
> diff --git a/tests/migration/i386/a-b-bootblock.S b/tests/migration/i386/a-b-bootblock.S
> index 3d464c7..63d446f 100644
> --- a/tests/migration/i386/a-b-bootblock.S
> +++ b/tests/migration/i386/a-b-bootblock.S
> @@ -9,6 +9,21 @@
> #
> # Author: dgilbert@redhat.com
>
> +#include "migration-test.h"
> +
> +#define ACPI_ENABLE 0xf1
> +#define ACPI_PORT_SMI_CMD 0xb2
> +#define ACPI_PM_BASE 0x600
> +#define PM1A_CNT_OFFSET 4
> +
> +#define ACPI_SCI_ENABLE 0x0001
> +#define ACPI_SLEEP_TYPE 0x0400
> +#define ACPI_SLEEP_ENABLE 0x2000
> +#define SLEEP (ACPI_SCI_ENABLE + ACPI_SLEEP_TYPE + ACPI_SLEEP_ENABLE)
> +
> +#define LOW_ADDR X86_TEST_MEM_START
> +#define HIGH_ADDR X86_TEST_MEM_END
> +#define suspended HIGH_ADDR
>
> .code16
> .org 0x7c00
> @@ -41,12 +56,11 @@ start: # at 0x7c00 ?
> # bl keeps a counter so we limit the output speed
> mov $0, %bl
> mainloop:
> - # Start from 1MB
> - mov $(1024*1024),%eax
> + mov $LOW_ADDR,%eax
> innerloop:
> incb (%eax)
> add $4096,%eax
> - cmp $(100*1024*1024),%eax
> + cmp $HIGH_ADDR,%eax
> jl innerloop
>
> inc %bl
> @@ -57,7 +71,30 @@ innerloop:
> mov $0x3f8,%dx
> outb %al,%dx
>
> - jmp mainloop
> + # should this test suspend?
> + mov (suspend_me),%eax
> + cmp $0,%eax
> + je mainloop
> +
> + # are we waking after suspend? do not suspend again.
> + mov $suspended,%eax
So IIUC then it'll use 4 bytes over 100MB range which means we need at
least 100MB+4bytes.. not obvious for a HIGH_ADDR definition to me..
Could we just define a variable inside the section like suspend_me?
> + mov (%eax),%eax
> + cmp $1,%eax
> + je mainloop
> +
> + # enable acpi
> + mov $ACPI_ENABLE,%al
> + outb %al,$ACPI_PORT_SMI_CMD
> +
> + # suspend to ram
> + mov $suspended,%eax
> + movl $1,(%eax)
> + mov $SLEEP,%ax
> + mov $(ACPI_PM_BASE + PM1A_CNT_OFFSET),%dx
> + outw %ax,%dx
> + # not reached. The wakeup causes reset and restart at 0x7c00, and we
> + # do not save and restore registers as a real kernel would do.
> +
>
> # GDT magic from old (GPLv2) Grub startup.S
> .p2align 2 /* force 4-byte alignment */
> @@ -83,6 +120,10 @@ gdtdesc:
> .word 0x27 /* limit */
> .long gdt /* addr */
>
> + /* test launcher can poke a 1 here to exercise suspend */
> +suspend_me:
> + .int 0
> +
> /* I'm a bootable disk */
> .org 0x7dfe
> .byte 0x55
> diff --git a/tests/migration/i386/a-b-bootblock.h b/tests/migration/i386/a-b-bootblock.h
> index b7b0fce..b39773f 100644
> --- a/tests/migration/i386/a-b-bootblock.h
> +++ b/tests/migration/i386/a-b-bootblock.h
> @@ -4,20 +4,20 @@
> * the header and the assembler differences in your patch submission.
> */
> unsigned char x86_bootsect[] = {
> - 0xfa, 0x0f, 0x01, 0x16, 0x78, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
> + 0xfa, 0x0f, 0x01, 0x16, 0xa4, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00,
> 0x0f, 0x22, 0xc0, 0x66, 0xea, 0x20, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00,
> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x92, 0x0c, 0x02,
> 0xe6, 0x92, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x8e, 0xd8, 0x66, 0xb8, 0x41,
> 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xb3, 0x00, 0xb8, 0x00, 0x00, 0x10,
> 0x00, 0xfe, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40,
> 0x06, 0x7c, 0xf2, 0xfe, 0xc3, 0x80, 0xe3, 0x3f, 0x75, 0xe6, 0x66, 0xb8,
> - 0x42, 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xeb, 0xdb, 0x8d, 0x76, 0x00,
> - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
> - 0x00, 0x9a, 0xcf, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00,
> - 0x27, 0x00, 0x60, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> + 0x42, 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xa1, 0xaa, 0x7c, 0x00, 0x00,
> + 0x83, 0xf8, 0x00, 0x74, 0xd3, 0xb8, 0x00, 0x00, 0x40, 0x06, 0x8b, 0x00,
> + 0x83, 0xf8, 0x01, 0x74, 0xc7, 0xb0, 0xf1, 0xe6, 0xb2, 0xb8, 0x00, 0x00,
> + 0x40, 0x06, 0xc7, 0x00, 0x01, 0x00, 0x00, 0x00, 0x66, 0xb8, 0x01, 0x24,
> + 0x66, 0xba, 0x04, 0x06, 0x66, 0xef, 0x66, 0x90, 0x00, 0x00, 0x00, 0x00,
> + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00,
> + 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0x27, 0x00, 0x8c, 0x7c,
> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> @@ -49,3 +49,9 @@ unsigned char x86_bootsect[] = {
> 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
> };
>
> +#define SYM_gdt 0x00007c8c
> +#define SYM_gdtdesc 0x00007ca4
> +#define SYM_innerloop 0x00007c3d
> +#define SYM_mainloop 0x00007c38
> +#define SYM_start 0x00007c00
> +#define SYM_suspend_me 0x00007caa
> diff --git a/tests/qtest/migration-helpers.c b/tests/qtest/migration-helpers.c
> index be00c52..433d678 100644
> --- a/tests/qtest/migration-helpers.c
> +++ b/tests/qtest/migration-helpers.c
> @@ -28,7 +28,7 @@ bool migrate_watch_for_stop(QTestState *who, const char *name,
> {
> bool *seen = opaque;
>
> - if (g_str_equal(name, "STOP")) {
> + if (g_str_equal(name, "STOP") || g_str_equal(name, "SUSPEND")) {
> *seen = true;
This is also a bit hachish.. "*seen" points to got_src_stop, so when
SUSPEND it'll set got_src_stop. It's not clear what stage we're in even if
that's set, irrelevant of the confusing naming after being able to SUSPEND.
Shall we just add one got_src_suspended here and explicitly check that when
suspend=true in test?
> return true;
> }
> diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
> index b0c355b..73b07b3 100644
> --- a/tests/qtest/migration-test.c
> +++ b/tests/qtest/migration-test.c
> @@ -121,7 +121,7 @@ static void init_bootfile(const char *bootpath, void *content, size_t len)
> /*
> * Wait for some output in the serial output file,
> * we get an 'A' followed by an endless string of 'B's
> - * but on the destination we won't have the A.
> + * but on the destination we won't have the A (unless we enabled suspend/resume)
> */
> static void wait_for_serial(const char *side)
> {
> @@ -507,6 +507,8 @@ typedef struct {
> bool use_dirty_ring;
> const char *opts_source;
> const char *opts_target;
> + /* suspend the src before migrating to dest. */
> + bool suspend;
> } MigrateStart;
>
> /*
> @@ -617,6 +619,8 @@ static int test_migrate_start(QTestState **from, QTestState **to,
> }
> }
>
> + x86_bootsect[SYM_suspend_me - SYM_start] = args->suspend;
> +
> got_src_stop = false;
> got_dst_resume = false;
> bootpath = g_strdup_printf("%s/bootsect", tmpfs);
> @@ -1475,7 +1479,13 @@ static void test_precopy_common(MigrateCommon *args)
> */
> wait_for_migration_complete(to);
>
> - qtest_qmp_assert_success(to, "{ 'execute' : 'cont'}");
> + if (!args->start.suspend) {
> + qtest_qmp_assert_success(to, "{ 'execute' : 'cont'}");
> + }
This is live==false path, if this test needs live=true then afaict this
path won't ever trigger.
Even if it triggers, "qmp_cont" skips for SUSPEND already, so I assume
we're fine.
> + }
> +
> + if (args->start.suspend) {
> + qtest_qmp_assert_success(to, "{'execute': 'system_wakeup'}");
Okay I did look up qmp_system_wakeup and I think it implicitly checks the
SUSPEND status, which is reasonable but not obvious. Not sure whether
that's intended.
Shall we just check it explicitly with a query-status, even if so?
If keeping relying on qmp_system_wakeup not failing, I suggest we add a
comment explaining that this explicitly checks machine state so we're sure
the SUSPEND state is migrated properly.
> }
>
> if (!got_dst_resume) {
> @@ -1508,6 +1518,18 @@ static void test_precopy_unix_plain(void)
> test_precopy_common(&args);
> }
>
> +static void test_precopy_unix_suspend(void)
> +{
> + g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
> + MigrateCommon args = {
> + .listen_uri = uri,
> + .connect_uri = uri,
> + .live = true,
We need explicit comment for all .live=true cases to state why. Please
refer to:
/*
* Optional: whether the guest CPUs should be running during a precopy
* migration test. We used to always run with live but it took much
* longer so we reduced live tests to only the ones that have solid
* reason to be tested live-only. For each of the new test cases for
* precopy please provide justifications to use live explicitly (please
* refer to existing ones with live=true), or use live=off by default.
*/
bool live;
Thanks,
> + .start.suspend = true,
> + };
> +
> + test_precopy_common(&args);
> +}
>
> static void test_precopy_unix_dirty_ring(void)
> {
> @@ -2682,6 +2704,11 @@ int main(int argc, char **argv)
>
> module_call_init(MODULE_INIT_QOM);
>
> + if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
> + qtest_add_func("/migration/precopy/unix/suspend",
> + test_precopy_unix_suspend);
> + }
> +
> if (has_uffd) {
> qtest_add_func("/migration/postcopy/plain", test_postcopy);
> qtest_add_func("/migration/postcopy/recovery/plain",
> --
> 1.8.3.1
>
--
Peter Xu
next prev parent reply other threads:[~2023-06-21 16:45 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-15 20:26 [PATCH V1 0/3] fix migration of suspended runstate Steve Sistare
2023-06-15 20:26 ` [PATCH V1 1/3] vl: start on wakeup request Steve Sistare
2023-06-15 20:26 ` [PATCH V1 2/3] migration: fix suspended runstate Steve Sistare
2023-06-20 21:46 ` Peter Xu
2023-06-21 19:15 ` Steven Sistare
2023-06-21 20:28 ` Peter Xu
2023-06-23 18:25 ` Steven Sistare
2023-06-23 19:56 ` Steven Sistare
2023-06-26 18:27 ` Peter Xu
2023-06-26 19:11 ` Peter Xu
2023-06-30 13:50 ` Steven Sistare
2023-07-26 20:18 ` Peter Xu
2023-08-14 18:53 ` Steven Sistare
2023-08-14 19:37 ` Peter Xu
2023-08-16 17:48 ` Steven Sistare
2023-08-17 18:19 ` Peter Xu
2023-08-24 20:53 ` Steven Sistare
2023-06-15 20:26 ` [PATCH V1 3/3] tests/qtest: live migration suspended state Steve Sistare
2023-06-21 16:45 ` Peter Xu [this message]
2023-06-21 19:39 ` Steven Sistare
2023-06-21 20:00 ` Peter Xu
2023-06-22 21:28 ` Steven Sistare
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZJMpFfetFkZ/QjfT@x1n \
--to=peterx@redhat.com \
--cc=berrange@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=quintela@redhat.com \
--cc=steven.sistare@oracle.com \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.