1 /* 2 * Arm CPU feature test cases 3 * 4 * Copyright (c) 2019 Red Hat Inc. 5 * Authors: 6 * Andrew Jones <drjones@redhat.com> 7 * 8 * This work is licensed under the terms of the GNU GPL, version 2 or later. 9 * See the COPYING file in the top-level directory. 10 */ 11 #include "qemu/osdep.h" 12 #include "qemu/bitops.h" 13 #include "libqtest.h" 14 #include "qapi/qmp/qdict.h" 15 #include "qapi/qmp/qjson.h" 16 17 /* 18 * We expect the SVE max-vq to be 16. Also it must be <= 64 19 * for our test code, otherwise 'vls' can't just be a uint64_t. 20 */ 21 #define SVE_MAX_VQ 16 22 23 #define MACHINE "-machine virt,gic-version=max -accel tcg " 24 #define MACHINE_KVM "-machine virt,gic-version=max -accel kvm -accel tcg " 25 #define QUERY_HEAD "{ 'execute': 'query-cpu-model-expansion', " \ 26 " 'arguments': { 'type': 'full', " 27 #define QUERY_TAIL "}}" 28 29 static bool kvm_enabled(QTestState *qts) 30 { 31 QDict *resp, *qdict; 32 bool enabled; 33 34 resp = qtest_qmp(qts, "{ 'execute': 'query-kvm' }"); 35 g_assert(qdict_haskey(resp, "return")); 36 qdict = qdict_get_qdict(resp, "return"); 37 g_assert(qdict_haskey(qdict, "enabled")); 38 enabled = qdict_get_bool(qdict, "enabled"); 39 qobject_unref(resp); 40 41 return enabled; 42 } 43 44 static QDict *do_query_no_props(QTestState *qts, const char *cpu_type) 45 { 46 return qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s }" 47 QUERY_TAIL, cpu_type); 48 } 49 50 static QDict *do_query(QTestState *qts, const char *cpu_type, 51 const char *fmt, ...) 52 { 53 QDict *resp; 54 55 if (fmt) { 56 QDict *args; 57 va_list ap; 58 59 va_start(ap, fmt); 60 args = qdict_from_vjsonf_nofail(fmt, ap); 61 va_end(ap); 62 63 resp = qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s, " 64 "'props': %p }" 65 QUERY_TAIL, cpu_type, args); 66 } else { 67 resp = do_query_no_props(qts, cpu_type); 68 } 69 70 return resp; 71 } 72 73 static const char *resp_get_error(QDict *resp) 74 { 75 QDict *qdict; 76 77 g_assert(resp); 78 79 qdict = qdict_get_qdict(resp, "error"); 80 if (qdict) { 81 return qdict_get_str(qdict, "desc"); 82 } 83 84 return NULL; 85 } 86 87 #define assert_error(qts, cpu_type, expected_error, fmt, ...) \ 88 ({ \ 89 QDict *_resp; \ 90 const char *_error; \ 91 \ 92 _resp = do_query(qts, cpu_type, fmt, ##__VA_ARGS__); \ 93 g_assert(_resp); \ 94 _error = resp_get_error(_resp); \ 95 g_assert(_error); \ 96 g_assert(g_str_equal(_error, expected_error)); \ 97 qobject_unref(_resp); \ 98 }) 99 100 static bool resp_has_props(QDict *resp) 101 { 102 QDict *qdict; 103 104 g_assert(resp); 105 106 if (!qdict_haskey(resp, "return")) { 107 return false; 108 } 109 qdict = qdict_get_qdict(resp, "return"); 110 111 if (!qdict_haskey(qdict, "model")) { 112 return false; 113 } 114 qdict = qdict_get_qdict(qdict, "model"); 115 116 return qdict_haskey(qdict, "props"); 117 } 118 119 static QDict *resp_get_props(QDict *resp) 120 { 121 QDict *qdict; 122 123 g_assert(resp); 124 g_assert(resp_has_props(resp)); 125 126 qdict = qdict_get_qdict(resp, "return"); 127 qdict = qdict_get_qdict(qdict, "model"); 128 qdict = qdict_get_qdict(qdict, "props"); 129 130 return qdict; 131 } 132 133 static bool resp_get_feature(QDict *resp, const char *feature) 134 { 135 QDict *props; 136 137 g_assert(resp); 138 g_assert(resp_has_props(resp)); 139 props = resp_get_props(resp); 140 g_assert(qdict_get(props, feature)); 141 return qdict_get_bool(props, feature); 142 } 143 144 #define assert_has_feature(qts, cpu_type, feature) \ 145 ({ \ 146 QDict *_resp = do_query_no_props(qts, cpu_type); \ 147 g_assert(_resp); \ 148 g_assert(resp_has_props(_resp)); \ 149 g_assert(qdict_get(resp_get_props(_resp), feature)); \ 150 qobject_unref(_resp); \ 151 }) 152 153 #define assert_has_not_feature(qts, cpu_type, feature) \ 154 ({ \ 155 QDict *_resp = do_query_no_props(qts, cpu_type); \ 156 g_assert(_resp); \ 157 g_assert(!resp_has_props(_resp) || \ 158 !qdict_get(resp_get_props(_resp), feature)); \ 159 qobject_unref(_resp); \ 160 }) 161 162 #define assert_feature(qts, cpu_type, feature, expected_value) \ 163 ({ \ 164 QDict *_resp, *_props; \ 165 \ 166 _resp = do_query_no_props(qts, cpu_type); \ 167 g_assert(_resp); \ 168 g_assert(resp_has_props(_resp)); \ 169 _props = resp_get_props(_resp); \ 170 g_assert(qdict_get(_props, feature)); \ 171 g_assert(qdict_get_bool(_props, feature) == (expected_value)); \ 172 qobject_unref(_resp); \ 173 }) 174 175 #define assert_has_feature_enabled(qts, cpu_type, feature) \ 176 assert_feature(qts, cpu_type, feature, true) 177 178 #define assert_has_feature_disabled(qts, cpu_type, feature) \ 179 assert_feature(qts, cpu_type, feature, false) 180 181 static void assert_type_full(QTestState *qts) 182 { 183 const char *error; 184 QDict *resp; 185 186 resp = qtest_qmp(qts, "{ 'execute': 'query-cpu-model-expansion', " 187 "'arguments': { 'type': 'static', " 188 "'model': { 'name': 'foo' }}}"); 189 g_assert(resp); 190 error = resp_get_error(resp); 191 g_assert(error); 192 g_assert(g_str_equal(error, 193 "The requested expansion type is not supported")); 194 qobject_unref(resp); 195 } 196 197 static void assert_bad_props(QTestState *qts, const char *cpu_type) 198 { 199 const char *error; 200 QDict *resp; 201 202 resp = qtest_qmp(qts, "{ 'execute': 'query-cpu-model-expansion', " 203 "'arguments': { 'type': 'full', " 204 "'model': { 'name': %s, " 205 "'props': false }}}", 206 cpu_type); 207 g_assert(resp); 208 error = resp_get_error(resp); 209 g_assert(error); 210 g_assert(g_str_equal(error, 211 "Invalid parameter type for 'props', expected: dict")); 212 qobject_unref(resp); 213 } 214 215 static uint64_t resp_get_sve_vls(QDict *resp) 216 { 217 QDict *props; 218 const QDictEntry *e; 219 uint64_t vls = 0; 220 int n = 0; 221 222 g_assert(resp); 223 g_assert(resp_has_props(resp)); 224 225 props = resp_get_props(resp); 226 227 for (e = qdict_first(props); e; e = qdict_next(props, e)) { 228 if (strlen(e->key) > 3 && !strncmp(e->key, "sve", 3) && 229 g_ascii_isdigit(e->key[3])) { 230 char *endptr; 231 int bits; 232 233 bits = g_ascii_strtoll(&e->key[3], &endptr, 10); 234 if (!bits || *endptr != '\0') { 235 continue; 236 } 237 238 if (qdict_get_bool(props, e->key)) { 239 vls |= BIT_ULL((bits / 128) - 1); 240 } 241 ++n; 242 } 243 } 244 245 g_assert(n == SVE_MAX_VQ); 246 247 return vls; 248 } 249 250 #define assert_sve_vls(qts, cpu_type, expected_vls, fmt, ...) \ 251 ({ \ 252 QDict *_resp = do_query(qts, cpu_type, fmt, ##__VA_ARGS__); \ 253 g_assert(_resp); \ 254 g_assert(resp_has_props(_resp)); \ 255 g_assert(resp_get_sve_vls(_resp) == expected_vls); \ 256 qobject_unref(_resp); \ 257 }) 258 259 static void sve_tests_default(QTestState *qts, const char *cpu_type) 260 { 261 /* 262 * With no sve-max-vq or sve<N> properties on the command line 263 * the default is to have all vector lengths enabled. This also 264 * tests that 'sve' is 'on' by default. 265 */ 266 assert_sve_vls(qts, cpu_type, BIT_ULL(SVE_MAX_VQ) - 1, NULL); 267 268 /* With SVE off, all vector lengths should also be off. */ 269 assert_sve_vls(qts, cpu_type, 0, "{ 'sve': false }"); 270 271 /* With SVE on, we must have at least one vector length enabled. */ 272 assert_error(qts, cpu_type, "cannot disable sve128", "{ 'sve128': false }"); 273 274 /* Basic enable/disable tests. */ 275 assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve384': true }"); 276 assert_sve_vls(qts, cpu_type, ((BIT_ULL(SVE_MAX_VQ) - 1) & ~BIT_ULL(2)), 277 "{ 'sve384': false }"); 278 279 /* 280 * --------------------------------------------------------------------- 281 * power-of-two(vq) all-power- can can 282 * of-two(< vq) enable disable 283 * --------------------------------------------------------------------- 284 * vq < max_vq no MUST* yes yes 285 * vq < max_vq yes MUST* yes no 286 * --------------------------------------------------------------------- 287 * vq == max_vq n/a MUST* yes** yes** 288 * --------------------------------------------------------------------- 289 * vq > max_vq n/a no no yes 290 * vq > max_vq n/a yes yes yes 291 * --------------------------------------------------------------------- 292 * 293 * [*] "MUST" means this requirement must already be satisfied, 294 * otherwise 'max_vq' couldn't itself be enabled. 295 * 296 * [**] Not testable with the QMP interface, only with the command line. 297 */ 298 299 /* max_vq := 8 */ 300 assert_sve_vls(qts, cpu_type, 0x8b, "{ 'sve1024': true }"); 301 302 /* max_vq := 8, vq < max_vq, !power-of-two(vq) */ 303 assert_sve_vls(qts, cpu_type, 0x8f, 304 "{ 'sve1024': true, 'sve384': true }"); 305 assert_sve_vls(qts, cpu_type, 0x8b, 306 "{ 'sve1024': true, 'sve384': false }"); 307 308 /* max_vq := 8, vq < max_vq, power-of-two(vq) */ 309 assert_sve_vls(qts, cpu_type, 0x8b, 310 "{ 'sve1024': true, 'sve256': true }"); 311 assert_error(qts, cpu_type, "cannot disable sve256", 312 "{ 'sve1024': true, 'sve256': false }"); 313 314 /* max_vq := 3, vq > max_vq, !all-power-of-two(< vq) */ 315 assert_error(qts, cpu_type, "cannot disable sve512", 316 "{ 'sve384': true, 'sve512': false, 'sve640': true }"); 317 318 /* 319 * We can disable power-of-two vector lengths when all larger lengths 320 * are also disabled. We only need to disable the power-of-two length, 321 * as all non-enabled larger lengths will then be auto-disabled. 322 */ 323 assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve512': false }"); 324 325 /* max_vq := 3, vq > max_vq, all-power-of-two(< vq) */ 326 assert_sve_vls(qts, cpu_type, 0x1f, 327 "{ 'sve384': true, 'sve512': true, 'sve640': true }"); 328 assert_sve_vls(qts, cpu_type, 0xf, 329 "{ 'sve384': true, 'sve512': true, 'sve640': false }"); 330 } 331 332 static void sve_tests_sve_max_vq_8(const void *data) 333 { 334 QTestState *qts; 335 336 qts = qtest_init(MACHINE "-cpu max,sve-max-vq=8"); 337 338 assert_sve_vls(qts, "max", BIT_ULL(8) - 1, NULL); 339 340 /* 341 * Disabling the max-vq set by sve-max-vq is not allowed, but 342 * of course enabling it is OK. 343 */ 344 assert_error(qts, "max", "cannot disable sve1024", "{ 'sve1024': false }"); 345 assert_sve_vls(qts, "max", 0xff, "{ 'sve1024': true }"); 346 347 /* 348 * Enabling anything larger than max-vq set by sve-max-vq is not 349 * allowed, but of course disabling everything larger is OK. 350 */ 351 assert_error(qts, "max", "cannot enable sve1152", "{ 'sve1152': true }"); 352 assert_sve_vls(qts, "max", 0xff, "{ 'sve1152': false }"); 353 354 /* 355 * We can enable/disable non power-of-two lengths smaller than the 356 * max-vq set by sve-max-vq, but, while we can enable power-of-two 357 * lengths, we can't disable them. 358 */ 359 assert_sve_vls(qts, "max", 0xff, "{ 'sve384': true }"); 360 assert_sve_vls(qts, "max", 0xfb, "{ 'sve384': false }"); 361 assert_sve_vls(qts, "max", 0xff, "{ 'sve256': true }"); 362 assert_error(qts, "max", "cannot disable sve256", "{ 'sve256': false }"); 363 364 qtest_quit(qts); 365 } 366 367 static void sve_tests_sve_off(const void *data) 368 { 369 QTestState *qts; 370 371 qts = qtest_init(MACHINE "-cpu max,sve=off"); 372 373 /* SVE is off, so the map should be empty. */ 374 assert_sve_vls(qts, "max", 0, NULL); 375 376 /* The map stays empty even if we turn lengths off. */ 377 assert_sve_vls(qts, "max", 0, "{ 'sve128': false }"); 378 379 /* It's an error to enable lengths when SVE is off. */ 380 assert_error(qts, "max", "cannot enable sve128", "{ 'sve128': true }"); 381 382 /* With SVE re-enabled we should get all vector lengths enabled. */ 383 assert_sve_vls(qts, "max", BIT_ULL(SVE_MAX_VQ) - 1, "{ 'sve': true }"); 384 385 /* Or enable SVE with just specific vector lengths. */ 386 assert_sve_vls(qts, "max", 0x3, 387 "{ 'sve': true, 'sve128': true, 'sve256': true }"); 388 389 qtest_quit(qts); 390 } 391 392 static void sve_tests_sve_off_kvm(const void *data) 393 { 394 QTestState *qts; 395 396 qts = qtest_init(MACHINE_KVM "-cpu max,sve=off"); 397 398 /* 399 * We don't know if this host supports SVE so we don't 400 * attempt to test enabling anything. We only test that 401 * everything is disabled (as it should be with sve=off) 402 * and that using sve<N>=off to explicitly disable vector 403 * lengths is OK too. 404 */ 405 assert_sve_vls(qts, "max", 0, NULL); 406 assert_sve_vls(qts, "max", 0, "{ 'sve128': false }"); 407 408 qtest_quit(qts); 409 } 410 411 static void test_query_cpu_model_expansion(const void *data) 412 { 413 QTestState *qts; 414 415 qts = qtest_init(MACHINE "-cpu max"); 416 417 /* Test common query-cpu-model-expansion input validation */ 418 assert_type_full(qts); 419 assert_bad_props(qts, "max"); 420 assert_error(qts, "foo", "The CPU type 'foo' is not a recognized " 421 "ARM CPU type", NULL); 422 assert_error(qts, "max", "Parameter 'not-a-prop' is unexpected", 423 "{ 'not-a-prop': false }"); 424 assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL); 425 426 /* Test expected feature presence/absence for some cpu types */ 427 assert_has_feature_enabled(qts, "max", "pmu"); 428 assert_has_feature_enabled(qts, "cortex-a15", "pmu"); 429 assert_has_not_feature(qts, "cortex-a15", "aarch64"); 430 431 assert_has_not_feature(qts, "max", "kvm-no-adjvtime"); 432 433 if (g_str_equal(qtest_get_arch(), "aarch64")) { 434 assert_has_feature_enabled(qts, "max", "aarch64"); 435 assert_has_feature_enabled(qts, "max", "sve"); 436 assert_has_feature_enabled(qts, "max", "sve128"); 437 assert_has_feature_enabled(qts, "cortex-a57", "pmu"); 438 assert_has_feature_enabled(qts, "cortex-a57", "aarch64"); 439 440 sve_tests_default(qts, "max"); 441 442 /* Test that features that depend on KVM generate errors without. */ 443 assert_error(qts, "max", 444 "'aarch64' feature cannot be disabled " 445 "unless KVM is enabled and 32-bit EL1 " 446 "is supported", 447 "{ 'aarch64': false }"); 448 } 449 450 qtest_quit(qts); 451 } 452 453 static void test_query_cpu_model_expansion_kvm(const void *data) 454 { 455 QTestState *qts; 456 457 qts = qtest_init(MACHINE_KVM "-cpu max"); 458 459 /* 460 * These tests target the 'host' CPU type, so KVM must be enabled. 461 */ 462 if (!kvm_enabled(qts)) { 463 qtest_quit(qts); 464 return; 465 } 466 467 assert_has_feature_disabled(qts, "host", "kvm-no-adjvtime"); 468 469 if (g_str_equal(qtest_get_arch(), "aarch64")) { 470 bool kvm_supports_sve; 471 char max_name[8], name[8]; 472 uint32_t max_vq, vq; 473 uint64_t vls; 474 QDict *resp; 475 char *error; 476 477 assert_has_feature_enabled(qts, "host", "aarch64"); 478 assert_has_feature_enabled(qts, "host", "pmu"); 479 480 assert_error(qts, "cortex-a15", 481 "We cannot guarantee the CPU type 'cortex-a15' works " 482 "with KVM on this host", NULL); 483 484 assert_has_feature(qts, "host", "sve"); 485 resp = do_query_no_props(qts, "host"); 486 kvm_supports_sve = resp_get_feature(resp, "sve"); 487 vls = resp_get_sve_vls(resp); 488 qobject_unref(resp); 489 490 if (kvm_supports_sve) { 491 g_assert(vls != 0); 492 max_vq = 64 - __builtin_clzll(vls); 493 sprintf(max_name, "sve%d", max_vq * 128); 494 495 /* Enabling a supported length is of course fine. */ 496 assert_sve_vls(qts, "host", vls, "{ %s: true }", max_name); 497 498 /* Get the next supported length smaller than max-vq. */ 499 vq = 64 - __builtin_clzll(vls & ~BIT_ULL(max_vq - 1)); 500 if (vq) { 501 /* 502 * We have at least one length smaller than max-vq, 503 * so we can disable max-vq. 504 */ 505 assert_sve_vls(qts, "host", (vls & ~BIT_ULL(max_vq - 1)), 506 "{ %s: false }", max_name); 507 508 /* 509 * Smaller, supported vector lengths cannot be disabled 510 * unless all larger, supported vector lengths are also 511 * disabled. 512 */ 513 sprintf(name, "sve%d", vq * 128); 514 error = g_strdup_printf("cannot disable %s", name); 515 assert_error(qts, "host", error, 516 "{ %s: true, %s: false }", 517 max_name, name); 518 g_free(error); 519 } 520 521 /* 522 * The smallest, supported vector length is required, because 523 * we need at least one vector length enabled. 524 */ 525 vq = __builtin_ffsll(vls); 526 sprintf(name, "sve%d", vq * 128); 527 error = g_strdup_printf("cannot disable %s", name); 528 assert_error(qts, "host", error, "{ %s: false }", name); 529 g_free(error); 530 531 /* Get an unsupported length. */ 532 for (vq = 1; vq <= max_vq; ++vq) { 533 if (!(vls & BIT_ULL(vq - 1))) { 534 break; 535 } 536 } 537 if (vq <= SVE_MAX_VQ) { 538 sprintf(name, "sve%d", vq * 128); 539 error = g_strdup_printf("cannot enable %s", name); 540 assert_error(qts, "host", error, "{ %s: true }", name); 541 g_free(error); 542 } 543 } else { 544 g_assert(vls == 0); 545 } 546 } else { 547 assert_has_not_feature(qts, "host", "aarch64"); 548 assert_has_not_feature(qts, "host", "pmu"); 549 assert_has_not_feature(qts, "host", "sve"); 550 } 551 552 qtest_quit(qts); 553 } 554 555 int main(int argc, char **argv) 556 { 557 g_test_init(&argc, &argv, NULL); 558 559 qtest_add_data_func("/arm/query-cpu-model-expansion", 560 NULL, test_query_cpu_model_expansion); 561 562 /* 563 * For now we only run KVM specific tests with AArch64 QEMU in 564 * order avoid attempting to run an AArch32 QEMU with KVM on 565 * AArch64 hosts. That won't work and isn't easy to detect. 566 */ 567 if (g_str_equal(qtest_get_arch(), "aarch64")) { 568 qtest_add_data_func("/arm/kvm/query-cpu-model-expansion", 569 NULL, test_query_cpu_model_expansion_kvm); 570 } 571 572 if (g_str_equal(qtest_get_arch(), "aarch64")) { 573 qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-max-vq-8", 574 NULL, sve_tests_sve_max_vq_8); 575 qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-off", 576 NULL, sve_tests_sve_off); 577 qtest_add_data_func("/arm/kvm/query-cpu-model-expansion/sve-off", 578 NULL, sve_tests_sve_off_kvm); 579 } 580 581 return g_test_run(); 582 } 583