]>
Commit | Line | Data |
---|---|---|
63baf8bf IM |
1 | /* |
2 | * NUMA configuration test cases | |
3 | * | |
4 | * Copyright (c) 2017 Red Hat Inc. | |
5 | * Authors: | |
6 | * Igor Mammedov <[email protected]> | |
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" | |
452fcdbc | 14 | #include "qapi/qmp/qdict.h" |
47e6b297 | 15 | #include "qapi/qmp/qlist.h" |
63baf8bf IM |
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 | ||
63baf8bf IM |
22 | static void test_mon_explicit(const void *data) |
23 | { | |
24 | char *s; | |
25 | char *cli; | |
3d5e7087 | 26 | QTestState *qts; |
63baf8bf IM |
27 | |
28 | cli = make_cli(data, "-smp 8 " | |
29 | "-numa node,nodeid=0,cpus=0-3 " | |
30 | "-numa node,nodeid=1,cpus=4-7 "); | |
3d5e7087 | 31 | qts = qtest_init(cli); |
63baf8bf | 32 | |
3d5e7087 | 33 | s = qtest_hmp(qts, "info numa"); |
63baf8bf IM |
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 | ||
3d5e7087 | 38 | qtest_quit(qts); |
63baf8bf IM |
39 | g_free(cli); |
40 | } | |
41 | ||
42 | static void test_mon_default(const void *data) | |
43 | { | |
44 | char *s; | |
45 | char *cli; | |
3d5e7087 | 46 | QTestState *qts; |
63baf8bf IM |
47 | |
48 | cli = make_cli(data, "-smp 8 -numa node -numa node"); | |
3d5e7087 | 49 | qts = qtest_init(cli); |
63baf8bf | 50 | |
3d5e7087 | 51 | s = qtest_hmp(qts, "info numa"); |
63baf8bf IM |
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 | ||
3d5e7087 | 56 | qtest_quit(qts); |
63baf8bf IM |
57 | g_free(cli); |
58 | } | |
59 | ||
60 | static void test_mon_partial(const void *data) | |
61 | { | |
62 | char *s; | |
63 | char *cli; | |
3d5e7087 | 64 | QTestState *qts; |
63baf8bf IM |
65 | |
66 | cli = make_cli(data, "-smp 8 " | |
67 | "-numa node,nodeid=0,cpus=0-1 " | |
68 | "-numa node,nodeid=1,cpus=4-5 "); | |
3d5e7087 | 69 | qts = qtest_init(cli); |
63baf8bf | 70 | |
3d5e7087 | 71 | s = qtest_hmp(qts, "info numa"); |
63baf8bf IM |
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 | ||
3d5e7087 | 76 | qtest_quit(qts); |
63baf8bf IM |
77 | g_free(cli); |
78 | } | |
79 | ||
3d5e7087 | 80 | static QList *get_cpus(QTestState *qts, QDict **resp) |
6accfb78 | 81 | { |
3d5e7087 | 82 | *resp = qtest_qmp(qts, "{ 'execute': 'query-cpus' }"); |
6accfb78 IM |
83 | g_assert(*resp); |
84 | g_assert(qdict_haskey(*resp, "return")); | |
5e39d89d | 85 | return qdict_get_qlist(*resp, "return"); |
6accfb78 IM |
86 | } |
87 | ||
88 | static void test_query_cpus(const void *data) | |
89 | { | |
90 | char *cli; | |
91 | QDict *resp; | |
92 | QList *cpus; | |
5e39d89d | 93 | QObject *e; |
3d5e7087 | 94 | QTestState *qts; |
6accfb78 IM |
95 | |
96 | cli = make_cli(data, "-smp 8 -numa node,cpus=0-3 -numa node,cpus=4-7"); | |
3d5e7087 TH |
97 | qts = qtest_init(cli); |
98 | cpus = get_cpus(qts, &resp); | |
6accfb78 IM |
99 | g_assert(cpus); |
100 | ||
101 | while ((e = qlist_pop(cpus))) { | |
102 | QDict *cpu, *props; | |
103 | int64_t cpu_idx, node; | |
104 | ||
7dc847eb | 105 | cpu = qobject_to(QDict, e); |
6accfb78 IM |
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 | } | |
cb3e7f08 | 118 | qobject_unref(e); |
6accfb78 IM |
119 | } |
120 | ||
cb3e7f08 | 121 | qobject_unref(resp); |
3d5e7087 | 122 | qtest_quit(qts); |
6accfb78 IM |
123 | g_free(cli); |
124 | } | |
125 | ||
2941020a IM |
126 | static void pc_numa_cpu(const void *data) |
127 | { | |
128 | char *cli; | |
129 | QDict *resp; | |
130 | QList *cpus; | |
5e39d89d | 131 | QObject *e; |
3d5e7087 | 132 | QTestState *qts; |
2941020a IM |
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"); | |
3d5e7087 TH |
140 | qts = qtest_init(cli); |
141 | cpus = get_cpus(qts, &resp); | |
2941020a IM |
142 | g_assert(cpus); |
143 | ||
144 | while ((e = qlist_pop(cpus))) { | |
145 | QDict *cpu, *props; | |
146 | int64_t socket, core, thread, node; | |
147 | ||
7dc847eb | 148 | cpu = qobject_to(QDict, e); |
2941020a IM |
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 | } | |
cb3e7f08 | 172 | qobject_unref(e); |
2941020a IM |
173 | } |
174 | ||
cb3e7f08 | 175 | qobject_unref(resp); |
3d5e7087 | 176 | qtest_quit(qts); |
2941020a IM |
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; | |
5e39d89d | 185 | QObject *e; |
3d5e7087 | 186 | QTestState *qts; |
2941020a IM |
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"); | |
3d5e7087 TH |
194 | qts = qtest_init(cli); |
195 | cpus = get_cpus(qts, &resp); | |
2941020a IM |
196 | g_assert(cpus); |
197 | ||
198 | while ((e = qlist_pop(cpus))) { | |
199 | QDict *cpu, *props; | |
200 | int64_t core, node; | |
201 | ||
7dc847eb | 202 | cpu = qobject_to(QDict, e); |
2941020a IM |
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 | } | |
cb3e7f08 | 218 | qobject_unref(e); |
2941020a IM |
219 | } |
220 | ||
cb3e7f08 | 221 | qobject_unref(resp); |
3d5e7087 | 222 | qtest_quit(qts); |
2941020a IM |
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; | |
5e39d89d | 231 | QObject *e; |
3d5e7087 | 232 | QTestState *qts; |
2941020a IM |
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"); | |
3d5e7087 TH |
238 | qts = qtest_init(cli); |
239 | cpus = get_cpus(qts, &resp); | |
2941020a IM |
240 | g_assert(cpus); |
241 | ||
242 | while ((e = qlist_pop(cpus))) { | |
243 | QDict *cpu, *props; | |
244 | int64_t thread, node; | |
245 | ||
7dc847eb | 246 | cpu = qobject_to(QDict, e); |
2941020a IM |
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 | } | |
cb3e7f08 | 262 | qobject_unref(e); |
2941020a IM |
263 | } |
264 | ||
cb3e7f08 | 265 | qobject_unref(resp); |
3d5e7087 | 266 | qtest_quit(qts); |
2941020a IM |
267 | g_free(cli); |
268 | } | |
269 | ||
c35665e1 IM |
270 | static void pc_dynamic_cpu_cfg(const void *data) |
271 | { | |
272 | QObject *e; | |
273 | QDict *resp; | |
274 | QList *cpus; | |
275 | QTestState *qs; | |
276 | ||
88b988c8 MA |
277 | qs = qtest_initf("%s -nodefaults --preconfig -smp 2", |
278 | data ? (char *)data : ""); | |
c35665e1 IM |
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 */ | |
361ac948 | 295 | g_assert(!qmp_rsp_is_err(qtest_qmp(qs, "{ 'execute': 'x-exit-preconfig' }"))); |
c35665e1 IM |
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 | ||
63baf8bf IM |
330 | int main(int argc, char **argv) |
331 | { | |
332 | const char *args = NULL; | |
333 | const char *arch = qtest_get_arch(); | |
334 | ||
335 | if (strcmp(arch, "aarch64") == 0) { | |
336 | args = "-machine virt"; | |
337 | } | |
338 | ||
339 | g_test_init(&argc, &argv, NULL); | |
340 | ||
341 | qtest_add_data_func("/numa/mon/default", args, test_mon_default); | |
342 | qtest_add_data_func("/numa/mon/cpus/explicit", args, test_mon_explicit); | |
343 | qtest_add_data_func("/numa/mon/cpus/partial", args, test_mon_partial); | |
6accfb78 | 344 | qtest_add_data_func("/numa/qmp/cpus/query-cpus", args, test_query_cpus); |
63baf8bf | 345 | |
2941020a IM |
346 | if (!strcmp(arch, "i386") || !strcmp(arch, "x86_64")) { |
347 | qtest_add_data_func("/numa/pc/cpu/explicit", args, pc_numa_cpu); | |
c35665e1 | 348 | qtest_add_data_func("/numa/pc/dynamic/cpu", args, pc_dynamic_cpu_cfg); |
2941020a IM |
349 | } |
350 | ||
351 | if (!strcmp(arch, "ppc64")) { | |
352 | qtest_add_data_func("/numa/spapr/cpu/explicit", args, spapr_numa_cpu); | |
353 | } | |
354 | ||
355 | if (!strcmp(arch, "aarch64")) { | |
356 | qtest_add_data_func("/numa/aarch64/cpu/explicit", args, | |
357 | aarch64_numa_cpu); | |
358 | } | |
359 | ||
63baf8bf IM |
360 | return g_test_run(); |
361 | } |