1bd31b751SAndrew Jones /* 2bd31b751SAndrew Jones * Arm CPU feature test cases 3bd31b751SAndrew Jones * 4bd31b751SAndrew Jones * Copyright (c) 2019 Red Hat Inc. 5bd31b751SAndrew Jones * Authors: 6bd31b751SAndrew Jones * Andrew Jones <drjones@redhat.com> 7bd31b751SAndrew Jones * 8bd31b751SAndrew Jones * This work is licensed under the terms of the GNU GPL, version 2 or later. 9bd31b751SAndrew Jones * See the COPYING file in the top-level directory. 10bd31b751SAndrew Jones */ 11bd31b751SAndrew Jones #include "qemu/osdep.h" 120df9142dSAndrew Jones #include "qemu/bitops.h" 13bd31b751SAndrew Jones #include "libqtest.h" 14bd31b751SAndrew Jones #include "qapi/qmp/qdict.h" 15bd31b751SAndrew Jones #include "qapi/qmp/qjson.h" 16bd31b751SAndrew Jones 170df9142dSAndrew Jones /* 180df9142dSAndrew Jones * We expect the SVE max-vq to be 16. Also it must be <= 64 190df9142dSAndrew Jones * for our test code, otherwise 'vls' can't just be a uint64_t. 200df9142dSAndrew Jones */ 210df9142dSAndrew Jones #define SVE_MAX_VQ 16 220df9142dSAndrew Jones 23bd31b751SAndrew Jones #define MACHINE "-machine virt,gic-version=max,accel=tcg " 24bd31b751SAndrew Jones #define MACHINE_KVM "-machine virt,gic-version=max,accel=kvm:tcg " 25bd31b751SAndrew Jones #define QUERY_HEAD "{ 'execute': 'query-cpu-model-expansion', " \ 26bd31b751SAndrew Jones " 'arguments': { 'type': 'full', " 27bd31b751SAndrew Jones #define QUERY_TAIL "}}" 28bd31b751SAndrew Jones 29bd31b751SAndrew Jones static bool kvm_enabled(QTestState *qts) 30bd31b751SAndrew Jones { 31bd31b751SAndrew Jones QDict *resp, *qdict; 32bd31b751SAndrew Jones bool enabled; 33bd31b751SAndrew Jones 34bd31b751SAndrew Jones resp = qtest_qmp(qts, "{ 'execute': 'query-kvm' }"); 35bd31b751SAndrew Jones g_assert(qdict_haskey(resp, "return")); 36bd31b751SAndrew Jones qdict = qdict_get_qdict(resp, "return"); 37bd31b751SAndrew Jones g_assert(qdict_haskey(qdict, "enabled")); 38bd31b751SAndrew Jones enabled = qdict_get_bool(qdict, "enabled"); 39bd31b751SAndrew Jones qobject_unref(resp); 40bd31b751SAndrew Jones 41bd31b751SAndrew Jones return enabled; 42bd31b751SAndrew Jones } 43bd31b751SAndrew Jones 44bd31b751SAndrew Jones static QDict *do_query_no_props(QTestState *qts, const char *cpu_type) 45bd31b751SAndrew Jones { 46bd31b751SAndrew Jones return qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s }" 47bd31b751SAndrew Jones QUERY_TAIL, cpu_type); 48bd31b751SAndrew Jones } 49bd31b751SAndrew Jones 50bd31b751SAndrew Jones static QDict *do_query(QTestState *qts, const char *cpu_type, 51bd31b751SAndrew Jones const char *fmt, ...) 52bd31b751SAndrew Jones { 53bd31b751SAndrew Jones QDict *resp; 54bd31b751SAndrew Jones 55bd31b751SAndrew Jones if (fmt) { 56bd31b751SAndrew Jones QDict *args; 57bd31b751SAndrew Jones va_list ap; 58bd31b751SAndrew Jones 59bd31b751SAndrew Jones va_start(ap, fmt); 60bd31b751SAndrew Jones args = qdict_from_vjsonf_nofail(fmt, ap); 61bd31b751SAndrew Jones va_end(ap); 62bd31b751SAndrew Jones 63bd31b751SAndrew Jones resp = qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s, " 64bd31b751SAndrew Jones "'props': %p }" 65bd31b751SAndrew Jones QUERY_TAIL, cpu_type, args); 66bd31b751SAndrew Jones } else { 67bd31b751SAndrew Jones resp = do_query_no_props(qts, cpu_type); 68bd31b751SAndrew Jones } 69bd31b751SAndrew Jones 70bd31b751SAndrew Jones return resp; 71bd31b751SAndrew Jones } 72bd31b751SAndrew Jones 73bd31b751SAndrew Jones static const char *resp_get_error(QDict *resp) 74bd31b751SAndrew Jones { 75bd31b751SAndrew Jones QDict *qdict; 76bd31b751SAndrew Jones 77bd31b751SAndrew Jones g_assert(resp); 78bd31b751SAndrew Jones 79bd31b751SAndrew Jones qdict = qdict_get_qdict(resp, "error"); 80bd31b751SAndrew Jones if (qdict) { 81bd31b751SAndrew Jones return qdict_get_str(qdict, "desc"); 82bd31b751SAndrew Jones } 83bd31b751SAndrew Jones 84bd31b751SAndrew Jones return NULL; 85bd31b751SAndrew Jones } 86bd31b751SAndrew Jones 87bd31b751SAndrew Jones #define assert_error(qts, cpu_type, expected_error, fmt, ...) \ 88bd31b751SAndrew Jones ({ \ 89bd31b751SAndrew Jones QDict *_resp; \ 90bd31b751SAndrew Jones const char *_error; \ 91bd31b751SAndrew Jones \ 92bd31b751SAndrew Jones _resp = do_query(qts, cpu_type, fmt, ##__VA_ARGS__); \ 93bd31b751SAndrew Jones g_assert(_resp); \ 94bd31b751SAndrew Jones _error = resp_get_error(_resp); \ 95bd31b751SAndrew Jones g_assert(_error); \ 96bd31b751SAndrew Jones g_assert(g_str_equal(_error, expected_error)); \ 97bd31b751SAndrew Jones qobject_unref(_resp); \ 98bd31b751SAndrew Jones }) 99bd31b751SAndrew Jones 100bd31b751SAndrew Jones static bool resp_has_props(QDict *resp) 101bd31b751SAndrew Jones { 102bd31b751SAndrew Jones QDict *qdict; 103bd31b751SAndrew Jones 104bd31b751SAndrew Jones g_assert(resp); 105bd31b751SAndrew Jones 106bd31b751SAndrew Jones if (!qdict_haskey(resp, "return")) { 107bd31b751SAndrew Jones return false; 108bd31b751SAndrew Jones } 109bd31b751SAndrew Jones qdict = qdict_get_qdict(resp, "return"); 110bd31b751SAndrew Jones 111bd31b751SAndrew Jones if (!qdict_haskey(qdict, "model")) { 112bd31b751SAndrew Jones return false; 113bd31b751SAndrew Jones } 114bd31b751SAndrew Jones qdict = qdict_get_qdict(qdict, "model"); 115bd31b751SAndrew Jones 116bd31b751SAndrew Jones return qdict_haskey(qdict, "props"); 117bd31b751SAndrew Jones } 118bd31b751SAndrew Jones 119bd31b751SAndrew Jones static QDict *resp_get_props(QDict *resp) 120bd31b751SAndrew Jones { 121bd31b751SAndrew Jones QDict *qdict; 122bd31b751SAndrew Jones 123bd31b751SAndrew Jones g_assert(resp); 124bd31b751SAndrew Jones g_assert(resp_has_props(resp)); 125bd31b751SAndrew Jones 126bd31b751SAndrew Jones qdict = qdict_get_qdict(resp, "return"); 127bd31b751SAndrew Jones qdict = qdict_get_qdict(qdict, "model"); 128bd31b751SAndrew Jones qdict = qdict_get_qdict(qdict, "props"); 129bd31b751SAndrew Jones 130bd31b751SAndrew Jones return qdict; 131bd31b751SAndrew Jones } 132bd31b751SAndrew Jones 133*6fa8a379SAndrew Jones static bool resp_get_feature(QDict *resp, const char *feature) 134*6fa8a379SAndrew Jones { 135*6fa8a379SAndrew Jones QDict *props; 136*6fa8a379SAndrew Jones 137*6fa8a379SAndrew Jones g_assert(resp); 138*6fa8a379SAndrew Jones g_assert(resp_has_props(resp)); 139*6fa8a379SAndrew Jones props = resp_get_props(resp); 140*6fa8a379SAndrew Jones g_assert(qdict_get(props, feature)); 141*6fa8a379SAndrew Jones return qdict_get_bool(props, feature); 142*6fa8a379SAndrew Jones } 143*6fa8a379SAndrew Jones 144bd31b751SAndrew Jones #define assert_has_feature(qts, cpu_type, feature) \ 145bd31b751SAndrew Jones ({ \ 146bd31b751SAndrew Jones QDict *_resp = do_query_no_props(qts, cpu_type); \ 147bd31b751SAndrew Jones g_assert(_resp); \ 148bd31b751SAndrew Jones g_assert(resp_has_props(_resp)); \ 149bd31b751SAndrew Jones g_assert(qdict_get(resp_get_props(_resp), feature)); \ 150bd31b751SAndrew Jones qobject_unref(_resp); \ 151bd31b751SAndrew Jones }) 152bd31b751SAndrew Jones 153bd31b751SAndrew Jones #define assert_has_not_feature(qts, cpu_type, feature) \ 154bd31b751SAndrew Jones ({ \ 155bd31b751SAndrew Jones QDict *_resp = do_query_no_props(qts, cpu_type); \ 156bd31b751SAndrew Jones g_assert(_resp); \ 157bd31b751SAndrew Jones g_assert(!resp_has_props(_resp) || \ 158bd31b751SAndrew Jones !qdict_get(resp_get_props(_resp), feature)); \ 159bd31b751SAndrew Jones qobject_unref(_resp); \ 160bd31b751SAndrew Jones }) 161bd31b751SAndrew Jones 162bd31b751SAndrew Jones static void assert_type_full(QTestState *qts) 163bd31b751SAndrew Jones { 164bd31b751SAndrew Jones const char *error; 165bd31b751SAndrew Jones QDict *resp; 166bd31b751SAndrew Jones 167bd31b751SAndrew Jones resp = qtest_qmp(qts, "{ 'execute': 'query-cpu-model-expansion', " 168bd31b751SAndrew Jones "'arguments': { 'type': 'static', " 169bd31b751SAndrew Jones "'model': { 'name': 'foo' }}}"); 170bd31b751SAndrew Jones g_assert(resp); 171bd31b751SAndrew Jones error = resp_get_error(resp); 172bd31b751SAndrew Jones g_assert(error); 173bd31b751SAndrew Jones g_assert(g_str_equal(error, 174bd31b751SAndrew Jones "The requested expansion type is not supported")); 175bd31b751SAndrew Jones qobject_unref(resp); 176bd31b751SAndrew Jones } 177bd31b751SAndrew Jones 178bd31b751SAndrew Jones static void assert_bad_props(QTestState *qts, const char *cpu_type) 179bd31b751SAndrew Jones { 180bd31b751SAndrew Jones const char *error; 181bd31b751SAndrew Jones QDict *resp; 182bd31b751SAndrew Jones 183bd31b751SAndrew Jones resp = qtest_qmp(qts, "{ 'execute': 'query-cpu-model-expansion', " 184bd31b751SAndrew Jones "'arguments': { 'type': 'full', " 185bd31b751SAndrew Jones "'model': { 'name': %s, " 186bd31b751SAndrew Jones "'props': false }}}", 187bd31b751SAndrew Jones cpu_type); 188bd31b751SAndrew Jones g_assert(resp); 189bd31b751SAndrew Jones error = resp_get_error(resp); 190bd31b751SAndrew Jones g_assert(error); 191bd31b751SAndrew Jones g_assert(g_str_equal(error, 192bd31b751SAndrew Jones "Invalid parameter type for 'props', expected: dict")); 193bd31b751SAndrew Jones qobject_unref(resp); 194bd31b751SAndrew Jones } 195bd31b751SAndrew Jones 1960df9142dSAndrew Jones static uint64_t resp_get_sve_vls(QDict *resp) 1970df9142dSAndrew Jones { 1980df9142dSAndrew Jones QDict *props; 1990df9142dSAndrew Jones const QDictEntry *e; 2000df9142dSAndrew Jones uint64_t vls = 0; 2010df9142dSAndrew Jones int n = 0; 2020df9142dSAndrew Jones 2030df9142dSAndrew Jones g_assert(resp); 2040df9142dSAndrew Jones g_assert(resp_has_props(resp)); 2050df9142dSAndrew Jones 2060df9142dSAndrew Jones props = resp_get_props(resp); 2070df9142dSAndrew Jones 2080df9142dSAndrew Jones for (e = qdict_first(props); e; e = qdict_next(props, e)) { 2090df9142dSAndrew Jones if (strlen(e->key) > 3 && !strncmp(e->key, "sve", 3) && 2100df9142dSAndrew Jones g_ascii_isdigit(e->key[3])) { 2110df9142dSAndrew Jones char *endptr; 2120df9142dSAndrew Jones int bits; 2130df9142dSAndrew Jones 2140df9142dSAndrew Jones bits = g_ascii_strtoll(&e->key[3], &endptr, 10); 2150df9142dSAndrew Jones if (!bits || *endptr != '\0') { 2160df9142dSAndrew Jones continue; 2170df9142dSAndrew Jones } 2180df9142dSAndrew Jones 2190df9142dSAndrew Jones if (qdict_get_bool(props, e->key)) { 2200df9142dSAndrew Jones vls |= BIT_ULL((bits / 128) - 1); 2210df9142dSAndrew Jones } 2220df9142dSAndrew Jones ++n; 2230df9142dSAndrew Jones } 2240df9142dSAndrew Jones } 2250df9142dSAndrew Jones 2260df9142dSAndrew Jones g_assert(n == SVE_MAX_VQ); 2270df9142dSAndrew Jones 2280df9142dSAndrew Jones return vls; 2290df9142dSAndrew Jones } 2300df9142dSAndrew Jones 2310df9142dSAndrew Jones #define assert_sve_vls(qts, cpu_type, expected_vls, fmt, ...) \ 2320df9142dSAndrew Jones ({ \ 2330df9142dSAndrew Jones QDict *_resp = do_query(qts, cpu_type, fmt, ##__VA_ARGS__); \ 2340df9142dSAndrew Jones g_assert(_resp); \ 2350df9142dSAndrew Jones g_assert(resp_has_props(_resp)); \ 2360df9142dSAndrew Jones g_assert(resp_get_sve_vls(_resp) == expected_vls); \ 2370df9142dSAndrew Jones qobject_unref(_resp); \ 2380df9142dSAndrew Jones }) 2390df9142dSAndrew Jones 2400df9142dSAndrew Jones static void sve_tests_default(QTestState *qts, const char *cpu_type) 2410df9142dSAndrew Jones { 2420df9142dSAndrew Jones /* 2430df9142dSAndrew Jones * With no sve-max-vq or sve<N> properties on the command line 2440df9142dSAndrew Jones * the default is to have all vector lengths enabled. This also 2450df9142dSAndrew Jones * tests that 'sve' is 'on' by default. 2460df9142dSAndrew Jones */ 2470df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, BIT_ULL(SVE_MAX_VQ) - 1, NULL); 2480df9142dSAndrew Jones 2490df9142dSAndrew Jones /* With SVE off, all vector lengths should also be off. */ 2500df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0, "{ 'sve': false }"); 2510df9142dSAndrew Jones 2520df9142dSAndrew Jones /* With SVE on, we must have at least one vector length enabled. */ 2530df9142dSAndrew Jones assert_error(qts, cpu_type, "cannot disable sve128", "{ 'sve128': false }"); 2540df9142dSAndrew Jones 2550df9142dSAndrew Jones /* Basic enable/disable tests. */ 2560df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve384': true }"); 2570df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, ((BIT_ULL(SVE_MAX_VQ) - 1) & ~BIT_ULL(2)), 2580df9142dSAndrew Jones "{ 'sve384': false }"); 2590df9142dSAndrew Jones 2600df9142dSAndrew Jones /* 2610df9142dSAndrew Jones * --------------------------------------------------------------------- 2620df9142dSAndrew Jones * power-of-two(vq) all-power- can can 2630df9142dSAndrew Jones * of-two(< vq) enable disable 2640df9142dSAndrew Jones * --------------------------------------------------------------------- 2650df9142dSAndrew Jones * vq < max_vq no MUST* yes yes 2660df9142dSAndrew Jones * vq < max_vq yes MUST* yes no 2670df9142dSAndrew Jones * --------------------------------------------------------------------- 2680df9142dSAndrew Jones * vq == max_vq n/a MUST* yes** yes** 2690df9142dSAndrew Jones * --------------------------------------------------------------------- 2700df9142dSAndrew Jones * vq > max_vq n/a no no yes 2710df9142dSAndrew Jones * vq > max_vq n/a yes yes yes 2720df9142dSAndrew Jones * --------------------------------------------------------------------- 2730df9142dSAndrew Jones * 2740df9142dSAndrew Jones * [*] "MUST" means this requirement must already be satisfied, 2750df9142dSAndrew Jones * otherwise 'max_vq' couldn't itself be enabled. 2760df9142dSAndrew Jones * 2770df9142dSAndrew Jones * [**] Not testable with the QMP interface, only with the command line. 2780df9142dSAndrew Jones */ 2790df9142dSAndrew Jones 2800df9142dSAndrew Jones /* max_vq := 8 */ 2810df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8b, "{ 'sve1024': true }"); 2820df9142dSAndrew Jones 2830df9142dSAndrew Jones /* max_vq := 8, vq < max_vq, !power-of-two(vq) */ 2840df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8f, 2850df9142dSAndrew Jones "{ 'sve1024': true, 'sve384': true }"); 2860df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8b, 2870df9142dSAndrew Jones "{ 'sve1024': true, 'sve384': false }"); 2880df9142dSAndrew Jones 2890df9142dSAndrew Jones /* max_vq := 8, vq < max_vq, power-of-two(vq) */ 2900df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8b, 2910df9142dSAndrew Jones "{ 'sve1024': true, 'sve256': true }"); 2920df9142dSAndrew Jones assert_error(qts, cpu_type, "cannot disable sve256", 2930df9142dSAndrew Jones "{ 'sve1024': true, 'sve256': false }"); 2940df9142dSAndrew Jones 2950df9142dSAndrew Jones /* max_vq := 3, vq > max_vq, !all-power-of-two(< vq) */ 2960df9142dSAndrew Jones assert_error(qts, cpu_type, "cannot disable sve512", 2970df9142dSAndrew Jones "{ 'sve384': true, 'sve512': false, 'sve640': true }"); 2980df9142dSAndrew Jones 2990df9142dSAndrew Jones /* 3000df9142dSAndrew Jones * We can disable power-of-two vector lengths when all larger lengths 3010df9142dSAndrew Jones * are also disabled. We only need to disable the power-of-two length, 3020df9142dSAndrew Jones * as all non-enabled larger lengths will then be auto-disabled. 3030df9142dSAndrew Jones */ 3040df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve512': false }"); 3050df9142dSAndrew Jones 3060df9142dSAndrew Jones /* max_vq := 3, vq > max_vq, all-power-of-two(< vq) */ 3070df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x1f, 3080df9142dSAndrew Jones "{ 'sve384': true, 'sve512': true, 'sve640': true }"); 3090df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0xf, 3100df9142dSAndrew Jones "{ 'sve384': true, 'sve512': true, 'sve640': false }"); 3110df9142dSAndrew Jones } 3120df9142dSAndrew Jones 3130df9142dSAndrew Jones static void sve_tests_sve_max_vq_8(const void *data) 3140df9142dSAndrew Jones { 3150df9142dSAndrew Jones QTestState *qts; 3160df9142dSAndrew Jones 3170df9142dSAndrew Jones qts = qtest_init(MACHINE "-cpu max,sve-max-vq=8"); 3180df9142dSAndrew Jones 3190df9142dSAndrew Jones assert_sve_vls(qts, "max", BIT_ULL(8) - 1, NULL); 3200df9142dSAndrew Jones 3210df9142dSAndrew Jones /* 3220df9142dSAndrew Jones * Disabling the max-vq set by sve-max-vq is not allowed, but 3230df9142dSAndrew Jones * of course enabling it is OK. 3240df9142dSAndrew Jones */ 3250df9142dSAndrew Jones assert_error(qts, "max", "cannot disable sve1024", "{ 'sve1024': false }"); 3260df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve1024': true }"); 3270df9142dSAndrew Jones 3280df9142dSAndrew Jones /* 3290df9142dSAndrew Jones * Enabling anything larger than max-vq set by sve-max-vq is not 3300df9142dSAndrew Jones * allowed, but of course disabling everything larger is OK. 3310df9142dSAndrew Jones */ 3320df9142dSAndrew Jones assert_error(qts, "max", "cannot enable sve1152", "{ 'sve1152': true }"); 3330df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve1152': false }"); 3340df9142dSAndrew Jones 3350df9142dSAndrew Jones /* 3360df9142dSAndrew Jones * We can enable/disable non power-of-two lengths smaller than the 3370df9142dSAndrew Jones * max-vq set by sve-max-vq, but, while we can enable power-of-two 3380df9142dSAndrew Jones * lengths, we can't disable them. 3390df9142dSAndrew Jones */ 3400df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve384': true }"); 3410df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xfb, "{ 'sve384': false }"); 3420df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve256': true }"); 3430df9142dSAndrew Jones assert_error(qts, "max", "cannot disable sve256", "{ 'sve256': false }"); 3440df9142dSAndrew Jones 3450df9142dSAndrew Jones qtest_quit(qts); 3460df9142dSAndrew Jones } 3470df9142dSAndrew Jones 3480df9142dSAndrew Jones static void sve_tests_sve_off(const void *data) 3490df9142dSAndrew Jones { 3500df9142dSAndrew Jones QTestState *qts; 3510df9142dSAndrew Jones 3520df9142dSAndrew Jones qts = qtest_init(MACHINE "-cpu max,sve=off"); 3530df9142dSAndrew Jones 3540df9142dSAndrew Jones /* SVE is off, so the map should be empty. */ 3550df9142dSAndrew Jones assert_sve_vls(qts, "max", 0, NULL); 3560df9142dSAndrew Jones 3570df9142dSAndrew Jones /* The map stays empty even if we turn lengths off. */ 3580df9142dSAndrew Jones assert_sve_vls(qts, "max", 0, "{ 'sve128': false }"); 3590df9142dSAndrew Jones 3600df9142dSAndrew Jones /* It's an error to enable lengths when SVE is off. */ 3610df9142dSAndrew Jones assert_error(qts, "max", "cannot enable sve128", "{ 'sve128': true }"); 3620df9142dSAndrew Jones 3630df9142dSAndrew Jones /* With SVE re-enabled we should get all vector lengths enabled. */ 3640df9142dSAndrew Jones assert_sve_vls(qts, "max", BIT_ULL(SVE_MAX_VQ) - 1, "{ 'sve': true }"); 3650df9142dSAndrew Jones 3660df9142dSAndrew Jones /* Or enable SVE with just specific vector lengths. */ 3670df9142dSAndrew Jones assert_sve_vls(qts, "max", 0x3, 3680df9142dSAndrew Jones "{ 'sve': true, 'sve128': true, 'sve256': true }"); 3690df9142dSAndrew Jones 3700df9142dSAndrew Jones qtest_quit(qts); 3710df9142dSAndrew Jones } 3720df9142dSAndrew Jones 373*6fa8a379SAndrew Jones static void sve_tests_sve_off_kvm(const void *data) 374*6fa8a379SAndrew Jones { 375*6fa8a379SAndrew Jones QTestState *qts; 376*6fa8a379SAndrew Jones 377*6fa8a379SAndrew Jones qts = qtest_init(MACHINE_KVM "-cpu max,sve=off"); 378*6fa8a379SAndrew Jones 379*6fa8a379SAndrew Jones /* 380*6fa8a379SAndrew Jones * We don't know if this host supports SVE so we don't 381*6fa8a379SAndrew Jones * attempt to test enabling anything. We only test that 382*6fa8a379SAndrew Jones * everything is disabled (as it should be with sve=off) 383*6fa8a379SAndrew Jones * and that using sve<N>=off to explicitly disable vector 384*6fa8a379SAndrew Jones * lengths is OK too. 385*6fa8a379SAndrew Jones */ 386*6fa8a379SAndrew Jones assert_sve_vls(qts, "max", 0, NULL); 387*6fa8a379SAndrew Jones assert_sve_vls(qts, "max", 0, "{ 'sve128': false }"); 388*6fa8a379SAndrew Jones 389*6fa8a379SAndrew Jones qtest_quit(qts); 390*6fa8a379SAndrew Jones } 391*6fa8a379SAndrew Jones 392bd31b751SAndrew Jones static void test_query_cpu_model_expansion(const void *data) 393bd31b751SAndrew Jones { 394bd31b751SAndrew Jones QTestState *qts; 395bd31b751SAndrew Jones 396bd31b751SAndrew Jones qts = qtest_init(MACHINE "-cpu max"); 397bd31b751SAndrew Jones 398bd31b751SAndrew Jones /* Test common query-cpu-model-expansion input validation */ 399bd31b751SAndrew Jones assert_type_full(qts); 400bd31b751SAndrew Jones assert_bad_props(qts, "max"); 401bd31b751SAndrew Jones assert_error(qts, "foo", "The CPU type 'foo' is not a recognized " 402bd31b751SAndrew Jones "ARM CPU type", NULL); 403bd31b751SAndrew Jones assert_error(qts, "max", "Parameter 'not-a-prop' is unexpected", 404bd31b751SAndrew Jones "{ 'not-a-prop': false }"); 405bd31b751SAndrew Jones assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL); 406bd31b751SAndrew Jones 407bd31b751SAndrew Jones /* Test expected feature presence/absence for some cpu types */ 408bd31b751SAndrew Jones assert_has_feature(qts, "max", "pmu"); 409bd31b751SAndrew Jones assert_has_feature(qts, "cortex-a15", "pmu"); 410bd31b751SAndrew Jones assert_has_not_feature(qts, "cortex-a15", "aarch64"); 411bd31b751SAndrew Jones 412bd31b751SAndrew Jones if (g_str_equal(qtest_get_arch(), "aarch64")) { 413bd31b751SAndrew Jones assert_has_feature(qts, "max", "aarch64"); 41473234775SAndrew Jones assert_has_feature(qts, "max", "sve"); 4150df9142dSAndrew Jones assert_has_feature(qts, "max", "sve128"); 416bd31b751SAndrew Jones assert_has_feature(qts, "cortex-a57", "pmu"); 417bd31b751SAndrew Jones assert_has_feature(qts, "cortex-a57", "aarch64"); 418bd31b751SAndrew Jones 4190df9142dSAndrew Jones sve_tests_default(qts, "max"); 4200df9142dSAndrew Jones 421bd31b751SAndrew Jones /* Test that features that depend on KVM generate errors without. */ 422bd31b751SAndrew Jones assert_error(qts, "max", 423bd31b751SAndrew Jones "'aarch64' feature cannot be disabled " 424bd31b751SAndrew Jones "unless KVM is enabled and 32-bit EL1 " 425bd31b751SAndrew Jones "is supported", 426bd31b751SAndrew Jones "{ 'aarch64': false }"); 427bd31b751SAndrew Jones } 428bd31b751SAndrew Jones 429bd31b751SAndrew Jones qtest_quit(qts); 430bd31b751SAndrew Jones } 431bd31b751SAndrew Jones 432bd31b751SAndrew Jones static void test_query_cpu_model_expansion_kvm(const void *data) 433bd31b751SAndrew Jones { 434bd31b751SAndrew Jones QTestState *qts; 435bd31b751SAndrew Jones 436bd31b751SAndrew Jones qts = qtest_init(MACHINE_KVM "-cpu max"); 437bd31b751SAndrew Jones 438bd31b751SAndrew Jones /* 439bd31b751SAndrew Jones * These tests target the 'host' CPU type, so KVM must be enabled. 440bd31b751SAndrew Jones */ 441bd31b751SAndrew Jones if (!kvm_enabled(qts)) { 442bd31b751SAndrew Jones qtest_quit(qts); 443bd31b751SAndrew Jones return; 444bd31b751SAndrew Jones } 445bd31b751SAndrew Jones 446bd31b751SAndrew Jones if (g_str_equal(qtest_get_arch(), "aarch64")) { 447*6fa8a379SAndrew Jones bool kvm_supports_sve; 448*6fa8a379SAndrew Jones char max_name[8], name[8]; 449*6fa8a379SAndrew Jones uint32_t max_vq, vq; 450*6fa8a379SAndrew Jones uint64_t vls; 451*6fa8a379SAndrew Jones QDict *resp; 452*6fa8a379SAndrew Jones char *error; 453*6fa8a379SAndrew Jones 454bd31b751SAndrew Jones assert_has_feature(qts, "host", "aarch64"); 455bd31b751SAndrew Jones assert_has_feature(qts, "host", "pmu"); 456bd31b751SAndrew Jones 457bd31b751SAndrew Jones assert_error(qts, "cortex-a15", 458bd31b751SAndrew Jones "We cannot guarantee the CPU type 'cortex-a15' works " 459bd31b751SAndrew Jones "with KVM on this host", NULL); 460*6fa8a379SAndrew Jones 461*6fa8a379SAndrew Jones assert_has_feature(qts, "max", "sve"); 462*6fa8a379SAndrew Jones resp = do_query_no_props(qts, "max"); 463*6fa8a379SAndrew Jones kvm_supports_sve = resp_get_feature(resp, "sve"); 464*6fa8a379SAndrew Jones vls = resp_get_sve_vls(resp); 465*6fa8a379SAndrew Jones qobject_unref(resp); 466*6fa8a379SAndrew Jones 467*6fa8a379SAndrew Jones if (kvm_supports_sve) { 468*6fa8a379SAndrew Jones g_assert(vls != 0); 469*6fa8a379SAndrew Jones max_vq = 64 - __builtin_clzll(vls); 470*6fa8a379SAndrew Jones sprintf(max_name, "sve%d", max_vq * 128); 471*6fa8a379SAndrew Jones 472*6fa8a379SAndrew Jones /* Enabling a supported length is of course fine. */ 473*6fa8a379SAndrew Jones assert_sve_vls(qts, "max", vls, "{ %s: true }", max_name); 474*6fa8a379SAndrew Jones 475*6fa8a379SAndrew Jones /* Get the next supported length smaller than max-vq. */ 476*6fa8a379SAndrew Jones vq = 64 - __builtin_clzll(vls & ~BIT_ULL(max_vq - 1)); 477*6fa8a379SAndrew Jones if (vq) { 478*6fa8a379SAndrew Jones /* 479*6fa8a379SAndrew Jones * We have at least one length smaller than max-vq, 480*6fa8a379SAndrew Jones * so we can disable max-vq. 481*6fa8a379SAndrew Jones */ 482*6fa8a379SAndrew Jones assert_sve_vls(qts, "max", (vls & ~BIT_ULL(max_vq - 1)), 483*6fa8a379SAndrew Jones "{ %s: false }", max_name); 484*6fa8a379SAndrew Jones 485*6fa8a379SAndrew Jones /* 486*6fa8a379SAndrew Jones * Smaller, supported vector lengths cannot be disabled 487*6fa8a379SAndrew Jones * unless all larger, supported vector lengths are also 488*6fa8a379SAndrew Jones * disabled. 489*6fa8a379SAndrew Jones */ 490*6fa8a379SAndrew Jones sprintf(name, "sve%d", vq * 128); 491*6fa8a379SAndrew Jones error = g_strdup_printf("cannot disable %s", name); 492*6fa8a379SAndrew Jones assert_error(qts, "max", error, 493*6fa8a379SAndrew Jones "{ %s: true, %s: false }", 494*6fa8a379SAndrew Jones max_name, name); 495*6fa8a379SAndrew Jones g_free(error); 496*6fa8a379SAndrew Jones } 497*6fa8a379SAndrew Jones 498*6fa8a379SAndrew Jones /* 499*6fa8a379SAndrew Jones * The smallest, supported vector length is required, because 500*6fa8a379SAndrew Jones * we need at least one vector length enabled. 501*6fa8a379SAndrew Jones */ 502*6fa8a379SAndrew Jones vq = __builtin_ffsll(vls); 503*6fa8a379SAndrew Jones sprintf(name, "sve%d", vq * 128); 504*6fa8a379SAndrew Jones error = g_strdup_printf("cannot disable %s", name); 505*6fa8a379SAndrew Jones assert_error(qts, "max", error, "{ %s: false }", name); 506*6fa8a379SAndrew Jones g_free(error); 507*6fa8a379SAndrew Jones 508*6fa8a379SAndrew Jones /* Get an unsupported length. */ 509*6fa8a379SAndrew Jones for (vq = 1; vq <= max_vq; ++vq) { 510*6fa8a379SAndrew Jones if (!(vls & BIT_ULL(vq - 1))) { 511*6fa8a379SAndrew Jones break; 512*6fa8a379SAndrew Jones } 513*6fa8a379SAndrew Jones } 514*6fa8a379SAndrew Jones if (vq <= SVE_MAX_VQ) { 515*6fa8a379SAndrew Jones sprintf(name, "sve%d", vq * 128); 516*6fa8a379SAndrew Jones error = g_strdup_printf("cannot enable %s", name); 517*6fa8a379SAndrew Jones assert_error(qts, "max", error, "{ %s: true }", name); 518*6fa8a379SAndrew Jones g_free(error); 519*6fa8a379SAndrew Jones } 520*6fa8a379SAndrew Jones } else { 521*6fa8a379SAndrew Jones g_assert(vls == 0); 522*6fa8a379SAndrew Jones } 523bd31b751SAndrew Jones } else { 524bd31b751SAndrew Jones assert_has_not_feature(qts, "host", "aarch64"); 525bd31b751SAndrew Jones assert_has_not_feature(qts, "host", "pmu"); 52614e99e0fSAndrew Jones 52714e99e0fSAndrew Jones assert_has_not_feature(qts, "max", "sve"); 528bd31b751SAndrew Jones } 529bd31b751SAndrew Jones 530bd31b751SAndrew Jones qtest_quit(qts); 531bd31b751SAndrew Jones } 532bd31b751SAndrew Jones 533bd31b751SAndrew Jones int main(int argc, char **argv) 534bd31b751SAndrew Jones { 535bd31b751SAndrew Jones g_test_init(&argc, &argv, NULL); 536bd31b751SAndrew Jones 537bd31b751SAndrew Jones qtest_add_data_func("/arm/query-cpu-model-expansion", 538bd31b751SAndrew Jones NULL, test_query_cpu_model_expansion); 539bd31b751SAndrew Jones 540bd31b751SAndrew Jones /* 541bd31b751SAndrew Jones * For now we only run KVM specific tests with AArch64 QEMU in 542bd31b751SAndrew Jones * order avoid attempting to run an AArch32 QEMU with KVM on 543bd31b751SAndrew Jones * AArch64 hosts. That won't work and isn't easy to detect. 544bd31b751SAndrew Jones */ 545bd31b751SAndrew Jones if (g_str_equal(qtest_get_arch(), "aarch64")) { 546bd31b751SAndrew Jones qtest_add_data_func("/arm/kvm/query-cpu-model-expansion", 547bd31b751SAndrew Jones NULL, test_query_cpu_model_expansion_kvm); 548bd31b751SAndrew Jones } 549bd31b751SAndrew Jones 5500df9142dSAndrew Jones if (g_str_equal(qtest_get_arch(), "aarch64")) { 5510df9142dSAndrew Jones qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-max-vq-8", 5520df9142dSAndrew Jones NULL, sve_tests_sve_max_vq_8); 5530df9142dSAndrew Jones qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-off", 5540df9142dSAndrew Jones NULL, sve_tests_sve_off); 555*6fa8a379SAndrew Jones qtest_add_data_func("/arm/kvm/query-cpu-model-expansion/sve-off", 556*6fa8a379SAndrew Jones NULL, sve_tests_sve_off_kvm); 5570df9142dSAndrew Jones } 5580df9142dSAndrew Jones 559bd31b751SAndrew Jones return g_test_run(); 560bd31b751SAndrew Jones } 561