Index: soft/giet_vm/giet_kernel/sys_handler.c
===================================================================
--- soft/giet_vm/giet_kernel/sys_handler.c	(revision 754)
+++ soft/giet_vm/giet_kernel/sys_handler.c	(revision 760)
@@ -95,6 +95,6 @@
 extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
 
-// allocated in bdv_driver.c file
-spin_lock_t  _bdv_lock;
+// allocated in kernel_init.c file
+extern unsigned long long  _ptabs_paddr[GIET_NB_VSPACE_MAX][X_SIZE][Y_SIZE]; 
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -229,6 +229,6 @@
 
     &_fat_open,                      /* 0x20 */
-    &_fat_read,                      /* 0x21 */
-    &_fat_write,                     /* 0x22 */
+    &_sys_fat_read,                  /* 0x21 */
+    &_sys_fat_write,                 /* 0x22 */
     &_fat_lseek,                     /* 0x23 */
     &_fat_file_info,                 /* 0x24 */
@@ -240,7 +240,7 @@
     &_fat_closedir,                  /* 0x2A */
     &_fat_readdir,                   /* 0x2B */
-    &_sys_ukn,                       /* 0x2C */
-    &_sys_ukn,                       /* 0x2D */
-    &_sys_ukn,                       /* 0x2E */
+    &_sys_fat_pread,                 /* 0x2C */
+    &_sys_fat_mmap,                  /* 0x2D */
+    &_sys_fat_munmap,                /* 0x2E */
     &_sys_ukn,                       /* 0x2F */
 
