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