xref: /qemu/tests/unit/test-smp-parse.c (revision 06b40d250ecfa1633209c2e431a7a38acfd03a98)
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