blob: 14e51bd86772a94594dcf09245a0d579b21069dc [file] [log] [blame]
David Cunadoce88eee2017-10-20 11:30:57 +01001/*
2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch.h>
8#include <arch_helpers.h>
9#include <pubsub.h>
10#include <sve.h>
11
12static void *disable_sve_hook(const void *arg)
13{
14 uint64_t features;
15
16 features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
17 if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
18 uint64_t cptr;
19
20 /*
21 * Disable SVE, SIMD and FP access for the Secure world.
22 * As the SIMD/FP registers are part of the SVE Z-registers, any
23 * use of SIMD/FP functionality will corrupt the SVE registers.
24 * Therefore it is necessary to prevent use of SIMD/FP support
25 * in the Secure world as well as SVE functionality.
26 */
27 cptr = read_cptr_el3();
28 cptr = (cptr | TFP_BIT) & ~(CPTR_EZ_BIT);
29 write_cptr_el3(cptr);
30
31 /*
32 * No explicit ISB required here as ERET to switch to Secure
33 * world covers it
34 */
35 }
36 return 0;
37}
38
39static void *enable_sve_hook(const void *arg)
40{
41 uint64_t features;
42
43 features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
44 if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
45 uint64_t cptr;
46
47 /*
48 * Enable SVE, SIMD and FP access for the Non-secure world.
49 */
50 cptr = read_cptr_el3();
51 cptr = (cptr | CPTR_EZ_BIT) & ~(TFP_BIT);
52 write_cptr_el3(cptr);
53
54 /*
55 * No explicit ISB required here as ERET to switch to Non-secure
56 * world covers it
57 */
58 }
59 return 0;
60}
61
62void sve_enable(int el2_unused)
63{
64 uint64_t features;
65
66 features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT;
67 if ((features & ID_AA64PFR0_SVE_MASK) == 1) {
68 uint64_t cptr;
69#if CTX_INCLUDE_FPREGS
70 /*
71 * CTX_INCLUDE_FPREGS is not supported on SVE enabled systems.
72 */
73 assert(0);
74#endif
75 /*
76 * Update CPTR_EL3 to enable access to SVE functionality for the
77 * Non-secure world.
78 * NOTE - assumed that CPTR_EL3.TFP is set to allow access to
79 * the SIMD, floating-point and SVE support.
80 *
81 * CPTR_EL3.EZ: Set to 1 to enable access to SVE functionality
82 * in the Non-secure world.
83 */
84 cptr = read_cptr_el3();
85 cptr |= CPTR_EZ_BIT;
86 write_cptr_el3(cptr);
87
88 /*
89 * Need explicit ISB here to guarantee that update to ZCR_ELx
90 * and CPTR_EL2.TZ do not result in trap to EL3.
91 */
92 isb();
93
94 /*
95 * Ensure lower ELs have access to full vector length.
96 */
97 write_zcr_el3(ZCR_EL3_LEN_MASK);
98
99 if (el2_unused) {
100 /*
101 * Update CPTR_EL2 to enable access to SVE functionality
102 * for Non-secure world, EL2 and Non-secure EL1 and EL0.
103 * NOTE - assumed that CPTR_EL2.TFP is set to allow
104 * access to the SIMD, floating-point and SVE support.
105 *
106 * CPTR_EL2.TZ: Set to 0 to enable access to SVE support
107 * for EL2 and Non-secure EL1 and EL0.
108 */
109 cptr = read_cptr_el2();
110 cptr &= ~(CPTR_EL2_TZ_BIT);
111 write_cptr_el2(cptr);
112
113 /*
114 * Ensure lower ELs have access to full vector length.
115 */
116 write_zcr_el2(ZCR_EL2_LEN_MASK);
117 }
118 /*
119 * No explicit ISB required here as ERET to switch to
120 * Non-secure world covers it.
121 */
122 }
123}
124
125SUBSCRIBE_TO_EVENT(cm_exited_normal_world, disable_sve_hook);
126SUBSCRIBE_TO_EVENT(cm_entering_normal_world, enable_sve_hook);