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

Last change on this file since 212 was 188, checked in by alain, 7 years ago

Redefine the PIC device API.

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