@@ -274,4 +274,324 @@
 
 
+
+///////////////////////////////////////////////////////////////////////////////////
+//           File system related syscall handlers 
+///////////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////////
+// This function is called by the _sys_fat_mmap() function.
+// It implements a simplistic pages allocator from the MMAP vseg of the vspace
+// identified by the <vspace_id> argument. The number of pages is defined by
+// the <count> argument. 
+// Allocated pages are never released, and the allocator is the "psegid" field
+// in the vseg mapping, that is initialised to 0 by the boot code.
+// In order to support concurrent system calls, the allocator must be
+// atomically incremented.
+///////////////////////////////////////////////////////////////////////////////////
+// Returns the buffer vbase address in case of success.
+// Returns 0 in case of error (no MMAP vseg or not enough space).
+///////////////////////////////////////////////////////////////////////////////////
+static unsigned int _mmap_pages_alloc( unsigned int  vspace_id,
+                                       unsigned int  count )
+{
+    mapping_header_t*   header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
+    mapping_vspace_t*   vspace  = _get_vspace_base( header );
+    mapping_vseg_t*     vseg    = _get_vseg_base( header );
+
+    // loop on the vsegs to find the MMAP vseg vbase, length, and offset
+    unsigned int  vseg_id;
+    unsigned int  vbase;    
+    unsigned int  offset;   
+    unsigned int  length;
+    unsigned int  found = 0;
+    for (vseg_id = vspace[vspace_id].vseg_offset;
+         vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs);
+         vseg_id++) 
+    {
+        if ( vseg[vseg_id].type == VSEG_TYPE_MMAP ) 
+        {
+            offset = _atomic_increment( &vseg[vseg_id].psegid , count );
+            vbase  = vseg[vseg_id].vbase;
+            length = vseg[vseg_id].length;
+            found  = 1;
+            break;
+        }
+    }
+
+    if ( (found == 0) || (((offset + count)<<12) > length) )
+    {
+        return 0;
+    }
+    else
+    {
+        return vbase + (offset<<12);
+    }
+}  // end _mmap_pages_alloc()
+
+
+///////////////////////////////////////////////////////////////////////////////////
+// This function implements the giet_fat_read() system call.
+///////////////////////////////////////////////////////////////////////////////////
+int _sys_fat_read( unsigned int fd_id,
+                   unsigned int vaddr,
+                   unsigned int count )
+{
+    return _fat_read( fd_id,
+                      vaddr,
+                      count,
+                      0,                       // no paddr extension
+                      0,                       // no forced offset
+                      0 );                     // no special mode
+}
+
+////////////////////////////////////////////////////////////////
+// This function implements the giet_fat_pread() system call.
+////////////////////////////////////////////////////////////////
+int _sys_fat_pread( unsigned int fd_id,
+                    unsigned int vaddr,
+                    unsigned int count,
+                    unsigned int offset )
+{
+    return _fat_read( fd_id,
+                      vaddr,
+                      count,
+                      0,                        // no paddr extension
+                      offset,
+                      FAT_FORCED_OFFSET );     
+}
+
+////////////////////////////////////////////////////////////////
+// This function implements the giet_fat_write() system call.
+////////////////////////////////////////////////////////////////
+int _sys_fat_write( unsigned int fd_id,
+                    unsigned int vaddr,
+                    unsigned int count )
+{
+    return _fat_write( fd_id,
+                       vaddr,
+                       count,
+                       0,                       // no paddr extension
+                       0 );                     // no special mode
+}
+
+///////////////////////////////////////////////////////////////////////////////////
+// This function implements the "giet_fat_mmap()" system call.
+// It allocates <count> contiguous pages from the MMAP vseg of the calling vspace.
+// It maps all these pages directly to the file_cache defined by <fd_id>.
+// The <offset> in the file is a number of pages. 
+// The <prot> argument defines the access modes MAP_PROT_WRITE and MAP_PROT_EXEC.
+// In writable mode, the file size is extended to the (offset + count) pages.
+// In non writable mode, the file size must be >= (offset + count) pages.
+// It has the following limitations:
+// - it does not support MAP_PRIVATE (no copy on write).
+// - it does not support MAP_FIXED (no forced user buffer address).
+// - it does not support MAP_ANONYMOUS (only file mapping).
+// - the <offset> and <count> arguments must multiple of 4 Kbytes.
+///////////////////////////////////////////////////////////////////////////////////
+// Returns memory buffer vbase in case of success.
+// Returns 0 on error.
+///////////////////////////////////////////////////////////////////////////////////
+int _sys_fat_mmap( unsigned int fd_id,
+                   unsigned int count, 
+                   unsigned int offset,
+                   unsigned int prot )
+{
+    // takes the FAT lock and register it in thread context
+    static_scheduler_t*  psched = _get_sched();
+    unsigned int         ltid   = _get_thread_ltid();
+    _spin_lock_acquire( &_fat.fat_lock );
+    _atomic_or( &psched->context[ltid].slot[CTX_LOCKS_ID] , LOCKS_MASK_FAT ); 
+
+    // check fd_id overflow
+    if ( fd_id >= GIET_OPEN_FILES_MAX )
+    {
+        _spin_lock_release( &_fat.fat_lock );
+        _atomic_and( &psched->context[ltid].slot[CTX_LOCKS_ID] , ~LOCKS_MASK_FAT ); 
+
+        _printf("\n[GIET ERROR] _sys_fat_mmap(): illegal file descriptor\n");
+        return 0;
+    }
+
+    // check file open
+    if ( _fat.fd[fd_id].allocated == 0 )
+    {
+        _spin_lock_release( &_fat.fat_lock );
+        _atomic_and( &psched->context[ltid].slot[CTX_LOCKS_ID] , ~LOCKS_MASK_FAT ); 
+
+        _printf("\n[GIET ERROR] _sys_fat_mmap(): file not open\n" );
+        return 0;
+    }
+
+    // get access modes
+    unsigned int writable   = prot & MAP_PROT_WRITE;
+    unsigned int executable = prot & MAP_PROT_EXEC;
+
+    // get inode pointer  
+    fat_inode_t* inode  = _fat.fd[fd_id].inode;
+
+    // check file writable
+    if ( _fat.fd[fd_id].read_only && writable )
+    {
+        _spin_lock_release( &_fat.fat_lock );
+        _atomic_and( &psched->context[ltid].slot[CTX_LOCKS_ID] , ~LOCKS_MASK_FAT ); 
+
+        _printf("\n[GIET ERROR] _sys_fat_mmap(): file <%s> is read-only\n",
+                inode->name );
+        return 0;
+    }
+
+    // get vspace index and calling proc coordinates
+    unsigned int vsid    = _get_context_slot( CTX_VSID_ID );
+
+    // compute first and last cluster indexes
+    unsigned int  first_cluster  = offset;
+    unsigned int  last_cluster   = offset + count - 1; 
+
+#if GIET_DEBUG_MMAP
+unsigned int procid  = _get_procid();
+unsigned int x_id    = procid >> (Y_WIDTH + P_WIDTH);
+unsigned int y_id    = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
+unsigned int p_id    = procid & ((1<<P_WIDTH)-1);
+if ( _get_proctime() > GIET_DEBUG_MMAP )
+_printf("\n[DEBUG MMAP] _sys_fat_mmap() : P[%d,%d,%d] enters at cycle %d\n"
+        " for file %s / size = %x / cluster = %x / cache = %x / desc[0] = %x\n"
+        " first_cluster = %d / last_cluster = %d\n",
+        x_id , y_id , p_id , _get_proctime() ,
+        inode->name , inode->size , inode->cluster ,
+        (unsigned int)inode->cache , (unsigned int)inode->cache->children[0] ,
+        first_cluster , last_cluster );
+#endif
+
+    // get buffer vbase from MMAP vseg in calling vspace
+    unsigned int buffer_vbase = _mmap_pages_alloc( vsid, count ); 
+    if ( buffer_vbase == 0 ) 
+    {
+        _spin_lock_release( &_fat.fat_lock );
+        _atomic_and( &psched->context[ltid].slot[CTX_LOCKS_ID] , ~LOCKS_MASK_FAT ); 
+
+        _printf("\n[GIET ERROR] _sys_fat_mmap(): no space in MMAP vseg to map file %s\n",
+                _fat.fd[fd_id].inode->name );
+        return 0;
+    }
+  
+    // set flags for all pages in buffer
+    unsigned int flags = 0;
+    flags |= PTE_C;                    // cachable
+    flags |= PTE_U;                    // user access
+    flags |= PTE_L;                    // local access (unused)
+    flags |= PTE_R;                    // remote access (unused)
+    if ( executable ) flags |= PTE_X;
+    if ( writable   ) flags |= PTE_W;
+
+    // loop on pages to be mapped
+    unsigned int cid;
+    unsigned int user_vaddr = buffer_vbase;
+    for ( cid = first_cluster ; cid <= last_cluster ; cid++ )  
+    {
+        // get file_cache buffer vaddr
+        unsigned char*     cache_vaddr;
+        fat_cache_desc_t*  pdesc;
+        if ( _get_file_cache_buffer( inode,
+                                     cid,
+                                     writable,
+                                     &pdesc ) )
+        {
+            _spin_lock_release( &_fat.fat_lock );
+            _atomic_and( &psched->context[ltid].slot[CTX_LOCKS_ID] , ~LOCKS_MASK_FAT ); 
+
+            _printf("\n[FAT ERROR] _sys_fat_mmap(): cannot access file <%s>\n",
+                    _fat.fd[fd_id].inode->name );
+            return 0;
+        }
+
+        cache_vaddr = pdesc->buffer;
+        
+        // compute buffer paddr
+        unsigned long long  cache_paddr;
+        unsigned int        unused;
+        cache_paddr = _v2p_translate( (unsigned int)cache_vaddr, &unused );
+
+        // map the user_vaddr to cache_paddr 
+        // in all pages tables defined for the vspace
+        unsigned int x_cur;
+        unsigned int y_cur;
+        for  ( x_cur = 0 ; x_cur < X_SIZE ; x_cur++ )
+        {
+            for  ( y_cur = 0 ; y_cur < Y_SIZE ; y_cur++ )
+            {
+                if ( _ptabs_paddr[vsid][x_cur][y_cur] )  // Page table is defined
+                {
+                    _v2p_add_pte2( vsid,
+                                   x_cur,
+                                   y_cur,
+                                   user_vaddr >> 12,
+                                   flags,
+                                   cache_paddr >> 12,
+                                   0 );
+                }
+            }
+        }
+
+#if GIET_DEBUG_MMAP
+if ( _get_proctime() > GIET_DEBUG_MMAP )
+_printf("\n[DEBUG MMAP] _sys_fat_mmap() : P[%d,%d,%d] map cluster %d\n"
+        " user_vaddr = %x / cache_paddr = %l\n",
+        x_id , y_id , p_id , cid , user_vaddr , cache_paddr );
+#endif
+
+        // increment user buffer vaddr
+        user_vaddr += 4096;
+    }
+
+    // releases the FAT lock
+    _spin_lock_release( &_fat.fat_lock );
+    _atomic_and( &psched->context[ltid].slot[CTX_LOCKS_ID] , ~LOCKS_MASK_FAT ); 
+
+#if GIET_DEBUG_MMAP
+if ( _get_proctime() > GIET_DEBUG_MMAP )
+_printf("\n[DEBUG MMAP] _sys_fat_mmap() : P[%d,%d,%d] returns buffer %x for file %s\n",
+        x_id , y_id , p_id , buffer_vbase , inode->name );
+#endif
+
+   // returns pointer on mapped buffer in user space
+    return buffer_vbase;
+
+}  // end _sys_fat_mmap()
+
+
+//////////////////////////////////////////////////////////////////
+// This function implements the giet_fat_munmap() system call.
+//////////////////////////////////////////////////////////////////
+int _sys_fat_munmap( unsigned int vaddr,
+                     unsigned int count ) 
+{
+    // get vspace index 
+    unsigned int  vsid   = _get_context_slot( CTX_VSID_ID );
+
+    // loop on pages
+    unsigned int page;
+    for ( page = 0 ; page < count ; page++ )
+    {
+        unsigned int vpn = (vaddr>>12) + page;
+
+        // loop on all page tables defined for the vspace
+        unsigned int x_cur;
+        unsigned int y_cur;
+        for  ( x_cur = 0 ; x_cur < X_SIZE ; x_cur++ )
+        {
+            for  ( y_cur = 0 ; y_cur < Y_SIZE ; y_cur++ )
+            {
+                if ( _ptabs_paddr[vsid][x_cur][y_cur] )  // Page table is defined
+                {
+                    _v2p_del_pte2( vsid , x_cur , y_cur , vpn );
+                }
+            }
+        }
+    }
+    return 0;
+}  // end _sys_fat_munmap()
+
+
+
 //////////////////////////////////////////////////////////////////////////////
 //           Applications related syscall handlers 
