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

Last change on this file since 248 was 248, checked in by max@…, 5 years ago

Don't include dev_icu.h when it's not needed.

File size: 57.7 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_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
1187/////////////////////////////////////////////////////////////////////////////////////////
1188
1189///////////////////////////////////////////
1190void rpc_mapper_move_client( cxy_t      cxy,
1191                             mapper_t * mapper,        // in
1192                             uint32_t   to_buffer,     // in
1193                             uint32_t   file_offset,   // in
1194                             void     * buffer,        // in
1195                             uint32_t   size,          // in
1196                             error_t  * error )        // out
1197{
1198    assert( (cxy != local_cxy) , __FUNCTION__ , "target cluster is not remote\n");
1199
1200    // initialise RPC descriptor header
1201    rpc_desc_t  rpc;
1202    rpc.index    = RPC_MAPPER_MOVE;
1203    rpc.response = 1;
1204
1205    // set input arguments in RPC descriptor
1206    rpc.args[0] = (uint64_t)(intptr_t)mapper;
1207    rpc.args[1] = (uint64_t)to_buffer;
1208    rpc.args[2] = (uint64_t)file_offset;
1209    rpc.args[3] = (uint64_t)(intptr_t)buffer;
1210    rpc.args[4] = (uint64_t)size;
1211
1212    // register RPC request in remote RPC fifo (blocking function)
1213    rpc_send_sync( cxy , &rpc );
1214
1215    // get output values from RPC descriptor
1216    *error     = (error_t)rpc.args[5];
1217}
1218
1219////////////////////////////////////////
1220void rpc_mapper_move_server( xptr_t xp )
1221{
1222    mapper_t * mapper;
1223    uint32_t   to_buffer;
1224    uint32_t   file_offset;
1225    void     * buffer;
1226    uint32_t   size;
1227    error_t    error;
1228
1229    // get client cluster identifier and pointer on RPC descriptor
1230    cxy_t        client_cxy  = (cxy_t)GET_CXY( xp );
1231    rpc_desc_t * desc        = (rpc_desc_t *)GET_PTR( xp );
1232
1233    // get arguments from client RPC descriptor
1234    mapper      = (mapper_t *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[0] ) );
1235    to_buffer   =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[1] ) );
1236    file_offset =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[2] ) );
1237    buffer      = (void     *)(intptr_t)hal_remote_lwd( XPTR( client_cxy , &desc->args[3] ) );
1238    size        =                       hal_remote_lwd( XPTR( client_cxy , &desc->args[4] ) );
1239
1240    // call local kernel function
1241    error = mapper_move( mapper,
1242                         to_buffer,
1243                         file_offset,
1244                         buffer,
1245                         size );
1246
1247    // set output argument to client RPC descriptor
1248    hal_remote_swd( XPTR( client_cxy , &desc->args[5] ) , (uint64_t)error );
1249}
1250
1251/***************************************************************************************/
1252/************ Generic functions supporting RPCs : client side **************************/
1253/***************************************************************************************/
1254
1255////////////////////////////////////////////
1256void rpc_send_sync( cxy_t        server_cxy, 
1257                    rpc_desc_t * rpc )
1258{
1259        thread_t * this = CURRENT_THREAD;
1260    uint32_t   cores;
1261    error_t    error;
1262    bool_t     first;
1263    reg_t      sr_save;
1264
1265    // get client CPU and cluster coordinates
1266    cxy_t      client_cxy = local_cxy;   
1267    lid_t      client_lid = CURRENT_CORE->lid;
1268
1269    // allocate and initialise an extended pointer on the RPC descriptor
1270        xptr_t   xp = XPTR( client_cxy , rpc );
1271
1272    // get local pointer on rpc_fifo in remote cluster with the
1273    // assumption that addresses are identical in all clusters
1274    rpc_fifo_t * rf = &LOCAL_CLUSTER->rpc_fifo;
1275
1276        // try to post an item in remote fifo
1277    // deschedule and retry if remote fifo full
1278    do
1279    { 
1280        error = remote_fifo_put_item( XPTR( server_cxy , &rf->fifo ),
1281                                      (uint64_t *)&xp,
1282                                      &first );
1283
1284            if ( error ) 
1285        {
1286            printk("\n[WARNING] %s : core %d in cluster %x cannot post RPC to cluster %x\n",
1287                   __FUNCTION__ , client_lid , client_cxy , server_cxy );
1288            if( thread_can_yield() ) sched_yield();
1289        }
1290    }
1291    while( error );
1292 
1293    rpc_dmsg("\n[INFO] %s on core %d in cluster %x sent RPC %p to cluster %x\n", 
1294              __FUNCTION__ , client_lid , client_cxy , rpc , server_cxy );
1295       
1296    // send IPI if this is the first RPC in remote FIFO
1297    // and no CPU is in kernel mode in server cluster.
1298    // the selected CPU in server has the same lid as the client CPU.
1299        if( first )
1300        {
1301        // get number of cores in kernel mode in server cluster
1302        cores = hal_remote_lw( XPTR( server_cxy , &LOCAL_CLUSTER->cores_in_kernel ) );
1303
1304                if( cores == 0 ) // no core in kernel mode in server
1305                {
1306                    dev_pic_send_ipi( server_cxy , client_lid );
1307
1308                    rpc_dmsg("\n[INFO] %s : core %d in cluster %x send IPI to core %d in cluster %x\n",
1309                      __FUNCTION__, client_lid , client_cxy , client_lid , server_cxy );
1310        }
1311        }
1312
1313        // activate preemption to allow incoming RPC and avoid deadlock
1314        if( this->type == THREAD_RPC ) hal_enable_irq( &sr_save );
1315
1316    // the sending thread poll the response slot until RPC completed
1317        while( 1 )
1318    {
1319        if( rpc->response == 0 ) break;
1320    }
1321
1322    // restore preemption
1323        if( this->type == THREAD_RPC ) hal_restore_irq( sr_save );
1324
1325}  // end rpc_send_sync()
1326
1327
1328
1329/***************************************************************************************/
1330/************ Generic functions supporting RPCs : server side **************************/
1331/***************************************************************************************/
1332
1333///////////////////////////////////////////
1334void rpc_fifo_init( rpc_fifo_t * rpc_fifo )
1335{
1336        rpc_fifo->count       = 0;
1337        rpc_fifo->owner       = 0;
1338        local_fifo_init( &rpc_fifo->fifo );
1339}
1340
1341////////////////////////////////////////////////
1342error_t rpc_execute_all( rpc_fifo_t * rpc_fifo )
1343{
1344        xptr_t         xp;             // extended pointer on RPC descriptor
1345        uint32_t       count;          // handled RPC request counter
1346        thread_t     * this;           // pointer on this RPC thread
1347    core_t       * core;           // pointer on core running this thread
1348    rpc_desc_t   * desc;           // pointer on RPC descriptor
1349    uint32_t       index;          // RPC index
1350    uint32_t       expected;       // number of expected responses
1351    cxy_t          client_cxy;     // client cluster identifier
1352        error_t        error;
1353     
1354        this = CURRENT_THREAD; 
1355    core = this->core;   
1356
1357
1358    // handle up to CONFIG_RPC_PENDING_MAX requests before exit
1359        count = 0;
1360        do
1361    {
1362            error = local_fifo_get_item( &rpc_fifo->fifo, 
1363                                     (uint64_t *)&xp );
1364
1365                if ( error == 0 )  // One RPC request successfully extracted from RPC_FIFO
1366        {
1367            rpc_dmsg("\n[INFO] %s : RPC_THREAD %x on core %x in cluster %x handles RPC %d\n"
1368                                     __FUNCTION__ , this->trdid , core->lid , local_cxy , count );
1369
1370            // get client cluster identifier and pointer on RPC descriptor
1371            client_cxy = (cxy_t)GET_CXY( xp );
1372            desc       = (rpc_desc_t *)GET_PTR( xp );
1373
1374            // get rpc index and expected responses from RPC descriptor
1375                index     = hal_remote_lw( XPTR( client_cxy , &desc->index ) );
1376                expected  = hal_remote_lw( XPTR( client_cxy , &desc->response ) );
1377
1378            // call the relevant server function
1379            rpc_server[index]( xp );
1380
1381            // increment handled RPC counter
1382                count++;
1383
1384            // notify RPC completion as required
1385            if( expected == 1 ) hal_remote_sw( XPTR(client_cxy,&desc->response) , 0 );
1386            if( expected >  1 ) hal_remote_atomic_add( XPTR(client_cxy,&desc->response) , -1 );
1387                }
1388       
1389                // exit loop in three cases:
1390        // - fifo is empty
1391        // - look has been released (because descheduling)
1392        // - max number of RPCs has been reached
1393                if( error || 
1394            (rpc_fifo->owner != this->trdid) || 
1395            (count > CONFIG_RPC_PENDING_MAX) ) break;
1396        }
1397    while( 1 )
1398
1399        rpc_dmsg("\n[INFO] %s running on core %d in cluster %x exit\n"
1400              __FUNCTION__ , CURRENT_CORE->lid , local_cxy );
1401               
1402    // update RPC_FIFO global counter
1403        rpc_fifo->count += count;
1404
1405        return 0;
1406}  // end rpc_execute_all()
1407
1408////////////////////////////////////////////////////
1409error_t rpc_activate_thread( rpc_fifo_t * rpc_fifo )
1410{
1411        core_t      * core;
1412        thread_t    * thread;
1413        thread_t    * this;
1414    scheduler_t * sched;
1415        error_t       error;
1416    bool_t        found;
1417    reg_t         sr_save;
1418
1419        this   = CURRENT_THREAD;
1420    core   = this->core;
1421    sched  = &core->scheduler;
1422    found  = false;
1423
1424    // calling thread must be the RPC_FIFO owner
1425    if( this->trdid != rpc_fifo->owner )
1426    {
1427        printk("\n[PANIC] in %s : calling thread is not RPC_FIFO owner\n", __FUNCTION__ );
1428        hal_core_sleep();
1429    }
1430
1431    // makes the calling thread not preemptable
1432    // during activation / creation of the RPC thread
1433        hal_disable_irq( &sr_save );
1434
1435    // search a free RPC thread (must be in THREAD_BLOCKED_IDLE state)   
1436    list_entry_t * iter;
1437    LIST_FOREACH( &sched->k_root , iter )
1438    {
1439        thread = LIST_ELEMENT( iter , thread_t , sched_list );
1440        if( (thread->type == THREAD_RPC) && (thread->blocked ==  THREAD_BLOCKED_IDLE ) ) 
1441        {
1442            found = true;
1443            break;
1444        }
1445    }
1446
1447    if( found )                    // activate this idle RPC thread     
1448    {
1449        thread->blocked = 0;
1450    }
1451    else                           // create a new RPC thread
1452    {
1453        error = thread_kernel_create( &thread,
1454                                      THREAD_RPC, 
1455                                                  &rpc_thread_func, 
1456                                      NULL,
1457                                                  core->lid );
1458            if( error ) 
1459        {
1460                hal_restore_irq( sr_save );
1461            printk("\n[ERROR] in %s : no memory for new RPC thread in cluster %x\n",
1462                   __FUNCTION__ , local_cxy );
1463            return ENOMEM;
1464        }
1465
1466        rpc_dmsg("\n[INFO] %s creates RPC thread %x on core %x in cluster %x at cycle %d\n", 
1467                          __FUNCTION__ , thread , core->gid , local_cxy , hal_get_cycles() );
1468
1469        // update core descriptor counter 
1470            hal_atomic_add( &core->rpc_threads , 1 );
1471    }
1472
1473    // update owner in rpc_fifo
1474    rpc_fifo->owner = thread->trdid;
1475
1476    rpc_dmsg ("\n[INFO] %s activates RPC thread %x on core %x in cluster %x at cycle %d\n",
1477                      __FUNCTION__ , thread , core->gid , local_cxy , hal_get_cycles() );
1478
1479    // current thread deschedules / RPC thread start execution
1480        sched_switch_to( thread );
1481
1482    // restore IRQs for the calling thread
1483        hal_restore_irq( sr_save );
1484
1485    // return success
1486        return 0;
1487
1488}  // end rpc_activate_thread()
1489
1490//////////////////
1491bool_t rpc_check()
1492{
1493        thread_t   * this     = CURRENT_THREAD;
1494        rpc_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
1495    error_t      error;
1496
1497    // calling thread does nothing if light lock already taken or FIFO empty 
1498        if( (rpc_fifo->owner != 0) || (local_fifo_is_empty( &rpc_fifo->fifo )) )
1499    {
1500        return false;
1501    }
1502
1503        // calling thread tries to take the light lock,
1504    // and activates an RPC thread if success
1505    if( hal_atomic_test_set( &rpc_fifo->owner , this->trdid ) )
1506        {
1507        error = rpc_activate_thread( rpc_fifo );
1508
1509        if( error )    // cannot activate an RPC_THREAD
1510        {
1511            rpc_fifo->owner = 0;
1512
1513            printk("\n[ERROR] in %s : no memory to create a RPC thread for core %d"
1514                   " in cluster %x => do nothing\n",
1515                   __FUNCTION__ , CURRENT_CORE->lid , local_cxy );
1516        }
1517
1518        return true;
1519    }
1520    else  // light lock taken by another thread
1521    {
1522        return false;
1523    }
1524} // end rpc_check()
1525
1526
1527//////////////////////
1528void rpc_thread_func()
1529{
1530    // makes the calling thread not preemptable
1531        hal_disable_irq( NULL );
1532 
1533        thread_t   * this     = CURRENT_THREAD;
1534        rpc_fifo_t * rpc_fifo = &LOCAL_CLUSTER->rpc_fifo;
1535
1536    rpc_dmsg("\n[INFO] RPC thread %x created on core %d in cluster %x at cycle %d\n",
1537             this->trdid , this->core->lid , local_cxy , hal_get_cycles() );
1538
1539    // this infinite loop is not preemptable
1540    // the RPC thread deschedule when the RPC_FIFO is empty
1541        while(1)
1542        {
1543        // check fifo ownership (ownership should be given by rpc_activate()
1544        if( this->trdid != rpc_fifo->owner )
1545        {
1546            printk("\n[PANIC] in %s : RPC_THREAD %x not owner of RPC_FIFO in cluster %x\n",
1547                   __FUNCTION__ , this->trdid , local_cxy );
1548            hal_core_sleep();
1549        }
1550 
1551        // executes pending RPC(s)
1552        rpc_execute_all( rpc_fifo );
1553
1554        // release rpc_fifo ownership (can be lost during RPC execution)
1555        if( rpc_fifo->owner == this->trdid ) rpc_fifo->owner = 0;
1556
1557
1558        // suicide if too much RPC threads for this core
1559                if( this->core->rpc_threads > CONFIG_RPC_THREADS_MAX ) 
1560                {
1561            rpc_dmsg("\n[INFO] RPC thread %x suicide on core %d in cluster %x at cycle %d\n", 
1562                             this->trdid , this->core->lid , local_cxy , hal_get_cycles() );
1563
1564            // update core descriptor counter
1565                hal_atomic_add( &this->core->rpc_threads , -1 );
1566
1567            // suicide
1568                        thread_exit();
1569                }
1570
1571        // block and deschedule
1572        rpc_dmsg("\n[INFO] RPC thread %x deschedule on core %d in cluster %x at cycle %d\n", 
1573                              this->trdid , this->core->lid , local_cxy , hal_get_cycles() ); 
1574
1575                thread_block( this , THREAD_BLOCKED_IDLE );
1576        sched_yield();
1577
1578                rpc_dmsg("\n[INFO] RPC thread %x wake up on core %d in cluster %x at cycle %d\n", 
1579                              this->trdid , this->core->lid , local_cxy , hal_get_cycles() );
1580        }
1581} // end rpc_thread_func()
1582
Note: See TracBrowser for help on using the repository browser.