aboutsummaryrefslogtreecommitdiff
path: root/components/messaging/ffa/libsp/sp_rxtx.c
blob: fb88f73b83212fccf50cefefe5b3e471ebfd53ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// SPDX-License-Identifier: BSD-3-Clause
/*
 * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
 */

#include "sp_rxtx.h"
#include "ffa_api.h"
#include <assert.h>
#include <stdlib.h>
#include <stdlib.h>

static void *ffa_tx_buffer;
static const void *ffa_rx_buffer;
static size_t ffa_rxtx_size;

sp_result sp_rxtx_buffer_map(void *tx_buffer, const void *rx_buffer,
			     size_t size)
{
	uintptr_t alignment_mask = 0;
	sp_result sp_res = SP_RESULT_OK;
	ffa_result result = FFA_OK;
	uint32_t page_count = 0;

	/* Checking for invalid parameters*/
	if (!tx_buffer || !rx_buffer || !size)
		return SP_RESULT_INVALID_PARAMETERS;

	/* Checking if the buffers are already mapped */
	if (ffa_rxtx_size)
		return SP_RESULT_INVALID_STATE;

	/* Querying alignment size */
	sp_res = sp_rxtx_buffer_alignment_boundary_get(&alignment_mask);
	if (sp_res != SP_RESULT_OK)
		return sp_res;

	/* Creating a binary mask from the size */
	alignment_mask = alignment_mask - 1;

	/* Checking buffer and size alignment */
	if (((uintptr_t)tx_buffer & alignment_mask) != 0 ||
	    ((uintptr_t)rx_buffer & alignment_mask) != 0 ||
	    (size & alignment_mask) != 0)
		return SP_RESULT_INVALID_PARAMETERS;

	/* Checking max page count for RXTX buffers */
	page_count = size / FFA_RXTX_MAP_PAGE_SIZE;
	if (page_count > FFA_RXTX_MAP_PAGE_COUNT_MAX)
		return SP_RESULT_INVALID_PARAMETERS;

	/* Mapping the buffers */
	result = ffa_rxtx_map(tx_buffer, rx_buffer, page_count);
	if (result != FFA_OK)
		return SP_RESULT_FFA(result);

	/* Storing the buffer pointers and size internally */
	ffa_tx_buffer = tx_buffer;
	ffa_rx_buffer = rx_buffer;
	ffa_rxtx_size = size;

	return SP_RESULT_OK;
}

sp_result sp_rxtx_buffer_unmap(void)
{
	ffa_result result = FFA_OK;
	uint16_t id = 0;

	/* Checking if the buffers are not yet mapped */
	if (!ffa_rxtx_size)
		return SP_RESULT_INVALID_STATE;

	result = ffa_id_get(&id);
	if (result != FFA_OK)
		return SP_RESULT_FFA(result);

	/* Unmapping the buffers */
	result = ffa_rxtx_unmap(id);
	if (result != FFA_OK)
		return SP_RESULT_FFA(result);

	/* Clearing internally stored buffer pointers and size */
	ffa_tx_buffer = NULL;
	ffa_rx_buffer = NULL;
	ffa_rxtx_size = 0;

	return SP_RESULT_OK;
}

sp_result sp_rxtx_buffer_alignment_boundary_get(uintptr_t *alignment)
{
	struct ffa_interface_properties interface_props = { 0 };
	uint32_t *props = NULL;
	ffa_result result = FFA_OK;
	uint32_t granularity = 0;

	/* Checking for invalid parameters */
	if (!alignment)
		return SP_RESULT_INVALID_PARAMETERS;

	/* Querying FFX_RXTX_MAP features */
	result = ffa_features(FFA_RXTX_MAP_32, &interface_props);
	if (result != FFA_OK) {
		*alignment = 0;
		return SP_RESULT_FFA(result);
	}

	props = interface_props.interface_properties;
	granularity = props[FFA_FEATURES_RXTX_MAP_GRANULARITY_INDEX];
	granularity = (granularity >> FFA_FEATURES_RXTX_MAP_GRANULARITY_SHIFT) &
		      FFA_FEATURES_RXTX_MAP_GRANULARITY_MASK;

	switch (granularity) {
	case FFA_FEATURES_RXTX_MAP_GRANULARITY_4K:
		*alignment = 4 * 1024;
		break;

	case FFA_FEATURES_RXTX_MAP_GRANULARITY_64K:
		*alignment = 64 * 1024;
		break;

	case FFA_FEATURES_RXTX_MAP_GRANULARITY_16K:
		*alignment = 16 * 1024;
		break;

	default:
		*alignment = 0;
		return SP_RESULT_INTERNAL_ERROR;
	}

	return SP_RESULT_OK;
}

sp_result sp_rxtx_buffer_rx_get(const void **buffer, size_t *size)
{
	if (!buffer || !size)
		return SP_RESULT_INVALID_PARAMETERS;

	if (!ffa_rxtx_size)
		return SP_RESULT_INVALID_STATE;

	*buffer = ffa_rx_buffer;
	*size = ffa_rxtx_size;

	return SP_RESULT_OK;
}

sp_result sp_rxtx_buffer_tx_get(void **buffer, size_t *size)
{
	if (!buffer || !size)
		return SP_RESULT_INVALID_PARAMETERS;

	if (!ffa_rxtx_size)
		return SP_RESULT_INVALID_STATE;

	*buffer = ffa_tx_buffer;
	*size = ffa_rxtx_size;

	return SP_RESULT_OK;
}