Index: trunk/hal/tsar_mips32/core/hal_context.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_context.c	(revision 401)
+++ trunk/hal/tsar_mips32/core/hal_context.c	(revision 406)
@@ -33,4 +33,5 @@
 #include <cluster.h>
 #include <hal_context.h>
+#include <hal_kentry.h>
 
 /////////////////////////////////////////////////////////////////////////////////////////
@@ -38,14 +39,13 @@
 /////////////////////////////////////////////////////////////////////////////////////////
 
-#define SR_USR_MODE       0xFC11
-#define SR_USR_MODE_FPU   0x2000FC11
-#define SR_SYS_MODE       0xFC00
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// These structuree defines the cpu_context anf fpu_context for TSAR MIPS32.
+#define SR_USR_MODE       0x0000FC13
+#define SR_USR_MODE_FPU   0x2000FC13
+#define SR_SYS_MODE       0x0000FC00
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// This structuree defines the cpu_context for TSAR MIPS32.
 // These registers are saved/restored at each context switch.
-// WARNING : update the hal_***_context_save() and hal_***_context_restore()
-//           functions when modifying this structure, and check the two
-//           CONFIG_CPU_CTX_SIZE & CONFIGFPU_CTX_SIZE configuration parameterss. 
+// WARNING : check the two CONFIG_CPU_CTX_SIZE & CONFIG_FPU_CTX_SIZE configuration 
+//           parameterss when modifying this structure.
 /////////////////////////////////////////////////////////////////////////////////////////
 
@@ -80,5 +80,5 @@
 
     uint32_t t8_24;      // slot 24
-    uint32_t t8_25;      // slot 25
+    uint32_t t9_25;      // slot 25
     uint32_t hi_26;      // slot 26
     uint32_t lo_27;      // slot 27
@@ -107,14 +107,13 @@
 
 
-
 /////////////////////////////////////////////////////////////////////////////////////////
 //        CPU context access functions
 /////////////////////////////////////////////////////////////////////////////////////////
 
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// Seven registers are initialised by this function:
-// GPR : sp_29 / fp_30 / ra_31
-// CP0 : c0_sr / c0_th
+/////////////////////////////////////////////////////////////////////////////////////////
+// This function allocates and initializes the cpu_context stucture in thread descriptor.
+// The following context slots are initialised by this function:
+// GPR : a0_04 / sp_29 / fp_30 / ra_31
+// CP0 : c0_sr / c0_th / c0_epc
 // CP2 : c2_ptpr / c2_mode
 /////////////////////////////////////////////////////////////////////////////////////////
@@ -123,10 +122,12 @@
     kmem_req_t  req;
 
-    context_dmsg("\n[INFO] %s : enters for thread %x in process %x\n",
+    assert( (sizeof(hal_cpu_context_t) <= CONFIG_CPU_CTX_SIZE) , __FUNCTION__ ,
+    "inconsistent CPU context size" );
+
+    context_dmsg("\n[DMSG] %s : enters for thread %x in process %x\n",
                  __FUNCTION__ , thread->trdid , thread->process->pid );
 
     // allocate memory for cpu_context
     req.type   = KMEM_CPU_CTX;
-    req.size   = sizeof(hal_cpu_context_t);
     req.flags  = AF_KERNEL | AF_ZERO;
 
@@ -158,7 +159,9 @@
 
     // initialise context
+    context->a0_04      = (uint32_t)thread->entry_args;
 	context->sp_29      = sp_29; 
-	context->fp_30      = sp_29;                          // TODO check this [AG]
-    context->ra_31      = (uint32_t)thread->entry_func;
+	context->fp_30      = sp_29;                               // TODO check this [AG]
+    context->ra_31      = (uint32_t)&hal_kentry_eret;
+    context->c0_epc     = (uint32_t)thread->entry_func;
 	context->c0_sr      = c0_sr;
 	context->c0_th      = (uint32_t)thread; 
@@ -166,8 +169,20 @@
 	context->c2_mode    = c2_mode;
 
-    context_dmsg("\n[INFO] %s : exit for thread %x in process %x / ra = %x\n",
-                 __FUNCTION__ , thread->trdid , thread->process->pid , context->ra_31 );
-
+    context_dmsg("\n[DMSG] %s : exit for thread %x in process %x\n"
+                 " - a0   = %x\n"
+                 " - sp   = %x\n"
+                 " - fp   = %x\n"
+                 " - ra   = %x\n"
+                 " - sr   = %x\n"
+                 " - th   = %x\n"   
+                 " - epc  = %x\n"   
+                 " - ptpr = %x\n"   
+                 " - mode = %x\n",  
+                 __FUNCTION__ , thread->trdid , thread->process->pid,
+                 context->a0_04, context->sp_29, context->fp_30, context->ra_31,
+                 context->c0_sr, context->c0_th, context->c0_epc,
+                 context->c2_ptpr, context->c2_mode );
     return 0;
+
 }  // end hal_cpu_context_create()
 
@@ -177,9 +192,9 @@
     hal_cpu_context_t * ctx = (hal_cpu_context_t *)thread->cpu_context;
 
