xref: /aosp_15_r20/external/arm-trusted-firmware/lib/extensions/sme/sme.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <stdbool.h>
8*54fd6939SJiyong Park 
9*54fd6939SJiyong Park #include <arch.h>
10*54fd6939SJiyong Park #include <arch_helpers.h>
11*54fd6939SJiyong Park #include <common/debug.h>
12*54fd6939SJiyong Park #include <lib/el3_runtime/context_mgmt.h>
13*54fd6939SJiyong Park #include <lib/extensions/sme.h>
14*54fd6939SJiyong Park #include <lib/extensions/sve.h>
15*54fd6939SJiyong Park 
feat_sme_supported(void)16*54fd6939SJiyong Park static bool feat_sme_supported(void)
17*54fd6939SJiyong Park {
18*54fd6939SJiyong Park 	uint64_t features;
19*54fd6939SJiyong Park 
20*54fd6939SJiyong Park 	features = read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_SME_SHIFT;
21*54fd6939SJiyong Park 	return (features & ID_AA64PFR1_EL1_SME_MASK) != 0U;
22*54fd6939SJiyong Park }
23*54fd6939SJiyong Park 
feat_sme_fa64_supported(void)24*54fd6939SJiyong Park static bool feat_sme_fa64_supported(void)
25*54fd6939SJiyong Park {
26*54fd6939SJiyong Park 	uint64_t features;
27*54fd6939SJiyong Park 
28*54fd6939SJiyong Park 	features = read_id_aa64smfr0_el1();
29*54fd6939SJiyong Park 	return (features & ID_AA64SMFR0_EL1_FA64_BIT) != 0U;
30*54fd6939SJiyong Park }
31*54fd6939SJiyong Park 
sme_enable(cpu_context_t * context)32*54fd6939SJiyong Park void sme_enable(cpu_context_t *context)
33*54fd6939SJiyong Park {
34*54fd6939SJiyong Park 	u_register_t reg;
35*54fd6939SJiyong Park 	u_register_t cptr_el3;
36*54fd6939SJiyong Park 	el3_state_t *state;
37*54fd6939SJiyong Park 
38*54fd6939SJiyong Park 	/* Make sure SME is implemented in hardware before continuing. */
39*54fd6939SJiyong Park 	if (!feat_sme_supported()) {
40*54fd6939SJiyong Park 		return;
41*54fd6939SJiyong Park 	}
42*54fd6939SJiyong Park 
43*54fd6939SJiyong Park 	/* Get the context state. */
44*54fd6939SJiyong Park 	state = get_el3state_ctx(context);
45*54fd6939SJiyong Park 
46*54fd6939SJiyong Park 	/* Enable SME in CPTR_EL3. */
47*54fd6939SJiyong Park 	reg = read_ctx_reg(state, CTX_CPTR_EL3);
48*54fd6939SJiyong Park 	reg |= ESM_BIT;
49*54fd6939SJiyong Park 	write_ctx_reg(state, CTX_CPTR_EL3, reg);
50*54fd6939SJiyong Park 
51*54fd6939SJiyong Park 	/* Set the ENTP2 bit in SCR_EL3 to enable access to TPIDR2_EL0. */
52*54fd6939SJiyong Park 	reg = read_ctx_reg(state, CTX_SCR_EL3);
53*54fd6939SJiyong Park 	reg |= SCR_ENTP2_BIT;
54*54fd6939SJiyong Park 	write_ctx_reg(state, CTX_SCR_EL3, reg);
55*54fd6939SJiyong Park 
56*54fd6939SJiyong Park 	/* Set CPTR_EL3.ESM bit so we can write SMCR_EL3 without trapping. */
57*54fd6939SJiyong Park 	cptr_el3 = read_cptr_el3();
58*54fd6939SJiyong Park 	write_cptr_el3(cptr_el3 | ESM_BIT);
59*54fd6939SJiyong Park 
60*54fd6939SJiyong Park 	/*
61*54fd6939SJiyong Park 	 * Set the max LEN value and FA64 bit. This register is set up globally
62*54fd6939SJiyong Park 	 * to be the least restrictive, then lower ELs can restrict as needed
63*54fd6939SJiyong Park 	 * using SMCR_EL2 and SMCR_EL1.
64*54fd6939SJiyong Park 	 */
65*54fd6939SJiyong Park 	reg = SMCR_ELX_LEN_MASK;
66*54fd6939SJiyong Park 	if (feat_sme_fa64_supported()) {
67*54fd6939SJiyong Park 		VERBOSE("[SME] FA64 enabled\n");
68*54fd6939SJiyong Park 		reg |= SMCR_ELX_FA64_BIT;
69*54fd6939SJiyong Park 	}
70*54fd6939SJiyong Park 	write_smcr_el3(reg);
71*54fd6939SJiyong Park 
72*54fd6939SJiyong Park 	/* Reset CPTR_EL3 value. */
73*54fd6939SJiyong Park 	write_cptr_el3(cptr_el3);
74*54fd6939SJiyong Park 
75*54fd6939SJiyong Park 	/* Enable SVE/FPU in addition to SME. */
76*54fd6939SJiyong Park 	sve_enable(context);
77*54fd6939SJiyong Park }
78*54fd6939SJiyong Park 
sme_disable(cpu_context_t * context)79*54fd6939SJiyong Park void sme_disable(cpu_context_t *context)
80*54fd6939SJiyong Park {
81*54fd6939SJiyong Park 	u_register_t reg;
82*54fd6939SJiyong Park 	el3_state_t *state;
83*54fd6939SJiyong Park 
84*54fd6939SJiyong Park 	/* Make sure SME is implemented in hardware before continuing. */
85*54fd6939SJiyong Park 	if (!feat_sme_supported()) {
86*54fd6939SJiyong Park 		return;
87*54fd6939SJiyong Park 	}
88*54fd6939SJiyong Park 
89*54fd6939SJiyong Park 	/* Get the context state. */
90*54fd6939SJiyong Park 	state = get_el3state_ctx(context);
91*54fd6939SJiyong Park 
92*54fd6939SJiyong Park 	/* Disable SME, SVE, and FPU since they all share registers. */
93*54fd6939SJiyong Park 	reg = read_ctx_reg(state, CTX_CPTR_EL3);
94*54fd6939SJiyong Park 	reg &= ~ESM_BIT;	/* Trap SME */
95*54fd6939SJiyong Park 	reg &= ~CPTR_EZ_BIT;	/* Trap SVE */
96*54fd6939SJiyong Park 	reg |= TFP_BIT;		/* Trap FPU/SIMD */
97*54fd6939SJiyong Park 	write_ctx_reg(state, CTX_CPTR_EL3, reg);
98*54fd6939SJiyong Park 
99*54fd6939SJiyong Park 	/* Disable access to TPIDR2_EL0. */
100*54fd6939SJiyong Park 	reg = read_ctx_reg(state, CTX_SCR_EL3);
101*54fd6939SJiyong Park 	reg &= ~SCR_ENTP2_BIT;
102*54fd6939SJiyong Park 	write_ctx_reg(state, CTX_SCR_EL3, reg);
103*54fd6939SJiyong Park }
104