qemu/tests/numa-test.c
<<
>>
Prefs
   1/*
   2 * NUMA configuration test cases
   3 *
   4 * Copyright (c) 2017 Red Hat Inc.
   5 * Authors:
   6 *  Igor Mammedov <imammedo@redhat.com>
   7 *
   8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
   9 * See the COPYING file in the top-level directory.
  10 */
  11
  12#include "qemu/osdep.h"
  13#include "libqtest.h"
  14
  15static char *make_cli(const char *generic_cli, const char *test_cli)
  16{
  17    return g_strdup_printf("%s %s", generic_cli ? generic_cli : "", test_cli);
  18}
  19
  20static char *hmp_info_numa(void)
  21{
  22    QDict *resp;
  23    char *s;
  24
  25    resp = qmp("{ 'execute': 'human-monitor-command', 'arguments': "
  26                      "{ 'command-line': 'info numa '} }");
  27    g_assert(resp);
  28    g_assert(qdict_haskey(resp, "return"));
  29    s = g_strdup(qdict_get_str(resp, "return"));
  30    g_assert(s);
  31    QDECREF(resp);
  32    return s;
  33}
  34
  35static void test_mon_explicit(const void *data)
  36{
  37    char *s;
  38    char *cli;
  39
  40    cli = make_cli(data, "-smp 8 "
  41                   "-numa node,nodeid=0,cpus=0-3 "
  42                   "-numa node,nodeid=1,cpus=4-7 ");
  43    qtest_start(cli);
  44
  45    s = hmp_info_numa();
  46    g_assert(strstr(s, "node 0 cpus: 0 1 2 3"));
  47    g_assert(strstr(s, "node 1 cpus: 4 5 6 7"));
  48    g_free(s);
  49
  50    qtest_end();
  51    g_free(cli);
  52}
  53
  54static void test_mon_default(const void *data)
  55{
  56    char *s;
  57    char *cli;
  58
  59    cli = make_cli(data, "-smp 8 -numa node -numa node");
  60    qtest_start(cli);
  61
  62    s = hmp_info_numa();
  63    g_assert(strstr(s, "node 0 cpus: 0 2 4 6"));
  64    g_assert(strstr(s, "node 1 cpus: 1 3 5 7"));
  65    g_free(s);
  66
  67    qtest_end();
  68    g_free(cli);
  69}
  70
  71static void test_mon_partial(const void *data)
  72{
  73    char *s;
  74    char *cli;
  75
  76    cli = make_cli(data, "-smp 8 "
  77                   "-numa node,nodeid=0,cpus=0-1 "
  78                   "-numa node,nodeid=1,cpus=4-5 ");
  79    qtest_start(cli);
  80
  81    s = hmp_info_numa();
  82    g_assert(strstr(s, "node 0 cpus: 0 1 2 3 6 7"));
  83    g_assert(strstr(s, "node 1 cpus: 4 5"));
  84    g_free(s);
  85
  86    qtest_end();
  87    g_free(cli);
  88}
  89
  90static QList *get_cpus(QDict **resp)
  91{
  92    *resp = qmp("{ 'execute': 'query-cpus' }");
  93    g_assert(*resp);
  94    g_assert(qdict_haskey(*resp, "return"));
  95    return qdict_get_qlist(*resp, "return");
  96}
  97
  98static void test_query_cpus(const void *data)
  99{
 100    char *cli;
 101    QDict *resp;
 102    QList *cpus;
 103    QObject *e;
 104
 105    cli = make_cli(data, "-smp 8 -numa node,cpus=0-3 -numa node,cpus=4-7");
 106    qtest_start(cli);
 107    cpus = get_cpus(&resp);
 108    g_assert(cpus);
 109
 110    while ((e = qlist_pop(cpus))) {
 111        QDict *cpu, *props;
 112        int64_t cpu_idx, node;
 113
 114        cpu = qobject_to_qdict(e);
 115        g_assert(qdict_haskey(cpu, "CPU"));
 116        g_assert(qdict_haskey(cpu, "props"));
 117
 118        cpu_idx = qdict_get_int(cpu, "CPU");
 119        props = qdict_get_qdict(cpu, "props");
 120        g_assert(qdict_haskey(props, "node-id"));
 121        node = qdict_get_int(props, "node-id");
 122        if (cpu_idx >= 0 && cpu_idx < 4) {
 123            g_assert_cmpint(node, ==, 0);
 124        } else {
 125            g_assert_cmpint(node, ==, 1);
 126        }
 127        qobject_decref(e);
 128    }
 129
 130    QDECREF(resp);
 131    qtest_end();
 132    g_free(cli);
 133}
 134
 135static void pc_numa_cpu(const void *data)
 136{
 137    char *cli;
 138    QDict *resp;
 139    QList *cpus;
 140    QObject *e;
 141
 142    cli = make_cli(data, "-cpu pentium -smp 8,sockets=2,cores=2,threads=2 "
 143        "-numa node,nodeid=0 -numa node,nodeid=1 "
 144        "-numa cpu,node-id=1,socket-id=0 "
 145        "-numa cpu,node-id=0,socket-id=1,core-id=0 "
 146        "-numa cpu,node-id=0,socket-id=1,core-id=1,thread-id=0 "
 147        "-numa cpu,node-id=1,socket-id=1,core-id=1,thread-id=1");
 148    qtest_start(cli);
 149    cpus = get_cpus(&resp);
 150    g_assert(cpus);
 151
 152    while ((e = qlist_pop(cpus))) {
 153        QDict *cpu, *props;
 154        int64_t socket, core, thread, node;
 155
 156        cpu = qobject_to_qdict(e);
 157        g_assert(qdict_haskey(cpu, "props"));
 158        props = qdict_get_qdict(cpu, "props");
 159
 160        g_assert(qdict_haskey(props, "node-id"));
 161        node = qdict_get_int(props, "node-id");
 162        g_assert(qdict_haskey(props, "socket-id"));
 163        socket = qdict_get_int(props, "socket-id");
 164        g_assert(qdict_haskey(props, "core-id"));
 165        core = qdict_get_int(props, "core-id");
 166        g_assert(qdict_haskey(props, "thread-id"));
 167        thread = qdict_get_int(props, "thread-id");
 168
 169        if (socket == 0) {
 170            g_assert_cmpint(node, ==, 1);
 171        } else if (socket == 1 && core == 0) {
 172            g_assert_cmpint(node, ==, 0);
 173        } else if (socket == 1 && core == 1 && thread == 0) {
 174            g_assert_cmpint(node, ==, 0);
 175        } else if (socket == 1 && core == 1 && thread == 1) {
 176            g_assert_cmpint(node, ==, 1);
 177        } else {
 178            g_assert(false);
 179        }
 180        qobject_decref(e);
 181    }
 182
 183    QDECREF(resp);
 184    qtest_end();
 185    g_free(cli);
 186}
 187
 188static void spapr_numa_cpu(const void *data)
 189{
 190    char *cli;
 191    QDict *resp;
 192    QList *cpus;
 193    QObject *e;
 194
 195    cli = make_cli(data, "-smp 4,cores=4 "
 196        "-numa node,nodeid=0 -numa node,nodeid=1 "
 197        "-numa cpu,node-id=0,core-id=0 "
 198        "-numa cpu,node-id=0,core-id=1 "
 199        "-numa cpu,node-id=0,core-id=2 "
 200        "-numa cpu,node-id=1,core-id=3");
 201    qtest_start(cli);
 202    cpus = get_cpus(&resp);
 203    g_assert(cpus);
 204
 205    while ((e = qlist_pop(cpus))) {
 206        QDict *cpu, *props;
 207        int64_t core, node;
 208
 209        cpu = qobject_to_qdict(e);
 210        g_assert(qdict_haskey(cpu, "props"));
 211        props = qdict_get_qdict(cpu, "props");
 212
 213        g_assert(qdict_haskey(props, "node-id"));
 214        node = qdict_get_int(props, "node-id");
 215        g_assert(qdict_haskey(props, "core-id"));
 216        core = qdict_get_int(props, "core-id");
 217
 218        if (core >= 0 && core < 3) {
 219            g_assert_cmpint(node, ==, 0);
 220        } else if (core == 3) {
 221            g_assert_cmpint(node, ==, 1);
 222        } else {
 223            g_assert(false);
 224        }
 225        qobject_decref(e);
 226    }
 227
 228    QDECREF(resp);
 229    qtest_end();
 230    g_free(cli);
 231}
 232
 233static void aarch64_numa_cpu(const void *data)
 234{
 235    char *cli;
 236    QDict *resp;
 237    QList *cpus;
 238    QObject *e;
 239
 240    cli = make_cli(data, "-smp 2 "
 241        "-numa node,nodeid=0 -numa node,nodeid=1 "
 242        "-numa cpu,node-id=1,thread-id=0 "
 243        "-numa cpu,node-id=0,thread-id=1");
 244    qtest_start(cli);
 245    cpus = get_cpus(&resp);
 246    g_assert(cpus);
 247
 248    while ((e = qlist_pop(cpus))) {
 249        QDict *cpu, *props;
 250        int64_t thread, node;
 251
 252        cpu = qobject_to_qdict(e);
 253        g_assert(qdict_haskey(cpu, "props"));
 254        props = qdict_get_qdict(cpu, "props");
 255
 256        g_assert(qdict_haskey(props, "node-id"));
 257        node = qdict_get_int(props, "node-id");
 258        g_assert(qdict_haskey(props, "thread-id"));
 259        thread = qdict_get_int(props, "thread-id");
 260
 261        if (thread == 0) {
 262            g_assert_cmpint(node, ==, 1);
 263        } else if (thread == 1) {
 264            g_assert_cmpint(node, ==, 0);
 265        } else {
 266            g_assert(false);
 267        }
 268        qobject_decref(e);
 269    }
 270
 271    QDECREF(resp);
 272    qtest_end();
 273    g_free(cli);
 274}
 275
 276int main(int argc, char **argv)
 277{
 278    const char *args = NULL;
 279    const char *arch = qtest_get_arch();
 280
 281    if (strcmp(arch, "aarch64") == 0) {
 282        args = "-machine virt";
 283    }
 284
 285    g_test_init(&argc, &argv, NULL);
 286
 287    qtest_add_data_func("/numa/mon/default", args, test_mon_default);
 288    qtest_add_data_func("/numa/mon/cpus/explicit", args, test_mon_explicit);
 289    qtest_add_data_func("/numa/mon/cpus/partial", args, test_mon_partial);
 290    qtest_add_data_func("/numa/qmp/cpus/query-cpus", args, test_query_cpus);
 291
 292    if (!strcmp(arch, "i386") || !strcmp(arch, "x86_64")) {
 293        qtest_add_data_func("/numa/pc/cpu/explicit", args, pc_numa_cpu);
 294    }
 295
 296    if (!strcmp(arch, "ppc64")) {
 297        qtest_add_data_func("/numa/spapr/cpu/explicit", args, spapr_numa_cpu);
 298    }
 299
 300    if (!strcmp(arch, "aarch64")) {
 301        qtest_add_data_func("/numa/aarch64/cpu/explicit", args,
 302                            aarch64_numa_cpu);
 303    }
 304
 305    return g_test_run();
 306}
 307