1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "qom/object.h"
15#include "qemu/module.h"
16#include "qapi/error.h"
17
18#include "hw/boards.h"
19
20#define T true
21#define F false
22
23#define MIN_CPUS 1
24#define MAX_CPUS 512
25
26#define SMP_MACHINE_NAME "TEST-SMP"
27
28
29
30
31
32#define SMP_CONFIG_GENERIC(ha, a, hb, b, hc, c, hd, d, he, e) \
33 { \
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, \
39 }
40
41#define CPU_TOPOLOGY_GENERIC(a, b, c, d, e) \
42 { \
43 .cpus = a, \
44 .sockets = b, \
45 .cores = c, \
46 .threads = d, \
47 .max_cpus = e, \
48 }
49
50
51
52
53
54#define SMP_CONFIG_WITH_DIES(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \
55 { \
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, \
62 }
63
64
65
66
67
68#define SMP_CONFIG_WITH_CLUSTERS(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \
69 { \
70 .has_cpus = ha, .cpus = a, \
71 .has_sockets = hb, .sockets = b, \
72 .has_clusters = hc, .clusters = c, \
73 .has_cores = hd, .cores = d, \
74 .has_threads = he, .threads = e, \
75 .has_maxcpus = hf, .maxcpus = f, \
76 }
77
78
79
80
81
82
83
84
85
86
87typedef struct SMPTestData {
88 SMPConfiguration config;
89 CpuTopology expect_prefer_sockets;
90 CpuTopology expect_prefer_cores;
91 const char *expect_error;
92} SMPTestData;
93
94
95
96
97
98
99
100static const struct SMPTestData data_generic_valid[] = {
101 {
102
103
104 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, F, 0, F, 0),
105 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(1, 1, 1, 1, 1),
106 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(1, 1, 1, 1, 1),
107 }, {
108
109
110
111 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, F, 0, F, 0),
112 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 8, 1, 1, 8),
113 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 8, 1, 8),
114 }, {
115
116
117 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, F, 0, F, 0),
118 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(2, 2, 1, 1, 2),
119 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(2, 2, 1, 1, 2),
120 }, {
121
122
123 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, F, 0, F, 0),
124 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(4, 1, 4, 1, 4),
125 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(4, 1, 4, 1, 4),
126 }, {
127
128
129 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, T, 2, F, 0),
130 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(2, 1, 1, 2, 2),
131 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(2, 1, 1, 2, 2),
132 }, {
133
134
135
136 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, F, 0, T, 16),
137 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 16, 1, 1, 16),
138 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 1, 16, 1, 16),
139 }, {
140
141
142 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, F, 0, F, 0),
143 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
144 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
145 }, {
146
147
148 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, F, 0, F, 0),
149 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
150 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
151 }, {
152
153
154
155 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, T, 2, F, 0),
156 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 4, 1, 2, 8),
157 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
158 }, {
159
160
161
162 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, F, 0, T, 16),
163 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 16, 1, 1, 16),
164 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 16, 1, 16),
165 }, {
166
167
168 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, F, 0, F, 0),
169 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
170 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
171 }, {
172
173
174 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, T, 2, F, 0),
175 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(4, 2, 1, 2, 4),
176 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(4, 2, 1, 2, 4),
177 }, {
178
179
180 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, F, 0, T, 16),
181 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 8, 1, 16),
182 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 8, 1, 16),
183 }, {
184
185
186 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, T, 2, F, 0),
187 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
188 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
189 }, {
190
191
192 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, F, 0, T, 16),
193 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 4, 4, 1, 16),
194 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 4, 4, 1, 16),
195 }, {
196
197
198
199 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, T, 2, T, 16),
200 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 8, 1, 2, 16),
201 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 1, 8, 2, 16),
202 }, {
203
204
205 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, F, 0, F, 0),
206 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
207 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
208 }, {
209
210
211 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, T, 2, F, 0),
212 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
213 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
214 }, {
215
216
217 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, F, 0, T, 16),
218 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 8, 1, 16),
219 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 8, 1, 16),
220 }, {
221
222
223 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, T, 2, F, 0),
224 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
225 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
226 }, {
227
228
229 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, F, 0, T, 16),
230 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 4, 4, 1, 16),
231 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 4, 4, 1, 16),
232 }, {
233
234
235
236 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, T, 2, T, 16),
237 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 8, 1, 2, 16),
238 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 8, 2, 16),
239 }, {
240
241
242 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, T, 2, F, 0),
243 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
244 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
245 }, {
246
247
248 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, F, 0, T, 16),
249 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
250 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
251 }, {
252
253
254 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, T, 2, T, 16),
255 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
256 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
257 }, {
258
259
260 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, T, 2, T, 16),
261 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
262 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
263 }, {
264
265
266 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 1, F, 0),
267 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
268 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
269 }, {
270
271
272 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, F, 0, T, 16),
273 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
274 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
275 }, {
276
277
278 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, T, 2, T, 16),
279 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
280 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
281 }, {
282
283
284 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, T, 2, T, 16),
285 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
286 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
287 }, {
288
289
290 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, T, 2, T, 16),
291 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
292 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
293 }, {
294
295
296 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 16),
297 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
298 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
299 },
300};
301
302static const struct SMPTestData data_generic_invalid[] = {
303 {
304
305 .config = SMP_CONFIG_WITH_DIES(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0),
306 .expect_error = "dies not supported by this machine's CPU topology",
307 }, {
308
309 .config = SMP_CONFIG_WITH_CLUSTERS(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0),
310 .expect_error = "clusters not supported by this machine's CPU topology",
311 }, {
312
313 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 8),
314 .expect_error = "Invalid CPU topology: "
315 "product of the hierarchy must match maxcpus: "
316 "sockets (2) * cores (4) * threads (2) "
317 "!= maxcpus (8)",
318 }, {
319
320 .config = SMP_CONFIG_GENERIC(T, 18, T, 2, T, 4, T, 2, T, 16),
321 .expect_error = "Invalid CPU topology: "
322 "maxcpus must be equal to or greater than smp: "
323 "sockets (2) * cores (4) * threads (2) "
324 "== maxcpus (16) < smp_cpus (18)",
325 }, {
326
327
328 .config = SMP_CONFIG_GENERIC(T, 1, F, 0, F, 0, F, 0, F, 0),
329 .expect_error = "Invalid SMP CPUs 1. The min CPUs supported "
330 "by machine '" SMP_MACHINE_NAME "' is 2",
331 }, {
332
333
334 .config = SMP_CONFIG_GENERIC(T, 512, F, 0, F, 0, F, 0, F, 0),
335 .expect_error = "Invalid SMP CPUs 512. The max CPUs supported "
336 "by machine '" SMP_MACHINE_NAME "' is 511",
337 },
338};
339
340static const struct SMPTestData data_with_dies_invalid[] = {
341 {
342
343 .config = SMP_CONFIG_WITH_DIES(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16),
344 .expect_error = "Invalid CPU topology: "
345 "product of the hierarchy must match maxcpus: "
346 "sockets (2) * dies (2) * cores (4) * threads (2) "
347 "!= maxcpus (16)",
348 }, {
349
350 .config = SMP_CONFIG_WITH_DIES(T, 34, T, 2, T, 2, T, 4, T, 2, T, 32),
351 .expect_error = "Invalid CPU topology: "
352 "maxcpus must be equal to or greater than smp: "
353 "sockets (2) * dies (2) * cores (4) * threads (2) "
354 "== maxcpus (32) < smp_cpus (34)",
355 },
356};
357
358static const struct SMPTestData data_with_clusters_invalid[] = {
359 {
360
361 .config = SMP_CONFIG_WITH_CLUSTERS(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16),
362 .expect_error = "Invalid CPU topology: "
363 "product of the hierarchy must match maxcpus: "
364 "sockets (2) * clusters (2) * cores (4) * threads (2) "
365 "!= maxcpus (16)",
366 }, {
367
368 .config = SMP_CONFIG_WITH_CLUSTERS(T, 34, T, 2, T, 2, T, 4, T, 2, T, 32),
369 .expect_error = "Invalid CPU topology: "
370 "maxcpus must be equal to or greater than smp: "
371 "sockets (2) * clusters (2) * cores (4) * threads (2) "
372 "== maxcpus (32) < smp_cpus (34)",
373 },
374};
375
376static char *smp_config_to_string(const SMPConfiguration *config)
377{
378 return g_strdup_printf(
379 "(SMPConfiguration) {\n"
380 " .has_cpus = %5s, cpus = %" PRId64 ",\n"
381 " .has_sockets = %5s, sockets = %" PRId64 ",\n"
382 " .has_dies = %5s, dies = %" PRId64 ",\n"
383 " .has_clusters = %5s, clusters = %" PRId64 ",\n"
384 " .has_cores = %5s, cores = %" PRId64 ",\n"
385 " .has_threads = %5s, threads = %" PRId64 ",\n"
386 " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n"
387 "}",
388 config->has_cpus ? "true" : "false", config->cpus,
389 config->has_sockets ? "true" : "false", config->sockets,
390 config->has_dies ? "true" : "false", config->dies,
391 config->has_clusters ? "true" : "false", config->clusters,
392 config->has_cores ? "true" : "false", config->cores,
393 config->has_threads ? "true" : "false", config->threads,
394 config->has_maxcpus ? "true" : "false", config->maxcpus);
395}
396
397static char *cpu_topology_to_string(const CpuTopology *topo)
398{
399 return g_strdup_printf(
400 "(CpuTopology) {\n"
401 " .cpus = %u,\n"
402 " .sockets = %u,\n"
403 " .dies = %u,\n"
404 " .clusters = %u,\n"
405 " .cores = %u,\n"
406 " .threads = %u,\n"
407 " .max_cpus = %u,\n"
408 "}",
409 topo->cpus, topo->sockets, topo->dies, topo->clusters,
410 topo->cores, topo->threads, topo->max_cpus);
411}
412
413static void check_parse(MachineState *ms, const SMPConfiguration *config,
414 const CpuTopology *expect_topo, const char *expect_err,
415 bool is_valid)
416{
417 g_autofree char *config_str = smp_config_to_string(config);
418 g_autofree char *expect_topo_str = cpu_topology_to_string(expect_topo);
419 g_autofree char *output_topo_str = NULL;
420 Error *err = NULL;
421
422
423 machine_parse_smp_config(ms, config, &err);
424
425 output_topo_str = cpu_topology_to_string(&ms->smp);
426
427
428 if (is_valid) {
429 if ((err == NULL) &&
430 (ms->smp.cpus == expect_topo->cpus) &&
431 (ms->smp.sockets == expect_topo->sockets) &&
432 (ms->smp.dies == expect_topo->dies) &&
433 (ms->smp.clusters == expect_topo->clusters) &&
434 (ms->smp.cores == expect_topo->cores) &&
435 (ms->smp.threads == expect_topo->threads) &&
436 (ms->smp.max_cpus == expect_topo->max_cpus)) {
437 return;
438 }
439
440 if (err != NULL) {
441 g_printerr("Test smp_parse failed!\n"
442 "Input configuration: %s\n"
443 "Should be valid: yes\n"
444 "Expected topology: %s\n\n"
445 "Result is valid: no\n"
446 "Output error report: %s\n",
447 config_str, expect_topo_str, error_get_pretty(err));
448 goto end;
449 }
450
451 g_printerr("Test smp_parse failed!\n"
452 "Input configuration: %s\n"
453 "Should be valid: yes\n"
454 "Expected topology: %s\n\n"
455 "Result is valid: yes\n"
456 "Output topology: %s\n",
457 config_str, expect_topo_str, output_topo_str);
458 goto end;
459 }
460
461
462 if (err != NULL) {
463 if (expect_err == NULL ||
464 g_str_equal(expect_err, error_get_pretty(err))) {
465 error_free(err);
466 return;
467 }
468
469 g_printerr("Test smp_parse failed!\n"
470 "Input configuration: %s\n"
471 "Should be valid: no\n"
472 "Expected error report: %s\n\n"
473 "Result is valid: no\n"
474 "Output error report: %s\n",
475 config_str, expect_err, error_get_pretty(err));
476 goto end;
477 }
478
479 g_printerr("Test smp_parse failed!\n"
480 "Input configuration: %s\n"
481 "Should be valid: no\n"
482 "Expected error report: %s\n\n"
483 "Result is valid: yes\n"
484 "Output topology: %s\n",
485 config_str, expect_err, output_topo_str);
486
487end:
488 if (err != NULL) {
489 error_free(err);
490 }
491
492 abort();
493}
494
495static void smp_parse_test(MachineState *ms, SMPTestData *data, bool is_valid)
496{
497 MachineClass *mc = MACHINE_GET_CLASS(ms);
498
499 mc->smp_props.prefer_sockets = true;
500 check_parse(ms, &data->config, &data->expect_prefer_sockets,
501 data->expect_error, is_valid);
502
503 mc->smp_props.prefer_sockets = false;
504 check_parse(ms, &data->config, &data->expect_prefer_cores,
505 data->expect_error, is_valid);
506}
507
508
509static void unsupported_params_init(const MachineClass *mc, SMPTestData *data)
510{
511 if (!mc->smp_props.dies_supported) {
512 data->expect_prefer_sockets.dies = 1;
513 data->expect_prefer_cores.dies = 1;
514 }
515
516 if (!mc->smp_props.clusters_supported) {
517 data->expect_prefer_sockets.clusters = 1;
518 data->expect_prefer_cores.clusters = 1;
519 }
520}
521
522static void machine_base_class_init(ObjectClass *oc, void *data)
523{
524 MachineClass *mc = MACHINE_CLASS(oc);
525
526 mc->min_cpus = MIN_CPUS;
527 mc->max_cpus = MAX_CPUS;
528
529 mc->name = g_strdup(SMP_MACHINE_NAME);
530}
531
532static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
533{
534 MachineClass *mc = MACHINE_CLASS(oc);
535
536
537 mc->min_cpus = 2;
538 mc->max_cpus = 511;
539}
540
541static void machine_with_dies_class_init(ObjectClass *oc, void *data)
542{
543 MachineClass *mc = MACHINE_CLASS(oc);
544
545 mc->smp_props.dies_supported = true;
546}
547
548static void machine_with_clusters_class_init(ObjectClass *oc, void *data)
549{
550 MachineClass *mc = MACHINE_CLASS(oc);
551
552 mc->smp_props.clusters_supported = true;
553}
554
555static void test_generic_valid(const void *opaque)
556{
557 const char *machine_type = opaque;
558 Object *obj = object_new(machine_type);
559 MachineState *ms = MACHINE(obj);
560 MachineClass *mc = MACHINE_GET_CLASS(obj);
561 SMPTestData data = {};
562 int i;
563
564 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
565 data = data_generic_valid[i];
566 unsupported_params_init(mc, &data);
567
568 smp_parse_test(ms, &data, true);
569
570
571 data.config.has_dies = true;
572 data.config.dies = 1;
573 smp_parse_test(ms, &data, true);
574 }
575
576 object_unref(obj);
577}
578
579static void test_generic_invalid(const void *opaque)
580{
581 const char *machine_type = opaque;
582 Object *obj = object_new(machine_type);
583 MachineState *ms = MACHINE(obj);
584 MachineClass *mc = MACHINE_GET_CLASS(obj);
585 SMPTestData data = {};
586 int i;
587
588 for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) {
589 data = data_generic_invalid[i];
590 unsupported_params_init(mc, &data);
591
592 smp_parse_test(ms, &data, false);
593 }
594
595 object_unref(obj);
596}
597
598static void test_with_dies(const void *opaque)
599{
600 const char *machine_type = opaque;
601 Object *obj = object_new(machine_type);
602 MachineState *ms = MACHINE(obj);
603 MachineClass *mc = MACHINE_GET_CLASS(obj);
604 SMPTestData data = {};
605 unsigned int num_dies = 2;
606 int i;
607
608 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
609 data = data_generic_valid[i];
610 unsupported_params_init(mc, &data);
611
612
613 data.expect_prefer_sockets.dies = 1;
614 data.expect_prefer_cores.dies = 1;
615
616 smp_parse_test(ms, &data, true);
617
618
619 data.config.has_dies = true;
620 data.config.dies = num_dies;
621 if (data.config.has_cpus) {
622 data.config.cpus *= num_dies;
623 }
624 if (data.config.has_maxcpus) {
625 data.config.maxcpus *= num_dies;
626 }
627
628 data.expect_prefer_sockets.dies = num_dies;
629 data.expect_prefer_sockets.cpus *= num_dies;
630 data.expect_prefer_sockets.max_cpus *= num_dies;
631 data.expect_prefer_cores.dies = num_dies;
632 data.expect_prefer_cores.cpus *= num_dies;
633 data.expect_prefer_cores.max_cpus *= num_dies;
634
635 smp_parse_test(ms, &data, true);
636 }
637
638 for (i = 0; i < ARRAY_SIZE(data_with_dies_invalid); i++) {
639 data = data_with_dies_invalid[i];
640 unsupported_params_init(mc, &data);
641
642 smp_parse_test(ms, &data, false);
643 }
644
645 object_unref(obj);
646}
647
648static void test_with_clusters(const void *opaque)
649{
650 const char *machine_type = opaque;
651 Object *obj = object_new(machine_type);
652 MachineState *ms = MACHINE(obj);
653 MachineClass *mc = MACHINE_GET_CLASS(obj);
654 SMPTestData data = {};
655 unsigned int num_clusters = 2;
656 int i;
657
658 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
659 data = data_generic_valid[i];
660 unsupported_params_init(mc, &data);
661
662
663 data.expect_prefer_sockets.clusters = 1;
664 data.expect_prefer_cores.clusters = 1;
665
666 smp_parse_test(ms, &data, true);
667
668
669 data.config.has_clusters = true;
670 data.config.clusters = num_clusters;
671 if (data.config.has_cpus) {
672 data.config.cpus *= num_clusters;
673 }
674 if (data.config.has_maxcpus) {
675 data.config.maxcpus *= num_clusters;
676 }
677
678 data.expect_prefer_sockets.clusters = num_clusters;
679 data.expect_prefer_sockets.cpus *= num_clusters;
680 data.expect_prefer_sockets.max_cpus *= num_clusters;
681 data.expect_prefer_cores.clusters = num_clusters;
682 data.expect_prefer_cores.cpus *= num_clusters;
683 data.expect_prefer_cores.max_cpus *= num_clusters;
684
685 smp_parse_test(ms, &data, true);
686 }
687
688 for (i = 0; i < ARRAY_SIZE(data_with_clusters_invalid); i++) {
689 data = data_with_clusters_invalid[i];
690 unsupported_params_init(mc, &data);
691
692 smp_parse_test(ms, &data, false);
693 }
694
695 object_unref(obj);
696}
697
698
699static const TypeInfo smp_machine_types[] = {
700 {
701 .name = TYPE_MACHINE,
702 .parent = TYPE_OBJECT,
703 .abstract = true,
704 .class_init = machine_base_class_init,
705 .class_size = sizeof(MachineClass),
706 .instance_size = sizeof(MachineState),
707 }, {
708 .name = MACHINE_TYPE_NAME("smp-generic-valid"),
709 .parent = TYPE_MACHINE,
710 }, {
711 .name = MACHINE_TYPE_NAME("smp-generic-invalid"),
712 .parent = TYPE_MACHINE,
713 .class_init = machine_generic_invalid_class_init,
714 }, {
715 .name = MACHINE_TYPE_NAME("smp-with-dies"),
716 .parent = TYPE_MACHINE,
717 .class_init = machine_with_dies_class_init,
718 }, {
719 .name = MACHINE_TYPE_NAME("smp-with-clusters"),
720 .parent = TYPE_MACHINE,
721 .class_init = machine_with_clusters_class_init,
722 }
723};
724
725DEFINE_TYPES(smp_machine_types)
726
727int main(int argc, char *argv[])
728{
729 module_call_init(MODULE_INIT_QOM);
730
731 g_test_init(&argc, &argv, NULL);
732
733 g_test_add_data_func("/test-smp-parse/generic/valid",
734 MACHINE_TYPE_NAME("smp-generic-valid"),
735 test_generic_valid);
736 g_test_add_data_func("/test-smp-parse/generic/invalid",
737 MACHINE_TYPE_NAME("smp-generic-invalid"),
738 test_generic_invalid);
739 g_test_add_data_func("/test-smp-parse/with_dies",
740 MACHINE_TYPE_NAME("smp-with-dies"),
741 test_with_dies);
742 g_test_add_data_func("/test-smp-parse/with_clusters",
743 MACHINE_TYPE_NAME("smp-with-clusters"),
744 test_with_clusters);
745
746 g_test_run();
747
748 return 0;
749}
750