blob: 9652b4520f9b2a462a6879c0ca7ea56d39b88d8c [file] [log] [blame]
johpow0150ccb552020-11-10 19:22:13 -06001/*
2 * Copyright (c) 2021, Arm Limited. All rights reserved.
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
17test_result_t test_sme_support(void)
18{
19 /* SME is an AArch64-only feature.*/
20 SKIP_TEST_IF_AARCH32();
21
22#ifdef __aarch64__
23 u_register_t reg;
24 unsigned int current_vector_len;
25 unsigned int requested_vector_len;
26 unsigned int len_max;
27
28 /* Skip the test if SME is not supported. */
29 if (!feat_sme_supported()) {
30 INFO("SME not supported, skipping.\n");
31 return TEST_RESULT_SKIPPED;
32 }
33
34 /* Enable SME for use at NS EL2. */
35 if (sme_enable() != 0) {
36 ERROR("Could not enable SME.\n");
37 return TEST_RESULT_FAIL;
38 }
Boyan Karatotev22248c82022-10-13 14:05:41 +010039 isb();
johpow0150ccb552020-11-10 19:22:13 -060040
41 /* Make sure TPIDR2_EL0 is accessible. */
42 write_tpidr2_el0(0);
43 if (read_tpidr2_el0() != 0) {
44 ERROR("Could not read TPIDR2_EL0.\n");
45 return TEST_RESULT_FAIL;
46 }
47 write_tpidr2_el0(0xb0bafe77);
48 if (read_tpidr2_el0() != 0xb0bafe77) {
49 ERROR("Could not write TPIDR2_EL0.\n");
50 return TEST_RESULT_FAIL;
51 }
52
53 /* Make sure we can start and stop streaming mode. */
54 VERBOSE("Entering Streaming SVE mode.\n");
55 sme_smstart(false);
56 read_smcr_el2();
57 sme_smstop(false);
58 sme_smstart(true);
59 read_smcr_el2();
60 sme_smstop(true);
61
62 /*
63 * Iterate through values for LEN to detect supported vector lengths.
64 * SME instructions aren't supported by GCC yet so for now this is all
65 * we'll do.
66 */
67 sme_smstart(false);
68
69 /* Write SMCR_EL2 with the LEN max to find implemented width. */
70 write_smcr_el2(SME_SMCR_LEN_MAX);
71 len_max = (unsigned int)read_smcr_el2();
72 VERBOSE("Maximum SMCR_EL2.LEN value: 0x%x\n", len_max);
73 VERBOSE("Enumerating supported vector lengths...\n");
74 for (unsigned int i = 0; i <= len_max; i++) {
75 /* Load new value into SMCR_EL2.LEN */
76 reg = read_smcr_el2();
77 reg &= ~(SMCR_ELX_LEN_MASK << SMCR_ELX_LEN_SHIFT);
78 reg |= (i << SMCR_ELX_LEN_SHIFT);
79 write_smcr_el2(reg);
80
81 /* Compute current and requested vector lengths in bits. */
82 current_vector_len = ((unsigned int)sme_rdvl_1() * 8U);
83 requested_vector_len = (i+1U)*128U;
84
85 /*
86 * We count down from the maximum SMLEN value, so if the values
87 * match, we've found the largest supported value for SMLEN.
88 */
89 if (current_vector_len == requested_vector_len) {
90 VERBOSE("SUPPORTED: %u bits (LEN=%u)\n", requested_vector_len, i);
91 } else {
92 VERBOSE("NOT SUPPORTED: %u bits (LEN=%u)\n", requested_vector_len, i);
93 }
94 }
95 sme_smstop(false);
96
97 /* If FEAT_SME_FA64 then attempt to execute an illegal instruction. */
98 if (feat_sme_fa64_supported()) {
99 VERBOSE("FA64 supported, trying illegal instruction.\n");
100 sme_try_illegal_instruction();
101 }
102
103 return TEST_RESULT_SUCCESS;
104#endif /* __aarch64__ */
105}