Index: trunk/hal/tsar_mips32/core/hal_context.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_context.c	(revision 679)
+++ trunk/hal/tsar_mips32/core/hal_context.c	(revision 686)
@@ -2,5 +2,5 @@
  * hal_context.c - implementation of Thread Context API for TSAR-MIPS32
  * 
- * Author  Alain Greiner    (2016,2017,2018,2019)
+ * Author  Alain Greiner    (2016,2017,2018,2019,2019)
  *
  * Copyright (c)  UPMC Sorbonne Universites
@@ -121,14 +121,10 @@
 {
 
-assert( __FUNCTION__, (sizeof(hal_cpu_context_t) <= CONFIG_CPU_CTX_SIZE), "illegal CPU context size" );
+assert( __FUNCTION__, (sizeof(hal_cpu_context_t) <= CONFIG_CPU_CTX_SIZE),
+"illegal CPU context size" );
 
     // allocate memory for cpu_context
-    kmem_req_t  req;
-    req.type   = KMEM_KCM;
-    req.order  = bits_log2( sizeof(hal_cpu_context_t) );
-    req.flags  = AF_KERNEL | AF_ZERO;
-
-    hal_cpu_context_t * context = kmem_alloc( &req );
-
+    hal_cpu_context_t * context = kmem_alloc( bits_log2( sizeof(hal_cpu_context_t) ),
+                                              AF_KERNEL | AF_ZERO);
     if( context == NULL ) return -1;
 
@@ -152,5 +148,6 @@
     hal_cpu_context_t * context = (hal_cpu_context_t *)thread->cpu_context;
 
-assert( __FUNCTION__, (context != NULL ), "CPU context not allocated" );
+assert( __FUNCTION__, (context != NULL ), 
+"CPU context not allocated" );
 
     // compute the PPN for the GPT PT1
@@ -405,15 +402,9 @@
 void hal_cpu_context_destroy( thread_t * thread )
 {
-    kmem_req_t          req;
-
+    // get pointer on CPU context
     hal_cpu_context_t * ctx = thread->cpu_context;
 
     // release CPU context if required
-    if( ctx != NULL )
-    {    
-        req.type = KMEM_KCM;
-        req.ptr  = ctx;
-        kmem_free( &req );
-    }
+    if( ctx != NULL )  kmem_free( ctx , bits_log2( sizeof(hal_cpu_context_t)) );
 
 }  // end hal_cpu_context_destroy()
@@ -434,10 +425,6 @@
 
     // allocate memory for fpu_context
-    kmem_req_t  req;
-    req.type   = KMEM_KCM;
-    req.flags  = AF_KERNEL | AF_ZERO;
-    req.order  = bits_log2( sizeof(hal_fpu_context_t) );
-
-    hal_fpu_context_t * context = kmem_alloc( &req );
+    hal_fpu_context_t * context = kmem_alloc( bits_log2( sizeof(hal_fpu_context_t) ),
+                                              AF_KERNEL | AF_ZERO );
 
     if( context == NULL ) return -1;
@@ -454,5 +441,6 @@
     hal_fpu_context_t * context = thread->fpu_context;
 
-    assert( __FUNCTION__, (context != NULL) , "fpu context not allocated" );
+assert( __FUNCTION__, (context != NULL) , 
+"fpu context not allocated" );
 
     memset( context , 0 , sizeof(hal_fpu_context_t) );
@@ -478,15 +466,9 @@
 void hal_fpu_context_destroy( thread_t * thread )
 {
-    kmem_req_t  req;
-
-    hal_fpu_context_t * context = thread->fpu_context;
+    // get pointer on FPU context
+    hal_fpu_context_t * ctx = thread->fpu_context;
 
     // release FPU context if required
-    if( context != NULL )
-    {    
-        req.type = KMEM_KCM;
-        req.ptr  = context;
-        kmem_free( &req );
-    }
+    if( ctx != NULL ) kmem_free( ctx , bits_log2( sizeof(hal_fpu_context_t)) );
 
 }  // end hal_fpu_context_destroy()
Index: trunk/hal/tsar_mips32/core/hal_drivers.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_drivers.c	(revision 679)
+++ trunk/hal/tsar_mips32/core/hal_drivers.c	(revision 686)
@@ -2,5 +2,7 @@
  * hal_drivers.c - Driver initializers for TSAR
  *
- * Copyright (c) 2017 Maxime Villard
+ * Author        Maxime Villard (2017)
+ *
+ * Copyright (c) UPMC Sorbonne Universites
  *
  * This file is part of ALMOS-MKH.
Index: trunk/hal/tsar_mips32/core/hal_exception.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_exception.c	(revision 679)
+++ trunk/hal/tsar_mips32/core/hal_exception.c	(revision 686)
@@ -228,5 +228,5 @@
             // try to map the unmapped PTE
             error = vmm_handle_page_fault( process, 
-                                           bad_vaddr >> CONFIG_PPM_PAGE_SHIFT );
+                                           bad_vaddr >> CONFIG_PPM_PAGE_ORDER );
 
             if( error == EXCP_NON_FATAL )            // page-fault successfully handled
