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

Last change on this file since 282 was 279, checked in by alain, 7 years ago

1) Introduce independant command fields for the various devices in the thread descriptor.
2) Introduce a new dev_pic_enable_ipi() function in the generic PIC device
3) Fix two bugs identified by Maxime in the scheduler initialisation, and in the sched_select().
4) fix several bugs in the TSAR hal_kentry.S.
5) Introduce a third kgiet segment (besides kdata and kcode) in the TSAR bootloader.

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