blob: 58690ea8c56a312e1a5fe476c5d07005b048905c [file] [log] [blame]
johpow0150ccb552020-11-10 19:22:13 -06001/*
Jayanth Dodderi Chidanandb3ffd3c2023-02-13 12:15:11 +00002 * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
johpow0150ccb552020-11-10 19:22:13 -06003 *
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 Chidanandb3ffd3c2023-02-13 12:15:11 +000017#ifdef __aarch64__
18
19/* Global buffers*/
20static uint64_t ZA_In_vector[8] = {0xaaff, 0xbbff, 0xccff, 0xddff, 0xeeff,
21 0xffff, 0xff00, 0xff00};
22static 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 */
30static 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 */
49static 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
johpow0150ccb552020-11-10 19:22:13 -060064test_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 Chidanandb3ffd3c2023-02-13 12:15:11 +000074 unsigned int __unused svl_max = 0U;
johpow0150ccb552020-11-10 19:22:13 -060075
76 /* Skip the test if SME is not supported. */
Jayanth Dodderi Chidanandb3ffd3c2023-02-13 12:15:11 +000077 SKIP_TEST_IF_SME_NOT_SUPPORTED();
johpow0150ccb552020-11-10 19:22:13 -060078
79 /* Enable SME for use at NS EL2. */
Jayanth Dodderi Chidanandb3ffd3c2023-02-13 12:15:11 +000080 sme_enable();
johpow0150ccb552020-11-10 19:22:13 -060081
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
johpow0150ccb552020-11-10 19:22:13 -060094 /*
95 * Iterate through values for LEN to detect supported vector lengths.
johpow0150ccb552020-11-10 19:22:13 -060096 */
Jayanth Dodderi Chidanandb3ffd3c2023-02-13 12:15:11 +000097
98 /* Entering Streaming SVE mode */
99 sme_smstart(SMSTART_SM);
johpow0150ccb552020-11-10 19:22:13 -0600100
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 Chidanandb3ffd3c2023-02-13 12:15:11 +0000122 svl_max = current_vector_len;
johpow0150ccb552020-11-10 19:22:13 -0600123 VERBOSE("SUPPORTED: %u bits (LEN=%u)\n", requested_vector_len, i);
124 } else {
Jayanth Dodderi Chidanandb3ffd3c2023-02-13 12:15:11 +0000125 VERBOSE("NOT SUPPORTED: %u bits (LEN=%u)\n", requested_vector_len, i);
johpow0150ccb552020-11-10 19:22:13 -0600126 }
127 }
Jayanth Dodderi Chidanandb3ffd3c2023-02-13 12:15:11 +0000128
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);
johpow0150ccb552020-11-10 19:22:13 -0600161
162 /* If FEAT_SME_FA64 then attempt to execute an illegal instruction. */
Jayanth Dodderi Chidanandb3ffd3c2023-02-13 12:15:11 +0000163 if (is_feat_sme_fa64_supported()) {
johpow0150ccb552020-11-10 19:22:13 -0600164 VERBOSE("FA64 supported, trying illegal instruction.\n");
165 sme_try_illegal_instruction();
166 }
167
168 return TEST_RESULT_SUCCESS;
169#endif /* __aarch64__ */
170}