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