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