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