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

Last change on this file since 242 was 238, checked in by alain, 7 years ago

Fixing bugs in vfs_lookup()

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