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