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