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" 13907b5105SMarc-André Lureau #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 236f6e1698SPaolo Bonzini #define MACHINE "-machine virt,gic-version=max -accel tcg " 24500a0accSFabiano Rosas #define MACHINE_KVM "-machine virt,gic-version=max -accel kvm " 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 QDict *do_query_no_props(QTestState *qts, const char *cpu_type) 30bd31b751SAndrew Jones { 31bd31b751SAndrew Jones return qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s }" 32bd31b751SAndrew Jones QUERY_TAIL, cpu_type); 33bd31b751SAndrew Jones } 34bd31b751SAndrew Jones 350472b2e5SDaniel P. Berrangé G_GNUC_PRINTF(3, 4) 36bd31b751SAndrew Jones static QDict *do_query(QTestState *qts, const char *cpu_type, 37bd31b751SAndrew Jones const char *fmt, ...) 38bd31b751SAndrew Jones { 39bd31b751SAndrew Jones QDict *resp; 40bd31b751SAndrew Jones 41bd31b751SAndrew Jones if (fmt) { 42bd31b751SAndrew Jones QDict *args; 43bd31b751SAndrew Jones va_list ap; 44bd31b751SAndrew Jones 45bd31b751SAndrew Jones va_start(ap, fmt); 46bd31b751SAndrew Jones args = qdict_from_vjsonf_nofail(fmt, ap); 47bd31b751SAndrew Jones va_end(ap); 48bd31b751SAndrew Jones 49bd31b751SAndrew Jones resp = qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s, " 50bd31b751SAndrew Jones "'props': %p }" 51bd31b751SAndrew Jones QUERY_TAIL, cpu_type, args); 52bd31b751SAndrew Jones } else { 53bd31b751SAndrew Jones resp = do_query_no_props(qts, cpu_type); 54bd31b751SAndrew Jones } 55bd31b751SAndrew Jones 56bd31b751SAndrew Jones return resp; 57bd31b751SAndrew Jones } 58bd31b751SAndrew Jones 59bd31b751SAndrew Jones static const char *resp_get_error(QDict *resp) 60bd31b751SAndrew Jones { 61bd31b751SAndrew Jones QDict *qdict; 62bd31b751SAndrew Jones 63bd31b751SAndrew Jones g_assert(resp); 64bd31b751SAndrew Jones 65bd31b751SAndrew Jones qdict = qdict_get_qdict(resp, "error"); 66bd31b751SAndrew Jones if (qdict) { 67bd31b751SAndrew Jones return qdict_get_str(qdict, "desc"); 68bd31b751SAndrew Jones } 69bd31b751SAndrew Jones 70bd31b751SAndrew Jones return NULL; 71bd31b751SAndrew Jones } 72bd31b751SAndrew Jones 73bd31b751SAndrew Jones #define assert_error(qts, cpu_type, expected_error, fmt, ...) \ 74bd31b751SAndrew Jones ({ \ 75bd31b751SAndrew Jones QDict *_resp; \ 76bd31b751SAndrew Jones const char *_error; \ 77bd31b751SAndrew Jones \ 78bd31b751SAndrew Jones _resp = do_query(qts, cpu_type, fmt, ##__VA_ARGS__); \ 79bd31b751SAndrew Jones g_assert(_resp); \ 80bd31b751SAndrew Jones _error = resp_get_error(_resp); \ 81bd31b751SAndrew Jones g_assert(_error); \ 82*ef6783d3SMarkus Armbruster g_assert_cmpstr(_error, ==, expected_error); \ 83bd31b751SAndrew Jones qobject_unref(_resp); \ 84bd31b751SAndrew Jones }) 85bd31b751SAndrew Jones 86bd31b751SAndrew Jones static bool resp_has_props(QDict *resp) 87bd31b751SAndrew Jones { 88bd31b751SAndrew Jones QDict *qdict; 89bd31b751SAndrew Jones 90bd31b751SAndrew Jones g_assert(resp); 91bd31b751SAndrew Jones 92bd31b751SAndrew Jones if (!qdict_haskey(resp, "return")) { 93bd31b751SAndrew Jones return false; 94bd31b751SAndrew Jones } 95bd31b751SAndrew Jones qdict = qdict_get_qdict(resp, "return"); 96bd31b751SAndrew Jones 97bd31b751SAndrew Jones if (!qdict_haskey(qdict, "model")) { 98bd31b751SAndrew Jones return false; 99bd31b751SAndrew Jones } 100bd31b751SAndrew Jones qdict = qdict_get_qdict(qdict, "model"); 101bd31b751SAndrew Jones 102bd31b751SAndrew Jones return qdict_haskey(qdict, "props"); 103bd31b751SAndrew Jones } 104bd31b751SAndrew Jones 105bd31b751SAndrew Jones static QDict *resp_get_props(QDict *resp) 106bd31b751SAndrew Jones { 107bd31b751SAndrew Jones QDict *qdict; 108bd31b751SAndrew Jones 109bd31b751SAndrew Jones g_assert(resp); 110bd31b751SAndrew Jones g_assert(resp_has_props(resp)); 111bd31b751SAndrew Jones 112bd31b751SAndrew Jones qdict = qdict_get_qdict(resp, "return"); 113bd31b751SAndrew Jones qdict = qdict_get_qdict(qdict, "model"); 114bd31b751SAndrew Jones qdict = qdict_get_qdict(qdict, "props"); 115bd31b751SAndrew Jones 116bd31b751SAndrew Jones return qdict; 117bd31b751SAndrew Jones } 118bd31b751SAndrew Jones 1196fa8a379SAndrew Jones static bool resp_get_feature(QDict *resp, const char *feature) 1206fa8a379SAndrew Jones { 1216fa8a379SAndrew Jones QDict *props; 1226fa8a379SAndrew Jones 1236fa8a379SAndrew Jones g_assert(resp); 1246fa8a379SAndrew Jones g_assert(resp_has_props(resp)); 1256fa8a379SAndrew Jones props = resp_get_props(resp); 1266fa8a379SAndrew Jones g_assert(qdict_get(props, feature)); 1276fa8a379SAndrew Jones return qdict_get_bool(props, feature); 1286fa8a379SAndrew Jones } 1296fa8a379SAndrew Jones 130bd31b751SAndrew Jones #define assert_has_feature(qts, cpu_type, feature) \ 131bd31b751SAndrew Jones ({ \ 132bd31b751SAndrew Jones QDict *_resp = do_query_no_props(qts, cpu_type); \ 133bd31b751SAndrew Jones g_assert(_resp); \ 134bd31b751SAndrew Jones g_assert(resp_has_props(_resp)); \ 135bd31b751SAndrew Jones g_assert(qdict_get(resp_get_props(_resp), feature)); \ 136bd31b751SAndrew Jones qobject_unref(_resp); \ 137bd31b751SAndrew Jones }) 138bd31b751SAndrew Jones 139bd31b751SAndrew Jones #define assert_has_not_feature(qts, cpu_type, feature) \ 140bd31b751SAndrew Jones ({ \ 141bd31b751SAndrew Jones QDict *_resp = do_query_no_props(qts, cpu_type); \ 142bd31b751SAndrew Jones g_assert(_resp); \ 143bd31b751SAndrew Jones g_assert(!resp_has_props(_resp) || \ 144bd31b751SAndrew Jones !qdict_get(resp_get_props(_resp), feature)); \ 145bd31b751SAndrew Jones qobject_unref(_resp); \ 146bd31b751SAndrew Jones }) 147bd31b751SAndrew Jones 14892a70997SAndrew Jones #define resp_assert_feature(resp, feature, expected_value) \ 149789a35efSAndrew Jones ({ \ 15092a70997SAndrew Jones QDict *_props; \ 151789a35efSAndrew Jones \ 152789a35efSAndrew Jones g_assert(_resp); \ 153789a35efSAndrew Jones g_assert(resp_has_props(_resp)); \ 154789a35efSAndrew Jones _props = resp_get_props(_resp); \ 155789a35efSAndrew Jones g_assert(qdict_get(_props, feature)); \ 156789a35efSAndrew Jones g_assert(qdict_get_bool(_props, feature) == (expected_value)); \ 15792a70997SAndrew Jones }) 15892a70997SAndrew Jones 15992a70997SAndrew Jones #define assert_feature(qts, cpu_type, feature, expected_value) \ 16092a70997SAndrew Jones ({ \ 16192a70997SAndrew Jones QDict *_resp; \ 16292a70997SAndrew Jones \ 16392a70997SAndrew Jones _resp = do_query_no_props(qts, cpu_type); \ 16492a70997SAndrew Jones g_assert(_resp); \ 16592a70997SAndrew Jones resp_assert_feature(_resp, feature, expected_value); \ 16692a70997SAndrew Jones qobject_unref(_resp); \ 16792a70997SAndrew Jones }) 16892a70997SAndrew Jones 16992a70997SAndrew Jones #define assert_set_feature(qts, cpu_type, feature, value) \ 17092a70997SAndrew Jones ({ \ 17192a70997SAndrew Jones const char *_fmt = (value) ? "{ %s: true }" : "{ %s: false }"; \ 17292a70997SAndrew Jones QDict *_resp; \ 17392a70997SAndrew Jones \ 17492a70997SAndrew Jones _resp = do_query(qts, cpu_type, _fmt, feature); \ 17592a70997SAndrew Jones g_assert(_resp); \ 17692a70997SAndrew Jones resp_assert_feature(_resp, feature, value); \ 177789a35efSAndrew Jones qobject_unref(_resp); \ 178789a35efSAndrew Jones }) 179789a35efSAndrew Jones 180789a35efSAndrew Jones #define assert_has_feature_enabled(qts, cpu_type, feature) \ 181789a35efSAndrew Jones assert_feature(qts, cpu_type, feature, true) 182789a35efSAndrew Jones 183789a35efSAndrew Jones #define assert_has_feature_disabled(qts, cpu_type, feature) \ 184789a35efSAndrew Jones assert_feature(qts, cpu_type, feature, false) 185789a35efSAndrew Jones 186bd31b751SAndrew Jones static void assert_type_full(QTestState *qts) 187bd31b751SAndrew Jones { 188bd31b751SAndrew Jones const char *error; 189bd31b751SAndrew Jones QDict *resp; 190bd31b751SAndrew Jones 191bd31b751SAndrew Jones resp = qtest_qmp(qts, "{ 'execute': 'query-cpu-model-expansion', " 192bd31b751SAndrew Jones "'arguments': { 'type': 'static', " 193bd31b751SAndrew Jones "'model': { 'name': 'foo' }}}"); 194bd31b751SAndrew Jones g_assert(resp); 195bd31b751SAndrew Jones error = resp_get_error(resp); 196bd31b751SAndrew Jones g_assert(error); 197*ef6783d3SMarkus Armbruster g_assert_cmpstr(error, ==, 198*ef6783d3SMarkus Armbruster "The requested expansion type is not supported"); 199bd31b751SAndrew Jones qobject_unref(resp); 200bd31b751SAndrew Jones } 201bd31b751SAndrew Jones 202bd31b751SAndrew Jones static void assert_bad_props(QTestState *qts, const char *cpu_type) 203bd31b751SAndrew Jones { 204bd31b751SAndrew Jones const char *error; 205bd31b751SAndrew Jones QDict *resp; 206bd31b751SAndrew Jones 207bd31b751SAndrew Jones resp = qtest_qmp(qts, "{ 'execute': 'query-cpu-model-expansion', " 208bd31b751SAndrew Jones "'arguments': { 'type': 'full', " 209bd31b751SAndrew Jones "'model': { 'name': %s, " 210bd31b751SAndrew Jones "'props': false }}}", 211bd31b751SAndrew Jones cpu_type); 212bd31b751SAndrew Jones g_assert(resp); 213bd31b751SAndrew Jones error = resp_get_error(resp); 214bd31b751SAndrew Jones g_assert(error); 215*ef6783d3SMarkus Armbruster g_assert_cmpstr(error, ==, 216*ef6783d3SMarkus Armbruster "Invalid parameter type for 'props', expected: object"); 217bd31b751SAndrew Jones qobject_unref(resp); 218bd31b751SAndrew Jones } 219bd31b751SAndrew Jones 2200df9142dSAndrew Jones static uint64_t resp_get_sve_vls(QDict *resp) 2210df9142dSAndrew Jones { 2220df9142dSAndrew Jones QDict *props; 2230df9142dSAndrew Jones const QDictEntry *e; 2240df9142dSAndrew Jones uint64_t vls = 0; 2250df9142dSAndrew Jones int n = 0; 2260df9142dSAndrew Jones 2270df9142dSAndrew Jones g_assert(resp); 2280df9142dSAndrew Jones g_assert(resp_has_props(resp)); 2290df9142dSAndrew Jones 2300df9142dSAndrew Jones props = resp_get_props(resp); 2310df9142dSAndrew Jones 2320df9142dSAndrew Jones for (e = qdict_first(props); e; e = qdict_next(props, e)) { 2330df9142dSAndrew Jones if (strlen(e->key) > 3 && !strncmp(e->key, "sve", 3) && 2340df9142dSAndrew Jones g_ascii_isdigit(e->key[3])) { 2350df9142dSAndrew Jones char *endptr; 2360df9142dSAndrew Jones int bits; 2370df9142dSAndrew Jones 2380df9142dSAndrew Jones bits = g_ascii_strtoll(&e->key[3], &endptr, 10); 2390df9142dSAndrew Jones if (!bits || *endptr != '\0') { 2400df9142dSAndrew Jones continue; 2410df9142dSAndrew Jones } 2420df9142dSAndrew Jones 2430df9142dSAndrew Jones if (qdict_get_bool(props, e->key)) { 2440df9142dSAndrew Jones vls |= BIT_ULL((bits / 128) - 1); 2450df9142dSAndrew Jones } 2460df9142dSAndrew Jones ++n; 2470df9142dSAndrew Jones } 2480df9142dSAndrew Jones } 2490df9142dSAndrew Jones 2500df9142dSAndrew Jones g_assert(n == SVE_MAX_VQ); 2510df9142dSAndrew Jones 2520df9142dSAndrew Jones return vls; 2530df9142dSAndrew Jones } 2540df9142dSAndrew Jones 2550df9142dSAndrew Jones #define assert_sve_vls(qts, cpu_type, expected_vls, fmt, ...) \ 2560df9142dSAndrew Jones ({ \ 2570df9142dSAndrew Jones QDict *_resp = do_query(qts, cpu_type, fmt, ##__VA_ARGS__); \ 2580df9142dSAndrew Jones g_assert(_resp); \ 2590df9142dSAndrew Jones g_assert(resp_has_props(_resp)); \ 2600df9142dSAndrew Jones g_assert(resp_get_sve_vls(_resp) == expected_vls); \ 2610df9142dSAndrew Jones qobject_unref(_resp); \ 2620df9142dSAndrew Jones }) 2630df9142dSAndrew Jones 2640df9142dSAndrew Jones static void sve_tests_default(QTestState *qts, const char *cpu_type) 2650df9142dSAndrew Jones { 2660df9142dSAndrew Jones /* 2670df9142dSAndrew Jones * With no sve-max-vq or sve<N> properties on the command line 2680df9142dSAndrew Jones * the default is to have all vector lengths enabled. This also 2690df9142dSAndrew Jones * tests that 'sve' is 'on' by default. 2700df9142dSAndrew Jones */ 2710df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, BIT_ULL(SVE_MAX_VQ) - 1, NULL); 2720df9142dSAndrew Jones 2730df9142dSAndrew Jones /* With SVE off, all vector lengths should also be off. */ 2740df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0, "{ 'sve': false }"); 2750df9142dSAndrew Jones 2760df9142dSAndrew Jones /* With SVE on, we must have at least one vector length enabled. */ 2770df9142dSAndrew Jones assert_error(qts, cpu_type, "cannot disable sve128", "{ 'sve128': false }"); 2780df9142dSAndrew Jones 2790df9142dSAndrew Jones /* Basic enable/disable tests. */ 2800df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve384': true }"); 2810df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, ((BIT_ULL(SVE_MAX_VQ) - 1) & ~BIT_ULL(2)), 2820df9142dSAndrew Jones "{ 'sve384': false }"); 2830df9142dSAndrew Jones 2840df9142dSAndrew Jones /* 2850df9142dSAndrew Jones * --------------------------------------------------------------------- 2860df9142dSAndrew Jones * power-of-two(vq) all-power- can can 2870df9142dSAndrew Jones * of-two(< vq) enable disable 2880df9142dSAndrew Jones * --------------------------------------------------------------------- 2890df9142dSAndrew Jones * vq < max_vq no MUST* yes yes 2900df9142dSAndrew Jones * vq < max_vq yes MUST* yes no 2910df9142dSAndrew Jones * --------------------------------------------------------------------- 2920df9142dSAndrew Jones * vq == max_vq n/a MUST* yes** yes** 2930df9142dSAndrew Jones * --------------------------------------------------------------------- 2940df9142dSAndrew Jones * vq > max_vq n/a no no yes 2950df9142dSAndrew Jones * vq > max_vq n/a yes yes yes 2960df9142dSAndrew Jones * --------------------------------------------------------------------- 2970df9142dSAndrew Jones * 2980df9142dSAndrew Jones * [*] "MUST" means this requirement must already be satisfied, 2990df9142dSAndrew Jones * otherwise 'max_vq' couldn't itself be enabled. 3000df9142dSAndrew Jones * 3010df9142dSAndrew Jones * [**] Not testable with the QMP interface, only with the command line. 3020df9142dSAndrew Jones */ 3030df9142dSAndrew Jones 3040df9142dSAndrew Jones /* max_vq := 8 */ 3050df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8b, "{ 'sve1024': true }"); 3060df9142dSAndrew Jones 3070df9142dSAndrew Jones /* max_vq := 8, vq < max_vq, !power-of-two(vq) */ 3080df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8f, 3090df9142dSAndrew Jones "{ 'sve1024': true, 'sve384': true }"); 3100df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8b, 3110df9142dSAndrew Jones "{ 'sve1024': true, 'sve384': false }"); 3120df9142dSAndrew Jones 3130df9142dSAndrew Jones /* max_vq := 8, vq < max_vq, power-of-two(vq) */ 3140df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8b, 3150df9142dSAndrew Jones "{ 'sve1024': true, 'sve256': true }"); 3160df9142dSAndrew Jones assert_error(qts, cpu_type, "cannot disable sve256", 3170df9142dSAndrew Jones "{ 'sve1024': true, 'sve256': false }"); 3180df9142dSAndrew Jones 3190df9142dSAndrew Jones /* max_vq := 3, vq > max_vq, !all-power-of-two(< vq) */ 3200df9142dSAndrew Jones assert_error(qts, cpu_type, "cannot disable sve512", 3210df9142dSAndrew Jones "{ 'sve384': true, 'sve512': false, 'sve640': true }"); 3220df9142dSAndrew Jones 3230df9142dSAndrew Jones /* 3240df9142dSAndrew Jones * We can disable power-of-two vector lengths when all larger lengths 3250df9142dSAndrew Jones * are also disabled. We only need to disable the power-of-two length, 3260df9142dSAndrew Jones * as all non-enabled larger lengths will then be auto-disabled. 3270df9142dSAndrew Jones */ 3280df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve512': false }"); 3290df9142dSAndrew Jones 3300df9142dSAndrew Jones /* max_vq := 3, vq > max_vq, all-power-of-two(< vq) */ 3310df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x1f, 3320df9142dSAndrew Jones "{ 'sve384': true, 'sve512': true, 'sve640': true }"); 3330df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0xf, 3340df9142dSAndrew Jones "{ 'sve384': true, 'sve512': true, 'sve640': false }"); 3350df9142dSAndrew Jones } 3360df9142dSAndrew Jones 3370df9142dSAndrew Jones static void sve_tests_sve_max_vq_8(const void *data) 3380df9142dSAndrew Jones { 3390df9142dSAndrew Jones QTestState *qts; 3400df9142dSAndrew Jones 3410df9142dSAndrew Jones qts = qtest_init(MACHINE "-cpu max,sve-max-vq=8"); 3420df9142dSAndrew Jones 3430df9142dSAndrew Jones assert_sve_vls(qts, "max", BIT_ULL(8) - 1, NULL); 3440df9142dSAndrew Jones 3450df9142dSAndrew Jones /* 3460df9142dSAndrew Jones * Disabling the max-vq set by sve-max-vq is not allowed, but 3470df9142dSAndrew Jones * of course enabling it is OK. 3480df9142dSAndrew Jones */ 3490df9142dSAndrew Jones assert_error(qts, "max", "cannot disable sve1024", "{ 'sve1024': false }"); 3500df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve1024': true }"); 3510df9142dSAndrew Jones 3520df9142dSAndrew Jones /* 3530df9142dSAndrew Jones * Enabling anything larger than max-vq set by sve-max-vq is not 3540df9142dSAndrew Jones * allowed, but of course disabling everything larger is OK. 3550df9142dSAndrew Jones */ 3560df9142dSAndrew Jones assert_error(qts, "max", "cannot enable sve1152", "{ 'sve1152': true }"); 3570df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve1152': false }"); 3580df9142dSAndrew Jones 3590df9142dSAndrew Jones /* 3600df9142dSAndrew Jones * We can enable/disable non power-of-two lengths smaller than the 3610df9142dSAndrew Jones * max-vq set by sve-max-vq, but, while we can enable power-of-two 3620df9142dSAndrew Jones * lengths, we can't disable them. 3630df9142dSAndrew Jones */ 3640df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve384': true }"); 3650df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xfb, "{ 'sve384': false }"); 3660df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve256': true }"); 3670df9142dSAndrew Jones assert_error(qts, "max", "cannot disable sve256", "{ 'sve256': false }"); 3680df9142dSAndrew Jones 3690df9142dSAndrew Jones qtest_quit(qts); 3700df9142dSAndrew Jones } 3710df9142dSAndrew Jones 3720df9142dSAndrew Jones static void sve_tests_sve_off(const void *data) 3730df9142dSAndrew Jones { 3740df9142dSAndrew Jones QTestState *qts; 3750df9142dSAndrew Jones 3760df9142dSAndrew Jones qts = qtest_init(MACHINE "-cpu max,sve=off"); 3770df9142dSAndrew Jones 3780df9142dSAndrew Jones /* SVE is off, so the map should be empty. */ 3790df9142dSAndrew Jones assert_sve_vls(qts, "max", 0, NULL); 3800df9142dSAndrew Jones 3810df9142dSAndrew Jones /* The map stays empty even if we turn lengths off. */ 3820df9142dSAndrew Jones assert_sve_vls(qts, "max", 0, "{ 'sve128': false }"); 3830df9142dSAndrew Jones 3840df9142dSAndrew Jones /* It's an error to enable lengths when SVE is off. */ 3850df9142dSAndrew Jones assert_error(qts, "max", "cannot enable sve128", "{ 'sve128': true }"); 3860df9142dSAndrew Jones 3870df9142dSAndrew Jones /* With SVE re-enabled we should get all vector lengths enabled. */ 3880df9142dSAndrew Jones assert_sve_vls(qts, "max", BIT_ULL(SVE_MAX_VQ) - 1, "{ 'sve': true }"); 3890df9142dSAndrew Jones 3900df9142dSAndrew Jones /* Or enable SVE with just specific vector lengths. */ 3910df9142dSAndrew Jones assert_sve_vls(qts, "max", 0x3, 3920df9142dSAndrew Jones "{ 'sve': true, 'sve128': true, 'sve256': true }"); 3930df9142dSAndrew Jones 3940df9142dSAndrew Jones qtest_quit(qts); 3950df9142dSAndrew Jones } 3960df9142dSAndrew Jones 3976fa8a379SAndrew Jones static void sve_tests_sve_off_kvm(const void *data) 3986fa8a379SAndrew Jones { 3996fa8a379SAndrew Jones QTestState *qts; 4006fa8a379SAndrew Jones 4016fa8a379SAndrew Jones qts = qtest_init(MACHINE_KVM "-cpu max,sve=off"); 4026fa8a379SAndrew Jones 4036fa8a379SAndrew Jones /* 4046fa8a379SAndrew Jones * We don't know if this host supports SVE so we don't 4056fa8a379SAndrew Jones * attempt to test enabling anything. We only test that 4066fa8a379SAndrew Jones * everything is disabled (as it should be with sve=off) 4076fa8a379SAndrew Jones * and that using sve<N>=off to explicitly disable vector 4086fa8a379SAndrew Jones * lengths is OK too. 4096fa8a379SAndrew Jones */ 4106fa8a379SAndrew Jones assert_sve_vls(qts, "max", 0, NULL); 4116fa8a379SAndrew Jones assert_sve_vls(qts, "max", 0, "{ 'sve128': false }"); 4126fa8a379SAndrew Jones 4136fa8a379SAndrew Jones qtest_quit(qts); 4146fa8a379SAndrew Jones } 4156fa8a379SAndrew Jones 416eb94284dSRichard Henderson static void pauth_tests_default(QTestState *qts, const char *cpu_type) 417eb94284dSRichard Henderson { 418eb94284dSRichard Henderson assert_has_feature_enabled(qts, cpu_type, "pauth"); 419eb94284dSRichard Henderson assert_has_feature_disabled(qts, cpu_type, "pauth-impdef"); 420399e5e71SRichard Henderson assert_has_feature_disabled(qts, cpu_type, "pauth-qarma3"); 421eb94284dSRichard Henderson assert_set_feature(qts, cpu_type, "pauth", false); 422eb94284dSRichard Henderson assert_set_feature(qts, cpu_type, "pauth", true); 423eb94284dSRichard Henderson assert_set_feature(qts, cpu_type, "pauth-impdef", true); 424eb94284dSRichard Henderson assert_set_feature(qts, cpu_type, "pauth-impdef", false); 425399e5e71SRichard Henderson assert_set_feature(qts, cpu_type, "pauth-qarma3", true); 426399e5e71SRichard Henderson assert_set_feature(qts, cpu_type, "pauth-qarma3", false); 427399e5e71SRichard Henderson assert_error(qts, cpu_type, 428399e5e71SRichard Henderson "cannot enable pauth-impdef or pauth-qarma3 without pauth", 429eb94284dSRichard Henderson "{ 'pauth': false, 'pauth-impdef': true }"); 430399e5e71SRichard Henderson assert_error(qts, cpu_type, 431399e5e71SRichard Henderson "cannot enable pauth-impdef or pauth-qarma3 without pauth", 432399e5e71SRichard Henderson "{ 'pauth': false, 'pauth-qarma3': true }"); 433399e5e71SRichard Henderson assert_error(qts, cpu_type, 434399e5e71SRichard Henderson "cannot enable both pauth-impdef and pauth-qarma3", 435399e5e71SRichard Henderson "{ 'pauth': true, 'pauth-impdef': true, 'pauth-qarma3': true }"); 436eb94284dSRichard Henderson } 437eb94284dSRichard Henderson 438bd31b751SAndrew Jones static void test_query_cpu_model_expansion(const void *data) 439bd31b751SAndrew Jones { 440bd31b751SAndrew Jones QTestState *qts; 441bd31b751SAndrew Jones 442bd31b751SAndrew Jones qts = qtest_init(MACHINE "-cpu max"); 443bd31b751SAndrew Jones 444bd31b751SAndrew Jones /* Test common query-cpu-model-expansion input validation */ 445bd31b751SAndrew Jones assert_type_full(qts); 446bd31b751SAndrew Jones assert_bad_props(qts, "max"); 447bd31b751SAndrew Jones assert_error(qts, "foo", "The CPU type 'foo' is not a recognized " 448bd31b751SAndrew Jones "ARM CPU type", NULL); 449*ef6783d3SMarkus Armbruster assert_error(qts, "max", "Parameter 'props.not-a-prop' is unexpected", 450bd31b751SAndrew Jones "{ 'not-a-prop': false }"); 451bd31b751SAndrew Jones assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL); 452bd31b751SAndrew Jones 453bd31b751SAndrew Jones /* Test expected feature presence/absence for some cpu types */ 454789a35efSAndrew Jones assert_has_feature_enabled(qts, "cortex-a15", "pmu"); 455bd31b751SAndrew Jones assert_has_not_feature(qts, "cortex-a15", "aarch64"); 456bd31b751SAndrew Jones 45792a70997SAndrew Jones /* Enabling and disabling pmu should always work. */ 45892a70997SAndrew Jones assert_has_feature_enabled(qts, "max", "pmu"); 45992a70997SAndrew Jones assert_set_feature(qts, "max", "pmu", false); 46092a70997SAndrew Jones assert_set_feature(qts, "max", "pmu", true); 46192a70997SAndrew Jones 462dea101a1SAndrew Jones assert_has_not_feature(qts, "max", "kvm-no-adjvtime"); 46368970d1eSAndrew Jones assert_has_not_feature(qts, "max", "kvm-steal-time"); 464dea101a1SAndrew Jones 465bd31b751SAndrew Jones if (g_str_equal(qtest_get_arch(), "aarch64")) { 466789a35efSAndrew Jones assert_has_feature_enabled(qts, "max", "aarch64"); 467789a35efSAndrew Jones assert_has_feature_enabled(qts, "max", "sve"); 468789a35efSAndrew Jones assert_has_feature_enabled(qts, "max", "sve128"); 469789a35efSAndrew Jones assert_has_feature_enabled(qts, "cortex-a57", "pmu"); 470789a35efSAndrew Jones assert_has_feature_enabled(qts, "cortex-a57", "aarch64"); 471bd31b751SAndrew Jones 472499243e1SShuuichirou Ishii assert_has_feature_enabled(qts, "a64fx", "pmu"); 473499243e1SShuuichirou Ishii assert_has_feature_enabled(qts, "a64fx", "aarch64"); 474499243e1SShuuichirou Ishii /* 475499243e1SShuuichirou Ishii * A64FX does not support any other vector lengths besides those 476499243e1SShuuichirou Ishii * that are enabled by default(128bit, 256bits, 512bit). 477499243e1SShuuichirou Ishii */ 478499243e1SShuuichirou Ishii assert_has_feature_enabled(qts, "a64fx", "sve"); 479499243e1SShuuichirou Ishii assert_sve_vls(qts, "a64fx", 0xb, NULL); 480499243e1SShuuichirou Ishii assert_error(qts, "a64fx", "cannot enable sve384", 481499243e1SShuuichirou Ishii "{ 'sve384': true }"); 482499243e1SShuuichirou Ishii assert_error(qts, "a64fx", "cannot enable sve640", 483499243e1SShuuichirou Ishii "{ 'sve640': true }"); 484499243e1SShuuichirou Ishii 4850df9142dSAndrew Jones sve_tests_default(qts, "max"); 486eb94284dSRichard Henderson pauth_tests_default(qts, "max"); 4870df9142dSAndrew Jones 488bd31b751SAndrew Jones /* Test that features that depend on KVM generate errors without. */ 489bd31b751SAndrew Jones assert_error(qts, "max", 490bd31b751SAndrew Jones "'aarch64' feature cannot be disabled " 491bd31b751SAndrew Jones "unless KVM is enabled and 32-bit EL1 " 492bd31b751SAndrew Jones "is supported", 493bd31b751SAndrew Jones "{ 'aarch64': false }"); 494bd31b751SAndrew Jones } 495bd31b751SAndrew Jones 496bd31b751SAndrew Jones qtest_quit(qts); 497bd31b751SAndrew Jones } 498bd31b751SAndrew Jones 499bd31b751SAndrew Jones static void test_query_cpu_model_expansion_kvm(const void *data) 500bd31b751SAndrew Jones { 501bd31b751SAndrew Jones QTestState *qts; 502bd31b751SAndrew Jones 503bd31b751SAndrew Jones qts = qtest_init(MACHINE_KVM "-cpu max"); 504bd31b751SAndrew Jones 50592a70997SAndrew Jones /* Enabling and disabling kvm-no-adjvtime should always work. */ 506dea101a1SAndrew Jones assert_has_feature_disabled(qts, "host", "kvm-no-adjvtime"); 50792a70997SAndrew Jones assert_set_feature(qts, "host", "kvm-no-adjvtime", true); 50892a70997SAndrew Jones assert_set_feature(qts, "host", "kvm-no-adjvtime", false); 509dea101a1SAndrew Jones 510bd31b751SAndrew Jones if (g_str_equal(qtest_get_arch(), "aarch64")) { 51168970d1eSAndrew Jones bool kvm_supports_steal_time; 5126fa8a379SAndrew Jones bool kvm_supports_sve; 5136fa8a379SAndrew Jones char max_name[8], name[8]; 5146fa8a379SAndrew Jones uint32_t max_vq, vq; 5156fa8a379SAndrew Jones uint64_t vls; 5166fa8a379SAndrew Jones QDict *resp; 5176fa8a379SAndrew Jones char *error; 5186fa8a379SAndrew Jones 519557ed03aSFabiano Rosas /* 520557ed03aSFabiano Rosas * When using KVM, only the 'host' and 'max' CPU models are 521557ed03aSFabiano Rosas * supported. Test that we're emitting a suitable error for 522557ed03aSFabiano Rosas * unsupported CPU models. 523557ed03aSFabiano Rosas */ 524557ed03aSFabiano Rosas if (qtest_has_accel("tcg")) { 525557ed03aSFabiano Rosas assert_error(qts, "cortex-a7", 526557ed03aSFabiano Rosas "We cannot guarantee the CPU type 'cortex-a7' works " 52768970d1eSAndrew Jones "with KVM on this host", NULL); 528557ed03aSFabiano Rosas } else { 529557ed03aSFabiano Rosas /* 530557ed03aSFabiano Rosas * With a KVM-only build the 32-bit CPUs are not present. 531557ed03aSFabiano Rosas */ 532557ed03aSFabiano Rosas assert_error(qts, "cortex-a7", 533557ed03aSFabiano Rosas "The CPU type 'cortex-a7' is not a " 534557ed03aSFabiano Rosas "recognized ARM CPU type", NULL); 535557ed03aSFabiano Rosas } 53668970d1eSAndrew Jones 537789a35efSAndrew Jones assert_has_feature_enabled(qts, "host", "aarch64"); 53892a70997SAndrew Jones 53992a70997SAndrew Jones /* Enabling and disabling pmu should always work. */ 540789a35efSAndrew Jones assert_has_feature_enabled(qts, "host", "pmu"); 54192a70997SAndrew Jones assert_set_feature(qts, "host", "pmu", false); 54292a70997SAndrew Jones assert_set_feature(qts, "host", "pmu", true); 543bd31b751SAndrew Jones 54468970d1eSAndrew Jones /* 54568970d1eSAndrew Jones * Some features would be enabled by default, but they're disabled 54668970d1eSAndrew Jones * because this instance of KVM doesn't support them. Test that the 54768970d1eSAndrew Jones * features are present, and, when enabled, issue further tests. 54868970d1eSAndrew Jones */ 54968970d1eSAndrew Jones assert_has_feature(qts, "host", "kvm-steal-time"); 55087014c6bSAndrew Jones assert_has_feature(qts, "host", "sve"); 55168970d1eSAndrew Jones 55287014c6bSAndrew Jones resp = do_query_no_props(qts, "host"); 55368970d1eSAndrew Jones kvm_supports_steal_time = resp_get_feature(resp, "kvm-steal-time"); 5546fa8a379SAndrew Jones kvm_supports_sve = resp_get_feature(resp, "sve"); 5556fa8a379SAndrew Jones vls = resp_get_sve_vls(resp); 5566fa8a379SAndrew Jones qobject_unref(resp); 5576fa8a379SAndrew Jones 55868970d1eSAndrew Jones if (kvm_supports_steal_time) { 55968970d1eSAndrew Jones /* If we have steal-time then we should be able to toggle it. */ 56068970d1eSAndrew Jones assert_set_feature(qts, "host", "kvm-steal-time", false); 56168970d1eSAndrew Jones assert_set_feature(qts, "host", "kvm-steal-time", true); 56268970d1eSAndrew Jones } 56368970d1eSAndrew Jones 5646fa8a379SAndrew Jones if (kvm_supports_sve) { 5656fa8a379SAndrew Jones g_assert(vls != 0); 5666fa8a379SAndrew Jones max_vq = 64 - __builtin_clzll(vls); 5673dc05792SAlexChen sprintf(max_name, "sve%u", max_vq * 128); 5686fa8a379SAndrew Jones 5696fa8a379SAndrew Jones /* Enabling a supported length is of course fine. */ 57087014c6bSAndrew Jones assert_sve_vls(qts, "host", vls, "{ %s: true }", max_name); 5716fa8a379SAndrew Jones 5726fa8a379SAndrew Jones /* Get the next supported length smaller than max-vq. */ 5736fa8a379SAndrew Jones vq = 64 - __builtin_clzll(vls & ~BIT_ULL(max_vq - 1)); 5746fa8a379SAndrew Jones if (vq) { 5756fa8a379SAndrew Jones /* 5766fa8a379SAndrew Jones * We have at least one length smaller than max-vq, 5776fa8a379SAndrew Jones * so we can disable max-vq. 5786fa8a379SAndrew Jones */ 57987014c6bSAndrew Jones assert_sve_vls(qts, "host", (vls & ~BIT_ULL(max_vq - 1)), 5806fa8a379SAndrew Jones "{ %s: false }", max_name); 5816fa8a379SAndrew Jones 5826fa8a379SAndrew Jones /* 5836fa8a379SAndrew Jones * Smaller, supported vector lengths cannot be disabled 5846fa8a379SAndrew Jones * unless all larger, supported vector lengths are also 5856fa8a379SAndrew Jones * disabled. 5866fa8a379SAndrew Jones */ 5873dc05792SAlexChen sprintf(name, "sve%u", vq * 128); 5886fa8a379SAndrew Jones error = g_strdup_printf("cannot disable %s", name); 58987014c6bSAndrew Jones assert_error(qts, "host", error, 5906fa8a379SAndrew Jones "{ %s: true, %s: false }", 5916fa8a379SAndrew Jones max_name, name); 5926fa8a379SAndrew Jones g_free(error); 5936fa8a379SAndrew Jones } 5946fa8a379SAndrew Jones 5956fa8a379SAndrew Jones /* 5966fa8a379SAndrew Jones * The smallest, supported vector length is required, because 5976fa8a379SAndrew Jones * we need at least one vector length enabled. 5986fa8a379SAndrew Jones */ 5996fa8a379SAndrew Jones vq = __builtin_ffsll(vls); 6003dc05792SAlexChen sprintf(name, "sve%u", vq * 128); 6016fa8a379SAndrew Jones error = g_strdup_printf("cannot disable %s", name); 60287014c6bSAndrew Jones assert_error(qts, "host", error, "{ %s: false }", name); 6036fa8a379SAndrew Jones g_free(error); 6046fa8a379SAndrew Jones 6056fa8a379SAndrew Jones /* Get an unsupported length. */ 6066fa8a379SAndrew Jones for (vq = 1; vq <= max_vq; ++vq) { 6076fa8a379SAndrew Jones if (!(vls & BIT_ULL(vq - 1))) { 6086fa8a379SAndrew Jones break; 6096fa8a379SAndrew Jones } 6106fa8a379SAndrew Jones } 6116fa8a379SAndrew Jones if (vq <= SVE_MAX_VQ) { 6123dc05792SAlexChen sprintf(name, "sve%u", vq * 128); 6136fa8a379SAndrew Jones error = g_strdup_printf("cannot enable %s", name); 61487014c6bSAndrew Jones assert_error(qts, "host", error, "{ %s: true }", name); 6156fa8a379SAndrew Jones g_free(error); 6166fa8a379SAndrew Jones } 6176fa8a379SAndrew Jones } else { 6186fa8a379SAndrew Jones g_assert(vls == 0); 6196fa8a379SAndrew Jones } 620bd31b751SAndrew Jones } else { 621bd31b751SAndrew Jones assert_has_not_feature(qts, "host", "aarch64"); 622bd31b751SAndrew Jones assert_has_not_feature(qts, "host", "pmu"); 62387014c6bSAndrew Jones assert_has_not_feature(qts, "host", "sve"); 62468970d1eSAndrew Jones assert_has_not_feature(qts, "host", "kvm-steal-time"); 625bd31b751SAndrew Jones } 626bd31b751SAndrew Jones 627bd31b751SAndrew Jones qtest_quit(qts); 628bd31b751SAndrew Jones } 629bd31b751SAndrew Jones 630bd31b751SAndrew Jones int main(int argc, char **argv) 631bd31b751SAndrew Jones { 632bd31b751SAndrew Jones g_test_init(&argc, &argv, NULL); 633bd31b751SAndrew Jones 634500a0accSFabiano Rosas if (qtest_has_accel("tcg")) { 635bd31b751SAndrew Jones qtest_add_data_func("/arm/query-cpu-model-expansion", 636bd31b751SAndrew Jones NULL, test_query_cpu_model_expansion); 637500a0accSFabiano Rosas } 638500a0accSFabiano Rosas 639500a0accSFabiano Rosas if (!g_str_equal(qtest_get_arch(), "aarch64")) { 640500a0accSFabiano Rosas goto out; 641500a0accSFabiano Rosas } 642bd31b751SAndrew Jones 643bd31b751SAndrew Jones /* 644bd31b751SAndrew Jones * For now we only run KVM specific tests with AArch64 QEMU in 645bd31b751SAndrew Jones * order avoid attempting to run an AArch32 QEMU with KVM on 646bd31b751SAndrew Jones * AArch64 hosts. That won't work and isn't easy to detect. 647bd31b751SAndrew Jones */ 648500a0accSFabiano Rosas if (qtest_has_accel("kvm")) { 64907e6ed2cSIgor Mammedov /* 65007e6ed2cSIgor Mammedov * This tests target the 'host' CPU type, so register it only if 65107e6ed2cSIgor Mammedov * KVM is available. 65207e6ed2cSIgor Mammedov */ 653bd31b751SAndrew Jones qtest_add_data_func("/arm/kvm/query-cpu-model-expansion", 654bd31b751SAndrew Jones NULL, test_query_cpu_model_expansion_kvm); 655bd31b751SAndrew Jones 6566fa8a379SAndrew Jones qtest_add_data_func("/arm/kvm/query-cpu-model-expansion/sve-off", 6576fa8a379SAndrew Jones NULL, sve_tests_sve_off_kvm); 6580df9142dSAndrew Jones } 6590df9142dSAndrew Jones 660500a0accSFabiano Rosas if (qtest_has_accel("tcg")) { 661500a0accSFabiano Rosas qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-max-vq-8", 662500a0accSFabiano Rosas NULL, sve_tests_sve_max_vq_8); 663500a0accSFabiano Rosas qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-off", 664500a0accSFabiano Rosas NULL, sve_tests_sve_off); 665500a0accSFabiano Rosas } 666500a0accSFabiano Rosas 667500a0accSFabiano Rosas out: 668bd31b751SAndrew Jones return g_test_run(); 669bd31b751SAndrew Jones } 670