]>
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" | |
14 | ||
15 | static char *make_cli(const char *generic_cli, const char *test_cli) | |
16 | { | |
17 | return g_strdup_printf("%s %s", generic_cli ? generic_cli : "", test_cli); | |
18 | } | |
19 | ||
20 | static char *hmp_info_numa(void) | |
21 | { | |
22 | QDict *resp; | |
23 | char *s; | |
24 | ||
25 | resp = qmp("{ 'execute': 'human-monitor-command', 'arguments': " | |
26 | "{ 'command-line': 'info numa '} }"); | |
27 | g_assert(resp); | |
28 | g_assert(qdict_haskey(resp, "return")); | |
29 | s = g_strdup(qdict_get_str(resp, "return")); | |
30 | g_assert(s); | |
31 | QDECREF(resp); | |
32 | return s; | |
33 | } | |
34 | ||
35 | static void test_mon_explicit(const void *data) | |
36 | { | |
37 | char *s; | |
38 | char *cli; | |
39 | ||
40 | cli = make_cli(data, "-smp 8 " | |
41 | "-numa node,nodeid=0,cpus=0-3 " | |
42 | "-numa node,nodeid=1,cpus=4-7 "); | |
43 | qtest_start(cli); | |
44 | ||
45 | s = hmp_info_numa(); | |
46 | g_assert(strstr(s, "node 0 cpus: 0 1 2 3")); | |
47 | g_assert(strstr(s, "node 1 cpus: 4 5 6 7")); | |
48 | g_free(s); | |
49 | ||
50 | qtest_end(); | |
51 | g_free(cli); | |
52 | } | |
53 | ||
54 | static void test_mon_default(const void *data) | |
55 | { | |
56 | char *s; | |
57 | char *cli; | |
58 | ||
59 | cli = make_cli(data, "-smp 8 -numa node -numa node"); | |
60 | qtest_start(cli); | |
61 | ||
62 | s = hmp_info_numa(); | |
63 | g_assert(strstr(s, "node 0 cpus: 0 2 4 6")); | |
64 | g_assert(strstr(s, "node 1 cpus: 1 3 5 7")); | |
65 | g_free(s); | |
66 | ||
67 | qtest_end(); | |
68 | g_free(cli); | |
69 | } | |
70 | ||
71 | static void test_mon_partial(const void *data) | |
72 | { | |
73 | char *s; | |
74 | char *cli; | |
75 | ||
76 | cli = make_cli(data, "-smp 8 " | |
77 | "-numa node,nodeid=0,cpus=0-1 " | |
78 | "-numa node,nodeid=1,cpus=4-5 "); | |
79 | qtest_start(cli); | |
80 | ||
81 | s = hmp_info_numa(); | |
82 | g_assert(strstr(s, "node 0 cpus: 0 1 2 3 6 7")); | |
83 | g_assert(strstr(s, "node 1 cpus: 4 5")); | |
84 | g_free(s); | |
85 | ||
86 | qtest_end(); | |
87 | g_free(cli); | |
88 | } | |
89 | ||
6accfb78 IM |
90 | static QList *get_cpus(QDict **resp) |
91 | { | |
92 | *resp = qmp("{ 'execute': 'query-cpus' }"); | |
93 | g_assert(*resp); | |
94 | g_assert(qdict_haskey(*resp, "return")); | |
5e39d89d | 95 | return qdict_get_qlist(*resp, "return"); |
6accfb78 IM |
96 | } |
97 | ||
98 | static void test_query_cpus(const void *data) | |
99 | { | |
100 | char *cli; | |
101 | QDict *resp; | |
102 | QList *cpus; | |
5e39d89d | 103 | QObject *e; |
6accfb78 IM |
104 | |
105 | cli = make_cli(data, "-smp 8 -numa node,cpus=0-3 -numa node,cpus=4-7"); | |
106 | qtest_start(cli); | |
107 | cpus = get_cpus(&resp); | |
108 | g_assert(cpus); | |
109 | ||
110 | while ((e = qlist_pop(cpus))) { | |
111 | QDict *cpu, *props; | |
112 | int64_t cpu_idx, node; | |
113 | ||
114 | cpu = qobject_to_qdict(e); | |
115 | g_assert(qdict_haskey(cpu, "CPU")); | |
116 | g_assert(qdict_haskey(cpu, "props")); | |
117 | ||
118 | cpu_idx = qdict_get_int(cpu, "CPU"); | |
119 | props = qdict_get_qdict(cpu, "props"); | |
120 | g_assert(qdict_haskey(props, "node-id")); | |
121 | node = qdict_get_int(props, "node-id"); | |
122 | if (cpu_idx >= 0 && cpu_idx < 4) { | |
123 | g_assert_cmpint(node, ==, 0); | |
124 | } else { | |
125 | g_assert_cmpint(node, ==, 1); | |
126 | } | |
5e39d89d | 127 | qobject_decref(e); |
6accfb78 IM |
128 | } |
129 | ||
130 | QDECREF(resp); | |
131 | qtest_end(); | |
132 | g_free(cli); | |
133 | } | |
134 | ||
2941020a IM |
135 | static void pc_numa_cpu(const void *data) |
136 | { | |
137 | char *cli; | |
138 | QDict *resp; | |
139 | QList *cpus; | |
5e39d89d | 140 | QObject *e; |
2941020a IM |
141 | |
142 | cli = make_cli(data, "-cpu pentium -smp 8,sockets=2,cores=2,threads=2 " | |
143 | "-numa node,nodeid=0 -numa node,nodeid=1 " | |
144 | "-numa cpu,node-id=1,socket-id=0 " | |
145 | "-numa cpu,node-id=0,socket-id=1,core-id=0 " | |
146 | "-numa cpu,node-id=0,socket-id=1,core-id=1,thread-id=0 " | |
147 | "-numa cpu,node-id=1,socket-id=1,core-id=1,thread-id=1"); | |
148 | qtest_start(cli); | |
149 | cpus = get_cpus(&resp); | |
150 | g_assert(cpus); | |
151 | ||
152 | while ((e = qlist_pop(cpus))) { | |
153 | QDict *cpu, *props; | |
154 | int64_t socket, core, thread, node; | |
155 | ||
156 | cpu = qobject_to_qdict(e); | |
157 | g_assert(qdict_haskey(cpu, "props")); | |
158 | props = qdict_get_qdict(cpu, "props"); | |
159 | ||
160 | g_assert(qdict_haskey(props, "node-id")); | |
161 | node = qdict_get_int(props, "node-id"); | |
162 | g_assert(qdict_haskey(props, "socket-id")); | |
163 | socket = qdict_get_int(props, "socket-id"); | |
164 | g_assert(qdict_haskey(props, "core-id")); | |
165 | core = qdict_get_int(props, "core-id"); | |
166 | g_assert(qdict_haskey(props, "thread-id")); | |
167 | thread = qdict_get_int(props, "thread-id"); | |
168 | ||
169 | if (socket == 0) { | |
170 | g_assert_cmpint(node, ==, 1); | |
171 | } else if (socket == 1 && core == 0) { | |
172 | g_assert_cmpint(node, ==, 0); | |
173 | } else if (socket == 1 && core == 1 && thread == 0) { | |
174 | g_assert_cmpint(node, ==, 0); | |
175 | } else if (socket == 1 && core == 1 && thread == 1) { | |
176 | g_assert_cmpint(node, ==, 1); | |
177 | } else { | |
178 | g_assert(false); | |
179 | } | |
5e39d89d | 180 | qobject_decref(e); |
2941020a IM |
181 | } |
182 | ||
183 | QDECREF(resp); | |
184 | qtest_end(); | |
185 | g_free(cli); | |
186 | } | |
187 | ||
188 | static void spapr_numa_cpu(const void *data) | |
189 | { | |
190 | char *cli; | |
191 | QDict *resp; | |
192 | QList *cpus; | |
5e39d89d | 193 | QObject *e; |
2941020a IM |
194 | |
195 | cli = make_cli(data, "-smp 4,cores=4 " | |
196 | "-numa node,nodeid=0 -numa node,nodeid=1 " | |
197 | "-numa cpu,node-id=0,core-id=0 " | |
198 | "-numa cpu,node-id=0,core-id=1 " | |
199 | "-numa cpu,node-id=0,core-id=2 " | |
200 | "-numa cpu,node-id=1,core-id=3"); | |
201 | qtest_start(cli); | |
202 | cpus = get_cpus(&resp); | |
203 | g_assert(cpus); | |
204 | ||
205 | while ((e = qlist_pop(cpus))) { | |
206 | QDict *cpu, *props; | |
207 | int64_t core, node; | |
208 | ||
209 | cpu = qobject_to_qdict(e); | |
210 | g_assert(qdict_haskey(cpu, "props")); | |
211 | props = qdict_get_qdict(cpu, "props"); | |
212 | ||
213 | g_assert(qdict_haskey(props, "node-id")); | |
214 | node = qdict_get_int(props, "node-id"); | |
215 | g_assert(qdict_haskey(props, "core-id")); | |
216 | core = qdict_get_int(props, "core-id"); | |
217 | ||
218 | if (core >= 0 && core < 3) { | |
219 | g_assert_cmpint(node, ==, 0); | |
220 | } else if (core == 3) { | |
221 | g_assert_cmpint(node, ==, 1); | |
222 | } else { | |
223 | g_assert(false); | |
224 | } | |
5e39d89d | 225 | qobject_decref(e); |
2941020a IM |
226 | } |
227 | ||
228 | QDECREF(resp); | |
229 | qtest_end(); | |
230 | g_free(cli); | |
231 | } | |
232 | ||
233 | static void aarch64_numa_cpu(const void *data) | |
234 | { | |
235 | char *cli; | |
236 | QDict *resp; | |
237 | QList *cpus; | |
5e39d89d | 238 | QObject *e; |
2941020a IM |
239 | |
240 | cli = make_cli(data, "-smp 2 " | |
241 | "-numa node,nodeid=0 -numa node,nodeid=1 " | |
242 | "-numa cpu,node-id=1,thread-id=0 " | |
243 | "-numa cpu,node-id=0,thread-id=1"); | |
244 | qtest_start(cli); | |
245 | cpus = get_cpus(&resp); | |
246 | g_assert(cpus); | |
247 | ||
248 | while ((e = qlist_pop(cpus))) { | |
249 | QDict *cpu, *props; | |
250 | int64_t thread, node; | |
251 | ||
252 | cpu = qobject_to_qdict(e); | |
253 | g_assert(qdict_haskey(cpu, "props")); | |
254 | props = qdict_get_qdict(cpu, "props"); | |
255 | ||
256 | g_assert(qdict_haskey(props, "node-id")); | |
257 | node = qdict_get_int(props, "node-id"); | |
258 | g_assert(qdict_haskey(props, "thread-id")); | |
259 | thread = qdict_get_int(props, "thread-id"); | |
260 | ||
261 | if (thread == 0) { | |
262 | g_assert_cmpint(node, ==, 1); | |
263 | } else if (thread == 1) { | |
264 | g_assert_cmpint(node, ==, 0); | |
265 | } else { | |
266 | g_assert(false); | |
267 | } | |
5e39d89d | 268 | qobject_decref(e); |
2941020a IM |
269 | } |
270 | ||
271 | QDECREF(resp); | |
272 | qtest_end(); | |
273 | g_free(cli); | |
274 | } | |
275 | ||
63baf8bf IM |
276 | int main(int argc, char **argv) |
277 | { | |
278 | const char *args = NULL; | |
279 | const char *arch = qtest_get_arch(); | |
280 | ||
281 | if (strcmp(arch, "aarch64") == 0) { | |
282 | args = "-machine virt"; | |
283 | } | |
284 | ||
285 | g_test_init(&argc, &argv, NULL); | |
286 | ||
287 | qtest_add_data_func("/numa/mon/default", args, test_mon_default); | |
288 | qtest_add_data_func("/numa/mon/cpus/explicit", args, test_mon_explicit); | |
289 | qtest_add_data_func("/numa/mon/cpus/partial", args, test_mon_partial); | |
6accfb78 | 290 | qtest_add_data_func("/numa/qmp/cpus/query-cpus", args, test_query_cpus); |
63baf8bf | 291 | |
2941020a IM |
292 | if (!strcmp(arch, "i386") || !strcmp(arch, "x86_64")) { |
293 | qtest_add_data_func("/numa/pc/cpu/explicit", args, pc_numa_cpu); | |
294 | } | |
295 | ||
296 | if (!strcmp(arch, "ppc64")) { | |
297 | qtest_add_data_func("/numa/spapr/cpu/explicit", args, spapr_numa_cpu); | |
298 | } | |
299 | ||
300 | if (!strcmp(arch, "aarch64")) { | |
301 | qtest_add_data_func("/numa/aarch64/cpu/explicit", args, | |
302 | aarch64_numa_cpu); | |
303 | } | |
304 | ||
63baf8bf IM |
305 | return g_test_run(); |
306 | } |