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