-    printk("\n***** cpu_context for thread %x in cluster %x / ctx = %x\n" 
+    printk("\n***** CPU context for thread %x in process %x / cycle %d\n" 
            " gp_28   = %X    sp_29   = %X    ra_31   = %X\n" 
            " c0_sr   = %X    c0_epc  = %X    c0_th = %X\n"
            " c2_ptpr = %X    c2_mode = %X\n",
-           thread->trdid, local_cxy, ctx,
+           thread->trdid, thread->process->pid, hal_time_stamp(),
            ctx->gp_28   , ctx->sp_29   , ctx->ra_31,
            ctx->c0_sr   , ctx->c0_epc  , ctx->c0_th,
@@ -188,150 +203,26 @@
 }  // end hal_context_display()
 
-/*
-////////////////////////////////////////////////////////////////////////////////////////
-// This static function makes the actual context switch.    
-////////////////////////////////////////////////////////////////////////////////////////
-static void hal_do_switch( hal_cpu_context_t * ctx_old,
-                           hal_cpu_context_t * ctx_new )
-{
-    asm volatile(
-    ".set noat                       \n"
-    ".set noreorder                  \n"
-    "move    $26,   %0               \n"
-
-    "mfc0    $27,   $14              \n"
-    "sw      $27,   0*4($26)         \n"
- 
-    "sw      $1,    1*4($26)         \n"
-    "sw      $2,    2*4($26)         \n"
-    "sw      $3,    3*4($26)         \n"
-    "sw      $4,    4*4($26)         \n"
-    "sw      $5,    5*4($26)         \n"
-    "sw      $6,    6*4($26)         \n"
-    "sw      $7,    7*4($26)         \n"
-
-    "sw      $8,    8*4($26)         \n"
-    "sw      $9,    9*4($26)         \n"
-    "sw      $10,  10*4($26)         \n"
-    "sw      $11,  11*4($26)         \n"
-    "sw      $12,  12*4($26)         \n"
-    "sw      $13,  13*4($26)         \n"
-    "sw      $14,  14*4($26)         \n"
-    "sw      $15,  15*4($26)         \n"
-
-    "sw      $16,  16*4($26)         \n"
-    "sw      $17,  17*4($26)         \n"
-    "sw      $18,  18*4($26)         \n"
-    "sw      $19,  19*4($26)         \n"
-    "sw      $20,  20*4($26)         \n"
-    "sw      $21,  21*4($26)         \n"
-    "sw      $22,  22*4($26)         \n"
-    "sw      $23,  23*4($26)         \n"
-
-    "sw      $24,  24*4($26)         \n"
-    "sw      $25,  25*4($26)         \n"
-
-    "mfhi    $27                     \n"
-    "sw      $27,  26*4($26)         \n"
-    "mflo    $27                     \n"
-    "sw      $27,  27*4($26)         \n"
-
-    "sw      $28,  28*4($26)         \n"
-    "sw      $29,  29*4($26)         \n"
-    "sw      $30,  30*4($26)         \n"
-    "sw      $31,  31*4($26)         \n"
-
-	"mfc2    $27,  $0                \n"
-	"sw      $27,  32*4($26)         \n"
-	"mfc2    $27,  $1                \n"
-	"sw      $27,  33*4($26)         \n"
-
-    "mfc0	 $27,  $12               \n"
-	"sw      $27,  34*4($26)         \n"
-    "mfc0	 $27,  $4, 2             \n"
-	"sw      $27,  35*4($26)         \n"
-
-    "sync                            \n"
-
-    "move    $26,   %1               \n"
-
-    "lw      $27,   0*4($26)         \n"
-    "mtc0    $27,   $14              \n"
-
-    "lw      $1,    1*4($26)         \n"
-    "lw      $2,    2*4($26)         \n"
-    "lw      $3,    3*4($26)         \n"
-    "lw      $4,    4*4($26)         \n"
-    "lw      $5,    5*4($26)         \n"
-    "lw      $6,    6*4($26)         \n"
-    "lw      $7,    7*4($26)         \n"
-
-    "lw      $8,    8*4($26)         \n"
-    "lw      $9,    9*4($26)         \n"
-    "lw      $10,  10*4($26)         \n"
-    "lw      $11,  11*4($26)         \n"
-    "lw      $12,  12*4($26)         \n"
-    "lw      $13,  13*4($26)         \n"
-    "lw      $14,  14*4($26)         \n"
-    "lw      $15,  15*4($26)         \n"
-
-	"lw      $16,  16*4($26)         \n"
-	"lw      $17,  17*4($26)         \n"
-    "lw      $18,  18*4($26)         \n"
-    "lw      $19,  19*4($26)         \n"
-    "lw      $20,  20*4($26)         \n"
-    "lw      $21,  21*4($26)         \n"
-    "lw      $22,  22*4($26)         \n"
-    "lw      $23,  23*4($26)         \n"
-
-    "lw      $24,  24*4($26)         \n"
-    "lw      $25,  25*4($26)         \n"
-
-    "lw      $27,  26*4($26)         \n"
-    "mthi    $27                     \n"
-    "lw      $27,  27*4($26)         \n"
-    "mtlo    $27                     \n"
-
-	"lw      $28,  28*4($26)         \n"
-	"lw      $29,  29*4($26)         \n"
-	"lw      $30,  30*4($26)         \n"
-	"lw      $31,  31*4($26)         \n"
-
-	"lw      $27,  32*4($26)         \n"
-	"mtc2    $27,  $0                \n"
-	"lw      $27,  33*4($26)         \n"
-	"mtc2    $27,  $1                \n"
-
-	"lw      $27,  34*4($26)         \n"
-    "mtc0	 $27,  $12               \n"
-	"lw      $27,  35*4($26)         \n"
-    "mtc0	 $27,  $4, 2             \n"
-
-    "jr      $31                     \n"
-
-	".set reorder                    \n"
-    ".set at                         \n"
-    : : "r"(ctx_old) , "r"(ctx_new) : "$26" , "$27" , "memory" ); 
-
-}  // hal_context_switch()
-
-*/
-
 /////////////////////////////////////////////////////////////////////////////////////////
 // These registers are saved/restored to/from CPU context defined by <ctx> argument.
 // - GPR : all, but (zero, k0, k1), plus (hi, lo)
-// - CP0 : c0_th , c0_sr 
-// - CP2 : c2_ptpr , C2_mode, C2_epc
-/////////////////////////////////////////////////////////////////////////////////////////
-void hal_cpu_context_switch( thread_t * old,
-                             thread_t * new )
-{
-    hal_cpu_context_t * ctx_old = old->cpu_context;
-    hal_cpu_context_t * ctx_new = new->cpu_context;
+// - CP0 : c0_th , c0_sr , C0_epc
+// - CP2 : c2_ptpr , C2_mode
+/////////////////////////////////////////////////////////////////////////////////////////
+// old_thread  : pointer on current thread descriptor
+// new_thread  : pointer on new thread descriptor
+/////////////////////////////////////////////////////////////////////////////////////////
+void hal_cpu_context_switch( thread_t * old_thread,
+                             thread_t * new_thread )
+{
+    hal_cpu_context_t * ctx_old = old_thread->cpu_context;
+    hal_cpu_context_t * ctx_new = new_thread->cpu_context;
 
     #if CONFIG_CONTEXT_DEBUG
-    hal_cpu_context_display( old );
-    hal_cpu_context_display( new );
+    hal_cpu_context_display( old_thread );
+    hal_cpu_context_display( new_thread );
     #endif
+
+    // reset loadable field in new thread descriptor 
+    new_thread->flags &= ~THREAD_FLAG_LOADABLE;
 
     hal_do_switch( ctx_old , ctx_new );
@@ -377,7 +268,4 @@
 
 
-
-
-
 ///////////////////////////////////////////////////
 error_t hal_fpu_context_create( thread_t * thread )
@@ -385,7 +273,9 @@
     kmem_req_t  req;
 
+    assert( (sizeof(hal_fpu_context_t) <= CONFIG_FPU_CTX_SIZE) , __FUNCTION__ ,
+    "inconsistent FPU context size" );
+
     // allocate memory for uzone
     req.type   = KMEM_FPU_CTX;
-    req.size   = sizeof(hal_fpu_context_t);
     req.flags  = AF_KERNEL | AF_ZERO;
 
@@ -407,5 +297,4 @@
     // allocate memory for dst fpu_context
     req.type   = KMEM_FPU_CTX;
-    req.size   = sizeof(hal_fpu_context_t);
     req.flags  = AF_KERNEL | AF_ZERO;
 
@@ -435,57 +324,4 @@
 
 }  // end hal_fpu_context_destroy()
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// These registers are initialised:
-// - GPR : sp_29 , fp_30 , a0
-// - CP0 : c0_sr , c0_epc , c0_th
-// - CP2 : C2_ptpr , c2_mode
-// TODO Quand cette fonction est-elle appelée? [AG]
-/////////////////////////////////////////////////////////////////////////////////////////
-void hal_cpu_context_load( thread_t * thread )
-{
-    // get relevant values from thread context
-    hal_cpu_context_t * ctx     = (hal_cpu_context_t *)thread->cpu_context;     
-    uint32_t            sp_29   = ctx->sp_29;
-    uint32_t            fp_30   = ctx->fp_30;
-    uint32_t            c0_th   = ctx->c0_th;
-    uint32_t            c0_sr   = ctx->c0_sr;
-    uint32_t            c2_ptpr = ctx->c2_ptpr;
-    uint32_t            c2_mode = ctx->c2_mode;
- 
-    // get pointer on entry function & argument from thread attributes
-    uint32_t            func    = (uint32_t)thread->entry_func;
-    uint32_t            args    = (uint32_t)thread->entry_args;
-
-    // reset loadable field in thread descriptor 
-    thread->flags &= ~THREAD_FLAG_LOADABLE;
-
-    // load registers
-    asm volatile(
-    ".set noreorder                \n"
-	"or       $26,    %0,    $0    \n"   /* $26 <= stack pointer                */
-	"or       $27,    %2,    $0    \n"   /* $27 <= status register              */
-	"addiu    $26,    $26,  -4     \n"   /* decrement stack pointer             */
-	"or       $4,     %7,   $0     \n"   /* load a0                             */
-	"sw       $4,     ($26)        \n"   /* set entry_args in stack             */
-	"ori      $27,    $27,  0x2    \n"   /* set EXL flag in status register     */
-	"mtc0     $27,    $12          \n"   /* load c0_sr                          */
-	"mtc0     %3,     $4,    2     \n"   /* load c0_th                          */
-	"mtc2     %4,     $0           \n"   /* load c2 ptpr                        */
-	"mtc0     %6,     $14          \n"   /* load c0_epc                         */
-	"or	      $29,	  $16,  $0     \n"   /* load sp_29                          */
-	"or	      $30,	  %1,   $0     \n"   /* load fp_30                          */
-    "mtc2     %5,     $1           \n"   /* load c2_mode                        */
-    "nop                           \n"
-    "eret                          \n"   /* jump to user code                   */
-    "nop                           \n"
-    ".set reorder                  \n"
-    : 
-    : "r"(sp_29),"r"(fp_30),"r"(c0_sr),"r"(c0_th),
-      "r"(c2_ptpr),"r"(c2_mode),"r"(func),"r"(args)
-    : "$4","$26","$27","$29","$30" );
-
-}  // end hal_cpu_context_load()
-
 
 //////////////////////////////////////////////
Index: trunk/hal/tsar_mips32/core/hal_exception.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_exception.c	(revision 401)
+++ trunk/hal/tsar_mips32/core/hal_exception.c	(revision 406)
@@ -24,4 +24,5 @@
 #include <hal_types.h>
 #include <hal_irqmask.h>
+#include <hal_special.h>
 #include <hal_exception.h>
 #include <thread.h>
@@ -35,5 +36,5 @@
 #include <syscalls.h>
 #include <remote_spinlock.h>
-#include <mips32_uzone.h>
+#include <hal_kentry.h>
 
 
@@ -57,13 +58,13 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
-// This enum defines the relevant subtypes for a MMU exception reported by the mips32.
+// This enum defines the mask valuesi for an MMU exception code reported by the mips32.
 //////////////////////////////////////////////////////////////////////////////////////////
 
 typedef enum
 {
-    MMU_EXCP_PAGE_UNMAPPED,
-    MMU_EXCP_USER_PRIVILEGE,
-    MMU_EXCP_USER_EXEC,
-    MMU_EXCP_USER_WRITE,
+    MMU_EXCP_PAGE_UNMAPPED   = 0x0003,
+    MMU_EXCP_USER_PRIVILEGE  = 0x0004,
+    MMU_EXCP_USER_WRITE      = 0x0008,
+    MMU_EXCP_USER_EXEC       = 0x1010,
 }
 mmu_exception_subtype_t;
@@ -86,5 +87,5 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
-// This static function is called when a FPU Coprocessor Unavailable exception has been 
+// This function is called when a FPU Coprocessor Unavailable exception has been 
 // detected for the calling thread. 
 // It enables the FPU, It saves the current FPU context in the current owner thread 
@@ -94,5 +95,5 @@
 // @ return always EXCP_NON_FATAL
 //////////////////////////////////////////////////////////////////////////////////////////
-static error_t hal_fpu_exception( thread_t * this )
+error_t hal_fpu_exception( thread_t * this )
 {
 	core_t   * core = this->core; 
@@ -119,5 +120,5 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
-// This static function is called when an MMU exception has been detected. 
+// This function is called when an MMU exception has been detected. 
 // It get the relevant exception arguments from the MMU.
 // It signal a fatal error in case of illegal access. In case of page unmapped
@@ -128,20 +129,25 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 // @ this     : pointer on faulty thread descriptor.
+// @ is_ins   : IBE if true / DBE if false.
 // @ return EXCP_NON_FATAL / EXCP_USER_ERROR / EXCP_KERNEL_PANIC
 //////////////////////////////////////////////////////////////////////////////////////////
-static error_t hal_mmu_exception( thread_t * this ) 
-{
-	process_t      * process;     // local process descriptor
-    error_t          error;       // return value
-
-    reg_t            mmu_ins_excp_code;
-    reg_t            mmu_ins_bad_vaddr;
-    reg_t            mmu_dat_excp_code;
-    reg_t            mmu_dat_bad_vaddr;
-
-    intptr_t         bad_vaddr;
+error_t hal_mmu_exception( thread_t * this,
+                           bool_t     is_ins ) 
+{
+	process_t      * process;
+    error_t          error;
+
+    uint32_t         mmu_ins_excp_code;
+    uint32_t         mmu_ins_bad_vaddr;
+    uint32_t         mmu_dat_excp_code;
+    uint32_t         mmu_dat_bad_vaddr;
+
+    uint32_t         bad_vaddr;
     uint32_t         excp_code;
 	
-    process     = this->process;
+    process = this->process;
+
+    excp_dmsg("\n[DMSG] %s : enter for thread %x in process %x / is_ins = %d\n",
+    __FUNCTION__ , this->trdid , process->pid , is_ins );
 
     // get relevant values from MMU
@@ -151,33 +157,30 @@
 	                  &mmu_dat_bad_vaddr );
 
-    // get exception code and faulty vaddr
-    if( mmu_ins_excp_code )
+    excp_dmsg("\n[DMSG] %s : icode = %x / ivaddr = %x / dcode = %x / dvaddr = %x\n",
+    __FUNCTION__ , mmu_ins_excp_code , mmu_ins_bad_vaddr ,
+                   mmu_dat_excp_code , mmu_dat_bad_vaddr );
+
+    // get exception code and faulty vaddr, depending on IBE/DBE
+    if( is_ins )
     {
         excp_code = mmu_ins_excp_code;
         bad_vaddr = mmu_ins_bad_vaddr;
     }
-    else if( mmu_dat_excp_code )
+    else 
     {
         excp_code = mmu_dat_excp_code;
         bad_vaddr = mmu_dat_bad_vaddr;
     }
-    else
-    {
-         return EXCP_NON_FATAL;
-    }
-
-	vmm_dmsg("\n[INFO] %s : enters for thread %x / process %x"
-             " / bad_vaddr = %x / excep_code = %x\n", 
-		     __FUNCTION__, this->trdid , process->pid , bad_vaddr , excp_code );
-
-    // on TSAR, a kernel thread should not rise an MMU exception
-	assert( (this->type != THREAD_USER) , __FUNCTION__ ,
-    "thread %x is a kernel thread / vaddr = %x\n", this->trdid , bad_vaddr );
-  
+
+    excp_dmsg("\n[DMSG] %s : excp_code = %x / bad_vaddr = %x\n",
+    __FUNCTION__ , excp_code , bad_vaddr );
+
     // analyse exception code
     if( excp_code & MMU_EXCP_PAGE_UNMAPPED )
     {
+        excp_dmsg("\n[DMSG] %s : type PAGE_UNMAPPED\n", __FUNCTION__ );
+
         // enable IRQs before handling page fault
-        hal_enable_irq( NULL );
+        // hal_enable_irq( NULL );
 
         // try to map the unmapped PTE
@@ -185,9 +188,9 @@
                                        bad_vaddr >> CONFIG_PPM_PAGE_SHIFT );  // vpn
         // disable IRQs
-        hal_disable_irq( NULL );
+        // hal_disable_irq( NULL );
 
         if( error )     // not enough memory
         {
-            printk("\n[ERROR] in %s for thread %x : cannot map legal vaddr = %x\n",
+            printk("\n[ERROR] in %s for thread %x : cannot map vaddr = %x\n",
                __FUNCTION__ , this->trdid , bad_vaddr );
 
@@ -196,6 +199,6 @@
         else            // page fault successfully handled
         {
-            vmm_dmsg("\n[INFO] %s : page fault handled for vaddr = %x in thread %x\n",
-		             __FUNCTION__ , bad_vaddr , this->trdid );
+            excp_dmsg("\n[DMSG] %s : page fault handled / bad_vaddr = %x / excp_code = %x\n",
+		             __FUNCTION__ , bad_vaddr , excp_code );
   
             return EXCP_NON_FATAL;
@@ -223,5 +226,4 @@
         return EXCP_USER_ERROR;
     }
-
     else  // this is a kernel error => panic    
     {
@@ -309,13 +311,19 @@
 	excCode        = (regs_tbl[UZ_CR] >> 2) & 0xF;
 
+    excp_dmsg("\n[DMSG] %s : enter for thread %x in process %x / xcode = %x / cycle %d\n",
+    __FUNCTION__ , this->trdid , this->process->pid , excCode , hal_time_stamp() );
+
 	switch(excCode)
 	{
         case XCODE_DBE:     // can be non fatal
+        {
+		    error = hal_mmu_exception( this , false );  // data MMU exception
+            break;
+        }
 	    case XCODE_IBE:     // can be non fatal
         {
-		    error = hal_mmu_exception( this );
-        }
-		break;
-
+		    error = hal_mmu_exception( this , true );   // ins MMU exception
+		    break;
+        }
 	    case XCODE_CPU:    // can be non fatal
         {
@@ -328,7 +336,6 @@
 		        error = EXCP_USER_ERROR;
             }
-        }
-		break;
-
+		    break;
+        }
         case XCODE_OVR:    // user fatal error
         case XCODE_RI:     // user fatal error
@@ -337,7 +344,6 @@
         {
 		    error = EXCP_USER_ERROR;
-        }
-	    break;
-
+	        break;
+        }
         default:
         {
@@ -357,4 +363,8 @@
         hal_core_sleep();
     }
+
+    excp_dmsg("\n[DMSG] %s : exit for thread %x in process %x / cycle %d\n",
+    __FUNCTION__ , this->trdid , this->process->pid , hal_time_stamp() );
+
 }  // end hal_do_exception()
 
Index: trunk/hal/tsar_mips32/core/hal_gpt.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_gpt.c	(revision 401)
+++ trunk/hal/tsar_mips32/core/hal_gpt.c	(revision 406)
@@ -131,11 +131,14 @@
 	page_t   * page;
     xptr_t     page_xp;
+    vpn_t      vpn;
+    error_t    error;
+    uint32_t   attr;
+
+    gpt_dmsg("\n[DMSG] %s : core[%x,%d] enter\n", 
+    __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid );
 
     // check page size
-    if( CONFIG_PPM_PAGE_SIZE != 4096 )
-    {
-        printk("\n[PANIC] in %s : For TSAR, the page must be 4 Kbytes\n", __FUNCTION__ );
-        hal_core_sleep();
-    }
+    assert( (CONFIG_PPM_PAGE_SIZE == 4096) , __FUNCTION__ ,
+    "for TSAR, the page must be 4 Kbytes\n" );
 
     // allocates 2 physical pages for PT1
@@ -146,9 +149,9 @@
 	page = (page_t *)kmem_alloc( &req );
 
-	if( page == NULL )
-    {
-		printk("\n[ERROR] in %s : cannot allocate physical memory for PT1\n", __FUNCTION__ );
+	if( page == NULL ) 
+    {
+        printk("\n[ERROR] in %s : cannot allocate memory for PT1\n", __FUNCTION__ );
         return ENOMEM;
-	}
+    }
 
     // initialize generic page table descriptor
@@ -159,5 +162,28 @@
 	gpt->page = GET_PTR( page_xp );
 
+    // identity map the kentry_vseg (must exist for all processes)
+    attr = GPT_MAPPED | GPT_SMALL | GPT_EXECUTABLE | GPT_CACHABLE | GPT_GLOBAL;
+    for( vpn = CONFIG_VMM_KENTRY_BASE;
+         vpn < (CONFIG_VMM_KENTRY_BASE + CONFIG_VMM_KENTRY_SIZE); vpn++ )
+    {
+        gpt_dmsg("\n[DMSG] %s : identity map vpn %d\n", __FUNCTION__ , vpn );
+
+        error = hal_gpt_set_pte( gpt,
+                                 vpn,
+                                 (local_cxy<<20) | (vpn & 0xFFFFF),
+                                 attr );
+
+        if( error )
+        {
+            printk("\n[ERROR] in %s : cannot identity map kentry vseg\n", __FUNCTION__ );
+            return ENOMEM;
+        }
+    }
+
+    gpt_dmsg("\n[DMSG] %s : core[%x,%d] exit\n",
+    __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid );
+
 	return 0;
+
 } // end hal_gpt_create()
 
@@ -245,6 +271,7 @@
 } // end hal_gpt_destroy()
 
-/////////////////////////////////
-void hal_gpt_print( gpt_t * gpt )
+////////////////////////////////
+void hal_gpt_print( gpt_t * gpt,
+                    pid_t   pid )
 {
 	uint32_t   ix1;
@@ -256,9 +283,11 @@
     uint32_t   pte2_attr;
     ppn_t      pte2_ppn;
-
-    printk("*** Page Table for process %x in cluster %x ***\n",
-           CURRENT_THREAD->process->pid , local_cxy );
+    vpn_t      vpn;
+
 
     pt1 = (uint32_t *)gpt->ptr;
+
+    printk("\n***** Generic Page Table for process %x : &gpt = %x / &pt1 = %x\n\n",
+    pid , gpt , pt1 );
 
     // scan the PT1
@@ -270,5 +299,6 @@
             if( (pte1 & TSAR_MMU_SMALL) == 0 )  // BIG page
             {
-                printk(" - BIG   : pt1[%d] = %x\n", ix1 , pte1 );
+                vpn = ix1 << 9;
+                printk(" - BIG   : vpn = %x / pt1[%d] = %X\n", vpn , ix1 , pte1 );
             }
             else                           // SMALL pages
@@ -283,8 +313,10 @@
                     pte2_attr = TSAR_MMU_ATTR_FROM_PTE2( pt2[2 * ix2] );
                     pte2_ppn  = TSAR_MMU_PPN_FROM_PTE2( pt2[2 * ix2 + 1] );
+
 		            if( (pte2_attr & TSAR_MMU_MAPPED) != 0 )
                     {
-                        printk(" - SMALL   : pt1[%d] = %x / pt2[%d] / pt2[%d]\n",
-                               ix1 , pt1[ix1] , 2*ix2 , pte2_attr , 2*ix2+1 , pte2_ppn );
+                        vpn = (ix1 << 9) | ix2;
+                        printk(" - SMALL : vpn = %x / PT2[%d] = %x / pt2[%d] = %x\n",
+                        vpn , 2*ix2 , pte2_attr , 2*ix2+1 , pte2_ppn );
                     }
                 }
@@ -301,13 +333,13 @@
                          uint32_t  attr )    // generic GPT attributes
 {
-    uint32_t          * pt1;                 // virtual base addres of PT1
-	volatile uint32_t * pte1_ptr;            // pointer on PT1 entry
+    uint32_t          * pt1;                 // PT1 base addres
+	uint32_t          * pte1_ptr;            // pointer on PT1 entry
 	uint32_t            pte1;                // PT1 entry value
 
 	ppn_t               pt2_ppn;             // PPN of PT2
-	uint32_t          * pt2;                 // virtual base address of PT2
+	uint32_t          * pt2;                 // PT2 base address
 
 	uint32_t            small;               // requested PTE is for a small page
-	bool_t              atomic;
+    bool_t              success;             // exit condition for while loop below
 
 	page_t            * page;                // pointer on new physical page descriptor
@@ -319,4 +351,7 @@
     uint32_t            tsar_attr;           // PTE attributes for TSAR MMU
 
+    gpt_dmsg("\n[DMSG] %s : core[%x,%d] enter for vpn = %x / ppn = %x / gpt_attr = %x\n", 
+    __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn , ppn , attr );
+ 
     // compute indexes in PT1 and PT2
     ix1 = TSAR_MMU_IX1_FROM_VPN( vpn );
@@ -329,17 +364,19 @@
     tsar_attr = gpt2tsar( attr );
 
-    // get PT1 entry value
+    gpt_dmsg("\n[DMSG] %s : core[%x,%d] / vpn = %x / &pt1 = %x / tsar_attr = %x\n", 
+    __FUNCTION__, local_cxy , CURRENT_THREAD->core->lid , vpn , pt1 , tsar_attr );
+
+    // get pointer on PT1[ix1]
 	pte1_ptr  = &pt1[ix1];
-	pte1      = *pte1_ptr;
-
-    // Big pages (PTE1) are only set for the kernel vsegs, in the kernel init phase.
+
+    // PTE1 (big page) are only set for the kernel vsegs, in the kernel init phase.
     // There is no risk of concurrent access.
 	if( small == 0 ) 
     {
-        if( pte1 != 0 )
-		{
-			panic("\n[PANIC] in %s : set a big page in a mapped PT1 entry / PT1[%d] = %x\n",
-                   __FUNCTION__ , ix1 , pte1 );
-		}
+        // get current pte1 value
+        pte1 = *pte1_ptr;
+
+        assert( (pte1 == 0) , __FUNCTION__ ,
+		"try to set a big page in a mapped PT1 entry / PT1[%d] = %x\n", ix1 , pte1 );
       
         // set the PTE1 
@@ -352,62 +389,58 @@
     // From this point, the requested PTE is a PTE2 (small page)
 
-	if( (pte1 & TSAR_MMU_MAPPED) == 0 )      // the PT1 entry is not valid
-	{
-        // allocate one physical page for the PT2
-	    kmem_req_t req;
-	    req.type  = KMEM_PAGE;
-	    req.size  = 0;                     // 1 small page 
-	    req.flags = AF_KERNEL | AF_ZERO;
-	    page = (page_t *)kmem_alloc( &req );
-        if( page == NULL )
+    // loop to access PTE1 and get pointer on PT2
+    success = false;
+    do
+    {
+        // get current pte1 value
+        pte1 = *pte1_ptr;
+        
+        gpt_dmsg("\n[DMSG] %s : core[%x,%d] / vpn = %x / current_pte1 = %x\n", 
+        __FUNCTION__, local_cxy , CURRENT_THREAD->core->lid , vpn , pte1 );
+        
+        // allocate a PT2 if PT1 entry not valid
+        if( (pte1 & TSAR_MMU_MAPPED) == 0 )             // PT1 entry not valid
+   	    {
+            // allocate one physical page for the PT2
+	        kmem_req_t req;
+	        req.type  = KMEM_PAGE;
+	        req.size  = 0;                       // 1 small page 
+	        req.flags = AF_KERNEL | AF_ZERO;
+            page = (page_t *)kmem_alloc( &req );
+            if( page == NULL )
+            {
+		        printk("\n[ERROR] in %s : cannot allocate PT2\n", __FUNCTION__ );
+                return ENOMEM;
+            }
+
+            // get the PT2 PPN
+            page_xp = XPTR( local_cxy , page );        
+            pt2_ppn = ppm_page2ppn( page_xp );
+
+            // try to atomicaly set the PT1 entry 
+            pte1 = TSAR_MMU_MAPPED | TSAR_MMU_SMALL | pt2_ppn;
+		    success = hal_atomic_cas( pte1_ptr , 0 , pte1 );
+
+            // release allocated PT2 if PT1 entry modified by another thread
+            if( success == false ) ppm_free_pages( page );
+        }
+        else                                           // PT1 entry is valid
         {
-			printk("\n[ERROR] in %s : try to set a small page but cannot allocate PT2\n",
-                    __FUNCTION__ );
-            return ENOMEM;
+            // This valid entry must be a PTD1
+            assert( (pte1 & TSAR_MMU_SMALL) , __FUNCTION__ ,
+            "try to set a small page in a big PT1 entry / PT1[%d] = %x\n", ix1 , pte1 );
+
+            success = true;
         }
 
-        page_xp = XPTR( local_cxy , page );        
-        pt2_ppn = ppm_page2ppn( page_xp );
-        pt2     = (uint32_t *)GET_PTR( ppm_page2base( page_xp ) );
-
-        // try to atomicaly set a PTD1 in the PT1 entry 
-		do 
-		{
-		    atomic = hal_atomic_cas( (void*)pte1, 0 , 
-                                      TSAR_MMU_MAPPED | TSAR_MMU_SMALL | pt2_ppn );
-        } 
-        while( (atomic == false) && (*pte1_ptr == 0) );
-
-	    if( atomic == false ) // the mapping has been done by another thread !!!
-        {
-            // release the allocated page
-	        ppm_free_pages( page );
-
-            // read PT1 entry again 
-			pte1 = *pte1_ptr;
-
-            // compute PPN of PT2 base
-			pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
-
-            // compute pointer on PT2 base
-			pt2 = (uint32_t*)GET_PTR( ppm_ppn2base( pt2_ppn ) );
-		}
-	}
-	else                             // The PT1 entry is valid  
-	{
-        // This valid entry must be a PTD1
-        if( (pte1 & TSAR_MMU_SMALL) == 0 )
-        {
-			printk("\n[ERROR] in %s : set a small page in a big PT1 entry / PT1[%d] = %x\n",
-                    __FUNCTION__ , ix1 , pte1 );
-            return EINVAL;
-        }
-
-        // compute PPN of PT2 base
-		pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
-
-        // compute pointer on PT2 base
-	    pt2 = (uint32_t*)GET_PTR( ppm_ppn2base( pt2_ppn ) );
-	}
+        // get PT2 base from pte1 
+	    pt2_ppn = TSAR_MMU_PTBA_FROM_PTE1( pte1 );
+	    pt2     = (uint32_t *)GET_PTR( ppm_ppn2base( pt2_ppn ) );
+
+        gpt_dmsg("\n[DMSG] %s : core[%x,%d] / vpn = %x / pte1 = %x / &pt2 = %x\n", 
+        __FUNCTION__, local_cxy , CURRENT_THREAD->core->lid , vpn , pte1 , pt2 );
+        
+    }
+    while (success == false);
 
     // set PTE2 in this order
@@ -417,7 +450,12 @@
 	hal_fence();
 
+    gpt_dmsg("\n[DMSG] %s : core[%x,%d] exit / vpn = %x / pte2_attr = %x / pte2_ppn = %x\n", 
+    __FUNCTION__ , local_cxy , CURRENT_THREAD->core->lid , vpn , 
+    pt2[2 * ix2] , pt2[2 * ix2 + 1] );
+ 
 	return 0;
 
 } // end of hal_gpt_set_pte()
+
 
 /////////////////////////////////////
Index: trunk/hal/tsar_mips32/core/hal_interrupt.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_interrupt.c	(revision 401)
+++ trunk/hal/tsar_mips32/core/hal_interrupt.c	(revision 406)
@@ -27,6 +27,4 @@
 #include <thread.h>
 #include <printk.h>
-#include <do_interrupt.h>
-#include <hal_interrupt.h>
 #include <soclib_pic.h>
 
@@ -35,17 +33,11 @@
 		               reg_t    * regs_tbl ) 
 {
-    irq_dmsg("\n[INFO] %s : enter / core[%x,%d] / cycle %d\n",
+    irq_dmsg("\n[DMSG] %s : enter / core[%x,%d] / cycle %d\n",
     __FUNCTION__ , local_cxy , this->core->lid , hal_time_stamp() );
-
-	// update user time	
-	thread_user_time_update( this );
 
     // access local ICU to call the relevant ISR
     soclib_pic_irq_handler();
 	   
-	// update kernel time
-	thread_kernel_time_update( this );
-
-    irq_dmsg("\n[INFO] %s : exit / core[%x,%d] / cycle %d\n",
+    irq_dmsg("\n[DMSG] %s : exit / core[%x,%d] / cycle %d\n",
     __FUNCTION__ , local_cxy , this->core->lid , hal_time_stamp() );
 }
Index: trunk/hal/tsar_mips32/core/hal_kentry.S
===================================================================
--- trunk/hal/tsar_mips32/core/hal_kentry.S	(revision 401)
+++ trunk/hal/tsar_mips32/core/hal_kentry.S	(revision 406)
@@ -24,21 +24,43 @@
  */
 
-#include <mips32_uzone.h>
-
-#---------------------------------------------------------------------------------
-# This code is the unique kernel entry point in case of exception, interrupt,
-# or syscall for the TSAR_MIPS32 architecture.  
-#
-# When we enter the kernel, we test the status register:
-# - If the core is in user mode, we desactivate the MMU, and we save
-#   the core context in the uzone of the calling thread descriptor.
-# - If the core is already in kernel mode (in case of interrupt), 
-#   we save the context in the kernel stack.
-# - In both cases, we increment the cores_in_kernel variable,
-#   and we call the relevant exception/interrupt/syscall handler
-#
-# When we exit the kernel after handler execution:
-# - we restore the core context from the uzone
-#---------------------------------------------------------------------------------
+#define      UZ_MODE         0                 
+#define      UZ_AT           1
+#define      UZ_V0           2
+#define      UZ_V1           3
+#define      UZ_A0           4 
+#define      UZ_A1           5
+#define      UZ_A2           6
+#define      UZ_A3           7
+#define      UZ_T0           8
+#define      UZ_T1           9
+#define      UZ_T2           10
+#define      UZ_T3           11
+#define      UZ_T4           12
+#define      UZ_T5           13
+#define      UZ_T6           14
+#define      UZ_T7           15
+#define      UZ_T8           16
+#define      UZ_T9           17
+#define      UZ_S0           18
+#define      UZ_S1           19
+#define      UZ_S2           20
+#define      UZ_S3           21
+#define      UZ_S4           22
+#define      UZ_S5           23
+#define      UZ_S6           24
+#define      UZ_S7           25
+#define      UZ_S8           26
+#define      UZ_GP           27
+#define      UZ_RA           28
+#define      UZ_EPC          29
+#define      UZ_CR           30
+#define      UZ_SP           31
+#define      UZ_SR           32
+#define      UZ_LO           33
+#define      UZ_HI           34
+
+#define      UZ_REGS         35
+
+#include <kernel_config.h>
 
 	.section   .kentry, "ax", @progbits
@@ -48,159 +70,134 @@
 	.extern    hal_do_syscall
 	.extern    cluster_core_kernel_enter
-	.extern    cluster_core_kernel_exit
+	.extern    cluster_core_kentry_exit
 
 	.org       0x180
-	.ent       kernel_enter
-	.global    kernel_enter
+
+	.global    hal_kentry_enter
+    .global    hal_kentry_eret
 
 	.set       noat
 	.set       noreorder
 
-#define SAVE_SIZE      CPU_REGS_NR*4
-#define LID_WIDTH      2
-#define CXY_WIDTH      8
-#define CXY_MASK       0xFF
-#define MMU_MODE_MASK  0xF
-#define GID_MASK       0x3FF	
-#define LID_MASK       0x3	
-
 #---------------------------------------------------------------------------------
 # Kernel Entry point for Interrupt / Exception / Syscall
+# The c2_dext and c2_iext CP2 registers must have been previously set
+# to "local_cxy", because the kernel run with MMU desactivated.
 #---------------------------------------------------------------------------------
 
-kernel_enter:
-	mfc0    $26,    $12                 # read SR to test user/kernel mode
-	andi    $26,    $26,  0x10          # User Mode bitmask
-	beq     $26,    $0,	  kernel_mode
-	ori     $26,    $0,	  0x3		    # $26 <= MMU OFF value
+hal_kentry_enter:
+
+	mfc0    $26,    $12                 # get c0_sr 
+	andi    $26,    $26,  0x10          # test User Mode bit
+	beq     $26,    $0,	  kernel_mode   # jump if core already in kernel
+	ori     $27,    $0,	  0x3           # $27 <= code for MMU OFF
 	
 #---------------------------------------------------------------------------------------	
-# this code is executed when the core is in user mode:
-# - we use the uzone defined in user thread descriptor. 
-# - we set the MMU off, and save the CP2_MODE register to uzone.
-# - we save the user thread stack pointer to uzone and load the kernel stack pointer
-# - we store the uzone pointer in $27
+# This code is executed when the core is in user mode:
+# - save current c2_mode in $26.
+# - set MMU OFF.
+# - save user stack pointer in $27.
+# - set kernel stack pointer in $29.
 
 user_mode:
-	mtc2    $26,    $1			        # set MMU OFF
-	nop
-
-	mfc0    $26,    $4,   2             # $26 <= thread pointer 
-	lw      $26,    0($26)              # $26 <= uzone pointer
-
-	sw      $29,    (UZ_SP*4)($26) 	    # save user stack to uzone
-	lw      $29,    (UZ_KSP*4)($26)     # load kernel stack from uzone
-
-	ori     $27,    $0,	  0xF	        # MMU old value: assumed ON
-	sw      $27,    (UZ_MODE*4)($26)    # save MMU MODE to uzone
-
-	j	    unified_mode
-	or      $27,    $0,	  $26           # $27 <= uzone
+
+    mfc2    $26,    $1                  # $26 <= c2_mode
+	mtc2    $27,    $1			        # set MMU OFF
+    move    $27,    $29                 # $27 <= user stack pointer
+	mfc0    $29,    $4,   2             # get pointer on thread descriptor from c0_th
+    addi    $29,    $29,    CONFIG_THREAD_DESC_SIZE
+    addi    $29,    $29,    -8          # $29 <= kernel stack pointer
+    j       unified_mode
+    nop
 
 #---------------------------------------------------------------------------------------	
-# this code is executed when the core is in kernel mode:
-# - we use an uzone dynamically allocated in kernel stack.
-# - we set the MMU off, set the MMU data_paddr extension to local_cxy,
-#   and save the CP2_MODE and CP2_DEXT to uzone.
-# - we save the kernel stack pointer to uzone and load the new kernel stack pointer
-# - we store the uzone pointer in $27
+# This code is executed when the core is already in kernel mode:
+# - save current c2_mode in $26.
+# - set MMU OFF.
+# - save current kernel stack pointer in $27.
 
 kernel_mode:
-	mfc2	$26,    $24
-	andi	$26,    $26,  CXY_MASK      # $26 <= CP2_DEXT 
-
-	mfc0    $27,    $15,  1
-	andi	$27,	$27,  GID_MASK	    # $27 <= core_gid (4/4/2 format)	
-
-	srl	    $27,    $27,  LID_WIDTH	    # $27 <= local_cxy
-	mtc2	$27,    $24			        # set local_cxy to CP2_DEXT
-
-    # use $26 to save both CP2_MODE (4 bits) and CP2_DEXT (8 bits) values
-
-	mfc2    $27,    $1
-	andi	$27,	$27,  MMU_MODE_MASK	# $27 <= CP2_MODE
-	sll	    $27,    $27,  CXY_WIDTH	    # $27 <= 0x00000M00
-	or	    $26,    $26,  $27           # $26 <= 0x00000MXY 
-
-	ori     $27,    $0,	  0x3
+
+    mfc2    $26,    $1                  # $26 <= c2_mode
 	mtc2    $27,    $1			        # set MMU OFF
-
-	# save old SP, CP2_MODE and CP2_DEXT in uzone allocated in kernel stack
-
-	addiu   $27,    $29,  -(SAVE_SIZE)	# allocate an uzone in stack (use $27 as KSP)
-	sw      $29,	(UZ_SP*4)($27)	    # save old KSP in this uzone
-
-	srl     $29,    $26,  CXY_WIDTH 
-	sw      $29,    (UZ_MODE*4)($27)    # save CP2_MODE in this uzone
-
-	andi	$26,    $26,  CXY_MASK	
-	sw      $26,    (UZ_DEXT*4)($27)    # save CP2_DEXT in this uzone 
-
-	or      $29,    $27,	$0          # load new kernel stack pointer
-
-#--------------------------------------------------------------------------------------	
-# This code is executed in both modes, and saves the core context,
-# with the two following assumptions:
-# - $27 contains the pointer on uzone to save the core registers
-# - $29 contains the kernel stack pointer
-
-unified_mode:	
-	sw      $1,	    (UZ_AT*4)($27)
-	sw      $2,     (UZ_V0*4)($27)
-	sw      $3,     (UZ_V1*4)($27)
-	sw      $4,     (UZ_A0*4)($27)
-	sw      $5,     (UZ_A1*4)($27)
-	sw      $6,     (UZ_A2*4)($27)
-	sw      $7,     (UZ_A3*4)($27)
-	sw      $8,     (UZ_T0*4)($27)
-	sw      $9,     (UZ_T1*4)($27)
-	sw      $10,	(UZ_T2*4)($27)
-	sw      $11,	(UZ_T3*4)($27)
-	sw      $12,	(UZ_T4*4)($27)
-	sw      $13,	(UZ_T5*4)($27)
-	sw      $14,	(UZ_T6*4)($27)
-	sw      $15,	(UZ_T7*4)($27)
-	sw      $16,	(UZ_S0*4)($27)
-	sw      $17,	(UZ_S1*4)($27)
-	sw	    $18,	(UZ_S2*4)($27)
-	sw	    $19,	(UZ_S3*4)($27)
-	sw	    $20,	(UZ_S4*4)($27)
-	sw	    $21,	(UZ_S5*4)($27)
-	sw	    $22,	(UZ_S6*4)($27)
-	sw	    $23,	(UZ_S7*4)($27)
-	sw      $24,	(UZ_T8*4)($27)
-	sw      $25,	(UZ_T9*4)($27)
-	sw	    $28,	(UZ_GP*4)($27)
-	sw	    $30,	(UZ_S8*4)($27)
-	sw	    $31,	(UZ_RA*4)($27)
+    move    $27,    $29                 # $27 <= current kernel stack pointer
+
+#---------------------------------------------------------------------------------------	
+# This code is executed in both modes (user or kernel):
+# The assumptions are:
+# - c2_mode contains the MMU OFF value.
+# - $26 contains the previous c2_mode value.
+# - $27 contains the previous sp value (can be usp or ksp).
+# - $29 contains the kernel stack pointer.
+# We execute the following actions:
+# - allocate an uzone in kernel stack, incrementing $29
+# - save relevant registers to uzone.
+# - set the SR in kernel mode: IRQ disabled, clear exl.
+# - signal the kernel entry.
+
+unified_mode:
+
+	addiu   $29,    $29,  -(UZ_REGS*4)	# allocate uzone in kernel stack 
+
+	sw      $1,	    (UZ_AT*4)($29)
+	sw      $2,     (UZ_V0*4)($29)
+	sw      $3,     (UZ_V1*4)($29)
+	sw      $4,     (UZ_A0*4)($29)
+	sw      $5,     (UZ_A1*4)($29)
+	sw      $6,     (UZ_A2*4)($29)
+	sw      $7,     (UZ_A3*4)($29)
+	sw      $8,     (UZ_T0*4)($29)
+	sw      $9,     (UZ_T1*4)($29)
+	sw      $10,	(UZ_T2*4)($29)
+	sw      $11,	(UZ_T3*4)($29)
+	sw      $12,	(UZ_T4*4)($29)
+	sw      $13,	(UZ_T5*4)($29)
+	sw      $14,	(UZ_T6*4)($29)
+	sw      $15,	(UZ_T7*4)($29)
+	sw      $16,	(UZ_S0*4)($29)
+	sw      $17,	(UZ_S1*4)($29)
+	sw	    $18,	(UZ_S2*4)($29)
+	sw	    $19,	(UZ_S3*4)($29)
+	sw	    $20,	(UZ_S4*4)($29)
+	sw	    $21,	(UZ_S5*4)($29)
+	sw	    $22,	(UZ_S6*4)($29)
+	sw	    $23,	(UZ_S7*4)($29)
+	sw      $24,	(UZ_T8*4)($29)
+	sw      $25,	(UZ_T9*4)($29)
+
+	sw      $26,    (UZ_MODE*4)($29)    # save c2_mode
+	sw      $27,	(UZ_SP*4)($29)	    # save sp
+
+	sw	    $28,	(UZ_GP*4)($29)
+	sw	    $30,	(UZ_S8*4)($29)
+	sw	    $31,	(UZ_RA*4)($29)
 
 	mfc0	$16,    $14
-	sw      $16,	(UZ_EPC*4)($27)	    # Save EPC
+	sw      $16,	(UZ_EPC*4)($29)	    # save c0_epc
 	mflo	$14
-	sw      $14,	(UZ_LO*4)($27)      # save LO
+	sw      $14,	(UZ_LO*4)($29)      # save lo
 	mfhi	$15 
-	sw      $15,	(UZ_HI*4)($27)		# save HI
+	sw      $15,	(UZ_HI*4)($29)		# save hi
 	mfc0	$18,	$12 
-	sw	    $18,	(UZ_SR*4)($27)		# Save SR
+	sw	    $18,	(UZ_SR*4)($29)		# save c0_sr
 	mfc0    $17,    $13
-	sw      $17,	(UZ_CR*4)($27)		# Save CR
-
-    # put SR in kernel mode, IRQ disabled, clear exl
+	sw      $17,	(UZ_CR*4)($29)		# save c0_cr
+	mfc2    $26,    $1
+
 	srl	    $3,     $18,  5
 	sll     $3,	    $3,   5	
-	mtc0	$3,	    $12			        # Set new SR
+	mtc0	$3,	    $12			        # set new sr
 
 	# signal that core enters kernel
 	la      $1,     cluster_core_kernel_enter
-	jal	    $1
+	jalr    $1
     nop
 
 #---------------------------------------------------------------------------------------
 # This code call the relevant Interrupt / Exception / Syscall handler,
-# depending on XCODE in CP0_CR, with the two following assumptions:
-# - $27 contains the pointer on uzone containing to save the core registers
-# - $29 contains the kernel stack pointer
+# depending on XCODE in CP0_CR.
+# assumption: $29 contains the kernel stack pointer, that is the uzone base.
 # The three handlers take the same two arguments: thread pointer and uzone pointer.
-# The uzone pointer is saved in $19 to be used by kernel_exit.
+# The uzone pointer is saved in $19 to be used by kentry_exit.
 
 	mfc0    $17,    $13                 # $17 <= CR
@@ -208,6 +205,6 @@
 
 	mfc0    $4,     $4,   2             # $4 <= thread pointer (first arg)
-	or	    $5,	    $0,   $27		    # $5 <= uzone pointer (second arg)
-	or	    $19,    $0,	  $27	        # $19 <= &uzone (for kernel_exit)
+	or	    $5,	    $0,   $29		    # $5 <= uzone pointer (second arg)
+	or	    $19,    $0,	  $29	        # $19 <= &uzone (for kentry_exit)
 
 	ori	    $8,     $0,   0x20          # $8 <= cause syscall
@@ -222,5 +219,5 @@
 	addiu	$29,	$29,  -8	        # hal_do_exception has 2 args
 	addiu	$29,	$29,  8
-	j       kernel_exit                 # jump to kernel_exit
+	j       kentry_exit                 # jump to kentry_exit
     nop
 
@@ -230,5 +227,5 @@
 	addiu	$29,	$29,  -8            # hal_do_syscall has 2 args
 	addiu	$29,	$29,  8
-	j	    kernel_exit                 # jump to kernel_exit
+	j	    kentry_exit                 # jump to kentry_exit
 	nop 
 	
@@ -243,5 +240,5 @@
 # The pointer on uzone is supposed to be stored in $19
 # -----------------------------------------------------------------------------------
-kernel_exit:
+kentry_exit:
 
 	# signal that core exit kernel
@@ -250,5 +247,5 @@
     nop
 
-	# restore context from uzone
+	# restore registers from uzone
 	or	    $27,    $0,	$19             # $27 <= &uzone
 
@@ -296,17 +293,18 @@
 	lw	    $31,	(UZ_RA*4)($27)
 
-	lw	    $26,    (UZ_DEXT*4)($27)
-	mtc2	$26,    $24			        # restore CP2_DEXT from uzone
-
 	lw	    $26,    (UZ_MODE*4)($27)    
     mtc2    $26,    $1                  # restore CP2_MODE from uzone
 
+# -----------------------------------------------------------------------------------
+# eret function
+# -----------------------------------------------------------------------------------
+
+hal_kentry_eret:
 	nop
     eret
 
-    .end kernel_enter
     .set reorder
     .set at
 
-#-------------------------------------------------------------------------------
-
+#------------------------------------------------------------------------------------
+
Index: trunk/hal/tsar_mips32/core/hal_kentry.h
===================================================================
--- trunk/hal/tsar_mips32/core/hal_kentry.h	(revision 401)
+++ trunk/hal/tsar_mips32/core/hal_kentry.h	(revision 406)
@@ -24,6 +24,82 @@
 #define _HAL_KENTRY_H_
 
+//////////////////////////////////////////////////////////////////////////////////////////
+// This file defines the MIPS32 specific mnemonics to access the "uzone", that is
+// a fixed size array of 32 bits integers, used by the kentry function to save/restore 
+// the MIPS32 CPU registers, at each exception / interruption / syscall.
+// It also defines several initial values for the SR register.
+//
+// This file is included in the hal_kentry.S, hal_syscall.c, hal_exception.c,
+// and hal_context.c files.
+//////////////////////////////////////////////////////////////////////////////////////////
 
-#define CPU_IN_KERNEL 1
+
+/****************************************************************************************
+ * This structure defines the cpu_uzone for TSAR MIPS32, as well as the
+ *  mnemonics used by the hal_kentry assembly code.
+ ***************************************************************************************/
+
+#define      UZ_MODE         0    /* c2_mode */             
+#define      UZ_AT           1
+#define      UZ_V0           2
+#define      UZ_V1           3
+#define      UZ_A0           4 
+#define      UZ_A1           5
+#define      UZ_A2           6
+#define      UZ_A3           7
+#define      UZ_T0           8
+#define      UZ_T1           9
+#define      UZ_T2           10
+#define      UZ_T3           11
+#define      UZ_T4           12
+#define      UZ_T5           13
+#define      UZ_T6           14
+#define      UZ_T7           15
+#define      UZ_T8           16
+#define      UZ_T9           17
+#define      UZ_S0           18
+#define      UZ_S1           19
+#define      UZ_S2           20
+#define      UZ_S3           21
+#define      UZ_S4           22
+#define      UZ_S5           23
+#define      UZ_S6           24
+#define      UZ_S7           25
+#define      UZ_S8           26
+#define      UZ_GP           27
+#define      UZ_RA           28
+#define      UZ_EPC          29   /* c0_epc */
+#define      UZ_CR           30   /* c0_cr */
+#define      UZ_SP           31
+#define      UZ_SR           32   /* c0_sr */
+#define      UZ_LO           33
+#define      UZ_HI           34
+
+#define      UZ_REGS         35
+
+/*************************************************************************************
+ * The hal_kentry_enter() function is the unique kernel entry point in case of 
+ * exception, interrupt, or syscall for the TSAR_MIPS32 architecture.  
+ *
+ * When we enter the kernel, we test the status register:
+ * - If the core is in user mode, we desactivate the MMU, and we save
+ *   the core context in the uzone of the calling thread descriptor.
+ * - If the core is already in kernel mode (in case of interrupt), 
+ *   we save the context in the kernel stack.
+ * - In both cases, we increment the cores_in_kernel variable,
+ *   and we call the relevant exception/interrupt/syscall handler
+ *
+ * When we exit the kernel after handler execution:
+ * - we restore the core context from the uzone and return to user space,
+ *   calling the hal_kentry_eret()
+ ************************************************************************************/
+void hal_kentry_enter();
+
+/*************************************************************************************
+ * The hal_kentry_eret() function contains only the assembly "eret" instruction,
+ * that and the EXL bit in the c0_sr register, and jump to the address 
+ * contained in the c0_epc register. 
+ * ************************************************************************************/
+void hal_kentry_eret();
 
 #endif	/* _HAL_KENTRY_H_ */
Index: trunk/hal/tsar_mips32/core/hal_special.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_special.c	(revision 401)
+++ trunk/hal/tsar_mips32/core/hal_special.c	(revision 406)
@@ -240,7 +240,8 @@
       "mfc2   %2,    $12        \n"
       "mfc2   %3,    $14        \n"
-      : "=&r"(mmu_ins_excp_code),
-        "=&r"(mmu_ins_bad_vaddr),
-        "=&r"(mmu_dat_excp_code),
-        "=&r"(mmu_dat_bad_vaddr) );
-}
+      : "=&r"(*mmu_ins_excp_code),
+        "=&r"(*mmu_ins_bad_vaddr),
+        "=&r"(*mmu_dat_excp_code),
+        "=&r"(*mmu_dat_bad_vaddr) );
+}
+
Index: trunk/hal/tsar_mips32/core/hal_switch.S
===================================================================
--- trunk/hal/tsar_mips32/core/hal_switch.S	(revision 401)
+++ trunk/hal/tsar_mips32/core/hal_switch.S	(revision 406)
@@ -30,11 +30,11 @@
 #---------------------------------------------------------------------------------
 
