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