@@ -278,5 +278,5 @@
             // try to handle a possible COW
             error = vmm_handle_cow( process,
-                                    bad_vaddr >> CONFIG_PPM_PAGE_SHIFT );
+                                    bad_vaddr >> CONFIG_PPM_PAGE_ORDER );
 
             if( error == EXCP_NON_FATAL )        // COW successfully handled
@@ -358,6 +358,6 @@
     remote_busylock_acquire( lock_xp );
 
-    nolock_printk("\n=== thread(%x,%x) / core[%d] / cycle %d ===\n",
-    process->pid, this->trdid, core->lid, (uint32_t)hal_get_cycles() );
+    nolock_printk("\n=== thread(%x,%x) / core[%x,%d] / cycle %d ===\n",
+    process->pid, this->trdid, process->pid, core->lid, (uint32_t)hal_get_cycles() );
 
 	nolock_printk("busylocks = %d / blocked_vector = %X / flags = %X\n\n",
Index: trunk/hal/tsar_mips32/core/hal_gpt.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_gpt.c	(revision 679)
+++ trunk/hal/tsar_mips32/core/hal_gpt.c	(revision 686)
@@ -2,5 +2,5 @@
  * hal_gpt.c - implementation of the Generic Page Table API for TSAR-MIPS32
  *
- * Author   Alain Greiner (2016,2017,2018,2019)
+ * Author   Alain Greiner (2016,2017,2018,2019,2020)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -37,4 +37,21 @@
 
 ////////////////////////////////////////////////////////////////////////////////////////
+// The Page Table for the TSAR-MIPS32 MMU is defined as a two levels radix tree.
+//
+// It defines two page sizes : 4 Kbytes pages, and 2 Mbytes pages.
+// The virtual address space size is 4 Gbytes (32 bits virtual addresses). 
+// The physical address space is limited to 1 Tbytes (40 bits physical addresses).
+// - For a 4 Kbytes page, the VPN uses 20 bits, and the PPN requires 28 bits.
+// - For a 2 Mbytes page, the PPN uses 11 bits, and the PPN requires 19 bits.
+//
+// The first level array (PT1) contains 2048 entries, each entry contains 4 bytes,
+// and this array is aligned on a 8K bytes boundary.
+//
+// The second level array (PT2) contains 512 entries, each entry contains 8 bytes,
+// and this array is ligned on a 4K bytes boundary. 
+////////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////////
 // This define the masks for the TSAR MMU PTE attributes (from TSAR MMU specification)
 ////////////////////////////////////////////////////////////////////////////////////////
@@ -152,12 +169,9 @@
 
 // check page size
-assert( __FUNCTION__, (CONFIG_PPM_PAGE_SIZE == 4096) , "the TSAR page size must be 4 Kbytes\n" );
-
-    // allocates 2 physical pages for PT1
-	kmem_req_t req;
-	req.type  = KMEM_PPM;
-	req.order = 1;                     // 2 small pages 
-	req.flags = AF_KERNEL | AF_ZERO;
-	base = kmem_alloc( &req );
+assert( __FUNCTION__, (CONFIG_PPM_PAGE_SIZE == 4096) , 
+"the TSAR page size must be 4 Kbytes\n" );
+
+    // allocates 8 Kbytes for PT1
+	base = kmem_alloc( 13 , AF_ZERO );
 
 	if( base == NULL ) 
@@ -197,5 +211,4 @@
     uint32_t   * pt2;
     uint32_t     attr;
-	kmem_req_t   req;
 
     thread_t * this = CURRENT_THREAD;
@@ -241,16 +254,12 @@
                 }
 
