1*30feb38aSMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause
2*30feb38aSMarouene Boubakri /*
3*30feb38aSMarouene Boubakri * Copyright 2025 NXP
4*30feb38aSMarouene Boubakri */
5*30feb38aSMarouene Boubakri
6*30feb38aSMarouene Boubakri #include <kernel/misc.h>
7*30feb38aSMarouene Boubakri #include <mm/core_memprot.h>
8*30feb38aSMarouene Boubakri #include <sbi.h>
9*30feb38aSMarouene Boubakri #include <sbi_mpxy.h>
10*30feb38aSMarouene Boubakri #include <string.h>
11*30feb38aSMarouene Boubakri
12*30feb38aSMarouene Boubakri /*
13*30feb38aSMarouene Boubakri * struct mpxy_core_local - MPXY per-hart local context
14*30feb38aSMarouene Boubakri * @shmem: Virtual base address of MPXY shared memory
15*30feb38aSMarouene Boubakri * @shmem_pa: Physical base address of MPXY shared memory
16*30feb38aSMarouene Boubakri * @shmem_active:Indicates whether shared memory is active for this hart
17*30feb38aSMarouene Boubakri *
18*30feb38aSMarouene Boubakri * Holds MPXY-related per-hart data required for message exchange via
19*30feb38aSMarouene Boubakri * the SBI MPXY extension.
20*30feb38aSMarouene Boubakri */
21*30feb38aSMarouene Boubakri struct mpxy_core_local {
22*30feb38aSMarouene Boubakri void *shmem;
23*30feb38aSMarouene Boubakri paddr_t shmem_pa;
24*30feb38aSMarouene Boubakri bool shmem_active;
25*30feb38aSMarouene Boubakri };
26*30feb38aSMarouene Boubakri
27*30feb38aSMarouene Boubakri static struct mpxy_core_local mpxy_core_local_array[CFG_TEE_CORE_NB_CORE];
28*30feb38aSMarouene Boubakri
mpxy_get_core_local(void)29*30feb38aSMarouene Boubakri static struct mpxy_core_local *mpxy_get_core_local(void)
30*30feb38aSMarouene Boubakri {
31*30feb38aSMarouene Boubakri struct mpxy_core_local *mpxy = NULL;
32*30feb38aSMarouene Boubakri size_t pos = 0;
33*30feb38aSMarouene Boubakri uint32_t hart_id = 0;
34*30feb38aSMarouene Boubakri
35*30feb38aSMarouene Boubakri assert((thread_get_exceptions() & THREAD_EXCP_ALL) == THREAD_EXCP_ALL);
36*30feb38aSMarouene Boubakri
37*30feb38aSMarouene Boubakri pos = get_core_pos();
38*30feb38aSMarouene Boubakri hart_id = thread_get_hartid_by_hartindex(pos);
39*30feb38aSMarouene Boubakri
40*30feb38aSMarouene Boubakri mpxy = &mpxy_core_local_array[hart_id];
41*30feb38aSMarouene Boubakri
42*30feb38aSMarouene Boubakri return mpxy;
43*30feb38aSMarouene Boubakri }
44*30feb38aSMarouene Boubakri
45*30feb38aSMarouene Boubakri /**
46*30feb38aSMarouene Boubakri * sbi_mpxy_get_shmem_size - Retrieve the MPXY shared memory size
47*30feb38aSMarouene Boubakri * @shmem_size: Pointer to store the shared memory size in bytes
48*30feb38aSMarouene Boubakri *
49*30feb38aSMarouene Boubakri * Makes an SBI call to query the shared memory size used for
50*30feb38aSMarouene Boubakri * sending and receiving messages via the MPXY extension.
51*30feb38aSMarouene Boubakri *
52*30feb38aSMarouene Boubakri * Return: 0 on success, negative SBI error code on failure.
53*30feb38aSMarouene Boubakri */
sbi_mpxy_get_shmem_size(unsigned long * shmem_size)54*30feb38aSMarouene Boubakri int sbi_mpxy_get_shmem_size(unsigned long *shmem_size)
55*30feb38aSMarouene Boubakri {
56*30feb38aSMarouene Boubakri struct sbiret sbiret = {};
57*30feb38aSMarouene Boubakri
58*30feb38aSMarouene Boubakri sbiret = sbi_ecall(SBI_EXT_MPXY, SBI_EXT_MPXY_GET_SHMEM_SIZE, 0, 0, 0,
59*30feb38aSMarouene Boubakri 0, 0, 0);
60*30feb38aSMarouene Boubakri if (sbiret.error) {
61*30feb38aSMarouene Boubakri EMSG("MPXY SBI call failed: error=%ld value=%ld", sbiret.error,
62*30feb38aSMarouene Boubakri sbiret.value);
63*30feb38aSMarouene Boubakri return sbiret.error;
64*30feb38aSMarouene Boubakri }
65*30feb38aSMarouene Boubakri
66*30feb38aSMarouene Boubakri if (shmem_size)
67*30feb38aSMarouene Boubakri *shmem_size = sbiret.value;
68*30feb38aSMarouene Boubakri
69*30feb38aSMarouene Boubakri return SBI_SUCCESS;
70*30feb38aSMarouene Boubakri }
71*30feb38aSMarouene Boubakri
72*30feb38aSMarouene Boubakri /**
73*30feb38aSMarouene Boubakri * sbi_mpxy_set_shmem - Set up MPXY shared memory on the current hart
74*30feb38aSMarouene Boubakri *
75*30feb38aSMarouene Boubakri * Allocates and registers a 4 KiB shared memory region, aligned to 4 KiB,
76*30feb38aSMarouene Boubakri * as required by the MPXY extension. This memory is used for sending and
77*30feb38aSMarouene Boubakri * receiving messages. Registers the shared memory with the SBI MPXY extension.
78*30feb38aSMarouene Boubakri *
79*30feb38aSMarouene Boubakri * Return: SBI_SUCCESS on success, negative SBI error code on failure.
80*30feb38aSMarouene Boubakri */
sbi_mpxy_set_shmem(void)81*30feb38aSMarouene Boubakri int sbi_mpxy_set_shmem(void)
82*30feb38aSMarouene Boubakri {
83*30feb38aSMarouene Boubakri struct mpxy_core_local *mpxy = NULL;
84*30feb38aSMarouene Boubakri struct sbiret sbiret = {};
85*30feb38aSMarouene Boubakri void *shmem = NULL;
86*30feb38aSMarouene Boubakri uint32_t exceptions = 0;
87*30feb38aSMarouene Boubakri int ret = SBI_ERR_FAILURE;
88*30feb38aSMarouene Boubakri
89*30feb38aSMarouene Boubakri exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
90*30feb38aSMarouene Boubakri
91*30feb38aSMarouene Boubakri mpxy = mpxy_get_core_local();
92*30feb38aSMarouene Boubakri if (mpxy->shmem_active)
93*30feb38aSMarouene Boubakri goto out;
94*30feb38aSMarouene Boubakri
95*30feb38aSMarouene Boubakri shmem = memalign(SMALL_PAGE_SIZE, SMALL_PAGE_SIZE);
96*30feb38aSMarouene Boubakri if (!shmem)
97*30feb38aSMarouene Boubakri goto out;
98*30feb38aSMarouene Boubakri
99*30feb38aSMarouene Boubakri mpxy->shmem = shmem;
100*30feb38aSMarouene Boubakri mpxy->shmem_pa = virt_to_phys(shmem);
101*30feb38aSMarouene Boubakri
102*30feb38aSMarouene Boubakri sbiret = sbi_ecall(SBI_EXT_MPXY, SBI_EXT_MPXY_SET_SHMEM, mpxy->shmem_pa,
103*30feb38aSMarouene Boubakri 0, 0);
104*30feb38aSMarouene Boubakri if (sbiret.error) {
105*30feb38aSMarouene Boubakri EMSG("MPXY SBI call failed: error=%ld", sbiret.error);
106*30feb38aSMarouene Boubakri free(shmem);
107*30feb38aSMarouene Boubakri ret = sbiret.error;
108*30feb38aSMarouene Boubakri goto out;
109*30feb38aSMarouene Boubakri }
110*30feb38aSMarouene Boubakri
111*30feb38aSMarouene Boubakri mpxy->shmem_active = true;
112*30feb38aSMarouene Boubakri
113*30feb38aSMarouene Boubakri ret = SBI_SUCCESS;
114*30feb38aSMarouene Boubakri
115*30feb38aSMarouene Boubakri out:
116*30feb38aSMarouene Boubakri thread_unmask_exceptions(exceptions);
117*30feb38aSMarouene Boubakri return ret;
118*30feb38aSMarouene Boubakri }
119*30feb38aSMarouene Boubakri
120*30feb38aSMarouene Boubakri /**
121*30feb38aSMarouene Boubakri * sbi_mpxy_get_channel_ids - Retrieve MPXY channel IDs
122*30feb38aSMarouene Boubakri * @channel_count: Number of channels expected
123*30feb38aSMarouene Boubakri * @channel_ids: Buffer to store the retrieved channel IDs
124*30feb38aSMarouene Boubakri *
125*30feb38aSMarouene Boubakri * Uses the SBI MPXY extension to query the list of available channel IDs
126*30feb38aSMarouene Boubakri * into the provided buffer.
127*30feb38aSMarouene Boubakri *
128*30feb38aSMarouene Boubakri * Return: SBI_SUCCESS on success, negative SBI error code on failure.
129*30feb38aSMarouene Boubakri */
sbi_mpxy_get_channel_ids(uint32_t channel_count,uint32_t * channel_ids)130*30feb38aSMarouene Boubakri int sbi_mpxy_get_channel_ids(uint32_t channel_count, uint32_t *channel_ids)
131*30feb38aSMarouene Boubakri {
132*30feb38aSMarouene Boubakri struct mpxy_core_local *mpxy = NULL;
133*30feb38aSMarouene Boubakri struct sbi_mpxy_channel_ids_data *data = NULL;
134*30feb38aSMarouene Boubakri uint32_t remaining = 0;
135*30feb38aSMarouene Boubakri uint32_t returned = 0;
136*30feb38aSMarouene Boubakri uint32_t count = 0;
137*30feb38aSMarouene Boubakri uint32_t start_index = 0;
138*30feb38aSMarouene Boubakri struct sbiret sbiret = {};
139*30feb38aSMarouene Boubakri uint32_t exceptions = 0;
140*30feb38aSMarouene Boubakri
141*30feb38aSMarouene Boubakri if (!channel_count || !channel_ids)
142*30feb38aSMarouene Boubakri return SBI_ERR_INVALID_PARAM;
143*30feb38aSMarouene Boubakri
144*30feb38aSMarouene Boubakri exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
145*30feb38aSMarouene Boubakri
146*30feb38aSMarouene Boubakri mpxy = mpxy_get_core_local();
147*30feb38aSMarouene Boubakri
148*30feb38aSMarouene Boubakri if (!mpxy->shmem_active) {
149*30feb38aSMarouene Boubakri sbiret.error = SBI_ERR_NO_SHMEM;
150*30feb38aSMarouene Boubakri goto out;
151*30feb38aSMarouene Boubakri }
152*30feb38aSMarouene Boubakri
153*30feb38aSMarouene Boubakri data = mpxy->shmem;
154*30feb38aSMarouene Boubakri
155*30feb38aSMarouene Boubakri do {
156*30feb38aSMarouene Boubakri sbiret = sbi_ecall(SBI_EXT_MPXY, SBI_EXT_MPXY_GET_CHANNEL_IDS,
157*30feb38aSMarouene Boubakri start_index, 0, 0, 0, 0, 0);
158*30feb38aSMarouene Boubakri if (sbiret.error) {
159*30feb38aSMarouene Boubakri EMSG("MPXY SBI call failed: error=%ld", sbiret.error);
160*30feb38aSMarouene Boubakri goto out;
161*30feb38aSMarouene Boubakri }
162*30feb38aSMarouene Boubakri
163*30feb38aSMarouene Boubakri remaining = data->remaining;
164*30feb38aSMarouene Boubakri returned = data->returned;
165*30feb38aSMarouene Boubakri
166*30feb38aSMarouene Boubakri count = returned < (channel_count - start_index) ?
167*30feb38aSMarouene Boubakri returned :
168*30feb38aSMarouene Boubakri (channel_count - start_index);
169*30feb38aSMarouene Boubakri memcpy(&channel_ids[start_index], data->channel_array,
170*30feb38aSMarouene Boubakri count * sizeof(uint32_t));
171*30feb38aSMarouene Boubakri start_index += count;
172*30feb38aSMarouene Boubakri } while (remaining && start_index < channel_count);
173*30feb38aSMarouene Boubakri
174*30feb38aSMarouene Boubakri out:
175*30feb38aSMarouene Boubakri thread_unmask_exceptions(exceptions);
176*30feb38aSMarouene Boubakri return sbiret.error;
177*30feb38aSMarouene Boubakri }
178*30feb38aSMarouene Boubakri
179*30feb38aSMarouene Boubakri /**
180*30feb38aSMarouene Boubakri * sbi_mpxy_read_attributes - Read attributes from an MPXY channel
181*30feb38aSMarouene Boubakri * @channel_id: ID of the channel
182*30feb38aSMarouene Boubakri * @base_attribute_id: Starting attribute ID
183*30feb38aSMarouene Boubakri * @attribute_count: Number of attributes to read
184*30feb38aSMarouene Boubakri * @attribute_buf: Buffer to store the read attribute values
185*30feb38aSMarouene Boubakri *
186*30feb38aSMarouene Boubakri * Makes an SBI call to read attributes from the specified channel and copies
187*30feb38aSMarouene Boubakri * the values from shared memory into the provided buffer.
188*30feb38aSMarouene Boubakri *
189*30feb38aSMarouene Boubakri * Return: SBI_SUCCESS on success, negative SBI error code on failure.
190*30feb38aSMarouene Boubakri */
sbi_mpxy_read_attributes(uint32_t channel_id,uint32_t base_attribute_id,uint32_t attribute_count,void * attribute_buf)191*30feb38aSMarouene Boubakri int sbi_mpxy_read_attributes(uint32_t channel_id, uint32_t base_attribute_id,
192*30feb38aSMarouene Boubakri uint32_t attribute_count, void *attribute_buf)
193*30feb38aSMarouene Boubakri {
194*30feb38aSMarouene Boubakri struct mpxy_core_local *mpxy = NULL;
195*30feb38aSMarouene Boubakri struct sbiret sbiret = {};
196*30feb38aSMarouene Boubakri uint32_t exceptions = 0;
197*30feb38aSMarouene Boubakri int ret = SBI_ERR_FAILURE;
198*30feb38aSMarouene Boubakri
199*30feb38aSMarouene Boubakri if (!attribute_count || !attribute_buf)
200*30feb38aSMarouene Boubakri return SBI_ERR_INVALID_PARAM;
201*30feb38aSMarouene Boubakri
202*30feb38aSMarouene Boubakri exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
203*30feb38aSMarouene Boubakri
204*30feb38aSMarouene Boubakri mpxy = mpxy_get_core_local();
205*30feb38aSMarouene Boubakri
206*30feb38aSMarouene Boubakri if (!mpxy->shmem_active) {
207*30feb38aSMarouene Boubakri ret = SBI_ERR_NO_SHMEM;
208*30feb38aSMarouene Boubakri goto out;
209*30feb38aSMarouene Boubakri }
210*30feb38aSMarouene Boubakri
211*30feb38aSMarouene Boubakri sbiret = sbi_ecall(SBI_EXT_MPXY, SBI_EXT_MPXY_READ_ATTRS, channel_id,
212*30feb38aSMarouene Boubakri base_attribute_id, attribute_count, 0, 0, 0);
213*30feb38aSMarouene Boubakri if (!sbiret.error)
214*30feb38aSMarouene Boubakri memcpy(attribute_buf, (void *)mpxy->shmem,
215*30feb38aSMarouene Boubakri attribute_count * sizeof(uint32_t));
216*30feb38aSMarouene Boubakri else
217*30feb38aSMarouene Boubakri EMSG("MPXY SBI call failed: error=%ld", sbiret.error);
218*30feb38aSMarouene Boubakri
219*30feb38aSMarouene Boubakri ret = sbiret.error;
220*30feb38aSMarouene Boubakri out:
221*30feb38aSMarouene Boubakri thread_unmask_exceptions(exceptions);
222*30feb38aSMarouene Boubakri return ret;
223*30feb38aSMarouene Boubakri }
224*30feb38aSMarouene Boubakri
225*30feb38aSMarouene Boubakri /**
226*30feb38aSMarouene Boubakri * sbi_mpxy_write_attributes - Write attributes to an MPXY channel
227*30feb38aSMarouene Boubakri * @channel_id: ID of the channel to write attributes to
228*30feb38aSMarouene Boubakri * @base_attribute_id: Starting attribute ID
229*30feb38aSMarouene Boubakri * @attribute_count: Number of attributes to write
230*30feb38aSMarouene Boubakri * @attributes_buf: Buffer containing the attribute values
231*30feb38aSMarouene Boubakri *
232*30feb38aSMarouene Boubakri * Copies the attribute values into shared memory and makes an SBI call to
233*30feb38aSMarouene Boubakri * write them to the specified channel.
234*30feb38aSMarouene Boubakri *
235*30feb38aSMarouene Boubakri * Return: SBI_SUCCESS on success, negative SBI error code on failure.
236*30feb38aSMarouene Boubakri */
sbi_mpxy_write_attributes(uint32_t channel_id,uint32_t base_attribute_id,uint32_t attribute_count,uint32_t * attributes_buf)237*30feb38aSMarouene Boubakri int sbi_mpxy_write_attributes(uint32_t channel_id, uint32_t base_attribute_id,
238*30feb38aSMarouene Boubakri uint32_t attribute_count,
239*30feb38aSMarouene Boubakri uint32_t *attributes_buf)
240*30feb38aSMarouene Boubakri {
241*30feb38aSMarouene Boubakri struct mpxy_core_local *mpxy = NULL;
242*30feb38aSMarouene Boubakri struct sbiret sbiret = {};
243*30feb38aSMarouene Boubakri uint32_t exceptions = 0;
244*30feb38aSMarouene Boubakri int ret = SBI_ERR_FAILURE;
245*30feb38aSMarouene Boubakri
246*30feb38aSMarouene Boubakri if (!attribute_count || !attributes_buf)
247*30feb38aSMarouene Boubakri return SBI_ERR_INVALID_PARAM;
248*30feb38aSMarouene Boubakri
249*30feb38aSMarouene Boubakri exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
250*30feb38aSMarouene Boubakri
251*30feb38aSMarouene Boubakri mpxy = mpxy_get_core_local();
252*30feb38aSMarouene Boubakri
253*30feb38aSMarouene Boubakri if (!mpxy->shmem_active) {
254*30feb38aSMarouene Boubakri ret = SBI_ERR_NO_SHMEM;
255*30feb38aSMarouene Boubakri goto out;
256*30feb38aSMarouene Boubakri }
257*30feb38aSMarouene Boubakri
258*30feb38aSMarouene Boubakri memcpy(mpxy->shmem, attributes_buf, attribute_count * sizeof(uint32_t));
259*30feb38aSMarouene Boubakri
260*30feb38aSMarouene Boubakri sbiret = sbi_ecall(SBI_EXT_MPXY, SBI_EXT_MPXY_WRITE_ATTRS, channel_id,
261*30feb38aSMarouene Boubakri base_attribute_id, attribute_count, 0, 0, 0);
262*30feb38aSMarouene Boubakri
263*30feb38aSMarouene Boubakri if (sbiret.error)
264*30feb38aSMarouene Boubakri EMSG("MPXY SBI call failed: error=%ld", sbiret.error);
265*30feb38aSMarouene Boubakri
266*30feb38aSMarouene Boubakri ret = sbiret.error;
267*30feb38aSMarouene Boubakri out:
268*30feb38aSMarouene Boubakri thread_unmask_exceptions(exceptions);
269*30feb38aSMarouene Boubakri return ret;
270*30feb38aSMarouene Boubakri }
271*30feb38aSMarouene Boubakri
272*30feb38aSMarouene Boubakri /**
273*30feb38aSMarouene Boubakri * sbi_mpxy_send_message_with_response - Send a message and receive response
274*30feb38aSMarouene Boubakri * via MPXY
275*30feb38aSMarouene Boubakri * @channel_id: ID of the channel
276*30feb38aSMarouene Boubakri * @message_id: ID of the message
277*30feb38aSMarouene Boubakri * @message: Pointer to transmit buffer (can be NULL if message_len is 0)
278*30feb38aSMarouene Boubakri * @message_len: Length of transmit buffer in bytes
279*30feb38aSMarouene Boubakri * @response: Pointer to receive buffer
280*30feb38aSMarouene Boubakri * @max_response_len: Maximum size of receive buffer in bytes
281*30feb38aSMarouene Boubakri * @response_len: Pointer to store length of received data
282*30feb38aSMarouene Boubakri *
283*30feb38aSMarouene Boubakri * Copies transmit data into shared memory and makes an SBI call to send
284*30feb38aSMarouene Boubakri * the message and receive a response. Copies the received response into
285*30feb38aSMarouene Boubakri * the provided receive buffer.
286*30feb38aSMarouene Boubakri *
287*30feb38aSMarouene Boubakri * Return: SBI_SUCCESS on success, negative SBI error code on failure.
288*30feb38aSMarouene Boubakri */
sbi_mpxy_send_message_with_response(uint32_t channel_id,uint32_t message_id,void * message,unsigned long message_len,void * response,unsigned long max_response_len,unsigned long * response_len)289*30feb38aSMarouene Boubakri int sbi_mpxy_send_message_with_response(uint32_t channel_id,
290*30feb38aSMarouene Boubakri uint32_t message_id, void *message,
291*30feb38aSMarouene Boubakri unsigned long message_len,
292*30feb38aSMarouene Boubakri void *response,
293*30feb38aSMarouene Boubakri unsigned long max_response_len,
294*30feb38aSMarouene Boubakri unsigned long *response_len)
295*30feb38aSMarouene Boubakri {
296*30feb38aSMarouene Boubakri struct mpxy_core_local *mpxy = NULL;
297*30feb38aSMarouene Boubakri unsigned long response_bytes = 0;
298*30feb38aSMarouene Boubakri struct sbiret sbiret = {};
299*30feb38aSMarouene Boubakri uint32_t exceptions = 0;
300*30feb38aSMarouene Boubakri int ret = SBI_ERR_FAILURE;
301*30feb38aSMarouene Boubakri
302*30feb38aSMarouene Boubakri if (!message && message_len)
303*30feb38aSMarouene Boubakri return SBI_ERR_INVALID_PARAM;
304*30feb38aSMarouene Boubakri
305*30feb38aSMarouene Boubakri exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
306*30feb38aSMarouene Boubakri
307*30feb38aSMarouene Boubakri mpxy = mpxy_get_core_local();
308*30feb38aSMarouene Boubakri
309*30feb38aSMarouene Boubakri if (!mpxy->shmem_active) {
310*30feb38aSMarouene Boubakri ret = SBI_ERR_NO_SHMEM;
311*30feb38aSMarouene Boubakri goto out;
312*30feb38aSMarouene Boubakri }
313*30feb38aSMarouene Boubakri
314*30feb38aSMarouene Boubakri if (message_len)
315*30feb38aSMarouene Boubakri memcpy(mpxy->shmem, message, message_len);
316*30feb38aSMarouene Boubakri
317*30feb38aSMarouene Boubakri sbiret = sbi_ecall(SBI_EXT_MPXY, SBI_EXT_MPXY_SEND_MSG_WITH_RESP,
318*30feb38aSMarouene Boubakri channel_id, message_id, message_len, 0, 0, 0);
319*30feb38aSMarouene Boubakri if (response && !sbiret.error) {
320*30feb38aSMarouene Boubakri response_bytes = sbiret.value;
321*30feb38aSMarouene Boubakri if (response_bytes > max_response_len) {
322*30feb38aSMarouene Boubakri ret = SBI_ERR_INVALID_PARAM;
323*30feb38aSMarouene Boubakri goto out;
324*30feb38aSMarouene Boubakri }
325*30feb38aSMarouene Boubakri
326*30feb38aSMarouene Boubakri memcpy(response, mpxy->shmem, response_bytes);
327*30feb38aSMarouene Boubakri if (response_len)
328*30feb38aSMarouene Boubakri *response_len = response_bytes;
329*30feb38aSMarouene Boubakri }
330*30feb38aSMarouene Boubakri
331*30feb38aSMarouene Boubakri if (sbiret.error)
332*30feb38aSMarouene Boubakri EMSG("MPXY SBI call failed: error=%ld", sbiret.error);
333*30feb38aSMarouene Boubakri
334*30feb38aSMarouene Boubakri ret = sbiret.error;
335*30feb38aSMarouene Boubakri out:
336*30feb38aSMarouene Boubakri thread_unmask_exceptions(exceptions);
337*30feb38aSMarouene Boubakri return ret;
338*30feb38aSMarouene Boubakri }
339*30feb38aSMarouene Boubakri
340*30feb38aSMarouene Boubakri /**
341*30feb38aSMarouene Boubakri * sbi_mpxy_send_message_without_response - Send a message via MPXY without
342*30feb38aSMarouene Boubakri * expecting a response
343*30feb38aSMarouene Boubakri * @channel_id: ID of the channel
344*30feb38aSMarouene Boubakri * @message_id: Message ID
345*30feb38aSMarouene Boubakri * @message: Pointer to transmit buffer (may be NULL if message_len is 0)
346*30feb38aSMarouene Boubakri * @message_len: Number of bytes to send
347*30feb38aSMarouene Boubakri *
348*30feb38aSMarouene Boubakri * Copies transmit data into shared memory and makes an SBI call to send the
349*30feb38aSMarouene Boubakri * message without waiting for a response.
350*30feb38aSMarouene Boubakri *
351*30feb38aSMarouene Boubakri * Return: SBI_SUCCESS on success, negative SBI error code on failure.
352*30feb38aSMarouene Boubakri */
sbi_mpxy_send_message_without_response(uint32_t channel_id,uint32_t message_id,void * message,unsigned long message_len)353*30feb38aSMarouene Boubakri int sbi_mpxy_send_message_without_response(uint32_t channel_id,
354*30feb38aSMarouene Boubakri uint32_t message_id, void *message,
355*30feb38aSMarouene Boubakri unsigned long message_len)
356*30feb38aSMarouene Boubakri {
357*30feb38aSMarouene Boubakri struct mpxy_core_local *mpxy = NULL;
358*30feb38aSMarouene Boubakri struct sbiret sbiret = {};
359*30feb38aSMarouene Boubakri uint32_t exceptions = 0;
360*30feb38aSMarouene Boubakri int ret = SBI_ERR_FAILURE;
361*30feb38aSMarouene Boubakri
362*30feb38aSMarouene Boubakri if (!message && message_len)
363*30feb38aSMarouene Boubakri return SBI_ERR_INVALID_PARAM;
364*30feb38aSMarouene Boubakri
365*30feb38aSMarouene Boubakri exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
366*30feb38aSMarouene Boubakri
367*30feb38aSMarouene Boubakri mpxy = mpxy_get_core_local();
368*30feb38aSMarouene Boubakri
369*30feb38aSMarouene Boubakri if (!mpxy->shmem_active) {
370*30feb38aSMarouene Boubakri ret = SBI_ERR_NO_SHMEM;
371*30feb38aSMarouene Boubakri goto out;
372*30feb38aSMarouene Boubakri }
373*30feb38aSMarouene Boubakri
374*30feb38aSMarouene Boubakri if (message_len)
375*30feb38aSMarouene Boubakri memcpy(mpxy->shmem, message, message_len);
376*30feb38aSMarouene Boubakri
377*30feb38aSMarouene Boubakri sbiret = sbi_ecall(SBI_EXT_MPXY, SBI_EXT_MPXY_SEND_MSG_WITHOUT_RESP,
378*30feb38aSMarouene Boubakri channel_id, message_id, message_len, 0, 0, 0);
379*30feb38aSMarouene Boubakri
380*30feb38aSMarouene Boubakri if (sbiret.error)
381*30feb38aSMarouene Boubakri EMSG("MPXY SBI call failed: error=%ld", sbiret.error);
382*30feb38aSMarouene Boubakri
383*30feb38aSMarouene Boubakri ret = sbiret.error;
384*30feb38aSMarouene Boubakri out:
385*30feb38aSMarouene Boubakri thread_unmask_exceptions(exceptions);
386*30feb38aSMarouene Boubakri return ret;
387*30feb38aSMarouene Boubakri }
388*30feb38aSMarouene Boubakri
389*30feb38aSMarouene Boubakri /**
390*30feb38aSMarouene Boubakri * sbi_mpxy_get_channel_count - Get the total number of MPXY channels
391*30feb38aSMarouene Boubakri * @channel_count: Pointer to store the total number of channels
392*30feb38aSMarouene Boubakri *
393*30feb38aSMarouene Boubakri * Makes an SBI call to retrieve the number of channels by reading
394*30feb38aSMarouene Boubakri * the remaining and returned fields from the shared memory structure.
395*30feb38aSMarouene Boubakri *
396*30feb38aSMarouene Boubakri * Return: SBI_SUCCESS on success, negative SBI error code on failure.
397*30feb38aSMarouene Boubakri */
sbi_mpxy_get_channel_count(uint32_t * channel_count)398*30feb38aSMarouene Boubakri int sbi_mpxy_get_channel_count(uint32_t *channel_count)
399*30feb38aSMarouene Boubakri {
400*30feb38aSMarouene Boubakri struct mpxy_core_local *mpxy = NULL;
401*30feb38aSMarouene Boubakri struct sbi_mpxy_channel_ids_data *data = NULL;
402*30feb38aSMarouene Boubakri uint32_t remaining = 0;
403*30feb38aSMarouene Boubakri uint32_t returned = 0;
404*30feb38aSMarouene Boubakri struct sbiret sbiret = {};
405*30feb38aSMarouene Boubakri uint32_t exceptions = 0;
406*30feb38aSMarouene Boubakri int ret = SBI_ERR_FAILURE;
407*30feb38aSMarouene Boubakri
408*30feb38aSMarouene Boubakri if (!channel_count)
409*30feb38aSMarouene Boubakri return SBI_ERR_INVALID_PARAM;
410*30feb38aSMarouene Boubakri
411*30feb38aSMarouene Boubakri exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
412*30feb38aSMarouene Boubakri
413*30feb38aSMarouene Boubakri mpxy = mpxy_get_core_local();
414*30feb38aSMarouene Boubakri
415*30feb38aSMarouene Boubakri if (!mpxy->shmem_active) {
416*30feb38aSMarouene Boubakri ret = SBI_ERR_NO_SHMEM;
417*30feb38aSMarouene Boubakri goto out;
418*30feb38aSMarouene Boubakri }
419*30feb38aSMarouene Boubakri
420*30feb38aSMarouene Boubakri data = mpxy->shmem;
421*30feb38aSMarouene Boubakri
422*30feb38aSMarouene Boubakri sbiret = sbi_ecall(SBI_EXT_MPXY, SBI_EXT_MPXY_GET_CHANNEL_IDS, 0, 0, 0,
423*30feb38aSMarouene Boubakri 0, 0, 0);
424*30feb38aSMarouene Boubakri if (sbiret.error) {
425*30feb38aSMarouene Boubakri EMSG("MPXY SBI call failed: error=%ld", sbiret.error);
426*30feb38aSMarouene Boubakri goto out;
427*30feb38aSMarouene Boubakri }
428*30feb38aSMarouene Boubakri
429*30feb38aSMarouene Boubakri remaining = data->remaining;
430*30feb38aSMarouene Boubakri returned = data->returned;
431*30feb38aSMarouene Boubakri *channel_count = remaining + returned;
432*30feb38aSMarouene Boubakri
433*30feb38aSMarouene Boubakri ret = sbiret.error;
434*30feb38aSMarouene Boubakri
435*30feb38aSMarouene Boubakri out:
436*30feb38aSMarouene Boubakri thread_unmask_exceptions(exceptions);
437*30feb38aSMarouene Boubakri return ret;
438*30feb38aSMarouene Boubakri }
439*30feb38aSMarouene Boubakri
440*30feb38aSMarouene Boubakri /**
441*30feb38aSMarouene Boubakri * sbi_mpxy_get_notification_events - Retrieve notification events from an
442*30feb38aSMarouene Boubakri * MPXY channel
443*30feb38aSMarouene Boubakri * @channel_id: ID of the channel
444*30feb38aSMarouene Boubakri * @notif_data: Pointer to buffer to store notification data
445*30feb38aSMarouene Boubakri * @events_data_len: Pointer to store length of events data in bytes
446*30feb38aSMarouene Boubakri *
447*30feb38aSMarouene Boubakri * Makes an SBI call to fetch notification events from the specified channel
448*30feb38aSMarouene Boubakri * and copies them from shared memory into the provided buffer.
449*30feb38aSMarouene Boubakri *
450*30feb38aSMarouene Boubakri * Return: SBI_SUCCESS on success, negative SBI error code on failure.
451*30feb38aSMarouene Boubakri */
452*30feb38aSMarouene Boubakri int
sbi_mpxy_get_notification_events(uint32_t channel_id,struct sbi_mpxy_notification_data * notif_data,unsigned long * events_data_len)453*30feb38aSMarouene Boubakri sbi_mpxy_get_notification_events(uint32_t channel_id,
454*30feb38aSMarouene Boubakri struct sbi_mpxy_notification_data *notif_data,
455*30feb38aSMarouene Boubakri unsigned long *events_data_len)
456*30feb38aSMarouene Boubakri {
457*30feb38aSMarouene Boubakri struct mpxy_core_local *mpxy = NULL;
458*30feb38aSMarouene Boubakri struct sbiret sbiret = {};
459*30feb38aSMarouene Boubakri uint32_t exceptions = 0;
460*30feb38aSMarouene Boubakri int ret = SBI_ERR_FAILURE;
461*30feb38aSMarouene Boubakri
462*30feb38aSMarouene Boubakri if (!notif_data || !events_data_len)
463*30feb38aSMarouene Boubakri return SBI_ERR_INVALID_PARAM;
464*30feb38aSMarouene Boubakri
465*30feb38aSMarouene Boubakri exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
466*30feb38aSMarouene Boubakri
467*30feb38aSMarouene Boubakri mpxy = mpxy_get_core_local();
468*30feb38aSMarouene Boubakri
469*30feb38aSMarouene Boubakri if (!mpxy->shmem_active) {
470*30feb38aSMarouene Boubakri ret = SBI_ERR_NO_SHMEM;
471*30feb38aSMarouene Boubakri goto out;
472*30feb38aSMarouene Boubakri }
473*30feb38aSMarouene Boubakri
474*30feb38aSMarouene Boubakri sbiret = sbi_ecall(SBI_EXT_MPXY, SBI_EXT_MPXY_GET_NOTIFICATION_EVENTS,
475*30feb38aSMarouene Boubakri channel_id, 0, 0, 0, 0, 0);
476*30feb38aSMarouene Boubakri if (sbiret.error) {
477*30feb38aSMarouene Boubakri EMSG("MPXY SBI call failed: error=%ld", sbiret.error);
478*30feb38aSMarouene Boubakri ret = sbiret.error;
479*30feb38aSMarouene Boubakri goto out;
480*30feb38aSMarouene Boubakri }
481*30feb38aSMarouene Boubakri
482*30feb38aSMarouene Boubakri memcpy(notif_data, mpxy->shmem, sbiret.value + 16);
483*30feb38aSMarouene Boubakri *events_data_len = sbiret.value;
484*30feb38aSMarouene Boubakri
485*30feb38aSMarouene Boubakri ret = sbiret.error;
486*30feb38aSMarouene Boubakri
487*30feb38aSMarouene Boubakri out:
488*30feb38aSMarouene Boubakri thread_unmask_exceptions(exceptions);
489*30feb38aSMarouene Boubakri return ret;
490*30feb38aSMarouene Boubakri }
491