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