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