17fe55c3cSAndreas Färber /* 2152e0393SThomas Huth * QTest testcase for CPU plugging 37fe55c3cSAndreas Färber * 47fe55c3cSAndreas Färber * Copyright (c) 2015 SUSE Linux GmbH 57fe55c3cSAndreas Färber * 67fe55c3cSAndreas Färber * This work is licensed under the terms of the GNU GPL, version 2 or later. 77fe55c3cSAndreas Färber * See the COPYING file in the top-level directory. 87fe55c3cSAndreas Färber */ 97fe55c3cSAndreas Färber 10681c28a3SPeter Maydell #include "qemu/osdep.h" 117fe55c3cSAndreas Färber 127fe55c3cSAndreas Färber #include "qemu-common.h" 137fe55c3cSAndreas Färber #include "libqtest.h" 14452fcdbcSMarkus Armbruster #include "qapi/qmp/qdict.h" 157fe55c3cSAndreas Färber 16152e0393SThomas Huth struct PlugTestData { 1734e46f60SMarc-André Lureau char *machine; 187fe55c3cSAndreas Färber const char *cpu_model; 1980b8c0beSThomas Huth char *device_model; 207fe55c3cSAndreas Färber unsigned sockets; 217fe55c3cSAndreas Färber unsigned cores; 227fe55c3cSAndreas Färber unsigned threads; 237fe55c3cSAndreas Färber unsigned maxcpus; 247fe55c3cSAndreas Färber }; 25152e0393SThomas Huth typedef struct PlugTestData PlugTestData; 267fe55c3cSAndreas Färber 27152e0393SThomas Huth static void test_plug_with_cpu_add(gconstpointer data) 287fe55c3cSAndreas Färber { 29152e0393SThomas Huth const PlugTestData *s = data; 307fe55c3cSAndreas Färber char *args; 317fe55c3cSAndreas Färber QDict *response; 327fe55c3cSAndreas Färber unsigned int i; 337fe55c3cSAndreas Färber 347fe55c3cSAndreas Färber args = g_strdup_printf("-machine %s -cpu %s " 35bc1fb850SIgor Mammedov "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u", 367fe55c3cSAndreas Färber s->machine, s->cpu_model, 377fe55c3cSAndreas Färber s->sockets, s->cores, s->threads, s->maxcpus); 387fe55c3cSAndreas Färber qtest_start(args); 397fe55c3cSAndreas Färber 40bc1fb850SIgor Mammedov for (i = 1; i < s->maxcpus; i++) { 417fe55c3cSAndreas Färber response = qmp("{ 'execute': 'cpu-add'," 427fe55c3cSAndreas Färber " 'arguments': { 'id': %d } }", i); 437fe55c3cSAndreas Färber g_assert(response); 447fe55c3cSAndreas Färber g_assert(!qdict_haskey(response, "error")); 45cb3e7f08SMarc-André Lureau qobject_unref(response); 467fe55c3cSAndreas Färber } 477fe55c3cSAndreas Färber 487fe55c3cSAndreas Färber qtest_end(); 497fe55c3cSAndreas Färber g_free(args); 507fe55c3cSAndreas Färber } 517fe55c3cSAndreas Färber 52152e0393SThomas Huth static void test_plug_without_cpu_add(gconstpointer data) 537fe55c3cSAndreas Färber { 54152e0393SThomas Huth const PlugTestData *s = data; 557fe55c3cSAndreas Färber char *args; 567fe55c3cSAndreas Färber QDict *response; 577fe55c3cSAndreas Färber 587fe55c3cSAndreas Färber args = g_strdup_printf("-machine %s -cpu %s " 59bc1fb850SIgor Mammedov "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u", 607fe55c3cSAndreas Färber s->machine, s->cpu_model, 617fe55c3cSAndreas Färber s->sockets, s->cores, s->threads, s->maxcpus); 627fe55c3cSAndreas Färber qtest_start(args); 637fe55c3cSAndreas Färber 647fe55c3cSAndreas Färber response = qmp("{ 'execute': 'cpu-add'," 657fe55c3cSAndreas Färber " 'arguments': { 'id': %d } }", 667fe55c3cSAndreas Färber s->sockets * s->cores * s->threads); 677fe55c3cSAndreas Färber g_assert(response); 687fe55c3cSAndreas Färber g_assert(qdict_haskey(response, "error")); 69cb3e7f08SMarc-André Lureau qobject_unref(response); 707fe55c3cSAndreas Färber 717fe55c3cSAndreas Färber qtest_end(); 727fe55c3cSAndreas Färber g_free(args); 737fe55c3cSAndreas Färber } 747fe55c3cSAndreas Färber 7580b8c0beSThomas Huth static void test_plug_with_device_add_x86(gconstpointer data) 7680b8c0beSThomas Huth { 7780b8c0beSThomas Huth const PlugTestData *td = data; 7880b8c0beSThomas Huth char *args; 7980b8c0beSThomas Huth unsigned int s, c, t; 8080b8c0beSThomas Huth 8180b8c0beSThomas Huth args = g_strdup_printf("-machine %s -cpu %s " 82bc1fb850SIgor Mammedov "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u", 8380b8c0beSThomas Huth td->machine, td->cpu_model, 8480b8c0beSThomas Huth td->sockets, td->cores, td->threads, td->maxcpus); 8580b8c0beSThomas Huth qtest_start(args); 8680b8c0beSThomas Huth 87bc1fb850SIgor Mammedov for (s = 1; s < td->sockets; s++) { 8880b8c0beSThomas Huth for (c = 0; c < td->cores; c++) { 8980b8c0beSThomas Huth for (t = 0; t < td->threads; t++) { 9080b8c0beSThomas Huth char *id = g_strdup_printf("id-%i-%i-%i", s, c, t); 9182cab70bSMarkus Armbruster qtest_qmp_device_add(td->device_model, id, 9282cab70bSMarkus Armbruster "{'socket-id':%u, 'core-id':%u," 9382cab70bSMarkus Armbruster " 'thread-id':%u}", 9480b8c0beSThomas Huth s, c, t); 9580b8c0beSThomas Huth g_free(id); 9680b8c0beSThomas Huth } 9780b8c0beSThomas Huth } 9880b8c0beSThomas Huth } 9980b8c0beSThomas Huth 10080b8c0beSThomas Huth qtest_end(); 10180b8c0beSThomas Huth g_free(args); 10280b8c0beSThomas Huth } 10380b8c0beSThomas Huth 10473a7d31eSThomas Huth static void test_plug_with_device_add_coreid(gconstpointer data) 10573a7d31eSThomas Huth { 10673a7d31eSThomas Huth const PlugTestData *td = data; 10773a7d31eSThomas Huth char *args; 10873a7d31eSThomas Huth unsigned int c; 10973a7d31eSThomas Huth 11073a7d31eSThomas Huth args = g_strdup_printf("-machine %s -cpu %s " 11173a7d31eSThomas Huth "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u", 11273a7d31eSThomas Huth td->machine, td->cpu_model, 11373a7d31eSThomas Huth td->sockets, td->cores, td->threads, td->maxcpus); 11473a7d31eSThomas Huth qtest_start(args); 11573a7d31eSThomas Huth 116bc1fb850SIgor Mammedov for (c = 1; c < td->cores; c++) { 11773a7d31eSThomas Huth char *id = g_strdup_printf("id-%i", c); 11882cab70bSMarkus Armbruster qtest_qmp_device_add(td->device_model, id, "{'core-id':%u}", c); 11973a7d31eSThomas Huth g_free(id); 12073a7d31eSThomas Huth } 12173a7d31eSThomas Huth 12273a7d31eSThomas Huth qtest_end(); 12373a7d31eSThomas Huth g_free(args); 12473a7d31eSThomas Huth } 12573a7d31eSThomas Huth 12634e46f60SMarc-André Lureau static void test_data_free(gpointer data) 12734e46f60SMarc-André Lureau { 128152e0393SThomas Huth PlugTestData *pc = data; 12934e46f60SMarc-André Lureau 13034e46f60SMarc-André Lureau g_free(pc->machine); 13180b8c0beSThomas Huth g_free(pc->device_model); 13234e46f60SMarc-André Lureau g_free(pc); 13334e46f60SMarc-André Lureau } 13434e46f60SMarc-André Lureau 13502ef6e87SThomas Huth static void add_pc_test_case(const char *mname) 1367fe55c3cSAndreas Färber { 13734e46f60SMarc-André Lureau char *path; 138152e0393SThomas Huth PlugTestData *data; 1397fe55c3cSAndreas Färber 1407fe55c3cSAndreas Färber if (!g_str_has_prefix(mname, "pc-")) { 14102ef6e87SThomas Huth return; 1427fe55c3cSAndreas Färber } 143152e0393SThomas Huth data = g_new(PlugTestData, 1); 14434e46f60SMarc-André Lureau data->machine = g_strdup(mname); 1457fe55c3cSAndreas Färber data->cpu_model = "Haswell"; /* 1.3+ theoretically */ 14680b8c0beSThomas Huth data->device_model = g_strdup_printf("%s-%s-cpu", data->cpu_model, 14780b8c0beSThomas Huth qtest_get_arch()); 1487fe55c3cSAndreas Färber data->sockets = 1; 1497fe55c3cSAndreas Färber data->cores = 3; 1507fe55c3cSAndreas Färber data->threads = 2; 151bc1fb850SIgor Mammedov data->maxcpus = data->sockets * data->cores * data->threads; 1527fe55c3cSAndreas Färber if (g_str_has_suffix(mname, "-1.4") || 1537fe55c3cSAndreas Färber (strcmp(mname, "pc-1.3") == 0) || 1547fe55c3cSAndreas Färber (strcmp(mname, "pc-1.2") == 0) || 1557fe55c3cSAndreas Färber (strcmp(mname, "pc-1.1") == 0) || 1567fe55c3cSAndreas Färber (strcmp(mname, "pc-1.0") == 0) || 1577fe55c3cSAndreas Färber (strcmp(mname, "pc-0.15") == 0) || 1587fe55c3cSAndreas Färber (strcmp(mname, "pc-0.14") == 0) || 1597fe55c3cSAndreas Färber (strcmp(mname, "pc-0.13") == 0) || 160*cc425b5dSThomas Huth (strcmp(mname, "pc-0.12") == 0)) { 16180b8c0beSThomas Huth path = g_strdup_printf("cpu-plug/%s/init/%ux%ux%u&maxcpus=%u", 16253f77e45SAndreas Färber mname, data->sockets, data->cores, 1637fe55c3cSAndreas Färber data->threads, data->maxcpus); 164152e0393SThomas Huth qtest_add_data_func_full(path, data, test_plug_without_cpu_add, 16534e46f60SMarc-André Lureau test_data_free); 16634e46f60SMarc-André Lureau g_free(path); 1677fe55c3cSAndreas Färber } else { 16880b8c0beSThomas Huth PlugTestData *data2 = g_memdup(data, sizeof(PlugTestData)); 16980b8c0beSThomas Huth 17080b8c0beSThomas Huth data2->machine = g_strdup(data->machine); 17180b8c0beSThomas Huth data2->device_model = g_strdup(data->device_model); 17280b8c0beSThomas Huth 17380b8c0beSThomas Huth path = g_strdup_printf("cpu-plug/%s/cpu-add/%ux%ux%u&maxcpus=%u", 17453f77e45SAndreas Färber mname, data->sockets, data->cores, 1757fe55c3cSAndreas Färber data->threads, data->maxcpus); 176152e0393SThomas Huth qtest_add_data_func_full(path, data, test_plug_with_cpu_add, 17734e46f60SMarc-André Lureau test_data_free); 17834e46f60SMarc-André Lureau g_free(path); 17980b8c0beSThomas Huth path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", 18080b8c0beSThomas Huth mname, data2->sockets, data2->cores, 18180b8c0beSThomas Huth data2->threads, data2->maxcpus); 18280b8c0beSThomas Huth qtest_add_data_func_full(path, data2, test_plug_with_device_add_x86, 18380b8c0beSThomas Huth test_data_free); 18480b8c0beSThomas Huth g_free(path); 1857fe55c3cSAndreas Färber } 1867fe55c3cSAndreas Färber } 1877fe55c3cSAndreas Färber 18873a7d31eSThomas Huth static void add_pseries_test_case(const char *mname) 18973a7d31eSThomas Huth { 19073a7d31eSThomas Huth char *path; 19173a7d31eSThomas Huth PlugTestData *data; 19273a7d31eSThomas Huth 19373a7d31eSThomas Huth if (!g_str_has_prefix(mname, "pseries-") || 19473a7d31eSThomas Huth (g_str_has_prefix(mname, "pseries-2.") && atoi(&mname[10]) < 7)) { 19573a7d31eSThomas Huth return; 19673a7d31eSThomas Huth } 19773a7d31eSThomas Huth data = g_new(PlugTestData, 1); 19873a7d31eSThomas Huth data->machine = g_strdup(mname); 19973a7d31eSThomas Huth data->cpu_model = "power8_v2.0"; 20073a7d31eSThomas Huth data->device_model = g_strdup("power8_v2.0-spapr-cpu-core"); 20173a7d31eSThomas Huth data->sockets = 2; 20273a7d31eSThomas Huth data->cores = 3; 20373a7d31eSThomas Huth data->threads = 1; 204bc1fb850SIgor Mammedov data->maxcpus = data->sockets * data->cores * data->threads; 20573a7d31eSThomas Huth 20673a7d31eSThomas Huth path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", 20773a7d31eSThomas Huth mname, data->sockets, data->cores, 20873a7d31eSThomas Huth data->threads, data->maxcpus); 20973a7d31eSThomas Huth qtest_add_data_func_full(path, data, test_plug_with_device_add_coreid, 21073a7d31eSThomas Huth test_data_free); 21173a7d31eSThomas Huth g_free(path); 21273a7d31eSThomas Huth } 21373a7d31eSThomas Huth 2147d8b00faSThomas Huth static void add_s390x_test_case(const char *mname) 2157d8b00faSThomas Huth { 2167d8b00faSThomas Huth char *path; 2177d8b00faSThomas Huth PlugTestData *data, *data2; 2187d8b00faSThomas Huth 2197d8b00faSThomas Huth if (!g_str_has_prefix(mname, "s390-ccw-virtio-")) { 2207d8b00faSThomas Huth return; 2217d8b00faSThomas Huth } 2227d8b00faSThomas Huth 2237d8b00faSThomas Huth data = g_new(PlugTestData, 1); 2247d8b00faSThomas Huth data->machine = g_strdup(mname); 2257d8b00faSThomas Huth data->cpu_model = "qemu"; 2267d8b00faSThomas Huth data->device_model = g_strdup("qemu-s390x-cpu"); 2277d8b00faSThomas Huth data->sockets = 1; 2287d8b00faSThomas Huth data->cores = 3; 2297d8b00faSThomas Huth data->threads = 1; 230bc1fb850SIgor Mammedov data->maxcpus = data->sockets * data->cores * data->threads; 2317d8b00faSThomas Huth 2327d8b00faSThomas Huth data2 = g_memdup(data, sizeof(PlugTestData)); 2337d8b00faSThomas Huth data2->machine = g_strdup(data->machine); 2347d8b00faSThomas Huth data2->device_model = g_strdup(data->device_model); 2357d8b00faSThomas Huth 2367d8b00faSThomas Huth path = g_strdup_printf("cpu-plug/%s/cpu-add/%ux%ux%u&maxcpus=%u", 2377d8b00faSThomas Huth mname, data->sockets, data->cores, 2387d8b00faSThomas Huth data->threads, data->maxcpus); 2397d8b00faSThomas Huth qtest_add_data_func_full(path, data, test_plug_with_cpu_add, 2407d8b00faSThomas Huth test_data_free); 2417d8b00faSThomas Huth g_free(path); 2427d8b00faSThomas Huth 2437d8b00faSThomas Huth path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", 2447d8b00faSThomas Huth mname, data2->sockets, data2->cores, 2457d8b00faSThomas Huth data2->threads, data2->maxcpus); 2467d8b00faSThomas Huth qtest_add_data_func_full(path, data2, test_plug_with_device_add_coreid, 2477d8b00faSThomas Huth test_data_free); 2487d8b00faSThomas Huth g_free(path); 2497d8b00faSThomas Huth } 2507d8b00faSThomas Huth 2517fe55c3cSAndreas Färber int main(int argc, char **argv) 2527fe55c3cSAndreas Färber { 2537fe55c3cSAndreas Färber const char *arch = qtest_get_arch(); 2547fe55c3cSAndreas Färber 2557fe55c3cSAndreas Färber g_test_init(&argc, &argv, NULL); 2567fe55c3cSAndreas Färber 2577fe55c3cSAndreas Färber if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { 2581f4a0d81SThomas Huth qtest_cb_for_every_machine(add_pc_test_case, g_test_quick()); 25973a7d31eSThomas Huth } else if (g_str_equal(arch, "ppc64")) { 2601f4a0d81SThomas Huth qtest_cb_for_every_machine(add_pseries_test_case, g_test_quick()); 2617d8b00faSThomas Huth } else if (g_str_equal(arch, "s390x")) { 2621f4a0d81SThomas Huth qtest_cb_for_every_machine(add_s390x_test_case, g_test_quick()); 2637fe55c3cSAndreas Färber } 2647fe55c3cSAndreas Färber 2657fe55c3cSAndreas Färber return g_test_run(); 2667fe55c3cSAndreas Färber } 267