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