qemu/tests/cpu-plug-test.c
<<
>>
Prefs
   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.h"
  14#include "qapi/qmp/qdict.h"
  15
  16struct 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};
  25typedef struct PlugTestData PlugTestData;
  26
  27static void test_plug_with_cpu_add(gconstpointer data)
  28{
  29    const PlugTestData *s = data;
  30    char *args;
  31    QDict *response;
  32    unsigned int i;
  33
  34    args = g_strdup_printf("-machine %s -cpu %s "
  35                           "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u",
  36                           s->machine, s->cpu_model,
  37                           s->sockets, s->cores, s->threads, s->maxcpus);
  38    qtest_start(args);
  39
  40    for (i = 1; i < s->maxcpus; i++) {
  41        response = qmp("{ 'execute': 'cpu-add',"
  42                       "  'arguments': { 'id': %d } }", i);
  43        g_assert(response);
  44        g_assert(!qdict_haskey(response, "error"));
  45        qobject_unref(response);
  46    }
  47
  48    qtest_end();
  49    g_free(args);
  50}
  51
  52static void test_plug_without_cpu_add(gconstpointer data)
  53{
  54    const PlugTestData *s = data;
  55    char *args;
  56    QDict *response;
  57
  58    args = g_strdup_printf("-machine %s -cpu %s "
  59                           "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u",
  60                           s->machine, s->cpu_model,
  61                           s->sockets, s->cores, s->threads, s->maxcpus);
  62    qtest_start(args);
  63
  64    response = qmp("{ 'execute': 'cpu-add',"
  65                   "  'arguments': { 'id': %d } }",
  66                   s->sockets * s->cores * s->threads);
  67    g_assert(response);
  68    g_assert(qdict_haskey(response, "error"));
  69    qobject_unref(response);
  70
  71    qtest_end();
  72    g_free(args);
  73}
  74
  75static void test_plug_with_device_add_x86(gconstpointer data)
  76{
  77    const PlugTestData *td = data;
  78    char *args;
  79    unsigned int s, c, t;
  80
  81    args = g_strdup_printf("-machine %s -cpu %s "
  82                           "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u",
  83                           td->machine, td->cpu_model,
  84                           td->sockets, td->cores, td->threads, td->maxcpus);
  85    qtest_start(args);
  86
  87    for (s = 1; s < td->sockets; s++) {
  88        for (c = 0; c < td->cores; c++) {
  89            for (t = 0; t < td->threads; t++) {
  90                char *id = g_strdup_printf("id-%i-%i-%i", s, c, t);
  91                qtest_qmp_device_add(td->device_model, id,
  92                                     "{'socket-id':%u, 'core-id':%u,"
  93                                     " 'thread-id':%u}",
  94                                     s, c, t);
  95                g_free(id);
  96            }
  97        }
  98    }
  99
 100    qtest_end();
 101    g_free(args);
 102}
 103
 104static void test_plug_with_device_add_coreid(gconstpointer data)
 105{
 106    const PlugTestData *td = data;
 107    char *args;
 108    unsigned int c;
 109
 110    args = g_strdup_printf("-machine %s -cpu %s "
 111                           "-smp 1,sockets=%u,cores=%u,threads=%u,maxcpus=%u",
 112                           td->machine, td->cpu_model,
 113                           td->sockets, td->cores, td->threads, td->maxcpus);
 114    qtest_start(args);
 115
 116    for (c = 1; c < td->cores; c++) {
 117        char *id = g_strdup_printf("id-%i", c);
 118        qtest_qmp_device_add(td->device_model, id, "{'core-id':%u}", c);
 119        g_free(id);
 120    }
 121
 122    qtest_end();
 123    g_free(args);
 124}
 125
 126static void test_data_free(gpointer data)
 127{
 128    PlugTestData *pc = data;
 129
 130    g_free(pc->machine);
 131    g_free(pc->device_model);
 132    g_free(pc);
 133}
 134
 135static void add_pc_test_case(const char *mname)
 136{
 137    char *path;
 138    PlugTestData *data;
 139
 140    if (!g_str_has_prefix(mname, "pc-")) {
 141        return;
 142    }
 143    data = g_new(PlugTestData, 1);
 144    data->machine = g_strdup(mname);
 145    data->cpu_model = "Haswell"; /* 1.3+ theoretically */
 146    data->device_model = g_strdup_printf("%s-%s-cpu", data->cpu_model,
 147                                         qtest_get_arch());
 148    data->sockets = 1;
 149    data->cores = 3;
 150    data->threads = 2;
 151    data->maxcpus = data->sockets * data->cores * data->threads;
 152    if (g_str_has_suffix(mname, "-1.4") ||
 153        (strcmp(mname, "pc-1.3") == 0) ||
 154        (strcmp(mname, "pc-1.2") == 0) ||
 155        (strcmp(mname, "pc-1.1") == 0) ||
 156        (strcmp(mname, "pc-1.0") == 0) ||
 157        (strcmp(mname, "pc-0.15") == 0) ||
 158        (strcmp(mname, "pc-0.14") == 0) ||
 159        (strcmp(mname, "pc-0.13") == 0) ||
 160        (strcmp(mname, "pc-0.12") == 0)) {
 161        path = g_strdup_printf("cpu-plug/%s/init/%ux%ux%u&maxcpus=%u",
 162                               mname, data->sockets, data->cores,
 163                               data->threads, data->maxcpus);
 164        qtest_add_data_func_full(path, data, test_plug_without_cpu_add,
 165                                 test_data_free);
 166        g_free(path);
 167    } else {
 168        PlugTestData *data2 = g_memdup(data, sizeof(PlugTestData));
 169
 170        data2->machine = g_strdup(data->machine);
 171        data2->device_model = g_strdup(data->device_model);
 172
 173        path = g_strdup_printf("cpu-plug/%s/cpu-add/%ux%ux%u&maxcpus=%u",
 174                               mname, data->sockets, data->cores,
 175                               data->threads, data->maxcpus);
 176        qtest_add_data_func_full(path, data, test_plug_with_cpu_add,
 177                                 test_data_free);
 178        g_free(path);
 179        path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u",
 180                               mname, data2->sockets, data2->cores,
 181                               data2->threads, data2->maxcpus);
 182        qtest_add_data_func_full(path, data2, test_plug_with_device_add_x86,
 183                                 test_data_free);
 184        g_free(path);
 185    }
 186}
 187
 188static void add_pseries_test_case(const char *mname)
 189{
 190    char *path;
 191    PlugTestData *data;
 192
 193    if (!g_str_has_prefix(mname, "pseries-") ||
 194        (g_str_has_prefix(mname, "pseries-2.") && atoi(&mname[10]) < 7)) {
 195        return;
 196    }
 197    data = g_new(PlugTestData, 1);
 198    data->machine = g_strdup(mname);
 199    data->cpu_model = "power8_v2.0";
 200    data->device_model = g_strdup("power8_v2.0-spapr-cpu-core");
 201    data->sockets = 2;
 202    data->cores = 3;
 203    data->threads = 1;
 204    data->maxcpus = data->sockets * data->cores * data->threads;
 205
 206    path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u",
 207                           mname, data->sockets, data->cores,
 208                           data->threads, data->maxcpus);
 209    qtest_add_data_func_full(path, data, test_plug_with_device_add_coreid,
 210                             test_data_free);
 211    g_free(path);
 212}
 213
 214static void add_s390x_test_case(const char *mname)
 215{
 216    char *path;
 217    PlugTestData *data, *data2;
 218
 219    if (!g_str_has_prefix(mname, "s390-ccw-virtio-")) {
 220        return;
 221    }
 222
 223    data = g_new(PlugTestData, 1);
 224    data->machine = g_strdup(mname);
 225    data->cpu_model = "qemu";
 226    data->device_model = g_strdup("qemu-s390x-cpu");
 227    data->sockets = 1;
 228    data->cores = 3;
 229    data->threads = 1;
 230    data->maxcpus = data->sockets * data->cores * data->threads;
 231
 232    data2 = g_memdup(data, sizeof(PlugTestData));
 233    data2->machine = g_strdup(data->machine);
 234    data2->device_model = g_strdup(data->device_model);
 235
 236    path = g_strdup_printf("cpu-plug/%s/cpu-add/%ux%ux%u&maxcpus=%u",
 237                           mname, data->sockets, data->cores,
 238                           data->threads, data->maxcpus);
 239    qtest_add_data_func_full(path, data, test_plug_with_cpu_add,
 240                             test_data_free);
 241    g_free(path);
 242
 243    path = g_strdup_printf("cpu-plug/%s/device-add/%ux%ux%u&maxcpus=%u",
 244                           mname, data2->sockets, data2->cores,
 245                           data2->threads, data2->maxcpus);
 246    qtest_add_data_func_full(path, data2, test_plug_with_device_add_coreid,
 247                             test_data_free);
 248    g_free(path);
 249}
 250
 251int main(int argc, char **argv)
 252{
 253    const char *arch = qtest_get_arch();
 254
 255    g_test_init(&argc, &argv, NULL);
 256
 257    if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
 258        qtest_cb_for_every_machine(add_pc_test_case, g_test_quick());
 259    } else if (g_str_equal(arch, "ppc64")) {
 260        qtest_cb_for_every_machine(add_pseries_test_case, g_test_quick());
 261    } else if (g_str_equal(arch, "s390x")) {
 262        qtest_cb_for_every_machine(add_s390x_test_case, g_test_quick());
 263    }
 264
 265    return g_test_run();
 266}
 267