blob: f9bccb56abc7e188250f2ebd66b5131694dc34a9 [file] [log] [blame]
Yanan Wang9e8e3932021-10-26 11:46:59 +08001/*
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
Zhao Liuf4e65d62024-03-09 00:01:41 +080023#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 */
Yanan Wang9e8e3932021-10-26 11:46:59 +080025
Philippe Mathieu-Daudé7b6d1bc2021-11-11 10:27:45 +010026#define SMP_MACHINE_NAME "TEST-SMP"
27
Yanan Wang9e8e3932021-10-26 11:46:59 +080028/*
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/*
Zhao Liua05ed352024-05-29 14:19:23 +080051 * Currently a 5-level topology hierarchy is supported on PC machines
52 * -sockets/dies/modules/cores/threads
Yanan Wang9e8e3932021-10-26 11:46:59 +080053 */
Zhao Liua05ed352024-05-29 14:19:23 +080054#define SMP_CONFIG_WITH_MODS_DIES(ha, a, hb, b, hc, c, hd, d, \
55 he, e, hf, f, hg, g) \
Yanan Wang9e8e3932021-10-26 11:46:59 +080056 { \
57 .has_cpus = ha, .cpus = a, \
58 .has_sockets = hb, .sockets = b, \
59 .has_dies = hc, .dies = c, \
Zhao Liua05ed352024-05-29 14:19:23 +080060 .has_modules = hd, .modules = d, \
61 .has_cores = he, .cores = e, \
62 .has_threads = hf, .threads = f, \
63 .has_maxcpus = hg, .maxcpus = g, \
Yanan Wang9e8e3932021-10-26 11:46:59 +080064 }
65
Yanan Wange5ef89a2021-12-28 17:22:11 +080066/*
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
Zhao Liuf0fe1cd2024-03-09 00:01:43 +080080/*
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
Zhao Liuef88e1e2024-03-09 00:01:46 +080096/*
Zhao Liu6a235522024-05-29 14:19:25 +080097 * Currently QEMU supports up to a 8-level topology hierarchy, which is the
Zhao Liuef88e1e2024-03-09 00:01:46 +080098 * QEMU's unified abstract representation of CPU topology.
Zhao Liu6a235522024-05-29 14:19:25 +080099 * -drawers/books/sockets/dies/clusters/modules/cores/threads
Zhao Liuef88e1e2024-03-09 00:01:46 +0800100 */
Zhao Liu6a235522024-05-29 14:19:25 +0800101#define SMP_CONFIG_WITH_FULL_TOPO(a, b, c, d, e, f, g, h, i, j) \
Zhao Liuef88e1e2024-03-09 00:01:46 +0800102 { \
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, \
Zhao Liu6a235522024-05-29 14:19:25 +0800109 .has_modules = true, .modules = g, \
110 .has_cores = true, .cores = h, \
111 .has_threads = true, .threads = i, \
112 .has_maxcpus = true, .maxcpus = j, \
Zhao Liuef88e1e2024-03-09 00:01:46 +0800113 }
114
Yanan Wang9e8e3932021-10-26 11:46:59 +0800115/**
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 */
124typedef struct SMPTestData {
125 SMPConfiguration config;
126 CpuTopology expect_prefer_sockets;
127 CpuTopology expect_prefer_cores;
128 const char *expect_error;
129} SMPTestData;
130
Yanan Wang9e8e3932021-10-26 11:46:59 +0800131/*
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 */
Philippe Mathieu-Daudécf650002021-11-11 10:23:06 +0100137static const struct SMPTestData data_generic_valid[] = {
Yanan Wang9e8e3932021-10-26 11:46:59 +0800138 {
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),
Daniel P. Berrangée68dcbb2024-05-13 13:33:58 +0100336 }, {
337 /*
338 * Unsupported parameters are always allowed to be set to '1'
Zhao Liu7c56fb72024-05-29 14:19:19 +0800339 * config:
Zhao Liu6a235522024-05-29 14:19:25 +0800340 * -smp 8,drawers=1,books=1,sockets=2,dies=1,clusters=1,modules=1,\
341 * cores=2,threads=2,maxcpus=8
Daniel P. Berrangée68dcbb2024-05-13 13:33:58 +0100342 * expect: cpus=8,sockets=2,cores=2,threads=2,maxcpus=8 */
Zhao Liu6a235522024-05-29 14:19:25 +0800343 .config = SMP_CONFIG_WITH_FULL_TOPO(8, 1, 1, 2, 1, 1, 1, 2, 2, 8),
Daniel P. Berrangée68dcbb2024-05-13 13:33:58 +0100344 .expect_prefer_sockets = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
345 .expect_prefer_cores = CPU_TOPOLOGY_GENERIC(8, 2, 2, 2, 8),
Yanan Wang9e8e3932021-10-26 11:46:59 +0800346 },
347};
348
Philippe Mathieu-Daudécf650002021-11-11 10:23:06 +0100349static const struct SMPTestData data_generic_invalid[] = {
Yanan Wang9e8e3932021-10-26 11:46:59 +0800350 {
Zhao Liua05ed352024-05-29 14:19:23 +0800351 /* 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 }, {
Yanan Wang9e8e3932021-10-26 11:46:59 +0800356 /* config: -smp 2,dies=2 */
Zhao Liua05ed352024-05-29 14:19:23 +0800357 .config = SMP_CONFIG_WITH_MODS_DIES(T, 2, F, 0, T, 2, F, 0,
358 F, 0, F, 0, F, 0),
Daniel P. Berrangé9d7950e2024-05-13 13:33:57 +0100359 .expect_error = "dies > 1 not supported by this machine's CPU topology",
Yanan Wang9e8e3932021-10-26 11:46:59 +0800360 }, {
Yanan Wange5ef89a2021-12-28 17:22:11 +0800361 /* config: -smp 2,clusters=2 */
362 .config = SMP_CONFIG_WITH_CLUSTERS(T, 2, F, 0, T, 2, F, 0, F, 0, F, 0),
Daniel P. Berrangé9d7950e2024-05-13 13:33:57 +0100363 .expect_error = "clusters > 1 not supported by this machine's CPU topology",
Yanan Wange5ef89a2021-12-28 17:22:11 +0800364 }, {
Zhao Liuf0fe1cd2024-03-09 00:01:43 +0800365 /* 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),
Daniel P. Berrangé9d7950e2024-05-13 13:33:57 +0100368 .expect_error = "books > 1 not supported by this machine's CPU topology",
Zhao Liuf0fe1cd2024-03-09 00:01:43 +0800369 }, {
Zhao Liu5a4c4142024-03-09 00:01:44 +0800370 /* 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),
Daniel P. Berrangé9d7950e2024-05-13 13:33:57 +0100373 .expect_error = "drawers > 1 not supported by this machine's CPU topology",
Zhao Liu5a4c4142024-03-09 00:01:44 +0800374 }, {
Yanan Wang9e8e3932021-10-26 11:46:59 +0800375 /* 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 }, {
Zhao Liu803f9712024-03-09 00:01:40 +0800389 /*
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),
Yanan Wang9e8e3932021-10-26 11:46:59 +0800395 .expect_error = "Invalid SMP CPUs 1. The min CPUs supported "
Philippe Mathieu-Daudé7b6d1bc2021-11-11 10:27:45 +0100396 "by machine '" SMP_MACHINE_NAME "' is 2",
Yanan Wang9e8e3932021-10-26 11:46:59 +0800397 }, {
Zhao Liu803f9712024-03-09 00:01:40 +0800398 /*
Zhao Liuf4e65d62024-03-09 00:01:41 +0800399 * config: -smp 4096
Zhao Liu803f9712024-03-09 00:01:40 +0800400 * The test machine should tweak the supported max CPUs to
Zhao Liuf4e65d62024-03-09 00:01:41 +0800401 * 4095 (MAX_CPUS - 1) for testing.
Zhao Liu803f9712024-03-09 00:01:40 +0800402 */
Zhao Liuf4e65d62024-03-09 00:01:41 +0800403 .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",
Yanan Wang9e8e3932021-10-26 11:46:59 +0800406 },
407};
408
Zhao Liua05ed352024-05-29 14:19:23 +0800409static 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
Philippe Mathieu-Daudécf650002021-11-11 10:23:06 +0100429static const struct SMPTestData data_with_dies_invalid[] = {
Yanan Wang9e8e3932021-10-26 11:46:59 +0800430 {
431 /* config: -smp 16,sockets=2,dies=2,cores=4,threads=2,maxcpus=16 */
Zhao Liua05ed352024-05-29 14:19:23 +0800432 .config = SMP_CONFIG_WITH_MODS_DIES(T, 16, T, 2, T, 2, F, 0,
433 T, 4, T, 2, T, 16),
Yanan Wang9e8e3932021-10-26 11:46:59 +0800434 .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 */
Zhao Liua05ed352024-05-29 14:19:23 +0800440 .config = SMP_CONFIG_WITH_MODS_DIES(T, 34, T, 2, T, 2, F, 0,
441 T, 4, T, 2, T, 32),
Yanan Wang9e8e3932021-10-26 11:46:59 +0800442 .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
Zhao Liufe4b9952024-05-29 14:19:24 +0800449static 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
Yanan Wange5ef89a2021-12-28 17:22:11 +0800476static 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
Zhao Liuf0fe1cd2024-03-09 00:01:43 +0800494static const struct SMPTestData data_with_books_invalid[] = {
495 {
496 /* config: -smp 16,books=2,sockets=2,cores=4,threads=2,maxcpus=16 */
Zhao Liuaedfeff2024-05-29 14:19:21 +0800497 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 16, F, 0, T, 2, T,
Zhao Liuf0fe1cd2024-03-09 00:01:43 +0800498 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 */
Zhao Liuaedfeff2024-05-29 14:19:21 +0800505 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 34, F, 0, T, 2, T,
Zhao Liuf0fe1cd2024-03-09 00:01:43 +0800506 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
Zhao Liu5a4c4142024-03-09 00:01:44 +0800514static const struct SMPTestData data_with_drawers_invalid[] = {
515 {
516 /* config: -smp 16,drawers=2,sockets=2,cores=4,threads=2,maxcpus=16 */
Zhao Liuaedfeff2024-05-29 14:19:21 +0800517 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 16, T, 2, F, 0, T,
Zhao Liu5a4c4142024-03-09 00:01:44 +0800518 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 */
Zhao Liuaedfeff2024-05-29 14:19:21 +0800525 .config = SMP_CONFIG_WITH_BOOKS_DRAWERS(T, 34, T, 2, F, 0, T,
Zhao Liu5a4c4142024-03-09 00:01:44 +0800526 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
Zhao Liu3f90fb02024-03-09 00:01:45 +0800534static const struct SMPTestData data_with_drawers_books_invalid[] = {
535 {
536 /*
Zhao Liu94aae6e2024-05-29 14:19:18 +0800537 * config: -smp 200,drawers=3,books=5,sockets=2,cores=4,\
538 * threads=2,maxcpus=200
Zhao Liu3f90fb02024-03-09 00:01:45 +0800539 */
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 /*
Zhao Liu94aae6e2024-05-29 14:19:18 +0800548 * config: -smp 242,drawers=3,books=5,sockets=2,cores=4,\
549 * threads=2,maxcpus=240
Zhao Liu3f90fb02024-03-09 00:01:45 +0800550 */
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
Zhao Liuef88e1e2024-03-09 00:01:46 +0800561static const struct SMPTestData data_full_topo_invalid[] = {
562 {
563 /*
564 * config: -smp 200,drawers=3,books=5,sockets=2,dies=4,\
Zhao Liu6a235522024-05-29 14:19:25 +0800565 * clusters=2,modules=3,cores=7,threads=2,\
566 * maxcpus=200
Zhao Liuef88e1e2024-03-09 00:01:46 +0800567 */
Zhao Liu6a235522024-05-29 14:19:25 +0800568 .config = SMP_CONFIG_WITH_FULL_TOPO(200, 3, 5, 2, 4, 2, 3, 7, 2, 200),
Zhao Liuef88e1e2024-03-09 00:01:46 +0800569 .expect_error = "Invalid CPU topology: "
570 "product of the hierarchy must match maxcpus: "
571 "drawers (3) * books (5) * sockets (2) * dies (4) * "
Zhao Liu6a235522024-05-29 14:19:25 +0800572 "clusters (2) * modules (3) * cores (7) * threads (2) "
Zhao Liuef88e1e2024-03-09 00:01:46 +0800573 "!= maxcpus (200)",
574 }, {
575 /*
Zhao Liu6a235522024-05-29 14:19:25 +0800576 * config: -smp 2881,drawers=3,books=5,sockets=2,dies=4,\
577 * clusters=2,modules=3,cores=2,threads=2,
578 * maxcpus=2880
Zhao Liuef88e1e2024-03-09 00:01:46 +0800579 */
Zhao Liu6a235522024-05-29 14:19:25 +0800580 .config = SMP_CONFIG_WITH_FULL_TOPO(2881, 3, 5, 2, 4,
581 2, 3, 2, 2, 2880),
Zhao Liuef88e1e2024-03-09 00:01:46 +0800582 .expect_error = "Invalid CPU topology: "
583 "maxcpus must be equal to or greater than smp: "
Zhao Liu6a235522024-05-29 14:19:25 +0800584 "drawers (3) * books (5) * sockets (2) * "
585 "dies (4) * clusters (2) * modules (3) * "
586 "cores (2) * threads (2) == maxcpus (2880) "
587 "< smp_cpus (2881)",
Zhao Liuef88e1e2024-03-09 00:01:46 +0800588 }, {
589 /*
590 * config: -smp 1,drawers=3,books=5,sockets=2,dies=4,\
Zhao Liu6a235522024-05-29 14:19:25 +0800591 * clusters=2,modules=3,cores=3,threads=3,\
592 * maxcpus=6480
Zhao Liuef88e1e2024-03-09 00:01:46 +0800593 */
Zhao Liu6a235522024-05-29 14:19:25 +0800594 .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 "
Zhao Liuef88e1e2024-03-09 00:01:46 +0800596 "by machine '" SMP_MACHINE_NAME "' is 4096",
597 },
598};
599
Zhao Liubb829cd2024-03-09 00:01:48 +0800600static 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,\
Zhao Liu6a235522024-05-29 14:19:25 +0800605 * clusters=1,modules=1,cores=1,threads=1,\
606 * maxcpus=1
Zhao Liubb829cd2024-03-09 00:01:48 +0800607 */
Zhao Liu6a235522024-05-29 14:19:25 +0800608 .config = SMP_CONFIG_WITH_FULL_TOPO(0, 1, 1, 1, 1, 1, 1, 1, 1, 1),
Zhao Liubb829cd2024-03-09 00:01:48 +0800609 .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,\
Zhao Liu6a235522024-05-29 14:19:25 +0800615 * clusters=1,modules=1,cores=1,threads=1,\
616 * maxcpus=1
Zhao Liubb829cd2024-03-09 00:01:48 +0800617 */
Zhao Liu6a235522024-05-29 14:19:25 +0800618 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 0, 1, 1, 1, 1, 1, 1, 1, 1),
Zhao Liubb829cd2024-03-09 00:01:48 +0800619 .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,\
Zhao Liu6a235522024-05-29 14:19:25 +0800625 * clusters=1,modules=1,cores=1,threads=1,\
626 * maxcpus=1
Zhao Liubb829cd2024-03-09 00:01:48 +0800627 */
Zhao Liu6a235522024-05-29 14:19:25 +0800628 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 0, 1, 1, 1, 1, 1, 1, 1),
Zhao Liubb829cd2024-03-09 00:01:48 +0800629 .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,\
Zhao Liu6a235522024-05-29 14:19:25 +0800635 * clusters=1,modules=1,cores=1,threads=1,
636 * maxcpus=1
Zhao Liubb829cd2024-03-09 00:01:48 +0800637 */
Zhao Liu6a235522024-05-29 14:19:25 +0800638 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 0, 1, 1, 1, 1, 1, 1),
Zhao Liubb829cd2024-03-09 00:01:48 +0800639 .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,\
Zhao Liu6a235522024-05-29 14:19:25 +0800645 * clusters=1,modules=1,cores=1,threads=1,\
646 * maxcpus=1
Zhao Liubb829cd2024-03-09 00:01:48 +0800647 */
Zhao Liu6a235522024-05-29 14:19:25 +0800648 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 0, 1, 1, 1, 1, 1),
Zhao Liubb829cd2024-03-09 00:01:48 +0800649 .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,\
Zhao Liu6a235522024-05-29 14:19:25 +0800655 * clusters=0,modules=1,cores=1,threads=1,\
656 * maxcpus=1
Zhao Liubb829cd2024-03-09 00:01:48 +0800657 */
Zhao Liu6a235522024-05-29 14:19:25 +0800658 .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),
Zhao Liubb829cd2024-03-09 00:01:48 +0800669 .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,\
Zhao Liu6a235522024-05-29 14:19:25 +0800675 * clusters=1,modules=1,cores=0,threads=1,
676 * maxcpus=1
Zhao Liubb829cd2024-03-09 00:01:48 +0800677 */
Zhao Liu6a235522024-05-29 14:19:25 +0800678 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 0, 1, 1),
Zhao Liubb829cd2024-03-09 00:01:48 +0800679 .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,\
Zhao Liu6a235522024-05-29 14:19:25 +0800685 * clusters=1,modules=1,cores=1,threads=0,\
686 * maxcpus=1
Zhao Liubb829cd2024-03-09 00:01:48 +0800687 */
Zhao Liu6a235522024-05-29 14:19:25 +0800688 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 1, 0, 1),
Zhao Liubb829cd2024-03-09 00:01:48 +0800689 .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,\
Zhao Liu6a235522024-05-29 14:19:25 +0800695 * clusters=1,modules=1,cores=1,threads=1,\
696 * maxcpus=0
Zhao Liubb829cd2024-03-09 00:01:48 +0800697 */
Zhao Liu6a235522024-05-29 14:19:25 +0800698 .config = SMP_CONFIG_WITH_FULL_TOPO(1, 1, 1, 1, 1, 1, 1, 1, 1, 0),
Zhao Liubb829cd2024-03-09 00:01:48 +0800699 .expect_error = "Invalid CPU topology: CPU topology parameters must "
700 "be greater than zero",
701 },
702};
703
Philippe Mathieu-Daudé3e2f1492021-11-11 10:21:23 +0100704static char *smp_config_to_string(const SMPConfiguration *config)
Yanan Wang9e8e3932021-10-26 11:46:59 +0800705{
706 return g_strdup_printf(
707 "(SMPConfiguration) {\n"
Yanan Wange5ef89a2021-12-28 17:22:11 +0800708 " .has_cpus = %5s, cpus = %" PRId64 ",\n"
Zhao Liudc583442024-03-09 00:01:42 +0800709 " .has_drawers = %5s, drawers = %" PRId64 ",\n"
710 " .has_books = %5s, books = %" PRId64 ",\n"
Yanan Wange5ef89a2021-12-28 17:22:11 +0800711 " .has_sockets = %5s, sockets = %" PRId64 ",\n"
712 " .has_dies = %5s, dies = %" PRId64 ",\n"
713 " .has_clusters = %5s, clusters = %" PRId64 ",\n"
Zhao Liub985f4b2024-05-29 14:19:22 +0800714 " .has_modules = %5s, modules = %" PRId64 ",\n"
Yanan Wange5ef89a2021-12-28 17:22:11 +0800715 " .has_cores = %5s, cores = %" PRId64 ",\n"
716 " .has_threads = %5s, threads = %" PRId64 ",\n"
717 " .has_maxcpus = %5s, maxcpus = %" PRId64 ",\n"
Yanan Wang9e8e3932021-10-26 11:46:59 +0800718 "}",
719 config->has_cpus ? "true" : "false", config->cpus,
Zhao Liudc583442024-03-09 00:01:42 +0800720 config->has_drawers ? "true" : "false", config->drawers,
721 config->has_books ? "true" : "false", config->books,
Yanan Wang9e8e3932021-10-26 11:46:59 +0800722 config->has_sockets ? "true" : "false", config->sockets,
723 config->has_dies ? "true" : "false", config->dies,
Yanan Wange5ef89a2021-12-28 17:22:11 +0800724 config->has_clusters ? "true" : "false", config->clusters,
Zhao Liub985f4b2024-05-29 14:19:22 +0800725 config->has_modules ? "true" : "false", config->modules,
Yanan Wang9e8e3932021-10-26 11:46:59 +0800726 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
Zhao Liu7d593672023-10-23 17:46:20 +0800731/* Use the different calculation than machine_topo_get_threads_per_socket(). */
732static unsigned int cpu_topology_get_threads_per_socket(const CpuTopology *topo)
733{
734 /* Check the divisor to avoid invalid topology examples causing SIGFPE. */
Zhao Liudc583442024-03-09 00:01:42 +0800735 if (!topo->drawers || !topo->books || !topo->sockets) {
Zhao Liu7d593672023-10-23 17:46:20 +0800736 return 0;
737 } else {
Zhao Liudc583442024-03-09 00:01:42 +0800738 return topo->max_cpus / topo->drawers / topo->books / topo->sockets;
Zhao Liu7d593672023-10-23 17:46:20 +0800739 }
740}
741
742/* Use the different calculation than machine_topo_get_cores_per_socket(). */
743static 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
753static char *cpu_topology_to_string(const CpuTopology *topo,
754 unsigned int threads_per_socket,
Zhao Liu71e44ee2024-03-09 00:01:47 +0800755 unsigned int cores_per_socket,
756 bool has_clusters)
Yanan Wang9e8e3932021-10-26 11:46:59 +0800757{
758 return g_strdup_printf(
759 "(CpuTopology) {\n"
Zhao Liu7d593672023-10-23 17:46:20 +0800760 " .cpus = %u,\n"
Zhao Liudc583442024-03-09 00:01:42 +0800761 " .drawers = %u,\n"
762 " .books = %u,\n"
Zhao Liu7d593672023-10-23 17:46:20 +0800763 " .sockets = %u,\n"
764 " .dies = %u,\n"
765 " .clusters = %u,\n"
Zhao Liub985f4b2024-05-29 14:19:22 +0800766 " .modules = %u,\n"
Zhao Liu7d593672023-10-23 17:46:20 +0800767 " .cores = %u,\n"
768 " .threads = %u,\n"
769 " .max_cpus = %u,\n"
770 " .threads_per_socket = %u,\n"
771 " .cores_per_socket = %u,\n"
Zhao Liu71e44ee2024-03-09 00:01:47 +0800772 " .has_clusters = %s,\n"
Yanan Wang9e8e3932021-10-26 11:46:59 +0800773 "}",
Zhao Liudc583442024-03-09 00:01:42 +0800774 topo->cpus, topo->drawers, topo->books,
775 topo->sockets, topo->dies, topo->clusters,
Zhao Liub985f4b2024-05-29 14:19:22 +0800776 topo->modules, topo->cores, topo->threads,
777 topo->max_cpus, threads_per_socket, cores_per_socket,
Zhao Liu71e44ee2024-03-09 00:01:47 +0800778 has_clusters ? "true" : "false");
Yanan Wang9e8e3932021-10-26 11:46:59 +0800779}
780
Philippe Mathieu-Daudé3e2f1492021-11-11 10:21:23 +0100781static void check_parse(MachineState *ms, const SMPConfiguration *config,
Philippe Mathieu-Daudécf650002021-11-11 10:23:06 +0100782 const CpuTopology *expect_topo, const char *expect_err,
Yanan Wang9e8e3932021-10-26 11:46:59 +0800783 bool is_valid)
784{
Zhao Liu71e44ee2024-03-09 00:01:47 +0800785 MachineClass *mc = MACHINE_GET_CLASS(ms);
Yanan Wang9e8e3932021-10-26 11:46:59 +0800786 g_autofree char *config_str = smp_config_to_string(config);
Zhao Liu7d593672023-10-23 17:46:20 +0800787 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;
Yanan Wang9e8e3932021-10-26 11:46:59 +0800790 Error *err = NULL;
791
Zhao Liu7d593672023-10-23 17:46:20 +0800792 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,
Zhao Liu71e44ee2024-03-09 00:01:47 +0800798 expect_cores_per_socket,
799 config->has_clusters);
Zhao Liu7d593672023-10-23 17:46:20 +0800800
Philippe Mathieu-Daudé3e2f1492021-11-11 10:21:23 +0100801 /* call the generic parser */
802 machine_parse_smp_config(ms, config, &err);
Yanan Wang9e8e3932021-10-26 11:46:59 +0800803
Zhao Liu7d593672023-10-23 17:46:20 +0800804 ms_threads_per_socket = machine_topo_get_threads_per_socket(ms);
805 ms_cores_per_socket = machine_topo_get_cores_per_socket(ms);
Zhao Liu71e44ee2024-03-09 00:01:47 +0800806 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);
Yanan Wang9e8e3932021-10-26 11:46:59 +0800810
811 /* when the configuration is supposed to be valid */
812 if (is_valid) {
813 if ((err == NULL) &&
814 (ms->smp.cpus == expect_topo->cpus) &&
Zhao Liudc583442024-03-09 00:01:42 +0800815 (ms->smp.drawers == expect_topo->drawers) &&
816 (ms->smp.books == expect_topo->books) &&
Yanan Wang9e8e3932021-10-26 11:46:59 +0800817 (ms->smp.sockets == expect_topo->sockets) &&
818 (ms->smp.dies == expect_topo->dies) &&
Yanan Wange5ef89a2021-12-28 17:22:11 +0800819 (ms->smp.clusters == expect_topo->clusters) &&
Zhao Liub985f4b2024-05-29 14:19:22 +0800820 (ms->smp.modules == expect_topo->modules) &&
Yanan Wang9e8e3932021-10-26 11:46:59 +0800821 (ms->smp.cores == expect_topo->cores) &&
822 (ms->smp.threads == expect_topo->threads) &&
Zhao Liu7d593672023-10-23 17:46:20 +0800823 (ms->smp.max_cpus == expect_topo->max_cpus) &&
824 (ms_threads_per_socket == expect_threads_per_socket) &&
Zhao Liu71e44ee2024-03-09 00:01:47 +0800825 (ms_cores_per_socket == expect_cores_per_socket) &&
826 (mc->smp_props.has_clusters == config->has_clusters)) {
Yanan Wang9e8e3932021-10-26 11:46:59 +0800827 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
877end:
878 if (err != NULL) {
879 error_free(err);
880 }
881
882 abort();
883}
884
885static 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 */
Philippe Mathieu-Daudécf650002021-11-11 10:23:06 +0100899static void unsupported_params_init(const MachineClass *mc, SMPTestData *data)
Yanan Wang9e8e3932021-10-26 11:46:59 +0800900{
Zhao Liub985f4b2024-05-29 14:19:22 +0800901 if (!mc->smp_props.modules_supported) {
902 data->expect_prefer_sockets.modules = 1;
903 data->expect_prefer_cores.modules = 1;
904 }
905
Yanan Wang9e8e3932021-10-26 11:46:59 +0800906 if (!mc->smp_props.dies_supported) {
907 data->expect_prefer_sockets.dies = 1;
908 data->expect_prefer_cores.dies = 1;
909 }
Yanan Wange5ef89a2021-12-28 17:22:11 +0800910
911 if (!mc->smp_props.clusters_supported) {
912 data->expect_prefer_sockets.clusters = 1;
913 data->expect_prefer_cores.clusters = 1;
914 }
Zhao Liudc583442024-03-09 00:01:42 +0800915
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 }
Yanan Wang9e8e3932021-10-26 11:46:59 +0800925}
926
Philippe Mathieu-Daudéc3440ef2021-11-11 09:20:22 +0100927static void machine_base_class_init(ObjectClass *oc, void *data)
Yanan Wang9e8e3932021-10-26 11:46:59 +0800928{
Philippe Mathieu-Daudéc3440ef2021-11-11 09:20:22 +0100929 MachineClass *mc = MACHINE_CLASS(oc);
930
Yanan Wang9e8e3932021-10-26 11:46:59 +0800931 mc->min_cpus = MIN_CPUS;
932 mc->max_cpus = MAX_CPUS;
Yanan Wanga2348fa2021-12-28 17:22:13 +0800933
934 mc->name = g_strdup(SMP_MACHINE_NAME);
Yanan Wang9e8e3932021-10-26 11:46:59 +0800935}
936
Philippe Mathieu-Daudé7ca0705e2021-11-15 15:44:07 +0100937static void machine_generic_invalid_class_init(ObjectClass *oc, void *data)
938{
939 MachineClass *mc = MACHINE_CLASS(oc);
940
941 /* Force invalid min CPUs and max CPUs */
Zhao Liu803f9712024-03-09 00:01:40 +0800942 mc->min_cpus = MIN_CPUS + 1;
943 mc->max_cpus = MAX_CPUS - 1;
Philippe Mathieu-Daudé7ca0705e2021-11-15 15:44:07 +0100944}
945
Zhao Liua05ed352024-05-29 14:19:23 +0800946static void machine_with_modules_class_init(ObjectClass *oc, void *data)
947{
948 MachineClass *mc = MACHINE_CLASS(oc);
949
950 mc->smp_props.modules_supported = true;
951}
952
Philippe Mathieu-Daudé76b6d4c2021-11-15 12:39:12 +0100953static void machine_with_dies_class_init(ObjectClass *oc, void *data)
954{
955 MachineClass *mc = MACHINE_CLASS(oc);
956
Philippe Mathieu-Daudé76b6d4c2021-11-15 12:39:12 +0100957 mc->smp_props.dies_supported = true;
Yanan Wange5ef89a2021-12-28 17:22:11 +0800958}
959
Zhao Liufe4b9952024-05-29 14:19:24 +0800960static void machine_with_modules_dies_class_init(ObjectClass *oc, void *data)
961{
962 MachineClass *mc = MACHINE_CLASS(oc);
963
964 mc->smp_props.modules_supported = true;
965 mc->smp_props.dies_supported = true;
966}
967
Yanan Wange5ef89a2021-12-28 17:22:11 +0800968static void machine_with_clusters_class_init(ObjectClass *oc, void *data)
969{
970 MachineClass *mc = MACHINE_CLASS(oc);
971
Yanan Wange5ef89a2021-12-28 17:22:11 +0800972 mc->smp_props.clusters_supported = true;
Philippe Mathieu-Daudé76b6d4c2021-11-15 12:39:12 +0100973}
974
Zhao Liuf0fe1cd2024-03-09 00:01:43 +0800975static void machine_with_books_class_init(ObjectClass *oc, void *data)
976{
977 MachineClass *mc = MACHINE_CLASS(oc);
978
979 mc->smp_props.books_supported = true;
980}
981
Zhao Liu5a4c4142024-03-09 00:01:44 +0800982static void machine_with_drawers_class_init(ObjectClass *oc, void *data)
983{
984 MachineClass *mc = MACHINE_CLASS(oc);
985
986 mc->smp_props.drawers_supported = true;
987}
988
Zhao Liu3f90fb02024-03-09 00:01:45 +0800989static void machine_with_drawers_books_class_init(ObjectClass *oc, void *data)
990{
991 MachineClass *mc = MACHINE_CLASS(oc);
992
993 mc->smp_props.drawers_supported = true;
994 mc->smp_props.books_supported = true;
995}
996
Zhao Liuef88e1e2024-03-09 00:01:46 +0800997static void machine_full_topo_class_init(ObjectClass *oc, void *data)
998{
999 MachineClass *mc = MACHINE_CLASS(oc);
1000
1001 mc->smp_props.drawers_supported = true;
1002 mc->smp_props.books_supported = true;
1003 mc->smp_props.dies_supported = true;
1004 mc->smp_props.clusters_supported = true;
Zhao Liu6a235522024-05-29 14:19:25 +08001005 mc->smp_props.modules_supported = true;
Zhao Liuef88e1e2024-03-09 00:01:46 +08001006}
1007
Philippe Mathieu-Daudéc30bdb02021-11-15 12:35:43 +01001008static void test_generic_valid(const void *opaque)
Yanan Wang9e8e3932021-10-26 11:46:59 +08001009{
Philippe Mathieu-Daudé1ab192f2021-11-15 12:32:09 +01001010 const char *machine_type = opaque;
1011 Object *obj = object_new(machine_type);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001012 MachineState *ms = MACHINE(obj);
1013 MachineClass *mc = MACHINE_GET_CLASS(obj);
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001014 SMPTestData data = {};
Yanan Wang9e8e3932021-10-26 11:46:59 +08001015 int i;
1016
Yanan Wang9e8e3932021-10-26 11:46:59 +08001017 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001018 data = data_generic_valid[i];
1019 unsupported_params_init(mc, &data);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001020
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001021 smp_parse_test(ms, &data, true);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001022 }
1023
Philippe Mathieu-Daudéc30bdb02021-11-15 12:35:43 +01001024 object_unref(obj);
1025}
1026
1027static void test_generic_invalid(const void *opaque)
1028{
1029 const char *machine_type = opaque;
1030 Object *obj = object_new(machine_type);
1031 MachineState *ms = MACHINE(obj);
1032 MachineClass *mc = MACHINE_GET_CLASS(obj);
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001033 SMPTestData data = {};
Philippe Mathieu-Daudéc30bdb02021-11-15 12:35:43 +01001034 int i;
1035
Yanan Wang9e8e3932021-10-26 11:46:59 +08001036 for (i = 0; i < ARRAY_SIZE(data_generic_invalid); i++) {
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001037 data = data_generic_invalid[i];
1038 unsupported_params_init(mc, &data);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001039
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001040 smp_parse_test(ms, &data, false);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001041 }
1042
1043 object_unref(obj);
1044}
1045
Zhao Liua05ed352024-05-29 14:19:23 +08001046static void test_with_modules(const void *opaque)
1047{
1048 const char *machine_type = opaque;
1049 Object *obj = object_new(machine_type);
1050 MachineState *ms = MACHINE(obj);
1051 MachineClass *mc = MACHINE_GET_CLASS(obj);
1052 SMPTestData data = {};
1053 unsigned int num_modules = 2;
1054 int i;
1055
1056 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1057 data = data_generic_valid[i];
1058 unsupported_params_init(mc, &data);
1059
1060 /* when modules parameter is omitted, it will be set as 1 */
1061 data.expect_prefer_sockets.modules = 1;
1062 data.expect_prefer_cores.modules = 1;
1063
1064 smp_parse_test(ms, &data, true);
1065
1066 /* when modules parameter is specified */
1067 data.config.has_modules = true;
1068 data.config.modules = num_modules;
1069 if (data.config.has_cpus) {
1070 data.config.cpus *= num_modules;
1071 }
1072 if (data.config.has_maxcpus) {
1073 data.config.maxcpus *= num_modules;
1074 }
1075
1076 data.expect_prefer_sockets.modules = num_modules;
1077 data.expect_prefer_sockets.cpus *= num_modules;
1078 data.expect_prefer_sockets.max_cpus *= num_modules;
1079 data.expect_prefer_cores.modules = num_modules;
1080 data.expect_prefer_cores.cpus *= num_modules;
1081 data.expect_prefer_cores.max_cpus *= num_modules;
1082
1083 smp_parse_test(ms, &data, true);
1084 }
1085
1086 for (i = 0; i < ARRAY_SIZE(data_with_modules_invalid); i++) {
1087 data = data_with_modules_invalid[i];
1088 unsupported_params_init(mc, &data);
1089
1090 smp_parse_test(ms, &data, false);
1091 }
1092
1093 object_unref(obj);
1094}
1095
Philippe Mathieu-Daudé1ab192f2021-11-15 12:32:09 +01001096static void test_with_dies(const void *opaque)
Yanan Wang9e8e3932021-10-26 11:46:59 +08001097{
Philippe Mathieu-Daudé1ab192f2021-11-15 12:32:09 +01001098 const char *machine_type = opaque;
1099 Object *obj = object_new(machine_type);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001100 MachineState *ms = MACHINE(obj);
1101 MachineClass *mc = MACHINE_GET_CLASS(obj);
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001102 SMPTestData data = {};
Yanan Wang9e8e3932021-10-26 11:46:59 +08001103 unsigned int num_dies = 2;
1104 int i;
1105
Yanan Wang9e8e3932021-10-26 11:46:59 +08001106 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001107 data = data_generic_valid[i];
1108 unsupported_params_init(mc, &data);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001109
1110 /* when dies parameter is omitted, it will be set as 1 */
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001111 data.expect_prefer_sockets.dies = 1;
1112 data.expect_prefer_cores.dies = 1;
Yanan Wang9e8e3932021-10-26 11:46:59 +08001113
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001114 smp_parse_test(ms, &data, true);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001115
1116 /* when dies parameter is specified */
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001117 data.config.has_dies = true;
1118 data.config.dies = num_dies;
1119 if (data.config.has_cpus) {
1120 data.config.cpus *= num_dies;
Yanan Wang9e8e3932021-10-26 11:46:59 +08001121 }
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001122 if (data.config.has_maxcpus) {
1123 data.config.maxcpus *= num_dies;
Yanan Wang9e8e3932021-10-26 11:46:59 +08001124 }
1125
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001126 data.expect_prefer_sockets.dies = num_dies;
1127 data.expect_prefer_sockets.cpus *= num_dies;
1128 data.expect_prefer_sockets.max_cpus *= num_dies;
1129 data.expect_prefer_cores.dies = num_dies;
1130 data.expect_prefer_cores.cpus *= num_dies;
1131 data.expect_prefer_cores.max_cpus *= num_dies;
Yanan Wang9e8e3932021-10-26 11:46:59 +08001132
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001133 smp_parse_test(ms, &data, true);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001134 }
1135
1136 for (i = 0; i < ARRAY_SIZE(data_with_dies_invalid); i++) {
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001137 data = data_with_dies_invalid[i];
1138 unsupported_params_init(mc, &data);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001139
Philippe Mathieu-Daudé47ab8a42021-11-11 08:58:40 +01001140 smp_parse_test(ms, &data, false);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001141 }
1142
Yanan Wang9e8e3932021-10-26 11:46:59 +08001143 object_unref(obj);
1144}
1145
Zhao Liufe4b9952024-05-29 14:19:24 +08001146static void test_with_modules_dies(const void *opaque)
1147{
1148 const char *machine_type = opaque;
1149 Object *obj = object_new(machine_type);
1150 MachineState *ms = MACHINE(obj);
1151 MachineClass *mc = MACHINE_GET_CLASS(obj);
1152 SMPTestData data = {};
1153 unsigned int num_modules = 5, num_dies = 3;
1154 int i;
1155
1156 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1157 data = data_generic_valid[i];
1158 unsupported_params_init(mc, &data);
1159
1160 /*
1161 * when modules and dies parameters are omitted, they will
1162 * be both set as 1.
1163 */
1164 data.expect_prefer_sockets.modules = 1;
1165 data.expect_prefer_sockets.dies = 1;
1166 data.expect_prefer_cores.modules = 1;
1167 data.expect_prefer_cores.dies = 1;
1168
1169 smp_parse_test(ms, &data, true);
1170
1171 /* when modules and dies parameters are both specified */
1172 data.config.has_modules = true;
1173 data.config.modules = num_modules;
1174 data.config.has_dies = true;
1175 data.config.dies = num_dies;
1176
1177 if (data.config.has_cpus) {
1178 data.config.cpus *= num_modules * num_dies;
1179 }
1180 if (data.config.has_maxcpus) {
1181 data.config.maxcpus *= num_modules * num_dies;
1182 }
1183
1184 data.expect_prefer_sockets.modules = num_modules;
1185 data.expect_prefer_sockets.dies = num_dies;
1186 data.expect_prefer_sockets.cpus *= num_modules * num_dies;
1187 data.expect_prefer_sockets.max_cpus *= num_modules * num_dies;
1188
1189 data.expect_prefer_cores.modules = num_modules;
1190 data.expect_prefer_cores.dies = num_dies;
1191 data.expect_prefer_cores.cpus *= num_modules * num_dies;
1192 data.expect_prefer_cores.max_cpus *= num_modules * num_dies;
1193
1194 smp_parse_test(ms, &data, true);
1195 }
1196
1197 for (i = 0; i < ARRAY_SIZE(data_with_modules_dies_invalid); i++) {
1198 data = data_with_modules_dies_invalid[i];
1199 unsupported_params_init(mc, &data);
1200
1201 smp_parse_test(ms, &data, false);
1202 }
1203
1204 object_unref(obj);
1205}
1206
Yanan Wange5ef89a2021-12-28 17:22:11 +08001207static void test_with_clusters(const void *opaque)
1208{
1209 const char *machine_type = opaque;
1210 Object *obj = object_new(machine_type);
1211 MachineState *ms = MACHINE(obj);
1212 MachineClass *mc = MACHINE_GET_CLASS(obj);
1213 SMPTestData data = {};
1214 unsigned int num_clusters = 2;
1215 int i;
1216
1217 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1218 data = data_generic_valid[i];
1219 unsupported_params_init(mc, &data);
1220
1221 /* when clusters parameter is omitted, it will be set as 1 */
1222 data.expect_prefer_sockets.clusters = 1;
1223 data.expect_prefer_cores.clusters = 1;
1224
1225 smp_parse_test(ms, &data, true);
1226
1227 /* when clusters parameter is specified */
1228 data.config.has_clusters = true;
1229 data.config.clusters = num_clusters;
1230 if (data.config.has_cpus) {
1231 data.config.cpus *= num_clusters;
1232 }
1233 if (data.config.has_maxcpus) {
1234 data.config.maxcpus *= num_clusters;
1235 }
1236
1237 data.expect_prefer_sockets.clusters = num_clusters;
1238 data.expect_prefer_sockets.cpus *= num_clusters;
1239 data.expect_prefer_sockets.max_cpus *= num_clusters;
1240 data.expect_prefer_cores.clusters = num_clusters;
1241 data.expect_prefer_cores.cpus *= num_clusters;
1242 data.expect_prefer_cores.max_cpus *= num_clusters;
1243
1244 smp_parse_test(ms, &data, true);
1245 }
1246
1247 for (i = 0; i < ARRAY_SIZE(data_with_clusters_invalid); i++) {
1248 data = data_with_clusters_invalid[i];
1249 unsupported_params_init(mc, &data);
1250
1251 smp_parse_test(ms, &data, false);
1252 }
1253
1254 object_unref(obj);
1255}
1256
Zhao Liuf0fe1cd2024-03-09 00:01:43 +08001257static void test_with_books(const void *opaque)
1258{
1259 const char *machine_type = opaque;
1260 Object *obj = object_new(machine_type);
1261 MachineState *ms = MACHINE(obj);
1262 MachineClass *mc = MACHINE_GET_CLASS(obj);
1263 SMPTestData data = {};
1264 unsigned int num_books = 2;
1265 int i;
1266
1267 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1268 data = data_generic_valid[i];
1269 unsupported_params_init(mc, &data);
1270
1271 /* when books parameter is omitted, it will be set as 1 */
1272 data.expect_prefer_sockets.books = 1;
1273 data.expect_prefer_cores.books = 1;
1274
1275 smp_parse_test(ms, &data, true);
1276
1277 /* when books parameter is specified */
1278 data.config.has_books = true;
1279 data.config.books = num_books;
1280 if (data.config.has_cpus) {
1281 data.config.cpus *= num_books;
1282 }
1283 if (data.config.has_maxcpus) {
1284 data.config.maxcpus *= num_books;
1285 }
1286
1287 data.expect_prefer_sockets.books = num_books;
1288 data.expect_prefer_sockets.cpus *= num_books;
1289 data.expect_prefer_sockets.max_cpus *= num_books;
1290 data.expect_prefer_cores.books = num_books;
1291 data.expect_prefer_cores.cpus *= num_books;
1292 data.expect_prefer_cores.max_cpus *= num_books;
1293
1294 smp_parse_test(ms, &data, true);
1295 }
1296
1297 for (i = 0; i < ARRAY_SIZE(data_with_books_invalid); i++) {
1298 data = data_with_books_invalid[i];
1299 unsupported_params_init(mc, &data);
1300
1301 smp_parse_test(ms, &data, false);
1302 }
1303
1304 object_unref(obj);
1305}
1306
Zhao Liu5a4c4142024-03-09 00:01:44 +08001307static void test_with_drawers(const void *opaque)
1308{
1309 const char *machine_type = opaque;
1310 Object *obj = object_new(machine_type);
1311 MachineState *ms = MACHINE(obj);
1312 MachineClass *mc = MACHINE_GET_CLASS(obj);
1313 SMPTestData data = {};
1314 unsigned int num_drawers = 2;
1315 int i;
1316
1317 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1318 data = data_generic_valid[i];
1319 unsupported_params_init(mc, &data);
1320
1321 /* when drawers parameter is omitted, it will be set as 1 */
1322 data.expect_prefer_sockets.drawers = 1;
1323 data.expect_prefer_cores.drawers = 1;
1324
1325 smp_parse_test(ms, &data, true);
1326
1327 /* when drawers parameter is specified */
1328 data.config.has_drawers = true;
1329 data.config.drawers = num_drawers;
1330 if (data.config.has_cpus) {
1331 data.config.cpus *= num_drawers;
1332 }
1333 if (data.config.has_maxcpus) {
1334 data.config.maxcpus *= num_drawers;
1335 }
1336
1337 data.expect_prefer_sockets.drawers = num_drawers;
1338 data.expect_prefer_sockets.cpus *= num_drawers;
1339 data.expect_prefer_sockets.max_cpus *= num_drawers;
1340 data.expect_prefer_cores.drawers = num_drawers;
1341 data.expect_prefer_cores.cpus *= num_drawers;
1342 data.expect_prefer_cores.max_cpus *= num_drawers;
1343
1344 smp_parse_test(ms, &data, true);
1345 }
1346
1347 for (i = 0; i < ARRAY_SIZE(data_with_drawers_invalid); i++) {
1348 data = data_with_drawers_invalid[i];
1349 unsupported_params_init(mc, &data);
1350
1351 smp_parse_test(ms, &data, false);
1352 }
1353
1354 object_unref(obj);
1355}
1356
Zhao Liu3f90fb02024-03-09 00:01:45 +08001357static void test_with_drawers_books(const void *opaque)
1358{
1359 const char *machine_type = opaque;
1360 Object *obj = object_new(machine_type);
1361 MachineState *ms = MACHINE(obj);
1362 MachineClass *mc = MACHINE_GET_CLASS(obj);
1363 SMPTestData data = {};
1364 unsigned int num_drawers = 5, num_books = 3;
1365 int i;
1366
1367 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1368 data = data_generic_valid[i];
1369 unsupported_params_init(mc, &data);
1370
1371 /*
1372 * when drawers and books parameters are omitted, they will
1373 * be both set as 1.
1374 */
1375 data.expect_prefer_sockets.drawers = 1;
1376 data.expect_prefer_sockets.books = 1;
1377 data.expect_prefer_cores.drawers = 1;
1378 data.expect_prefer_cores.books = 1;
1379
1380 smp_parse_test(ms, &data, true);
1381
1382 /* when drawers and books parameters are both specified */
1383 data.config.has_drawers = true;
1384 data.config.drawers = num_drawers;
1385 data.config.has_books = true;
1386 data.config.books = num_books;
1387
1388 if (data.config.has_cpus) {
1389 data.config.cpus *= num_drawers * num_books;
1390 }
1391 if (data.config.has_maxcpus) {
1392 data.config.maxcpus *= num_drawers * num_books;
1393 }
1394
1395 data.expect_prefer_sockets.drawers = num_drawers;
1396 data.expect_prefer_sockets.books = num_books;
1397 data.expect_prefer_sockets.cpus *= num_drawers * num_books;
1398 data.expect_prefer_sockets.max_cpus *= num_drawers * num_books;
1399
1400 data.expect_prefer_cores.drawers = num_drawers;
1401 data.expect_prefer_cores.books = num_books;
1402 data.expect_prefer_cores.cpus *= num_drawers * num_books;
1403 data.expect_prefer_cores.max_cpus *= num_drawers * num_books;
1404
1405 smp_parse_test(ms, &data, true);
1406 }
1407
1408 for (i = 0; i < ARRAY_SIZE(data_with_drawers_books_invalid); i++) {
1409 data = data_with_drawers_books_invalid[i];
1410 unsupported_params_init(mc, &data);
1411
1412 smp_parse_test(ms, &data, false);
1413 }
1414
1415 object_unref(obj);
1416}
1417
Zhao Liuef88e1e2024-03-09 00:01:46 +08001418static void test_full_topo(const void *opaque)
1419{
1420 const char *machine_type = opaque;
1421 Object *obj = object_new(machine_type);
1422 MachineState *ms = MACHINE(obj);
1423 MachineClass *mc = MACHINE_GET_CLASS(obj);
1424 SMPTestData data = {};
Zhao Liu6a235522024-05-29 14:19:25 +08001425 unsigned int drawers, books, dies, clusters, modules, multiplier;
Zhao Liuef88e1e2024-03-09 00:01:46 +08001426 int i;
1427
Zhao Liu6a235522024-05-29 14:19:25 +08001428 drawers = 5;
1429 books = 3;
1430 dies = 2;
1431 clusters = 3;
1432 modules = 2;
1433
1434 multiplier = drawers * books * dies * clusters * modules;
Zhao Liuef88e1e2024-03-09 00:01:46 +08001435 for (i = 0; i < ARRAY_SIZE(data_generic_valid); i++) {
1436 data = data_generic_valid[i];
1437 unsupported_params_init(mc, &data);
1438
1439 /*
Zhao Liu6a235522024-05-29 14:19:25 +08001440 * when drawers, books, dies, clusters and modules parameters are
1441 * omitted, they will be set as 1.
Zhao Liuef88e1e2024-03-09 00:01:46 +08001442 */
1443 data.expect_prefer_sockets.drawers = 1;
1444 data.expect_prefer_sockets.books = 1;
1445 data.expect_prefer_sockets.dies = 1;
1446 data.expect_prefer_sockets.clusters = 1;
Zhao Liu6a235522024-05-29 14:19:25 +08001447 data.expect_prefer_sockets.modules = 1;
Zhao Liuef88e1e2024-03-09 00:01:46 +08001448 data.expect_prefer_cores.drawers = 1;
1449 data.expect_prefer_cores.books = 1;
1450 data.expect_prefer_cores.dies = 1;
1451 data.expect_prefer_cores.clusters = 1;
Zhao Liu6a235522024-05-29 14:19:25 +08001452 data.expect_prefer_cores.modules = 1;
Zhao Liuef88e1e2024-03-09 00:01:46 +08001453
1454 smp_parse_test(ms, &data, true);
1455
Zhao Liu6a235522024-05-29 14:19:25 +08001456 /*
1457 * when drawers, books, dies, clusters and modules parameters
1458 * are specified.
1459 */
Zhao Liuef88e1e2024-03-09 00:01:46 +08001460 data.config.has_drawers = true;
1461 data.config.drawers = drawers;
1462 data.config.has_books = true;
1463 data.config.books = books;
1464 data.config.has_dies = true;
1465 data.config.dies = dies;
1466 data.config.has_clusters = true;
1467 data.config.clusters = clusters;
Zhao Liu6a235522024-05-29 14:19:25 +08001468 data.config.has_modules = true;
1469 data.config.modules = modules;
Zhao Liuef88e1e2024-03-09 00:01:46 +08001470
1471 if (data.config.has_cpus) {
1472 data.config.cpus *= multiplier;
1473 }
1474 if (data.config.has_maxcpus) {
1475 data.config.maxcpus *= multiplier;
1476 }
1477
1478 data.expect_prefer_sockets.drawers = drawers;
1479 data.expect_prefer_sockets.books = books;
1480 data.expect_prefer_sockets.dies = dies;
1481 data.expect_prefer_sockets.clusters = clusters;
Zhao Liu6a235522024-05-29 14:19:25 +08001482 data.expect_prefer_sockets.modules = modules;
Zhao Liuef88e1e2024-03-09 00:01:46 +08001483 data.expect_prefer_sockets.cpus *= multiplier;
1484 data.expect_prefer_sockets.max_cpus *= multiplier;
1485
1486 data.expect_prefer_cores.drawers = drawers;
1487 data.expect_prefer_cores.books = books;
1488 data.expect_prefer_cores.dies = dies;
1489 data.expect_prefer_cores.clusters = clusters;
Zhao Liu6a235522024-05-29 14:19:25 +08001490 data.expect_prefer_cores.modules = modules;
Zhao Liuef88e1e2024-03-09 00:01:46 +08001491 data.expect_prefer_cores.cpus *= multiplier;
1492 data.expect_prefer_cores.max_cpus *= multiplier;
1493
1494 smp_parse_test(ms, &data, true);
1495 }
1496
1497 for (i = 0; i < ARRAY_SIZE(data_full_topo_invalid); i++) {
1498 data = data_full_topo_invalid[i];
1499 unsupported_params_init(mc, &data);
1500
1501 smp_parse_test(ms, &data, false);
1502 }
1503
Zhao Liubb829cd2024-03-09 00:01:48 +08001504 for (i = 0; i < ARRAY_SIZE(data_zero_topo_invalid); i++) {
1505 data = data_zero_topo_invalid[i];
1506 unsupported_params_init(mc, &data);
1507
1508 smp_parse_test(ms, &data, false);
1509 }
1510
Zhao Liuef88e1e2024-03-09 00:01:46 +08001511 object_unref(obj);
1512}
1513
Philippe Mathieu-Daudéc3440ef2021-11-11 09:20:22 +01001514/* Type info of the tested machine */
1515static const TypeInfo smp_machine_types[] = {
1516 {
1517 .name = TYPE_MACHINE,
1518 .parent = TYPE_OBJECT,
Philippe Mathieu-Daudé2dc426c2021-11-15 15:49:59 +01001519 .abstract = true,
Philippe Mathieu-Daudéc3440ef2021-11-11 09:20:22 +01001520 .class_init = machine_base_class_init,
1521 .class_size = sizeof(MachineClass),
1522 .instance_size = sizeof(MachineState),
Philippe Mathieu-Daudé76b6d4c2021-11-15 12:39:12 +01001523 }, {
Philippe Mathieu-Daudé2dc426c2021-11-15 15:49:59 +01001524 .name = MACHINE_TYPE_NAME("smp-generic-valid"),
1525 .parent = TYPE_MACHINE,
Philippe Mathieu-Daudé2dc426c2021-11-15 15:49:59 +01001526 }, {
Philippe Mathieu-Daudé7ca0705e2021-11-15 15:44:07 +01001527 .name = MACHINE_TYPE_NAME("smp-generic-invalid"),
1528 .parent = TYPE_MACHINE,
1529 .class_init = machine_generic_invalid_class_init,
1530 }, {
Zhao Liua05ed352024-05-29 14:19:23 +08001531 .name = MACHINE_TYPE_NAME("smp-with-modules"),
1532 .parent = TYPE_MACHINE,
1533 .class_init = machine_with_modules_class_init,
1534 }, {
Philippe Mathieu-Daudé76b6d4c2021-11-15 12:39:12 +01001535 .name = MACHINE_TYPE_NAME("smp-with-dies"),
1536 .parent = TYPE_MACHINE,
1537 .class_init = machine_with_dies_class_init,
Yanan Wange5ef89a2021-12-28 17:22:11 +08001538 }, {
Zhao Liufe4b9952024-05-29 14:19:24 +08001539 .name = MACHINE_TYPE_NAME("smp-with-modules-dies"),
1540 .parent = TYPE_MACHINE,
1541 .class_init = machine_with_modules_dies_class_init,
1542 }, {
Yanan Wange5ef89a2021-12-28 17:22:11 +08001543 .name = MACHINE_TYPE_NAME("smp-with-clusters"),
1544 .parent = TYPE_MACHINE,
1545 .class_init = machine_with_clusters_class_init,
Zhao Liuf0fe1cd2024-03-09 00:01:43 +08001546 }, {
1547 .name = MACHINE_TYPE_NAME("smp-with-books"),
1548 .parent = TYPE_MACHINE,
1549 .class_init = machine_with_books_class_init,
Zhao Liu5a4c4142024-03-09 00:01:44 +08001550 }, {
1551 .name = MACHINE_TYPE_NAME("smp-with-drawers"),
1552 .parent = TYPE_MACHINE,
1553 .class_init = machine_with_drawers_class_init,
Zhao Liu3f90fb02024-03-09 00:01:45 +08001554 }, {
1555 .name = MACHINE_TYPE_NAME("smp-with-drawers-books"),
1556 .parent = TYPE_MACHINE,
1557 .class_init = machine_with_drawers_books_class_init,
Zhao Liuef88e1e2024-03-09 00:01:46 +08001558 }, {
1559 .name = MACHINE_TYPE_NAME("smp-full-topo"),
1560 .parent = TYPE_MACHINE,
1561 .class_init = machine_full_topo_class_init,
Philippe Mathieu-Daudéc3440ef2021-11-11 09:20:22 +01001562 }
1563};
1564
1565DEFINE_TYPES(smp_machine_types)
1566
Yanan Wang9e8e3932021-10-26 11:46:59 +08001567int main(int argc, char *argv[])
1568{
Yanan Wang9e8e3932021-10-26 11:46:59 +08001569 module_call_init(MODULE_INIT_QOM);
Philippe Mathieu-Daudéc3440ef2021-11-11 09:20:22 +01001570
1571 g_test_init(&argc, &argv, NULL);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001572
Philippe Mathieu-Daudéc30bdb02021-11-15 12:35:43 +01001573 g_test_add_data_func("/test-smp-parse/generic/valid",
Philippe Mathieu-Daudé2dc426c2021-11-15 15:49:59 +01001574 MACHINE_TYPE_NAME("smp-generic-valid"),
Philippe Mathieu-Daudéc30bdb02021-11-15 12:35:43 +01001575 test_generic_valid);
1576 g_test_add_data_func("/test-smp-parse/generic/invalid",
Philippe Mathieu-Daudé7ca0705e2021-11-15 15:44:07 +01001577 MACHINE_TYPE_NAME("smp-generic-invalid"),
Philippe Mathieu-Daudéc30bdb02021-11-15 12:35:43 +01001578 test_generic_invalid);
Zhao Liua05ed352024-05-29 14:19:23 +08001579 g_test_add_data_func("/test-smp-parse/with_modules",
1580 MACHINE_TYPE_NAME("smp-with-modules"),
1581 test_with_modules);
Philippe Mathieu-Daudé1ab192f2021-11-15 12:32:09 +01001582 g_test_add_data_func("/test-smp-parse/with_dies",
Philippe Mathieu-Daudé76b6d4c2021-11-15 12:39:12 +01001583 MACHINE_TYPE_NAME("smp-with-dies"),
Philippe Mathieu-Daudé1ab192f2021-11-15 12:32:09 +01001584 test_with_dies);
Zhao Liufe4b9952024-05-29 14:19:24 +08001585 g_test_add_data_func("/test-smp-parse/with_modules_dies",
1586 MACHINE_TYPE_NAME("smp-with-modules-dies"),
1587 test_with_modules_dies);
Yanan Wange5ef89a2021-12-28 17:22:11 +08001588 g_test_add_data_func("/test-smp-parse/with_clusters",
1589 MACHINE_TYPE_NAME("smp-with-clusters"),
1590 test_with_clusters);
Zhao Liuf0fe1cd2024-03-09 00:01:43 +08001591 g_test_add_data_func("/test-smp-parse/with_books",
1592 MACHINE_TYPE_NAME("smp-with-books"),
1593 test_with_books);
Zhao Liu5a4c4142024-03-09 00:01:44 +08001594 g_test_add_data_func("/test-smp-parse/with_drawers",
1595 MACHINE_TYPE_NAME("smp-with-drawers"),
1596 test_with_drawers);
Zhao Liu3f90fb02024-03-09 00:01:45 +08001597 g_test_add_data_func("/test-smp-parse/with_drawers_books",
1598 MACHINE_TYPE_NAME("smp-with-drawers-books"),
1599 test_with_drawers_books);
Zhao Liuef88e1e2024-03-09 00:01:46 +08001600 g_test_add_data_func("/test-smp-parse/full",
1601 MACHINE_TYPE_NAME("smp-full-topo"),
1602 test_full_topo);
Yanan Wang9e8e3932021-10-26 11:46:59 +08001603
1604 g_test_run();
1605
1606 return 0;
1607}