-                // release the page allocated for the PT2
-                req.type = KMEM_PPM;
-                req.ptr  = pt2;
-                kmem_free( &req );
+                // release the 4K bytes allocated for the PT2
+                kmem_free( pt2 , 12 );
             }
         }
 	}
 
-    // release the PT1
-    req.type = KMEM_PPM;
-    req.ptr  = pt1;
-    kmem_free( &req );
+    // release the 8K bytes allocated for PT1
+    kmem_free( pt1 , 13 );
 
 #if DEBUG_HAL_GPT_DESTROY
@@ -272,7 +281,4 @@
     xptr_t              pte1_xp;         // extended pointer on PT1[x1] entry
 	uint32_t            pte1;            // value of PT1[x1] entry
-
-    kmem_req_t          req;             // kmem request fro PT2 allocation
-
     uint32_t          * pt2;             // local pointer on PT2 base
 	ppn_t               pt2_ppn;         // PPN of page containing PT2
@@ -334,8 +340,6 @@
             hal_disable_irq( &sr_save );
 
-            req.type  = KMEM_PPM;
-            req.order = 0;  
-            req.flags = AF_ZERO | AF_KERNEL;
-            pt2       = kmem_remote_alloc( gpt_cxy , &req );
+            // allocate a 4K bytes PT2
+            pt2       = kmem_remote_alloc( gpt_cxy , 12 , AF_ZERO );
 
             if( pt2 == NULL )
@@ -863,6 +867,4 @@
     uint32_t   * dst_pt2;   // local pointer on DST PT2
 
-	kmem_req_t   req;       // for PT2 allocation
-
     uint32_t     src_pte1;
     uint32_t     dst_pte1;
@@ -917,9 +919,6 @@
         if( (dst_pte1 & TSAR_PTE_MAPPED) == 0 ) 
         { 
-            // allocate one physical page for a new PT2
-	        req.type  = KMEM_PPM;
-	        req.order = 0;                     // 1 small page 
-	        req.flags = AF_KERNEL | AF_ZERO;
-	        dst_pt2   = kmem_alloc( &req );
+            // allocate one 4K bytes physical page for a new PT2
+	        dst_pt2   = kmem_alloc( 12 , AF_ZERO );
 
             if( dst_pt2 == NULL )
Index: trunk/hal/tsar_mips32/core/hal_ppm.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_ppm.c	(revision 679)
+++ trunk/hal/tsar_mips32/core/hal_ppm.c	(revision 686)
@@ -79,5 +79,5 @@
 
 	// compute number of pages required to store page descriptor array
-	uint32_t pages_tbl_nr = bytes >> CONFIG_PPM_PAGE_SHIFT;
+	uint32_t pages_tbl_nr = bytes >> CONFIG_PPM_PAGE_ORDER;
 
 	// compute total number of reserved pages (kernel code & pages_tbl[])
@@ -90,5 +90,5 @@
 	ppm->vaddr_base = NULL;
 	ppm->pages_tbl  = (page_t*)( ppm->vaddr_base +
-	                             (pages_tbl_offset << CONFIG_PPM_PAGE_SHIFT) );
+	                             (pages_tbl_offset << CONFIG_PPM_PAGE_ORDER) );
 
 	// initialize all page descriptors in pages_tbl[]
Index: trunk/hal/tsar_mips32/core/hal_special.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_special.c	(revision 679)
+++ trunk/hal/tsar_mips32/core/hal_special.c	(revision 686)
@@ -2,5 +2,5 @@
  * hal_special.c - implementation of Generic Special Register Access API for TSAR-MIPS32
  * 
