summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2022-07-20 22:33:35 +0100
committerPeter Maydell <peter.maydell@linaro.org>2022-07-20 22:33:35 +0100
commitfe16c833fdb74642c296fa96a472e39229cd4351 (patch)
treeba1d92b35dc4eb227d72a0c4839c06d4d375cc76 /tests
parent8ec4bc3c8c09366a9e4859de7c0a1860911e8424 (diff)
parentdb727a14108b5f7ee1273f94e8ccce428a646140 (diff)
Merge tag 'pull-migration-20220720c' of https://gitlab.com/dagrh/qemu into staging
Migration pull 2022-07-20 This replaces yesterdays pull and: a) Fixes some test build errors without TLS b) Reenabled the zlib acceleration on s390 now that we have Ilya's fix Hyman's dirty page rate limit set Ilya's fix for zlib vs migration Peter's postcopy-preempt Cleanup from Dan zero-copy tidy ups from Leo multifd doc fix from Juan Revert disable of zlib acceleration on s390x Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com> # gpg: Signature made Wed 20 Jul 2022 12:18:56 BST # gpg: using RSA key 45F5C71B4A0CB7FB977A9FA90516331EBC5BFDE7 # gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" [full] # Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A 9FA9 0516 331E BC5B FDE7 * tag 'pull-migration-20220720c' of https://gitlab.com/dagrh/qemu: (30 commits) Revert "gitlab: disable accelerated zlib for s390x" migration: Avoid false-positive on non-supported scenarios for zero-copy-send multifd: Document the locking of MultiFD{Send/Recv}Params migration/multifd: Report to user when zerocopy not working Add dirty-sync-missed-zero-copy migration stat QIOChannelSocket: Fix zero-copy flush returning code 1 when nothing sent migration: remove unreachable code after reading data tests: Add postcopy preempt tests tests: Add postcopy tls recovery migration test tests: Add postcopy tls migration test tests: Move MigrateCommon upper migration: Respect postcopy request order in preemption mode migration: Enable TLS for preempt channel migration: Export tls-[creds|hostname|authz] params to cmdline too migration: Add helpers to detect TLS capability migration: Add property x-postcopy-preempt-break-huge migration: Create the postcopy preempt channel asynchronously migration: Postcopy recover with preempt enabled migration: Postcopy preemption enablement migration: Postcopy preemption preparation on channel creation ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/qtest/migration-helpers.c22
-rw-r--r--tests/qtest/migration-helpers.h2
-rw-r--r--tests/qtest/migration-test.c543
-rw-r--r--tests/qtest/qmp-cmd-test.c2
4 files changed, 484 insertions, 85 deletions
diff --git a/tests/qtest/migration-helpers.c b/tests/qtest/migration-helpers.c
index e81e831c85..c6fbeb3974 100644
--- a/tests/qtest/migration-helpers.c
+++ b/tests/qtest/migration-helpers.c
@@ -84,6 +84,28 @@ QDict *wait_command(QTestState *who, const char *command, ...)
}
/*
+ * Execute the qmp command only
+ */
+QDict *qmp_command(QTestState *who, const char *command, ...)
+{
+ va_list ap;
+ QDict *resp, *ret;
+
+ va_start(ap, command);
+ resp = qtest_vqmp(who, command, ap);
+ va_end(ap);
+
+ g_assert(!qdict_haskey(resp, "error"));
+ g_assert(qdict_haskey(resp, "return"));
+
+ ret = qdict_get_qdict(resp, "return");
+ qobject_ref(ret);
+ qobject_unref(resp);
+
+ return ret;
+}
+
+/*
* Send QMP command "migrate".
* Arguments are built from @fmt... (formatted like
* qobject_from_jsonf_nofail()) with "uri": @uri spliced in.
diff --git a/tests/qtest/migration-helpers.h b/tests/qtest/migration-helpers.h
index 78587c2b82..59561898d0 100644
--- a/tests/qtest/migration-helpers.h
+++ b/tests/qtest/migration-helpers.h
@@ -23,6 +23,8 @@ QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...);
G_GNUC_PRINTF(2, 3)
QDict *wait_command(QTestState *who, const char *command, ...);
+QDict *qmp_command(QTestState *who, const char *command, ...);
+
G_GNUC_PRINTF(3, 4)
void migrate_qmp(QTestState *who, const char *uri, const char *fmt, ...);
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 9e64125f02..71595a74fd 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -24,6 +24,7 @@
#include "qapi/qobject-input-visitor.h"
#include "qapi/qobject-output-visitor.h"
#include "crypto/tlscredspsk.h"
+#include "qapi/qmp/qlist.h"
#include "migration-helpers.h"
#include "tests/migration/migration-test.h"
@@ -46,6 +47,12 @@ unsigned start_address;
unsigned end_address;
static bool uffd_feature_thread_id;
+/*
+ * Dirtylimit stop working if dirty page rate error
+ * value less than DIRTYLIMIT_TOLERANCE_RANGE
+ */
+#define DIRTYLIMIT_TOLERANCE_RANGE 25 /* MB/s */
+
#if defined(__linux__)
#include <sys/syscall.h>
#include <sys/vfs.h>
@@ -496,6 +503,82 @@ typedef struct {
const char *opts_target;
} MigrateStart;
+/*
+ * A hook that runs after the src and dst QEMUs have been
+ * created, but before the migration is started. This can
+ * be used to set migration parameters and capabilities.
+ *
+ * Returns: NULL, or a pointer to opaque state to be
+ * later passed to the TestMigrateFinishHook
+ */
+typedef void * (*TestMigrateStartHook)(QTestState *from,
+ QTestState *to);
+
+/*
+ * A hook that runs after the migration has finished,
+ * regardless of whether it succeeded or failed, but
+ * before QEMU has terminated (unless it self-terminated
+ * due to migration error)
+ *
+ * @opaque is a pointer to state previously returned
+ * by the TestMigrateStartHook if any, or NULL.
+ */
+typedef void (*TestMigrateFinishHook)(QTestState *from,
+ QTestState *to,
+ void *opaque);
+
+typedef struct {
+ /* Optional: fine tune start parameters */
+ MigrateStart start;
+
+ /* Required: the URI for the dst QEMU to listen on */
+ const char *listen_uri;
+
+ /*
+ * Optional: the URI for the src QEMU to connect to
+ * If NULL, then it will query the dst QEMU for its actual
+ * listening address and use that as the connect address.
+ * This allows for dynamically picking a free TCP port.
+ */
+ const char *connect_uri;
+
+ /* Optional: callback to run at start to set migration parameters */
+ TestMigrateStartHook start_hook;
+ /* Optional: callback to run at finish to cleanup */
+ TestMigrateFinishHook finish_hook;
+
+ /*
+ * Optional: normally we expect the migration process to complete.
+ *
+ * There can be a variety of reasons and stages in which failure
+ * can happen during tests.
+ *
+ * If a failure is expected to happen at time of establishing
+ * the connection, then MIG_TEST_FAIL will indicate that the dst
+ * QEMU is expected to stay running and accept future migration
+ * connections.
+ *
+ * If a failure is expected to happen while processing the
+ * migration stream, then MIG_TEST_FAIL_DEST_QUIT_ERR will indicate
+ * that the dst QEMU is expected to quit with non-zero exit status
+ */
+ enum {
+ /* This test should succeed, the default */
+ MIG_TEST_SUCCEED = 0,
+ /* This test should fail, dest qemu should keep alive */
+ MIG_TEST_FAIL,
+ /* This test should fail, dest qemu should fail with abnormal status */
+ MIG_TEST_FAIL_DEST_QUIT_ERR,
+ } result;
+
+ /* Optional: set number of migration passes to wait for */
+ unsigned int iterations;
+
+ /* Postcopy specific fields */
+ void *postcopy_data;
+ bool postcopy_preempt;
+} MigrateCommon;
+
static int test_migrate_start(QTestState **from, QTestState **to,
const char *uri, MigrateStart *args)
{
@@ -982,19 +1065,28 @@ test_migrate_tls_x509_finish(QTestState *from,
static int migrate_postcopy_prepare(QTestState **from_ptr,
QTestState **to_ptr,
- MigrateStart *args)
+ MigrateCommon *args)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
QTestState *from, *to;
- if (test_migrate_start(&from, &to, uri, args)) {
+ if (test_migrate_start(&from, &to, uri, &args->start)) {
return -1;
}
+ if (args->start_hook) {
+ args->postcopy_data = args->start_hook(from, to);
+ }
+
migrate_set_capability(from, "postcopy-ram", true);
migrate_set_capability(to, "postcopy-ram", true);
migrate_set_capability(to, "postcopy-blocktime", true);
+ if (args->postcopy_preempt) {
+ migrate_set_capability(from, "postcopy-preempt", true);
+ migrate_set_capability(to, "postcopy-preempt", true);
+ }
+
migrate_ensure_non_converge(from);
/* Wait for the first serial output from the source */
@@ -1010,7 +1102,8 @@ static int migrate_postcopy_prepare(QTestState **from_ptr,
return 0;
}
-static void migrate_postcopy_complete(QTestState *from, QTestState *to)
+static void migrate_postcopy_complete(QTestState *from, QTestState *to,
+ MigrateCommon *args)
{
wait_for_migration_complete(from);
@@ -1021,30 +1114,73 @@ static void migrate_postcopy_complete(QTestState *from, QTestState *to)
read_blocktime(to);
}
+ if (args->finish_hook) {
+ args->finish_hook(from, to, args->postcopy_data);
+ args->postcopy_data = NULL;
+ }
+
test_migrate_end(from, to, true);
}
-static void test_postcopy(void)
+static void test_postcopy_common(MigrateCommon *args)
{
- MigrateStart args = {};
QTestState *from, *to;
- if (migrate_postcopy_prepare(&from, &to, &args)) {
+ if (migrate_postcopy_prepare(&from, &to, args)) {
return;
}
migrate_postcopy_start(from, to);
- migrate_postcopy_complete(from, to);
+ migrate_postcopy_complete(from, to, args);
}
-static void test_postcopy_recovery(void)
+static void test_postcopy(void)
{
- MigrateStart args = {
- .hide_stderr = true,
+ MigrateCommon args = { };
+
+ test_postcopy_common(&args);
+}
+
+static void test_postcopy_preempt(void)
+{
+ MigrateCommon args = {
+ .postcopy_preempt = true,
};
+
+ test_postcopy_common(&args);
+}
+
+#ifdef CONFIG_GNUTLS
+static void test_postcopy_tls_psk(void)
+{
+ MigrateCommon args = {
+ .start_hook = test_migrate_tls_psk_start_match,
+ .finish_hook = test_migrate_tls_psk_finish,
+ };
+
+ test_postcopy_common(&args);
+}
+
+static void test_postcopy_preempt_tls_psk(void)
+{
+ MigrateCommon args = {
+ .postcopy_preempt = true,
+ .start_hook = test_migrate_tls_psk_start_match,
+ .finish_hook = test_migrate_tls_psk_finish,
+ };
+
+ test_postcopy_common(&args);
+}
+#endif
+
+static void test_postcopy_recovery_common(MigrateCommon *args)
+{
QTestState *from, *to;
g_autofree char *uri = NULL;
- if (migrate_postcopy_prepare(&from, &to, &args)) {
+ /* Always hide errors for postcopy recover tests since they're expected */
+ args->start.hide_stderr = true;
+
+ if (migrate_postcopy_prepare(&from, &to, args)) {
return;
}
@@ -1095,9 +1231,51 @@ static void test_postcopy_recovery(void)
/* Restore the postcopy bandwidth to unlimited */
migrate_set_parameter_int(from, "max-postcopy-bandwidth", 0);
- migrate_postcopy_complete(from, to);
+ migrate_postcopy_complete(from, to, args);
}
+static void test_postcopy_recovery(void)
+{
+ MigrateCommon args = { };
+
+ test_postcopy_recovery_common(&args);
+}
+
+#ifdef CONFIG_GNUTLS
+static void test_postcopy_recovery_tls_psk(void)
+{
+ MigrateCommon args = {
+ .start_hook = test_migrate_tls_psk_start_match,
+ .finish_hook = test_migrate_tls_psk_finish,
+ };
+
+ test_postcopy_recovery_common(&args);
+}
+#endif
+
+static void test_postcopy_preempt_recovery(void)
+{
+ MigrateCommon args = {
+ .postcopy_preempt = true,
+ };
+
+ test_postcopy_recovery_common(&args);
+}
+
+#ifdef CONFIG_GNUTLS
+/* This contains preempt+recovery+tls test altogether */
+static void test_postcopy_preempt_all(void)
+{
+ MigrateCommon args = {
+ .postcopy_preempt = true,
+ .start_hook = test_migrate_tls_psk_start_match,
+ .finish_hook = test_migrate_tls_psk_finish,
+ };
+
+ test_postcopy_recovery_common(&args);
+}
+#endif
+
static void test_baddest(void)
{
MigrateStart args = {
@@ -1113,78 +1291,6 @@ static void test_baddest(void)
test_migrate_end(from, to, false);
}
-/*
- * A hook that runs after the src and dst QEMUs have been
- * created, but before the migration is started. This can
- * be used to set migration parameters and capabilities.
- *
- * Returns: NULL, or a pointer to opaque state to be
- * later passed to the TestMigrateFinishHook
- */
-typedef void * (*TestMigrateStartHook)(QTestState *from,
- QTestState *to);
-
-/*
- * A hook that runs after the migration has finished,
- * regardless of whether it succeeded or failed, but
- * before QEMU has terminated (unless it self-terminated
- * due to migration error)
- *
- * @opaque is a pointer to state previously returned
- * by the TestMigrateStartHook if any, or NULL.
- */
-typedef void (*TestMigrateFinishHook)(QTestState *from,
- QTestState *to,
- void *opaque);
-
-typedef struct {
- /* Optional: fine tune start parameters */
- MigrateStart start;
-
- /* Required: the URI for the dst QEMU to listen on */
- const char *listen_uri;
-
- /*
- * Optional: the URI for the src QEMU to connect to
- * If NULL, then it will query the dst QEMU for its actual
- * listening address and use that as the connect address.
- * This allows for dynamically picking a free TCP port.
- */
- const char *connect_uri;
-
- /* Optional: callback to run at start to set migration parameters */
- TestMigrateStartHook start_hook;
- /* Optional: callback to run at finish to cleanup */
- TestMigrateFinishHook finish_hook;
-
- /*
- * Optional: normally we expect the migration process to complete.
- *
- * There can be a variety of reasons and stages in which failure
- * can happen during tests.
- *
- * If a failure is expected to happen at time of establishing
- * the connection, then MIG_TEST_FAIL will indicate that the dst
- * QEMU is expected to stay running and accept future migration
- * connections.
- *
- * If a failure is expected to happen while processing the
- * migration stream, then MIG_TEST_FAIL_DEST_QUIT_ERR will indicate
- * that the dst QEMU is expected to quit with non-zero exit status
- */
- enum {
- /* This test should succeed, the default */
- MIG_TEST_SUCCEED = 0,
- /* This test should fail, dest qemu should keep alive */
- MIG_TEST_FAIL,
- /* This test should fail, dest qemu should fail with abnormal status */
- MIG_TEST_FAIL_DEST_QUIT_ERR,
- } result;
-
- /* Optional: set number of migration passes to wait for */
- unsigned int iterations;
-} MigrateCommon;
-
static void test_precopy_common(MigrateCommon *args)
{
QTestState *from, *to;
@@ -2059,6 +2165,253 @@ static void test_multifd_tcp_cancel(void)
test_migrate_end(from, to2, true);
}
+static void calc_dirty_rate(QTestState *who, uint64_t calc_time)
+{
+ qobject_unref(qmp_command(who,
+ "{ 'execute': 'calc-dirty-rate',"
+ "'arguments': { "
+ "'calc-time': %ld,"
+ "'mode': 'dirty-ring' }}",
+ calc_time));
+}
+
+static QDict *query_dirty_rate(QTestState *who)
+{
+ return qmp_command(who, "{ 'execute': 'query-dirty-rate' }");
+}
+
+static void dirtylimit_set_all(QTestState *who, uint64_t dirtyrate)
+{
+ qobject_unref(qmp_command(who,
+ "{ 'execute': 'set-vcpu-dirty-limit',"
+ "'arguments': { "
+ "'dirty-rate': %ld } }",
+ dirtyrate));
+}
+
+static void cancel_vcpu_dirty_limit(QTestState *who)
+{
+ qobject_unref(qmp_command(who,
+ "{ 'execute': 'cancel-vcpu-dirty-limit' }"));
+}
+
+static QDict *query_vcpu_dirty_limit(QTestState *who)
+{
+ QDict *rsp;
+
+ rsp = qtest_qmp(who, "{ 'execute': 'query-vcpu-dirty-limit' }");
+ g_assert(!qdict_haskey(rsp, "error"));
+ g_assert(qdict_haskey(rsp, "return"));
+
+ return rsp;
+}
+
+static bool calc_dirtyrate_ready(QTestState *who)
+{
+ QDict *rsp_return;
+ gchar *status;
+
+ rsp_return = query_dirty_rate(who);
+ g_assert(rsp_return);
+
+ status = g_strdup(qdict_get_str(rsp_return, "status"));
+ g_assert(status);
+
+ return g_strcmp0(status, "measuring");
+}
+
+static void wait_for_calc_dirtyrate_complete(QTestState *who,
+ int64_t time_s)
+{
+ int max_try_count = 10000;
+ usleep(time_s * 1000000);
+
+ while (!calc_dirtyrate_ready(who) && max_try_count--) {
+ usleep(1000);
+ }
+
+ /*
+ * Set the timeout with 10 s(max_try_count * 1000us),
+ * if dirtyrate measurement not complete, fail test.
+ */
+ g_assert_cmpint(max_try_count, !=, 0);
+}
+
+static int64_t get_dirty_rate(QTestState *who)
+{
+ QDict *rsp_return;
+ gchar *status;
+ QList *rates;
+ const QListEntry *entry;
+ QDict *rate;
+ int64_t dirtyrate;
+
+ rsp_return = query_dirty_rate(who);
+ g_assert(rsp_return);
+
+ status = g_strdup(qdict_get_str(rsp_return, "status"));
+ g_assert(status);
+ g_assert_cmpstr(status, ==, "measured");
+
+ rates = qdict_get_qlist(rsp_return, "vcpu-dirty-rate");
+ g_assert(rates && !qlist_empty(rates));
+
+ entry = qlist_first(rates);
+ g_assert(entry);
+
+ rate = qobject_to(QDict, qlist_entry_obj(entry));
+ g_assert(rate);
+
+ dirtyrate = qdict_get_try_int(rate, "dirty-rate", -1);
+
+ qobject_unref(rsp_return);
+ return dirtyrate;
+}
+
+static int64_t get_limit_rate(QTestState *who)
+{
+ QDict *rsp_return;
+ QList *rates;
+ const QListEntry *entry;
+ QDict *rate;
+ int64_t dirtyrate;
+
+ rsp_return = query_vcpu_dirty_limit(who);
+ g_assert(rsp_return);
+
+ rates = qdict_get_qlist(rsp_return, "return");
+ g_assert(rates && !qlist_empty(rates));
+
+ entry = qlist_first(rates);
+ g_assert(entry);
+
+ rate = qobject_to(QDict, qlist_entry_obj(entry));
+ g_assert(rate);
+
+ dirtyrate = qdict_get_try_int(rate, "limit-rate", -1);
+
+ qobject_unref(rsp_return);
+ return dirtyrate;
+}
+
+static QTestState *dirtylimit_start_vm(void)
+{
+ QTestState *vm = NULL;
+ g_autofree gchar *cmd = NULL;
+ const char *arch = qtest_get_arch();
+ g_autofree char *bootpath = NULL;
+
+ assert((strcmp(arch, "x86_64") == 0));
+ bootpath = g_strdup_printf("%s/bootsect", tmpfs);
+ assert(sizeof(x86_bootsect) == 512);
+ init_bootfile(bootpath, x86_bootsect, sizeof(x86_bootsect));
+
+ cmd = g_strdup_printf("-accel kvm,dirty-ring-size=4096 "
+ "-name dirtylimit-test,debug-threads=on "
+ "-m 150M -smp 1 "
+ "-serial file:%s/vm_serial "
+ "-drive file=%s,format=raw ",
+ tmpfs, bootpath);
+
+ vm = qtest_init(cmd);
+ return vm;
+}
+
+static void dirtylimit_stop_vm(QTestState *vm)
+{
+ qtest_quit(vm);
+ cleanup("bootsect");
+ cleanup("vm_serial");
+}
+
+static void test_vcpu_dirty_limit(void)
+{
+ QTestState *vm;
+ int64_t origin_rate;
+ int64_t quota_rate;
+ int64_t rate ;
+ int max_try_count = 20;
+ int hit = 0;
+
+ /* Start vm for vcpu dirtylimit test */
+ vm = dirtylimit_start_vm();
+
+ /* Wait for the first serial output from the vm*/
+ wait_for_serial("vm_serial");
+
+ /* Do dirtyrate measurement with calc time equals 1s */
+ calc_dirty_rate(vm, 1);
+
+ /* Sleep calc time and wait for calc dirtyrate complete */
+ wait_for_calc_dirtyrate_complete(vm, 1);
+
+ /* Query original dirty page rate */
+ origin_rate = get_dirty_rate(vm);
+
+ /* VM booted from bootsect should dirty memory steadily */
+ assert(origin_rate != 0);
+
+ /* Setup quota dirty page rate at half of origin */
+ quota_rate = origin_rate / 2;
+
+ /* Set dirtylimit */
+ dirtylimit_set_all(vm, quota_rate);
+
+ /*
+ * Check if set-vcpu-dirty-limit and query-vcpu-dirty-limit
+ * works literally
+ */
+ g_assert_cmpint(quota_rate, ==, get_limit_rate(vm));
+
+ /* Sleep a bit to check if it take effect */
+ usleep(2000000);
+
+ /*
+ * Check if dirtylimit take effect realistically, set the
+ * timeout with 20 s(max_try_count * 1s), if dirtylimit
+ * doesn't take effect, fail test.
+ */
+ while (--max_try_count) {
+ calc_dirty_rate(vm, 1);
+ wait_for_calc_dirtyrate_complete(vm, 1);
+ rate = get_dirty_rate(vm);
+
+ /*
+ * Assume hitting if current rate is less
+ * than quota rate (within accepting error)
+ */
+ if (rate < (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) {
+ hit = 1;
+ break;
+ }
+ }
+
+ g_assert_cmpint(hit, ==, 1);
+
+ hit = 0;
+ max_try_count = 20;
+
+ /* Check if dirtylimit cancellation take effect */
+ cancel_vcpu_dirty_limit(vm);
+ while (--max_try_count) {
+ calc_dirty_rate(vm, 1);
+ wait_for_calc_dirtyrate_complete(vm, 1);
+ rate = get_dirty_rate(vm);
+
+ /*
+ * Assume dirtylimit be canceled if current rate is
+ * greater than quota rate (within accepting error)
+ */
+ if (rate > (quota_rate + DIRTYLIMIT_TOLERANCE_RANGE)) {
+ hit = 1;
+ break;
+ }
+ }
+
+ g_assert_cmpint(hit, ==, 1);
+ dirtylimit_stop_vm(vm);
+}
+
static bool kvm_dirty_ring_supported(void)
{
#if defined(__linux__) && defined(HOST_X86_64)
@@ -2123,13 +2476,31 @@ int main(int argc, char **argv)
module_call_init(MODULE_INIT_QOM);
qtest_add_func("/migration/postcopy/unix", test_postcopy);
- qtest_add_func("/migration/postcopy/recovery", test_postcopy_recovery);
+ qtest_add_func("/migration/postcopy/plain", test_postcopy);
+ qtest_add_func("/migration/postcopy/recovery/plain",
+ test_postcopy_recovery);
+ qtest_add_func("/migration/postcopy/preempt/plain", test_postcopy_preempt);
+ qtest_add_func("/migration/postcopy/preempt/recovery/plain",
+ test_postcopy_preempt_recovery);
+
qtest_add_func("/migration/bad_dest", test_baddest);
qtest_add_func("/migration/precopy/unix/plain", test_precopy_unix_plain);
qtest_add_func("/migration/precopy/unix/xbzrle", test_precopy_unix_xbzrle);
#ifdef CONFIG_GNUTLS
qtest_add_func("/migration/precopy/unix/tls/psk",
test_precopy_unix_tls_psk);
+ /*
+ * NOTE: psk test is enough for postcopy, as other types of TLS
+ * channels are tested under precopy. Here what we want to test is the
+ * general postcopy path that has TLS channel enabled.
+ */
+ qtest_add_func("/migration/postcopy/tls/psk", test_postcopy_tls_psk);
+ qtest_add_func("/migration/postcopy/recovery/tls/psk",
+ test_postcopy_recovery_tls_psk);
+ qtest_add_func("/migration/postcopy/preempt/tls/psk",
+ test_postcopy_preempt_tls_psk);
+ qtest_add_func("/migration/postcopy/preempt/recovery/tls/psk",
+ test_postcopy_preempt_all);
#ifdef CONFIG_TASN1
qtest_add_func("/migration/precopy/unix/tls/x509/default-host",
test_precopy_unix_tls_x509_default_host);
@@ -2204,6 +2575,8 @@ int main(int argc, char **argv)
if (kvm_dirty_ring_supported()) {
qtest_add_func("/migration/dirty_ring",
test_precopy_unix_dirty_ring);
+ qtest_add_func("/migration/vcpu_dirty_limit",
+ test_vcpu_dirty_limit);
}
ret = g_test_run();
diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c
index 056b40e67f..af00712458 100644
--- a/tests/qtest/qmp-cmd-test.c
+++ b/tests/qtest/qmp-cmd-test.c
@@ -110,6 +110,8 @@ static bool query_is_ignored(const char *cmd)
"query-sev-capabilities",
"query-sgx",
"query-sgx-capabilities",
+ /* Success depends on enabling dirty page rate limit */
+ "query-vcpu-dirty-limit",
NULL
};
int i;