1 /*
2 * SMP parsing unit-tests
3 *
4 * Copyright (c) 2021 Huawei Technologies Co., Ltd
5 *
6 * Authors:
7 * Yanan Wang <wangyanan55@huawei.com>
8 *
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.
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 /* set the min CPUs supported by the machine as 1 */
24 #define MAX_CPUS 4096 /* set the max CPUs supported by the machine as 4096 */
25
26 #define SMP_MACHINE_NAME "TEST-SMP"
27
28 /*
29 * Used to define the generic 3-level CPU topology hierarchy
30 * -sockets/cores/threads
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 * Currently a 5-level topology hierarchy is supported on PC machines
52 * -sockets/dies/modules/cores/threads
53 */
54 #define SMP_CONFIG_WITH_MODS_DIES(ha, a, hb, b, hc, c, hd, d, \
55 he, e, hf, f, hg, g) \
56 { \
57 .has_cpus = ha, .cpus = a, \
58 .has_sockets = hb, .sockets = b, \
59 .has_dies = hc, .dies = c, \
60 .has_modules = hd, .modules = d, \
61 .has_cores = he, .cores = e, \
62 .has_threads = hf, .threads = f, \
63 .has_maxcpus = hg, .maxcpus = g, \
64 }
65
66 /*
67 * Currently a 4-level topology hierarchy is supported on ARM virt machines
68 * -sockets/clusters/cores/threads
69 */
70 #define SMP_CONFIG_WITH_CLUSTERS(ha, a, hb, b, hc, c, hd, d, he, e, hf, f) \
71 { \
72 .has_cpus = ha, .cpus = a, \
73 .has_sockets = hb, .sockets = b, \
74 .has_clusters = hc, .clusters = c, \
75 .has_cores = hd, .cores = d, \
76 .has_threads = he, .threads = e, \
77 .has_maxcpus = hf, .maxcpus = f, \
78 }
79
80 /*
81 * Currently a 5-level topology hierarchy is supported on s390 ccw machines
82 * -drawers/books/sockets/cores/threads
83 */
84 #define SMP_CONFIG_WITH_BOOKS_DRAWERS(ha, a, hb, b, hc, c, hd, \
85 d, he, e, hf, f, hg, g) \
86 { \
87 .has_cpus = ha, .cpus = a, \
88 .has_drawers = hb, .drawers = b, \
89 .has_books = hc, .books = c, \
90 .has_sockets = hd, .sockets = d, \
91 .has_cores = he, .cores = e, \
92 .has_threads = hf, .threads = f, \
93 .has_maxcpus = hg, .maxcpus = g, \
94 }
95
96 /*
97 * Currently QEMU supports up to a 8-level topology hierarchy, which is the
98 * QEMU's unified abstract representation of CPU topology.
99 * -drawers/books/sockets/dies/clusters/modules/cores/threads
100 */
101 #define SMP_CONFIG_WITH_FULL_TOPO(a, b, c, d, e, f, g, h, i, j) \
102 { \
103 .has_cpus = true, .cpus = a, \
104 .has_drawers = true, .drawers = b, \
105 .has_books = true, .books = c, \
106 .has_sockets = true, .sockets = d, \
107 .has_dies = true, .dies = e, \
108 .has_clusters = true, .clusters = f, \
109 .has_modules = true, .modules = g, \
110 .has_cores = true, .cores = h, \
111 .has_threads = true, .threads = i, \
112 .has_maxcpus = true, .maxcpus = j, \
113 }
114
115 /**
116 * @config - the given SMP configuration
117 * @expect_prefer_sockets - the expected parsing result for the
118 * valid configuration, when sockets are preferred over cores
119 * @expect_prefer_cores - the expected parsing result for the
120 * valid configuration, when cores are preferred over sockets
121 * @expect_error - the expected error report when the given
122 * configuration is invalid
123 */
124 typedef struct SMPTestData {
125 SMPConfiguration config;
126 CpuTopology expect_prefer_sockets;
127 CpuTopology expect_prefer_cores;
128 const char *expect_error;
129 } SMPTestData;
130
131 /*
132 * List all the possible valid sub-collections of the generic 5
133 * topology parameters (i.e. cpus/maxcpus/sockets/cores/threads),
134 * then test the automatic calculation algorithm of the missing
135 * values in the parser.
136 */
137 static const struct SMPTestData data_generic_valid[] = {
138 {
139 /* config: no configuration provided
140 * expect: cpus=1,sockets=1,cores=1,threads=1,maxcpus=1 */
141 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, F, 0, F, 0),
142 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(1, 1, 1, 1, 1),
143 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(1, 1, 1, 1, 1),
144 }, {
145 /* config: -smp 8
146 * prefer_sockets: cpus=8,sockets=8,cores=1,threads=1,maxcpus=8
147 * prefer_cores: cpus=8,sockets=1,cores=8,threads=1,maxcpus=8 */
148 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, F, 0, F, 0),
149 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 8, 1, 1, 8),
150 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 8, 1, 8),
151 }, {
152 /* config: -smp sockets=2
153 * expect: cpus=2,sockets=2,cores=1,threads=1,maxcpus=2 */
154 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, F, 0, F, 0),
155 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(2, 2, 1, 1, 2),
156 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(2, 2, 1, 1, 2),
157 }, {
158 /* config: -smp cores=4
159 * expect: cpus=4,sockets=1,cores=4,threads=1,maxcpus=4 */
160 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, F, 0, F, 0),
161 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(4, 1, 4, 1, 4),
162 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(4, 1, 4, 1, 4),
163 }, {
164 /* config: -smp threads=2
165 * expect: cpus=2,sockets=1,cores=1,threads=2,maxcpus=2 */
166 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, T, 2, F, 0),
167 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(2, 1, 1, 2, 2),
168 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(2, 1, 1, 2, 2),
169 }, {
170 /* config: -smp maxcpus=16
171 * prefer_sockets: cpus=16,sockets=16,cores=1,threads=1,maxcpus=16
172 * prefer_cores: cpus=16,sockets=1,cores=16,threads=1,maxcpus=16 */
173 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, F, 0, T, 16),
174 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 16, 1, 1, 16),
175 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 1, 16, 1, 16),
176 }, {
177 /* config: -smp 8,sockets=2
178 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
179 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, F, 0, F, 0),
180 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
181 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
182 }, {
183 /* config: -smp 8,cores=4
184 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
185 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, F, 0, F, 0),
186 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
187 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
188 }, {
189 /* config: -smp 8,threads=2
190 * prefer_sockets: cpus=8,sockets=4,cores=1,threads=2,maxcpus=8
191 * prefer_cores: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
192 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, T, 2, F, 0),
193 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 4, 1, 2, 8),
194 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
195 }, {
196 /* config: -smp 8,maxcpus=16
197 * prefer_sockets: cpus=8,sockets=16,cores=1,threads=1,maxcpus=16
198 * prefer_cores: cpus=8,sockets=1,cores=16,threads=1,maxcpus=16 */
199 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, F, 0, T, 16),
200 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 16, 1, 1, 16),
201 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 16, 1, 16),
202 }, {
203 /* config: -smp sockets=2,cores=4
204 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
205 .config = SMP_CONFIG_GENERIC(F, 0, 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 /* config: -smp sockets=2,threads=2
210 * expect: cpus=4,sockets=2,cores=1,threads=2,maxcpus=4 */
211 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, T, 2, F, 0),
212 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(4, 2, 1, 2, 4),
213 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(4, 2, 1, 2, 4),
214 }, {
215 /* config: -smp sockets=2,maxcpus=16
216 * expect: cpus=16,sockets=2,cores=8,threads=1,maxcpus=16 */
217 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, F, 0, T, 16),
218 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 8, 1, 16),
219 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 8, 1, 16),
220 }, {
221 /* config: -smp cores=4,threads=2
222 * expect: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
223 .config = SMP_CONFIG_GENERIC(F, 0, 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 /* config: -smp cores=4,maxcpus=16
228 * expect: cpus=16,sockets=4,cores=4,threads=1,maxcpus=16 */
229 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, F, 0, T, 16),
230 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 4, 4, 1, 16),
231 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 4, 4, 1, 16),
232 }, {
233 /* config: -smp threads=2,maxcpus=16
234 * prefer_sockets: cpus=16,sockets=8,cores=1,threads=2,maxcpus=16
235 * prefer_cores: cpus=16,sockets=1,cores=8,threads=2,maxcpus=16 */
236 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, F, 0, T, 2, T, 16),
237 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 8, 1, 2, 16),
238 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 1, 8, 2, 16),
239 }, {
240 /* config: -smp 8,sockets=2,cores=4
241 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
242 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, F, 0, F, 0),
243 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
244 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
245 }, {
246 /* config: -smp 8,sockets=2,threads=2
247 * expect: cpus=8,sockets=2,cores=2,threads=2,maxcpus=8 */
248 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, T, 2, F, 0),
249 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
250 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
251 }, {
252 /* config: -smp 8,sockets=2,maxcpus=16
253 * expect: cpus=8,sockets=2,cores=8,threads=1,maxcpus=16 */
254 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, F, 0, T, 16),
255 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 8, 1, 16),
256 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 8, 1, 16),
257 }, {
258 /* config: -smp 8,cores=4,threads=2
259 * expect: cpus=8,sockets=1,cores=4,threads=2,maxcpus=8 */
260 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, T, 2, F, 0),
261 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
262 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 4, 2, 8),
263 }, {
264 /* config: -smp 8,cores=4,maxcpus=16
265 * expect: cpus=8,sockets=4,cores=4,threads=1,maxcpus=16 */
266 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, F, 0, T, 16),
267 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 4, 4, 1, 16),
268 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 4, 4, 1, 16),
269 }, {
270 /* config: -smp 8,threads=2,maxcpus=16
271 * prefer_sockets: cpus=8,sockets=8,cores=1,threads=2,maxcpus=16
272 * prefer_cores: cpus=8,sockets=1,cores=8,threads=2,maxcpus=16 */
273 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, F, 0, T, 2, T, 16),
274 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 8, 1, 2, 16),
275 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 1, 8, 2, 16),
276 }, {
277 /* config: -smp sockets=2,cores=4,threads=2
278 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
279 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, T, 2, F, 0),
280 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
281 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
282 }, {
283 /* config: -smp sockets=2,cores=4,maxcpus=16
284 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
285 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, F, 0, T, 16),
286 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
287 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
288 }, {
289 /* config: -smp sockets=2,threads=2,maxcpus=16
290 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
291 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, F, 0, T, 2, T, 16),
292 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
293 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
294 }, {
295 /* config: -smp cores=4,threads=2,maxcpus=16
296 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
297 .config = SMP_CONFIG_GENERIC(F, 0, F, 0, T, 4, T, 2, T, 16),
298 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
299 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
300 }, {
301 /* config: -smp 8,sockets=2,cores=4,threads=1
302 * expect: cpus=8,sockets=2,cores=4,threads=1,maxcpus=8 */
303 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 1, F, 0),
304 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
305 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 1, 8),
306 }, {
307 /* config: -smp 8,sockets=2,cores=4,maxcpus=16
308 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
309 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, F, 0, T, 16),
310 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
311 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
312 }, {
313 /* config: -smp 8,sockets=2,threads=2,maxcpus=16
314 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
315 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, F, 0, T, 2, T, 16),
316 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
317 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
318 }, {
319 /* config: -smp 8,cores=4,threads=2,maxcpus=16
320 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
321 .config = SMP_CONFIG_GENERIC(T, 8, F, 0, T, 4, T, 2, T, 16),
322 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
323 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
324 }, {
325 /* config: -smp sockets=2,cores=4,threads=2,maxcpus=16
326 * expect: cpus=16,sockets=2,cores=4,threads=2,maxcpus=16 */
327 .config = SMP_CONFIG_GENERIC(F, 0, T, 2, T, 4, T, 2, T, 16),
328 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
329 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(16, 2, 4, 2, 16),
330 }, {
331 /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=16
332 * expect: cpus=8,sockets=2,cores=4,threads=2,maxcpus=16 */
333 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 16),
334 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
335 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 4, 2, 16),
336 }, {
337 /*
338 * Unsupported parameters are always allowed to be set to '1'
339 * config:
340 * -smp 8,drawers=1,books=1,sockets=2,dies=1,clusters=1,modules=1,\
341 * cores=2,threads=2,maxcpus=8
342 * expect: cpus=8,sockets=2,cores=2,threads=2,maxcpus=8 */
343 .config = SMP_CONFIG_WITH_FULL_TOPO(8, 1, 1, 2, 1, 1, 1, 2, 2, 8),
344 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
345 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
346 },
347 };
348
349 static const struct SMPTestData data_generic_invalid[] = {
350 {
351 /* config: -smp 2,modules=2 */
352 .config = SMP_CONFIG_WITH_MODS_DIES(T, 2, F, 0, F, 0, T, 2,
353 F, 0, F, 0, F, 0),
354 .expect_error = "modules > 1 not supported by this machine's CPU topology",
355 }, {
356 /* config: -smp 2,dies=2 */
357 .config = SMP_CONFIG_WITH_MODS_DIES(T, 2, F, 0, T, 2, F, 0,
358 F, 0, F, 0, F, 0),
359 .expect_error = "dies > 1 not supported by this machine's CPU topology",
360 }, {
361 /* config: -smp 2,clusters=2 */
362 .config = SMP_CONFIG_WITH_CLUSTERS(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0),
363 .expect_error = "clusters > 1 not supported by this machine's CPU topology",
364 }, {
365 /* config: -smp 2,books=2 */
366 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 2, F, 0, T, 2, F,
367 0, F, 0, F, 0, F, 0),
368 .expect_error = "books > 1 not supported by this machine's CPU topology",
369 }, {
370 /* config: -smp 2,drawers=2 */
371 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 2, T, 2, F, 0, F,
372 0, F, 0, F, 0, F, 0),
373 .expect_error = "drawers > 1 not supported by this machine's CPU topology",
374 }, {
375 /* config: -smp 8,sockets=2,cores=4,threads=2,maxcpus=8 */
376 .config = SMP_CONFIG_GENERIC(T, 8, T, 2, T, 4, T, 2, T, 8),
377 .expect_error = "Invalid CPU topology: "
378 "product of the hierarchy must match maxcpus: "
379 "sockets (2) * cores (4) * threads (2) "
380 "!= maxcpus (8)",
381 }, {
382 /* config: -smp 18,sockets=2,cores=4,threads=2,maxcpus=16 */
383 .config = SMP_CONFIG_GENERIC(T, 18, T, 2, T, 4, T, 2, T, 16),
384 .expect_error = "Invalid CPU topology: "
385 "maxcpus must be equal to or greater than smp: "
386 "sockets (2) * cores (4) * threads (2) "
387 "== maxcpus (16) < smp_cpus (18)",
388 }, {
389 /*
390 * config: -smp 1
391 * The test machine should tweak the supported min CPUs to
392 * 2 (MIN_CPUS + 1) for testing.
393 */
394 .config = SMP_CONFIG_GENERIC(T, MIN_CPUS, F, 0, F, 0, F, 0, F, 0),
395 .expect_error = "Invalid SMP CPUs 1. The min CPUs supported "
396 "by machine '" SMP_MACHINE_NAME "' is 2",
397 }, {
398 /*
399 * config: -smp 4096
400 * The test machine should tweak the supported max CPUs to
401 * 4095 (MAX_CPUS - 1) for testing.
402 */
403 .config = SMP_CONFIG_GENERIC(T, 4096, F, 0, F, 0, F, 0, F, 0),
404 .expect_error = "Invalid SMP CPUs 4096. The max CPUs supported "
405 "by machine '" SMP_MACHINE_NAME "' is 4095",
406 },
407 };
408
409 static const struct SMPTestData data_with_modules_invalid[] = {
410 {
411 /* config: -smp 16,sockets=2,modules=2,cores=4,threads=2,maxcpus=16 */
412 .config = SMP_CONFIG_WITH_MODS_DIES(T, 16, T, 2, F, 0, T, 2,
413 T, 4, T, 2, T, 16),
414 .expect_error = "Invalid CPU topology: "
415 "product of the hierarchy must match maxcpus: "
416 "sockets (2) * modules (2) * cores (4) * threads (2) "
417 "!= maxcpus (16)",
418 }, {
419 /* config: -smp 34,sockets=2,modules=2,cores=4,threads=2,maxcpus=32 */
420 .config = SMP_CONFIG_WITH_MODS_DIES(T, 34, T, 2, F, 0, T, 2,
421 T, 4, T, 2, T, 32),
422 .expect_error = "Invalid CPU topology: "
423 "maxcpus must be equal to or greater than smp: "
424 "sockets (2) * modules (2) * cores (4) * threads (2) "
425 "== maxcpus (32) < smp_cpus (34)",
426 },
427 };
428
429 static const struct SMPTestData data_with_dies_invalid[] = {
430 {
431 /* config: -smp 16,sockets=2,dies=2,cores=4,threads=2,maxcpus=16 */
432 .config = SMP_CONFIG_WITH_MODS_DIES(T, 16, T, 2, T, 2, F, 0,
433 T, 4, T, 2, T, 16),
434 .expect_error = "Invalid CPU topology: "
435 "product of the hierarchy must match maxcpus: "
436 "sockets (2) * dies (2) * cores (4) * threads (2) "
437 "!= maxcpus (16)",
438 }, {
439 /* config: -smp 34,sockets=2,dies=2,cores=4,threads=2,maxcpus=32 */
440 .config = SMP_CONFIG_WITH_MODS_DIES(T, 34, T, 2, T, 2, F, 0,
441 T, 4, T, 2, T, 32),
442 .expect_error = "Invalid CPU topology: "
443 "maxcpus must be equal to or greater than smp: "
444 "sockets (2) * dies (2) * cores (4) * threads (2) "
445 "== maxcpus (32) < smp_cpus (34)",
446 },
447 };
448
449 static const struct SMPTestData data_with_modules_dies_invalid[] = {
450 {
451 /*
452 * config: -smp 200,sockets=3,dies=5,modules=2,cores=4,\
453 * threads=2,maxcpus=200
454 */
455 .config = SMP_CONFIG_WITH_MODS_DIES(T, 200, T, 3, T, 5, T,
456 2, T, 4, T, 2, T, 200),
457 .expect_error = "Invalid CPU topology: "
458 "product of the hierarchy must match maxcpus: "
459 "sockets (3) * dies (5) * modules (2) * "
460 "cores (4) * threads (2) != maxcpus (200)",
461 }, {
462 /*
463 * config: -smp 242,sockets=3,dies=5,modules=2,cores=4,\
464 * threads=2,maxcpus=240
465 */
466 .config = SMP_CONFIG_WITH_MODS_DIES(T, 242, T, 3, T, 5, T,
467 2, T, 4, T, 2, T, 240),
468 .expect_error = "Invalid CPU topology: "
469 "maxcpus must be equal to or greater than smp: "
470 "sockets (3) * dies (5) * modules (2) * "
471 "cores (4) * threads (2) "
472 "== maxcpus (240) < smp_cpus (242)",
473 },
474 };
475
476 static const struct SMPTestData data_with_clusters_invalid[] = {
477 {
478 /* config: -smp 16,sockets=2,clusters=2,cores=4,threads=2,maxcpus=16 */
479 .config = SMP_CONFIG_WITH_CLUSTERS(T, 16, T, 2, T, 2, T, 4, T, 2, T, 16),
480 .expect_error = "Invalid CPU topology: "
481 "product of the hierarchy must match maxcpus: "
482 "sockets (2) * clusters (2) * cores (4) * threads (2) "
483 "!= maxcpus (16)",
484 }, {
485 /* config: -smp 34,sockets=2,clusters=2,cores=4,threads=2,maxcpus=32 */
486 .config = SMP_CONFIG_WITH_CLUSTERS(T, 34, T, 2, T, 2, T, 4, T, 2, T, 32),
487 .expect_error = "Invalid CPU topology: "
488 "maxcpus must be equal to or greater than smp: "
489 "sockets (2) * clusters (2) * cores (4) * threads (2) "
490 "== maxcpus (32) < smp_cpus (34)",
491 },
492 };
493
494 static const struct SMPTestData data_with_books_invalid[] = {
495 {
496 /* config: -smp 16,books=2,sockets=2,cores=4,threads=2,maxcpus=16 */
497 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 16, F, 0, T, 2, T,
498 2, T, 4, T, 2, T, 16),
499 .expect_error = "Invalid CPU topology: "
500 "product of the hierarchy must match maxcpus: "
501 "books (2) * sockets (2) * cores (4) * threads (2) "
502 "!= maxcpus (16)",
503 }, {
504 /* config: -smp 34,books=2,sockets=2,cores=4,threads=2,maxcpus=32 */
505 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 34, F, 0, T, 2, T,
506 2, T, 4, T, 2, T, 32),
507 .expect_error = "Invalid CPU topology: "
508 "maxcpus must be equal to or greater than smp: "
509 "books (2) * sockets (2) * cores (4) * threads (2) "
510 "== maxcpus (32) < smp_cpus (34)",
511 },
512 };
513
514 static const struct SMPTestData data_with_drawers_invalid[] = {
515 {
516 /* config: -smp 16,drawers=2,sockets=2,cores=4,threads=2,maxcpus=16 */
517 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 16, T, 2, F, 0, T,
518 2, T, 4, T, 2, T, 16),
519 .expect_error = "Invalid CPU topology: "
520 "product of the hierarchy must match maxcpus: "
521 "drawers (2) * sockets (2) * cores (4) * threads (2) "
522 "!= maxcpus (16)",
523 }, {
524 /* config: -smp 34,drawers=2,sockets=2,cores=4,threads=2,maxcpus=32 */
525 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 34, T, 2, F, 0, T,
526 2, T, 4, T, 2, T, 32),
527 .expect_error = "Invalid CPU topology: "
528 "maxcpus must be equal to or greater than smp: "
529 "drawers (2) * sockets (2) * cores (4) * threads (2) "
530 "== maxcpus (32) < smp_cpus (34)",
531 },
532 };
533
534 static const struct SMPTestData data_with_drawers_books_invalid[] = {
535 {
536 /*
537 * config: -smp 200,drawers=3,books=5,sockets=2,cores=4,\
538 * threads=2,maxcpus=200
539 */
540 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 200, T, 3, T, 5, T,
541 2, T, 4, T, 2, T, 200),
542 .expect_error = "Invalid CPU topology: "
543 "product of the hierarchy must match maxcpus: "
544 "drawers (3) * books (5) * sockets (2) * "
545 "cores (4) * threads (2) != maxcpus (200)",
546 }, {
547 /*
548 * config: -smp 242,drawers=3,books=5,sockets=2,cores=4,\
549 * threads=2,maxcpus=240
550 */
551 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 242, T, 3, T, 5, T,
552 2, T, 4, T, 2, T, 240),
553 .expect_error = "Invalid CPU topology: "
554 "maxcpus must be equal to or greater than smp: "
555 "drawers (3) * books (5) * sockets (2) * "
556 "cores (4) * threads (2) "
557 "== maxcpus (240) < smp_cpus (242)",
558 },
559 };
560
561 static const struct SMPTestData data_full_topo_invalid[] = {
562 {
563 /*
564 * config: -smp 200,drawers=3,books=5,sockets=2,dies=4,\
565 * clusters=2,modules=3,cores=7,threads=2,\
566 * maxcpus=200
567 */
568 .config = SMP_CONFIG_WITH_FULL_TOPO(200, 3, 5, 2, 4, 2, 3, 7, 2, 200),
569 .expect_error = "Invalid CPU topology: "
570 "product of the hierarchy must match maxcpus: "
571 "drawers (3) * books (5) * sockets (2) * dies (4) * "
572 "clusters (2) * modules (3) * cores (7) * threads (2) "
573 "!= maxcpus (200)",
574 }, {
575 /*
576 * config: -smp 2881,drawers=3,books=5,sockets=2,dies=4,\
577 * clusters=2,modules=3,cores=2,threads=2,
578 * maxcpus=2880
579 */
580 .config = SMP_CONFIG_WITH_FULL_TOPO(2881, 3, 5, 2, 4,
581 2, 3, 2, 2, 2880),
582 .expect_error = "Invalid CPU topology: "
583 "maxcpus must be equal to or greater than smp: "
584 "drawers (3) * books (5) * sockets (2) * "
585 "dies (4) * clusters (2) * modules (3) * "
586 "cores (2) * threads (2) == maxcpus (2880) "
587 "< smp_cpus (2881)",
588 }, {
589 /*
590 * config: -smp 1,drawers=3,books=5,sockets=2,dies=4,\
591 * clusters=2,modules=3,cores=3,threads=3,\
592 * maxcpus=6480
593 */
594 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 3, 5, 2, 4, 2, 3, 3, 3, 6480),
595 .expect_error = "Invalid SMP CPUs 6480. The max CPUs supported "
596 "by machine '" SMP_MACHINE_NAME "' is 4096",
597 },
598 };
599
600 static const struct SMPTestData data_zero_topo_invalid[] = {
601 {
602 /*
603 * Test "cpus=0".
604 * config: -smp 0,drawers=1,books=1,sockets=1,dies=1,\
605 * clusters=1,modules=1,cores=1,threads=1,\
606 * maxcpus=1
607 */
608 .config = SMP_CONFIG_WITH_FULL_TOPO(0, 1, 1, 1, 1, 1, 1, 1, 1, 1),
609 .expect_error = "Invalid CPU topology: CPU topology parameters must "
610 "be greater than zero",
611 }, {
612 /*
613 * Test "drawers=0".
614 * config: -smp 1,drawers=0,books=1,sockets=1,dies=1,\
615 * clusters=1,modules=1,cores=1,threads=1,\
616 * maxcpus=1
617 */
618 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 0, 1, 1, 1, 1, 1, 1, 1, 1),
619 .expect_error = "Invalid CPU topology: CPU topology parameters must "
620 "be greater than zero",
621 }, {
622 /*
623 * Test "books=0".
624 * config: -smp 1,drawers=1,books=0,sockets=1,dies=1,\
625 * clusters=1,modules=1,cores=1,threads=1,\
626 * maxcpus=1
627 */
628 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 0, 1, 1, 1, 1, 1, 1, 1),
629 .expect_error = "Invalid CPU topology: CPU topology parameters must "
630 "be greater than zero",
631 }, {
632 /*
633 * Test "sockets=0".
634 * config: -smp 1,drawers=1,books=1,sockets=0,dies=1,\
635 * clusters=1,modules=1,cores=1,threads=1,
636 * maxcpus=1
637 */
638 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 0, 1, 1, 1, 1, 1, 1),
639 .expect_error = "Invalid CPU topology: CPU topology parameters must "
640 "be greater than zero",
641 }, {
642 /*
643 * Test "dies=0".
644 * config: -smp 1,drawers=1,books=1,sockets=1,dies=0,\
645 * clusters=1,modules=1,cores=1,threads=1,\
646 * maxcpus=1
647 */
648 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 0, 1, 1, 1, 1, 1),
649 .expect_error = "Invalid CPU topology: CPU topology parameters must "
650 "be greater than zero",
651 }, {
652 /*
653 * Test "clusters=0".
654 * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\
655 * clusters=0,modules=1,cores=1,threads=1,\
656 * maxcpus=1
657 */
658 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 0, 1, 1, 1, 1),
659 .expect_error = "Invalid CPU topology: CPU topology parameters must "
660 "be greater than zero",
661 }, {
662 /*
663 * Test "modules=0".
664 * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\
665 * clusters=1,modules=0,cores=1,threads=1,\
666 * maxcpus=1
667 */
668 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 0, 1, 1, 1),
669 .expect_error = "Invalid CPU topology: CPU topology parameters must "
670 "be greater than zero",
671 }, {
672 /*
673 * Test "cores=0".
674 * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\
675 * clusters=1,modules=1,cores=0,threads=1,
676 * maxcpus=1
677 */
678 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 0, 1, 1),
679 .expect_error = "Invalid CPU topology: CPU topology parameters must "
680 "be greater than zero",
681 }, {
682 /*
683 * Test "threads=0".
684 * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\
685 * clusters=1,modules=1,cores=1,threads=0,\
686 * maxcpus=1
687 */
688 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 1, 0, 1),
689 .expect_error = "Invalid CPU topology: CPU topology parameters must "
690 "be greater than zero",
691 }, {
692 /*
693 * Test "maxcpus=0".
694 * config: -smp 1,drawers=1,books=1,sockets=1,dies=1,\
695 * clusters=1,modules=1,cores=1,threads=1,\
696 * maxcpus=0
697 */
698 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 1, 1, 0),
699 .expect_error = "Invalid CPU topology: CPU topology parameters must "
700 "be greater than zero",
701 },
702 };
703
smp_config_to_string(const SMPConfiguration * config)704 static char *smp_config_to_string(const SMPConfiguration *config)
705 {
706 return g_strdup_printf(
707 "(SMPConfiguration) {\n"
708 " .has_cpus = %5s, cpus = %" PRId64 ",\n"
709 " .has_drawers = %5s, drawers = %" PRId64 ",\n"
710 " .has_books = %5s, books = %" PRId64 ",\n"
711 " .has_sockets = %5s, sockets = %" PRId64 ",\n"
712 " .has_dies = %5s, dies = %" PRId64 ",\n"
713 " .has_clusters = %5s, clusters = %" PRId64 ",\n"
714 " .has_modules = %5s, modules = %" PRId64 ",\n"
715 " .has_cores = %5s, cores = %" PRId64 ",\n"
716 " .has_threads = %5s, threads = %" PRId64 ",\n"
717 " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n"
718 "}",
719 config->has_cpus ? "true" : "false", config->cpus,
720 config->has_drawers ? "true" : "false", config->drawers,
721 config->has_books ? "true" : "false", config->books,
722 config->has_sockets ? "true" : "false", config->sockets,
723 config->has_dies ? "true" : "false", config->dies,
724 config->has_clusters ? "true" : "false", config->clusters,
725 config->has_modules ? "true" : "false", config->modules,
726 config->has_cores ? "true" : "false", config->cores,
727 config->has_threads ? "true" : "false", config->threads,
728 config->has_maxcpus ? "true" : "false", config->maxcpus);
729 }
730
731 /* Use the different calculation than machine_topo_get_threads_per_socket(). */
cpu_topology_get_threads_per_socket(const CpuTopology * topo)732 static unsigned int cpu_topology_get_threads_per_socket(const CpuTopology *topo)
733 {
734 /* Check the divisor to avoid invalid topology examples causing SIGFPE. */
735 if (!topo->drawers || !topo->books || !topo->sockets) {
736 return 0;
737 } else {
738 return topo->max_cpus / topo->drawers / topo->books / topo->sockets;
739 }
740 }
741
742 /* Use the different calculation than machine_topo_get_cores_per_socket(). */
cpu_topology_get_cores_per_socket(const CpuTopology * topo)743 static unsigned int cpu_topology_get_cores_per_socket(const CpuTopology *topo)
744 {
745 /* Check the divisor to avoid invalid topology examples causing SIGFPE. */
746 if (!topo->threads) {
747 return 0;
748 } else {
749 return cpu_topology_get_threads_per_socket(topo) / topo->threads;
750 }
751 }
752
cpu_topology_to_string(const CpuTopology * topo,unsigned int threads_per_socket,unsigned int cores_per_socket,bool has_clusters)753 static char *cpu_topology_to_string(const CpuTopology *topo,
754 unsigned int threads_per_socket,
755 unsigned int cores_per_socket,
756 bool has_clusters)
757 {
758 return g_strdup_printf(
759 "(CpuTopology) {\n"
760 " .cpus = %u,\n"
761 " .drawers = %u,\n"
762 " .books = %u,\n"
763 " .sockets = %u,\n"
764 " .dies = %u,\n"
765 " .clusters = %u,\n"
766 " .modules = %u,\n"
767 " .cores = %u,\n"
768 " .threads = %u,\n"
769 " .max_cpus = %u,\n"
770 " .threads_per_socket = %u,\n"
771 " .cores_per_socket = %u,\n"
772 " .has_clusters = %s,\n"
773 "}",
774 topo->cpus, topo->drawers, topo->books,
775 topo->sockets, topo->dies, topo->clusters,
776 topo->modules, topo->cores, topo->threads,
777 topo->max_cpus, threads_per_socket, cores_per_socket,
778 has_clusters ? "true" : "false");
779 }
780
check_parse(MachineState * ms,const SMPConfiguration * config,const CpuTopology * expect_topo,const char * expect_err,bool is_valid)781 static void check_parse(MachineState *ms, const SMPConfiguration *config,
782 const CpuTopology *expect_topo, const char *expect_err,
783 bool is_valid)
784 {
785 MachineClass *mc = MACHINE_GET_CLASS(ms);
786 g_autofree char *config_str = smp_config_to_string(config);
787 g_autofree char *expect_topo_str = NULL, *output_topo_str = NULL;
788 unsigned int expect_threads_per_socket, expect_cores_per_socket;
789 unsigned int ms_threads_per_socket, ms_cores_per_socket;
790 Error *err = NULL;
791
792 expect_threads_per_socket =
793 cpu_topology_get_threads_per_socket(expect_topo);
794 expect_cores_per_socket =
795 cpu_topology_get_cores_per_socket(expect_topo);
796 expect_topo_str = cpu_topology_to_string(expect_topo,
797 expect_threads_per_socket,
798 expect_cores_per_socket,
799 config->has_clusters);
800
801 /* call the generic parser */
802 machine_parse_smp_config(ms, config, &err);
803
804 ms_threads_per_socket = machine_topo_get_threads_per_socket(ms);
805 ms_cores_per_socket = machine_topo_get_cores_per_socket(ms);
806 output_topo_str = cpu_topology_to_string(&ms->smp,
807 ms_threads_per_socket,
808 ms_cores_per_socket,
809 mc->smp_props.has_clusters);
810
811 /* when the configuration is supposed to be valid */
812 if (is_valid) {
813 if ((err == NULL) &&
814 (ms->smp.cpus == expect_topo->cpus) &&
815 (ms->smp.drawers == expect_topo->drawers) &&
816 (ms->smp.books == expect_topo->books) &&
817 (ms->smp.sockets == expect_topo->sockets) &&
818 (ms->smp.dies == expect_topo->dies) &&
819 (ms->smp.clusters == expect_topo->clusters) &&
820 (ms->smp.modules == expect_topo->modules) &&
821 (ms->smp.cores == expect_topo->cores) &&
822 (ms->smp.threads == expect_topo->threads) &&
823 (ms->smp.max_cpus == expect_topo->max_cpus) &&
824 (ms_threads_per_socket == expect_threads_per_socket) &&
825 (ms_cores_per_socket == expect_cores_per_socket) &&
826 (mc->smp_props.has_clusters == config->has_clusters)) {
827 return;
828 }
829
830 if (err != NULL) {
831 g_printerr("Test smp_parse failed!\n"
832 "Input configuration: %s\n"
833 "Should be valid: yes\n"
834 "Expected topology: %s\n\n"
835 "Result is valid: no\n"
836 "Output error report: %s\n",
837 config_str, expect_topo_str, error_get_pretty(err));
838 goto end;
839 }
840
841 g_printerr("Test smp_parse failed!\n"
842 "Input configuration: %s\n"
843 "Should be valid: yes\n"
844 "Expected topology: %s\n\n"
845 "Result is valid: yes\n"
846 "Output topology: %s\n",
847 config_str, expect_topo_str, output_topo_str);
848 goto end;
849 }
850
851 /* when the configuration is supposed to be invalid */
852 if (err != NULL) {
853 if (expect_err == NULL ||
854 g_str_equal(expect_err, error_get_pretty(err))) {
855 error_free(err);
856 return;
857 }
858
859 g_printerr("Test smp_parse failed!\n"
860 "Input configuration: %s\n"
861 "Should be valid: no\n"
862 "Expected error report: %s\n\n"
863 "Result is valid: no\n"
864 "Output error report: %s\n",
865 config_str, expect_err, error_get_pretty(err));
866 goto end;
867 }
868
869 g_printerr("Test smp_parse failed!\n"
870 "Input configuration: %s\n"
871 "Should be valid: no\n"
872 "Expected error report: %s\n\n"
873 "Result is valid: yes\n"
874 "Output topology: %s\n",
875 config_str, expect_err, output_topo_str);
876
877 end:
878 if (err != NULL) {
879 error_free(err);
880 }
881
882 abort();
883 }
884
smp_parse_test(MachineState * ms,SMPTestData * data,bool is_valid)885 static void smp_parse_test(MachineState *ms, SMPTestData *data, bool is_valid)
886 {
887 MachineClass *mc = MACHINE_GET_CLASS(ms);
888
889 mc->smp_props.prefer_sockets = true;
890 check_parse(ms, &data->config, &data->expect_prefer_sockets,
891 data->expect_error, is_valid);
892
893 mc->smp_props.prefer_sockets = false;
894 check_parse(ms, &data->config, &data->expect_prefer_cores,
895 data->expect_error, is_valid);
896 }
897
898 /* The parsed results of the unsupported parameters should be 1 */
unsupported_params_init(const MachineClass * mc,SMPTestData * data)899 static void unsupported_params_init(const MachineClass *mc, SMPTestData *data)
900 {
901 if (!mc->smp_props.modules_supported) {
902 data->expect_prefer_sockets.modules = 1;
903 data->expect_prefer_cores.modules = 1;
904 }
905
906 if (!mc->smp_props.dies_supported) {
907 data->expect_prefer_sockets.dies = 1;
908 data->expect_prefer_cores.dies = 1;
909 }
910
911 if (!mc->smp_props.clusters_supported) {
912 data->expect_prefer_sockets.clusters = 1;
913 data->expect_prefer_cores.clusters = 1;
914 }
915
916 if (!mc->smp_props.books_supported) {
917 data->expect_prefer_sockets.books = 1;
918 data->expect_prefer_cores.books = 1;
919 }
920
921 if (!mc->smp_props.drawers_supported) {
922 data->expect_prefer_sockets.drawers = 1;
923 data->expect_prefer_cores.drawers = 1;
924 }
925 }
926
machine_base_class_init(ObjectClass * oc,void * data)927 static void machine_base_class_init(ObjectClass *oc, void *data)
928 {
929 MachineClass *mc = MACHINE_CLASS(oc);
930
931 mc->min_cpus = MIN_CPUS;
932 mc->max_cpus = MAX_CPUS;
933
934 mc->name = g_strdup(SMP_MACHINE_NAME);
935 }
936
machine_generic_invalid_class_init(ObjectClass * oc,void * data)937 static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
938 {
939 MachineClass *mc = MACHINE_CLASS(oc);
940
941 /* Force invalid min CPUs and max CPUs */
942 mc->min_cpus = MIN_CPUS + 1;
943 mc->max_cpus = MAX_CPUS - 1;
944 }
945
machine_with_modules_class_init(ObjectClass * oc,void * data)946 static void machine_with_modules_class_init(ObjectClass *oc, void *data)
947 {
948 MachineClass *mc = MACHINE_CLASS(oc);
949
950 mc->smp_props.modules_supported = true;
951 }
952
machine_with_dies_class_init(ObjectClass * oc,void * data)953 static void machine_with_dies_class_init(ObjectClass *oc, void *data)
954 {
955 MachineClass *mc = MACHINE_CLASS(oc);
956
957 mc->smp_props.dies_supported = true;
958 }
959
machine_with_modules_dies_class_init(ObjectClass * oc,void * data)960 static void machine_with_modules_dies_class_init(ObjectClass *oc, void *data)
961 {
962 MachineClass *mc = MACHINE_CLASS(oc);
963
964 mc->smp_props.modules_supported = true;
965 mc->smp_props.dies_supported = true;
966 }
967
machine_with_clusters_class_init(ObjectClass * oc,void * data)968 static void machine_with_clusters_class_init(ObjectClass *oc, void *data)
969 {
970 MachineClass *mc = MACHINE_CLASS(oc);
971
972 mc->smp_props.clusters_supported = true;
973 }
974
machine_with_books_class_init(ObjectClass * oc,void * data)975 static void machine_with_books_class_init(ObjectClass *oc, void *data)
976 {
977 MachineClass *mc = MACHINE_CLASS(oc);
978
979 mc->smp_props.books_supported = true;
980 }
981
machine_with_drawers_class_init(ObjectClass * oc,void * data)982 static void machine_with_drawers_class_init(ObjectClass *oc, void *data)
983 {
984 MachineClass *mc = MACHINE_CLASS(oc);
985
986 mc->smp_props.drawers_supported = true;
987 }
988
machine_with_drawers_books_class_init(ObjectClass * oc,void * data)989 static void machine_with_drawers_books_class_init(ObjectClass *oc, void *data)
990 {
991 MachineClass *mc = MACHINE_CLASS(oc);
992
993 mc->smp_props.drawers_supported = true;
994 mc->smp_props.books_supported = true;
995 }
996
machine_full_topo_class_init(ObjectClass * oc,void * data)997 static void machine_full_topo_class_init(ObjectClass *oc, void *data)
998 {
999 MachineClass *mc = MACHINE_CLASS(oc);
1000
1001 mc->smp_props.drawers_supported = true;
1002 mc->smp_props.books_supported = true;
1003 mc->smp_props.dies_supported = true;
1004 mc->smp_props.clusters_supported = true;
1005 mc->smp_props.modules_supported = true;
1006 }
1007
test_generic_valid(const void * opaque)1008 static void test_generic_valid(const void *opaque)
1009 {
1010 const char *machine_type = opaque;
1011 Object *obj = object_new(machine_type);
1012 MachineState *ms = MACHINE(obj);
1013 MachineClass *mc = MACHINE_GET_CLASS(obj);
1014 SMPTestData data = {};
1015 int i;
1016
1017 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1018 data = data_generic_valid[i];
1019 unsupported_params_init(mc, &data);
1020
1021 smp_parse_test(ms, &data, true);
1022 }
1023
1024 object_unref(obj);
1025 }
1026
test_generic_invalid(const void * opaque)1027 static void test_generic_invalid(const void *opaque)
1028 {
1029 const char *machine_type = opaque;
1030 Object *obj = object_new(machine_type);
1031 MachineState *ms = MACHINE(obj);
1032 MachineClass *mc = MACHINE_GET_CLASS(obj);
1033 SMPTestData data = {};
1034 int i;
1035
1036 for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) {
1037 data = data_generic_invalid[i];
1038 unsupported_params_init(mc, &data);
1039
1040 smp_parse_test(ms, &data, false);
1041 }
1042
1043 object_unref(obj);
1044 }
1045
test_with_modules(const void * opaque)1046 static void test_with_modules(const void *opaque)
1047 {
1048 const char *machine_type = opaque;
1049 Object *obj = object_new(machine_type);
1050 MachineState *ms = MACHINE(obj);
1051 MachineClass *mc = MACHINE_GET_CLASS(obj);
1052 SMPTestData data = {};
1053 unsigned int num_modules = 2;
1054 int i;
1055
1056 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1057 data = data_generic_valid[i];
1058 unsupported_params_init(mc, &data);
1059
1060 /* when modules parameter is omitted, it will be set as 1 */
1061 data.expect_prefer_sockets.modules = 1;
1062 data.expect_prefer_cores.modules = 1;
1063
1064 smp_parse_test(ms, &data, true);
1065
1066 /* when modules parameter is specified */
1067 data.config.has_modules = true;
1068 data.config.modules = num_modules;
1069 if (data.config.has_cpus) {
1070 data.config.cpus *= num_modules;
1071 }
1072 if (data.config.has_maxcpus) {
1073 data.config.maxcpus *= num_modules;
1074 }
1075
1076 data.expect_prefer_sockets.modules = num_modules;
1077 data.expect_prefer_sockets.cpus *= num_modules;
1078 data.expect_prefer_sockets.max_cpus *= num_modules;
1079 data.expect_prefer_cores.modules = num_modules;
1080 data.expect_prefer_cores.cpus *= num_modules;
1081 data.expect_prefer_cores.max_cpus *= num_modules;
1082
1083 smp_parse_test(ms, &data, true);
1084 }
1085
1086 for (i = 0; i < ARRAY_SIZE(data_with_modules_invalid); i++) {
1087 data = data_with_modules_invalid[i];
1088 unsupported_params_init(mc, &data);
1089
1090 smp_parse_test(ms, &data, false);
1091 }
1092
1093 object_unref(obj);
1094 }
1095
test_with_dies(const void * opaque)1096 static void test_with_dies(const void *opaque)
1097 {
1098 const char *machine_type = opaque;
1099 Object *obj = object_new(machine_type);
1100 MachineState *ms = MACHINE(obj);
1101 MachineClass *mc = MACHINE_GET_CLASS(obj);
1102 SMPTestData data = {};
1103 unsigned int num_dies = 2;
1104 int i;
1105
1106 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1107 data = data_generic_valid[i];
1108 unsupported_params_init(mc, &data);
1109
1110 /* when dies parameter is omitted, it will be set as 1 */
1111 data.expect_prefer_sockets.dies = 1;
1112 data.expect_prefer_cores.dies = 1;
1113
1114 smp_parse_test(ms, &data, true);
1115
1116 /* when dies parameter is specified */
1117 data.config.has_dies = true;
1118 data.config.dies = num_dies;
1119 if (data.config.has_cpus) {
1120 data.config.cpus *= num_dies;
1121 }
1122 if (data.config.has_maxcpus) {
1123 data.config.maxcpus *= num_dies;
1124 }
1125
1126 data.expect_prefer_sockets.dies = num_dies;
1127 data.expect_prefer_sockets.cpus *= num_dies;
1128 data.expect_prefer_sockets.max_cpus *= num_dies;
1129 data.expect_prefer_cores.dies = num_dies;
1130 data.expect_prefer_cores.cpus *= num_dies;
1131 data.expect_prefer_cores.max_cpus *= num_dies;
1132
1133 smp_parse_test(ms, &data, true);
1134 }
1135
1136 for (i = 0; i < ARRAY_SIZE(data_with_dies_invalid); i++) {
1137 data = data_with_dies_invalid[i];
1138 unsupported_params_init(mc, &data);
1139
1140 smp_parse_test(ms, &data, false);
1141 }
1142
1143 object_unref(obj);
1144 }
1145
test_with_modules_dies(const void * opaque)1146 static void test_with_modules_dies(const void *opaque)
1147 {
1148 const char *machine_type = opaque;
1149 Object *obj = object_new(machine_type);
1150 MachineState *ms = MACHINE(obj);
1151 MachineClass *mc = MACHINE_GET_CLASS(obj);
1152 SMPTestData data = {};
1153 unsigned int num_modules = 5, num_dies = 3;
1154 int i;
1155
1156 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1157 data = data_generic_valid[i];
1158 unsupported_params_init(mc, &data);
1159
1160 /*
1161 * when modules and dies parameters are omitted, they will
1162 * be both set as 1.
1163 */
1164 data.expect_prefer_sockets.modules = 1;
1165 data.expect_prefer_sockets.dies = 1;
1166 data.expect_prefer_cores.modules = 1;
1167 data.expect_prefer_cores.dies = 1;
1168
1169 smp_parse_test(ms, &data, true);
1170
1171 /* when modules and dies parameters are both specified */
1172 data.config.has_modules = true;
1173 data.config.modules = num_modules;
1174 data.config.has_dies = true;
1175 data.config.dies = num_dies;
1176
1177 if (data.config.has_cpus) {
1178 data.config.cpus *= num_modules * num_dies;
1179 }
1180 if (data.config.has_maxcpus) {
1181 data.config.maxcpus *= num_modules * num_dies;
1182 }
1183
1184 data.expect_prefer_sockets.modules = num_modules;
1185 data.expect_prefer_sockets.dies = num_dies;
1186 data.expect_prefer_sockets.cpus *= num_modules * num_dies;
1187 data.expect_prefer_sockets.max_cpus *= num_modules * num_dies;
1188
1189 data.expect_prefer_cores.modules = num_modules;
1190 data.expect_prefer_cores.dies = num_dies;
1191 data.expect_prefer_cores.cpus *= num_modules * num_dies;
1192 data.expect_prefer_cores.max_cpus *= num_modules * num_dies;
1193
1194 smp_parse_test(ms, &data, true);
1195 }
1196
1197 for (i = 0; i < ARRAY_SIZE(data_with_modules_dies_invalid); i++) {
1198 data = data_with_modules_dies_invalid[i];
1199 unsupported_params_init(mc, &data);
1200
1201 smp_parse_test(ms, &data, false);
1202 }
1203
1204 object_unref(obj);
1205 }
1206
test_with_clusters(const void * opaque)1207 static void test_with_clusters(const void *opaque)
1208 {
1209 const char *machine_type = opaque;
1210 Object *obj = object_new(machine_type);
1211 MachineState *ms = MACHINE(obj);
1212 MachineClass *mc = MACHINE_GET_CLASS(obj);
1213 SMPTestData data = {};
1214 unsigned int num_clusters = 2;
1215 int i;
1216
1217 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1218 data = data_generic_valid[i];
1219 unsupported_params_init(mc, &data);
1220
1221 /* when clusters parameter is omitted, it will be set as 1 */
1222 data.expect_prefer_sockets.clusters = 1;
1223 data.expect_prefer_cores.clusters = 1;
1224
1225 smp_parse_test(ms, &data, true);
1226
1227 /* when clusters parameter is specified */
1228 data.config.has_clusters = true;
1229 data.config.clusters = num_clusters;
1230 if (data.config.has_cpus) {
1231 data.config.cpus *= num_clusters;
1232 }
1233 if (data.config.has_maxcpus) {
1234 data.config.maxcpus *= num_clusters;
1235 }
1236
1237 data.expect_prefer_sockets.clusters = num_clusters;
1238 data.expect_prefer_sockets.cpus *= num_clusters;
1239 data.expect_prefer_sockets.max_cpus *= num_clusters;
1240 data.expect_prefer_cores.clusters = num_clusters;
1241 data.expect_prefer_cores.cpus *= num_clusters;
1242 data.expect_prefer_cores.max_cpus *= num_clusters;
1243
1244 smp_parse_test(ms, &data, true);
1245 }
1246
1247 for (i = 0; i < ARRAY_SIZE(data_with_clusters_invalid); i++) {
1248 data = data_with_clusters_invalid[i];
1249 unsupported_params_init(mc, &data);
1250
1251 smp_parse_test(ms, &data, false);
1252 }
1253
1254 object_unref(obj);
1255 }
1256
test_with_books(const void * opaque)1257 static void test_with_books(const void *opaque)
1258 {
1259 const char *machine_type = opaque;
1260 Object *obj = object_new(machine_type);
1261 MachineState *ms = MACHINE(obj);
1262 MachineClass *mc = MACHINE_GET_CLASS(obj);
1263 SMPTestData data = {};
1264 unsigned int num_books = 2;
1265 int i;
1266
1267 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1268 data = data_generic_valid[i];
1269 unsupported_params_init(mc, &data);
1270
1271 /* when books parameter is omitted, it will be set as 1 */
1272 data.expect_prefer_sockets.books = 1;
1273 data.expect_prefer_cores.books = 1;
1274
1275 smp_parse_test(ms, &data, true);
1276
1277 /* when books parameter is specified */
1278 data.config.has_books = true;
1279 data.config.books = num_books;
1280 if (data.config.has_cpus) {
1281 data.config.cpus *= num_books;
1282 }
1283 if (data.config.has_maxcpus) {
1284 data.config.maxcpus *= num_books;
1285 }
1286
1287 data.expect_prefer_sockets.books = num_books;
1288 data.expect_prefer_sockets.cpus *= num_books;
1289 data.expect_prefer_sockets.max_cpus *= num_books;
1290 data.expect_prefer_cores.books = num_books;
1291 data.expect_prefer_cores.cpus *= num_books;
1292 data.expect_prefer_cores.max_cpus *= num_books;
1293
1294 smp_parse_test(ms, &data, true);
1295 }
1296
1297 for (i = 0; i < ARRAY_SIZE(data_with_books_invalid); i++) {
1298 data = data_with_books_invalid[i];
1299 unsupported_params_init(mc, &data);
1300
1301 smp_parse_test(ms, &data, false);
1302 }
1303
1304 object_unref(obj);
1305 }
1306
test_with_drawers(const void * opaque)1307 static void test_with_drawers(const void *opaque)
1308 {
1309 const char *machine_type = opaque;
1310 Object *obj = object_new(machine_type);
1311 MachineState *ms = MACHINE(obj);
1312 MachineClass *mc = MACHINE_GET_CLASS(obj);
1313 SMPTestData data = {};
1314 unsigned int num_drawers = 2;
1315 int i;
1316
1317 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1318 data = data_generic_valid[i];
1319 unsupported_params_init(mc, &data);
1320
1321 /* when drawers parameter is omitted, it will be set as 1 */
1322 data.expect_prefer_sockets.drawers = 1;
1323 data.expect_prefer_cores.drawers = 1;
1324
1325 smp_parse_test(ms, &data, true);
1326
1327 /* when drawers parameter is specified */
1328 data.config.has_drawers = true;
1329 data.config.drawers = num_drawers;
1330 if (data.config.has_cpus) {
1331 data.config.cpus *= num_drawers;
1332 }
1333 if (data.config.has_maxcpus) {
1334 data.config.maxcpus *= num_drawers;
1335 }
1336
1337 data.expect_prefer_sockets.drawers = num_drawers;
1338 data.expect_prefer_sockets.cpus *= num_drawers;
1339 data.expect_prefer_sockets.max_cpus *= num_drawers;
1340 data.expect_prefer_cores.drawers = num_drawers;
1341 data.expect_prefer_cores.cpus *= num_drawers;
1342 data.expect_prefer_cores.max_cpus *= num_drawers;
1343
1344 smp_parse_test(ms, &data, true);
1345 }
1346
1347 for (i = 0; i < ARRAY_SIZE(data_with_drawers_invalid); i++) {
1348 data = data_with_drawers_invalid[i];
1349 unsupported_params_init(mc, &data);
1350
1351 smp_parse_test(ms, &data, false);
1352 }
1353
1354 object_unref(obj);
1355 }
1356
test_with_drawers_books(const void * opaque)1357 static void test_with_drawers_books(const void *opaque)
1358 {
1359 const char *machine_type = opaque;
1360 Object *obj = object_new(machine_type);
1361 MachineState *ms = MACHINE(obj);
1362 MachineClass *mc = MACHINE_GET_CLASS(obj);
1363 SMPTestData data = {};
1364 unsigned int num_drawers = 5, num_books = 3;
1365 int i;
1366
1367 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1368 data = data_generic_valid[i];
1369 unsupported_params_init(mc, &data);
1370
1371 /*
1372 * when drawers and books parameters are omitted, they will
1373 * be both set as 1.
1374 */
1375 data.expect_prefer_sockets.drawers = 1;
1376 data.expect_prefer_sockets.books = 1;
1377 data.expect_prefer_cores.drawers = 1;
1378 data.expect_prefer_cores.books = 1;
1379
1380 smp_parse_test(ms, &data, true);
1381
1382 /* when drawers and books parameters are both specified */
1383 data.config.has_drawers = true;
1384 data.config.drawers = num_drawers;
1385 data.config.has_books = true;
1386 data.config.books = num_books;
1387
1388 if (data.config.has_cpus) {
1389 data.config.cpus *= num_drawers * num_books;
1390 }
1391 if (data.config.has_maxcpus) {
1392 data.config.maxcpus *= num_drawers * num_books;
1393 }
1394
1395 data.expect_prefer_sockets.drawers = num_drawers;
1396 data.expect_prefer_sockets.books = num_books;
1397 data.expect_prefer_sockets.cpus *= num_drawers * num_books;
1398 data.expect_prefer_sockets.max_cpus *= num_drawers * num_books;
1399
1400 data.expect_prefer_cores.drawers = num_drawers;
1401 data.expect_prefer_cores.books = num_books;
1402 data.expect_prefer_cores.cpus *= num_drawers * num_books;
1403 data.expect_prefer_cores.max_cpus *= num_drawers * num_books;
1404
1405 smp_parse_test(ms, &data, true);
1406 }
1407
1408 for (i = 0; i < ARRAY_SIZE(data_with_drawers_books_invalid); i++) {
1409 data = data_with_drawers_books_invalid[i];
1410 unsupported_params_init(mc, &data);
1411
1412 smp_parse_test(ms, &data, false);
1413 }
1414
1415 object_unref(obj);
1416 }
1417
test_full_topo(const void * opaque)1418 static void test_full_topo(const void *opaque)
1419 {
1420 const char *machine_type = opaque;
1421 Object *obj = object_new(machine_type);
1422 MachineState *ms = MACHINE(obj);
1423 MachineClass *mc = MACHINE_GET_CLASS(obj);
1424 SMPTestData data = {};
1425 unsigned int drawers, books, dies, clusters, modules, multiplier;
1426 int i;
1427
1428 drawers = 5;
1429 books = 3;
1430 dies = 2;
1431 clusters = 3;
1432 modules = 2;
1433
1434 multiplier = drawers * books * dies * clusters * modules;
1435 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1436 data = data_generic_valid[i];
1437 unsupported_params_init(mc, &data);
1438
1439 /*
1440 * when drawers, books, dies, clusters and modules parameters are
1441 * omitted, they will be set as 1.
1442 */
1443 data.expect_prefer_sockets.drawers = 1;
1444 data.expect_prefer_sockets.books = 1;
1445 data.expect_prefer_sockets.dies = 1;
1446 data.expect_prefer_sockets.clusters = 1;
1447 data.expect_prefer_sockets.modules = 1;
1448 data.expect_prefer_cores.drawers = 1;
1449 data.expect_prefer_cores.books = 1;
1450 data.expect_prefer_cores.dies = 1;
1451 data.expect_prefer_cores.clusters = 1;
1452 data.expect_prefer_cores.modules = 1;
1453
1454 smp_parse_test(ms, &data, true);
1455
1456 /*
1457 * when drawers, books, dies, clusters and modules parameters
1458 * are specified.
1459 */
1460 data.config.has_drawers = true;
1461 data.config.drawers = drawers;
1462 data.config.has_books = true;
1463 data.config.books = books;
1464 data.config.has_dies = true;
1465 data.config.dies = dies;
1466 data.config.has_clusters = true;
1467 data.config.clusters = clusters;
1468 data.config.has_modules = true;
1469 data.config.modules = modules;
1470
1471 if (data.config.has_cpus) {
1472 data.config.cpus *= multiplier;
1473 }
1474 if (data.config.has_maxcpus) {
1475 data.config.maxcpus *= multiplier;
1476 }
1477
1478 data.expect_prefer_sockets.drawers = drawers;
1479 data.expect_prefer_sockets.books = books;
1480 data.expect_prefer_sockets.dies = dies;
1481 data.expect_prefer_sockets.clusters = clusters;
1482 data.expect_prefer_sockets.modules = modules;
1483 data.expect_prefer_sockets.cpus *= multiplier;
1484 data.expect_prefer_sockets.max_cpus *= multiplier;
1485
1486 data.expect_prefer_cores.drawers = drawers;
1487 data.expect_prefer_cores.books = books;
1488 data.expect_prefer_cores.dies = dies;
1489 data.expect_prefer_cores.clusters = clusters;
1490 data.expect_prefer_cores.modules = modules;
1491 data.expect_prefer_cores.cpus *= multiplier;
1492 data.expect_prefer_cores.max_cpus *= multiplier;
1493
1494 smp_parse_test(ms, &data, true);
1495 }
1496
1497 for (i = 0; i < ARRAY_SIZE(data_full_topo_invalid); i++) {
1498 data = data_full_topo_invalid[i];
1499 unsupported_params_init(mc, &data);
1500
1501 smp_parse_test(ms, &data, false);
1502 }
1503
1504 for (i = 0; i < ARRAY_SIZE(data_zero_topo_invalid); i++) {
1505 data = data_zero_topo_invalid[i];
1506 unsupported_params_init(mc, &data);
1507
1508 smp_parse_test(ms, &data, false);
1509 }
1510
1511 object_unref(obj);
1512 }
1513
1514 /* Type info of the tested machine */
1515 static const TypeInfo smp_machine_types[] = {
1516 {
1517 .name = TYPE_MACHINE,
1518 .parent = TYPE_OBJECT,
1519 .abstract = true,
1520 .class_init = machine_base_class_init,
1521 .class_size = sizeof(MachineClass),
1522 .instance_size = sizeof(MachineState),
1523 }, {
1524 .name = MACHINE_TYPE_NAME("smp-generic-valid"),
1525 .parent = TYPE_MACHINE,
1526 }, {
1527 .name = MACHINE_TYPE_NAME("smp-generic-invalid"),
1528 .parent = TYPE_MACHINE,
1529 .class_init = machine_generic_invalid_class_init,
1530 }, {
1531 .name = MACHINE_TYPE_NAME("smp-with-modules"),
1532 .parent = TYPE_MACHINE,
1533 .class_init = machine_with_modules_class_init,
1534 }, {
1535 .name = MACHINE_TYPE_NAME("smp-with-dies"),
1536 .parent = TYPE_MACHINE,
1537 .class_init = machine_with_dies_class_init,
1538 }, {
1539 .name = MACHINE_TYPE_NAME("smp-with-modules-dies"),
1540 .parent = TYPE_MACHINE,
1541 .class_init = machine_with_modules_dies_class_init,
1542 }, {
1543 .name = MACHINE_TYPE_NAME("smp-with-clusters"),
1544 .parent = TYPE_MACHINE,
1545 .class_init = machine_with_clusters_class_init,
1546 }, {
1547 .name = MACHINE_TYPE_NAME("smp-with-books"),
1548 .parent = TYPE_MACHINE,
1549 .class_init = machine_with_books_class_init,
1550 }, {
1551 .name = MACHINE_TYPE_NAME("smp-with-drawers"),
1552 .parent = TYPE_MACHINE,
1553 .class_init = machine_with_drawers_class_init,
1554 }, {
1555 .name = MACHINE_TYPE_NAME("smp-with-drawers-books"),
1556 .parent = TYPE_MACHINE,
1557 .class_init = machine_with_drawers_books_class_init,
1558 }, {
1559 .name = MACHINE_TYPE_NAME("smp-full-topo"),
1560 .parent = TYPE_MACHINE,
1561 .class_init = machine_full_topo_class_init,
1562 }
1563 };
1564
DEFINE_TYPES(smp_machine_types)1565 DEFINE_TYPES(smp_machine_types)
1566
1567 int main(int argc, char *argv[])
1568 {
1569 module_call_init(MODULE_INIT_QOM);
1570
1571 g_test_init(&argc, &argv, NULL);
1572
1573 g_test_add_data_func("/test-smp-parse/generic/valid",
1574 MACHINE_TYPE_NAME("smp-generic-valid"),
1575 test_generic_valid);
1576 g_test_add_data_func("/test-smp-parse/generic/invalid",
1577 MACHINE_TYPE_NAME("smp-generic-invalid"),
1578 test_generic_invalid);
1579 g_test_add_data_func("/test-smp-parse/with_modules",
1580 MACHINE_TYPE_NAME("smp-with-modules"),
1581 test_with_modules);
1582 g_test_add_data_func("/test-smp-parse/with_dies",
1583 MACHINE_TYPE_NAME("smp-with-dies"),
1584 test_with_dies);
1585 g_test_add_data_func("/test-smp-parse/with_modules_dies",
1586 MACHINE_TYPE_NAME("smp-with-modules-dies"),
1587 test_with_modules_dies);
1588 g_test_add_data_func("/test-smp-parse/with_clusters",
1589 MACHINE_TYPE_NAME("smp-with-clusters"),
1590 test_with_clusters);
1591 g_test_add_data_func("/test-smp-parse/with_books",
1592 MACHINE_TYPE_NAME("smp-with-books"),
1593 test_with_books);
1594 g_test_add_data_func("/test-smp-parse/with_drawers",
1595 MACHINE_TYPE_NAME("smp-with-drawers"),
1596 test_with_drawers);
1597 g_test_add_data_func("/test-smp-parse/with_drawers_books",
1598 MACHINE_TYPE_NAME("smp-with-drawers-books"),
1599 test_with_drawers_books);
1600 g_test_add_data_func("/test-smp-parse/full",
1601 MACHINE_TYPE_NAME("smp-full-topo"),
1602 test_full_topo);
1603
1604 g_test_run();
1605
1606 return 0;
1607 }
1608