qemu/tests/qtest/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 GString *generic_cli, const char *test_cli)
  18{
  19    return g_strdup_printf("%s %s", generic_cli->str, test_cli);
  20}
  21
  22static void test_mon_explicit(const void *data)
  23{
  24    QTestState *qts;
  25    g_autofree char *s = NULL;
  26    g_autofree char *cli = NULL;
  27
  28    cli = make_cli(data, "-machine smp.cpus=8 -numa node,nodeid=0,memdev=ram,cpus=0-3 "
  29                         "-numa node,nodeid=1,cpus=4-7");
  30    qts = qtest_init(cli);
  31
  32    s = qtest_hmp(qts, "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
  36    qtest_quit(qts);
  37}
  38
  39static void test_def_cpu_split(const void *data)
  40{
  41    QTestState *qts;
  42    g_autofree char *s = NULL;
  43    g_autofree char *cli = NULL;
  44
  45    cli = make_cli(data, "-machine smp.cpus=8,smp.sockets=8 "
  46                         "-numa node,memdev=ram -numa node");
  47    qts = qtest_init(cli);
  48
  49    s = qtest_hmp(qts, "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
  53    qtest_quit(qts);
  54}
  55
  56static void test_mon_partial(const void *data)
  57{
  58    QTestState *qts;
  59    g_autofree char *s = NULL;
  60    g_autofree char *cli = NULL;
  61
  62    cli = make_cli(data, "-machine smp.cpus=8 "
  63                   "-numa node,nodeid=0,memdev=ram,cpus=0-1 "
  64                   "-numa node,nodeid=1,cpus=4-5 ");
  65    qts = qtest_init(cli);
  66
  67    s = qtest_hmp(qts, "info numa");
  68    g_assert(strstr(s, "node 0 cpus: 0 1 2 3 6 7"));
  69    g_assert(strstr(s, "node 1 cpus: 4 5"));
  70
  71    qtest_quit(qts);
  72}
  73
  74static QList *get_cpus(QTestState *qts, QDict **resp)
  75{
  76    *resp = qtest_qmp(qts, "{ 'execute': 'query-cpus-fast' }");
  77    g_assert(*resp);
  78    g_assert(qdict_haskey(*resp, "return"));
  79    return qdict_get_qlist(*resp, "return");
  80}
  81
  82static void test_query_cpus(const void *data)
  83{
  84    QDict *resp;
  85    QList *cpus;
  86    QObject *e;
  87    QTestState *qts;
  88    g_autofree char *cli = NULL;
  89
  90    cli = make_cli(data, "-machine smp.cpus=8 -numa node,memdev=ram,cpus=0-3 "
  91                         "-numa node,cpus=4-7");
  92    qts = qtest_init(cli);
  93    cpus = get_cpus(qts, &resp);
  94    g_assert(cpus);
  95
  96    while ((e = qlist_pop(cpus))) {
  97        QDict *cpu, *props;
  98        int64_t cpu_idx, node;
  99
 100        cpu = qobject_to(QDict, e);
 101        g_assert(qdict_haskey(cpu, "cpu-index"));
 102        g_assert(qdict_haskey(cpu, "props"));
 103
 104        cpu_idx = qdict_get_int(cpu, "cpu-index");
 105        props = qdict_get_qdict(cpu, "props");
 106        g_assert(qdict_haskey(props, "node-id"));
 107        node = qdict_get_int(props, "node-id");
 108        if (cpu_idx >= 0 && cpu_idx < 4) {
 109            g_assert_cmpint(node, ==, 0);
 110        } else {
 111            g_assert_cmpint(node, ==, 1);
 112        }
 113        qobject_unref(e);
 114    }
 115
 116    qobject_unref(resp);
 117    qtest_quit(qts);
 118}
 119
 120static void pc_numa_cpu(const void *data)
 121{
 122    QDict *resp;
 123    QList *cpus;
 124    QObject *e;
 125    QTestState *qts;
 126    g_autofree char *cli = NULL;
 127
 128    cli = make_cli(data, "-cpu pentium -machine smp.cpus=8,smp.sockets=2,smp.cores=2,smp.threads=2 "
 129        "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 "
 130        "-numa cpu,node-id=1,socket-id=0 "
 131        "-numa cpu,node-id=0,socket-id=1,core-id=0 "
 132        "-numa cpu,node-id=0,socket-id=1,core-id=1,thread-id=0 "
 133        "-numa cpu,node-id=1,socket-id=1,core-id=1,thread-id=1");
 134    qts = qtest_init(cli);
 135    cpus = get_cpus(qts, &resp);
 136    g_assert(cpus);
 137
 138    while ((e = qlist_pop(cpus))) {
 139        QDict *cpu, *props;
 140        int64_t socket, core, thread, node;
 141
 142        cpu = qobject_to(QDict, e);
 143        g_assert(qdict_haskey(cpu, "props"));
 144        props = qdict_get_qdict(cpu, "props");
 145
 146        g_assert(qdict_haskey(props, "node-id"));
 147        node = qdict_get_int(props, "node-id");
 148        g_assert(qdict_haskey(props, "socket-id"));
 149        socket = qdict_get_int(props, "socket-id");
 150        g_assert(qdict_haskey(props, "core-id"));
 151        core = qdict_get_int(props, "core-id");
 152        g_assert(qdict_haskey(props, "thread-id"));
 153        thread = qdict_get_int(props, "thread-id");
 154
 155        if (socket == 0) {
 156            g_assert_cmpint(node, ==, 1);
 157        } else if (socket == 1 && core == 0) {
 158            g_assert_cmpint(node, ==, 0);
 159        } else if (socket == 1 && core == 1 && thread == 0) {
 160            g_assert_cmpint(node, ==, 0);
 161        } else if (socket == 1 && core == 1 && thread == 1) {
 162            g_assert_cmpint(node, ==, 1);
 163        } else {
 164            g_assert(false);
 165        }
 166        qobject_unref(e);
 167    }
 168
 169    qobject_unref(resp);
 170    qtest_quit(qts);
 171}
 172
 173static void spapr_numa_cpu(const void *data)
 174{
 175    QDict *resp;
 176    QList *cpus;
 177    QObject *e;
 178    QTestState *qts;
 179    g_autofree char *cli = NULL;
 180
 181    cli = make_cli(data, "-machine smp.cpus=4,smp.cores=4 "
 182        "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 "
 183        "-numa cpu,node-id=0,core-id=0 "
 184        "-numa cpu,node-id=0,core-id=1 "
 185        "-numa cpu,node-id=0,core-id=2 "
 186        "-numa cpu,node-id=1,core-id=3");
 187    qts = qtest_init(cli);
 188    cpus = get_cpus(qts, &resp);
 189    g_assert(cpus);
 190
 191    while ((e = qlist_pop(cpus))) {
 192        QDict *cpu, *props;
 193        int64_t core, node;
 194
 195        cpu = qobject_to(QDict, e);
 196        g_assert(qdict_haskey(cpu, "props"));
 197        props = qdict_get_qdict(cpu, "props");
 198
 199        g_assert(qdict_haskey(props, "node-id"));
 200        node = qdict_get_int(props, "node-id");
 201        g_assert(qdict_haskey(props, "core-id"));
 202        core = qdict_get_int(props, "core-id");
 203
 204        if (core >= 0 && core < 3) {
 205            g_assert_cmpint(node, ==, 0);
 206        } else if (core == 3) {
 207            g_assert_cmpint(node, ==, 1);
 208        } else {
 209            g_assert(false);
 210        }
 211        qobject_unref(e);
 212    }
 213
 214    qobject_unref(resp);
 215    qtest_quit(qts);
 216}
 217
 218static void aarch64_numa_cpu(const void *data)
 219{
 220    QDict *resp;
 221    QList *cpus;
 222    QObject *e;
 223    QTestState *qts;
 224    g_autofree char *cli = NULL;
 225
 226    cli = make_cli(data, "-machine "
 227        "smp.cpus=2,smp.sockets=2,smp.clusters=1,smp.cores=1,smp.threads=1 "
 228        "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 "
 229        "-numa cpu,node-id=0,socket-id=1,cluster-id=0,core-id=0,thread-id=0 "
 230        "-numa cpu,node-id=1,socket-id=0,cluster-id=0,core-id=0,thread-id=0");
 231    qts = qtest_init(cli);
 232    cpus = get_cpus(qts, &resp);
 233    g_assert(cpus);
 234
 235    while ((e = qlist_pop(cpus))) {
 236        QDict *cpu, *props;
 237        int64_t socket, cluster, core, 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, "socket-id"));
 246        socket = qdict_get_int(props, "socket-id");
 247        g_assert(qdict_haskey(props, "cluster-id"));
 248        cluster = qdict_get_int(props, "cluster-id");
 249        g_assert(qdict_haskey(props, "core-id"));
 250        core = qdict_get_int(props, "core-id");
 251        g_assert(qdict_haskey(props, "thread-id"));
 252        thread = qdict_get_int(props, "thread-id");
 253
 254        if (socket == 0 && cluster == 0 && core == 0 && thread == 0) {
 255            g_assert_cmpint(node, ==, 1);
 256        } else if (socket == 1 && cluster == 0 && core == 0 && thread == 0) {
 257            g_assert_cmpint(node, ==, 0);
 258        } else {
 259            g_assert(false);
 260        }
 261        qobject_unref(e);
 262    }
 263
 264    qobject_unref(resp);
 265    qtest_quit(qts);
 266}
 267
 268static void pc_dynamic_cpu_cfg(const void *data)
 269{
 270    QObject *e;
 271    QDict *resp;
 272    QList *cpus;
 273    QTestState *qs;
 274    g_autofree char *cli = NULL;
 275
 276    cli = make_cli(data, "-nodefaults --preconfig "
 277                         "-machine smp.cpus=2,smp.sockets=2");
 278    qs = qtest_init(cli);
 279
 280    /* create 2 numa nodes */
 281    g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 282        " 'arguments': { 'type': 'node', 'nodeid': 0, 'memdev': 'ram' } }")));
 283    g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 284        " 'arguments': { 'type': 'node', 'nodeid': 1 } }")));
 285
 286    /* map 2 cpus in non default reverse order
 287     * i.e socket1->node0, socket0->node1
 288     */
 289    g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 290        " 'arguments': { 'type': 'cpu', 'node-id': 0, 'socket-id': 1 } }")));
 291    g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 292        " 'arguments': { 'type': 'cpu', 'node-id': 1, 'socket-id': 0 } }")));
 293
 294    /* let machine initialization to complete and run */
 295    g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'x-exit-preconfig' }")));
 296    qtest_qmp_eventwait(qs, "RESUME");
 297
 298    /* check that CPUs are mapped as expected */
 299    resp = qtest_qmp(qs, "{ 'execute': 'query-hotpluggable-cpus'}");
 300    g_assert(qdict_haskey(resp, "return"));
 301    cpus = qdict_get_qlist(resp, "return");
 302    g_assert(cpus);
 303    while ((e = qlist_pop(cpus))) {
 304        const QDict *cpu, *props;
 305        int64_t socket, node;
 306
 307        cpu = qobject_to(QDict, e);
 308        g_assert(qdict_haskey(cpu, "props"));
 309        props = qdict_get_qdict(cpu, "props");
 310
 311        g_assert(qdict_haskey(props, "node-id"));
 312        node = qdict_get_int(props, "node-id");
 313        g_assert(qdict_haskey(props, "socket-id"));
 314        socket = qdict_get_int(props, "socket-id");
 315
 316        if (socket == 0) {
 317            g_assert_cmpint(node, ==, 1);
 318        } else if (socket == 1) {
 319            g_assert_cmpint(node, ==, 0);
 320        } else {
 321            g_assert(false);
 322        }
 323        qobject_unref(e);
 324    }
 325    qobject_unref(resp);
 326
 327    qtest_quit(qs);
 328}
 329
 330static void pc_hmat_build_cfg(const void *data)
 331{
 332    QTestState *qs;
 333    g_autofree char *cli = NULL;
 334
 335    cli = make_cli(data, "-nodefaults --preconfig -machine hmat=on "
 336                         "-machine smp.cpus=2,smp.sockets=2 "
 337                         "-m 128M,slots=2,maxmem=1G "
 338                         "-object memory-backend-ram,size=64M,id=m0 "
 339                         "-object memory-backend-ram,size=64M,id=m1 "
 340                         "-numa node,nodeid=0,memdev=m0 "
 341                         "-numa node,nodeid=1,memdev=m1,initiator=0 "
 342                         "-numa cpu,node-id=0,socket-id=0 "
 343                         "-numa cpu,node-id=0,socket-id=1");
 344    qs = qtest_init(cli);
 345
 346    /* Fail: Initiator should be less than the number of nodes */
 347    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 348        " 'arguments': { 'type': 'hmat-lb', 'initiator': 2, 'target': 0,"
 349        " 'hierarchy': \"memory\", 'data-type': \"access-latency\" } }")));
 350
 351    /* Fail: Target should be less than the number of nodes */
 352    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 353        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 2,"
 354        " 'hierarchy': \"memory\", 'data-type': \"access-latency\" } }")));
 355
 356    /* Fail: Initiator should contain cpu */
 357    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 358        " 'arguments': { 'type': 'hmat-lb', 'initiator': 1, 'target': 0,"
 359        " 'hierarchy': \"memory\", 'data-type': \"access-latency\" } }")));
 360
 361    /* Fail: Data-type mismatch */
 362    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 363        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 364        " 'hierarchy': \"memory\", 'data-type': \"write-latency\","
 365        " 'bandwidth': 524288000 } }")));
 366    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 367        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 368        " 'hierarchy': \"memory\", 'data-type': \"read-bandwidth\","
 369        " 'latency': 5 } }")));
 370
 371    /* Fail: Bandwidth should be 1MB (1048576) aligned */
 372    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 373        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 374        " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\","
 375        " 'bandwidth': 1048575 } }")));
 376
 377    /* Configuring HMAT bandwidth and latency details */
 378    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 379        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 380        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 381        " 'latency': 1 } }")));    /* 1 ns */
 382    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 383        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 384        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 385        " 'latency': 5 } }")));    /* Fail: Duplicate configuration */
 386    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 387        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 388        " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\","
 389        " 'bandwidth': 68717379584 } }")));    /* 65534 MB/s */
 390    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 391        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1,"
 392        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 393        " 'latency': 65534 } }")));    /* 65534 ns */
 394    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 395        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1,"
 396        " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\","
 397        " 'bandwidth': 34358689792 } }")));    /* 32767 MB/s */
 398
 399    /* Fail: node_id should be less than the number of nodes */
 400    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 401        " 'arguments': { 'type': 'hmat-cache', 'node-id': 2, 'size': 10240,"
 402        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 403        " 'line': 8 } }")));
 404
 405    /* Fail: level should be less than HMAT_LB_LEVELS (4) */
 406    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 407        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 408        " 'level': 4, 'associativity': \"direct\", 'policy': \"write-back\","
 409        " 'line': 8 } }")));
 410
 411    /* Fail: associativity option should be 'none', if level is 0 */
 412    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 413        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 414        " 'level': 0, 'associativity': \"direct\", 'policy': \"none\","
 415        " 'line': 0 } }")));
 416    /* Fail: policy option should be 'none', if level is 0 */
 417    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 418        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 419        " 'level': 0, 'associativity': \"none\", 'policy': \"write-back\","
 420        " 'line': 0 } }")));
 421    /* Fail: line option should be 0, if level is 0 */
 422    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 423        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 424        " 'level': 0, 'associativity': \"none\", 'policy': \"none\","
 425        " 'line': 8 } }")));
 426
 427    /* Configuring HMAT memory side cache attributes */
 428    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 429        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 430        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 431        " 'line': 8 } }")));
 432    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 433        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 434        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 435        " 'line': 8 } }")));    /* Fail: Duplicate configuration */
 436    /* Fail: The size of level 2 size should be small than level 1 */
 437    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 438        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 439        " 'level': 2, 'associativity': \"direct\", 'policy': \"write-back\","
 440        " 'line': 8 } }")));
 441    /* Fail: The size of level 0 size should be larger than level 1 */
 442    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 443        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 444        " 'level': 0, 'associativity': \"direct\", 'policy': \"write-back\","
 445        " 'line': 8 } }")));
 446    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 447        " 'arguments': { 'type': 'hmat-cache', 'node-id': 1, 'size': 10240,"
 448        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 449        " 'line': 8 } }")));
 450
 451    /* let machine initialization to complete and run */
 452    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs,
 453        "{ 'execute': 'x-exit-preconfig' }")));
 454    qtest_qmp_eventwait(qs, "RESUME");
 455
 456    qtest_quit(qs);
 457}
 458
 459static void pc_hmat_off_cfg(const void *data)
 460{
 461    QTestState *qs;
 462    g_autofree char *cli = NULL;
 463
 464    cli = make_cli(data, "-nodefaults --preconfig "
 465                         "-machine smp.cpus=2,smp.sockets=2 "
 466                         "-m 128M,slots=2,maxmem=1G "
 467                         "-object memory-backend-ram,size=64M,id=m0,prealloc=y "
 468                         "-object memory-backend-ram,size=64M,id=m1 "
 469                         "-numa node,nodeid=0,memdev=m0");
 470    qs = qtest_init(cli);
 471
 472    /*
 473     * Fail: Enable HMAT with -machine hmat=on
 474     * before using any of hmat specific options
 475     */
 476    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 477        " 'arguments': { 'type': 'node', 'nodeid': 1, 'memdev': \"m1\","
 478        " 'initiator': 0 } }")));
 479    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 480        " 'arguments': { 'type': 'node', 'nodeid': 1, 'memdev': \"m1\" } }")));
 481    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 482        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 483        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 484        " 'latency': 1 } }")));
 485    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 486        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 487        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 488        " 'line': 8 } }")));
 489
 490    /* let machine initialization to complete and run */
 491    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs,
 492        "{ 'execute': 'x-exit-preconfig' }")));
 493    qtest_qmp_eventwait(qs, "RESUME");
 494
 495    qtest_quit(qs);
 496}
 497
 498static void pc_hmat_erange_cfg(const void *data)
 499{
 500    QTestState *qs;
 501    g_autofree char *cli = NULL;
 502
 503    cli = make_cli(data, "-nodefaults --preconfig -machine hmat=on "
 504                         "-machine smp.cpus=2,smp.sockets=2 "
 505                         "-m 128M,slots=2,maxmem=1G "
 506                         "-object memory-backend-ram,size=64M,id=m0 "
 507                         "-object memory-backend-ram,size=64M,id=m1 "
 508                         "-numa node,nodeid=0,memdev=m0 "
 509                         "-numa node,nodeid=1,memdev=m1,initiator=0 "
 510                         "-numa cpu,node-id=0,socket-id=0 "
 511                         "-numa cpu,node-id=0,socket-id=1");
 512    qs = qtest_init(cli);
 513
 514    /* Can't store the compressed latency */
 515    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 516        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 517        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 518        " 'latency': 1 } }")));    /* 1 ns */
 519    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 520        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1,"
 521        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 522        " 'latency': 65535 } }")));    /* 65535 ns */
 523
 524    /* Test the 0 input (bandwidth not provided) */
 525    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 526        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 527        " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\","
 528        " 'bandwidth': 0 } }")));    /* 0 MB/s */
 529    /* Fail: bandwidth should be provided before memory side cache attributes */
 530    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 531        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 532        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 533        " 'line': 8 } }")));
 534
 535    /* Can't store the compressed bandwidth */
 536    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 537        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1,"
 538        " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\","
 539        " 'bandwidth': 68718428160 } }")));    /* 65535 MB/s */
 540
 541    /* let machine initialization to complete and run */
 542    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs,
 543        "{ 'execute': 'x-exit-preconfig' }")));
 544    qtest_qmp_eventwait(qs, "RESUME");
 545
 546    qtest_quit(qs);
 547}
 548
 549int main(int argc, char **argv)
 550{
 551    g_autoptr(GString) args = g_string_new(NULL);
 552    const char *arch = qtest_get_arch();
 553
 554    if (g_str_equal(arch, "ppc64")) {
 555        g_string_append(args, " -object memory-backend-ram,id=ram,size=512M");
 556    } else {
 557        g_string_append(args, " -object memory-backend-ram,id=ram,size=128M");
 558    }
 559
 560    if (g_str_equal(arch, "aarch64")) {
 561        g_string_append(args, " -machine virt");
 562    }
 563
 564    g_test_init(&argc, &argv, NULL);
 565
 566    qtest_add_data_func("/numa/mon/cpus/default", args, test_def_cpu_split);
 567    qtest_add_data_func("/numa/mon/cpus/explicit", args, test_mon_explicit);
 568    qtest_add_data_func("/numa/mon/cpus/partial", args, test_mon_partial);
 569    qtest_add_data_func("/numa/qmp/cpus/query-cpus", args, test_query_cpus);
 570
 571    if (!strcmp(arch, "i386") || !strcmp(arch, "x86_64")) {
 572        qtest_add_data_func("/numa/pc/cpu/explicit", args, pc_numa_cpu);
 573        qtest_add_data_func("/numa/pc/dynamic/cpu", args, pc_dynamic_cpu_cfg);
 574        qtest_add_data_func("/numa/pc/hmat/build", args, pc_hmat_build_cfg);
 575        qtest_add_data_func("/numa/pc/hmat/off", args, pc_hmat_off_cfg);
 576        qtest_add_data_func("/numa/pc/hmat/erange", args, pc_hmat_erange_cfg);
 577    }
 578
 579    if (!strcmp(arch, "ppc64")) {
 580        qtest_add_data_func("/numa/spapr/cpu/explicit", args, spapr_numa_cpu);
 581    }
 582
 583    if (!strcmp(arch, "aarch64")) {
 584        qtest_add_data_func("/numa/aarch64/cpu/explicit", args,
 585                            aarch64_numa_cpu);
 586    }
 587
 588    return g_test_run();
 589}
 590