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"
14*407bc4bfSDaniel P. Berrangé #include "qobject/qdict.h"
15*407bc4bfSDaniel P. Berrangé #include "qobject/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
do_query_no_props(QTestState * qts,const char * cpu_type)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)
do_query(QTestState * qts,const char * cpu_type,const char * fmt,...)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
resp_get_error(QDict * resp)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); \
82ef6783d3SMarkus Armbruster g_assert_cmpstr(_error, ==, expected_error); \
83bd31b751SAndrew Jones qobject_unref(_resp); \
84bd31b751SAndrew Jones })
85bd31b751SAndrew Jones
resp_has_props(QDict * resp)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
resp_get_props(QDict * resp)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
resp_get_feature(QDict * resp,const char * feature)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
assert_type_full(QTestState * qts)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);
197ef6783d3SMarkus Armbruster g_assert_cmpstr(error, ==,
198ef6783d3SMarkus Armbruster "The requested expansion type is not supported");
199bd31b751SAndrew Jones qobject_unref(resp);
200bd31b751SAndrew Jones }
201bd31b751SAndrew Jones
assert_bad_props(QTestState * qts,const char * cpu_type)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);
215ef6783d3SMarkus Armbruster g_assert_cmpstr(error, ==,
2168934643aSMarkus Armbruster "Invalid parameter type for 'model.props',"
2178934643aSMarkus Armbruster " expected: object");
218bd31b751SAndrew Jones qobject_unref(resp);
219bd31b751SAndrew Jones }
220bd31b751SAndrew Jones
resp_get_sve_vls(QDict * resp)2210df9142dSAndrew Jones static uint64_t resp_get_sve_vls(QDict *resp)
2220df9142dSAndrew Jones {
2230df9142dSAndrew Jones QDict *props;
2240df9142dSAndrew Jones const QDictEntry *e;
2250df9142dSAndrew Jones uint64_t vls = 0;
2260df9142dSAndrew Jones int n = 0;
2270df9142dSAndrew Jones
2280df9142dSAndrew Jones g_assert(resp);
2290df9142dSAndrew Jones g_assert(resp_has_props(resp));
2300df9142dSAndrew Jones
2310df9142dSAndrew Jones props = resp_get_props(resp);
2320df9142dSAndrew Jones
2330df9142dSAndrew Jones for (e = qdict_first(props); e; e = qdict_next(props, e)) {
2340df9142dSAndrew Jones if (strlen(e->key) > 3 && !strncmp(e->key, "sve", 3) &&
2350df9142dSAndrew Jones g_ascii_isdigit(e->key[3])) {
2360df9142dSAndrew Jones char *endptr;
2370df9142dSAndrew Jones int bits;
2380df9142dSAndrew Jones
2390df9142dSAndrew Jones bits = g_ascii_strtoll(&e->key[3], &endptr, 10);
2400df9142dSAndrew Jones if (!bits || *endptr != '\0') {
2410df9142dSAndrew Jones continue;
2420df9142dSAndrew Jones }
2430df9142dSAndrew Jones
2440df9142dSAndrew Jones if (qdict_get_bool(props, e->key)) {
2450df9142dSAndrew Jones vls |= BIT_ULL((bits / 128) - 1);
2460df9142dSAndrew Jones }
2470df9142dSAndrew Jones ++n;
2480df9142dSAndrew Jones }
2490df9142dSAndrew Jones }
2500df9142dSAndrew Jones
2510df9142dSAndrew Jones g_assert(n == SVE_MAX_VQ);
2520df9142dSAndrew Jones
2530df9142dSAndrew Jones return vls;
2540df9142dSAndrew Jones }
2550df9142dSAndrew Jones
2560df9142dSAndrew Jones #define assert_sve_vls(qts, cpu_type, expected_vls, fmt, ...) \
2570df9142dSAndrew Jones ({ \
2580df9142dSAndrew Jones QDict *_resp = do_query(qts, cpu_type, fmt, ##__VA_ARGS__); \
2590df9142dSAndrew Jones g_assert(_resp); \
2600df9142dSAndrew Jones g_assert(resp_has_props(_resp)); \
2610df9142dSAndrew Jones g_assert(resp_get_sve_vls(_resp) == expected_vls); \
2620df9142dSAndrew Jones qobject_unref(_resp); \
2630df9142dSAndrew Jones })
2640df9142dSAndrew Jones
sve_tests_default(QTestState * qts,const char * cpu_type)2650df9142dSAndrew Jones static void sve_tests_default(QTestState *qts, const char *cpu_type)
2660df9142dSAndrew Jones {
2670df9142dSAndrew Jones /*
2680df9142dSAndrew Jones * With no sve-max-vq or sve<N> properties on the command line
2690df9142dSAndrew Jones * the default is to have all vector lengths enabled. This also
2700df9142dSAndrew Jones * tests that 'sve' is 'on' by default.
2710df9142dSAndrew Jones */
2720df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, BIT_ULL(SVE_MAX_VQ) - 1, NULL);
2730df9142dSAndrew Jones
2740df9142dSAndrew Jones /* With SVE off, all vector lengths should also be off. */
2750df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0, "{ 'sve': false }");
2760df9142dSAndrew Jones
2770df9142dSAndrew Jones /* With SVE on, we must have at least one vector length enabled. */
2780df9142dSAndrew Jones assert_error(qts, cpu_type, "cannot disable sve128", "{ 'sve128': false }");
2790df9142dSAndrew Jones
2800df9142dSAndrew Jones /* Basic enable/disable tests. */
2810df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve384': true }");
2820df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, ((BIT_ULL(SVE_MAX_VQ) - 1) & ~BIT_ULL(2)),
2830df9142dSAndrew Jones "{ 'sve384': false }");
2840df9142dSAndrew Jones
2850df9142dSAndrew Jones /*
2860df9142dSAndrew Jones * ---------------------------------------------------------------------
2870df9142dSAndrew Jones * power-of-two(vq) all-power- can can
2880df9142dSAndrew Jones * of-two(< vq) enable disable
2890df9142dSAndrew Jones * ---------------------------------------------------------------------
2900df9142dSAndrew Jones * vq < max_vq no MUST* yes yes
2910df9142dSAndrew Jones * vq < max_vq yes MUST* yes no
2920df9142dSAndrew Jones * ---------------------------------------------------------------------
2930df9142dSAndrew Jones * vq == max_vq n/a MUST* yes** yes**
2940df9142dSAndrew Jones * ---------------------------------------------------------------------
2950df9142dSAndrew Jones * vq > max_vq n/a no no yes
2960df9142dSAndrew Jones * vq > max_vq n/a yes yes yes
2970df9142dSAndrew Jones * ---------------------------------------------------------------------
2980df9142dSAndrew Jones *
2990df9142dSAndrew Jones * [*] "MUST" means this requirement must already be satisfied,
3000df9142dSAndrew Jones * otherwise 'max_vq' couldn't itself be enabled.
3010df9142dSAndrew Jones *
3020df9142dSAndrew Jones * [**] Not testable with the QMP interface, only with the command line.
3030df9142dSAndrew Jones */
3040df9142dSAndrew Jones
3050df9142dSAndrew Jones /* max_vq := 8 */
3060df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8b, "{ 'sve1024': true }");
3070df9142dSAndrew Jones
3080df9142dSAndrew Jones /* max_vq := 8, vq < max_vq, !power-of-two(vq) */
3090df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8f,
3100df9142dSAndrew Jones "{ 'sve1024': true, 'sve384': true }");
3110df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8b,
3120df9142dSAndrew Jones "{ 'sve1024': true, 'sve384': false }");
3130df9142dSAndrew Jones
3140df9142dSAndrew Jones /* max_vq := 8, vq < max_vq, power-of-two(vq) */
3150df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x8b,
3160df9142dSAndrew Jones "{ 'sve1024': true, 'sve256': true }");
3170df9142dSAndrew Jones assert_error(qts, cpu_type, "cannot disable sve256",
3180df9142dSAndrew Jones "{ 'sve1024': true, 'sve256': false }");
3190df9142dSAndrew Jones
3200df9142dSAndrew Jones /* max_vq := 3, vq > max_vq, !all-power-of-two(< vq) */
3210df9142dSAndrew Jones assert_error(qts, cpu_type, "cannot disable sve512",
3220df9142dSAndrew Jones "{ 'sve384': true, 'sve512': false, 'sve640': true }");
3230df9142dSAndrew Jones
3240df9142dSAndrew Jones /*
3250df9142dSAndrew Jones * We can disable power-of-two vector lengths when all larger lengths
3260df9142dSAndrew Jones * are also disabled. We only need to disable the power-of-two length,
3270df9142dSAndrew Jones * as all non-enabled larger lengths will then be auto-disabled.
3280df9142dSAndrew Jones */
3290df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve512': false }");
3300df9142dSAndrew Jones
3310df9142dSAndrew Jones /* max_vq := 3, vq > max_vq, all-power-of-two(< vq) */
3320df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0x1f,
3330df9142dSAndrew Jones "{ 'sve384': true, 'sve512': true, 'sve640': true }");
3340df9142dSAndrew Jones assert_sve_vls(qts, cpu_type, 0xf,
3350df9142dSAndrew Jones "{ 'sve384': true, 'sve512': true, 'sve640': false }");
3360df9142dSAndrew Jones }
3370df9142dSAndrew Jones
sve_tests_sve_max_vq_8(const void * data)3380df9142dSAndrew Jones static void sve_tests_sve_max_vq_8(const void *data)
3390df9142dSAndrew Jones {
3400df9142dSAndrew Jones QTestState *qts;
3410df9142dSAndrew Jones
3420df9142dSAndrew Jones qts = qtest_init(MACHINE "-cpu max,sve-max-vq=8");
3430df9142dSAndrew Jones
3440df9142dSAndrew Jones assert_sve_vls(qts, "max", BIT_ULL(8) - 1, NULL);
3450df9142dSAndrew Jones
3460df9142dSAndrew Jones /*
3470df9142dSAndrew Jones * Disabling the max-vq set by sve-max-vq is not allowed, but
3480df9142dSAndrew Jones * of course enabling it is OK.
3490df9142dSAndrew Jones */
3500df9142dSAndrew Jones assert_error(qts, "max", "cannot disable sve1024", "{ 'sve1024': false }");
3510df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve1024': true }");
3520df9142dSAndrew Jones
3530df9142dSAndrew Jones /*
3540df9142dSAndrew Jones * Enabling anything larger than max-vq set by sve-max-vq is not
3550df9142dSAndrew Jones * allowed, but of course disabling everything larger is OK.
3560df9142dSAndrew Jones */
3570df9142dSAndrew Jones assert_error(qts, "max", "cannot enable sve1152", "{ 'sve1152': true }");
3580df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve1152': false }");
3590df9142dSAndrew Jones
3600df9142dSAndrew Jones /*
3610df9142dSAndrew Jones * We can enable/disable non power-of-two lengths smaller than the
3620df9142dSAndrew Jones * max-vq set by sve-max-vq, but, while we can enable power-of-two
3630df9142dSAndrew Jones * lengths, we can't disable them.
3640df9142dSAndrew Jones */
3650df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve384': true }");
3660df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xfb, "{ 'sve384': false }");
3670df9142dSAndrew Jones assert_sve_vls(qts, "max", 0xff, "{ 'sve256': true }");
3680df9142dSAndrew Jones assert_error(qts, "max", "cannot disable sve256", "{ 'sve256': false }");
3690df9142dSAndrew Jones
3700df9142dSAndrew Jones qtest_quit(qts);
3710df9142dSAndrew Jones }
3720df9142dSAndrew Jones
sve_tests_sve_off(const void * data)3730df9142dSAndrew Jones static void sve_tests_sve_off(const void *data)
3740df9142dSAndrew Jones {
3750df9142dSAndrew Jones QTestState *qts;
3760df9142dSAndrew Jones
3770df9142dSAndrew Jones qts = qtest_init(MACHINE "-cpu max,sve=off");
3780df9142dSAndrew Jones
3790df9142dSAndrew Jones /* SVE is off, so the map should be empty. */
3800df9142dSAndrew Jones assert_sve_vls(qts, "max", 0, NULL);
3810df9142dSAndrew Jones
3820df9142dSAndrew Jones /* The map stays empty even if we turn lengths off. */
3830df9142dSAndrew Jones assert_sve_vls(qts, "max", 0, "{ 'sve128': false }");
3840df9142dSAndrew Jones
3850df9142dSAndrew Jones /* It's an error to enable lengths when SVE is off. */
3860df9142dSAndrew Jones assert_error(qts, "max", "cannot enable sve128", "{ 'sve128': true }");
3870df9142dSAndrew Jones
3880df9142dSAndrew Jones /* With SVE re-enabled we should get all vector lengths enabled. */
3890df9142dSAndrew Jones assert_sve_vls(qts, "max", BIT_ULL(SVE_MAX_VQ) - 1, "{ 'sve': true }");
3900df9142dSAndrew Jones
3910df9142dSAndrew Jones /* Or enable SVE with just specific vector lengths. */
3920df9142dSAndrew Jones assert_sve_vls(qts, "max", 0x3,
3930df9142dSAndrew Jones "{ 'sve': true, 'sve128': true, 'sve256': true }");
3940df9142dSAndrew Jones
3950df9142dSAndrew Jones qtest_quit(qts);
3960df9142dSAndrew Jones }
3970df9142dSAndrew Jones
sve_tests_sve_off_kvm(const void * data)3986fa8a379SAndrew Jones static void sve_tests_sve_off_kvm(const void *data)
3996fa8a379SAndrew Jones {
4006fa8a379SAndrew Jones QTestState *qts;
4016fa8a379SAndrew Jones
4026fa8a379SAndrew Jones qts = qtest_init(MACHINE_KVM "-cpu max,sve=off");
4036fa8a379SAndrew Jones
4046fa8a379SAndrew Jones /*
4056fa8a379SAndrew Jones * We don't know if this host supports SVE so we don't
4066fa8a379SAndrew Jones * attempt to test enabling anything. We only test that
4076fa8a379SAndrew Jones * everything is disabled (as it should be with sve=off)
4086fa8a379SAndrew Jones * and that using sve<N>=off to explicitly disable vector
4096fa8a379SAndrew Jones * lengths is OK too.
4106fa8a379SAndrew Jones */
4116fa8a379SAndrew Jones assert_sve_vls(qts, "max", 0, NULL);
4126fa8a379SAndrew Jones assert_sve_vls(qts, "max", 0, "{ 'sve128': false }");
4136fa8a379SAndrew Jones
4146fa8a379SAndrew Jones qtest_quit(qts);
4156fa8a379SAndrew Jones }
4166fa8a379SAndrew Jones
pauth_tests_default(QTestState * qts,const char * cpu_type)417eb94284dSRichard Henderson static void pauth_tests_default(QTestState *qts, const char *cpu_type)
418eb94284dSRichard Henderson {
419eb94284dSRichard Henderson assert_has_feature_enabled(qts, cpu_type, "pauth");
420eb94284dSRichard Henderson assert_has_feature_disabled(qts, cpu_type, "pauth-impdef");
421399e5e71SRichard Henderson assert_has_feature_disabled(qts, cpu_type, "pauth-qarma3");
42286a00f20SPierrick Bouvier assert_has_feature_disabled(qts, cpu_type, "pauth-qarma5");
423eb94284dSRichard Henderson assert_set_feature(qts, cpu_type, "pauth", false);
424eb94284dSRichard Henderson assert_set_feature(qts, cpu_type, "pauth", true);
425eb94284dSRichard Henderson assert_set_feature(qts, cpu_type, "pauth-impdef", true);
426eb94284dSRichard Henderson assert_set_feature(qts, cpu_type, "pauth-impdef", false);
427399e5e71SRichard Henderson assert_set_feature(qts, cpu_type, "pauth-qarma3", true);
428399e5e71SRichard Henderson assert_set_feature(qts, cpu_type, "pauth-qarma3", false);
42986a00f20SPierrick Bouvier assert_set_feature(qts, cpu_type, "pauth-qarma5", true);
43086a00f20SPierrick Bouvier assert_set_feature(qts, cpu_type, "pauth-qarma5", false);
431399e5e71SRichard Henderson assert_error(qts, cpu_type,
43286a00f20SPierrick Bouvier "cannot enable pauth-impdef, pauth-qarma3 or pauth-qarma5 without pauth",
433eb94284dSRichard Henderson "{ 'pauth': false, 'pauth-impdef': true }");
434399e5e71SRichard Henderson assert_error(qts, cpu_type,
43586a00f20SPierrick Bouvier "cannot enable pauth-impdef, pauth-qarma3 or pauth-qarma5 without pauth",
436399e5e71SRichard Henderson "{ 'pauth': false, 'pauth-qarma3': true }");
437399e5e71SRichard Henderson assert_error(qts, cpu_type,
43886a00f20SPierrick Bouvier "cannot enable pauth-impdef, pauth-qarma3 or pauth-qarma5 without pauth",
43986a00f20SPierrick Bouvier "{ 'pauth': false, 'pauth-qarma5': true }");
44086a00f20SPierrick Bouvier assert_error(qts, cpu_type,
44186a00f20SPierrick Bouvier "cannot enable pauth-impdef, pauth-qarma3 and pauth-qarma5 at the same time",
44286a00f20SPierrick Bouvier "{ 'pauth': true, 'pauth-impdef': true, 'pauth-qarma3': true,"
44386a00f20SPierrick Bouvier " 'pauth-qarma5': true }");
444eb94284dSRichard Henderson }
445eb94284dSRichard Henderson
test_query_cpu_model_expansion(const void * data)446bd31b751SAndrew Jones static void test_query_cpu_model_expansion(const void *data)
447bd31b751SAndrew Jones {
448bd31b751SAndrew Jones QTestState *qts;
449bd31b751SAndrew Jones
450bd31b751SAndrew Jones qts = qtest_init(MACHINE "-cpu max");
451bd31b751SAndrew Jones
452bd31b751SAndrew Jones /* Test common query-cpu-model-expansion input validation */
453bd31b751SAndrew Jones assert_type_full(qts);
454bd31b751SAndrew Jones assert_bad_props(qts, "max");
455bd31b751SAndrew Jones assert_error(qts, "foo", "The CPU type 'foo' is not a recognized "
456bd31b751SAndrew Jones "ARM CPU type", NULL);
4578934643aSMarkus Armbruster assert_error(qts, "max", "Parameter 'model.props.not-a-prop' is unexpected",
458bd31b751SAndrew Jones "{ 'not-a-prop': false }");
459bd31b751SAndrew Jones assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL);
460bd31b751SAndrew Jones
461bd31b751SAndrew Jones /* Test expected feature presence/absence for some cpu types */
462789a35efSAndrew Jones assert_has_feature_enabled(qts, "cortex-a15", "pmu");
463bd31b751SAndrew Jones assert_has_not_feature(qts, "cortex-a15", "aarch64");
464bd31b751SAndrew Jones
46592a70997SAndrew Jones /* Enabling and disabling pmu should always work. */
46692a70997SAndrew Jones assert_has_feature_enabled(qts, "max", "pmu");
46792a70997SAndrew Jones assert_set_feature(qts, "max", "pmu", false);
46892a70997SAndrew Jones assert_set_feature(qts, "max", "pmu", true);
46992a70997SAndrew Jones
470dea101a1SAndrew Jones assert_has_not_feature(qts, "max", "kvm-no-adjvtime");
47168970d1eSAndrew Jones assert_has_not_feature(qts, "max", "kvm-steal-time");
472dea101a1SAndrew Jones
473bd31b751SAndrew Jones if (g_str_equal(qtest_get_arch(), "aarch64")) {
474789a35efSAndrew Jones assert_has_feature_enabled(qts, "max", "aarch64");
475789a35efSAndrew Jones assert_has_feature_enabled(qts, "max", "sve");
476789a35efSAndrew Jones assert_has_feature_enabled(qts, "max", "sve128");
477789a35efSAndrew Jones assert_has_feature_enabled(qts, "cortex-a57", "pmu");
478789a35efSAndrew Jones assert_has_feature_enabled(qts, "cortex-a57", "aarch64");
479bd31b751SAndrew Jones
480499243e1SShuuichirou Ishii assert_has_feature_enabled(qts, "a64fx", "pmu");
481499243e1SShuuichirou Ishii assert_has_feature_enabled(qts, "a64fx", "aarch64");
482499243e1SShuuichirou Ishii /*
483499243e1SShuuichirou Ishii * A64FX does not support any other vector lengths besides those
484499243e1SShuuichirou Ishii * that are enabled by default(128bit, 256bits, 512bit).
485499243e1SShuuichirou Ishii */
486499243e1SShuuichirou Ishii assert_has_feature_enabled(qts, "a64fx", "sve");
487499243e1SShuuichirou Ishii assert_sve_vls(qts, "a64fx", 0xb, NULL);
488499243e1SShuuichirou Ishii assert_error(qts, "a64fx", "cannot enable sve384",
489499243e1SShuuichirou Ishii "{ 'sve384': true }");
490499243e1SShuuichirou Ishii assert_error(qts, "a64fx", "cannot enable sve640",
491499243e1SShuuichirou Ishii "{ 'sve640': true }");
492499243e1SShuuichirou Ishii
4930df9142dSAndrew Jones sve_tests_default(qts, "max");
494eb94284dSRichard Henderson pauth_tests_default(qts, "max");
4950df9142dSAndrew Jones
496bd31b751SAndrew Jones /* Test that features that depend on KVM generate errors without. */
497bd31b751SAndrew Jones assert_error(qts, "max",
498bd31b751SAndrew Jones "'aarch64' feature cannot be disabled "
499bd31b751SAndrew Jones "unless KVM is enabled and 32-bit EL1 "
500bd31b751SAndrew Jones "is supported",
501bd31b751SAndrew Jones "{ 'aarch64': false }");
502bd31b751SAndrew Jones }
503bd31b751SAndrew Jones
504bd31b751SAndrew Jones qtest_quit(qts);
505bd31b751SAndrew Jones }
506bd31b751SAndrew Jones
test_query_cpu_model_expansion_kvm(const void * data)507bd31b751SAndrew Jones static void test_query_cpu_model_expansion_kvm(const void *data)
508bd31b751SAndrew Jones {
509bd31b751SAndrew Jones QTestState *qts;
510bd31b751SAndrew Jones
511bd31b751SAndrew Jones qts = qtest_init(MACHINE_KVM "-cpu max");
512bd31b751SAndrew Jones
51392a70997SAndrew Jones /* Enabling and disabling kvm-no-adjvtime should always work. */
514dea101a1SAndrew Jones assert_has_feature_disabled(qts, "host", "kvm-no-adjvtime");
51592a70997SAndrew Jones assert_set_feature(qts, "host", "kvm-no-adjvtime", true);
51692a70997SAndrew Jones assert_set_feature(qts, "host", "kvm-no-adjvtime", false);
517dea101a1SAndrew Jones
518bd31b751SAndrew Jones if (g_str_equal(qtest_get_arch(), "aarch64")) {
51971328d82SAkihiko Odaki bool kvm_supports_pmu;
52068970d1eSAndrew Jones bool kvm_supports_steal_time;
5216fa8a379SAndrew Jones bool kvm_supports_sve;
5226fa8a379SAndrew Jones char max_name[8], name[8];
5236fa8a379SAndrew Jones uint32_t max_vq, vq;
5246fa8a379SAndrew Jones uint64_t vls;
5256fa8a379SAndrew Jones QDict *resp;
5266fa8a379SAndrew Jones char *error;
5276fa8a379SAndrew Jones
528557ed03aSFabiano Rosas /*
529557ed03aSFabiano Rosas * When using KVM, only the 'host' and 'max' CPU models are
530557ed03aSFabiano Rosas * supported. Test that we're emitting a suitable error for
531557ed03aSFabiano Rosas * unsupported CPU models.
532557ed03aSFabiano Rosas */
533557ed03aSFabiano Rosas if (qtest_has_accel("tcg")) {
534557ed03aSFabiano Rosas assert_error(qts, "cortex-a7",
535557ed03aSFabiano Rosas "We cannot guarantee the CPU type 'cortex-a7' works "
53668970d1eSAndrew Jones "with KVM on this host", NULL);
537557ed03aSFabiano Rosas } else {
538557ed03aSFabiano Rosas /*
539557ed03aSFabiano Rosas * With a KVM-only build the 32-bit CPUs are not present.
540557ed03aSFabiano Rosas */
541557ed03aSFabiano Rosas assert_error(qts, "cortex-a7",
542557ed03aSFabiano Rosas "The CPU type 'cortex-a7' is not a "
543557ed03aSFabiano Rosas "recognized ARM CPU type", NULL);
544557ed03aSFabiano Rosas }
54568970d1eSAndrew Jones
546789a35efSAndrew Jones assert_has_feature_enabled(qts, "host", "aarch64");
54792a70997SAndrew Jones
54868970d1eSAndrew Jones /*
54968970d1eSAndrew Jones * Some features would be enabled by default, but they're disabled
55068970d1eSAndrew Jones * because this instance of KVM doesn't support them. Test that the
55168970d1eSAndrew Jones * features are present, and, when enabled, issue further tests.
55268970d1eSAndrew Jones */
55368970d1eSAndrew Jones assert_has_feature(qts, "host", "kvm-steal-time");
55487014c6bSAndrew Jones assert_has_feature(qts, "host", "sve");
55568970d1eSAndrew Jones
55687014c6bSAndrew Jones resp = do_query_no_props(qts, "host");
55771328d82SAkihiko Odaki kvm_supports_pmu = resp_get_feature(resp, "pmu");
55868970d1eSAndrew Jones kvm_supports_steal_time = resp_get_feature(resp, "kvm-steal-time");
5596fa8a379SAndrew Jones kvm_supports_sve = resp_get_feature(resp, "sve");
5606fa8a379SAndrew Jones vls = resp_get_sve_vls(resp);
5616fa8a379SAndrew Jones qobject_unref(resp);
5626fa8a379SAndrew Jones
56371328d82SAkihiko Odaki if (kvm_supports_pmu) {
56471328d82SAkihiko Odaki /* If we have pmu then we should be able to toggle it. */
56571328d82SAkihiko Odaki assert_set_feature(qts, "host", "pmu", false);
56671328d82SAkihiko Odaki assert_set_feature(qts, "host", "pmu", true);
56771328d82SAkihiko Odaki }
56871328d82SAkihiko Odaki
56968970d1eSAndrew Jones if (kvm_supports_steal_time) {
57068970d1eSAndrew Jones /* If we have steal-time then we should be able to toggle it. */
57168970d1eSAndrew Jones assert_set_feature(qts, "host", "kvm-steal-time", false);
57268970d1eSAndrew Jones assert_set_feature(qts, "host", "kvm-steal-time", true);
57368970d1eSAndrew Jones }
57468970d1eSAndrew Jones
5756fa8a379SAndrew Jones if (kvm_supports_sve) {
5766fa8a379SAndrew Jones g_assert(vls != 0);
5776fa8a379SAndrew Jones max_vq = 64 - __builtin_clzll(vls);
5783dc05792SAlexChen sprintf(max_name, "sve%u", max_vq * 128);
5796fa8a379SAndrew Jones
5806fa8a379SAndrew Jones /* Enabling a supported length is of course fine. */
58187014c6bSAndrew Jones assert_sve_vls(qts, "host", vls, "{ %s: true }", max_name);
5826fa8a379SAndrew Jones
5836fa8a379SAndrew Jones /* Get the next supported length smaller than max-vq. */
5846fa8a379SAndrew Jones vq = 64 - __builtin_clzll(vls & ~BIT_ULL(max_vq - 1));
5856fa8a379SAndrew Jones if (vq) {
5866fa8a379SAndrew Jones /*
5876fa8a379SAndrew Jones * We have at least one length smaller than max-vq,
5886fa8a379SAndrew Jones * so we can disable max-vq.
5896fa8a379SAndrew Jones */
59087014c6bSAndrew Jones assert_sve_vls(qts, "host", (vls & ~BIT_ULL(max_vq - 1)),
5916fa8a379SAndrew Jones "{ %s: false }", max_name);
5926fa8a379SAndrew Jones
5936fa8a379SAndrew Jones /*
5946fa8a379SAndrew Jones * Smaller, supported vector lengths cannot be disabled
5956fa8a379SAndrew Jones * unless all larger, supported vector lengths are also
5966fa8a379SAndrew Jones * disabled.
5976fa8a379SAndrew Jones */
5983dc05792SAlexChen sprintf(name, "sve%u", vq * 128);
5996fa8a379SAndrew Jones error = g_strdup_printf("cannot disable %s", name);
60087014c6bSAndrew Jones assert_error(qts, "host", error,
6016fa8a379SAndrew Jones "{ %s: true, %s: false }",
6026fa8a379SAndrew Jones max_name, name);
6036fa8a379SAndrew Jones g_free(error);
6046fa8a379SAndrew Jones }
6056fa8a379SAndrew Jones
6066fa8a379SAndrew Jones /*
6076fa8a379SAndrew Jones * The smallest, supported vector length is required, because
6086fa8a379SAndrew Jones * we need at least one vector length enabled.
6096fa8a379SAndrew Jones */
6106fa8a379SAndrew Jones vq = __builtin_ffsll(vls);
6113dc05792SAlexChen sprintf(name, "sve%u", vq * 128);
6126fa8a379SAndrew Jones error = g_strdup_printf("cannot disable %s", name);
61387014c6bSAndrew Jones assert_error(qts, "host", error, "{ %s: false }", name);
6146fa8a379SAndrew Jones g_free(error);
6156fa8a379SAndrew Jones
6166fa8a379SAndrew Jones /* Get an unsupported length. */
6176fa8a379SAndrew Jones for (vq = 1; vq <= max_vq; ++vq) {
6186fa8a379SAndrew Jones if (!(vls & BIT_ULL(vq - 1))) {
6196fa8a379SAndrew Jones break;
6206fa8a379SAndrew Jones }
6216fa8a379SAndrew Jones }
6226fa8a379SAndrew Jones if (vq <= SVE_MAX_VQ) {
6233dc05792SAlexChen sprintf(name, "sve%u", vq * 128);
6246fa8a379SAndrew Jones error = g_strdup_printf("cannot enable %s", name);
62587014c6bSAndrew Jones assert_error(qts, "host", error, "{ %s: true }", name);
6266fa8a379SAndrew Jones g_free(error);
6276fa8a379SAndrew Jones }
6286fa8a379SAndrew Jones } else {
6296fa8a379SAndrew Jones g_assert(vls == 0);
6306fa8a379SAndrew Jones }
631bd31b751SAndrew Jones } else {
632bd31b751SAndrew Jones assert_has_not_feature(qts, "host", "aarch64");
633bd31b751SAndrew Jones assert_has_not_feature(qts, "host", "pmu");
63487014c6bSAndrew Jones assert_has_not_feature(qts, "host", "sve");
63568970d1eSAndrew Jones assert_has_not_feature(qts, "host", "kvm-steal-time");
636bd31b751SAndrew Jones }
637bd31b751SAndrew Jones
638bd31b751SAndrew Jones qtest_quit(qts);
639bd31b751SAndrew Jones }
640bd31b751SAndrew Jones
main(int argc,char ** argv)641bd31b751SAndrew Jones int main(int argc, char **argv)
642bd31b751SAndrew Jones {
643bd31b751SAndrew Jones g_test_init(&argc, &argv, NULL);
644bd31b751SAndrew Jones
6456bd92a7cSPaolo Bonzini if (!qtest_has_machine("virt")) {
6466bd92a7cSPaolo Bonzini goto out;
6476bd92a7cSPaolo Bonzini }
6486bd92a7cSPaolo Bonzini
649500a0accSFabiano Rosas if (qtest_has_accel("tcg")) {
650bd31b751SAndrew Jones qtest_add_data_func("/arm/query-cpu-model-expansion",
651bd31b751SAndrew Jones NULL, test_query_cpu_model_expansion);
652500a0accSFabiano Rosas }
653500a0accSFabiano Rosas
654500a0accSFabiano Rosas if (!g_str_equal(qtest_get_arch(), "aarch64")) {
655500a0accSFabiano Rosas goto out;
656500a0accSFabiano Rosas }
657bd31b751SAndrew Jones
658bd31b751SAndrew Jones /*
659bd31b751SAndrew Jones * For now we only run KVM specific tests with AArch64 QEMU in
660bd31b751SAndrew Jones * order avoid attempting to run an AArch32 QEMU with KVM on
661bd31b751SAndrew Jones * AArch64 hosts. That won't work and isn't easy to detect.
662bd31b751SAndrew Jones */
663500a0accSFabiano Rosas if (qtest_has_accel("kvm")) {
66407e6ed2cSIgor Mammedov /*
66507e6ed2cSIgor Mammedov * This tests target the 'host' CPU type, so register it only if
66607e6ed2cSIgor Mammedov * KVM is available.
66707e6ed2cSIgor Mammedov */
668bd31b751SAndrew Jones qtest_add_data_func("/arm/kvm/query-cpu-model-expansion",
669bd31b751SAndrew Jones NULL, test_query_cpu_model_expansion_kvm);
670bd31b751SAndrew Jones
6716fa8a379SAndrew Jones qtest_add_data_func("/arm/kvm/query-cpu-model-expansion/sve-off",
6726fa8a379SAndrew Jones NULL, sve_tests_sve_off_kvm);
6730df9142dSAndrew Jones }
6740df9142dSAndrew Jones
675500a0accSFabiano Rosas if (qtest_has_accel("tcg")) {
676500a0accSFabiano Rosas qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-max-vq-8",
677500a0accSFabiano Rosas NULL, sve_tests_sve_max_vq_8);
678500a0accSFabiano Rosas qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-off",
679500a0accSFabiano Rosas NULL, sve_tests_sve_off);
680500a0accSFabiano Rosas }
681500a0accSFabiano Rosas
682500a0accSFabiano Rosas out:
683bd31b751SAndrew Jones return g_test_run();
684bd31b751SAndrew Jones }
685