-    .section   .text , "ax" , @progbits
+    .section   .switch , "ax" , @progbits
 
-    .ent   hal_do_switch
-    .globl hal_do_switch
+    .ent     hal_do_switch
+    .global  hal_do_switch
 
-    .set   noat 
-    .set   noreorder 
+    .set     noat 
+    .set     noreorder 
 
 hal_do_switch:
@@ -84,13 +84,13 @@
     sw      $31,  31*4($26)         
 
+    mfc0    $27,  $12               
+	sw      $27,  34*4($26)           /* save c0_sr to slot 34 */
+    mfc0    $27,  $4, 2             
+	sw      $27,  35*4($26)           /* save c0_th to slot 35 */
+
 	mfc2    $27,  $0                
 	sw      $27,  32*4($26)           /* save c2_ptpr to slot 32 */
 	mfc2    $27,  $1                
 	sw      $27,  33*4($26)           /* save c2_mode to slot 33 */
-
-    mfc0    $27,  $12               
-	sw      $27,  34*4($26)           /* save c0_sr to slot 34 */
-    mfc0    $27,  $4, 2             
-	sw      $27,  35*4($26)           /* save c0_th to slot 35 */
 
     sync                            
@@ -140,13 +140,15 @@
 	lw      $31,  31*4($26)         
 
