11e8a1faeSThomas Huth /*
21e8a1faeSThomas Huth * QTest testcase for CPU plugging
31e8a1faeSThomas Huth *
41e8a1faeSThomas Huth * Copyright (c) 2015 SUSE Linux GmbH
51e8a1faeSThomas Huth *
61e8a1faeSThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 or later.
71e8a1faeSThomas Huth * See the COPYING file in the top-level directory.
81e8a1faeSThomas Huth */
91e8a1faeSThomas Huth
101e8a1faeSThomas Huth #include "qemu/osdep.h"
111e8a1faeSThomas Huth
121e8a1faeSThomas Huth #include "libqtest-single.h"
131e8a1faeSThomas Huth #include "qapi/qmp/qdict.h"
141e8a1faeSThomas Huth #include "qapi/qmp/qlist.h"
151e8a1faeSThomas Huth
161e8a1faeSThomas Huth struct PlugTestData {
171e8a1faeSThomas Huth char *machine;
181e8a1faeSThomas Huth const char *cpu_model;
191e8a1faeSThomas Huth char *device_model;
201e8a1faeSThomas Huth unsigned sockets;
211e8a1faeSThomas Huth unsigned cores;
221e8a1faeSThomas Huth unsigned threads;
231e8a1faeSThomas Huth unsigned maxcpus;
241e8a1faeSThomas Huth };
251e8a1faeSThomas Huth typedef struct PlugTestData PlugTestData;
261e8a1faeSThomas Huth
test_plug_with_device_add(gconstpointer data)271e8a1faeSThomas Huth static void test_plug_with_device_add(gconstpointer data)
281e8a1faeSThomas Huth {
291e8a1faeSThomas Huth const PlugTestData *td = data;
301e8a1faeSThomas Huth char *args;
311e8a1faeSThomas Huth QTestState *qts;
321e8a1faeSThomas Huth QDict *resp;
331e8a1faeSThomas Huth QList *cpus;
341e8a1faeSThomas Huth QObject *e;
351e8a1faeSThomas Huth int hotplugged = 0;
361e8a1faeSThomas Huth
371e8a1faeSThomas Huth args = g_strdup_printf("-machine %s -cpu %s "
381e8a1faeSThomas Huth "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u",
391e8a1faeSThomas Huth td->machine, td->cpu_model,
401e8a1faeSThomas Huth td->sockets, td->cores, td->threads, td->maxcpus);
411e8a1faeSThomas Huth qts = qtest_init(args);
421e8a1faeSThomas Huth
431e8a1faeSThomas Huth resp = qtest_qmp(qts, "{ 'execute': 'query-hotpluggable-cpus'}");
441e8a1faeSThomas Huth g_assert(qdict_haskey(resp, "return"));
451e8a1faeSThomas Huth cpus = qdict_get_qlist(resp, "return");
461e8a1faeSThomas Huth g_assert(cpus);
471e8a1faeSThomas Huth
481e8a1faeSThomas Huth while ((e = qlist_pop(cpus))) {
491e8a1faeSThomas Huth const QDict *cpu, *props;
501e8a1faeSThomas Huth
511e8a1faeSThomas Huth cpu = qobject_to(QDict, e);
521e8a1faeSThomas Huth if (qdict_haskey(cpu, "qom-path")) {
531e8a1faeSThomas Huth qobject_unref(e);
541e8a1faeSThomas Huth continue;
551e8a1faeSThomas Huth }
561e8a1faeSThomas Huth
571e8a1faeSThomas Huth g_assert(qdict_haskey(cpu, "props"));
581e8a1faeSThomas Huth props = qdict_get_qdict(cpu, "props");
591e8a1faeSThomas Huth
601e8a1faeSThomas Huth qtest_qmp_device_add_qdict(qts, td->device_model, props);
611e8a1faeSThomas Huth hotplugged++;
621e8a1faeSThomas Huth qobject_unref(e);
631e8a1faeSThomas Huth }
641e8a1faeSThomas Huth
651e8a1faeSThomas Huth /* make sure that there were hotplugged CPUs */
661e8a1faeSThomas Huth g_assert(hotplugged);
671e8a1faeSThomas Huth qobject_unref(resp);
681e8a1faeSThomas Huth qtest_quit(qts);
691e8a1faeSThomas Huth g_free(args);
701e8a1faeSThomas Huth }
711e8a1faeSThomas Huth
test_data_free(gpointer data)721e8a1faeSThomas Huth static void test_data_free(gpointer data)
731e8a1faeSThomas Huth {
741e8a1faeSThomas Huth PlugTestData *pc = data;
751e8a1faeSThomas Huth
761e8a1faeSThomas Huth g_free(pc->machine);
771e8a1faeSThomas Huth g_free(pc->device_model);
781e8a1faeSThomas Huth g_free(pc);
791e8a1faeSThomas Huth }
801e8a1faeSThomas Huth
add_pc_test_case(const char * mname)811e8a1faeSThomas Huth static void add_pc_test_case(const char *mname)
821e8a1faeSThomas Huth {
831e8a1faeSThomas Huth char *path;
841e8a1faeSThomas Huth PlugTestData *data;
851e8a1faeSThomas Huth
861e8a1faeSThomas Huth if (!g_str_has_prefix(mname, "pc-")) {
871e8a1faeSThomas Huth return;
881e8a1faeSThomas Huth }
891e8a1faeSThomas Huth data = g_new(PlugTestData, 1);
901e8a1faeSThomas Huth data->machine = g_strdup(mname);
911e8a1faeSThomas Huth data->cpu_model = "Haswell"; /* 1.3+ theoretically */
921e8a1faeSThomas Huth data->device_model = g_strdup_printf("%s-%s-cpu", data->cpu_model,
931e8a1faeSThomas Huth qtest_get_arch());
941e8a1faeSThomas Huth data->sockets = 1;
951e8a1faeSThomas Huth data->cores = 3;
961e8a1faeSThomas Huth data->threads = 2;
971e8a1faeSThomas Huth data->maxcpus = data->sockets * data->cores * data->threads;
981e8a1faeSThomas Huth
991e8a1faeSThomas Huth path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u",
100*63e79833SIgor Mammedov mname, data->sockets, data->cores,
101*63e79833SIgor Mammedov data->threads, data->maxcpus);
102*63e79833SIgor Mammedov qtest_add_data_func_full(path, data, test_plug_with_device_add,
1031e8a1faeSThomas Huth test_data_free);
1041e8a1faeSThomas Huth g_free(path);
1051e8a1faeSThomas Huth }
1061e8a1faeSThomas Huth
add_pseries_test_case(const char * mname)1071e8a1faeSThomas Huth static void add_pseries_test_case(const char *mname)
1081e8a1faeSThomas Huth {
1091e8a1faeSThomas Huth char *path;
1101e8a1faeSThomas Huth PlugTestData *data;
1111e8a1faeSThomas Huth
1121e8a1faeSThomas Huth if (!g_str_has_prefix(mname, "pseries-") ||
1131e8a1faeSThomas Huth (g_str_has_prefix(mname, "pseries-2.") && atoi(&mname[10]) < 7)) {
1141e8a1faeSThomas Huth return;
1151e8a1faeSThomas Huth }
1161e8a1faeSThomas Huth data = g_new(PlugTestData, 1);
1171e8a1faeSThomas Huth data->machine = g_strdup(mname);
1181e8a1faeSThomas Huth data->cpu_model = "power8_v2.0";
1191e8a1faeSThomas Huth data->device_model = g_strdup("power8_v2.0-spapr-cpu-core");
1201e8a1faeSThomas Huth data->sockets = 2;
1211e8a1faeSThomas Huth data->cores = 3;
1221e8a1faeSThomas Huth data->threads = 1;
1231e8a1faeSThomas Huth data->maxcpus = data->sockets * data->cores * data->threads;
1241e8a1faeSThomas Huth
1251e8a1faeSThomas Huth path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u",
1261e8a1faeSThomas Huth mname, data->sockets, data->cores,
1271e8a1faeSThomas Huth data->threads, data->maxcpus);
1281e8a1faeSThomas Huth qtest_add_data_func_full(path, data, test_plug_with_device_add,
1291e8a1faeSThomas Huth test_data_free);
1301e8a1faeSThomas Huth g_free(path);
1311e8a1faeSThomas Huth }
1321e8a1faeSThomas Huth
add_s390x_test_case(const char * mname)1331e8a1faeSThomas Huth static void add_s390x_test_case(const char *mname)
1341e8a1faeSThomas Huth {
1351e8a1faeSThomas Huth char *path;
136*63e79833SIgor Mammedov PlugTestData *data;
1371e8a1faeSThomas Huth
1381e8a1faeSThomas Huth if (!g_str_has_prefix(mname, "s390-ccw-virtio-")) {
1391e8a1faeSThomas Huth return;
1401e8a1faeSThomas Huth }
1411e8a1faeSThomas Huth
1421e8a1faeSThomas Huth data = g_new(PlugTestData, 1);
1431e8a1faeSThomas Huth data->machine = g_strdup(mname);
1441e8a1faeSThomas Huth data->cpu_model = "qemu";
1451e8a1faeSThomas Huth data->device_model = g_strdup("qemu-s390x-cpu");
1461e8a1faeSThomas Huth data->sockets = 1;
1471e8a1faeSThomas Huth data->cores = 3;
1481e8a1faeSThomas Huth data->threads = 1;
1491e8a1faeSThomas Huth data->maxcpus = data->sockets * data->cores * data->threads;
1501e8a1faeSThomas Huth
151*63e79833SIgor Mammedov path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u",
1521e8a1faeSThomas Huth mname, data->sockets, data->cores,
1531e8a1faeSThomas Huth data->threads, data->maxcpus);
154*63e79833SIgor Mammedov qtest_add_data_func_full(path, data, test_plug_with_device_add,
1551e8a1faeSThomas Huth test_data_free);
1561e8a1faeSThomas Huth g_free(path);
1571e8a1faeSThomas Huth }
1581e8a1faeSThomas Huth
main(int argc,char ** argv)1591e8a1faeSThomas Huth int main(int argc, char **argv)
1601e8a1faeSThomas Huth {
1611e8a1faeSThomas Huth const char *arch = qtest_get_arch();
1621e8a1faeSThomas Huth
1631e8a1faeSThomas Huth g_test_init(&argc, &argv, NULL);
1641e8a1faeSThomas Huth
1651e8a1faeSThomas Huth if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
1661e8a1faeSThomas Huth qtest_cb_for_every_machine(add_pc_test_case, g_test_quick());
1671e8a1faeSThomas Huth } else if (g_str_equal(arch, "ppc64")) {
1681e8a1faeSThomas Huth qtest_cb_for_every_machine(add_pseries_test_case, g_test_quick());
1691e8a1faeSThomas Huth } else if (g_str_equal(arch, "s390x")) {
1701e8a1faeSThomas Huth qtest_cb_for_every_machine(add_s390x_test_case, g_test_quick());
1711e8a1faeSThomas Huth }
1721e8a1faeSThomas Huth
1731e8a1faeSThomas Huth return g_test_run();
1741e8a1faeSThomas Huth }
175