johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 1 | /* |
Jayanth Dodderi Chidanand | b3ffd3c | 2023-02-13 12:15:11 +0000 | [diff] [blame^] | 2 | * Copyright (c) 2021-2023, Arm Limited. All rights reserved. |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
| 6 | |
| 7 | #include <stdbool.h> |
| 8 | #include <stdio.h> |
| 9 | #include <stdlib.h> |
| 10 | |
| 11 | #include <arch_features.h> |
| 12 | #include <arch_helpers.h> |
| 13 | #include <lib/extensions/sme.h> |
| 14 | #include <test_helpers.h> |
| 15 | #include <tftf_lib.h> |
| 16 | |
Jayanth Dodderi Chidanand | b3ffd3c | 2023-02-13 12:15:11 +0000 | [diff] [blame^] | 17 | #ifdef __aarch64__ |
| 18 | |
| 19 | /* Global buffers*/ |
| 20 | static uint64_t ZA_In_vector[8] = {0xaaff, 0xbbff, 0xccff, 0xddff, 0xeeff, |
| 21 | 0xffff, 0xff00, 0xff00}; |
| 22 | static uint64_t ZA_Out_vector[8] = {0}; |
| 23 | |
| 24 | |
| 25 | /** |
| 26 | * sme_zero_ZA |
| 27 | * ZER0 : Zero a list of upto eight 64bit element ZA tiles. |
| 28 | * ZERO {<mask>} , where mask=ff, to clear all the 8, 64 bit elements. |
| 29 | */ |
| 30 | static void sme_zero_ZA(void) |
| 31 | { |
| 32 | /** |
| 33 | * Due to the lack of support from the toolchain, instruction |
| 34 | * opcodes are used here. |
| 35 | * Manual Encoding Instruction, to Zero all the tiles of ZA array. |
| 36 | * |
| 37 | * TODO: Further, once the toolchain adds support for SME features |
| 38 | * this could be replaced with the actual instruction ZERO { <mask>}. |
| 39 | */ |
| 40 | asm volatile(".inst 0xc008000f" : : : ); |
| 41 | } |
| 42 | |
| 43 | /** |
| 44 | * This function compares two buffers/vector elements |
| 45 | * Inputs: uint64_t *ZA_In_vector, ZA_Out_vector |
| 46 | * @return true : If both are equal |
| 47 | * @return false : If both are not equal |
| 48 | */ |
| 49 | static bool sme_cmp_vector(const uint64_t *ZA_In_vector, const uint64_t *ZA_Out_vector) |
| 50 | { |
| 51 | bool ret = true; |
| 52 | |
| 53 | for (int i = 0; i < (MAX_VL_B/8); i++) { |
| 54 | if (ZA_In_vector[i] != ZA_Out_vector[i]) { |
| 55 | ret = false; |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | return ret; |
| 60 | } |
| 61 | |
| 62 | #endif /* __aarch64__ */ |
| 63 | |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 64 | test_result_t test_sme_support(void) |
| 65 | { |
| 66 | /* SME is an AArch64-only feature.*/ |
| 67 | SKIP_TEST_IF_AARCH32(); |
| 68 | |
| 69 | #ifdef __aarch64__ |
| 70 | u_register_t reg; |
| 71 | unsigned int current_vector_len; |
| 72 | unsigned int requested_vector_len; |
| 73 | unsigned int len_max; |
Jayanth Dodderi Chidanand | b3ffd3c | 2023-02-13 12:15:11 +0000 | [diff] [blame^] | 74 | unsigned int __unused svl_max = 0U; |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 75 | |
| 76 | /* Skip the test if SME is not supported. */ |
Jayanth Dodderi Chidanand | b3ffd3c | 2023-02-13 12:15:11 +0000 | [diff] [blame^] | 77 | SKIP_TEST_IF_SME_NOT_SUPPORTED(); |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 78 | |
| 79 | /* Enable SME for use at NS EL2. */ |
Jayanth Dodderi Chidanand | b3ffd3c | 2023-02-13 12:15:11 +0000 | [diff] [blame^] | 80 | sme_enable(); |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 81 | |
| 82 | /* Make sure TPIDR2_EL0 is accessible. */ |
| 83 | write_tpidr2_el0(0); |
| 84 | if (read_tpidr2_el0() != 0) { |
| 85 | ERROR("Could not read TPIDR2_EL0.\n"); |
| 86 | return TEST_RESULT_FAIL; |
| 87 | } |
| 88 | write_tpidr2_el0(0xb0bafe77); |
| 89 | if (read_tpidr2_el0() != 0xb0bafe77) { |
| 90 | ERROR("Could not write TPIDR2_EL0.\n"); |
| 91 | return TEST_RESULT_FAIL; |
| 92 | } |
| 93 | |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 94 | /* |
| 95 | * Iterate through values for LEN to detect supported vector lengths. |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 96 | */ |
Jayanth Dodderi Chidanand | b3ffd3c | 2023-02-13 12:15:11 +0000 | [diff] [blame^] | 97 | |
| 98 | /* Entering Streaming SVE mode */ |
| 99 | sme_smstart(SMSTART_SM); |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 100 | |
| 101 | /* Write SMCR_EL2 with the LEN max to find implemented width. */ |
| 102 | write_smcr_el2(SME_SMCR_LEN_MAX); |
| 103 | len_max = (unsigned int)read_smcr_el2(); |
| 104 | VERBOSE("Maximum SMCR_EL2.LEN value: 0x%x\n", len_max); |
| 105 | VERBOSE("Enumerating supported vector lengths...\n"); |
| 106 | for (unsigned int i = 0; i <= len_max; i++) { |
| 107 | /* Load new value into SMCR_EL2.LEN */ |
| 108 | reg = read_smcr_el2(); |
| 109 | reg &= ~(SMCR_ELX_LEN_MASK << SMCR_ELX_LEN_SHIFT); |
| 110 | reg |= (i << SMCR_ELX_LEN_SHIFT); |
| 111 | write_smcr_el2(reg); |
| 112 | |
| 113 | /* Compute current and requested vector lengths in bits. */ |
| 114 | current_vector_len = ((unsigned int)sme_rdvl_1() * 8U); |
| 115 | requested_vector_len = (i+1U)*128U; |
| 116 | |
| 117 | /* |
| 118 | * We count down from the maximum SMLEN value, so if the values |
| 119 | * match, we've found the largest supported value for SMLEN. |
| 120 | */ |
| 121 | if (current_vector_len == requested_vector_len) { |
Jayanth Dodderi Chidanand | b3ffd3c | 2023-02-13 12:15:11 +0000 | [diff] [blame^] | 122 | svl_max = current_vector_len; |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 123 | VERBOSE("SUPPORTED: %u bits (LEN=%u)\n", requested_vector_len, i); |
| 124 | } else { |
Jayanth Dodderi Chidanand | b3ffd3c | 2023-02-13 12:15:11 +0000 | [diff] [blame^] | 125 | VERBOSE("NOT SUPPORTED: %u bits (LEN=%u)\n", requested_vector_len, i); |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 126 | } |
| 127 | } |
Jayanth Dodderi Chidanand | b3ffd3c | 2023-02-13 12:15:11 +0000 | [diff] [blame^] | 128 | |
| 129 | INFO("Largest Supported Streaming Vector Length(SVL): %u bits \n", svl_max); |
| 130 | |
| 131 | /* Exiting Streaming SVE mode */ |
| 132 | sme_smstop(SMSTOP_SM); |
| 133 | |
| 134 | /** |
| 135 | * Perform/Execute SME Instructions. |
| 136 | * SME Data processing instructions LDR, STR, and ZERO instructions that |
| 137 | * access the SME ZA storage are legal only if ZA is enabled. |
| 138 | */ |
| 139 | |
| 140 | /* Enable SME ZA Array Storage */ |
| 141 | sme_smstart(SMSTART_ZA); |
| 142 | |
| 143 | /* LDR : Load vector to ZA Array */ |
| 144 | sme_vector_to_ZA(ZA_In_vector); |
| 145 | |
| 146 | /* STR : Store Vector from ZA Array. */ |
| 147 | sme_ZA_to_vector(ZA_Out_vector); |
| 148 | |
| 149 | /* Compare both vectors to ensure load and store instructions have |
| 150 | * executed precisely. |
| 151 | */ |
| 152 | if (!sme_cmp_vector(ZA_In_vector, ZA_Out_vector)) { |
| 153 | return TEST_RESULT_FAIL; |
| 154 | } |
| 155 | |
| 156 | /* Zero or clear the entire ZA Array Storage/Tile */ |
| 157 | sme_zero_ZA(); |
| 158 | |
| 159 | /* Disable the SME ZA array storage. */ |
| 160 | sme_smstop(SMSTOP_ZA); |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 161 | |
| 162 | /* If FEAT_SME_FA64 then attempt to execute an illegal instruction. */ |
Jayanth Dodderi Chidanand | b3ffd3c | 2023-02-13 12:15:11 +0000 | [diff] [blame^] | 163 | if (is_feat_sme_fa64_supported()) { |
johpow01 | 50ccb55 | 2020-11-10 19:22:13 -0600 | [diff] [blame] | 164 | VERBOSE("FA64 supported, trying illegal instruction.\n"); |
| 165 | sme_try_illegal_instruction(); |
| 166 | } |
| 167 | |
| 168 | return TEST_RESULT_SUCCESS; |
| 169 | #endif /* __aarch64__ */ |
| 170 | } |