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 "libqos/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 smp.cpus=2 "
 227        "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 "
 228        "-numa cpu,node-id=1,thread-id=0 "
 229        "-numa cpu,node-id=0,thread-id=1");
 230    qts = qtest_init(cli);
 231    cpus = get_cpus(qts, &resp);
 232    g_assert(cpus);
 233
 234    while ((e = qlist_pop(cpus))) {
 235        QDict *cpu, *props;
 236        int64_t thread, node;
 237
 238        cpu = qobject_to(QDict, e);
 239        g_assert(qdict_haskey(cpu, "props"));
 240        props = qdict_get_qdict(cpu, "props");
 241
 242        g_assert(qdict_haskey(props, "node-id"));
 243        node = qdict_get_int(props, "node-id");
 244        g_assert(qdict_haskey(props, "thread-id"));
 245        thread = qdict_get_int(props, "thread-id");
 246
 247        if (thread == 0) {
 248            g_assert_cmpint(node, ==, 1);
 249        } else if (thread == 1) {
 250            g_assert_cmpint(node, ==, 0);
 251        } else {
 252            g_assert(false);
 253        }
 254        qobject_unref(e);
 255    }
 256
 257    qobject_unref(resp);
 258    qtest_quit(qts);
 259}
 260
 261static void pc_dynamic_cpu_cfg(const void *data)
 262{
 263    QObject *e;
 264    QDict *resp;
 265    QList *cpus;
 266    QTestState *qs;
 267    g_autofree char *cli = NULL;
 268
 269    cli = make_cli(data, "-nodefaults --preconfig "
 270                         "-machine smp.cpus=2,smp.sockets=2");
 271    qs = qtest_init(cli);
 272
 273    /* create 2 numa nodes */
 274    g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 275        " 'arguments': { 'type': 'node', 'nodeid': 0, 'memdev': 'ram' } }")));
 276    g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 277        " 'arguments': { 'type': 'node', 'nodeid': 1 } }")));
 278
 279    /* map 2 cpus in non default reverse order
 280     * i.e socket1->node0, socket0->node1
 281     */
 282    g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 283        " 'arguments': { 'type': 'cpu', 'node-id': 0, 'socket-id': 1 } }")));
 284    g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 285        " 'arguments': { 'type': 'cpu', 'node-id': 1, 'socket-id': 0 } }")));
 286
 287    /* let machine initialization to complete and run */
 288    g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'x-exit-preconfig' }")));
 289    qtest_qmp_eventwait(qs, "RESUME");
 290
 291    /* check that CPUs are mapped as expected */
 292    resp = qtest_qmp(qs, "{ 'execute': 'query-hotpluggable-cpus'}");
 293    g_assert(qdict_haskey(resp, "return"));
 294    cpus = qdict_get_qlist(resp, "return");
 295    g_assert(cpus);
 296    while ((e = qlist_pop(cpus))) {
 297        const QDict *cpu, *props;
 298        int64_t socket, node;
 299
 300        cpu = qobject_to(QDict, e);
 301        g_assert(qdict_haskey(cpu, "props"));
 302        props = qdict_get_qdict(cpu, "props");
 303
 304        g_assert(qdict_haskey(props, "node-id"));
 305        node = qdict_get_int(props, "node-id");
 306        g_assert(qdict_haskey(props, "socket-id"));
 307        socket = qdict_get_int(props, "socket-id");
 308
 309        if (socket == 0) {
 310            g_assert_cmpint(node, ==, 1);
 311        } else if (socket == 1) {
 312            g_assert_cmpint(node, ==, 0);
 313        } else {
 314            g_assert(false);
 315        }
 316        qobject_unref(e);
 317    }
 318    qobject_unref(resp);
 319
 320    qtest_quit(qs);
 321}
 322
 323static void pc_hmat_build_cfg(const void *data)
 324{
 325    QTestState *qs;
 326    g_autofree char *cli = NULL;
 327
 328    cli = make_cli(data, "-nodefaults --preconfig -machine hmat=on "
 329                         "-machine smp.cpus=2,smp.sockets=2 "
 330                         "-m 128M,slots=2,maxmem=1G "
 331                         "-object memory-backend-ram,size=64M,id=m0 "
 332                         "-object memory-backend-ram,size=64M,id=m1 "
 333                         "-numa node,nodeid=0,memdev=m0 "
 334                         "-numa node,nodeid=1,memdev=m1,initiator=0 "
 335                         "-numa cpu,node-id=0,socket-id=0 "
 336                         "-numa cpu,node-id=0,socket-id=1");
 337    qs = qtest_init(cli);
 338
 339    /* Fail: Initiator should be less than the number of nodes */
 340    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 341        " 'arguments': { 'type': 'hmat-lb', 'initiator': 2, 'target': 0,"
 342        " 'hierarchy': \"memory\", 'data-type': \"access-latency\" } }")));
 343
 344    /* Fail: Target should be less than the number of nodes */
 345    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 346        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 2,"
 347        " 'hierarchy': \"memory\", 'data-type': \"access-latency\" } }")));
 348
 349    /* Fail: Initiator should contain cpu */
 350    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 351        " 'arguments': { 'type': 'hmat-lb', 'initiator': 1, 'target': 0,"
 352        " 'hierarchy': \"memory\", 'data-type': \"access-latency\" } }")));
 353
 354    /* Fail: Data-type mismatch */
 355    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 356        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 357        " 'hierarchy': \"memory\", 'data-type': \"write-latency\","
 358        " 'bandwidth': 524288000 } }")));
 359    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 360        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 361        " 'hierarchy': \"memory\", 'data-type': \"read-bandwidth\","
 362        " 'latency': 5 } }")));
 363
 364    /* Fail: Bandwidth should be 1MB (1048576) aligned */
 365    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 366        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 367        " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\","
 368        " 'bandwidth': 1048575 } }")));
 369
 370    /* Configuring HMAT bandwidth and latency details */
 371    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 372        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 373        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 374        " 'latency': 1 } }")));    /* 1 ns */
 375    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 376        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 377        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 378        " 'latency': 5 } }")));    /* Fail: Duplicate configuration */
 379    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 380        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 381        " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\","
 382        " 'bandwidth': 68717379584 } }")));    /* 65534 MB/s */
 383    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 384        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1,"
 385        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 386        " 'latency': 65534 } }")));    /* 65534 ns */
 387    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 388        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1,"
 389        " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\","
 390        " 'bandwidth': 34358689792 } }")));    /* 32767 MB/s */
 391
 392    /* Fail: node_id should be less than the number of nodes */
 393    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 394        " 'arguments': { 'type': 'hmat-cache', 'node-id': 2, 'size': 10240,"
 395        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 396        " 'line': 8 } }")));
 397
 398    /* Fail: level should be less than HMAT_LB_LEVELS (4) */
 399    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 400        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 401        " 'level': 4, 'associativity': \"direct\", 'policy': \"write-back\","
 402        " 'line': 8 } }")));
 403
 404    /* Fail: associativity option should be 'none', if level is 0 */
 405    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 406        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 407        " 'level': 0, 'associativity': \"direct\", 'policy': \"none\","
 408        " 'line': 0 } }")));
 409    /* Fail: policy option should be 'none', if level is 0 */
 410    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 411        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 412        " 'level': 0, 'associativity': \"none\", 'policy': \"write-back\","
 413        " 'line': 0 } }")));
 414    /* Fail: line option should be 0, if level is 0 */
 415    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 416        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 417        " 'level': 0, 'associativity': \"none\", 'policy': \"none\","
 418        " 'line': 8 } }")));
 419
 420    /* Configuring HMAT memory side cache attributes */
 421    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 422        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 423        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 424        " 'line': 8 } }")));
 425    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 426        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 427        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 428        " 'line': 8 } }")));    /* Fail: Duplicate configuration */
 429    /* Fail: The size of level 2 size should be small than level 1 */
 430    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 431        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 432        " 'level': 2, 'associativity': \"direct\", 'policy': \"write-back\","
 433        " 'line': 8 } }")));
 434    /* Fail: The size of level 0 size should be larger than level 1 */
 435    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 436        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 437        " 'level': 0, 'associativity': \"direct\", 'policy': \"write-back\","
 438        " 'line': 8 } }")));
 439    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 440        " 'arguments': { 'type': 'hmat-cache', 'node-id': 1, 'size': 10240,"
 441        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 442        " 'line': 8 } }")));
 443
 444    /* let machine initialization to complete and run */
 445    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs,
 446        "{ 'execute': 'x-exit-preconfig' }")));
 447    qtest_qmp_eventwait(qs, "RESUME");
 448
 449    qtest_quit(qs);
 450}
 451
 452static void pc_hmat_off_cfg(const void *data)
 453{
 454    QTestState *qs;
 455    g_autofree char *cli = NULL;
 456
 457    cli = make_cli(data, "-nodefaults --preconfig "
 458                         "-machine smp.cpus=2,smp.sockets=2 "
 459                         "-m 128M,slots=2,maxmem=1G "
 460                         "-object memory-backend-ram,size=64M,id=m0,prealloc=y "
 461                         "-object memory-backend-ram,size=64M,id=m1 "
 462                         "-numa node,nodeid=0,memdev=m0");
 463    qs = qtest_init(cli);
 464
 465    /*
 466     * Fail: Enable HMAT with -machine hmat=on
 467     * before using any of hmat specific options
 468     */
 469    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 470        " 'arguments': { 'type': 'node', 'nodeid': 1, 'memdev': \"m1\","
 471        " 'initiator': 0 } }")));
 472    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 473        " 'arguments': { 'type': 'node', 'nodeid': 1, 'memdev': \"m1\" } }")));
 474    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 475        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 476        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 477        " 'latency': 1 } }")));
 478    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 479        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 480        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 481        " 'line': 8 } }")));
 482
 483    /* let machine initialization to complete and run */
 484    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs,
 485        "{ 'execute': 'x-exit-preconfig' }")));
 486    qtest_qmp_eventwait(qs, "RESUME");
 487
 488    qtest_quit(qs);
 489}
 490
 491static void pc_hmat_erange_cfg(const void *data)
 492{
 493    QTestState *qs;
 494    g_autofree char *cli = NULL;
 495
 496    cli = make_cli(data, "-nodefaults --preconfig -machine hmat=on "
 497                         "-machine smp.cpus=2,smp.sockets=2 "
 498                         "-m 128M,slots=2,maxmem=1G "
 499                         "-object memory-backend-ram,size=64M,id=m0 "
 500                         "-object memory-backend-ram,size=64M,id=m1 "
 501                         "-numa node,nodeid=0,memdev=m0 "
 502                         "-numa node,nodeid=1,memdev=m1,initiator=0 "
 503                         "-numa cpu,node-id=0,socket-id=0 "
 504                         "-numa cpu,node-id=0,socket-id=1");
 505    qs = qtest_init(cli);
 506
 507    /* Can't store the compressed latency */
 508    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 509        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 510        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 511        " 'latency': 1 } }")));    /* 1 ns */
 512    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 513        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1,"
 514        " 'hierarchy': \"memory\", 'data-type': \"access-latency\","
 515        " 'latency': 65535 } }")));    /* 65535 ns */
 516
 517    /* Test the 0 input (bandwidth not provided) */
 518    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 519        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 0,"
 520        " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\","
 521        " 'bandwidth': 0 } }")));    /* 0 MB/s */
 522    /* Fail: bandwidth should be provided before memory side cache attributes */
 523    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 524        " 'arguments': { 'type': 'hmat-cache', 'node-id': 0, 'size': 10240,"
 525        " 'level': 1, 'associativity': \"direct\", 'policy': \"write-back\","
 526        " 'line': 8 } }")));
 527
 528    /* Can't store the compressed bandwidth */
 529    g_assert_true(qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'set-numa-node',"
 530        " 'arguments': { 'type': 'hmat-lb', 'initiator': 0, 'target': 1,"
 531        " 'hierarchy': \"memory\", 'data-type': \"access-bandwidth\","
 532        " 'bandwidth': 68718428160 } }")));    /* 65535 MB/s */
 533
 534    /* let machine initialization to complete and run */
 535    g_assert_false(qmp_rsp_is_err(qtest_qmp(qs,
 536        "{ 'execute': 'x-exit-preconfig' }")));
 537    qtest_qmp_eventwait(qs, "RESUME");
 538
 539    qtest_quit(qs);
 540}
 541
 542int main(int argc, char **argv)
 543{
 544    g_autoptr(GString) args = g_string_new(NULL);
 545    const char *arch = qtest_get_arch();
 546
 547    if (g_str_equal(arch, "ppc64")) {
 548        g_string_append(args, " -object memory-backend-ram,id=ram,size=512M");
 549    } else {
 550        g_string_append(args, " -object memory-backend-ram,id=ram,size=128M");
 551    }
 552
 553    if (g_str_equal(arch, "aarch64")) {
 554        g_string_append(args, " -machine virt");
 555    }
 556
 557    g_test_init(&argc, &argv, NULL);
 558
 559    qtest_add_data_func("/numa/mon/cpus/default", args, test_def_cpu_split);
 560    qtest_add_data_func("/numa/mon/cpus/explicit", args, test_mon_explicit);
 561    qtest_add_data_func("/numa/mon/cpus/partial", args, test_mon_partial);
 562    qtest_add_data_func("/numa/qmp/cpus/query-cpus", args, test_query_cpus);
 563
 564    if (!strcmp(arch, "i386") || !strcmp(arch, "x86_64")) {
 565        qtest_add_data_func("/numa/pc/cpu/explicit", args, pc_numa_cpu);
 566        qtest_add_data_func("/numa/pc/dynamic/cpu", args, pc_dynamic_cpu_cfg);
 567        qtest_add_data_func("/numa/pc/hmat/build", args, pc_hmat_build_cfg);
 568        qtest_add_data_func("/numa/pc/hmat/off", args, pc_hmat_off_cfg);
 569        qtest_add_data_func("/numa/pc/hmat/erange", args, pc_hmat_erange_cfg);
 570    }
 571
 572    if (!strcmp(arch, "ppc64")) {
 573        qtest_add_data_func("/numa/spapr/cpu/explicit", args, spapr_numa_cpu);
 574    }
 575
 576    if (!strcmp(arch, "aarch64")) {
 577        qtest_add_data_func("/numa/aarch64/cpu/explicit", args,
 578                            aarch64_numa_cpu);
 579    }
 580
 581    return g_test_run();
 582}
 583