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,const void * data)927 static void machine_base_class_init(ObjectClass *oc, const 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,const void * data)937 static void machine_generic_invalid_class_init(ObjectClass *oc,
938 const void *data)
939 {
940 MachineClass *mc = MACHINE_CLASS(oc);
941
942 /* Force invalid min CPUs and max CPUs */
943 mc->min_cpus = MIN_CPUS + 1;
944 mc->max_cpus = MAX_CPUS - 1;
945 }
946
machine_with_modules_class_init(ObjectClass * oc,const void * data)947 static void machine_with_modules_class_init(ObjectClass *oc, const void *data)
948 {
949 MachineClass *mc = MACHINE_CLASS(oc);
950
951 mc->smp_props.modules_supported = true;
952 }
953
machine_with_dies_class_init(ObjectClass * oc,const void * data)954 static void machine_with_dies_class_init(ObjectClass *oc, const void *data)
955 {
956 MachineClass *mc = MACHINE_CLASS(oc);
957
958 mc->smp_props.dies_supported = true;
959 }
960
machine_with_modules_dies_class_init(ObjectClass * oc,const void * data)961 static void machine_with_modules_dies_class_init(ObjectClass *oc,
962 const void *data)
963 {
964 MachineClass *mc = MACHINE_CLASS(oc);
965
966 mc->smp_props.modules_supported = true;
967 mc->smp_props.dies_supported = true;
968 }
969
machine_with_clusters_class_init(ObjectClass * oc,const void * data)970 static void machine_with_clusters_class_init(ObjectClass *oc, const void *data)
971 {
972 MachineClass *mc = MACHINE_CLASS(oc);
973
974 mc->smp_props.clusters_supported = true;
975 }
976
machine_with_books_class_init(ObjectClass * oc,const void * data)977 static void machine_with_books_class_init(ObjectClass *oc, const void *data)
978 {
979 MachineClass *mc = MACHINE_CLASS(oc);
980
981 mc->smp_props.books_supported = true;
982 }
983
machine_with_drawers_class_init(ObjectClass * oc,const void * data)984 static void machine_with_drawers_class_init(ObjectClass *oc, const void *data)
985 {
986 MachineClass *mc = MACHINE_CLASS(oc);
987
988 mc->smp_props.drawers_supported = true;
989 }
990
machine_with_drawers_books_class_init(ObjectClass * oc,const void * data)991 static void machine_with_drawers_books_class_init(ObjectClass *oc,
992 const void *data)
993 {
994 MachineClass *mc = MACHINE_CLASS(oc);
995
996 mc->smp_props.drawers_supported = true;
997 mc->smp_props.books_supported = true;
998 }
999
machine_full_topo_class_init(ObjectClass * oc,const void * data)1000 static void machine_full_topo_class_init(ObjectClass *oc, const void *data)
1001 {
1002 MachineClass *mc = MACHINE_CLASS(oc);
1003
1004 mc->smp_props.drawers_supported = true;
1005 mc->smp_props.books_supported = true;
1006 mc->smp_props.dies_supported = true;
1007 mc->smp_props.clusters_supported = true;
1008 mc->smp_props.modules_supported = true;
1009 }
1010
test_generic_valid(const void * opaque)1011 static void test_generic_valid(const void *opaque)
1012 {
1013 const char *machine_type = opaque;
1014 Object *obj = object_new(machine_type);
1015 MachineState *ms = MACHINE(obj);
1016 MachineClass *mc = MACHINE_GET_CLASS(obj);
1017 SMPTestData data = {};
1018 int i;
1019
1020 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1021 data = data_generic_valid[i];
1022 unsupported_params_init(mc, &data);
1023
1024 smp_parse_test(ms, &data, true);
1025 }
1026
1027 object_unref(obj);
1028 }
1029
test_generic_invalid(const void * opaque)1030 static void test_generic_invalid(const void *opaque)
1031 {
1032 const char *machine_type = opaque;
1033 Object *obj = object_new(machine_type);
1034 MachineState *ms = MACHINE(obj);
1035 MachineClass *mc = MACHINE_GET_CLASS(obj);
1036 SMPTestData data = {};
1037 int i;
1038
1039 for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) {
1040 data = data_generic_invalid[i];
1041 unsupported_params_init(mc, &data);
1042
1043 smp_parse_test(ms, &data, false);
1044 }
1045
1046 object_unref(obj);
1047 }
1048
test_with_modules(const void * opaque)1049 static void test_with_modules(const void *opaque)
1050 {
1051 const char *machine_type = opaque;
1052 Object *obj = object_new(machine_type);
1053 MachineState *ms = MACHINE(obj);
1054 MachineClass *mc = MACHINE_GET_CLASS(obj);
1055 SMPTestData data = {};
1056 unsigned int num_modules = 2;
1057 int i;
1058
1059 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1060 data = data_generic_valid[i];
1061 unsupported_params_init(mc, &data);
1062
1063 /* when modules parameter is omitted, it will be set as 1 */
1064 data.expect_prefer_sockets.modules = 1;
1065 data.expect_prefer_cores.modules = 1;
1066
1067 smp_parse_test(ms, &data, true);
1068
1069 /* when modules parameter is specified */
1070 data.config.has_modules = true;
1071 data.config.modules = num_modules;
1072 if (data.config.has_cpus) {
1073 data.config.cpus *= num_modules;
1074 }
1075 if (data.config.has_maxcpus) {
1076 data.config.maxcpus *= num_modules;
1077 }
1078
1079 data.expect_prefer_sockets.modules = num_modules;
1080 data.expect_prefer_sockets.cpus *= num_modules;
1081 data.expect_prefer_sockets.max_cpus *= num_modules;
1082 data.expect_prefer_cores.modules = num_modules;
1083 data.expect_prefer_cores.cpus *= num_modules;
1084 data.expect_prefer_cores.max_cpus *= num_modules;
1085
1086 smp_parse_test(ms, &data, true);
1087 }
1088
1089 for (i = 0; i < ARRAY_SIZE(data_with_modules_invalid); i++) {
1090 data = data_with_modules_invalid[i];
1091 unsupported_params_init(mc, &data);
1092
1093 smp_parse_test(ms, &data, false);
1094 }
1095
1096 object_unref(obj);
1097 }
1098
test_with_dies(const void * opaque)1099 static void test_with_dies(const void *opaque)
1100 {
1101 const char *machine_type = opaque;
1102 Object *obj = object_new(machine_type);
1103 MachineState *ms = MACHINE(obj);
1104 MachineClass *mc = MACHINE_GET_CLASS(obj);
1105 SMPTestData data = {};
1106 unsigned int num_dies = 2;
1107 int i;
1108
1109 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1110 data = data_generic_valid[i];
1111 unsupported_params_init(mc, &data);
1112
1113 /* when dies parameter is omitted, it will be set as 1 */
1114 data.expect_prefer_sockets.dies = 1;
1115 data.expect_prefer_cores.dies = 1;
1116
1117 smp_parse_test(ms, &data, true);
1118
1119 /* when dies parameter is specified */
1120 data.config.has_dies = true;
1121 data.config.dies = num_dies;
1122 if (data.config.has_cpus) {
1123 data.config.cpus *= num_dies;
1124 }
1125 if (data.config.has_maxcpus) {
1126 data.config.maxcpus *= num_dies;
1127 }
1128
1129 data.expect_prefer_sockets.dies = num_dies;
1130 data.expect_prefer_sockets.cpus *= num_dies;
1131 data.expect_prefer_sockets.max_cpus *= num_dies;
1132 data.expect_prefer_cores.dies = num_dies;
1133 data.expect_prefer_cores.cpus *= num_dies;
1134 data.expect_prefer_cores.max_cpus *= num_dies;
1135
1136 smp_parse_test(ms, &data, true);
1137 }
1138
1139 for (i = 0; i < ARRAY_SIZE(data_with_dies_invalid); i++) {
1140 data = data_with_dies_invalid[i];
1141 unsupported_params_init(mc, &data);
1142
1143 smp_parse_test(ms, &data, false);
1144 }
1145
1146 object_unref(obj);
1147 }
1148
test_with_modules_dies(const void * opaque)1149 static void test_with_modules_dies(const void *opaque)
1150 {
1151 const char *machine_type = opaque;
1152 Object *obj = object_new(machine_type);
1153 MachineState *ms = MACHINE(obj);
1154 MachineClass *mc = MACHINE_GET_CLASS(obj);
1155 SMPTestData data = {};
1156 unsigned int num_modules = 5, num_dies = 3;
1157 int i;
1158
1159 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1160 data = data_generic_valid[i];
1161 unsupported_params_init(mc, &data);
1162
1163 /*
1164 * when modules and dies parameters are omitted, they will
1165 * be both set as 1.
1166 */
1167 data.expect_prefer_sockets.modules = 1;
1168 data.expect_prefer_sockets.dies = 1;
1169 data.expect_prefer_cores.modules = 1;
1170 data.expect_prefer_cores.dies = 1;
1171
1172 smp_parse_test(ms, &data, true);
1173
1174 /* when modules and dies parameters are both specified */
1175 data.config.has_modules = true;
1176 data.config.modules = num_modules;
1177 data.config.has_dies = true;
1178 data.config.dies = num_dies;
1179
1180 if (data.config.has_cpus) {
1181 data.config.cpus *= num_modules * num_dies;
1182 }
1183 if (data.config.has_maxcpus) {
1184 data.config.maxcpus *= num_modules * num_dies;
1185 }
1186
1187 data.expect_prefer_sockets.modules = num_modules;
1188 data.expect_prefer_sockets.dies = num_dies;
1189 data.expect_prefer_sockets.cpus *= num_modules * num_dies;
1190 data.expect_prefer_sockets.max_cpus *= num_modules * num_dies;
1191
1192 data.expect_prefer_cores.modules = num_modules;
1193 data.expect_prefer_cores.dies = num_dies;
1194 data.expect_prefer_cores.cpus *= num_modules * num_dies;
1195 data.expect_prefer_cores.max_cpus *= num_modules * num_dies;
1196
1197 smp_parse_test(ms, &data, true);
1198 }
1199
1200 for (i = 0; i < ARRAY_SIZE(data_with_modules_dies_invalid); i++) {
1201 data = data_with_modules_dies_invalid[i];
1202 unsupported_params_init(mc, &data);
1203
1204 smp_parse_test(ms, &data, false);
1205 }
1206
1207 object_unref(obj);
1208 }
1209
test_with_clusters(const void * opaque)1210 static void test_with_clusters(const void *opaque)
1211 {
1212 const char *machine_type = opaque;
1213 Object *obj = object_new(machine_type);
1214 MachineState *ms = MACHINE(obj);
1215 MachineClass *mc = MACHINE_GET_CLASS(obj);
1216 SMPTestData data = {};
1217 unsigned int num_clusters = 2;
1218 int i;
1219
1220 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1221 data = data_generic_valid[i];
1222 unsupported_params_init(mc, &data);
1223
1224 /* when clusters parameter is omitted, it will be set as 1 */
1225 data.expect_prefer_sockets.clusters = 1;
1226 data.expect_prefer_cores.clusters = 1;
1227
1228 smp_parse_test(ms, &data, true);
1229
1230 /* when clusters parameter is specified */
1231 data.config.has_clusters = true;
1232 data.config.clusters = num_clusters;
1233 if (data.config.has_cpus) {
1234 data.config.cpus *= num_clusters;
1235 }
1236 if (data.config.has_maxcpus) {
1237 data.config.maxcpus *= num_clusters;
1238 }
1239
1240 data.expect_prefer_sockets.clusters = num_clusters;
1241 data.expect_prefer_sockets.cpus *= num_clusters;
1242 data.expect_prefer_sockets.max_cpus *= num_clusters;
1243 data.expect_prefer_cores.clusters = num_clusters;
1244 data.expect_prefer_cores.cpus *= num_clusters;
1245 data.expect_prefer_cores.max_cpus *= num_clusters;
1246
1247 smp_parse_test(ms, &data, true);
1248 }
1249
1250 for (i = 0; i < ARRAY_SIZE(data_with_clusters_invalid); i++) {
1251 data = data_with_clusters_invalid[i];
1252 unsupported_params_init(mc, &data);
1253
1254 smp_parse_test(ms, &data, false);
1255 }
1256
1257 object_unref(obj);
1258 }
1259
test_with_books(const void * opaque)1260 static void test_with_books(const void *opaque)
1261 {
1262 const char *machine_type = opaque;
1263 Object *obj = object_new(machine_type);
1264 MachineState *ms = MACHINE(obj);
1265 MachineClass *mc = MACHINE_GET_CLASS(obj);
1266 SMPTestData data = {};
1267 unsigned int num_books = 2;
1268 int i;
1269
1270 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1271 data = data_generic_valid[i];
1272 unsupported_params_init(mc, &data);
1273
1274 /* when books parameter is omitted, it will be set as 1 */
1275 data.expect_prefer_sockets.books = 1;
1276 data.expect_prefer_cores.books = 1;
1277
1278 smp_parse_test(ms, &data, true);
1279
1280 /* when books parameter is specified */
1281 data.config.has_books = true;
1282 data.config.books = num_books;
1283 if (data.config.has_cpus) {
1284 data.config.cpus *= num_books;
1285 }
1286 if (data.config.has_maxcpus) {
1287 data.config.maxcpus *= num_books;
1288 }
1289
1290 data.expect_prefer_sockets.books = num_books;
1291 data.expect_prefer_sockets.cpus *= num_books;
1292 data.expect_prefer_sockets.max_cpus *= num_books;
1293 data.expect_prefer_cores.books = num_books;
1294 data.expect_prefer_cores.cpus *= num_books;
1295 data.expect_prefer_cores.max_cpus *= num_books;
1296
1297 smp_parse_test(ms, &data, true);
1298 }
1299
1300 for (i = 0; i < ARRAY_SIZE(data_with_books_invalid); i++) {
1301 data = data_with_books_invalid[i];
1302 unsupported_params_init(mc, &data);
1303
1304 smp_parse_test(ms, &data, false);
1305 }
1306
1307 object_unref(obj);
1308 }
1309
test_with_drawers(const void * opaque)1310 static void test_with_drawers(const void *opaque)
1311 {
1312 const char *machine_type = opaque;
1313 Object *obj = object_new(machine_type);
1314 MachineState *ms = MACHINE(obj);
1315 MachineClass *mc = MACHINE_GET_CLASS(obj);
1316 SMPTestData data = {};
1317 unsigned int num_drawers = 2;
1318 int i;
1319
1320 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1321 data = data_generic_valid[i];
1322 unsupported_params_init(mc, &data);
1323
1324 /* when drawers parameter is omitted, it will be set as 1 */
1325 data.expect_prefer_sockets.drawers = 1;
1326 data.expect_prefer_cores.drawers = 1;
1327
1328 smp_parse_test(ms, &data, true);
1329
1330 /* when drawers parameter is specified */
1331 data.config.has_drawers = true;
1332 data.config.drawers = num_drawers;
1333 if (data.config.has_cpus) {
1334 data.config.cpus *= num_drawers;
1335 }
1336 if (data.config.has_maxcpus) {
1337 data.config.maxcpus *= num_drawers;
1338 }
1339
1340 data.expect_prefer_sockets.drawers = num_drawers;
1341 data.expect_prefer_sockets.cpus *= num_drawers;
1342 data.expect_prefer_sockets.max_cpus *= num_drawers;
1343 data.expect_prefer_cores.drawers = num_drawers;
1344 data.expect_prefer_cores.cpus *= num_drawers;
1345 data.expect_prefer_cores.max_cpus *= num_drawers;
1346
1347 smp_parse_test(ms, &data, true);
1348 }
1349
1350 for (i = 0; i < ARRAY_SIZE(data_with_drawers_invalid); i++) {
1351 data = data_with_drawers_invalid[i];
1352 unsupported_params_init(mc, &data);
1353
1354 smp_parse_test(ms, &data, false);
1355 }
1356
1357 object_unref(obj);
1358 }
1359
test_with_drawers_books(const void * opaque)1360 static void test_with_drawers_books(const void *opaque)
1361 {
1362 const char *machine_type = opaque;
1363 Object *obj = object_new(machine_type);
1364 MachineState *ms = MACHINE(obj);
1365 MachineClass *mc = MACHINE_GET_CLASS(obj);
1366 SMPTestData data = {};
1367 unsigned int num_drawers = 5, num_books = 3;
1368 int i;
1369
1370 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1371 data = data_generic_valid[i];
1372 unsupported_params_init(mc, &data);
1373
1374 /*
1375 * when drawers and books parameters are omitted, they will
1376 * be both set as 1.
1377 */
1378 data.expect_prefer_sockets.drawers = 1;
1379 data.expect_prefer_sockets.books = 1;
1380 data.expect_prefer_cores.drawers = 1;
1381 data.expect_prefer_cores.books = 1;
1382
1383 smp_parse_test(ms, &data, true);
1384
1385 /* when drawers and books parameters are both specified */
1386 data.config.has_drawers = true;
1387 data.config.drawers = num_drawers;
1388 data.config.has_books = true;
1389 data.config.books = num_books;
1390
1391 if (data.config.has_cpus) {
1392 data.config.cpus *= num_drawers * num_books;
1393 }
1394 if (data.config.has_maxcpus) {
1395 data.config.maxcpus *= num_drawers * num_books;
1396 }
1397
1398 data.expect_prefer_sockets.drawers = num_drawers;
1399 data.expect_prefer_sockets.books = num_books;
1400 data.expect_prefer_sockets.cpus *= num_drawers * num_books;
1401 data.expect_prefer_sockets.max_cpus *= num_drawers * num_books;
1402
1403 data.expect_prefer_cores.drawers = num_drawers;
1404 data.expect_prefer_cores.books = num_books;
1405 data.expect_prefer_cores.cpus *= num_drawers * num_books;
1406 data.expect_prefer_cores.max_cpus *= num_drawers * num_books;
1407
1408 smp_parse_test(ms, &data, true);
1409 }
1410
1411 for (i = 0; i < ARRAY_SIZE(data_with_drawers_books_invalid); i++) {
1412 data = data_with_drawers_books_invalid[i];
1413 unsupported_params_init(mc, &data);
1414
1415 smp_parse_test(ms, &data, false);
1416 }
1417
1418 object_unref(obj);
1419 }
1420
test_full_topo(const void * opaque)1421 static void test_full_topo(const void *opaque)
1422 {
1423 const char *machine_type = opaque;
1424 Object *obj = object_new(machine_type);
1425 MachineState *ms = MACHINE(obj);
1426 MachineClass *mc = MACHINE_GET_CLASS(obj);
1427 SMPTestData data = {};
1428 unsigned int drawers, books, dies, clusters, modules, multiplier;
1429 int i;
1430
1431 drawers = 5;
1432 books = 3;
1433 dies = 2;
1434 clusters = 3;
1435 modules = 2;
1436
1437 multiplier = drawers * books * dies * clusters * modules;
1438 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1439 data = data_generic_valid[i];
1440 unsupported_params_init(mc, &data);
1441
1442 /*
1443 * when drawers, books, dies, clusters and modules parameters are
1444 * omitted, they will be set as 1.
1445 */
1446 data.expect_prefer_sockets.drawers = 1;
1447 data.expect_prefer_sockets.books = 1;
1448 data.expect_prefer_sockets.dies = 1;
1449 data.expect_prefer_sockets.clusters = 1;
1450 data.expect_prefer_sockets.modules = 1;
1451 data.expect_prefer_cores.drawers = 1;
1452 data.expect_prefer_cores.books = 1;
1453 data.expect_prefer_cores.dies = 1;
1454 data.expect_prefer_cores.clusters = 1;
1455 data.expect_prefer_cores.modules = 1;
1456
1457 smp_parse_test(ms, &data, true);
1458
1459 /*
1460 * when drawers, books, dies, clusters and modules parameters
1461 * are specified.
1462 */
1463 data.config.has_drawers = true;
1464 data.config.drawers = drawers;
1465 data.config.has_books = true;
1466 data.config.books = books;
1467 data.config.has_dies = true;
1468 data.config.dies = dies;
1469 data.config.has_clusters = true;
1470 data.config.clusters = clusters;
1471 data.config.has_modules = true;
1472 data.config.modules = modules;
1473
1474 if (data.config.has_cpus) {
1475 data.config.cpus *= multiplier;
1476 }
1477 if (data.config.has_maxcpus) {
1478 data.config.maxcpus *= multiplier;
1479 }
1480
1481 data.expect_prefer_sockets.drawers = drawers;
1482 data.expect_prefer_sockets.books = books;
1483 data.expect_prefer_sockets.dies = dies;
1484 data.expect_prefer_sockets.clusters = clusters;
1485 data.expect_prefer_sockets.modules = modules;
1486 data.expect_prefer_sockets.cpus *= multiplier;
1487 data.expect_prefer_sockets.max_cpus *= multiplier;
1488
1489 data.expect_prefer_cores.drawers = drawers;
1490 data.expect_prefer_cores.books = books;
1491 data.expect_prefer_cores.dies = dies;
1492 data.expect_prefer_cores.clusters = clusters;
1493 data.expect_prefer_cores.modules = modules;
1494 data.expect_prefer_cores.cpus *= multiplier;
1495 data.expect_prefer_cores.max_cpus *= multiplier;
1496
1497 smp_parse_test(ms, &data, true);
1498 }
1499
1500 for (i = 0; i < ARRAY_SIZE(data_full_topo_invalid); i++) {
1501 data = data_full_topo_invalid[i];
1502 unsupported_params_init(mc, &data);
1503
1504 smp_parse_test(ms, &data, false);
1505 }
1506
1507 for (i = 0; i < ARRAY_SIZE(data_zero_topo_invalid); i++) {
1508 data = data_zero_topo_invalid[i];
1509 unsupported_params_init(mc, &data);
1510
1511 smp_parse_test(ms, &data, false);
1512 }
1513
1514 object_unref(obj);
1515 }
1516
1517 /* Type info of the tested machine */
1518 static const TypeInfo smp_machine_types[] = {
1519 {
1520 .name = TYPE_MACHINE,
1521 .parent = TYPE_OBJECT,
1522 .abstract = true,
1523 .class_init = machine_base_class_init,
1524 .class_size = sizeof(MachineClass),
1525 .instance_size = sizeof(MachineState),
1526 }, {
1527 .name = MACHINE_TYPE_NAME("smp-generic-valid"),
1528 .parent = TYPE_MACHINE,
1529 }, {
1530 .name = MACHINE_TYPE_NAME("smp-generic-invalid"),
1531 .parent = TYPE_MACHINE,
1532 .class_init = machine_generic_invalid_class_init,
1533 }, {
1534 .name = MACHINE_TYPE_NAME("smp-with-modules"),
1535 .parent = TYPE_MACHINE,
1536 .class_init = machine_with_modules_class_init,
1537 }, {
1538 .name = MACHINE_TYPE_NAME("smp-with-dies"),
1539 .parent = TYPE_MACHINE,
1540 .class_init = machine_with_dies_class_init,
1541 }, {
1542 .name = MACHINE_TYPE_NAME("smp-with-modules-dies"),
1543 .parent = TYPE_MACHINE,
1544 .class_init = machine_with_modules_dies_class_init,
1545 }, {
1546 .name = MACHINE_TYPE_NAME("smp-with-clusters"),
1547 .parent = TYPE_MACHINE,
1548 .class_init = machine_with_clusters_class_init,
1549 }, {
1550 .name = MACHINE_TYPE_NAME("smp-with-books"),
1551 .parent = TYPE_MACHINE,
1552 .class_init = machine_with_books_class_init,
1553 }, {
1554 .name = MACHINE_TYPE_NAME("smp-with-drawers"),
1555 .parent = TYPE_MACHINE,
1556 .class_init = machine_with_drawers_class_init,
1557 }, {
1558 .name = MACHINE_TYPE_NAME("smp-with-drawers-books"),
1559 .parent = TYPE_MACHINE,
1560 .class_init = machine_with_drawers_books_class_init,
1561 }, {
1562 .name = MACHINE_TYPE_NAME("smp-full-topo"),
1563 .parent = TYPE_MACHINE,
1564 .class_init = machine_full_topo_class_init,
1565 }
1566 };
1567
DEFINE_TYPES(smp_machine_types)1568 DEFINE_TYPES(smp_machine_types)
1569
1570 int main(int argc, char *argv[])
1571 {
1572 module_call_init(MODULE_INIT_QOM);
1573
1574 g_test_init(&argc, &argv, NULL);
1575
1576 g_test_add_data_func("/test-smp-parse/generic/valid",
1577 MACHINE_TYPE_NAME("smp-generic-valid"),
1578 test_generic_valid);
1579 g_test_add_data_func("/test-smp-parse/generic/invalid",
1580 MACHINE_TYPE_NAME("smp-generic-invalid"),
1581 test_generic_invalid);
1582 g_test_add_data_func("/test-smp-parse/with_modules",
1583 MACHINE_TYPE_NAME("smp-with-modules"),
1584 test_with_modules);
1585 g_test_add_data_func("/test-smp-parse/with_dies",
1586 MACHINE_TYPE_NAME("smp-with-dies"),
1587 test_with_dies);
1588 g_test_add_data_func("/test-smp-parse/with_modules_dies",
1589 MACHINE_TYPE_NAME("smp-with-modules-dies"),
1590 test_with_modules_dies);
1591 g_test_add_data_func("/test-smp-parse/with_clusters",
1592 MACHINE_TYPE_NAME("smp-with-clusters"),
1593 test_with_clusters);
1594 g_test_add_data_func("/test-smp-parse/with_books",
1595 MACHINE_TYPE_NAME("smp-with-books"),
1596 test_with_books);
1597 g_test_add_data_func("/test-smp-parse/with_drawers",
1598 MACHINE_TYPE_NAME("smp-with-drawers"),
1599 test_with_drawers);
1600 g_test_add_data_func("/test-smp-parse/with_drawers_books",
1601 MACHINE_TYPE_NAME("smp-with-drawers-books"),
1602 test_with_drawers_books);
1603 g_test_add_data_func("/test-smp-parse/full",
1604 MACHINE_TYPE_NAME("smp-full-topo"),
1605 test_full_topo);
1606
1607 g_test_run();
1608
1609 return 0;
1610 }
1611