2 * SMP parsing unit-tests
4 * Copyright (c) 2021 Huawei Technologies Co., Ltd
7 * Yanan Wang <wangyanan55@huawei.com>
9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10 * See the COPYING.LIB file in the top-level directory.
13 #include "qemu/osdep.h"
14 #include "qom/object.h"
15 #include "qemu/module.h"
16 #include "qapi/error.h"
18 #include "hw/boards.h"
23 #define MIN_CPUS 1 /* set the min CPUs supported by the machine as 1 */
24 #define MAX_CPUS 512 /* set the max CPUs supported by the machine as 512 */
26 #define SMP_MACHINE_NAME "TEST-SMP"
29 * Used to define the generic 3-level CPU topology hierarchy
30 * -sockets/cores/threads
32 #define SMP_CONFIG_GENERIC(ha, a, hb, b, hc, c, hd, d, he, e) \
34 .has_cpus = ha, .cpus = a, \
35 .has_sockets = hb, .sockets = b, \
36 .has_cores = hc, .cores = c, \
37 .has_threads = hd, .threads = d, \
38 .has_maxcpus = he, .maxcpus = e, \
41 #define CPU_TOPOLOGY_GENERIC(a, b, c, d, e) \
51 * Currently a 4-level topology hierarchy is supported on PC machines
52 * -sockets/dies/cores/threads
54 #define SMP_CONFIG_WITH_DIES(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \
56 .has_cpus = ha, .cpus = a, \
57 .has_sockets = hb, .sockets = b, \
58 .has_dies = hc, .dies = c, \
59 .has_cores = hd, .cores = d, \
60 .has_threads = he, .threads = e, \
61 .has_maxcpus = hf, .maxcpus = f, \
65 * @config - the given SMP configuration
66 * @expect_prefer_sockets - the expected parsing result for the
67 * valid configuration, when sockets are preferred over cores
68 * @expect_prefer_cores - the expected parsing result for the
69 * valid configuration, when cores are preferred over sockets
70 * @expect_error - the expected error report when the given
71 * configuration is invalid
73 typedef struct SMPTestData
{
74 SMPConfiguration config
;
75 CpuTopology expect_prefer_sockets
;
76 CpuTopology expect_prefer_cores
;
77 const char *expect_error
;
81 * List all the possible valid sub-collections of the generic 5
82 * topology parameters (i.e. cpus/maxcpus/sockets/cores/threads),
83 * then test the automatic calculation algorithm of the missing
84 * values in the parser.
86 static const struct SMPTestData data_generic_valid
[] = {
88 /* config: no configuration provided
89 * expect: cpus=1,sockets=1,cores=1,threads=1,maxcpus=1 */
90 .config
= SMP_CONFIG_GENERIC(F
, 0, F
, 0, F
, 0, F
, 0, F
, 0),
91 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(1, 1, 1, 1, 1),
92 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(1, 1, 1, 1, 1),
95 * prefer_sockets: cpus=8,sockets=8,cores=1,threads=1,maxcpus=8
96 * prefer_cores: cpus=8,sockets=1,cores=8,threads=1,maxcpus=8 */
97 .config
= SMP_CONFIG_GENERIC(T
, 8, F
, 0, F
, 0, F
, 0, F
, 0),
98 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 8, 1, 1, 8),
99 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 1, 8, 1, 8),
101 /* config: -smp sockets=2
102 * expect: cpus=2,sockets=2,cores=1,threads=1,maxcpus=2 */
103 .config
= SMP_CONFIG_GENERIC(F
, 0, T
, 2, F
, 0, F
, 0, F
, 0),
104 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(2, 2, 1, 1, 2),
105 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(2, 2, 1, 1, 2),
107 /* config: -smp cores=4
108 * expect: cpus=4,sockets=1,cores=4,threads=1,maxcpus=4 */
109 .config
= SMP_CONFIG_GENERIC(F
, 0, F
, 0, T
, 4, F
, 0, F
, 0),
110 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(4, 1, 4, 1, 4),
111 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(4, 1, 4, 1, 4),
113 /* config: -smp threads=2
114 * expect: cpus=2,sockets=1,cores=1,threads=2,maxcpus=2 */
115 .config
= SMP_CONFIG_GENERIC(F
, 0, F
, 0, F
, 0, T
, 2, F
, 0),
116 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(2, 1, 1, 2, 2),
117 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(2, 1, 1, 2, 2),
119 /* config: -smp maxcpus=16
120 * prefer_sockets: cpus=16,sockets=16,cores=1,threads=1,maxcpus=16
121 * prefer_cores: cpus=16,sockets=1,cores=16,threads=1,maxcpus=16 */
122 .config
= SMP_CONFIG_GENERIC(F
, 0, F
, 0, F
, 0, F
, 0, T
, 16),
123 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(16, 16, 1, 1, 16),
124 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(16, 1, 16, 1, 16),
126 /* config: -smp 8,sockets=2
127 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
128 .config
= SMP_CONFIG_GENERIC(T
, 8, T
, 2, F
, 0, F
, 0, F
, 0),
129 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
130 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
132 /* config: -smp 8,cores=4
133 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
134 .config
= SMP_CONFIG_GENERIC(T
, 8, F
, 0, T
, 4, F
, 0, F
, 0),
135 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
136 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
138 /* config: -smp 8,threads=2
139 * prefer_sockets: cpus=8,sockets=4,cores=1,threads=2,maxcpus=8
140 * prefer_cores: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
141 .config
= SMP_CONFIG_GENERIC(T
, 8, F
, 0, F
, 0, T
, 2, F
, 0),
142 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 4, 1, 2, 8),
143 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
145 /* config: -smp 8,maxcpus=16
146 * prefer_sockets: cpus=8,sockets=16,cores=1,threads=1,maxcpus=16
147 * prefer_cores: cpus=8,sockets=1,cores=16,threads=1,maxcpus=16 */
148 .config
= SMP_CONFIG_GENERIC(T
, 8, F
, 0, F
, 0, F
, 0, T
, 16),
149 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 16, 1, 1, 16),
150 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 1, 16, 1, 16),
152 /* config: -smp sockets=2,cores=4
153 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
154 .config
= SMP_CONFIG_GENERIC(F
, 0, T
, 2, T
, 4, F
, 0, F
, 0),
155 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
156 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
158 /* config: -smp sockets=2,threads=2
159 * expect: cpus=4,sockets=2,cores=1,threads=2,maxcpus=4 */
160 .config
= SMP_CONFIG_GENERIC(F
, 0, T
, 2, F
, 0, T
, 2, F
, 0),
161 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(4, 2, 1, 2, 4),
162 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(4, 2, 1, 2, 4),
164 /* config: -smp sockets=2,maxcpus=16
165 * expect: cpus=16,sockets=2,cores=8,threads=1,maxcpus=16 */
166 .config
= SMP_CONFIG_GENERIC(F
, 0, T
, 2, F
, 0, F
, 0, T
, 16),
167 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(16, 2, 8, 1, 16),
168 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(16, 2, 8, 1, 16),
170 /* config: -smp cores=4,threads=2
171 * expect: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
172 .config
= SMP_CONFIG_GENERIC(F
, 0, F
, 0, T
, 4, T
, 2, F
, 0),
173 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
174 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
176 /* config: -smp cores=4,maxcpus=16
177 * expect: cpus=16,sockets=4,cores=4,threads=1,maxcpus=16 */
178 .config
= SMP_CONFIG_GENERIC(F
, 0, F
, 0, T
, 4, F
, 0, T
, 16),
179 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(16, 4, 4, 1, 16),
180 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(16, 4, 4, 1, 16),
182 /* config: -smp threads=2,maxcpus=16
183 * prefer_sockets: cpus=16,sockets=8,cores=1,threads=2,maxcpus=16
184 * prefer_cores: cpus=16,sockets=1,cores=8,threads=2,maxcpus=16 */
185 .config
= SMP_CONFIG_GENERIC(F
, 0, F
, 0, F
, 0, T
, 2, T
, 16),
186 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(16, 8, 1, 2, 16),
187 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(16, 1, 8, 2, 16),
189 /* config: -smp 8,sockets=2,cores=4
190 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
191 .config
= SMP_CONFIG_GENERIC(T
, 8, T
, 2, T
, 4, F
, 0, F
, 0),
192 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
193 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
195 /* config: -smp 8,sockets=2,threads=2
196 * expect: cpus=8,sockets=2,cores=2,threads=2,maxcpus=8 */
197 .config
= SMP_CONFIG_GENERIC(T
, 8, T
, 2, F
, 0, T
, 2, F
, 0),
198 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
199 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
201 /* config: -smp 8,sockets=2,maxcpus=16
202 * expect: cpus=8,sockets=2,cores=8,threads=1,maxcpus=16 */
203 .config
= SMP_CONFIG_GENERIC(T
, 8, T
, 2, F
, 0, F
, 0, T
, 16),
204 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 2, 8, 1, 16),
205 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 2, 8, 1, 16),
207 /* config: -smp 8,cores=4,threads=2
208 * expect: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
209 .config
= SMP_CONFIG_GENERIC(T
, 8, F
, 0, T
, 4, T
, 2, F
, 0),
210 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
211 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
213 /* config: -smp 8,cores=4,maxcpus=16
214 * expect: cpus=8,sockets=4,cores=4,threads=1,maxcpus=16 */
215 .config
= SMP_CONFIG_GENERIC(T
, 8, F
, 0, T
, 4, F
, 0, T
, 16),
216 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 4, 4, 1, 16),
217 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 4, 4, 1, 16),
219 /* config: -smp 8,threads=2,maxcpus=16
220 * prefer_sockets: cpus=8,sockets=8,cores=1,threads=2,maxcpus=16
221 * prefer_cores: cpus=8,sockets=1,cores=8,threads=2,maxcpus=16 */
222 .config
= SMP_CONFIG_GENERIC(T
, 8, F
, 0, F
, 0, T
, 2, T
, 16),
223 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 8, 1, 2, 16),
224 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 1, 8, 2, 16),
226 /* config: -smp sockets=2,cores=4,threads=2
227 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
228 .config
= SMP_CONFIG_GENERIC(F
, 0, T
, 2, T
, 4, T
, 2, F
, 0),
229 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
230 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
232 /* config: -smp sockets=2,cores=4,maxcpus=16
233 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
234 .config
= SMP_CONFIG_GENERIC(F
, 0, T
, 2, T
, 4, F
, 0, T
, 16),
235 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
236 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
238 /* config: -smp sockets=2,threads=2,maxcpus=16
239 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
240 .config
= SMP_CONFIG_GENERIC(F
, 0, T
, 2, F
, 0, T
, 2, T
, 16),
241 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
242 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
244 /* config: -smp cores=4,threads=2,maxcpus=16
245 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
246 .config
= SMP_CONFIG_GENERIC(F
, 0, F
, 0, T
, 4, T
, 2, T
, 16),
247 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
248 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
250 /* config: -smp 8,sockets=2,cores=4,threads=1
251 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
252 .config
= SMP_CONFIG_GENERIC(T
, 8, T
, 2, T
, 4, T
, 1, F
, 0),
253 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
254 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
256 /* config: -smp 8,sockets=2,cores=4,maxcpus=16
257 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
258 .config
= SMP_CONFIG_GENERIC(T
, 8, T
, 2, T
, 4, F
, 0, T
, 16),
259 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
260 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
262 /* config: -smp 8,sockets=2,threads=2,maxcpus=16
263 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
264 .config
= SMP_CONFIG_GENERIC(T
, 8, T
, 2, F
, 0, T
, 2, T
, 16),
265 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
266 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
268 /* config: -smp 8,cores=4,threads=2,maxcpus=16
269 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
270 .config
= SMP_CONFIG_GENERIC(T
, 8, F
, 0, T
, 4, T
, 2, T
, 16),
271 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
272 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
274 /* config: -smp sockets=2,cores=4,threads=2,maxcpus=16
275 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
276 .config
= SMP_CONFIG_GENERIC(F
, 0, T
, 2, T
, 4, T
, 2, T
, 16),
277 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
278 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
280 /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=16
281 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
282 .config
= SMP_CONFIG_GENERIC(T
, 8, T
, 2, T
, 4, T
, 2, T
, 16),
283 .expect_prefer_sockets
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
284 .expect_prefer_cores
= CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
288 static const struct SMPTestData data_generic_invalid
[] = {
290 /* config: -smp 2,dies=2 */
291 .config
= SMP_CONFIG_WITH_DIES(T
, 2, F
, 0, T
, 2, F
, 0, F
, 0, F
, 0),
292 .expect_error
= "dies not supported by this machine's CPU topology",
294 /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=8 */
295 .config
= SMP_CONFIG_GENERIC(T
, 8, T
, 2, T
, 4, T
, 2, T
, 8),
296 .expect_error
= "Invalid CPU topology: "
297 "product of the hierarchy must match maxcpus: "
298 "sockets (2) * cores (4) * threads (2) "
301 /* config: -smp 18,sockets=2,cores=4,threads=2,maxcpus=16 */
302 .config
= SMP_CONFIG_GENERIC(T
, 18, T
, 2, T
, 4, T
, 2, T
, 16),
303 .expect_error
= "Invalid CPU topology: "
304 "maxcpus must be equal to or greater than smp: "
305 "sockets (2) * cores (4) * threads (2) "
306 "== maxcpus (16) < smp_cpus (18)",
309 * should tweak the supported min CPUs to 2 for testing */
310 .config
= SMP_CONFIG_GENERIC(T
, 1, F
, 0, F
, 0, F
, 0, F
, 0),
311 .expect_error
= "Invalid SMP CPUs 1. The min CPUs supported "
312 "by machine '" SMP_MACHINE_NAME
"' is 2",
315 * should tweak the supported max CPUs to 511 for testing */
316 .config
= SMP_CONFIG_GENERIC(T
, 512, F
, 0, F
, 0, F
, 0, F
, 0),
317 .expect_error
= "Invalid SMP CPUs 512. The max CPUs supported "
318 "by machine '" SMP_MACHINE_NAME
"' is 511",
322 static const struct SMPTestData data_with_dies_invalid
[] = {
324 /* config: -smp 16,sockets=2,dies=2,cores=4,threads=2,maxcpus=16 */
325 .config
= SMP_CONFIG_WITH_DIES(T
, 16, T
, 2, T
, 2, T
, 4, T
, 2, T
, 16),
326 .expect_error
= "Invalid CPU topology: "
327 "product of the hierarchy must match maxcpus: "
328 "sockets (2) * dies (2) * cores (4) * threads (2) "
331 /* config: -smp 34,sockets=2,dies=2,cores=4,threads=2,maxcpus=32 */
332 .config
= SMP_CONFIG_WITH_DIES(T
, 34, T
, 2, T
, 2, T
, 4, T
, 2, T
, 32),
333 .expect_error
= "Invalid CPU topology: "
334 "maxcpus must be equal to or greater than smp: "
335 "sockets (2) * dies (2) * cores (4) * threads (2) "
336 "== maxcpus (32) < smp_cpus (34)",
340 static char *smp_config_to_string(SMPConfiguration
*config
)
342 return g_strdup_printf(
343 "(SMPConfiguration) {\n"
344 " .has_cpus = %5s, cpus = %" PRId64
",\n"
345 " .has_sockets = %5s, sockets = %" PRId64
",\n"
346 " .has_dies = %5s, dies = %" PRId64
",\n"
347 " .has_cores = %5s, cores = %" PRId64
",\n"
348 " .has_threads = %5s, threads = %" PRId64
",\n"
349 " .has_maxcpus = %5s, maxcpus = %" PRId64
",\n"
351 config
->has_cpus
? "true" : "false", config
->cpus
,
352 config
->has_sockets
? "true" : "false", config
->sockets
,
353 config
->has_dies
? "true" : "false", config
->dies
,
354 config
->has_cores
? "true" : "false", config
->cores
,
355 config
->has_threads
? "true" : "false", config
->threads
,
356 config
->has_maxcpus
? "true" : "false", config
->maxcpus
);
359 static char *cpu_topology_to_string(const CpuTopology
*topo
)
361 return g_strdup_printf(
370 topo
->cpus
, topo
->sockets
, topo
->dies
,
371 topo
->cores
, topo
->threads
, topo
->max_cpus
);
374 static void check_parse(MachineState
*ms
, SMPConfiguration
*config
,
375 const CpuTopology
*expect_topo
, const char *expect_err
,
378 g_autofree
char *config_str
= smp_config_to_string(config
);
379 g_autofree
char *expect_topo_str
= cpu_topology_to_string(expect_topo
);
380 g_autofree
char *output_topo_str
= NULL
;
383 /* call the generic parser smp_parse() */
384 smp_parse(ms
, config
, &err
);
386 output_topo_str
= cpu_topology_to_string(&ms
->smp
);
388 /* when the configuration is supposed to be valid */
391 (ms
->smp
.cpus
== expect_topo
->cpus
) &&
392 (ms
->smp
.sockets
== expect_topo
->sockets
) &&
393 (ms
->smp
.dies
== expect_topo
->dies
) &&
394 (ms
->smp
.cores
== expect_topo
->cores
) &&
395 (ms
->smp
.threads
== expect_topo
->threads
) &&
396 (ms
->smp
.max_cpus
== expect_topo
->max_cpus
)) {
401 g_printerr("Test smp_parse failed!\n"
402 "Input configuration: %s\n"
403 "Should be valid: yes\n"
404 "Expected topology: %s\n\n"
405 "Result is valid: no\n"
406 "Output error report: %s\n",
407 config_str
, expect_topo_str
, error_get_pretty(err
));
411 g_printerr("Test smp_parse failed!\n"
412 "Input configuration: %s\n"
413 "Should be valid: yes\n"
414 "Expected topology: %s\n\n"
415 "Result is valid: yes\n"
416 "Output topology: %s\n",
417 config_str
, expect_topo_str
, output_topo_str
);
421 /* when the configuration is supposed to be invalid */
423 if (expect_err
== NULL
||
424 g_str_equal(expect_err
, error_get_pretty(err
))) {
429 g_printerr("Test smp_parse failed!\n"
430 "Input configuration: %s\n"
431 "Should be valid: no\n"
432 "Expected error report: %s\n\n"
433 "Result is valid: no\n"
434 "Output error report: %s\n",
435 config_str
, expect_err
, error_get_pretty(err
));
439 g_printerr("Test smp_parse failed!\n"
440 "Input configuration: %s\n"
441 "Should be valid: no\n"
442 "Expected error report: %s\n\n"
443 "Result is valid: yes\n"
444 "Output topology: %s\n",
445 config_str
, expect_err
, output_topo_str
);
455 static void smp_parse_test(MachineState
*ms
, SMPTestData
*data
, bool is_valid
)
457 MachineClass
*mc
= MACHINE_GET_CLASS(ms
);
459 mc
->smp_props
.prefer_sockets
= true;
460 check_parse(ms
, &data
->config
, &data
->expect_prefer_sockets
,
461 data
->expect_error
, is_valid
);
463 mc
->smp_props
.prefer_sockets
= false;
464 check_parse(ms
, &data
->config
, &data
->expect_prefer_cores
,
465 data
->expect_error
, is_valid
);
468 /* The parsed results of the unsupported parameters should be 1 */
469 static void unsupported_params_init(const MachineClass
*mc
, SMPTestData
*data
)
471 if (!mc
->smp_props
.dies_supported
) {
472 data
->expect_prefer_sockets
.dies
= 1;
473 data
->expect_prefer_cores
.dies
= 1;
477 static void machine_base_class_init(ObjectClass
*oc
, void *data
)
479 MachineClass
*mc
= MACHINE_CLASS(oc
);
481 mc
->smp_props
.prefer_sockets
= true;
483 mc
->name
= g_strdup(SMP_MACHINE_NAME
);
486 static void machine_generic_valid_class_init(ObjectClass
*oc
, void *data
)
488 MachineClass
*mc
= MACHINE_CLASS(oc
);
490 mc
->min_cpus
= MIN_CPUS
;
491 mc
->max_cpus
= MAX_CPUS
;
493 mc
->smp_props
.dies_supported
= false;
496 static void machine_generic_invalid_class_init(ObjectClass
*oc
, void *data
)
498 MachineClass
*mc
= MACHINE_CLASS(oc
);
500 /* Force invalid min CPUs and max CPUs */
504 mc
->smp_props
.dies_supported
= false;
507 static void machine_with_dies_class_init(ObjectClass
*oc
, void *data
)
509 MachineClass
*mc
= MACHINE_CLASS(oc
);
511 mc
->min_cpus
= MIN_CPUS
;
512 mc
->max_cpus
= MAX_CPUS
;
514 mc
->smp_props
.dies_supported
= true;
517 static void test_generic_valid(const void *opaque
)
519 const char *machine_type
= opaque
;
520 Object
*obj
= object_new(machine_type
);
521 MachineState
*ms
= MACHINE(obj
);
522 MachineClass
*mc
= MACHINE_GET_CLASS(obj
);
523 SMPTestData data
= {};
526 for (i
= 0; i
< ARRAY_SIZE(data_generic_valid
); i
++) {
527 data
= data_generic_valid
[i
];
528 unsupported_params_init(mc
, &data
);
530 smp_parse_test(ms
, &data
, true);
532 /* Unsupported parameters can be provided with their values as 1 */
533 data
.config
.has_dies
= true;
534 data
.config
.dies
= 1;
535 smp_parse_test(ms
, &data
, true);
541 static void test_generic_invalid(const void *opaque
)
543 const char *machine_type
= opaque
;
544 Object
*obj
= object_new(machine_type
);
545 MachineState
*ms
= MACHINE(obj
);
546 MachineClass
*mc
= MACHINE_GET_CLASS(obj
);
547 SMPTestData data
= {};
550 for (i
= 0; i
< ARRAY_SIZE(data_generic_invalid
); i
++) {
551 data
= data_generic_invalid
[i
];
552 unsupported_params_init(mc
, &data
);
554 smp_parse_test(ms
, &data
, false);
560 static void test_with_dies(const void *opaque
)
562 const char *machine_type
= opaque
;
563 Object
*obj
= object_new(machine_type
);
564 MachineState
*ms
= MACHINE(obj
);
565 MachineClass
*mc
= MACHINE_GET_CLASS(obj
);
566 SMPTestData data
= {};
567 unsigned int num_dies
= 2;
570 for (i
= 0; i
< ARRAY_SIZE(data_generic_valid
); i
++) {
571 data
= data_generic_valid
[i
];
572 unsupported_params_init(mc
, &data
);
574 /* when dies parameter is omitted, it will be set as 1 */
575 data
.expect_prefer_sockets
.dies
= 1;
576 data
.expect_prefer_cores
.dies
= 1;
578 smp_parse_test(ms
, &data
, true);
580 /* when dies parameter is specified */
581 data
.config
.has_dies
= true;
582 data
.config
.dies
= num_dies
;
583 if (data
.config
.has_cpus
) {
584 data
.config
.cpus
*= num_dies
;
586 if (data
.config
.has_maxcpus
) {
587 data
.config
.maxcpus
*= num_dies
;
590 data
.expect_prefer_sockets
.dies
= num_dies
;
591 data
.expect_prefer_sockets
.cpus
*= num_dies
;
592 data
.expect_prefer_sockets
.max_cpus
*= num_dies
;
593 data
.expect_prefer_cores
.dies
= num_dies
;
594 data
.expect_prefer_cores
.cpus
*= num_dies
;
595 data
.expect_prefer_cores
.max_cpus
*= num_dies
;
597 smp_parse_test(ms
, &data
, true);
600 for (i
= 0; i
< ARRAY_SIZE(data_with_dies_invalid
); i
++) {
601 data
= data_with_dies_invalid
[i
];
602 unsupported_params_init(mc
, &data
);
604 smp_parse_test(ms
, &data
, false);
610 /* Type info of the tested machine */
611 static const TypeInfo smp_machine_types
[] = {
613 .name
= TYPE_MACHINE
,
614 .parent
= TYPE_OBJECT
,
616 .class_init
= machine_base_class_init
,
617 .class_size
= sizeof(MachineClass
),
618 .instance_size
= sizeof(MachineState
),
620 .name
= MACHINE_TYPE_NAME("smp-generic-valid"),
621 .parent
= TYPE_MACHINE
,
622 .class_init
= machine_generic_valid_class_init
,
624 .name
= MACHINE_TYPE_NAME("smp-generic-invalid"),
625 .parent
= TYPE_MACHINE
,
626 .class_init
= machine_generic_invalid_class_init
,
628 .name
= MACHINE_TYPE_NAME("smp-with-dies"),
629 .parent
= TYPE_MACHINE
,
630 .class_init
= machine_with_dies_class_init
,
634 DEFINE_TYPES(smp_machine_types
)
636 int main(int argc
, char *argv
[])
638 module_call_init(MODULE_INIT_QOM
);
640 g_test_init(&argc
, &argv
, NULL
);
642 g_test_add_data_func("/test-smp-parse/generic/valid",
643 MACHINE_TYPE_NAME("smp-generic-valid"),
645 g_test_add_data_func("/test-smp-parse/generic/invalid",
646 MACHINE_TYPE_NAME("smp-generic-invalid"),
647 test_generic_invalid
);
648 g_test_add_data_func("/test-smp-parse/with_dies",
649 MACHINE_TYPE_NAME("smp-with-dies"),