- * Author    Alain Greiner (2016,2017)
+ * Author    Alain Greiner (2016,2017,2018,2019,2020)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -55,5 +55,6 @@
 // For the TSAR architecture, this function register the physical address of
 // the first level page table (PT1) in the PTPR register.
-// It activates the intructions MMU, and de-activates the data MMU.
+// It activates the intructions MMU, and de-activates the data MMU, that is NOT
+// used by the kernel for 32 bits architectures.
 /////////////////////////////////////////////////////////////////////////////////
 void hal_mmu_init( gpt_t * gpt )
Index: trunk/hal/tsar_mips32/core/hal_uspace.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_uspace.c	(revision 679)
+++ trunk/hal/tsar_mips32/core/hal_uspace.c	(revision 686)
@@ -49,5 +49,6 @@
     uint32_t cxy = (uint32_t)GET_CXY( k_dst_xp );
  
-assert( __FUNCTION__, (CURRENT_THREAD->process->pid > 0), "must be called by an user thread" );
+assert( __FUNCTION__, (CURRENT_THREAD->process->pid > 0), 
+"must be called by an user thread" );
 
 #if DEBUG_HAL_USPACE
@@ -147,5 +148,6 @@
     uint32_t cxy = (uint32_t)GET_CXY( k_src_xp );
 
-assert( __FUNCTION__, (CURRENT_THREAD->process->pid > 0), "must be called by an user thread" );
+assert( __FUNCTION__, (CURRENT_THREAD->process->pid > 0), 
+"must be called by an user thread" );
 
 #if DEBUG_HAL_USPACE
@@ -236,5 +238,6 @@
     uint32_t cxy = (uint32_t)GET_CXY( k_dst_xp );
 
-assert( __FUNCTION__, (CURRENT_THREAD->process->pid > 0), "must be called by an user thread" );
+assert( __FUNCTION__, (CURRENT_THREAD->process->pid > 0), 
+"must be called by an user thread" );
 
     hal_disable_irq( &save_sr );
@@ -291,5 +294,6 @@
     uint32_t cxy = (uint32_t)GET_CXY( k_src_xp );
 
-assert( __FUNCTION__, (CURRENT_THREAD->process->pid > 0), "must be called by an user thread" );
+assert( __FUNCTION__, (CURRENT_THREAD->process->pid > 0), 
+"must be called by an user thread" );
 
     hal_disable_irq( &save_sr );
@@ -343,5 +347,6 @@
     uint32_t str   = (uint32_t)u_str;
 
-assert( __FUNCTION__, (CURRENT_THREAD->process->pid > 0), "must be called by an user thread" );
+assert( __FUNCTION__, (CURRENT_THREAD->process->pid > 0), 
+"must be called by an user thread" );
 
     hal_disable_irq( &save_sr ); 
@@ -352,11 +357,13 @@
         "mfc2   $15,   $1           \n"   /* $15 <= MMU_MODE (DTLB off)     */
         "ori    $14,   $15,  0x4    \n"   /* $14 <= mode DTLB on            */
+        "mtc2   $14,   $1			\n"   /* set DTLB on                    */
         "1:                         \n"
-        "mtc2   $14,   $1			\n"   /* set DTLB on                    */
         "lb	    $12,   0($13)       \n"   /* $12 <= one byte from u_space   */
+        "beq    $12,   $0,   2f     \n"   /* exit loop when NUL found       */
+        "addi   $13,   $13,  1      \n"   /* increment address              */
+        "j                   1b     \n"   /* jump to next iteration         */
+        "addi	%0,    %0,   1      \n"   /* increment count if not NUL     */
+        "2:                         \n"
         "mtc2   $15,   $1			\n"   /* set DTLB off                   */
-        "addi   $13,   $13,  1      \n"   /* increment address              */
-        "bne    $12,   $0,   1b     \n"   /* loop until NUL found           */
-        "addi	%0,    %0,   1      \n"   /* increment count                */
         ".set reorder               \n"
         : "+r"(count) 
