johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 1 | /* |
Jayanth Dodderi Chidanand | 605419a | 2023-03-06 23:56:14 +0000 | [diff] [blame] | 2 | * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved. |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
| 6 | |
| 7 | #include <stdbool.h> |
| 8 | |
| 9 | #include <arch.h> |
Jayanth Dodderi Chidanand | 605419a | 2023-03-06 23:56:14 +0000 | [diff] [blame] | 10 | #include <arch_features.h> |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 11 | #include <arch_helpers.h> |
| 12 | #include <common/debug.h> |
| 13 | #include <lib/el3_runtime/context_mgmt.h> |
| 14 | #include <lib/extensions/sme.h> |
| 15 | #include <lib/extensions/sve.h> |
| 16 | |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 17 | void sme_enable(cpu_context_t *context) |
| 18 | { |
| 19 | u_register_t reg; |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 20 | el3_state_t *state; |
| 21 | |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 22 | /* Get the context state. */ |
| 23 | state = get_el3state_ctx(context); |
| 24 | |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 25 | /* Set the ENTP2 bit in SCR_EL3 to enable access to TPIDR2_EL0. */ |
| 26 | reg = read_ctx_reg(state, CTX_SCR_EL3); |
| 27 | reg |= SCR_ENTP2_BIT; |
| 28 | write_ctx_reg(state, CTX_SCR_EL3, reg); |
Boyan Karatotev | 6468d4a | 2023-02-16 15:12:45 +0000 | [diff] [blame] | 29 | } |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 30 | |
Elizabeth Ho | 4fc00d2 | 2023-07-18 14:10:25 +0100 | [diff] [blame] | 31 | void sme_enable_per_world(per_world_context_t *per_world_ctx) |
| 32 | { |
| 33 | u_register_t reg; |
| 34 | |
| 35 | /* Enable SME in CPTR_EL3. */ |
| 36 | reg = per_world_ctx->ctx_cptr_el3; |
| 37 | reg |= ESM_BIT; |
| 38 | per_world_ctx->ctx_cptr_el3 = reg; |
| 39 | } |
| 40 | |
Boyan Karatotev | 6468d4a | 2023-02-16 15:12:45 +0000 | [diff] [blame] | 41 | void sme_init_el3(void) |
| 42 | { |
| 43 | u_register_t cptr_el3 = read_cptr_el3(); |
| 44 | u_register_t smcr_el3; |
| 45 | |
| 46 | /* Set CPTR_EL3.ESM bit so we can access SMCR_EL3 without trapping. */ |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 47 | write_cptr_el3(cptr_el3 | ESM_BIT); |
Boyan Karatotev | be028b4 | 2022-10-13 13:51:05 +0100 | [diff] [blame] | 48 | isb(); |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 49 | |
| 50 | /* |
Elizabeth Ho | 4fc00d2 | 2023-07-18 14:10:25 +0100 | [diff] [blame] | 51 | * Set the max LEN value and FA64 bit. This register is set up per_world |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 52 | * to be the least restrictive, then lower ELs can restrict as needed |
| 53 | * using SMCR_EL2 and SMCR_EL1. |
| 54 | */ |
Boyan Karatotev | 6468d4a | 2023-02-16 15:12:45 +0000 | [diff] [blame] | 55 | smcr_el3 = SMCR_ELX_LEN_MAX; |
Jayanth Dodderi Chidanand | 605419a | 2023-03-06 23:56:14 +0000 | [diff] [blame] | 56 | if (read_feat_sme_fa64_id_field() != 0U) { |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 57 | VERBOSE("[SME] FA64 enabled\n"); |
Boyan Karatotev | 6468d4a | 2023-02-16 15:12:45 +0000 | [diff] [blame] | 58 | smcr_el3 |= SMCR_ELX_FA64_BIT; |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 59 | } |
Jayanth Dodderi Chidanand | cfe053a | 2022-11-08 10:31:07 +0000 | [diff] [blame] | 60 | |
| 61 | /* |
| 62 | * Enable access to ZT0 register. |
| 63 | * Make sure FEAT_SME2 is supported by the hardware before continuing. |
| 64 | * If supported, Set the EZT0 bit in SMCR_EL3 to allow instructions to |
| 65 | * access ZT0 register without trapping. |
| 66 | */ |
| 67 | if (is_feat_sme2_supported()) { |
| 68 | VERBOSE("SME2 enabled\n"); |
Boyan Karatotev | 6468d4a | 2023-02-16 15:12:45 +0000 | [diff] [blame] | 69 | smcr_el3 |= SMCR_ELX_EZT0_BIT; |
Jayanth Dodderi Chidanand | cfe053a | 2022-11-08 10:31:07 +0000 | [diff] [blame] | 70 | } |
Boyan Karatotev | 6468d4a | 2023-02-16 15:12:45 +0000 | [diff] [blame] | 71 | write_smcr_el3(smcr_el3); |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 72 | |
| 73 | /* Reset CPTR_EL3 value. */ |
| 74 | write_cptr_el3(cptr_el3); |
Boyan Karatotev | be028b4 | 2022-10-13 13:51:05 +0100 | [diff] [blame] | 75 | isb(); |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 76 | } |
| 77 | |
Boyan Karatotev | 6468d4a | 2023-02-16 15:12:45 +0000 | [diff] [blame] | 78 | void sme_init_el2_unused(void) |
| 79 | { |
| 80 | /* |
| 81 | * CPTR_EL2.TCPAC: Set to zero so that Non-secure EL1 accesses to the |
| 82 | * CPACR_EL1 or CPACR from both Execution states do not trap to EL2. |
| 83 | */ |
| 84 | write_cptr_el2(read_cptr_el2() & ~CPTR_EL2_TCPAC_BIT); |
| 85 | } |
| 86 | |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 87 | void sme_disable(cpu_context_t *context) |
| 88 | { |
| 89 | u_register_t reg; |
| 90 | el3_state_t *state; |
| 91 | |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 92 | /* Get the context state. */ |
| 93 | state = get_el3state_ctx(context); |
| 94 | |
johpow01 | 9baade3 | 2021-07-08 14:14:00 -0500 | [diff] [blame] | 95 | /* Disable access to TPIDR2_EL0. */ |
| 96 | reg = read_ctx_reg(state, CTX_SCR_EL3); |
| 97 | reg &= ~SCR_ENTP2_BIT; |
| 98 | write_ctx_reg(state, CTX_SCR_EL3, reg); |
| 99 | } |
Elizabeth Ho | 4fc00d2 | 2023-07-18 14:10:25 +0100 | [diff] [blame] | 100 | |
| 101 | void sme_disable_per_world(per_world_context_t *per_world_ctx) |
| 102 | { |
| 103 | u_register_t reg; |
| 104 | |
| 105 | /* Disable SME, SVE, and FPU since they all share registers. */ |
| 106 | reg = per_world_ctx->ctx_cptr_el3; |
| 107 | reg &= ~ESM_BIT; /* Trap SME */ |
| 108 | reg &= ~CPTR_EZ_BIT; /* Trap SVE */ |
| 109 | reg |= TFP_BIT; /* Trap FPU/SIMD */ |
| 110 | per_world_ctx->ctx_cptr_el3 = reg; |
| 111 | } |