source: trunk/kernel/libk/remote_buf.c @ 662

Last change on this file since 662 was 657, checked in by alain, 5 years ago

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

File size: 10.4 KB
Line 
1/*
2 * remote_buf.c Remotely accessible, circular buffer implementation.
3 *
4 * Authors : Alain Greiner  (2016,2017,2018,2019,2020)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <hal_kernel_types.h>
25#include <hal_irqmask.h>
26#include <hal_remote.h>
27#include <hal_uspace.h>
28#include <bits.h>
29#include <memcpy.h>
30#include <kmem.h>
31#include <remote_buf.h>
32
33///////////////////////////////////////////
34error_t remote_buf_create( xptr_t   buf_xp,
35                           uint32_t size )
36{
37    kmem_req_t     req;
38    uint8_t      * data;
39
40    remote_buf_t * buf_ptr = GET_PTR( buf_xp );
41    cxy_t          buf_cxy = GET_CXY( buf_xp );
42
43    // allocate the data buffer
44    if( size >= CONFIG_PPM_PAGE_SIZE )
45    {
46        req.type  = KMEM_PPM;
47        req.order = bits_log2( size >> CONFIG_PPM_PAGE_SHIFT );
48        req.flags = AF_NONE;
49        data = kmem_remote_alloc( buf_cxy , &req );
50    }
51    else
52    {
53        req.type  = KMEM_KCM;
54        req.order = bits_log2( size );
55        req.flags = AF_NONE;
56        data = kmem_remote_alloc( buf_cxy , &req );
57    }
58
59    if( data == NULL )  return -1;
60
61    // initialize buffer descriptor
62    hal_remote_s32( XPTR( buf_cxy , &buf_ptr->size ) , size );
63    hal_remote_s32( XPTR( buf_cxy , &buf_ptr->ptw  ) , 0 );
64    hal_remote_s32( XPTR( buf_cxy , &buf_ptr->ptr  ) , 0 );
65    hal_remote_s32( XPTR( buf_cxy , &buf_ptr->sts  ) , 0 );
66    hal_remote_spt( XPTR( buf_cxy , &buf_ptr->data ) , data );
67
68    return 0;
69
70}  // end remote_buf_create()
71
72/////////////////////////////////////////
73void remote_buf_destroy( xptr_t  buf_xp )
74{
75    kmem_req_t   req;
76
77    remote_buf_t * buf_ptr = GET_PTR( buf_xp );
78    cxy_t          buf_cxy = GET_CXY( buf_xp );
79
80    // release memory allocated to data buffer
81    if( buf_ptr->size >= CONFIG_PPM_PAGE_SIZE )
82    {
83        req.type  = KMEM_PPM;
84        req.ptr   = hal_remote_lpt( XPTR( buf_cxy , &buf_ptr->data ) );
85        kmem_remote_free( buf_cxy , &req );
86    }
87    else
88    {
89        req.type  = KMEM_KCM;
90        req.ptr   = hal_remote_lpt( XPTR( buf_cxy , &buf_ptr->data ) );
91        kmem_remote_free( buf_cxy , &req );
92    }
93}
94
95/////////////////////////////////////////
96void remote_buf_reset( xptr_t    buf_xp )
97{
98    remote_buf_t * buf_ptr = GET_PTR( buf_xp );
99    cxy_t          buf_cxy = GET_CXY( buf_xp );
100
101    hal_remote_s32( XPTR( buf_cxy , &buf_ptr->ptw ) , 0 );
102    hal_remote_s32( XPTR( buf_cxy , &buf_ptr->ptr ) , 0 );
103    hal_remote_s32( XPTR( buf_cxy , &buf_ptr->sts ) , 0 );
104}
105
106/////////////////////////////////////////////////
107error_t remote_buf_get_to_user( xptr_t    buf_xp,
108                                uint8_t * u_buf, 
109                                uint32_t  nbytes )
110{
111    remote_buf_t * buf_ptr = GET_PTR( buf_xp );
112    cxy_t          buf_cxy = GET_CXY( buf_xp );
113
114    // build relevant extended pointers
115    xptr_t sts_xp  = XPTR( buf_cxy , &buf_ptr->sts );
116    xptr_t ptr_xp  = XPTR( buf_cxy , &buf_ptr->ptr );
117    xptr_t size_xp = XPTR( buf_cxy , &buf_ptr->size );
118    xptr_t data_xp = XPTR( buf_cxy , &buf_ptr->data );
119
120    // get relevant infos from remote buffer descriptor
121    uint32_t  sts  = hal_remote_l32( sts_xp );
122    uint32_t  ptr  = hal_remote_l32( ptr_xp );
123    uint32_t  size = hal_remote_l32( size_xp );
124    uint8_t * data = hal_remote_lpt( data_xp );
125
126    // check enough bytes in buffer
127    if( nbytes > sts ) return -1;
128
129    // move nbytes
130    if( (ptr + nbytes) <= size)  // no wrap around => one move
131    {
132        hal_copy_to_uspace( u_buf,
133                            XPTR( buf_cxy , data + ptr ),
134                            nbytes );
135    }
136    else                         // wrap around => two moves
137    {
138        uint32_t bytes_1 = size - ptr;
139        uint32_t bytes_2 = nbytes - bytes_1;
140     
141        hal_copy_to_uspace( u_buf,
142                            XPTR( buf_cxy , data + ptr ),
143                            bytes_1 );
144
145        hal_copy_to_uspace( u_buf + bytes_1,
146                            XPTR( buf_cxy , data ),
147                            bytes_2 );
148    }
149
150    // update ptr in buffer descriptor
151    hal_remote_s32( ptr_xp , (ptr + nbytes) % size );
152
153    // atomically update sts
154    hal_remote_atomic_add( sts_xp , -nbytes );
155
156    return 0;
157
158}  // end remote_buf_get_to_user()
159
160///////////////////////////////////////////////////
161error_t remote_buf_get_to_kernel( xptr_t    buf_xp,
162                                  uint8_t * k_buf,
163                                  uint32_t  nbytes )
164{
165    remote_buf_t * buf_ptr = GET_PTR( buf_xp );
166    cxy_t          buf_cxy = GET_CXY( buf_xp );
167
168    // build relevant extended pointers
169    xptr_t sts_xp  = XPTR( buf_cxy , &buf_ptr->sts );
170    xptr_t ptr_xp  = XPTR( buf_cxy , &buf_ptr->ptr );
171    xptr_t size_xp = XPTR( buf_cxy , &buf_ptr->size );
172    xptr_t data_xp = XPTR( buf_cxy , &buf_ptr->data );
173
174    // get relevant infos from remote buffer descriptor
175    uint32_t  sts  = hal_remote_l32( sts_xp );
176    uint32_t  ptr  = hal_remote_l32( ptr_xp );
177    uint32_t  size = hal_remote_l32( size_xp );
178    uint8_t * data = hal_remote_lpt( data_xp );
179
180    // check enough bytes in buffer
181    if( nbytes > sts ) return -1;
182
183    // move nbytes
184    if( (ptr + nbytes) <= size)  // no wrap around => one move
185    {
186        hal_remote_memcpy( XPTR( local_cxy , k_buf ),
187                           XPTR( buf_cxy   , data + ptr ),
188                           nbytes );
189    }
190    else                         // wrap around => two moves
191    {
192        uint32_t bytes_1 = size - ptr;
193        uint32_t bytes_2 = nbytes - bytes_1;
194     
195        hal_remote_memcpy( XPTR( local_cxy , k_buf ),
196                           XPTR( buf_cxy   , data + ptr ),
197                           bytes_1 );
198
199        hal_remote_memcpy( XPTR( local_cxy , k_buf + bytes_1 ),
200                           XPTR( buf_cxy   , data ),
201                           bytes_2 );
202    }
203
204    // update ptr in buffer descriptor
205    hal_remote_s32( ptr_xp , (ptr + nbytes) % size );
206
207    // atomically update sts
208    hal_remote_atomic_add( sts_xp , -nbytes );
209
210    return 0;
211
212}  // end remote_buf_get_to_user()
213
214///////////////////////////////////////////////////
215error_t remote_buf_put_from_user( xptr_t    buf_xp,
216                                  uint8_t * u_buf,
217                                  uint32_t  nbytes )
218{
219    remote_buf_t * buf_ptr = GET_PTR( buf_xp );
220    cxy_t          buf_cxy = GET_CXY( buf_xp );
221
222    // build relevant extended pointers
223    xptr_t sts_xp  = XPTR( buf_cxy , &buf_ptr->sts );
224    xptr_t ptw_xp  = XPTR( buf_cxy , &buf_ptr->ptw );
225    xptr_t size_xp = XPTR( buf_cxy , &buf_ptr->size );
226    xptr_t data_xp = XPTR( buf_cxy , &buf_ptr->data );
227
228    // get relevant infos from remote buffer descriptor
229    uint32_t  sts  = hal_remote_l32( sts_xp );
230    uint32_t  ptw  = hal_remote_l32( ptw_xp );
231    uint32_t  size = hal_remote_l32( size_xp );
232    uint8_t * data = hal_remote_lpt( data_xp );
233
234    // check enough space in buffer
235    if( nbytes > (size - sts) ) return -1;
236
237    // move nbytes
238    if( (ptw + nbytes) <= size)  // no wrap around => one move
239    {
240        hal_copy_from_uspace( XPTR( buf_cxy , data + ptw ),
241                              u_buf,
242                              nbytes );
243    }
244    else                         // wrap around => two moves
245    {
246        uint32_t bytes_1 = size - ptw;
247        uint32_t bytes_2 = nbytes - bytes_1;
248     
249        hal_copy_from_uspace( XPTR( buf_cxy , data + ptw ),
250                              u_buf,
251                              bytes_1 );
252
253        hal_copy_from_uspace( XPTR( buf_cxy , data ),
254                              u_buf + bytes_1,
255                              bytes_2 );
256    }
257
258    // update ptw in buffer descriptor
259    hal_remote_s32( ptw_xp , (ptw + nbytes) % size );
260
261    // atomically update sts
262    hal_remote_atomic_add( sts_xp , nbytes );
263
264    return 0;
265
266}  // end remote_buf_put_from_user()
267
268/////////////////////////////////////////////////////
269error_t remote_buf_put_from_kernel( xptr_t    buf_xp,
270                                    uint8_t * k_buf, 
271                                    uint32_t  nbytes )
272{
273    remote_buf_t * buf_ptr = GET_PTR( buf_xp );
274    cxy_t          buf_cxy = GET_CXY( buf_xp );
275
276    // build relevant extended pointers
277    xptr_t sts_xp  = XPTR( buf_cxy , &buf_ptr->sts );
278    xptr_t ptw_xp  = XPTR( buf_cxy , &buf_ptr->ptw );
279    xptr_t size_xp = XPTR( buf_cxy , &buf_ptr->size );
280    xptr_t data_xp = XPTR( buf_cxy , &buf_ptr->data );
281
282    // get relevant infos from remote buffer descriptor
283    uint32_t  sts  = hal_remote_l32( sts_xp );
284    uint32_t  ptw  = hal_remote_l32( ptw_xp );
285    uint32_t  size = hal_remote_l32( size_xp );
286    uint8_t * data = hal_remote_lpt( data_xp );
287
288    // check enough space in buffer
289    if( nbytes > (size - sts) ) return -1;
290
291    // move nbytes
292    if( (ptw + nbytes) <= size)  // no wrap around => one move
293    {
294        hal_remote_memcpy( XPTR( buf_cxy   , data + ptw ),
295                           XPTR( local_cxy , k_buf ),
296                           nbytes );
297    }
298    else                         // wrap around => two moves
299    {
300        uint32_t bytes_1 = size - ptw;
301        uint32_t bytes_2 = nbytes - bytes_1;
302     
303        hal_remote_memcpy( XPTR( buf_cxy   , data + ptw ),
304                           XPTR( local_cxy , k_buf ),
305                           bytes_1 );
306
307        hal_remote_memcpy( XPTR( buf_cxy   , data ),
308                           XPTR( local_cxy , k_buf + bytes_1 ),
309                           bytes_2 );
310    }
311
312    // update ptw in buffer descriptor
313    hal_remote_s32( ptw_xp , (ptw + nbytes) % size );
314
315    // atomically update sts
316    hal_remote_atomic_add( sts_xp , nbytes );
317
318    return 0;
319
320}  // end remote_buf_put_from_kernel()
321
322////////////////////////////////////////////
323uint32_t remote_buf_status( xptr_t  buf_xp )
324{
325    remote_buf_t * buf_ptr = GET_PTR( buf_xp );
326    cxy_t          buf_cxy = GET_CXY( buf_xp );
327
328    return hal_remote_l32( XPTR( buf_cxy , &buf_ptr->sts ) );
329   
330}  // end remote_buf_status()
331
332
Note: See TracBrowser for help on using the repository browser.