blob: 4bf6e59edb9a0b81c62069763d7836a8268678ad [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 }
39
40 /* Make sure TPIDR2_EL0 is accessible. */
41 write_tpidr2_el0(0);
42 if (read_tpidr2_el0() != 0) {
43 ERROR("Could not read TPIDR2_EL0.\n");
44 return TEST_RESULT_FAIL;
45 }
46 write_tpidr2_el0(0xb0bafe77);
47 if (read_tpidr2_el0() != 0xb0bafe77) {
48 ERROR("Could not write TPIDR2_EL0.\n");
49 return TEST_RESULT_FAIL;
50 }
51
52 /* Make sure we can start and stop streaming mode. */
53 VERBOSE("Entering Streaming SVE mode.\n");
54 sme_smstart(false);
55 read_smcr_el2();
56 sme_smstop(false);
57 sme_smstart(true);
58 read_smcr_el2();
59 sme_smstop(true);
60
61 /*
62 * Iterate through values for LEN to detect supported vector lengths.
63 * SME instructions aren't supported by GCC yet so for now this is all
64 * we'll do.
65 */
66 sme_smstart(false);
67
68 /* Write SMCR_EL2 with the LEN max to find implemented width. */
69 write_smcr_el2(SME_SMCR_LEN_MAX);
70 len_max = (unsigned int)read_smcr_el2();
71 VERBOSE("Maximum SMCR_EL2.LEN value: 0x%x\n", len_max);
72 VERBOSE("Enumerating supported vector lengths...\n");
73 for (unsigned int i = 0; i <= len_max; i++) {
74 /* Load new value into SMCR_EL2.LEN */
75 reg = read_smcr_el2();
76 reg &= ~(SMCR_ELX_LEN_MASK << SMCR_ELX_LEN_SHIFT);
77 reg |= (i << SMCR_ELX_LEN_SHIFT);
78 write_smcr_el2(reg);
79
80 /* Compute current and requested vector lengths in bits. */
81 current_vector_len = ((unsigned int)sme_rdvl_1() * 8U);
82 requested_vector_len = (i+1U)*128U;
83
84 /*
85 * We count down from the maximum SMLEN value, so if the values
86 * match, we've found the largest supported value for SMLEN.
87 */
88 if (current_vector_len == requested_vector_len) {
89 VERBOSE("SUPPORTED: %u bits (LEN=%u)\n", requested_vector_len, i);
90 } else {
91 VERBOSE("NOT SUPPORTED: %u bits (LEN=%u)\n", requested_vector_len, i);
92 }
93 }
94 sme_smstop(false);
95
96 /* If FEAT_SME_FA64 then attempt to execute an illegal instruction. */
97 if (feat_sme_fa64_supported()) {
98 VERBOSE("FA64 supported, trying illegal instruction.\n");
99 sme_try_illegal_instruction();
100 }
101
102 return TEST_RESULT_SUCCESS;
103#endif /* __aarch64__ */
104}