source: trunk/kernel/mm/mapper.c @ 619

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

1) introduce a dev_ioc_sync_write() function in IOC API,

to improve the DEVFS synchronous update.

2) fix a big bug in both the user_dir_create() and user_dir_destroy()

functions: add an extended pointer on the reference client process
in the function's arguments.

File size: 22.7 KB
Line 
1/*
2 * mapper.c - Kernel cache for FS files or directories implementation.
3 *
4 * Authors   Mohamed Lamine Karaoui (2015)
5 *           Alain Greiner (2016,2017,2018)
6 *
7 * Copyright (c)  UPMC Sorbonne Universites
8 *
9 * This file is part of ALMOS-MKH.
10 *
11 * ALMOS-MKH is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2.0 of the License.
14 *
15 * ALMOS-MKH is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25#include <kernel_config.h>
26#include <hal_kernel_types.h>
27#include <hal_special.h>
28#include <hal_uspace.h>
29#include <grdxt.h>
30#include <string.h>
31#include <rwlock.h>
32#include <printk.h>
33#include <memcpy.h>
34#include <thread.h>
35#include <core.h>
36#include <process.h>
37#include <kmem.h>
38#include <kcm.h>
39#include <ppm.h>
40#include <page.h>
41#include <cluster.h>
42#include <vfs.h>
43#include <mapper.h>
44#include <dev_ioc.h>
45
46
47//////////////////////////////////////////////
48mapper_t * mapper_create( vfs_fs_type_t type )
49{
50    mapper_t * mapper;
51    kmem_req_t req;
52    error_t    error;
53
54    // allocate memory for mapper
55    req.type  = KMEM_MAPPER;
56    req.size  = sizeof(mapper_t);
57    req.flags = AF_KERNEL | AF_ZERO;
58    mapper    = (mapper_t *)kmem_alloc( &req );
59
60    if( mapper == NULL )
61    {
62        printk("\n[ERROR] in %s : no memory for mapper descriptor\n", __FUNCTION__ );
63        return NULL;
64    }
65
66    // initialize refcount & inode
67    mapper->refcount = 0;
68    mapper->inode    = NULL;
69
70    // initialize radix tree
71    error = grdxt_init( &mapper->rt,
72                        CONFIG_MAPPER_GRDXT_W1,
73                        CONFIG_MAPPER_GRDXT_W2,
74                        CONFIG_MAPPER_GRDXT_W3 );
75
76    if( error )
77    {
78        printk("\n[ERROR] in %s : cannot initialize radix tree\n", __FUNCTION__ );
79        req.type  = KMEM_MAPPER;
80        req.ptr   = mapper;
81        kmem_free( &req );
82        return NULL;
83    }
84
85    // initialize mapper type
86    mapper->type = type;
87
88    // initialize mapper lock
89    remote_rwlock_init( XPTR( local_cxy , &mapper->lock ) , LOCK_MAPPER_STATE );
90
91    // initialize waiting threads xlist (empty)
92    xlist_root_init( XPTR( local_cxy , &mapper->wait_root ) );
93
94    // initialize vsegs xlist (empty)
95    xlist_root_init( XPTR( local_cxy , &mapper->vsegs_root ) );
96
97    return mapper;
98
99}  // end mapper_create()
100
101////////////////////////////////////////
102void mapper_destroy( mapper_t * mapper )
103{
104    page_t   * page;
105    uint32_t   found_index = 0;
106    uint32_t   start_index = 0;
107    kmem_req_t req;
108
109    // scan radix tree
110    do
111    {
112        // get page from radix tree
113        page = (page_t *)grdxt_get_first( &mapper->rt , start_index , &found_index );
114
115        // release registered pages to PPM
116        if( page != NULL )
117        {
118            // remove page from mapper and release to PPM
119            mapper_release_page( mapper , page );
120
121            // update start_key value for next page
122            start_index = found_index;
123        }
124    }
125    while( page != NULL );
126
127    // release the memory allocated to radix tree itself
128    grdxt_destroy( &mapper->rt );
129
130    // release memory for mapper descriptor
131    req.type = KMEM_MAPPER;
132    req.ptr  = mapper;
133    kmem_free( &req );
134
135}  // end mapper_destroy()
136
137////////////////////////////////////////////////////
138xptr_t  mapper_remote_get_page( xptr_t    mapper_xp,
139                                uint32_t  page_id )
140{
141    error_t       error;
142    mapper_t    * mapper_ptr;
143    cxy_t         mapper_cxy;
144    xptr_t        lock_xp;        // extended pointer on mapper lock
145    xptr_t        page_xp;        // extended pointer on searched page descriptor
146    xptr_t        rt_xp;          // extended pointer on radix tree in mapper
147
148    thread_t * this = CURRENT_THREAD;
149
150    // get mapper cluster and local pointer
151    mapper_ptr = GET_PTR( mapper_xp );
152    mapper_cxy = GET_CXY( mapper_xp );
153
154#if DEBUG_MAPPER_GET_PAGE
155uint32_t cycle = (uint32_t)hal_get_cycles();
156char          name[CONFIG_VFS_MAX_NAME_LENGTH];
157vfs_inode_t * inode = hal_remote_lpt( XPTR( mapper_cxy , &mapper_ptr->inode ) );
158vfs_inode_get_name( XPTR( mapper_cxy , inode ) , name );
159if( DEBUG_MAPPER_GET_PAGE < cycle )
160printk("\n[%s] thread [%x,%x] enter for page %d of <%s> / cycle %d\n",
161__FUNCTION__, this->process->pid, this->trdid, page_id, name, cycle );
162#endif
163
164    // check thread can yield
165    thread_assert_can_yield( this , __FUNCTION__ );
166
167    // build extended pointer on mapper lock and mapper rt
168    lock_xp  = XPTR( mapper_cxy , &mapper_ptr->lock );
169    rt_xp    = XPTR( mapper_cxy , &mapper_ptr->rt );
170
171    // take mapper lock in READ_MODE
172    remote_rwlock_rd_acquire( lock_xp );
173
174    // search page in radix tree
175    page_xp  = grdxt_remote_lookup( rt_xp , page_id );
176
177    // test mapper miss
178    if( page_xp == XPTR_NULL )                  // miss => try to handle it
179    {
180        // release the lock in READ_MODE and take it in WRITE_MODE
181        remote_rwlock_rd_release( lock_xp );
182        remote_rwlock_wr_acquire( lock_xp );
183
184        // second test on missing page because the page status can be modified
185        // by another thread, when passing from READ_MODE to WRITE_MODE.
186        // from this point there is no concurrent accesses to mapper.
187        page_xp = grdxt_remote_lookup( rt_xp , page_id );
188
189        if ( page_xp == XPTR_NULL )  // miss confirmed => handle it
190        {
191
192            if( mapper_cxy == local_cxy )   // mapper is local
193            {
194
195#if (DEBUG_MAPPER_GET_PAGE & 1)
196if( DEBUG_MAPPER_GET_PAGE < cycle )
197printk("\n[%s] missing page => load it from FS / local access \n", __FUNCTION__ );
198#endif
199                 error = mapper_handle_miss( mapper_ptr,
200                                             page_id, 
201                                             &page_xp );
202            } 
203            else
204            {
205
206#if (DEBUG_MAPPER_GET_PAGE & 1)
207if( DEBUG_MAPPER_GET_PAGE < cycle )
208printk("\n[%s] missing page => load it from FS / RPC access \n", __FUNCTION__ );
209#endif
210                 rpc_mapper_handle_miss_client( mapper_cxy,
211                                                mapper_ptr,
212                                                page_id,
213                                                &page_xp,
214                                                &error );
215            }
216
217            if ( error )
218            {
219                printk("\n[ERROR] in %s : thread[%x,%x] cannot handle mapper miss\n",
220                __FUNCTION__ , this->process->pid, this->trdid );
221                remote_rwlock_wr_release( lock_xp );
222                return XPTR_NULL;
223            }
224        }
225       
226        // release mapper lock from WRITE_MODE
227        remote_rwlock_wr_release( lock_xp );
228    }
229    else                                              // hit
230    {
231        // release mapper lock from READ_MODE
232        remote_rwlock_rd_release( lock_xp );
233    }
234
235#if DEBUG_MAPPER_GET_PAGE
236cycle = (uint32_t)hal_get_cycles();
237if( DEBUG_MAPPER_GET_PAGE < cycle )
238printk("\n[%s] thread[%x,%x] exit for page %d of <%s> / ppn %x / cycle %d\n",
239__FUNCTION__, this->process->pid, this->trdid, 
240page_id, name, ppm_page2ppn( page_xp ), cycle );
241#endif
242
243    return page_xp;
244
245}  // end mapper_remote_get_page()
246
247//////////////////////////////////////////////
248error_t mapper_handle_miss( mapper_t * mapper,
249                            uint32_t   page_id,
250                            xptr_t   * page_xp )
251{
252    kmem_req_t   req;
253    page_t     * page;
254    error_t      error;
255
256    thread_t * this = CURRENT_THREAD;
257
258#if DEBUG_MAPPER_HANDLE_MISS
259uint32_t cycle = (uint32_t)hal_get_cycles();
260char          name[CONFIG_VFS_MAX_NAME_LENGTH];
261vfs_inode_t * inode = mapper->inode;
262vfs_inode_get_name( XPTR( local_cxy , inode ) , name );
263// if( DEBUG_MAPPER_HANDLE_MISS < cycle )
264// if( (page_id == 1) && (cycle > 10000000) )
265printk("\n[%s] enter for page %d in <%s> / cycle %d",
266__FUNCTION__, page_id, name, cycle );
267if( DEBUG_MAPPER_HANDLE_MISS & 1 )
268grdxt_display( XPTR( local_cxy , &mapper->rt ) , name );
269#endif
270
271    // allocate one page from the local cluster
272    req.type  = KMEM_PAGE;
273    req.size  = 0;
274    req.flags = AF_NONE;
275    page = kmem_alloc( &req );
276
277    if( page == NULL )
278    {
279        printk("\n[ERROR] in %s : thread [%x,%x] cannot allocate page in cluster %x\n",
280        __FUNCTION__ , this->process->pid, this->trdid , local_cxy );
281        return -1;
282    }
283
284    // initialize the page descriptor
285    page_init( page );
286    page_set_flag( page , PG_INIT );
287    page_refcount_up( page );
288    page->mapper = mapper;
289    page->index  = page_id;
290
291    // insert page in mapper radix tree
292    error = grdxt_insert( &mapper->rt , page_id , page );
293
294    if( error )
295    {
296        printk("\n[ERROR] in %s : thread[%x,%x] cannot insert page in mapper\n",
297        __FUNCTION__ , this->process->pid, this->trdid );
298        mapper_release_page( mapper , page );
299        req.ptr  = page;
300        req.type = KMEM_PAGE;
301        kmem_free(&req);
302        return -1;
303    }
304
305    // launch I/O operation to load page from device to mapper
306    error = vfs_fs_move_page( XPTR( local_cxy , page ) , IOC_SYNC_READ );
307
308    if( error )
309    {
310        printk("\n[ERROR] in %s : thread[%x,%x] cannot load page from device\n",
311        __FUNCTION__ , this->process->pid, this->trdid );
312        mapper_release_page( mapper , page );
313        req.ptr  = page;
314        req.type = KMEM_PAGE;
315        kmem_free( &req );
316        return -1;
317    }
318
319    // set extended pointer on allocated page
320    *page_xp = XPTR( local_cxy , page );
321
322#if DEBUG_MAPPER_HANDLE_MISS
323cycle = (uint32_t)hal_get_cycles();
324// if( DEBUG_MAPPER_HANDLE_MISS < cycle )
325// if( (page_id == 1) && (cycle > 10000000) )
326printk("\n[%s] exit for page %d in <%s> / ppn %x / cycle %d",
327__FUNCTION__, page_id, name, ppm_page2ppn( *page_xp ), cycle );
328if( DEBUG_MAPPER_HANDLE_MISS & 1 )
329grdxt_display( XPTR( local_cxy , &mapper->rt ) , name );
330#endif
331
332    return 0;
333
334}  // end mapper_handle_miss()
335
336////////////////////////////////////////////
337void mapper_release_page( mapper_t * mapper,
338                          page_t   * page )
339{
340    // build extended pointer on mapper lock
341    xptr_t mapper_lock_xp = XPTR( local_cxy , &mapper->lock );
342
343    // take mapper lock in WRITE_MODE
344    remote_rwlock_wr_acquire( mapper_lock_xp );
345
346    // remove physical page from radix tree
347    grdxt_remove( &mapper->rt , page->index );
348
349    // release mapper lock from WRITE_MODE
350    remote_rwlock_wr_release( mapper_lock_xp );
351
352    // release page to PPM
353    kmem_req_t   req;
354    req.type  = KMEM_PAGE;
355    req.ptr   = page;
356    kmem_free( &req );
357
358}  // end mapper_release_page()
359
360///////////////////////////////////////////////
361error_t mapper_move_user( xptr_t     mapper_xp,
362                          bool_t     to_buffer,
363                          uint32_t   file_offset,
364                          void     * buffer,
365                          uint32_t   size )
366{
367    uint32_t   page_offset;    // first byte to move to/from a mapper page
368    uint32_t   page_count;     // number of bytes to move to/from a mapper page
369    uint32_t   page_id;        // current mapper page index
370    uint32_t   done;           // number of moved bytes
371    xptr_t     page_xp;        // extended pointer on current mapper page descriptor
372
373#if DEBUG_MAPPER_MOVE_USER
374uint32_t   cycle = (uint32_t)hal_get_cycles();
375thread_t * this  = CURRENT_THREAD;
376if( DEBUG_MAPPER_MOVE_USER < cycle )
377printk("\n[%s] thread[%x,%x] : to_buf %d / buffer %x / size %d / offset %d / cycle %d\n",
378__FUNCTION__, this->process->pid, this->trdid,
379to_buffer, buffer, size, file_offset, cycle );
380#endif
381
382    // compute offsets of first and last bytes in file
383    uint32_t min_byte = file_offset;
384    uint32_t max_byte = file_offset + size - 1;
385
386    // compute indexes of pages for first and last byte in mapper
387    uint32_t first = min_byte >> CONFIG_PPM_PAGE_SHIFT;
388    uint32_t last  = max_byte >> CONFIG_PPM_PAGE_SHIFT;
389
390#if (DEBUG_MAPPER_MOVE_USER & 1)
391if( DEBUG_MAPPER_MOVE_USER < cycle )
392printk("\n[%s] thread[%x,%x] : first_page %d / last_page %d\n",
393__FUNCTION__, this->process->pid, this->trdid, first, last );
394#endif
395
396    done = 0;
397
398    // loop on pages in mapper
399    for( page_id = first ; page_id <= last ; page_id++ )
400    {
401        // compute page_offset
402        if( page_id == first ) page_offset = min_byte & CONFIG_PPM_PAGE_MASK;
403        else                   page_offset = 0;
404
405        // compute number of bytes in page
406        if      ( first   == last  ) page_count = size;
407        else if ( page_id == first ) page_count = CONFIG_PPM_PAGE_SIZE - page_offset;
408        else if ( page_id == last  ) page_count = (max_byte & CONFIG_PPM_PAGE_MASK) + 1;
409        else                         page_count = CONFIG_PPM_PAGE_SIZE;
410
411#if (DEBUG_MAPPER_MOVE_USER & 1)
412if( DEBUG_MAPPER_MOVE_USER < cycle )
413printk("\n[%s] thread[%x,%x] : page_id = %d / page_offset = %d / page_count = %d\n",
414__FUNCTION__, this->process->pid, this->trdid, page_id , page_offset , page_count );
415#endif
416
417        // get extended pointer on page descriptor
418        page_xp = mapper_remote_get_page( mapper_xp , page_id ); 
419
420        if ( page_xp == XPTR_NULL ) return -1;
421
422#if (DEBUG_MAPPER_MOVE_USER & 1)
423if( DEBUG_MAPPER_MOVE_USER < cycle )
424printk("\n[%s] thread[%x,%x] : get page (%x,%x) from mapper\n",
425__FUNCTION__, this->process->pid, this->trdid, GET_CXY(page_xp), GET_PTR(page_xp) );
426#endif
427
428        // compute pointer in mapper
429        xptr_t    base_xp = ppm_page2base( page_xp );
430        uint8_t * map_ptr = (uint8_t *)GET_PTR( base_xp ) + page_offset;
431
432        // compute pointer in buffer
433        uint8_t * buf_ptr = (uint8_t *)buffer + done;
434
435        // move fragment
436        if( to_buffer )
437        {
438            hal_copy_to_uspace( buf_ptr , map_ptr , page_count ); 
439        }
440        else
441        {
442            ppm_page_do_dirty( page_xp ); 
443            hal_copy_from_uspace( map_ptr , buf_ptr , page_count ); 
444        }
445
446        done += page_count;
447    }
448
449#if DEBUG_MAPPER_MOVE_USER
450cycle = (uint32_t)hal_get_cycles();
451if( DEBUG_MAPPER_MOVE_USER < cycle )
452printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
453__FUNCTION__, this->process->pid, this->trdid, cycle );
454#endif
455
456    return 0;
457
458}  // end mapper_move_user()
459
460////////////////////////////////////////////////
461error_t mapper_move_kernel( xptr_t    mapper_xp,
462                            bool_t    to_buffer,
463                            uint32_t  file_offset,
464                            xptr_t    buffer_xp,
465                            uint32_t  size )
466{
467    uint32_t   page_offset;    // first byte to move to/from a mapper page
468    uint32_t   page_count;     // number of bytes to move to/from a mapper page
469    uint32_t   page_id;        // current mapper page index
470    uint32_t   done;           // number of moved bytes
471    xptr_t     page_xp;        // extended pointer on current mapper page descriptor
472
473    uint8_t  * src_ptr;        // source buffer local pointer
474    cxy_t      src_cxy;        // source cluster
475    uint8_t  * dst_ptr;        // destination buffer local pointer
476    cxy_t      dst_cxy;        // destination cluster
477
478    // get buffer cluster and local pointer
479    cxy_t     buffer_cxy = GET_CXY( buffer_xp );
480    uint8_t * buffer_ptr = GET_PTR( buffer_xp );
481
482    // get mapper cluster
483    cxy_t     mapper_cxy = GET_CXY( mapper_xp );
484
485#if DEBUG_MAPPER_MOVE_KERNEL
486uint32_t   cycle = (uint32_t)hal_get_cycles();
487thread_t * this  = CURRENT_THREAD;
488if( DEBUG_MAPPER_MOVE_KERNEL < cycle )
489printk("\n[%s] thread[%x,%x] enter / to_buf %d / buf_cxy %x / buf_ptr %x / cycle %d\n",
490__FUNCTION__, this->process->pid, this->trdid, to_buffer, buffer_cxy, buffer_ptr, cycle );
491#endif
492
493    // compute offsets of first and last bytes in file
494    uint32_t min_byte = file_offset;
495    uint32_t max_byte = file_offset + size -1;
496
497    // compute indexes for first and last pages in mapper
498    uint32_t first = min_byte >> CONFIG_PPM_PAGE_SHIFT;
499    uint32_t last  = max_byte >> CONFIG_PPM_PAGE_SHIFT;
500
501#if (DEBUG_MAPPER_MOVE_KERNEL & 1)
502if( DEBUG_MAPPER_MOVE_KERNEL < cycle )
503printk("\n[%s] first_page %d / last_page %d\n", __FUNCTION__, first, last );
504#endif
505
506    // compute source and destination clusters
507    if( to_buffer )
508    {
509        dst_cxy = buffer_cxy;
510        src_cxy = mapper_cxy;
511    }
512    else
513    {
514        src_cxy = buffer_cxy;
515        dst_cxy = mapper_cxy;
516    }
517
518    done = 0;
519
520    // loop on pages in mapper
521    for( page_id = first ; page_id <= last ; page_id++ )
522    {
523        // compute page_offset
524        if( page_id == first ) page_offset = min_byte & CONFIG_PPM_PAGE_MASK;
525        else                   page_offset = 0;
526
527        // compute number of bytes to move in page
528        if      ( first == last  )   page_count = size;
529        else if ( page_id == first ) page_count = CONFIG_PPM_PAGE_SIZE - page_offset;
530        else if ( page_id == last  ) page_count = (max_byte & CONFIG_PPM_PAGE_MASK) + 1;
531        else                         page_count = CONFIG_PPM_PAGE_SIZE;
532
533#if (DEBUG_MAPPER_MOVE_KERNEL & 1)
534if( DEBUG_MAPPER_MOVE_KERNEL < cycle )
535printk("\n[%s] page_id = %d / offset = %d / bytes = %d\n",
536__FUNCTION__ , page_id , page_offset , page_count );
537#endif
538
539        // get extended pointer on page descriptor
540        page_xp = mapper_remote_get_page( mapper_xp , page_id );
541
542        if ( page_xp == XPTR_NULL ) return -1;
543
544        // get page base address
545        xptr_t    base_xp  = ppm_page2base( page_xp );
546        uint8_t * base_ptr = (uint8_t *)GET_PTR( base_xp );
547
548        // compute source and destination pointers
549        if( to_buffer )
550        {
551            dst_ptr = buffer_ptr + done;
552            src_ptr = base_ptr + page_offset;
553        }
554        else
555        {
556            src_ptr = buffer_ptr + done;
557            dst_ptr = base_ptr + page_offset;
558
559            ppm_page_do_dirty( page_xp );
560        }
561
562#if (DEBUG_MAPPER_MOVE_KERNEL & 1)
563if( DEBUG_MAPPER_MOVE_KERNEL < cycle )
564printk("\n[%s] src_cxy %x / src_ptr %x / dst_cxy %x / dst_ptr %x\n",
565__FUNCTION__, src_cxy, src_ptr, dst_cxy, dst_ptr );
566#endif
567
568        // move fragment
569        hal_remote_memcpy( XPTR( dst_cxy , dst_ptr ), XPTR( src_cxy , src_ptr ), page_count );
570
571        done += page_count;
572    }
573
574#if DEBUG_MAPPER_MOVE_KERNEL
575cycle = (uint32_t)hal_get_cycles();
576if( DEBUG_MAPPER_MOVE_KERNEL < cycle )
577printk("\n[%s] thread[%x,%x] exit / to_buf %d / buf_cxy %x / buf_ptr %x / cycle %d\n",
578__FUNCTION__, this->process->pid, this->trdid, to_buffer, buffer_cxy, buffer_ptr, cycle );
579#endif
580
581    return 0;
582
583}  // end mapper_move_kernel()
584
585///////////////////////////////////////////////////
586error_t mapper_remote_get_32( xptr_t     mapper_xp,
587                              uint32_t   word_id,
588                              uint32_t * p_value )
589{
590    uint32_t   page_id;      // page index in file
591    uint32_t   local_id;     // word index in page
592    xptr_t     page_xp;      // extended pointer on searched page descriptor
593    xptr_t     base_xp;      // extended pointer on searched page base
594
595   
596    // get page index and local word index
597    page_id  = word_id >> 10;
598    local_id = word_id & 0x3FF;
599
600    // get page containing the searched word
601    page_xp  = mapper_remote_get_page( mapper_xp , page_id );
602
603    if( page_xp == XPTR_NULL )  return -1;
604   
605    // get page base
606    base_xp = ppm_page2base( page_xp );
607
608    // get the value from mapper
609    *p_value = hal_remote_l32( base_xp + (local_id<<2) ); 
610
611    return 0;
612
613}  // end mapper_remote_get_32()
614
615///////////////////////////////////////////////////
616error_t mapper_remote_set_32( xptr_t     mapper_xp,
617                              uint32_t   word_id,
618                              uint32_t   value )
619{
620   
621    uint32_t   page_id;      // page index in file
622    uint32_t   local_id;     // word index in page
623    xptr_t     page_xp;      // extended pointer on searched page descriptor
624    xptr_t     base_xp;      // extended pointer on searched page base
625
626    // get page index and local vord index
627    page_id  = word_id >> 10;
628    local_id = word_id & 0x3FF;
629
630    // get page containing the searched word
631    page_xp  = mapper_remote_get_page( mapper_xp , page_id );
632
633    if( page_xp == XPTR_NULL ) return -1;
634
635    // get page base
636    base_xp = ppm_page2base( page_xp );
637
638    // set value to mapper
639    hal_remote_s32( (base_xp + (local_id << 2)) , value );
640
641    // set the dirty flag
642    ppm_page_do_dirty( page_xp );
643
644    return 0;
645
646}  // end mapper_remote_set_32()
647
648//////////////////////////////////////////////////
649error_t mapper_display_page( xptr_t     mapper_xp,
650                             uint32_t   page_id,
651                             uint32_t   nbytes )
652{
653    xptr_t        page_xp;        // extended pointer on page descriptor
654    xptr_t        base_xp;        // extended pointer on page base
655    char          buffer[4096];   // local buffer
656    uint32_t    * tabi;           // pointer on uint32_t to scan buffer
657    char        * tabc;           // pointer on char to scan buffer
658    uint32_t      line;           // line index
659    uint32_t      word;           // word index
660    uint32_t      n;              // char index
661    cxy_t         mapper_cxy;     // mapper cluster identifier
662    mapper_t    * mapper_ptr;     // mapper local pointer
663    vfs_inode_t * inode_ptr;      // inode local pointer
664 
665    char       name[CONFIG_VFS_MAX_NAME_LENGTH];
666
667    if( nbytes > 4096)
668    {
669        printk("\n[ERROR] in %s : nbytes (%d) cannot be larger than 4096\n",
670        __FUNCTION__, nbytes );
671        return -1;
672    }
673   
674    // get extended pointer on page descriptor
675    page_xp = mapper_remote_get_page( mapper_xp , page_id );
676
677    if( page_xp == XPTR_NULL)
678    {
679        printk("\n[ERROR] in %s : cannot access page %d in mapper\n",
680        __FUNCTION__, page_id );
681        return -1;
682    }
683
684    // get cluster and local pointer
685    mapper_cxy = GET_CXY( mapper_xp );
686    mapper_ptr = GET_PTR( mapper_xp );
687
688    // get inode
689    inode_ptr = hal_remote_lpt( XPTR( mapper_cxy , &mapper_ptr->inode ) );
690
691    // get inode name
692    if( inode_ptr == NULL ) strcpy( name , "fat" );
693    else  vfs_inode_get_name( XPTR( mapper_cxy , inode_ptr ) , name );
694   
695    // get extended pointer on page base
696    base_xp = ppm_page2base( page_xp );
697   
698    // copy remote page to local buffer
699    hal_remote_memcpy( XPTR( local_cxy , buffer ) , base_xp , nbytes );
700
701    // display 8 words per line
702    tabi = (uint32_t *)buffer;
703    tabc = (char *)buffer;
704    printk("\n***** <%s> first %d bytes of page %d *****\n", name, nbytes, page_id );
705    for( line = 0 ; line < (nbytes >> 5) ; line++ )
706    {
707        printk("%X : ", line );
708        for( word = 0 ; word < 8 ; word++ ) printk("%X ", tabi[(line<<3) + word] );
709        printk(" | ");
710        for( n = 0 ; n < 32 ; n++ ) printk("%c", tabc[(line<<5) + n] );
711        printk("\n");
712    }
713
714    return 0;
715
716}  // end mapper_display_page
717
718
Note: See TracBrowser for help on using the repository browser.