source: trunk/kernel/kern/rpc.c @ 265

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

Fix several bugs in VFS.

File size: 58.1 KB
Line 
1/*
2 * rpc.c - RPC related operations implementation.
3 *
4 * Author    Alain Greiner (2016,2017)
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 <kernel_config.h>
25#include <hal_types.h>
26#include <hal_atomic.h>
27#include <hal_remote.h>
28#include <hal_irqmask.h>
29#include <hal_special.h>
30#include <printk.h>
31#include <remote_sem.h>
32#include <core.h>
33#include <mapper.h>
34#include <chdev.h>
35#include <bits.h>
36#include <thread.h>
37#include <cluster.h>
38#include <process.h>
39#include <vfs.h>
40#include <fatfs.h>
41#include <signal.h>
42#include <rpc.h>
43
44/////////////////////////////////////////////////////////////////////////////////////////
45//      array of function pointers  (must be consistent with enum in rpc.h)
46/////////////////////////////////////////////////////////////////////////////////////////
47
48rpc_server_t * rpc_server[RPC_MAX_INDEX] =
49{
50    &rpc_pmem_get_pages_server,         // 0
51    &rpc_process_pid_alloc_server,      // 1
52    &rpc_process_exec_server,           // 2
53    &rpc_process_kill_server,           // 3
54    &rpc_thread_user_create_server,     // 4
55    &rpc_thread_kernel_create_server,   // 5
56    &rpc_signal_rise_server,            // 6                       
57    &rpc_undefined,                     // 7
58    &rpc_undefined,                     // 8
59    &rpc_undefined,                     // 9
60
61    &rpc_vfs_inode_create_server,       // 10 
62    &rpc_vfs_inode_destroy_server,      // 11 
63    &rpc_vfs_dentry_create_server,      // 12 
64    &rpc_vfs_dentry_destroy_server,     // 13 
65    &rpc_vfs_file_create_server,        // 14
66    &rpc_vfs_file_destroy_server,       // 15
67    &rpc_vfs_inode_load_server,         // 16
68    &rpc_vfs_mapper_load_all_server,    // 17
69    &rpc_fatfs_get_cluster_server,      // 18
70    &rpc_undefined,                     // 19
71
72    &rpc_vmm_get_ref_vseg_server,       // 20
73    &rpc_vmm_get_pte_server,            // 21
74    &rpc_kcm_alloc_server,              // 22
75    &rpc_kcm_free_server,               // 23
76    &rpc_mapper_move_buffer_server,     // 24
77    &rpc_undefined,                     // 25
78    &rpc_undefined,                     // 26
79    &rpc_undefined,                     // 27
80    &rpc_undefined,                     // 28
81    &rpc_undefined,                     // 29
82};
83
84//////////////////////////////////////////////
85void __attribute__((noinline)) rpc_undefined()
86{
87    printk("\n[PANIC] ‰s called in cluster %x\n", __FUNCTION__ , local_cxy );
88    hal_core_sleep();
89}
90
91/////////////////////////////////////////////////////////////////////////////////////////
92// [0]           Marshaling functions attached to RPC_PMEM_GET_PAGES
93/////////////////////////////////////////////////////////////////////////////////////////
94
95///////////////////////////////////////////////
96void rpc_pmem_get_pages_client( cxy_t      cxy,
97                                uint32_t   order,      // in
98                                error_t  * error,      // out
99                                uint32_t * ppn )       // out
100{
101    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
102
103    // initialise RPC descriptor header
104    rpc_desc_t  rpc;
105    rpc.index    = RPC_PMEM_GET_PAGES;
106    rpc.response = 1;
107
108    // set input arguments in RPC descriptor
109    rpc.args[0] = (uint64_t)order;
110
111    // register RPC request in remote RPC fifo (blocking function)
112    rpc_send_sync( cxy , &rpc );
113
114    // get output arguments RPC descriptor
115    *error  = (error_t)rpc.args[0];     
116    *ppn    = (uint32_t)rpc.args[1];
117}
118
119///////////////////////////////////////////
120void rpc_pmem_get_pages_server( xptr_t xp )
121{
122    uint32_t order;  // input
123    error_t  error;  // output
124    uint32_t ppn;    // output
125
126    // get client cluster identifier and pointer on RPC descriptor
127    cxy_t        cxy  = (cxy_t)GET_CXY( xp );
128    rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp );
129
130    // get input arguments from client RPC descriptor
131    order = hal_remote_lw( XPTR( cxy , &desc->args[0] ) );
132   
133    // call local pmem allocator
134    page_t * page = ppm_alloc_pages( order ); 
135    error = ( page == NULL ) ? ENOMEM : 0;
136    ppn   = ppm_page2ppn( page );
137
138    // set output arguments into client RPC descriptor
139    hal_remote_sw( XPTR( cxy , &desc->args[0] ) , error );
140    hal_remote_sw( XPTR( cxy , &desc->args[1] ) , ppn );
141}
142
143/////////////////////////////////////////////////////////////////////////////////////////
144// [1]           Marshaling functions attached to RPC_PROCESS_PID_ALLOC
145/////////////////////////////////////////////////////////////////////////////////////////
146
147//////////////////////////////////////////////////
148void rpc_process_pid_alloc_client( cxy_t       cxy, 
149                                   process_t * process,  // in
150                                   error_t   * error,    // out
151                                   pid_t     * pid )     // out
152{
153    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
154
155    // initialise RPC descriptor header
156    rpc_desc_t  rpc;
157    rpc.index    = RPC_PROCESS_PID_ALLOC;
158    rpc.response = 1;
159
160    // set input arguments in RPC descriptor
161    rpc.args[0] = (uint64_t)(intptr_t)process;
162
163    // register RPC request in remote RPC fifo (blocking function)
164    rpc_send_sync( cxy , &rpc );
165
166    // get output arguments RPC descriptor
167    *pid    = (pid_t)rpc.args[1];
168    *error  = (error_t)rpc.args[2];     
169}
170
171//////////////////////////////////////////////
172void rpc_process_pid_alloc_server( xptr_t xp )
173{
174    process_t * process;   // input  : client process descriptor
175    error_t     error;     // output : error status
176    pid_t       pid;       // output : process identifier
177
178    // get client cluster identifier and pointer on RPC descriptor
179    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
180    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
181
182    // get input argument from client RPC descriptor
183    process = (process_t*)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
184   
185    // call local pid allocator
186    xptr_t xp_process = XPTR( client_cxy , process );
187    error = cluster_pid_alloc( xp_process , &pid ); 
188
189    // set output arguments into client RPC descriptor
190    hal_remote_sw( XPTR( client_cxy , &desc->args[0] ) , (uint64_t)error );
191    hal_remote_sw( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)pid );
192}
193
194
195/////////////////////////////////////////////////////////////////////////////////////////
196// [2]           Marshaling functions attached to RPC_PROCESS_EXEC
197/////////////////////////////////////////////////////////////////////////////////////////
198
199////////////////////////////////////////////////
200void rpc_process_exec_client( cxy_t         cxy,
201                              exec_info_t * info,     // in
202                              error_t     * error )   // out
203{
204    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
205
206    // initialise RPC descriptor header
207    rpc_desc_t  rpc;
208    rpc.index    = RPC_PROCESS_EXEC;
209    rpc.response = 1;
210
211    // set input arguments in RPC descriptor 
212    rpc.args[0] = (uint64_t)(intptr_t)info;
213
214    // register RPC request in remote RPC fifo (blocking function)
215    rpc_send_sync( cxy , &rpc );
216
217    // get output arguments from RPC descriptor
218    *error  = (error_t)rpc.args[1];     
219}
220
221/////////////////////////////////////////
222void rpc_process_exec_server( xptr_t xp )
223{
224    exec_info_t * ptr;       // local pointer on remote exec_info structure
225    exec_info_t   info;      // local copy of exec_info structure
226    error_t       error;     // local error error status
227
228    // get client cluster identifier and pointer on RPC descriptor
229    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
230    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
231
232    // get pointer on exec_info structure in client cluster from RPC descriptor
233    ptr = (exec_info_t*)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
234
235    // copy exec_info structure from client buffer to server buffer
236    hal_remote_memcpy( XPTR( client_cxy , ptr ),
237                       XPTR( local_cxy , &info ),
238                       sizeof(exec_info_t) );
239
240    // call local kernel function
241    error = process_make_exec( &info ); 
242
243    // set output argument into client RPC descriptor
244    hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)error );
245}
246
247
248/////////////////////////////////////////////////////////////////////////////////////////
249// [3]           Marshaling functions attached to RPC_PROCESS_KILL
250/////////////////////////////////////////////////////////////////////////////////////////
251
252///////////////////////////////////////////////////
253void rpc_process_kill_client( process_t * process ) 
254{
255    // only reference cluster can send this RPC
256    assert( (GET_CXY( process->ref_xp ) == local_cxy) , __FUNCTION__ ,
257            "caller must be reference process cluster\n");
258
259    // get local process index in reference cluster
260    lpid_t lpid = LPID_FROM_PID( process->pid );
261
262    // get local process manager pointer
263    pmgr_t * pmgr = &LOCAL_CLUSTER->pmgr;
264
265    // get number of copies
266    uint32_t copies = pmgr->copies_nr[lpid];
267
268    // initialise RPC descriptor
269    rpc_desc_t  rpc;
270    rpc.index    = RPC_PROCESS_KILL;
271    rpc.response = copies;
272    rpc.args[0]  = (uint64_t)process->pid;
273
274    // loop on list of copies to send RPC
275    xptr_t  iter;
276    XLIST_FOREACH( XPTR( local_cxy , &pmgr->copies_root[lpid] ) , iter )
277    {
278        // get cluster_identifier for current copy
279        cxy_t  target_cxy = GET_CXY( iter );
280
281        // register RPC request in remote RPC fifo ... but the reference
282        if( target_cxy != local_cxy ) rpc_send_sync( target_cxy , &rpc );
283    }
284} 
285
286/////////////////////////////////////////
287void rpc_process_kill_server( xptr_t xp )
288{
289    pid_t       pid;
290    process_t * process; 
291
292    // get client cluster identifier and pointer on RPC descriptor
293    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
294    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
295
296    // get pid argument from RPC descriptor
297    pid = (pid_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
298
299    // get process pointer to call local kernel function
300    process = cluster_get_local_process_from_pid( pid );
301
302    if( process == NULL )  // process not found => do nothing
303    {
304        printk("\n[WARNING] in %s : process %x not found in cluster %x\n",
305               __FUNCTION__ , pid , local_cxy );
306    }
307    else                   // destroy process
308    {
309        process_kill( process ); 
310    }
311} 
312
313
314/////////////////////////////////////////////////////////////////////////////////////////
315// [4]           Marshaling functions attached to RPC_THREAD_USER_CREATE               
316/////////////////////////////////////////////////////////////////////////////////////////
317
318/////////////////////////////////////////////////////////
319void rpc_thread_user_create_client( cxy_t            cxy, 
320                                    pid_t            pid,         // in
321                                    void           * start_func,  // in
322                                    void           * start_arg,   // in
323                                    pthread_attr_t * attr,        // in
324                                    xptr_t         * thread_xp,   // out
325                                    error_t        * error )      // out
326{
327    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
328
329    // initialise RPC descriptor header
330    rpc_desc_t  rpc;
331    rpc.index    = RPC_THREAD_USER_CREATE;
332    rpc.response = 1;
333
334    // set input arguments in RPC descriptor
335    rpc.args[0] = (uint64_t)pid;
336    rpc.args[1] = (uint64_t)(intptr_t)start_func;
337    rpc.args[2] = (uint64_t)(intptr_t)start_arg;
338    rpc.args[3] = (uint64_t)(intptr_t)attr;
339
340    // register RPC request in remote RPC fifo
341    rpc_send_sync( cxy , &rpc );
342
343    // get output arguments from RPC descriptor
344    *thread_xp = (xptr_t)rpc.args[4];
345    *error     = (error_t)rpc.args[5];
346}
347
348///////////////////////////////////////////////
349void rpc_thread_user_create_server( xptr_t xp )
350{
351    pthread_attr_t * attr_ptr;   // pointer on attributes structure in client cluster
352    pthread_attr_t   attr_copy;  // attributes structure  copy in server cluster
353    thread_t       * thread_ptr; // local pointer on thread descriptor
354    xptr_t           thread_xp;  // extended pointer on thread descriptor
355
356    pid_t            pid;        // process identifier
357    void           * start_func;
358    void           * start_arg;
359    error_t          error;
360
361    // get client cluster identifier and pointer on RPC descriptor
362    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
363    rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp );
364
365    // get pointer on attributes structure in client cluster from RPC descriptor
366
367    // get input arguments from RPC descriptor
368    pid        = (pid_t)                     hal_remote_lwd(XPTR(client_cxy , &desc->args[0]));
369    start_func = (void *)(intptr_t)          hal_remote_lwd(XPTR(client_cxy , &desc->args[1]));
370    start_arg  = (void *)(intptr_t)          hal_remote_lwd(XPTR(client_cxy , &desc->args[2]));
371    attr_ptr   = (pthread_attr_t *)(intptr_t)hal_remote_lwd(XPTR(client_cxy , &desc->args[3]));
372
373    // makes a local copy of attributes structure
374    hal_remote_memcpy( XPTR( local_cxy , &attr_copy ),
375                       XPTR( client_cxy , attr_ptr ), 
376                       sizeof(pthread_attr_t) );
377   
378    assert( (attr_copy.cxy == local_cxy) , __FUNCTION__ , "bad target cluster\n" );
379
380    // call kernel function
381    error = thread_user_create( pid,
382                                start_func,
383                                start_arg,
384                                &attr_copy,
385                                &thread_ptr );
386
387    // set output arguments
388    thread_xp = XPTR( local_cxy , thread_ptr );
389    hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)error );
390    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)thread_xp );
391}
392
393/////////////////////////////////////////////////////////////////////////////////////////
394// [5]           Marshaling functions attached to RPC_THREAD_KERNEL_CREATE
395/////////////////////////////////////////////////////////////////////////////////////////
396
397////////////////////////////////////////////////////
398void rpc_thread_kernel_create_client( cxy_t     cxy,
399                                      uint32_t  type,        // in
400                                      void    * func,        // in
401                                      void    * args,        // in
402                                      xptr_t  * thread_xp,   // out
403                                      error_t * error )      // out
404{
405    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
406
407    // initialise RPC descriptor header
408    rpc_desc_t  rpc;
409    rpc.index    = RPC_THREAD_KERNEL_CREATE;
410    rpc.response = 1;
411
412    // set input arguments in RPC descriptor
413    rpc.args[0] = (uint64_t)type;
414    rpc.args[1] = (uint64_t)(intptr_t)func;
415    rpc.args[2] = (uint64_t)(intptr_t)args;
416   
417    // register RPC request in remote RPC fifo
418    rpc_send_sync( cxy , &rpc );
419
420    // get output arguments from RPC descriptor
421    *thread_xp = (xptr_t)rpc.args[3];
422    *error     = (error_t)rpc.args[4];
423}
424
425/////////////////////////////////////////////////
426void rpc_thread_kernel_create_server( xptr_t xp )
427{
428    thread_t       * thread_ptr;  // local pointer on thread descriptor
429    xptr_t           thread_xp;   // extended pointer on thread descriptor
430    lid_t            core_lid;    // core local index
431    error_t          error;   
432
433    // get client cluster identifier and pointer on RPC descriptor
434    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
435    rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp );
436
437    // get attributes from RPC descriptor
438    uint32_t  type = (uint32_t)       hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
439    void    * func = (void*)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
440    void    * args = (void*)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
441
442    // select one core
443    core_lid = cluster_select_local_core();
444
445    // call local kernel function
446    error = thread_kernel_create( &thread_ptr , type , func , args , core_lid );
447
448    // set output arguments
449    thread_xp = XPTR( local_cxy , thread_ptr );
450    hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)error );
451    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)thread_xp );
452}
453
454/////////////////////////////////////////////////////////////////////////////////////////
455// [6]           Marshaling functions attached to RPC_SIGNAL_RISE
456/////////////////////////////////////////////////////////////////////////////////////////
457
458/////////////////////////////////////////////
459void rpc_signal_rise_client( cxy_t       cxy,
460                             process_t * process,    // in
461                             uint32_t    sig_id )    // in
462{
463    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
464
465    // initialise RPC descriptor header
466    rpc_desc_t  rpc;
467    rpc.index    = RPC_SIGNAL_RISE;
468    rpc.response = 1;
469
470    // set input arguments in RPC descriptor
471    rpc.args[0] = (uint64_t)(intptr_t)process;
472    rpc.args[1] = (uint64_t)sig_id;
473   
474    // register RPC request in remote RPC fifo
475    rpc_send_sync( cxy , &rpc );
476}
477
478////////////////////////////////////////                             
479void rpc_signal_rise_server( xptr_t xp )
480{
481    process_t  * process;  // local pointer on process descriptor
482    uint32_t     sig_id;   // signal index
483
484    // get client cluster identifier and pointer on RPC descriptor
485    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
486    rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp );
487
488    // get attributes from RPC descriptor
489    process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
490    sig_id  = (uint32_t)             hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
491
492    // call local kernel function
493    signal_rise( process , sig_id );
494}
495
496/////////////////////////////////////////////////////////////////////////////////////////
497// [10]          Marshaling functions attached to RPC_VFS_INODE_CREATE
498/////////////////////////////////////////////////////////////////////////////////////////
499
500/////////////////////////////////////////////////////
501void rpc_vfs_inode_create_client( cxy_t          cxy,     
502                                  xptr_t         dentry_xp,  // in
503                                  uint32_t       fs_type,    // in
504                                  uint32_t       inode_type, // in
505                                  void         * extend,     // in
506                                  uint32_t       attr,       // in
507                                  uint32_t       rights,     // in
508                                  uint32_t       uid,        // in
509                                  uint32_t       gid,        // in
510                                  xptr_t       * inode_xp,   // out
511                                  error_t      * error )     // out
512{
513    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
514
515    // initialise RPC descriptor header
516    rpc_desc_t  rpc;
517    rpc.index    = RPC_VFS_INODE_CREATE;
518    rpc.response = 1;
519
520    // set input arguments in RPC descriptor
521    rpc.args[0] = (uint64_t)dentry_xp;
522    rpc.args[1] = (uint64_t)fs_type;
523    rpc.args[2] = (uint64_t)inode_type;
524    rpc.args[3] = (uint64_t)(intptr_t)extend;
525    rpc.args[4] = (uint64_t)attr;
526    rpc.args[5] = (uint64_t)rights;
527    rpc.args[6] = (uint64_t)uid;
528    rpc.args[7] = (uint64_t)gid;
529
530    // register RPC request in remote RPC fifo (blocking function)
531    rpc_send_sync( cxy , &rpc );
532
533    // get output values from RPC descriptor
534    *inode_xp = (xptr_t)rpc.args[8];
535    *error    = (error_t)rpc.args[9];
536}
537
538/////////////////////////////////////////////
539void rpc_vfs_inode_create_server( xptr_t xp )
540{
541    xptr_t           dentry_xp;
542    uint32_t         fs_type;
543    uint32_t         inode_type;
544    void           * extend;
545    uint32_t         attr;
546    uint32_t         rights;
547    uint32_t         uid;
548    uint32_t         gid;
549    xptr_t           inode_xp;
550    error_t          error;
551
552    // get client cluster identifier and pointer on RPC descriptor
553    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
554    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
555
556    // get input arguments from client rpc descriptor
557    dentry_xp  = (xptr_t)          hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
558    fs_type    = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
559    inode_type = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
560    extend     = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) );
561    attr       = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
562    rights     = (uint32_t)        hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) );
563    uid        = (uid_t)           hal_remote_lwd( XPTR( client_cxy , &desc->args[6] ) );
564    gid        = (gid_t)           hal_remote_lwd( XPTR( client_cxy , &desc->args[7] ) );
565
566    // call local kernel function
567    error = vfs_inode_create( dentry_xp,
568                              fs_type,
569                              inode_type,
570                              extend,
571                              attr,
572                              rights,
573                              uid,
574                              gid,
575                              &inode_xp );
576
577    // set output arguments
578    hal_remote_swd( XPTR( client_cxy , &desc->args[8] ) , (uint64_t)inode_xp );
579    hal_remote_swd( XPTR( client_cxy , &desc->args[9] ) , (uint64_t)error );
580}
581
582/////////////////////////////////////////////////////////////////////////////////////////
583// [11]          Marshaling functions attached to RPC_VFS_INODE_DESTROY
584/////////////////////////////////////////////////////////////////////////////////////////
585
586/////////////////////////////////////////////////////////////
587void rpc_vfs_inode_destroy_client( cxy_t                cxy,
588                                   struct vfs_inode_s * inode )
589{
590    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
591
592    // initialise RPC descriptor header
593    rpc_desc_t  rpc;
594    rpc.index    = RPC_VFS_INODE_DESTROY;
595    rpc.response = 1;
596
597    // set input arguments in RPC descriptor
598    rpc.args[0] = (uint64_t)(intptr_t)inode;
599   
600    // register RPC request in remote RPC fifo (blocking function)
601    rpc_send_sync( cxy , &rpc );
602}
603
604//////////////////////////////////////////////
605void rpc_vfs_inode_destroy_server( xptr_t xp )
606{
607    vfs_inode_t * inode;
608
609    // get client cluster identifier and pointer on RPC descriptor
610    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
611    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
612
613    // get arguments "inode" from client RPC descriptor
614    inode = (vfs_inode_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
615                       
616    // call local kernel function
617    vfs_inode_destroy( inode );
618}
619
620/////////////////////////////////////////////////////////////////////////////////////////
621// [12]          Marshaling functions attached to RPC_VFS_DENTRY_CREATE
622/////////////////////////////////////////////////////////////////////////////////////////
623
624//////////////////////////////////////////////////////////////
625void rpc_vfs_dentry_create_client( cxy_t                  cxy,
626                                   uint32_t               type,         // in
627                                   char                 * name,         // in
628                                   struct vfs_inode_s   * parent,       // in
629                                   xptr_t               * dentry_xp,    // out
630                                   error_t              * error )       // out
631{
632    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
633
634    // initialise RPC descriptor header
635    rpc_desc_t  rpc;
636    rpc.index    = RPC_VFS_DENTRY_CREATE;
637    rpc.response = 1;
638
639    // set input arguments in RPC descriptor
640    rpc.args[0] = (uint64_t)type;
641    rpc.args[1] = (uint64_t)(intptr_t)name;
642    rpc.args[2] = (uint64_t)(intptr_t)parent;
643
644    // register RPC request in remote RPC fifo (blocking function)
645    rpc_send_sync( cxy , &rpc );
646
647    // get output values from RPC descriptor
648    *dentry_xp = (xptr_t)rpc.args[3];
649    *error     = (error_t)rpc.args[4];
650}
651
652//////////////////////////////////////////////
653void rpc_vfs_dentry_create_server( xptr_t xp )
654{
655    uint32_t      type;
656    char        * name;
657    vfs_inode_t * parent;
658    xptr_t        dentry_xp;
659    error_t       error;
660
661    char          name_copy[CONFIG_VFS_MAX_NAME_LENGTH];
662
663    // get client cluster identifier and pointer on RPC descriptor
664    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
665    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
666
667    // get arguments "name", "type", and "parent" from client RPC descriptor
668    type   = (uint32_t)               hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
669    name   = (char *)(intptr_t)       hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
670    parent = (vfs_inode_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
671                       
672    // makes a local copy of  name
673    hal_remote_strcpy( XPTR( local_cxy , name_copy ),
674                       XPTR( client_cxy , name ) );
675
676    // call local kernel function
677    error = vfs_dentry_create( type,
678                               name_copy,
679                               parent,
680                               &dentry_xp );
681 
682    // set output arguments
683    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)dentry_xp );
684    hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error );
685}
686
687/////////////////////////////////////////////////////////////////////////////////////////
688// [13]          Marshaling functions attached to RPC_VFS_DENTRY_DESTROY
689/////////////////////////////////////////////////////////////////////////////////////////
690
691///////////////////////////////////////////////////////
692void rpc_vfs_dentry_destroy_client( cxy_t          cxy,
693                                    vfs_dentry_t * dentry )
694{
695    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
696
697    // initialise RPC descriptor header
698    rpc_desc_t  rpc;
699    rpc.index    = RPC_VFS_DENTRY_DESTROY;
700    rpc.response = 1;
701
702    // set input arguments in RPC descriptor
703    rpc.args[0] = (uint64_t)(intptr_t)dentry;
704   
705    // register RPC request in remote RPC fifo (blocking function)
706    rpc_send_sync( cxy , &rpc );
707}
708
709///////////////////////////////////////////////
710void rpc_vfs_dentry_destroy_server( xptr_t xp )
711{
712    vfs_dentry_t * dentry;
713
714    // get client cluster identifier and pointer on RPC descriptor
715    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
716    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
717
718    // get arguments "dentry" from client RPC descriptor
719    dentry = (vfs_dentry_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
720                       
721    // call local kernel function
722    vfs_dentry_destroy( dentry );
723}
724
725
726/////////////////////////////////////////////////////////////////////////////////////////
727// [14]          Marshaling functions attached to RPC_VFS_FILE_CREATE
728/////////////////////////////////////////////////////////////////////////////////////////
729
730//////////////////////////////////////////////////////////////
731void rpc_vfs_file_create_client( cxy_t                  cxy,
732                                 struct vfs_inode_s   * inode,       // in
733                                 uint32_t               file_attr,   // in
734                                 xptr_t               * file_xp,     // out
735                                 error_t              * error )      // out
736{
737    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
738
739    // initialise RPC descriptor header
740    rpc_desc_t  rpc;
741    rpc.index    = RPC_VFS_FILE_CREATE;
742    rpc.response = 1;
743
744    // set input arguments in RPC descriptor
745    rpc.args[0] = (uint64_t)(intptr_t)inode;
746    rpc.args[1] = (uint64_t)file_attr;
747
748    // register RPC request in remote RPC fifo (blocking function)
749    rpc_send_sync( cxy , &rpc );
750
751    // get output values from RPC descriptor
752    *file_xp = (xptr_t)rpc.args[2];
753    *error   = (error_t)rpc.args[3];
754}
755
756////////////////////////////////////////////
757void rpc_vfs_file_create_server( xptr_t xp )
758{
759    uint32_t      file_attr;
760    vfs_inode_t * inode;
761    xptr_t        file_xp;
762    error_t       error;
763
764    // get client cluster identifier and pointer on RPC descriptor
765    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
766    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
767
768    // get arguments "file_attr" and "inode" from client RPC descriptor
769    inode     = (vfs_inode_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
770    file_attr = (uint32_t)               hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
771                       
772    // call local kernel function
773    error = vfs_file_create( inode,
774                             file_attr,
775                             &file_xp );
776 
777    // set output arguments
778    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)file_xp );
779    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error );
780}
781
782/////////////////////////////////////////////////////////////////////////////////////////
783// [15]          Marshaling functions attached to RPC_VFS_FILE_DESTROY
784/////////////////////////////////////////////////////////////////////////////////////////
785
786///////////////////////////////////////////////////
787void rpc_vfs_file_destroy_client( cxy_t        cxy,
788                                  vfs_file_t * file )
789{
790    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
791
792    // initialise RPC descriptor header
793    rpc_desc_t  rpc;
794    rpc.index    = RPC_VFS_FILE_DESTROY;
795    rpc.response = 1;
796
797    // set input arguments in RPC descriptor
798    rpc.args[0] = (uint64_t)(intptr_t)file;
799   
800    // register RPC request in remote RPC fifo (blocking function)
801    rpc_send_sync( cxy , &rpc );
802}
803
804/////////////////////////////////////////////
805void rpc_vfs_file_destroy_server( xptr_t xp )
806{
807    vfs_file_t * file;
808
809    // get client cluster identifier and pointer on RPC descriptor
810    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
811    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
812
813    // get arguments "dentry" from client RPC descriptor
814    file = (vfs_file_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
815                       
816    // call local kernel function
817    vfs_file_destroy( file );
818}
819
820/////////////////////////////////////////////////////////////////////////////////////////
821// [16]          Marshaling functions attached to RPC_VFS_INODE_LOAD 
822/////////////////////////////////////////////////////////////////////////////////////////
823
824//////////////////////////////////////////////////
825void rpc_vfs_inode_load_client( cxy_t         cxy,
826                                vfs_inode_t * parent_inode,    // in
827                                char        * name,            // in
828                                xptr_t        child_inode_xp,  // in
829                                error_t     * error )          // out
830{
831    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
832
833    // initialise RPC descriptor header
834    rpc_desc_t  rpc;
835    rpc.index    = RPC_VFS_INODE_LOAD;
836    rpc.response = 1;
837
838    // set input arguments in RPC descriptor
839    rpc.args[0] = (uint64_t)(intptr_t)parent_inode;
840    rpc.args[1] = (uint64_t)(intptr_t)name;
841    rpc.args[2] = (uint64_t)child_inode_xp;
842
843    // register RPC request in remote RPC fifo (blocking function)
844    rpc_send_sync( cxy , &rpc );
845
846    // get output values from RPC descriptor
847    *error   = (error_t)rpc.args[3];
848}
849
850///////////////////////////////////////////
851void rpc_vfs_inode_load_server( xptr_t xp )
852{
853    error_t       error;
854    vfs_inode_t * parent;
855    xptr_t        child_xp;
856    char        * name;
857
858    char          name_copy[CONFIG_VFS_MAX_NAME_LENGTH];
859
860    // get client cluster identifier and pointer on RPC descriptor
861    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
862    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
863
864    // get arguments "parent", "name", and "child_xp"
865    parent     = (vfs_inode_t*)(intptr_t)hal_remote_lwd(XPTR(client_cxy , &desc->args[0]));
866    name       = (char*)(intptr_t)       hal_remote_lwd(XPTR(client_cxy , &desc->args[1]));
867    child_xp   = (xptr_t)                hal_remote_lwd(XPTR(client_cxy , &desc->args[2]));
868
869    // get name local copy
870    hal_remote_strcpy( XPTR( local_cxy , name_copy ) ,
871                       XPTR( client_cxy , name ) );
872
873    // call the kernel function
874    error = vfs_inode_load( parent , name_copy , child_xp );
875
876    // set output argument
877    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error );
878}
879
880/////////////////////////////////////////////////////////////////////////////////////////
881// [17]          Marshaling functions attached to RPC_VFS_MAPPER_LOAD_ALL
882/////////////////////////////////////////////////////////////////////////////////////////
883
884///////////////////////////////////////////////////////
885void rpc_vfs_mapper_load_all_client( cxy_t         cxy,
886                                     vfs_inode_t * inode,      // in
887                                     error_t     * error )     // out
888{
889    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
890
891    // initialise RPC descriptor header
892    rpc_desc_t  rpc;
893    rpc.index    = RPC_VFS_INODE_LOAD;
894    rpc.response = 1;
895
896    // set input arguments in RPC descriptor
897    rpc.args[0] = (uint64_t)(intptr_t)inode;
898
899    // register RPC request in remote RPC fifo (blocking function)
900    rpc_send_sync( cxy , &rpc );
901
902    // get output values from RPC descriptor
903    *error   = (error_t)rpc.args[1];
904}
905
906////////////////////////////////////////////////
907void rpc_vfs_mapper_load_all_server( xptr_t xp )
908{
909    error_t       error;
910    vfs_inode_t * inode;
911
912    // get client cluster identifier and pointer on RPC descriptor
913    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
914    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
915
916    // get arguments "parent", "name", and "child_xp"
917    inode = (vfs_inode_t*)(intptr_t)hal_remote_lwd(XPTR(client_cxy , &desc->args[0]));
918
919    // call the kernel function
920    error = vfs_mapper_load_all( inode );
921
922    // set output argument
923    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)error );
924}
925
926/////////////////////////////////////////////////////////////////////////////////////////
927// [18]          Marshaling functions attached to RPC_FATFS_GET_CLUSTER
928/////////////////////////////////////////////////////////////////////////////////////////
929
930//////////////////////////////////////////////////
931void rpc_fatfs_get_cluster_client( cxy_t      cxy,
932                                   mapper_t * mapper,    // in
933                                   uint32_t   first,     // in
934                                   uint32_t   page,      // in
935                                   uint32_t * cluster,   // out
936                                   error_t  * error )    // out
937{
938    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
939
940    // initialise RPC descriptor header
941    rpc_desc_t  rpc;
942    rpc.index    = RPC_FATFS_GET_CLUSTER;
943    rpc.response = 1;
944
945    // set input arguments in RPC descriptor
946    rpc.args[0] = (uint64_t)(intptr_t)mapper;
947    rpc.args[1] = (uint64_t)first;
948    rpc.args[2] = (uint64_t)page;
949
950    // register RPC request in remote RPC fifo
951    rpc_send_sync( cxy , &rpc );
952
953    // get output argument from rpc descriptor
954    *cluster = (uint32_t)rpc.args[3];
955    *error   = (error_t)rpc.args[4];
956}
957
958//////////////////////////////////////////////
959void rpc_fatfs_get_cluster_server( xptr_t xp )
960{
961    mapper_t    * mapper;
962    uint32_t      first;
963    uint32_t      page;
964    uint32_t      cluster;
965    error_t       error;
966
967    // get client cluster identifier and pointer on RPC descriptor
968    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
969    rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp );
970
971    // get input arguments
972    mapper = (mapper_t *)(intptr_t)hal_remote_lpt( XPTR( client_cxy , &desc->args[0] ) );
973    first  = (uint32_t)            hal_remote_lw ( XPTR( client_cxy , &desc->args[1] ) );
974    page   = (uint32_t)            hal_remote_lw ( XPTR( client_cxy , &desc->args[2] ) );
975
976    // call the kernel function
977    error = fatfs_get_cluster( mapper , first , page , &cluster );
978
979    // set output argument
980    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)cluster );
981    hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error );
982}
983
984/////////////////////////////////////////////////////////////////////////////////////////
985// [20]          Marshaling functions attached to RPC_VMM_GET_REF_VSEG
986/////////////////////////////////////////////////////////////////////////////////////////
987
988//////////////////////////////////////////////////
989void rpc_vmm_get_ref_vseg_client( cxy_t       cxy,     
990                                  process_t * process,     // in 
991                                  intptr_t    vaddr,       // in 
992                                  xptr_t    * vseg_xp )    // out
993{
994    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
995
996    // initialise RPC descriptor header
997    rpc_desc_t  rpc;
998    rpc.index    = RPC_VMM_GET_REF_VSEG;
999    rpc.response = 1;
1000
1001    // set input arguments in RPC descriptor
1002    rpc.args[0] = (uint64_t)(intptr_t)process;
1003    rpc.args[1] = (uint64_t)vaddr;
1004
1005    // register RPC request in remote RPC fifo (blocking function)
1006    rpc_send_sync( cxy , &rpc );
1007
1008    // get output argument from rpc descriptor
1009    *vseg_xp = rpc.args[2];
1010}
1011
1012/////////////////////////////////////////////
1013void rpc_vmm_get_ref_vseg_server( xptr_t xp )
1014{
1015    process_t   * process;
1016    intptr_t      vaddr;
1017    vseg_t      * vseg_ptr;
1018    xptr_t        vseg_xp;
1019
1020    // get client cluster identifier and pointer on RPC descriptor
1021    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
1022    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
1023
1024    // get input argument from client RPC descriptor
1025    process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1026    vaddr   = (intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1027   
1028    // call local kernel function
1029    vseg_ptr = vmm_get_vseg( process , vaddr );
1030
1031    // set output argument to client RPC descriptor
1032    if( vseg_ptr == NULL ) vseg_xp = XPTR_NULL;
1033    else                   vseg_xp = XPTR( local_cxy , vseg_ptr );
1034    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)vseg_xp );
1035}
1036
1037
1038/////////////////////////////////////////////////////////////////////////////////////////
1039// [21]          Marshaling functions attached to RPC_VMM_GET_PTE
1040/////////////////////////////////////////////////////////////////////////////////////////
1041
1042////////////////////////////////////////////
1043void rpc_vmm_get_pte_client( cxy_t       cxy,   
1044                             process_t * process,  // in
1045                             vpn_t       vpn,      // in
1046                             uint32_t  * attr,     // out
1047                             ppn_t     * ppn,      // out
1048                             error_t   * error )   // out
1049{
1050    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1051
1052    // initialise RPC descriptor header
1053    rpc_desc_t  rpc;
1054    rpc.index    = RPC_VMM_GET_PTE;
1055    rpc.response = 1;
1056
1057    // set input arguments in RPC descriptor
1058    rpc.args[0] = (uint64_t)(intptr_t)process;
1059    rpc.args[1] = (uint64_t)vpn;
1060
1061    // register RPC request in remote RPC fifo (blocking function)
1062    rpc_send_sync( cxy , &rpc );
1063
1064    // get output argument from rpc descriptor
1065    *attr  = (uint32_t)rpc.args[2];
1066    *ppn   = (ppn_t)rpc.args[3];
1067    *error = (error_t)rpc.args[4];
1068}
1069
1070////////////////////////////////////////
1071void rpc_vmm_get_pte_server( xptr_t xp )
1072{
1073    process_t   * process;
1074    vpn_t         vpn;
1075    uint32_t      attr;
1076    ppn_t         ppn;
1077    error_t       error;
1078
1079    // get client cluster identifier and pointer on RPC descriptor
1080    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
1081    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
1082
1083    // get input argument "process" & "vpn" from client RPC descriptor
1084    process = (process_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1085    vpn     = (vpn_t)                hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1086   
1087    // call local kernel function
1088    error = vmm_get_pte( process , vpn , &attr , &ppn ); 
1089
1090    // set output argument "attr" & "ppn" to client RPC descriptor
1091    hal_remote_swd( XPTR( client_cxy , &desc->args[2] ) , (uint64_t)attr );
1092    hal_remote_swd( XPTR( client_cxy , &desc->args[3] ) , (uint64_t)ppn );
1093    hal_remote_swd( XPTR( client_cxy , &desc->args[4] ) , (uint64_t)error );
1094}
1095
1096/////////////////////////////////////////////////////////////////////////////////////////
1097// [22]          Marshaling functions attached to RPC_KCM_ALLOC
1098/////////////////////////////////////////////////////////////////////////////////////////
1099
1100//////////////////////////////////////////
1101void rpc_kcm_alloc_client( cxy_t      cxy,
1102                           uint32_t   kmem_type,   // in
1103                           xptr_t *   buf_xp )     // out
1104{
1105    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1106
1107    // initialise RPC descriptor header
1108    rpc_desc_t  rpc;
1109    rpc.index    = RPC_THREAD_USER_CREATE;
1110    rpc.response = 1;
1111
1112    // set input arguments in RPC descriptor
1113    rpc.args[0] = (uint64_t)kmem_type;
1114
1115    // register RPC request in remote RPC fifo
1116    rpc_send_sync( cxy , &rpc );
1117
1118    // get output arguments from RPC descriptor
1119    *buf_xp = (xptr_t)rpc.args[1];
1120}
1121
1122//////////////////////////////////////
1123void rpc_kcm_alloc_server( xptr_t xp )
1124{
1125    // get client cluster identifier and pointer on RPC descriptor
1126    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
1127    rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp );
1128
1129    // get input argument "kmem_type" from client RPC descriptor
1130    uint32_t kmem_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1131
1132    // allocates memory for kcm
1133    kmem_req_t  req;
1134    req.type  = kmem_type;
1135    req.flags = AF_ZERO;
1136    void * buf_ptr = kmem_alloc( &req );
1137
1138    // set output argument
1139    xptr_t buf_xp = XPTR( local_cxy , buf_ptr );
1140    hal_remote_swd( XPTR( client_cxy , &desc->args[1] ) , (uint64_t)buf_xp );
1141}   
1142
1143/////////////////////////////////////////////////////////////////////////////////////////
1144// [23]          Marshaling functions attached to RPC_KCM_FREE
1145/////////////////////////////////////////////////////////////////////////////////////////
1146
1147/////////////////////////////////////////
1148void rpc_kcm_free_client( cxy_t      cxy,
1149                          void     * buf,          // in
1150                          uint32_t   kmem_type )   // in
1151{
1152    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1153
1154    // initialise RPC descriptor header
1155    rpc_desc_t  rpc;
1156    rpc.index    = RPC_THREAD_USER_CREATE;
1157    rpc.response = 1;
1158
1159    // set input arguments in RPC descriptor
1160    rpc.args[0] = (uint64_t)(intptr_t)buf;
1161    rpc.args[1] = (uint64_t)kmem_type;
1162
1163    // register RPC request in remote RPC fifo
1164    rpc_send_sync( cxy , &rpc );
1165}
1166
1167/////////////////////////////////////
1168void rpc_kcm_free_server( xptr_t xp )
1169{
1170    // get client cluster identifier and pointer on RPC descriptor
1171    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
1172    rpc_desc_t * desc = (rpc_desc_t *)GET_PTR( xp );
1173
1174    // get input arguments "buf" and "kmem_type" from client RPC descriptor
1175    void     * buf = (void *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1176    uint32_t   kmem_type = (uint32_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1177
1178    // releases memory
1179    kmem_req_t  req;
1180    req.type = kmem_type;
1181    req.ptr  = buf;
1182    kmem_free( &req );
1183}   
1184
1185/////////////////////////////////////////////////////////////////////////////////////////
1186// [24]          Marshaling functions attached to RPC_MAPPER_MOVE_BUFFER
1187/////////////////////////////////////////////////////////////////////////////////////////
1188
1189///////////////////////////////////////////////////
1190void rpc_mapper_move_buffer_client( cxy_t      cxy,
1191                                    mapper_t * mapper,        // in
1192                                    bool_t     to_buffer,     // in
1193                                    bool_t     is_user,       // in
1194                                    uint32_t   file_offset,   // in
1195                                    void     * buffer,        // in
1196                                    uint32_t   size,          // in
1197                                    error_t  * error )        // out
1198{
1199    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1200
1201    // initialise RPC descriptor header
1202    rpc_desc_t  rpc;
1203    rpc.index    = RPC_MAPPER_MOVE_BUFFER;
1204    rpc.response = 1;
1205
1206    // set input arguments in RPC descriptor
1207    rpc.args[0] = (uint64_t)(intptr_t)mapper;
1208    rpc.args[1] = (uint64_t)to_buffer;
1209    rpc.args[2] = (uint64_t)is_user;
1210    rpc.args[3] = (uint64_t)file_offset;
1211    rpc.args[4] = (uint64_t)(intptr_t)buffer;
1212    rpc.args[5] = (uint64_t)size;
1213
1214    // register RPC request in remote RPC fifo (blocking function)
1215    rpc_send_sync( cxy , &rpc );
1216
1217    // get output values from RPC descriptor
1218    *error     = (error_t)rpc.args[6];
1219}
1220
1221///////////////////////////////////////////////
1222void rpc_mapper_move_buffer_server( xptr_t xp )
1223{
1224    mapper_t * mapper;
1225    bool_t     to_buffer;
1226    bool_t     is_user;
1227    uint32_t   file_offset;
1228    void     * buffer;
1229    uint32_t   size;
1230    error_t    error;
1231
1232    // get client cluster identifier and pointer on RPC descriptor
1233    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
1234    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
1235
1236    // get arguments from client RPC descriptor
1237    mapper      = (mapper_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1238    to_buffer   =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1239    is_user     =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
1240    file_offset =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) );
1241    buffer      = (void     *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
1242    size        =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[5] ) );
1243
1244    // call local kernel function
1245    error = mapper_move_buffer( mapper,
1246                                to_buffer,
1247                                is_user,
1248                                file_offset,
1249                                buffer,
1250                                size );
1251
1252    // set output argument to client RPC descriptor
1253    hal_remote_swd( XPTR( client_cxy , &desc->args[6] ) , (uint64_t)error );
1254}
1255
1256/***************************************************************************************/
1257/************ Generic functions supporting RPCs : client side **************************/
1258/***************************************************************************************/
1259
1260////////////////////////////////////////////
1261void rpc_send_sync( cxy_t        server_cxy, 
1262                    rpc_desc_t * rpc )
1263{
1264        thread_t * this = CURRENT_THREAD;
1265    uint32_t   cores;
1266    error_t    error;
1267    bool_t     first;
1268    reg_t      sr_save;
1269
1270    // get client CPU and cluster coordinates
1271    cxy_t      client_cxy = local_cxy;   
1272    lid_t      client_lid = CURRENT_CORE->lid;
1273
1274    // allocate and initialise an extended pointer on the RPC descriptor
1275        xptr_t   xp = XPTR( client_cxy , rpc );
1276
1277    // get local pointer on rpc_fifo in remote cluster with the
1278    // assumption that addresses are identical in all clusters
1279    rpc_fifo_t * rf = &LOCAL_CLUSTER->rpc_fifo;
1280
1281        // try to post an item in remote fifo
1282    // deschedule and retry if remote fifo full
1283    do
1284    { 
1285        error = remote_fifo_put_item( XPTR( server_cxy , &rf->fifo ),
1286                                      (uint64_t *)&xp,
1287                                      &first );
1288
1289            if ( error ) 
1290        {
1291            printk("\n[WARNING] %s : core %d in cluster %x cannot post RPC to cluster %x\n",
1292                   __FUNCTION__ , client_lid , client_cxy , server_cxy );
1293            if( thread_can_yield() ) sched_yield();
1294        }
1295    }
1296    while( error );
1297 
1298    rpc_dmsg("\n[INFO] %s on core %d in cluster %x sent RPC %p to cluster %x\n", 
1299              __FUNCTION__ , client_lid , client_cxy , rpc , server_cxy );
1300       
1301    // send IPI if this is the first RPC in remote FIFO
1302    // and no CPU is in kernel mode in server cluster.
1303    // the selected CPU in server has the same lid as the client CPU.
1304        if( first )
1305        {
1306        // get number of cores in kernel mode in server cluster
1307        cores = hal_remote_lw( XPTR( server_cxy , &LOCAL_CLUSTER->cores_in_kernel ) );
1308
1309                if( cores == 0 ) // no core in kernel mode in server
1310                {
1311                    dev_pic_send_ipi( server_cxy , client_lid );
1312
1313                    rpc_dmsg("\n[INFO] %s : core %d in cluster %x send IPI to core %d in cluster %x\n",
1314                      __FUNCTION__, client_lid , client_cxy , client_lid , server_cxy );
1315        }
1316        }
1317
1318        // activate preemption to allow incoming RPC and avoid deadlock
1319        if( this->type == THREAD_RPC ) hal_enable_irq( &sr_save );
1320
1321    // the sending thread poll the response slot until RPC completed
1322        while( 1 )
1323    {
1324        if( rpc->response == 0 ) break;
1325    }
1326
1327    // restore preemption
1328        if( this->type == THREAD_RPC ) hal_restore_irq( sr_save );
1329
1330}  // end rpc_send_sync()
1331
1332
1333
1334/***************************************************************************************/
1335/************ Generic functions supporting RPCs : server side **************************/
1336/***************************************************************************************/
1337
1338///////////////////////////////////////////
1339void rpc_fifo_init( rpc_fifo_t * rpc_fifo )
1340{
1341        rpc_fifo->count       = 0;
1342        rpc_fifo->owner       = 0;
1343        local_fifo_init( &rpc_fifo->fifo );
1344}
1345
1346////////////////////////////////////////////////
1347error_t rpc_execute_all( rpc_fifo_t * rpc_fifo )
1348{
1349        xptr_t         xp;             // extended pointer on RPC descriptor
1350        uint32_t       count;          // handled RPC request counter
1351        thread_t     * this;           // pointer on this RPC thread
1352    core_t       * core;           // pointer on core running this thread
1353    rpc_desc_t   * desc;           // pointer on RPC descriptor
1354    uint32_t       index;          // RPC index
1355    uint32_t       expected;       // number of expected responses
1356    cxy_t          client_cxy;     // client cluster identifier
1357        error_t        error;
1358     
1359        this = CURRENT_THREAD; 
1360    core = this->core;   
1361
1362
1363    // handle up to CONFIG_RPC_PENDING_MAX requests before exit
1364        count = 0;
1365        do
1366    {
1367            error = local_fifo_get_item( &rpc_fifo->fifo, 
1368                                     (uint64_t *)&xp );
1369
1370                if ( error == 0 )  // One RPC request successfully extracted from RPC_FIFO
1371        {
1372            rpc_dmsg("\n[INFO] %s : RPC_THREAD %x on core %x in cluster %x handles RPC %d\n"
1373                                     __FUNCTION__ , this->trdid , core->lid , local_cxy , count );
1374
1375            // get client cluster identifier and pointer on RPC descriptor
1376            client_cxy = (cxy_t)GET_CXY( xp );
1377            desc       = (rpc_desc_t *)GET_PTR( xp );
1378
1379            // get rpc index and expected responses from RPC descriptor
1380                index     = hal_remote_lw( XPTR( client_cxy , &desc->index ) );
1381                expected  = hal_remote_lw( XPTR( client_cxy , &desc->response ) );
1382
1383            // call the relevant server function
1384            rpc_server[index]( xp );
1385
1386            // increment handled RPC counter
1387                count++;
1388
1389            // notify RPC completion as required
1390            if( expected == 1 ) hal_remote_sw( XPTR(client_cxy,&desc->response) , 0 );
1391            if( expected >  1 ) hal_remote_atomic_add( XPTR(client_cxy,&desc->response) , -1 );
1392                }
1393       
1394                // exit loop in three cases:
1395        // - fifo is empty
1396        // - look has been released (because descheduling)
1397        // - max number of RPCs has been reached
1398                if( error || 
1399            (rpc_fifo->owner != this->trdid) || 
1400            (count > CONFIG_RPC_PENDING_MAX) ) break;
1401        }
1402    while( 1 )
1403
1404        rpc_dmsg("\n[INFO] %s running on core %d in cluster %x exit\n"
1405              __FUNCTION__ , CURRENT_CORE->lid , local_cxy );
1406               
1407    // update RPC_FIFO global counter
1408        rpc_fifo->count += count;
1409
1410        return 0;
1411}  // end rpc_execute_all()
1412
1413////////////////////////////////////////////////////
1414error_t rpc_activate_thread( rpc_fifo_t * rpc_fifo )
1415{
1416        core_t      * core;
1417        thread_t    * thread;
1418        thread_t    * this;
1419    scheduler_t * sched;
1420        error_t       error;
1421    bool_t        found;
1422    reg_t         sr_save;
1423
1424        this   = CURRENT_THREAD;
1425    core   = this->core;
1426    sched  = &core->scheduler;
1427    found  = false;
1428
1429    // calling thread must be the RPC_FIFO owner
1430    if( this->trdid != rpc_fifo->owner )
1431    {
1432        printk("\n[PANIC] in %s : calling thread is not RPC_FIFO owner\n", __FUNCTION__ );
1433        hal_core_sleep();
1434    }
1435
1436    // makes the calling thread not preemptable
1437    // during activation / creation of the RPC thread
1438        hal_disable_irq( &sr_save );
1439
1440    // search a free RPC thread (must be in THREAD_BLOCKED_IDLE state)   
1441    list_entry_t * iter;
1442    LIST_FOREACH( &sched->k_root , iter )
1443    {
1444        thread = LIST_ELEMENT( iter , thread_t , sched_list );
1445        if( (thread->type == THREAD_RPC) && (thread->blocked ==  THREAD_BLOCKED_IDLE ) ) 
1446        {
1447            found = true;
1448            break;
1449        }
1450    }
1451
1452    if( found )                    // activate this idle RPC thread     
1453    {
1454        thread->blocked = 0;
1455    }
1456    else                           // create a new RPC thread
1457    {
1458        error = thread_kernel_create( &thread,
1459                                      THREAD_RPC, 
1460                                                  &rpc_thread_func, 
1461                                      NULL,
1462                                                  core->lid );
1463            if( error ) 
1464        {
1465                hal_restore_irq( sr_save );
1466            printk("\n[ERROR] in %s : no memory for new RPC thread in cluster %x\n",
1467                   __FUNCTION__ , local_cxy );
1468            return ENOMEM;
1469        }
1470
1471        rpc_dmsg("\n[INFO] %s creates RPC thread %x on core %x in cluster %x at cycle %d\n", 
1472                          __FUNCTION__ , thread , core->gid , local_cxy , hal_get_cycles() );
1473
1474        // update core descriptor counter 
1475            hal_atomic_add( &core->rpc_threads , 1 );
1476    }
1477
1478    // update owner in rpc_fifo
1479    rpc_fifo->owner = thread->trdid;
1480
1481    rpc_dmsg ("\n[INFO] %s activates RPC thread %x on core %x in cluster %x at cycle %d\n",
1482                      __FUNCTION__ , thread , core->gid , local_cxy , hal_get_cycles() );
1483
1484    // current thread deschedules / RPC thread start execution
1485        sched_switch_to( thread );
1486
1487    // restore IRQs for the calling thread
1488        hal_restore_irq( sr_save );
1489
1490    // return success
1491        return 0;
1492
1493}  // end rpc_activate_thread()
1494
1495//////////////////
1496bool_t rpc_check()
1497{
1498        thread_t   * this     = CURRENT_THREAD;
1499        rpc_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
1500    error_t      error;
1501
1502    // calling thread does nothing if light lock already taken or FIFO empty 
1503        if( (rpc_fifo->owner != 0) || (local_fifo_is_empty( &rpc_fifo->fifo )) )
1504    {
1505        return false;
1506    }
1507
1508        // calling thread tries to take the light lock,
1509    // and activates an RPC thread if success
1510    if( hal_atomic_test_set( &rpc_fifo->owner , this->trdid ) )
1511        {
1512        error = rpc_activate_thread( rpc_fifo );
1513
1514        if( error )    // cannot activate an RPC_THREAD
1515        {
1516            rpc_fifo->owner = 0;
1517
1518            printk("\n[ERROR] in %s : no memory to create a RPC thread for core %d"
1519                   " in cluster %x => do nothing\n",
1520                   __FUNCTION__ , CURRENT_CORE->lid , local_cxy );
1521        }
1522
1523        return true;
1524    }
1525    else  // light lock taken by another thread
1526    {
1527        return false;
1528    }
1529} // end rpc_check()
1530
1531
1532//////////////////////
1533void rpc_thread_func()
1534{
1535    // makes the calling thread not preemptable
1536        hal_disable_irq( NULL );
1537 
1538        thread_t   * this     = CURRENT_THREAD;
1539        rpc_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
1540
1541    rpc_dmsg("\n[INFO] RPC thread %x created on core %d in cluster %x at cycle %d\n",
1542             this->trdid , this->core->lid , local_cxy , hal_get_cycles() );
1543
1544    // this infinite loop is not preemptable
1545    // the RPC thread deschedule when the RPC_FIFO is empty
1546        while(1)
1547        {
1548        // check fifo ownership (ownership should be given by rpc_activate()
1549        if( this->trdid != rpc_fifo->owner )
1550        {
1551            printk("\n[PANIC] in %s : RPC_THREAD %x not owner of RPC_FIFO in cluster %x\n",
1552                   __FUNCTION__ , this->trdid , local_cxy );
1553            hal_core_sleep();
1554        }
1555 
1556        // executes pending RPC(s)
1557        rpc_execute_all( rpc_fifo );
1558
1559        // release rpc_fifo ownership (can be lost during RPC execution)
1560        if( rpc_fifo->owner == this->trdid ) rpc_fifo->owner = 0;
1561
1562
1563        // suicide if too much RPC threads for this core
1564                if( this->core->rpc_threads > CONFIG_RPC_THREADS_MAX ) 
1565                {
1566            rpc_dmsg("\n[INFO] RPC thread %x suicide on core %d in cluster %x at cycle %d\n", 
1567                             this->trdid , this->core->lid , local_cxy , hal_get_cycles() );
1568
1569            // update core descriptor counter
1570                hal_atomic_add( &this->core->rpc_threads , -1 );
1571
1572            // suicide
1573                        thread_exit();
1574                }
1575
1576        // block and deschedule
1577        rpc_dmsg("\n[INFO] RPC thread %x deschedule on core %d in cluster %x at cycle %d\n", 
1578                              this->trdid , this->core->lid , local_cxy , hal_get_cycles() ); 
1579
1580                thread_block( this , THREAD_BLOCKED_IDLE );
1581        sched_yield();
1582
1583                rpc_dmsg("\n[INFO] RPC thread %x wake up on core %d in cluster %x at cycle %d\n", 
1584                              this->trdid , this->core->lid , local_cxy , hal_get_cycles() );
1585        }
1586} // end rpc_thread_func()
1587
Note: See TracBrowser for help on using the repository browser.