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