summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordavidcunado-arm <david.cunado@arm.com>2017-12-11 12:29:47 +0000
committerGitHub <noreply@github.com>2017-12-11 12:29:47 +0000
commit211d307c6bfadbe44aa27998e105436143e1b147 (patch)
treea37e6e9abfffa4c98ad3d95894ea7009755c56e6 /lib
parent83df7ce38dd5b2357fa73798ad1f3546c6073482 (diff)
parent3872fc2d1fc58170e0ebc87a0cc20bff6a83ef51 (diff)
Merge pull request #1178 from davidcunado-arm/dc/enable_sve
Enable SVE for Non-secure world
Diffstat (limited to 'lib')
-rw-r--r--lib/el3_runtime/aarch64/context_mgmt.c5
-rw-r--r--lib/extensions/sve/sve.c126
2 files changed, 131 insertions, 0 deletions
diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c
index b892729e..c6c2249a 100644
--- a/lib/el3_runtime/aarch64/context_mgmt.c
+++ b/lib/el3_runtime/aarch64/context_mgmt.c
@@ -18,6 +18,7 @@
#include <smcc_helpers.h>
#include <spe.h>
#include <string.h>
+#include <sve.h>
#include <utils.h>
@@ -225,6 +226,10 @@ static void enable_extensions_nonsecure(int el2_unused)
#if ENABLE_AMU
amu_enable(el2_unused);
#endif
+
+#if ENABLE_SVE_FOR_NS
+ sve_enable(el2_unused);
+#endif
#endif
}
diff --git a/lib/extensions/sve/sve.c b/lib/extensions/sve/sve.c
new file mode 100644
index 00000000..14e51bd8
--- /dev/null
+++ b/lib/extensions/sve/sve.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <pubsub.h>
+#include <sve.h>
+
+static void *disable_sve_hook(const void *arg)
+{
+ uint64_t features;
+
+ features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
+ if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
+ uint64_t cptr;
+
+ /*
+ * Disable SVE, SIMD and FP access for the Secure world.
+ * As the SIMD/FP registers are part of the SVE Z-registers, any
+ * use of SIMD/FP functionality will corrupt the SVE registers.
+ * Therefore it is necessary to prevent use of SIMD/FP support
+ * in the Secure world as well as SVE functionality.
+ */
+ cptr = read_cptr_el3();
+ cptr = (cptr | TFP_BIT) & ~(CPTR_EZ_BIT);
+ write_cptr_el3(cptr);
+
+ /*
+ * No explicit ISB required here as ERET to switch to Secure
+ * world covers it
+ */
+ }
+ return 0;
+}
+
+static void *enable_sve_hook(const void *arg)
+{
+ uint64_t features;
+
+ features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
+ if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
+ uint64_t cptr;
+
+ /*
+ * Enable SVE, SIMD and FP access for the Non-secure world.
+ */
+ cptr = read_cptr_el3();
+ cptr = (cptr | CPTR_EZ_BIT) & ~(TFP_BIT);
+ write_cptr_el3(cptr);
+
+ /*
+ * No explicit ISB required here as ERET to switch to Non-secure
+ * world covers it
+ */
+ }
+ return 0;
+}
+
+void sve_enable(int el2_unused)
+{
+ uint64_t features;
+
+ features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
+ if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
+ uint64_t cptr;
+#if CTX_INCLUDE_FPREGS
+ /*
+ * CTX_INCLUDE_FPREGS is not supported on SVE enabled systems.
+ */
+ assert(0);
+#endif
+ /*
+ * Update CPTR_EL3 to enable access to SVE functionality for the
+ * Non-secure world.
+ * NOTE - assumed that CPTR_EL3.TFP is set to allow access to
+ * the SIMD, floating-point and SVE support.
+ *
+ * CPTR_EL3.EZ: Set to 1 to enable access to SVE functionality
+ * in the Non-secure world.
+ */
+ cptr = read_cptr_el3();
+ cptr |= CPTR_EZ_BIT;
+ write_cptr_el3(cptr);
+
+ /*
+ * Need explicit ISB here to guarantee that update to ZCR_ELx
+ * and CPTR_EL2.TZ do not result in trap to EL3.
+ */
+ isb();
+
+ /*
+ * Ensure lower ELs have access to full vector length.
+ */
+ write_zcr_el3(ZCR_EL3_LEN_MASK);
+
+ if (el2_unused) {
+ /*
+ * Update CPTR_EL2 to enable access to SVE functionality
+ * for Non-secure world, EL2 and Non-secure EL1 and EL0.
+ * NOTE - assumed that CPTR_EL2.TFP is set to allow
+ * access to the SIMD, floating-point and SVE support.
+ *
+ * CPTR_EL2.TZ: Set to 0 to enable access to SVE support
+ * for EL2 and Non-secure EL1 and EL0.
+ */
+ cptr = read_cptr_el2();
+ cptr &= ~(CPTR_EL2_TZ_BIT);
+ write_cptr_el2(cptr);
+
+ /*
+ * Ensure lower ELs have access to full vector length.
+ */
+ write_zcr_el2(ZCR_EL2_LEN_MASK);
+ }
+ /*
+ * No explicit ISB required here as ERET to switch to
+ * Non-secure world covers it.
+ */
+ }
+}
+
+SUBSCRIBE_TO_EVENT(cm_exited_normal_world, disable_sve_hook);
+SUBSCRIBE_TO_EVENT(cm_entering_normal_world, enable_sve_hook);