1 /* 2 * QTest testcase for CPU plugging 3 * 4 * Copyright (c) 2015 SUSE Linux GmbH 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or later. 7 * See the COPYING file in the top-level directory. 8 */ 9 10 #include "qemu/osdep.h" 11 12 #include "qemu-common.h" 13 #include "libqtest-single.h" 14 #include "qapi/qmp/qdict.h" 15 #include "qapi/qmp/qlist.h" 16 17 struct PlugTestData { 18 char *machine; 19 const char *cpu_model; 20 char *device_model; 21 unsigned sockets; 22 unsigned cores; 23 unsigned threads; 24 unsigned maxcpus; 25 }; 26 typedef struct PlugTestData PlugTestData; 27 28 static void test_plug_with_device_add(gconstpointer data) 29 { 30 const PlugTestData *td = data; 31 char *args; 32 QTestState *qts; 33 QDict *resp; 34 QList *cpus; 35 QObject *e; 36 int hotplugged = 0; 37 38 args = g_strdup_printf("-machine %s -cpu %s " 39 "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u", 40 td->machine, td->cpu_model, 41 td->sockets, td->cores, td->threads, td->maxcpus); 42 qts = qtest_init(args); 43 44 resp = qtest_qmp(qts, "{ 'execute': 'query-hotpluggable-cpus'}"); 45 g_assert(qdict_haskey(resp, "return")); 46 cpus = qdict_get_qlist(resp, "return"); 47 g_assert(cpus); 48 49 while ((e = qlist_pop(cpus))) { 50 const QDict *cpu, *props; 51 52 cpu = qobject_to(QDict, e); 53 if (qdict_haskey(cpu, "qom-path")) { 54 qobject_unref(e); 55 continue; 56 } 57 58 g_assert(qdict_haskey(cpu, "props")); 59 props = qdict_get_qdict(cpu, "props"); 60 61 qtest_qmp_device_add_qdict(qts, td->device_model, props); 62 hotplugged++; 63 qobject_unref(e); 64 } 65 66 /* make sure that there were hotplugged CPUs */ 67 g_assert(hotplugged); 68 qobject_unref(resp); 69 qtest_quit(qts); 70 g_free(args); 71 } 72 73 static void test_data_free(gpointer data) 74 { 75 PlugTestData *pc = data; 76 77 g_free(pc->machine); 78 g_free(pc->device_model); 79 g_free(pc); 80 } 81 82 static void add_pc_test_case(const char *mname) 83 { 84 char *path; 85 PlugTestData *data; 86 87 if (!g_str_has_prefix(mname, "pc-")) { 88 return; 89 } 90 data = g_new(PlugTestData, 1); 91 data->machine = g_strdup(mname); 92 data->cpu_model = "Haswell"; /* 1.3+ theoretically */ 93 data->device_model = g_strdup_printf("%s-%s-cpu", data->cpu_model, 94 qtest_get_arch()); 95 data->sockets = 1; 96 data->cores = 3; 97 data->threads = 2; 98 data->maxcpus = data->sockets * data->cores * data->threads; 99 100 path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", 101 mname, data->sockets, data->cores, 102 data->threads, data->maxcpus); 103 qtest_add_data_func_full(path, data, test_plug_with_device_add, 104 test_data_free); 105 g_free(path); 106 } 107 108 static void add_pseries_test_case(const char *mname) 109 { 110 char *path; 111 PlugTestData *data; 112 113 if (!g_str_has_prefix(mname, "pseries-") || 114 (g_str_has_prefix(mname, "pseries-2.") && atoi(&mname[10]) < 7)) { 115 return; 116 } 117 data = g_new(PlugTestData, 1); 118 data->machine = g_strdup(mname); 119 data->cpu_model = "power8_v2.0"; 120 data->device_model = g_strdup("power8_v2.0-spapr-cpu-core"); 121 data->sockets = 2; 122 data->cores = 3; 123 data->threads = 1; 124 data->maxcpus = data->sockets * data->cores * data->threads; 125 126 path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", 127 mname, data->sockets, data->cores, 128 data->threads, data->maxcpus); 129 qtest_add_data_func_full(path, data, test_plug_with_device_add, 130 test_data_free); 131 g_free(path); 132 } 133 134 static void add_s390x_test_case(const char *mname) 135 { 136 char *path; 137 PlugTestData *data; 138 139 if (!g_str_has_prefix(mname, "s390-ccw-virtio-")) { 140 return; 141 } 142 143 data = g_new(PlugTestData, 1); 144 data->machine = g_strdup(mname); 145 data->cpu_model = "qemu"; 146 data->device_model = g_strdup("qemu-s390x-cpu"); 147 data->sockets = 1; 148 data->cores = 3; 149 data->threads = 1; 150 data->maxcpus = data->sockets * data->cores * data->threads; 151 152 path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u", 153 mname, data->sockets, data->cores, 154 data->threads, data->maxcpus); 155 qtest_add_data_func_full(path, data, test_plug_with_device_add, 156 test_data_free); 157 g_free(path); 158 } 159 160 int main(int argc, char **argv) 161 { 162 const char *arch = qtest_get_arch(); 163 164 g_test_init(&argc, &argv, NULL); 165 166 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { 167 qtest_cb_for_every_machine(add_pc_test_case, g_test_quick()); 168 } else if (g_str_equal(arch, "ppc64")) { 169 qtest_cb_for_every_machine(add_pseries_test_case, g_test_quick()); 170 } else if (g_str_equal(arch, "s390x")) { 171 qtest_cb_for_every_machine(add_s390x_test_case, g_test_quick()); 172 } 173 174 return g_test_run(); 175 } 176