blob: 317ececd687c73434d230195c5e53090a6c14a61 [file] [log] [blame]
Imre Kis64476932020-11-23 03:15:47 +01001// SPDX-License-Identifier: BSD-3-Clause
2/*
Balint Dobszay40410ab2022-01-19 16:31:02 +01003 * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
Imre Kis64476932020-11-23 03:15:47 +01004 */
5
6#include "sp_rxtx.h"
7#include "ffa_api.h"
8#include <assert.h>
9#include <stdlib.h>
10#include <stdlib.h>
11
Imre Kisce67e652021-01-12 22:23:01 +010012static void *ffa_tx_buffer;
13static const void *ffa_rx_buffer;
14static size_t ffa_rxtx_size;
Imre Kis64476932020-11-23 03:15:47 +010015
16sp_result sp_rxtx_buffer_map(void *tx_buffer, const void *rx_buffer,
17 size_t size)
18{
19 uintptr_t alignment_mask = 0;
20 sp_result sp_res = SP_RESULT_OK;
21 ffa_result result = FFA_OK;
22 uint32_t page_count = 0;
23
24 /* Checking for invalid parameters*/
25 if (!tx_buffer || !rx_buffer || !size)
26 return SP_RESULT_INVALID_PARAMETERS;
27
28 /* Checking if the buffers are already mapped */
29 if (ffa_rxtx_size)
30 return SP_RESULT_INVALID_STATE;
31
32 /* Querying alignment size */
33 sp_res = sp_rxtx_buffer_alignment_boundary_get(&alignment_mask);
34 if (sp_res != SP_RESULT_OK)
35 return sp_res;
36
37 /* Creating a binary mask from the size */
38 alignment_mask = alignment_mask - 1;
39
40 /* Checking buffer and size alignment */
41 if (((uintptr_t)tx_buffer & alignment_mask) != 0 ||
42 ((uintptr_t)rx_buffer & alignment_mask) != 0 ||
43 (size & alignment_mask) != 0)
44 return SP_RESULT_INVALID_PARAMETERS;
45
46 /* Checking max page count for RXTX buffers */
47 page_count = size / FFA_RXTX_MAP_PAGE_SIZE;
Imre Kis3924b1b2021-01-12 22:23:17 +010048 if (page_count > FFA_RXTX_MAP_PAGE_COUNT_MAX)
Imre Kis64476932020-11-23 03:15:47 +010049 return SP_RESULT_INVALID_PARAMETERS;
50
51 /* Mapping the buffers */
52 result = ffa_rxtx_map(tx_buffer, rx_buffer, page_count);
53 if (result != FFA_OK)
54 return SP_RESULT_FFA(result);
55
56 /* Storing the buffer pointers and size internally */
57 ffa_tx_buffer = tx_buffer;
58 ffa_rx_buffer = rx_buffer;
59 ffa_rxtx_size = size;
60
61 return SP_RESULT_OK;
62}
63
64sp_result sp_rxtx_buffer_unmap(void)
65{
66 ffa_result result = FFA_OK;
67 uint16_t id = 0;
68
69 /* Checking if the buffers are not yet mapped */
70 if (!ffa_rxtx_size)
71 return SP_RESULT_INVALID_STATE;
72
73 result = ffa_id_get(&id);
74 if (result != FFA_OK)
75 return SP_RESULT_FFA(result);
76
77 /* Unmapping the buffers */
78 result = ffa_rxtx_unmap(id);
79 if (result != FFA_OK)
80 return SP_RESULT_FFA(result);
81
82 /* Clearing internally stored buffer pointers and size */
83 ffa_tx_buffer = NULL;
84 ffa_rx_buffer = NULL;
85 ffa_rxtx_size = 0;
86
87 return SP_RESULT_OK;
88}
89
90sp_result sp_rxtx_buffer_alignment_boundary_get(uintptr_t *alignment)
91{
Imre Kis0202c9f2021-01-12 22:49:34 +010092 struct ffa_interface_properties interface_props = { 0 };
Imre Kis64476932020-11-23 03:15:47 +010093 uint32_t *props = NULL;
94 ffa_result result = FFA_OK;
95 uint32_t granularity = 0;
96
97 /* Checking for invalid parameters */
98 if (!alignment)
99 return SP_RESULT_INVALID_PARAMETERS;
100
101 /* Querying FFX_RXTX_MAP features */
Balint Dobszay40410ab2022-01-19 16:31:02 +0100102 result = ffa_features(FFA_RXTX_MAP_64, &interface_props);
Imre Kis64476932020-11-23 03:15:47 +0100103 if (result != FFA_OK) {
104 *alignment = 0;
105 return SP_RESULT_FFA(result);
106 }
107
108 props = interface_props.interface_properties;
109 granularity = props[FFA_FEATURES_RXTX_MAP_GRANULARITY_INDEX];
110 granularity = (granularity >> FFA_FEATURES_RXTX_MAP_GRANULARITY_SHIFT) &
111 FFA_FEATURES_RXTX_MAP_GRANULARITY_MASK;
112
113 switch (granularity) {
114 case FFA_FEATURES_RXTX_MAP_GRANULARITY_4K:
115 *alignment = 4 * 1024;
116 break;
117
118 case FFA_FEATURES_RXTX_MAP_GRANULARITY_64K:
119 *alignment = 64 * 1024;
120 break;
121
122 case FFA_FEATURES_RXTX_MAP_GRANULARITY_16K:
123 *alignment = 16 * 1024;
124 break;
125
126 default:
127 *alignment = 0;
128 return SP_RESULT_INTERNAL_ERROR;
129 }
130
131 return SP_RESULT_OK;
132}
133
134sp_result sp_rxtx_buffer_rx_get(const void **buffer, size_t *size)
135{
136 if (!buffer || !size)
137 return SP_RESULT_INVALID_PARAMETERS;
138
139 if (!ffa_rxtx_size)
140 return SP_RESULT_INVALID_STATE;
141
142 *buffer = ffa_rx_buffer;
143 *size = ffa_rxtx_size;
144
145 return SP_RESULT_OK;
146}
147
148sp_result sp_rxtx_buffer_tx_get(void **buffer, size_t *size)
149{
150 if (!buffer || !size)
151 return SP_RESULT_INVALID_PARAMETERS;
152
153 if (!ffa_rxtx_size)
154 return SP_RESULT_INVALID_STATE;
155
156 *buffer = ffa_tx_buffer;
157 *size = ffa_rxtx_size;
158
159 return SP_RESULT_OK;
160}