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