-	lw      $27,  32*4($26)         
+	lw      $27,  32*4($26)            /* $27 <= c2_ptpr */
 	mtc2    $27,  $0                   /* restore c2_ptpr from slot 32 */
-	lw      $27,  33*4($26)         
+
+	lw      $27,  35*4($26)            /* $27 <= c0_th */      
+    mtc0	$27,  $4, 2                /* restore c0_th from slot 35 */
+
+	lw      $27,  33*4($26)            /* $27 <= c2_mode */
+	lw      $26,  34*4($26)            /* $26 <= c0_sr */
+
 	mtc2    $27,  $1                   /* restore c2_mode from slot 33 */
-
-	lw      $27,  34*4($26)         
-    mtc0	$27,  $12                  /* restore c0_sr from slot 34 */
-	lw      $27,  35*4($26)         
-    mtc0	$27,  $4, 2                /* restore co_th from slot 35 */
+    mtc0	$26,  $12                  /* restore c0_sr from slot 34 */
 
     jr      $31                        /* return to caller */
Index: trunk/hal/tsar_mips32/core/hal_syscall.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_syscall.c	(revision 401)
+++ trunk/hal/tsar_mips32/core/hal_syscall.c	(revision 406)
@@ -26,5 +26,5 @@
 #include <do_syscall.h>
 #include <thread.h>
