aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAndrew Jones <drjones@redhat.com>2019-10-31 15:27:33 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-11-01 20:40:59 +0000
commit6fa8a37949d912bb463caa0c139ff0ca88c6ec33 (patch)
tree4997a693b0d50948a64a572e02296b4124741896 /tests
parent0cdb4020b34b455fb9ef1e6283407d952cb02e63 (diff)
target/arm/cpu64: max cpu: Support sve properties with KVM
Extend the SVE vq map initialization and validation with KVM's supported vector lengths when KVM is enabled. In order to determine and select supported lengths we add two new KVM functions for getting and setting the KVM_REG_ARM64_SVE_VLS pseudo-register. This patch has been co-authored with Richard Henderson, who reworked the target/arm/cpu64.c changes in order to push all the validation and auto-enabling/disabling steps into the finalizer, resulting in a nice LOC reduction. Signed-off-by: Andrew Jones <drjones@redhat.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Tested-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com> Message-id: 20191031142734.8590-9-drjones@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/arm-cpu-features.c104
1 files changed, 102 insertions, 2 deletions
diff --git a/tests/arm-cpu-features.c b/tests/arm-cpu-features.c
index a48f9107dd..ffdbc3fce6 100644
--- a/tests/arm-cpu-features.c
+++ b/tests/arm-cpu-features.c
@@ -130,6 +130,17 @@ static QDict *resp_get_props(QDict *resp)
return qdict;
}
+static bool resp_get_feature(QDict *resp, const char *feature)
+{
+ QDict *props;
+
+ g_assert(resp);
+ g_assert(resp_has_props(resp));
+ props = resp_get_props(resp);
+ g_assert(qdict_get(props, feature));
+ return qdict_get_bool(props, feature);
+}
+
#define assert_has_feature(qts, cpu_type, feature) \
({ \
QDict *_resp = do_query_no_props(qts, cpu_type); \
@@ -359,6 +370,25 @@ static void sve_tests_sve_off(const void *data)
qtest_quit(qts);
}
+static void sve_tests_sve_off_kvm(const void *data)
+{
+ QTestState *qts;
+
+ qts = qtest_init(MACHINE_KVM "-cpu max,sve=off");
+
+ /*
+ * We don't know if this host supports SVE so we don't
+ * attempt to test enabling anything. We only test that
+ * everything is disabled (as it should be with sve=off)
+ * and that using sve<N>=off to explicitly disable vector
+ * lengths is OK too.
+ */
+ assert_sve_vls(qts, "max", 0, NULL);
+ assert_sve_vls(qts, "max", 0, "{ 'sve128': false }");
+
+ qtest_quit(qts);
+}
+
static void test_query_cpu_model_expansion(const void *data)
{
QTestState *qts;
@@ -414,14 +444,82 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
}
if (g_str_equal(qtest_get_arch(), "aarch64")) {
+ bool kvm_supports_sve;
+ char max_name[8], name[8];
+ uint32_t max_vq, vq;
+ uint64_t vls;
+ QDict *resp;
+ char *error;
+
assert_has_feature(qts, "host", "aarch64");
assert_has_feature(qts, "host", "pmu");
- assert_has_feature(qts, "max", "sve");
-
assert_error(qts, "cortex-a15",
"We cannot guarantee the CPU type 'cortex-a15' works "
"with KVM on this host", NULL);
+
+ assert_has_feature(qts, "max", "sve");
+ resp = do_query_no_props(qts, "max");
+ kvm_supports_sve = resp_get_feature(resp, "sve");
+ vls = resp_get_sve_vls(resp);
+ qobject_unref(resp);
+
+ if (kvm_supports_sve) {
+ g_assert(vls != 0);
+ max_vq = 64 - __builtin_clzll(vls);
+ sprintf(max_name, "sve%d", max_vq * 128);
+
+ /* Enabling a supported length is of course fine. */
+ assert_sve_vls(qts, "max", vls, "{ %s: true }", max_name);
+
+ /* Get the next supported length smaller than max-vq. */
+ vq = 64 - __builtin_clzll(vls & ~BIT_ULL(max_vq - 1));
+ if (vq) {
+ /*
+ * We have at least one length smaller than max-vq,
+ * so we can disable max-vq.
+ */
+ assert_sve_vls(qts, "max", (vls & ~BIT_ULL(max_vq - 1)),
+ "{ %s: false }", max_name);
+
+ /*
+ * Smaller, supported vector lengths cannot be disabled
+ * unless all larger, supported vector lengths are also
+ * disabled.
+ */
+ sprintf(name, "sve%d", vq * 128);
+ error = g_strdup_printf("cannot disable %s", name);
+ assert_error(qts, "max", error,
+ "{ %s: true, %s: false }",
+ max_name, name);
+ g_free(error);
+ }
+
+ /*
+ * The smallest, supported vector length is required, because
+ * we need at least one vector length enabled.
+ */
+ vq = __builtin_ffsll(vls);
+ sprintf(name, "sve%d", vq * 128);
+ error = g_strdup_printf("cannot disable %s", name);
+ assert_error(qts, "max", error, "{ %s: false }", name);
+ g_free(error);
+
+ /* Get an unsupported length. */
+ for (vq = 1; vq <= max_vq; ++vq) {
+ if (!(vls & BIT_ULL(vq - 1))) {
+ break;
+ }
+ }
+ if (vq <= SVE_MAX_VQ) {
+ sprintf(name, "sve%d", vq * 128);
+ error = g_strdup_printf("cannot enable %s", name);
+ assert_error(qts, "max", error, "{ %s: true }", name);
+ g_free(error);
+ }
+ } else {
+ g_assert(vls == 0);
+ }
} else {
assert_has_not_feature(qts, "host", "aarch64");
assert_has_not_feature(qts, "host", "pmu");
@@ -454,6 +552,8 @@ int main(int argc, char **argv)
NULL, sve_tests_sve_max_vq_8);
qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-off",
NULL, sve_tests_sve_off);
+ qtest_add_data_func("/arm/kvm/query-cpu-model-expansion/sve-off",
+ NULL, sve_tests_sve_off_kvm);
}
return g_test_run();