blob: 698e78be30e5672f2839cc92b989b5d55273d700 [file] [log] [blame]
Arunachalam Ganapathy0bbdc2d2023-04-05 15:30:18 +01001/*
2 * Copyright (c) 2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_features.h>
8#include <arch_helpers.h>
9#include <assert.h>
10#include <debug.h>
11#include <lib/extensions/sve.h>
12
13static inline uint64_t sve_read_zcr_elx(void)
14{
15 return IS_IN_EL2() ? read_zcr_el2() : read_zcr_el1();
16}
17
18static inline void sve_write_zcr_elx(uint64_t reg_val)
19{
20 if (IS_IN_EL2()) {
21 write_zcr_el2(reg_val);
22 } else {
23 write_zcr_el1(reg_val);
24 }
25 isb();
26}
27
28static void _sve_config_vq(uint8_t sve_vq)
29{
30 u_register_t zcr_elx;
31
32 zcr_elx = sve_read_zcr_elx();
33 if (IS_IN_EL2()) {
34 zcr_elx &= ~(MASK(ZCR_EL2_SVE_VL));
35 zcr_elx |= INPLACE(ZCR_EL2_SVE_VL, sve_vq);
36 } else {
37 zcr_elx &= ~(MASK(ZCR_EL1_SVE_VL));
38 zcr_elx |= INPLACE(ZCR_EL1_SVE_VL, sve_vq);
39 }
40 sve_write_zcr_elx(zcr_elx);
41}
42
43/* Set the SVE vector length in the current EL's ZCR_ELx register */
44void sve_config_vq(uint8_t sve_vq)
45{
46 assert(is_armv8_2_sve_present());
47
48 /* cap vq to arch supported max value */
49 if (sve_vq > SVE_VQ_ARCH_MAX) {
50 sve_vq = SVE_VQ_ARCH_MAX;
51 }
52
53 _sve_config_vq(sve_vq);
54}
55
56/*
57 * Probes all valid vector length upto 'sve_max_vq'. Configures ZCR_ELx with 0
58 * to 'sve_max_vq'. And for each step, call sve_rdvl to get the vector length.
59 * Convert the vector length to VQ and set the bit corresponding to the VQ.
60 * Returns:
61 * bitmap corresponding to each support VL
62 */
63uint32_t sve_probe_vl(uint8_t sve_max_vq)
64{
65 uint32_t vl_bitmap = 0;
66 uint8_t vq, rdvl_vq;
67
68 assert(is_armv8_2_sve_present());
69
70 /* cap vq to arch supported max value */
71 if (sve_max_vq > SVE_VQ_ARCH_MAX) {
72 sve_max_vq = SVE_VQ_ARCH_MAX;
73 }
74
75 for (vq = 0; vq <= sve_max_vq; vq++) {
76 _sve_config_vq(vq);
77 rdvl_vq = SVE_VL_TO_VQ(sve_vector_length_get());
78 if (vl_bitmap & BIT_32(rdvl_vq)) {
79 continue;
80 }
81 vl_bitmap |= BIT_32(rdvl_vq);
82 }
83
84 return vl_bitmap;
85}