@@ -279,5 +599,5 @@
 
 ////////////////////////////////////////////////////////////////////////
-// This function is called by the _sys_exec_application function
+// This function is called by the _sys_exec_application() function
 // to reload all data segments contained in an application.elf file.
 // File checking is minimal, because these segments have already
@@ -344,5 +664,5 @@
         return 1;
     }
-    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 )
+    if ( _fat_read( fd, (unsigned int)buf, 4096, 0, 0, 0 ) < 0 )
     {
         _printf("\n[GIET ERROR] _load_writable_segments() : cannot read\n");
@@ -369,5 +689,5 @@
         return 1;
     }
-    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 )
+    if ( _fat_read( fd, (unsigned int)buf, 4096, 0, 0, 0 ) < 0 )
     {
         _fat_close( fd );
@@ -414,5 +734,5 @@
                     // compute destination address and extension for _fat_read()
                     unsigned int dest   = (unsigned int)pbase;
-                    unsigned int extend = (unsigned int)(pbase>>32) | 0xFFFF0000;
+                    unsigned int extend = (unsigned int)(pbase>>32);
 
                     // load the segment
@@ -422,5 +742,5 @@
                         return 1;
                     }
-                    if ( _fat_read( fd, dest, seg_size, extend ) < 0 )
+                    if ( _fat_read( fd, dest, seg_size, extend, 0, FAT_PADDR_MODE ) < 0 )
                     {
                         _fat_close( fd );