-#include <mips32_uzone.h>
+#include <hal_kentry.h>
 
 
Index: trunk/hal/tsar_mips32/core/mips32_context.h
===================================================================
--- trunk/hal/tsar_mips32/core/mips32_context.h	(revision 401)
+++ 	(revision )
@@ -1,79 +1,0 @@
-/*
- * mips32_context.h - structures used to save MIPS32 CPU & FPU registers
- * 
- * Author  Alain Greiner    (2016)
- *
- * Copyright (c) UPMC Sorbonne Universites
- * 
- * This file is part of ALMOS-MKH.
- *
- * ALMOS-MKH is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2.0 of the License.
- *
- * ALMOS-MKH is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with ALMOS-MKH; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef  _MIPS32_CONTEXT_H_
-#define  _MIPS32_CONTEXT_H_
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// This file defines the MIPPS32specific structures, that are used to save /restore
-// MIPS32 CPU and FPU registers at context swich.
-//////////////////////////////////////////////////////////////////////////////////////////
-
-/****************************************************************************************
- * This defines the "mips32_cpu_context_t" structure, containing general registers,
- * as well as CP0 or CP2 registers.
- * These registers are saved/restored at each context switch.
- * It can be accessed through a void* pointer contained in the thread descriptor.
- *
- * WARNING : update the hal_cpu_context_save() and hal_cpu_context_restore()
- *           functions when modifying this structure. 
- ***************************************************************************************/
-
-typedef struct mips_32_cpu_context_s
-{
-	uint32_t s0_16;      // slot 0
-	uint32_t s1_17;      // slot 1
-	uint32_t s2_18;      // slot 2
-	uint32_t s3_19;      // slot 3
-	uint32_t s4_20;      // slot 4
-	uint32_t s5_21;      // slot 5
-	uint32_t s6_22;      // slot 6
-	uint32_t s7_23;      // slot 7
-	uint32_t sp_29;      // slot 8
-	uint32_t fp_30;      // slot 9
-	uint32_t ra_31;      // slot 10
-	uint32_t c0_sr;      // slot 11
-	uint32_t c0_th;      // slot 12
-	uint32_t c2_ptpr;    // slot 13
-	uint32_t c2_mode;    // slot 14
-} 
-mips32_cpu_context_t;
-
-/****************************************************************************************
- * This defines the "mips32_fpu_context_t" structure, containing all FPU registers
- * (i.e. CP1 coprocessor registers).
- * These registers are saved/restored each time the FPU is allocated to a thread.
- * It can be accessed through a void* pointer contained in the thread descriptor.
- *
- * WARNING : update the hal_fpu_context_save() and hal_fpu_context_restore()
- *           functions when modifying this structure. 
- ***************************************************************************************/
-
-typedef struct mips32_fpu_context_s
-{
-	uint32_t   fpu_regs[32];     
-}
-mips32_fpu_context_t;
-
-
-#endif	/* _MIPS32_CONTEXT_H_ */
Index: trunk/hal/tsar_mips32/core/mips32_uzone.h
===================================================================
--- trunk/hal/tsar_mips32/core/mips32_uzone.h	(revision 401)
+++ 	(revision )
@@ -1,90 +1,0 @@
-/*
- * mips32_uzone.h - structures used to save MIPS32 core registers
- * 
- * Author  Alain Greiner    (2016)
- *
- * Copyright (c) UPMC Sorbonne Universites
- * 
- * This file is part of ALMOS-MKH.
- *
- * ALMOS-MKH is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2.0 of the License.
- *
- * ALMOS-MKH is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with ALMOS-MKH; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef  _MIPS32_UZONE_REGS_H_
-#define  _MIPS32_UZONE_REGS_H_
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// This file defines the MIPS32 specific mnemonics to access the "uzone", that is
-// a fixed size array of 32 bits integers, used by the kentry function to save/restore 
-// the MIPS32 CPU registers, at each exception / interruption / syscall.
-// It also defines several initial values for the SR register.
-//
-// This file is included in the TSAR_MIPS32 specific hal_kentry.S, hal_syscall.c,
-// hal_exception.c, and hal_interrupt.c files.
-//////////////////////////////////////////////////////////////////////////////////////////
-
-/****************************************************************************************
- * This defines  SR values for TSAR-MIPS32 
- ***************************************************************************************/
-
-#define SR_USR_MODE       0xFC11
-#define SR_USR_MODE_FPU   0x2000FC11
-#define SR_SYS_MODE       0xFC00
-
-/****************************************************************************************
- * This defines the "uzone" mnemonics and size.
- ***************************************************************************************/
-
-#define      UZ_KSP          0    // kernel stack pointer
-#define      UZ_AT           1
-#define      UZ_V0           2
-#define      UZ_V1           3
-#define      UZ_A0           4 
-#define      UZ_A1           5
-#define      UZ_A2           6
-#define      UZ_A3           7
-#define      UZ_T0           8
-#define      UZ_T1           9
-#define      UZ_T2           10
-#define      UZ_T3           11
-#define      UZ_T4           12
-#define      UZ_T5           13
-#define      UZ_T6           14
-#define      UZ_T7           15
-#define      UZ_T8           16
-#define      UZ_T9           17
-#define      UZ_S0           18
-#define      UZ_S1           19
-#define      UZ_S2           20
-#define      UZ_S3           21
-#define      UZ_S4           22
-#define      UZ_S5           23
-#define      UZ_S6           24
-#define      UZ_S7           25
-#define      UZ_S8           26
-#define      UZ_GP           27
-#define      UZ_RA           28
-#define      UZ_EPC          29   // CP0 Exception Program Counter
-#define      UZ_CR           30   // CP0 Cause register
-#define      UZ_SP           31   // user stack pointer
-#define      UZ_SR           32   // CP0 Status Register
-#define      UZ_LO           33
-#define      UZ_HI           34
-#define      UZ_DEXT	     35   // CP2 data paddr extension
-#define      UZ_MODE	     36   // CP2 MMU mode
-
-#define      CPU_REGS_NR     37
-
-
-#endif	/* _MIPS32_UZONE_REGS_H_ */
