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" 147fe55c3cSAndreas Färber #include "qapi/qmp/types.h" 157fe55c3cSAndreas Färber 16152e0393SThomas Huth struct PlugTestData { 1734e46f60SMarc-André Lureau char *machine; 187fe55c3cSAndreas Färber const char *cpu_model; 19*80b8c0beSThomas 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 " 357fe55c3cSAndreas Färber "-smp 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 407fe55c3cSAndreas Färber for (i = s->sockets * s->cores * s->threads; 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")); 457fe55c3cSAndreas Färber QDECREF(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 " 597fe55c3cSAndreas Färber "-smp 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")); 697fe55c3cSAndreas Färber QDECREF(response); 707fe55c3cSAndreas Färber 717fe55c3cSAndreas Färber qtest_end(); 727fe55c3cSAndreas Färber g_free(args); 737fe55c3cSAndreas Färber } 747fe55c3cSAndreas Färber 75*80b8c0beSThomas Huth static void test_plug_with_device_add_x86(gconstpointer data) 76*80b8c0beSThomas Huth { 77*80b8c0beSThomas Huth const PlugTestData *td = data; 78*80b8c0beSThomas Huth char *args; 79*80b8c0beSThomas Huth unsigned int s, c, t; 80*80b8c0beSThomas Huth 81*80b8c0beSThomas Huth args = g_strdup_printf("-machine %s -cpu %s " 82*80b8c0beSThomas Huth "-smp sockets=%u,cores=%u,threads=%u,maxcpus=%u", 83*80b8c0beSThomas Huth td->machine, td->cpu_model, 84*80b8c0beSThomas Huth td->sockets, td->cores, td->threads, td->maxcpus); 85*80b8c0beSThomas Huth qtest_start(args); 86*80b8c0beSThomas Huth 87*80b8c0beSThomas Huth for (s = td->sockets; s < td->maxcpus / td->cores / td->threads; s++) { 88*80b8c0beSThomas Huth for (c = 0; c < td->cores; c++) { 89*80b8c0beSThomas Huth for (t = 0; t < td->threads; t++) { 90*80b8c0beSThomas Huth char *id = g_strdup_printf("id-%i-%i-%i", s, c, t); 91*80b8c0beSThomas Huth qtest_qmp_device_add(td->device_model, id, "'socket-id':'%i', " 92*80b8c0beSThomas Huth "'core-id':'%i', 'thread-id':'%i'", 93*80b8c0beSThomas Huth s, c, t); 94*80b8c0beSThomas Huth g_free(id); 95*80b8c0beSThomas Huth } 96*80b8c0beSThomas Huth } 97*80b8c0beSThomas Huth } 98*80b8c0beSThomas Huth 99*80b8c0beSThomas Huth qtest_end(); 100*80b8c0beSThomas Huth g_free(args); 101*80b8c0beSThomas Huth } 102*80b8c0beSThomas Huth 10334e46f60SMarc-André Lureau static void test_data_free(gpointer data) 10434e46f60SMarc-André Lureau { 105152e0393SThomas Huth PlugTestData *pc = data; 10634e46f60SMarc-André Lureau 10734e46f60SMarc-André Lureau g_free(pc->machine); 108*80b8c0beSThomas Huth g_free(pc->device_model); 10934e46f60SMarc-André Lureau g_free(pc); 11034e46f60SMarc-André Lureau } 11134e46f60SMarc-André Lureau 11202ef6e87SThomas Huth static void add_pc_test_case(const char *mname) 1137fe55c3cSAndreas Färber { 11434e46f60SMarc-André Lureau char *path; 115152e0393SThomas Huth PlugTestData *data; 1167fe55c3cSAndreas Färber 1177fe55c3cSAndreas Färber if (!g_str_has_prefix(mname, "pc-")) { 11802ef6e87SThomas Huth return; 1197fe55c3cSAndreas Färber } 120152e0393SThomas Huth data = g_new(PlugTestData, 1); 12134e46f60SMarc-André Lureau data->machine = g_strdup(mname); 1227fe55c3cSAndreas Färber data->cpu_model = "Haswell"; /* 1.3+ theoretically */ 123*80b8c0beSThomas Huth data->device_model = g_strdup_printf("%s-%s-cpu", data->cpu_model, 124*80b8c0beSThomas Huth qtest_get_arch()); 1257fe55c3cSAndreas Färber data->sockets = 1; 1267fe55c3cSAndreas Färber data->cores = 3; 1277fe55c3cSAndreas Färber data->threads = 2; 1287fe55c3cSAndreas Färber data->maxcpus = data->sockets * data->cores * data->threads * 2; 1297fe55c3cSAndreas Färber if (g_str_has_suffix(mname, "-1.4") || 1307fe55c3cSAndreas Färber (strcmp(mname, "pc-1.3") == 0) || 1317fe55c3cSAndreas Färber (strcmp(mname, "pc-1.2") == 0) || 1327fe55c3cSAndreas Färber (strcmp(mname, "pc-1.1") == 0) || 1337fe55c3cSAndreas Färber (strcmp(mname, "pc-1.0") == 0) || 1347fe55c3cSAndreas Färber (strcmp(mname, "pc-0.15") == 0) || 1357fe55c3cSAndreas Färber (strcmp(mname, "pc-0.14") == 0) || 1367fe55c3cSAndreas Färber (strcmp(mname, "pc-0.13") == 0) || 1377fe55c3cSAndreas Färber (strcmp(mname, "pc-0.12") == 0) || 1387fe55c3cSAndreas Färber (strcmp(mname, "pc-0.11") == 0) || 1397fe55c3cSAndreas Färber (strcmp(mname, "pc-0.10") == 0)) { 140*80b8c0beSThomas Huth path = g_strdup_printf("cpu-plug/%s/init/%ux%ux%u&maxcpus=%u", 14153f77e45SAndreas Färber mname, data->sockets, data->cores, 1427fe55c3cSAndreas Färber data->threads, data->maxcpus); 143152e0393SThomas Huth qtest_add_data_func_full(path, data, test_plug_without_cpu_add, 14434e46f60SMarc-André Lureau test_data_free); 14534e46f60SMarc-André Lureau g_free(path); 1467fe55c3cSAndreas Färber } else { 147*80b8c0beSThomas Huth PlugTestData *data2 = g_memdup(data, sizeof(PlugTestData)); 148*80b8c0beSThomas Huth 149*80b8c0beSThomas Huth data2->machine = g_strdup(data->machine); 150*80b8c0beSThomas Huth data2->device_model = g_strdup(data->device_model); 151*80b8c0beSThomas Huth 152*80b8c0beSThomas Huth path = g_strdup_printf("cpu-plug/%s/cpu-add/%ux%ux%u&maxcpus=%u", 15353f77e45SAndreas Färber mname, data->sockets, data->cores, 1547fe55c3cSAndreas Färber data->threads, data->maxcpus); 155152e0393SThomas Huth qtest_add_data_func_full(path, data, test_plug_with_cpu_add, 15634e46f60SMarc-André Lureau test_data_free); 15734e46f60SMarc-André Lureau g_free(path); 158*80b8c0beSThomas Huth path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", 159*80b8c0beSThomas Huth mname, data2->sockets, data2->cores, 160*80b8c0beSThomas Huth data2->threads, data2->maxcpus); 161*80b8c0beSThomas Huth qtest_add_data_func_full(path, data2, test_plug_with_device_add_x86, 162*80b8c0beSThomas Huth test_data_free); 163*80b8c0beSThomas Huth g_free(path); 1647fe55c3cSAndreas Färber } 1657fe55c3cSAndreas Färber } 1667fe55c3cSAndreas Färber 1677fe55c3cSAndreas Färber int main(int argc, char **argv) 1687fe55c3cSAndreas Färber { 1697fe55c3cSAndreas Färber const char *arch = qtest_get_arch(); 1707fe55c3cSAndreas Färber 1717fe55c3cSAndreas Färber g_test_init(&argc, &argv, NULL); 1727fe55c3cSAndreas Färber 1737fe55c3cSAndreas Färber if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { 17402ef6e87SThomas Huth qtest_cb_for_every_machine(add_pc_test_case); 1757fe55c3cSAndreas Färber } 1767fe55c3cSAndreas Färber 1777fe55c3cSAndreas Färber return g_test_run(); 1787fe55c3cSAndreas Färber } 179