From 0d9d4872e54945c161933f1c1f6eddf1f18dfc90 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Mon, 18 Feb 2019 10:21:59 +0100 Subject: tests/device-plug: Add a simple PCI unplug request test The issue with testing asynchronous unplug requests it that they usually require a running guest to handle the request. However, to test if unplug of PCI devices works, we can apply a nice little trick on some architectures: On system reset, x86 ACPI, s390x and spapr will perform the unplug, resulting in the device of interest to get deleted and a DEVICE_DELETED event getting sent. On s390x, we still get a warning qemu-system-s390x: -device virtio-mouse-pci,id=dev0: warning: Plugging a PCI/zPCI device without the 'zpci' CPU feature enabled; the guest will not be able to see/use this device This will be fixed soon, when we enable the zpci CPU feature always (Conny already has a patch for this queued). Reviewed-by: Michael S. Tsirkin Reviewed-by: Greg Kurz Reviewed-by: Thomas Huth Reviewed-by: Collin Walling Reviewed-by: David Gibson Signed-off-by: David Hildenbrand Message-Id: <20190218092202.26683-4-david@redhat.com> Acked-by: Cornelia Huck Signed-off-by: David Gibson --- tests/Makefile.include | 4 +++ tests/device-plug-test.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 tests/device-plug-test.c (limited to 'tests') diff --git a/tests/Makefile.include b/tests/Makefile.include index 3741f8f..b62d82b 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -192,6 +192,7 @@ check-qtest-i386-$(CONFIG_ISA_IPMI_KCS) += tests/ipmi-kcs-test$(EXESUF) # check-qtest-i386-$(CONFIG_ISA_IPMI_BT) += tests/ipmi-bt-test$(EXESUF) check-qtest-i386-y += tests/i440fx-test$(EXESUF) check-qtest-i386-y += tests/fw_cfg-test$(EXESUF) +check-qtest-i386-y += tests/device-plug-test$(EXESUF) check-qtest-i386-y += tests/drive_del-test$(EXESUF) check-qtest-i386-$(CONFIG_WDT_IB700) += tests/wdt_ib700-test$(EXESUF) check-qtest-i386-y += tests/tco-test$(EXESUF) @@ -256,6 +257,7 @@ check-qtest-ppc-$(CONFIG_M48T59) += tests/m48t59-test$(EXESUF) check-qtest-ppc64-y += $(check-qtest-ppc-y) check-qtest-ppc64-$(CONFIG_PSERIES) += tests/spapr-phb-test$(EXESUF) +check-qtest-ppc64-$(CONFIG_PSERIES) += tests/device-plug-test$(EXESUF) check-qtest-ppc64-$(CONFIG_POWERNV) += tests/pnv-xscom-test$(EXESUF) check-qtest-ppc64-y += tests/migration-test$(EXESUF) check-qtest-ppc64-$(CONFIG_PSERIES) += tests/rtas-test$(EXESUF) @@ -310,6 +312,7 @@ check-qtest-s390x-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF) check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF) check-qtest-s390x-$(CONFIG_POSIX) += tests/test-filter-redirector$(EXESUF) check-qtest-s390x-y += tests/drive_del-test$(EXESUF) +check-qtest-s390x-y += tests/device-plug-test$(EXESUF) check-qtest-s390x-y += tests/virtio-ccw-test$(EXESUF) check-qtest-s390x-y += tests/cpu-plug-test$(EXESUF) check-qtest-s390x-y += tests/migration-test$(EXESUF) @@ -750,6 +753,7 @@ tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o tests/qom-test$(EXESUF): tests/qom-test.o tests/test-hmp$(EXESUF): tests/test-hmp.o tests/machine-none-test$(EXESUF): tests/machine-none-test.o +tests/device-plug-test$(EXESUF): tests/device-plug-test.o tests/drive_del-test$(EXESUF): tests/drive_del-test.o $(libqos-virtio-obj-y) tests/nvme-test$(EXESUF): tests/nvme-test.o $(libqos-pc-obj-y) tests/pvpanic-test$(EXESUF): tests/pvpanic-test.o diff --git a/tests/device-plug-test.c b/tests/device-plug-test.c new file mode 100644 index 0000000..cd9ada5 --- /dev/null +++ b/tests/device-plug-test.c @@ -0,0 +1,93 @@ +/* + * QEMU device plug/unplug handling + * + * Copyright (C) 2019 Red Hat Inc. + * + * Authors: + * David Hildenbrand + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qstring.h" + +static void device_del_request(QTestState *qtest, const char *id) +{ + QDict *resp; + + resp = qtest_qmp(qtest, + "{'execute': 'device_del', 'arguments': { 'id': %s } }", + id); + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); +} + +static void system_reset(QTestState *qtest) +{ + QDict *resp; + + resp = qtest_qmp(qtest, "{'execute': 'system_reset'}"); + g_assert(qdict_haskey(resp, "return")); + qobject_unref(resp); +} + +static void wait_device_deleted_event(QTestState *qtest, const char *id) +{ + QDict *resp, *data; + QString *qstr; + + /* + * Other devices might get removed along with the removed device. Skip + * these. The device of interest will be the last one. + */ + for (;;) { + resp = qtest_qmp_eventwait_ref(qtest, "DEVICE_DELETED"); + data = qdict_get_qdict(resp, "data"); + if (!data || !qdict_get(data, "device")) { + qobject_unref(resp); + continue; + } + qstr = qobject_to(QString, qdict_get(data, "device")); + g_assert(qstr); + if (!strcmp(qstring_get_str(qstr), id)) { + qobject_unref(resp); + break; + } + qobject_unref(resp); + } +} + +static void test_pci_unplug_request(void) +{ + QTestState *qtest = qtest_initf("-device virtio-mouse-pci,id=dev0"); + + /* + * Request device removal. As the guest is not running, the request won't + * be processed. However during system reset, the removal will be + * handled, removing the device. + */ + device_del_request(qtest, "dev0"); + system_reset(qtest); + wait_device_deleted_event(qtest, "dev0"); + + qtest_quit(qtest); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + /* + * We need a system that will process unplug requests during system resets + * and does not do PCI surprise removal. This holds for x86 ACPI, + * s390x and spapr. + */ + qtest_add_func("/device-plug/pci-unplug-request", + test_pci_unplug_request); + + return g_test_run(); +} -- cgit v1.1 From 613ebbec647d6d159a2fc81b4c34290765901de3 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Mon, 18 Feb 2019 10:22:00 +0100 Subject: tests/device-plug: Add CCW unplug test for s390x As CCW unplugs are surprise removals without asking the guest first, we can test this without any guest interaction. Reviewed-by: Michael S. Tsirkin Reviewed-by: Thomas Huth Signed-off-by: David Hildenbrand Message-Id: <20190218092202.26683-5-david@redhat.com> Acked-by: Cornelia Huck Signed-off-by: David Gibson --- tests/device-plug-test.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) (limited to 'tests') diff --git a/tests/device-plug-test.c b/tests/device-plug-test.c index cd9ada5..d1a6c94 100644 --- a/tests/device-plug-test.c +++ b/tests/device-plug-test.c @@ -15,17 +15,26 @@ #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" -static void device_del_request(QTestState *qtest, const char *id) +static void device_del_start(QTestState *qtest, const char *id) { - QDict *resp; + qtest_qmp_send(qtest, + "{'execute': 'device_del', 'arguments': { 'id': %s } }", id); +} + +static void device_del_finish(QTestState *qtest) +{ + QDict *resp = qtest_qmp_receive(qtest); - resp = qtest_qmp(qtest, - "{'execute': 'device_del', 'arguments': { 'id': %s } }", - id); g_assert(qdict_haskey(resp, "return")); qobject_unref(resp); } +static void device_del_request(QTestState *qtest, const char *id) +{ + device_del_start(qtest, id); + device_del_finish(qtest); +} + static void system_reset(QTestState *qtest) { QDict *resp; @@ -77,8 +86,25 @@ static void test_pci_unplug_request(void) qtest_quit(qtest); } +static void test_ccw_unplug(void) +{ + QTestState *qtest = qtest_initf("-device virtio-balloon-ccw,id=dev0"); + + /* + * The DEVICE_DELETED events will be sent before the command + * completes. + */ + device_del_start(qtest, "dev0"); + wait_device_deleted_event(qtest, "dev0"); + device_del_finish(qtest); + + qtest_quit(qtest); +} + int main(int argc, char **argv) { + const char *arch = qtest_get_arch(); + g_test_init(&argc, &argv, NULL); /* @@ -89,5 +115,10 @@ int main(int argc, char **argv) qtest_add_func("/device-plug/pci-unplug-request", test_pci_unplug_request); + if (!strcmp(arch, "s390x")) { + qtest_add_func("/device-plug/ccw-unplug", + test_ccw_unplug); + } + return g_test_run(); } -- cgit v1.1 From c76480e5a0cc068b5fd39b50f4e36496bfaba95a Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Mon, 18 Feb 2019 10:22:01 +0100 Subject: tests/device-plug: Add CPU core unplug request test for spapr We can easily test this, just like PCI. On s390x, cpu unplug is not supported. On x86 ACPI, cpu unplug requires guest interaction to work, so it can't be tested that easily. We might add tests for ACPI later. Reviewed-by: Michael S. Tsirkin Reviewed-by: Greg Kurz Reviewed-by: Thomas Huth Signed-off-by: David Hildenbrand Message-Id: <20190218092202.26683-6-david@redhat.com> Signed-off-by: David Gibson --- tests/device-plug-test.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'tests') diff --git a/tests/device-plug-test.c b/tests/device-plug-test.c index d1a6c94..0262ad6 100644 --- a/tests/device-plug-test.c +++ b/tests/device-plug-test.c @@ -101,6 +101,21 @@ static void test_ccw_unplug(void) qtest_quit(qtest); } +static void test_spapr_cpu_unplug_request(void) +{ + QTestState *qtest; + + qtest = qtest_initf("-cpu power9_v2.0 -smp 1,maxcpus=2 " + "-device power9_v2.0-spapr-cpu-core,core-id=1,id=dev0"); + + /* similar to test_pci_unplug_request */ + device_del_request(qtest, "dev0"); + system_reset(qtest); + wait_device_deleted_event(qtest, "dev0"); + + qtest_quit(qtest); +} + int main(int argc, char **argv) { const char *arch = qtest_get_arch(); @@ -120,5 +135,10 @@ int main(int argc, char **argv) test_ccw_unplug); } + if (!strcmp(arch, "ppc64")) { + qtest_add_func("/device-plug/spapr-cpu-unplug-request", + test_spapr_cpu_unplug_request); + } + return g_test_run(); } -- cgit v1.1 From 368807049344f437d467aea9af4bc8b05d5fbee2 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Mon, 18 Feb 2019 10:22:02 +0100 Subject: tests/device-plug: Add memory unplug request test for spapr We can easily test this, just like PCI. On x86 ACPI, we need guest interaction to make it work, so it is not that easy to test. We might add tests for that later on. Reviewed-by: Michael S. Tsirkin Reviewed-by: Greg Kurz Reviewed-by: Thomas Huth Signed-off-by: David Hildenbrand Message-Id: <20190218092202.26683-7-david@redhat.com> Signed-off-by: David Gibson --- tests/device-plug-test.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'tests') diff --git a/tests/device-plug-test.c b/tests/device-plug-test.c index 0262ad6..87593d9 100644 --- a/tests/device-plug-test.c +++ b/tests/device-plug-test.c @@ -116,6 +116,22 @@ static void test_spapr_cpu_unplug_request(void) qtest_quit(qtest); } +static void test_spapr_memory_unplug_request(void) +{ + QTestState *qtest; + + qtest = qtest_initf("-m 256M,slots=1,maxmem=768M " + "-object memory-backend-ram,id=mem0,size=512M " + "-device pc-dimm,id=dev0,memdev=mem0"); + + /* similar to test_pci_unplug_request */ + device_del_request(qtest, "dev0"); + system_reset(qtest); + wait_device_deleted_event(qtest, "dev0"); + + qtest_quit(qtest); +} + int main(int argc, char **argv) { const char *arch = qtest_get_arch(); @@ -138,6 +154,8 @@ int main(int argc, char **argv) if (!strcmp(arch, "ppc64")) { qtest_add_func("/device-plug/spapr-cpu-unplug-request", test_spapr_cpu_unplug_request); + qtest_add_func("/device-plug/spapr-memory-unplug-request", + test_spapr_memory_unplug_request); } return g_test_run(); -- cgit v1.1 From 9bcb5b29419c79f0249280aaed80d40d7d798eeb Mon Sep 17 00:00:00 2001 From: Greg Kurz Date: Tue, 19 Feb 2019 18:18:59 +0100 Subject: tests/device-plug: Add PHB unplug request test for spapr We can easily test this, just like PCI. PHB unplug is not supported on s390x and x86 ACPI. Signed-off-by: Greg Kurz Message-Id: <155059673939.1466090.14354001937819612724.stgit@bahia.lab.toulouse-stg.fr.ibm.com> Signed-off-by: David Gibson --- tests/device-plug-test.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'tests') diff --git a/tests/device-plug-test.c b/tests/device-plug-test.c index 87593d9..318e422 100644 --- a/tests/device-plug-test.c +++ b/tests/device-plug-test.c @@ -132,6 +132,20 @@ static void test_spapr_memory_unplug_request(void) qtest_quit(qtest); } +static void test_spapr_phb_unplug_request(void) +{ + QTestState *qtest; + + qtest = qtest_initf("-device spapr-pci-host-bridge,index=1,id=dev0"); + + /* similar to test_pci_unplug_request */ + device_del_request(qtest, "dev0"); + system_reset(qtest); + wait_device_deleted_event(qtest, "dev0"); + + qtest_quit(qtest); +} + int main(int argc, char **argv) { const char *arch = qtest_get_arch(); @@ -156,6 +170,8 @@ int main(int argc, char **argv) test_spapr_cpu_unplug_request); qtest_add_func("/device-plug/spapr-memory-unplug-request", test_spapr_memory_unplug_request); + qtest_add_func("/device-plug/spapr-phb-unplug-request", + test_spapr_phb_unplug_request); } return g_test_run(); -- cgit v1.1