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; 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 " 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 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 " 8280b8c0beSThomas Huth "-smp 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 8780b8c0beSThomas Huth for (s = td->sockets; s < td->maxcpus / td->cores / td->threads; 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); 9180b8c0beSThomas Huth qtest_qmp_device_add(td->device_model, id, "'socket-id':'%i', " 9280b8c0beSThomas Huth "'core-id':'%i', 'thread-id':'%i'", 9380b8c0beSThomas Huth s, c, t); 9480b8c0beSThomas Huth g_free(id); 9580b8c0beSThomas Huth } 9680b8c0beSThomas Huth } 9780b8c0beSThomas Huth } 9880b8c0beSThomas Huth 9980b8c0beSThomas Huth qtest_end(); 10080b8c0beSThomas Huth g_free(args); 10180b8c0beSThomas Huth } 10280b8c0beSThomas Huth 103*73a7d31eSThomas Huth static void test_plug_with_device_add_coreid(gconstpointer data) 104*73a7d31eSThomas Huth { 105*73a7d31eSThomas Huth const PlugTestData *td = data; 106*73a7d31eSThomas Huth char *args; 107*73a7d31eSThomas Huth unsigned int c; 108*73a7d31eSThomas Huth 109*73a7d31eSThomas Huth args = g_strdup_printf("-machine %s -cpu %s " 110*73a7d31eSThomas Huth "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u", 111*73a7d31eSThomas Huth td->machine, td->cpu_model, 112*73a7d31eSThomas Huth td->sockets, td->cores, td->threads, td->maxcpus); 113*73a7d31eSThomas Huth qtest_start(args); 114*73a7d31eSThomas Huth 115*73a7d31eSThomas Huth for (c = td->cores; c < td->maxcpus / td->sockets / td->threads; c++) { 116*73a7d31eSThomas Huth char *id = g_strdup_printf("id-%i", c); 117*73a7d31eSThomas Huth qtest_qmp_device_add(td->device_model, id, "'core-id':'%i'", c); 118*73a7d31eSThomas Huth g_free(id); 119*73a7d31eSThomas Huth } 120*73a7d31eSThomas Huth 121*73a7d31eSThomas Huth qtest_end(); 122*73a7d31eSThomas Huth g_free(args); 123*73a7d31eSThomas Huth } 124*73a7d31eSThomas Huth 12534e46f60SMarc-André Lureau static void test_data_free(gpointer data) 12634e46f60SMarc-André Lureau { 127152e0393SThomas Huth PlugTestData *pc = data; 12834e46f60SMarc-André Lureau 12934e46f60SMarc-André Lureau g_free(pc->machine); 13080b8c0beSThomas Huth g_free(pc->device_model); 13134e46f60SMarc-André Lureau g_free(pc); 13234e46f60SMarc-André Lureau } 13334e46f60SMarc-André Lureau 13402ef6e87SThomas Huth static void add_pc_test_case(const char *mname) 1357fe55c3cSAndreas Färber { 13634e46f60SMarc-André Lureau char *path; 137152e0393SThomas Huth PlugTestData *data; 1387fe55c3cSAndreas Färber 1397fe55c3cSAndreas Färber if (!g_str_has_prefix(mname, "pc-")) { 14002ef6e87SThomas Huth return; 1417fe55c3cSAndreas Färber } 142152e0393SThomas Huth data = g_new(PlugTestData, 1); 14334e46f60SMarc-André Lureau data->machine = g_strdup(mname); 1447fe55c3cSAndreas Färber data->cpu_model = "Haswell"; /* 1.3+ theoretically */ 14580b8c0beSThomas Huth data->device_model = g_strdup_printf("%s-%s-cpu", data->cpu_model, 14680b8c0beSThomas Huth qtest_get_arch()); 1477fe55c3cSAndreas Färber data->sockets = 1; 1487fe55c3cSAndreas Färber data->cores = 3; 1497fe55c3cSAndreas Färber data->threads = 2; 1507fe55c3cSAndreas Färber data->maxcpus = data->sockets * data->cores * data->threads * 2; 1517fe55c3cSAndreas Färber if (g_str_has_suffix(mname, "-1.4") || 1527fe55c3cSAndreas Färber (strcmp(mname, "pc-1.3") == 0) || 1537fe55c3cSAndreas Färber (strcmp(mname, "pc-1.2") == 0) || 1547fe55c3cSAndreas Färber (strcmp(mname, "pc-1.1") == 0) || 1557fe55c3cSAndreas Färber (strcmp(mname, "pc-1.0") == 0) || 1567fe55c3cSAndreas Färber (strcmp(mname, "pc-0.15") == 0) || 1577fe55c3cSAndreas Färber (strcmp(mname, "pc-0.14") == 0) || 1587fe55c3cSAndreas Färber (strcmp(mname, "pc-0.13") == 0) || 1597fe55c3cSAndreas Färber (strcmp(mname, "pc-0.12") == 0) || 1607fe55c3cSAndreas Färber (strcmp(mname, "pc-0.11") == 0) || 1617fe55c3cSAndreas Färber (strcmp(mname, "pc-0.10") == 0)) { 16280b8c0beSThomas Huth path = g_strdup_printf("cpu-plug/%s/init/%ux%ux%u&maxcpus=%u", 16353f77e45SAndreas Färber mname, data->sockets, data->cores, 1647fe55c3cSAndreas Färber data->threads, data->maxcpus); 165152e0393SThomas Huth qtest_add_data_func_full(path, data, test_plug_without_cpu_add, 16634e46f60SMarc-André Lureau test_data_free); 16734e46f60SMarc-André Lureau g_free(path); 1687fe55c3cSAndreas Färber } else { 16980b8c0beSThomas Huth PlugTestData *data2 = g_memdup(data, sizeof(PlugTestData)); 17080b8c0beSThomas Huth 17180b8c0beSThomas Huth data2->machine = g_strdup(data->machine); 17280b8c0beSThomas Huth data2->device_model = g_strdup(data->device_model); 17380b8c0beSThomas Huth 17480b8c0beSThomas Huth path = g_strdup_printf("cpu-plug/%s/cpu-add/%ux%ux%u&maxcpus=%u", 17553f77e45SAndreas Färber mname, data->sockets, data->cores, 1767fe55c3cSAndreas Färber data->threads, data->maxcpus); 177152e0393SThomas Huth qtest_add_data_func_full(path, data, test_plug_with_cpu_add, 17834e46f60SMarc-André Lureau test_data_free); 17934e46f60SMarc-André Lureau g_free(path); 18080b8c0beSThomas Huth path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", 18180b8c0beSThomas Huth mname, data2->sockets, data2->cores, 18280b8c0beSThomas Huth data2->threads, data2->maxcpus); 18380b8c0beSThomas Huth qtest_add_data_func_full(path, data2, test_plug_with_device_add_x86, 18480b8c0beSThomas Huth test_data_free); 18580b8c0beSThomas Huth g_free(path); 1867fe55c3cSAndreas Färber } 1877fe55c3cSAndreas Färber } 1887fe55c3cSAndreas Färber 189*73a7d31eSThomas Huth static void add_pseries_test_case(const char *mname) 190*73a7d31eSThomas Huth { 191*73a7d31eSThomas Huth char *path; 192*73a7d31eSThomas Huth PlugTestData *data; 193*73a7d31eSThomas Huth 194*73a7d31eSThomas Huth if (!g_str_has_prefix(mname, "pseries-") || 195*73a7d31eSThomas Huth (g_str_has_prefix(mname, "pseries-2.") && atoi(&mname[10]) < 7)) { 196*73a7d31eSThomas Huth return; 197*73a7d31eSThomas Huth } 198*73a7d31eSThomas Huth data = g_new(PlugTestData, 1); 199*73a7d31eSThomas Huth data->machine = g_strdup(mname); 200*73a7d31eSThomas Huth data->cpu_model = "power8_v2.0"; 201*73a7d31eSThomas Huth data->device_model = g_strdup("power8_v2.0-spapr-cpu-core"); 202*73a7d31eSThomas Huth data->sockets = 2; 203*73a7d31eSThomas Huth data->cores = 3; 204*73a7d31eSThomas Huth data->threads = 1; 205*73a7d31eSThomas Huth data->maxcpus = data->sockets * data->cores * data->threads * 2; 206*73a7d31eSThomas Huth 207*73a7d31eSThomas Huth path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", 208*73a7d31eSThomas Huth mname, data->sockets, data->cores, 209*73a7d31eSThomas Huth data->threads, data->maxcpus); 210*73a7d31eSThomas Huth qtest_add_data_func_full(path, data, test_plug_with_device_add_coreid, 211*73a7d31eSThomas Huth test_data_free); 212*73a7d31eSThomas Huth g_free(path); 213*73a7d31eSThomas Huth } 214*73a7d31eSThomas Huth 2157fe55c3cSAndreas Färber int main(int argc, char **argv) 2167fe55c3cSAndreas Färber { 2177fe55c3cSAndreas Färber const char *arch = qtest_get_arch(); 2187fe55c3cSAndreas Färber 2197fe55c3cSAndreas Färber g_test_init(&argc, &argv, NULL); 2207fe55c3cSAndreas Färber 2217fe55c3cSAndreas Färber if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { 22202ef6e87SThomas Huth qtest_cb_for_every_machine(add_pc_test_case); 223*73a7d31eSThomas Huth } else if (g_str_equal(arch, "ppc64")) { 224*73a7d31eSThomas Huth qtest_cb_for_every_machine(add_pseries_test_case); 2257fe55c3cSAndreas Färber } 2267fe55c3cSAndreas Färber 2277fe55c3cSAndreas Färber return g_test_run(); 2287fe55c3cSAndreas Färber } 229