Index: trunk/hal/tsar_mips32/core/hal_exception.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_exception.c	(revision 420)
+++ trunk/hal/tsar_mips32/core/hal_exception.c	(revision 425)
@@ -284,6 +284,6 @@
         default:                             // this is a kernel error => panic    
         {
-            printk("\n[PANIC] in %s for thread %x : kernel exception = %x / vaddr = %x\n",
-            __FUNCTION__ , this->trdid , excp_code , bad_vaddr );
+            assert( false , __FUNCTION__ , "thread %x / excp_code = %x / vaddr = %x\n",
+            this->trdid , excp_code , bad_vaddr );
 
             return EXCP_KERNEL_PANIC;
@@ -297,5 +297,5 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 // @ this     : pointer on faulty thread descriptor.
-// @ uzone : pointer on register array.
+// @ uzone    : pointer on register array.
 // @ error    : EXCP_USER_ERROR or EXCP_KERNEL_PANIC
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -372,5 +372,5 @@
     // get pointer on faulty thread uzone
     this  = CURRENT_THREAD;
-    uzone = (uint32_t *)CURRENT_THREAD->uzone;
+    uzone = (uint32_t *)CURRENT_THREAD->uzone_current;
 
     // get 4 bits XCODE from CP0_CR register
@@ -424,12 +424,11 @@
         hal_exception_dump( this , uzone , error );
 
-        // FIXME : replace this loop by sys_kill()
-        while( 1 ) asm volatile ("nop");
-        // sys_kill( this->process->pid , SIGKILL );
+        sys_kill( this->process->pid , SIGKILL );
 	}
     else if( error == EXCP_KERNEL_PANIC )   // kernel error => kernel panic
     {
         hal_exception_dump( this , uzone , error );
-        panic( "for thread %x in process %x on core [%x,%d]",
+
+        assert( false , __FUNCTION__ , "thread %x in process %x on core [%x,%d]",
         this->trdid , this->process->pid , local_cxy , this->core->lid );
     }
Index: trunk/hal/tsar_mips32/core/hal_kentry.S
===================================================================
--- trunk/hal/tsar_mips32/core/hal_kentry.S	(revision 420)
+++ trunk/hal/tsar_mips32/core/hal_kentry.S	(revision 425)
@@ -119,5 +119,5 @@
 #------------------------------------------------------------------------------------
 # This code is executed when the core is already in kernel mode,
-# after a syscall, to handle an interrupt.
+# after a syscall, to handle an interrupt, or to handle a non-fatal exception.
 # - save current c2_mode in $26.
 # - set MMU OFF.
@@ -286,13 +286,27 @@
     
 #------------------------------------------------------------------------------------
-# This code calls the relevant Interrupt / Exception / Syscall handler,
-# depending on XCODE in CP0_CR.
-# In case of syscall or exception, it set the "uzone" pointer in thread descriptor,
-# that is used by the hal_do_syscall() & hal_do_exception() functions.
-# WARNING: This "uzone" pointer is NOT modified in case of interrupt,
-# because syscalls can be interrupted, and we want preserve this pointer.
-
+# This code handle the uzone pointers stack, and calls the relevant 
+# Interrupt / Exception / Syscall handler, depending on XCODE in CP0_CR.
+# Both the hal_do_syscall() and the hal_do_exception() functions use
+# the values saved in the "uzone", but a syscall can be interrupted 
+# by an interrupt, or by a non-fatal exception. Therefore, we need 
+# to handle a two-slots "stack of uzones", implemented in the kernel stack,
+# using the two "current_uzone" and "previous_uzone" pointers in thread descriptor. 
+# - at kernel_entry, we copy the "current_uzone" pointer to the "previous_uzone"
+#   slot, and copy the "$29" stack pointer to the "current_uzone" slot.
+# - at kernel_exit, we simply restore the "previous_uzone" value to the
+#   "current_uzone" slot.
+# For a syscall, the hal_do_syscall() function increment the uzone[EPC]
+# slot and set the return value in the uzone[V0] slot before returning.
+
+    # update "current_uzone" and "previous_uzone" pointers
+	mfc0    $4,     $4,   2             # $4 <= pointer on thread desc
+    lw      $5,     8($4)               # $5 <= current uzone pointer trom thread
+    sw      $29,    8($4)               # current uzone pointer <= $29
+    sw      $5,    12($4)               # previous uzone pointer <= current
+
+    # analyse XCODE to call relevant handler
 	mfc0    $17,    $13                 # $17 <= CR
-	andi    $17,    $17,   0x3F         # $17 <= XCODE
+	andi    $17,    $17,  0x3F          # $17 <= XCODE
 	ori	    $8,     $0,   0x20
     beq	    $8,	    $17,  cause_sys     # go to syscall handler
@@ -302,6 +316,5 @@
 
 cause_excp:
-	mfc0    $4,     $4,   2             # get pointer on thread desc
-    sw      $29,    8($4)               # update uzone pointer in thread desc
+
 	jal     hal_do_exception            # call exception handler
 	nop
@@ -310,6 +323,5 @@
 
 cause_sys:
-	mfc0    $4,     $4,   2             # get pointer on thread desc
-    sw      $29,    8($4)               # update uzone pointer in thread desc
+
 	jal 	hal_do_syscall              # call syscall handler                 
     nop
@@ -318,4 +330,5 @@
 	
 cause_int:
+
 	jal     hal_do_interrupt            # call interrupt handler
     nop
@@ -330,4 +343,9 @@
 
 kentry_exit:
+
+    # restore "current_uzone" pointer
+	mfc0    $4,      $4,   2            # $4 <= pointer on thread desc
+    lw      $5,   12($4)                # $5 <= previous uzone pointer from thread
+    sw      $5,    8($4)                # current uzone pointer <= previous
 
 #----------------------
Index: trunk/hal/tsar_mips32/core/hal_special.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_special.c	(revision 420)
+++ trunk/hal/tsar_mips32/core/hal_special.c	(revision 425)
@@ -206,5 +206,5 @@
 void hal_core_sleep()
 {
-	asm volatile ("wait");
+	while( 1 ) asm volatile ("nop");
 }
 
Index: trunk/hal/tsar_mips32/core/hal_syscall.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_syscall.c	(revision 420)
+++ trunk/hal/tsar_mips32/core/hal_syscall.c	(revision 425)
@@ -29,9 +29,4 @@
 #include <hal_kentry.h>
 
-// @@@
-// __attribute__((section(".kdata"))) uint32_t * enter_uzone;
-// __attribute__((section(".kdata"))) uint32_t * exit_uzone;
-// @@@
-
 /////////////////////
 void hal_do_syscall()
@@ -51,5 +46,8 @@
     // get pointer on enter_thread uzone
     this        = CURRENT_THREAD;
-    enter_uzone = (uint32_t *)this->uzone;
+    enter_uzone = (uint32_t *)this->uzone_current;
+
+//printk("\n@@@ enter %s : thread = %x / enter_uzone = %x / EPC = %x\n", 
+//__FUNCTION__ , this , enter_uzone , enter_uzone[UZ_EPC] );
 
     // get syscall arguments from uzone
@@ -68,13 +66,13 @@
                          service_num );
 
-    // get pointer on exit_thread uzone,
+    // get pointer on exit_thread uzone, because
     // exit_thread can be different from enter_thread
     this       = CURRENT_THREAD;
-    exit_uzone = (uint32_t *)this->uzone;
+    exit_uzone = (uint32_t *)this->uzone_current;
 
-// printk("\n@@@ %s exit : enter_uzone = %x / exit_uzone = %x\n",
-// __FUNCTION__ , enter_uzone , exit_uzone );
+//printk("\n@@@ exit %s : thread = %x / exit_uzone = %x / EPC = %x\n", 
+//__FUNCTION__ , this , exit_uzone , exit_uzone[UZ_EPC] );
 
-    // set syscall return value to uzone 
+    // set return value to uzone 
 	exit_uzone[UZ_V0] = retval;
 
Index: trunk/hal/tsar_mips32/core/hal_user.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_user.c	(revision 420)
+++ trunk/hal/tsar_mips32/core/hal_user.c	(revision 425)
@@ -30,18 +30,17 @@
                              int arg3 )
 {
-    register int reg_num_and_ret __asm__("v0") = service_num;
-    register int reg_a0          __asm__("a0") = arg0;
-    register int reg_a1          __asm__("a1") = arg1;
-    register int reg_a2          __asm__("a2") = arg2;
-    register int reg_a3          __asm__("a3") = arg3;
+    register int num_and_ret __asm__("v0") = service_num;
+    register int a0          __asm__("a0") = arg0;
+    register int a1          __asm__("a1") = arg1;
+    register int a2          __asm__("a2") = arg2;
+    register int a3          __asm__("a3") = arg3;
 
-    __asm__ volatile(
+    asm volatile(
             "syscall"
-            : "+r" (reg_num_and_ret),
-              "+r" (reg_a0),             
-              "+r" (reg_a1),
-              "+r" (reg_a2),
-              "+r" (reg_a3)
-            : 
+            : "+r" (num_and_ret)
+            : "r" (a0),             
+              "r" (a1),
+              "r" (a2),
+              "r" (a3)
             : "memory",
               "at",
@@ -60,5 +59,5 @@
                );
 
-    return (volatile int)reg_num_and_ret;
+    return (volatile int)num_and_ret;
 }
 
Index: trunk/hal/tsar_mips32/core/hal_uspace.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_uspace.c	(revision 420)
+++ trunk/hal/tsar_mips32/core/hal_uspace.c	(revision 425)
@@ -29,8 +29,11 @@
 #include <hal_irqmask.h>
 
+#include <printk.h>
+#include <thread.h>
+
 ///////////////////////////////////////////
 void hal_copy_from_uspace( void     * k_dst,
                            void     * u_src,
-                           uint32_t   size )
+                           uint32_t   size )  
 {
     uint32_t save_sr;
@@ -136,5 +139,4 @@
 {
     uint32_t save_sr;
-
     uint32_t src = (uint32_t)u_src;
     uint32_t dst = (uint32_t)k_dst;
@@ -142,5 +144,5 @@
     hal_disable_irq( &save_sr );
 
-    // loop on characters while ( (character != NUL) and (count < size ) 
+    // loop on characters while ( (character != NUL) and (count < size ) )
     asm volatile(
         ".set noreorder             \n"
@@ -148,12 +150,12 @@
         "move   $12,   %1           \n"   /* $12 <= u_src                   */
         "move   $13,   %2           \n"   /* $13 <= k_dst                   */
-        "mfc2   $15,   $1           \n"   /* $15 <= MMU_MODE                */
-        "ori    $14,   $15,  0x7    \n"   /* $14 <= mode DTLB on            */
+        "mfc2   $15,   $1           \n"   /* $15 <= mode DTLB and ITLB off  */
+        "ori    $14,   $15,  0x4    \n"   /* $14 <= mode DTLB on            */
         "1:                         \n"
         "mtc2   $14,   $1			\n"   /* MMU_MODE <= DTLB ON            */
         "lb     $10,   0($12)       \n"   /* read char from user space      */
-        "mtc2   $15,   $1			\n"   /* restore MMU_MODE               */
+        "mtc2   $15,   $1			\n"   /* restore DTLB and ITLB off      */
 	    "sb	    $10,   0($13)       \n"   /* store char to kernel space     */
-        "beq    $13,   $0,   2f     \n"   /* exit if char = 0               */
+        "beq    $10,   $0,   2f     \n"   /* exit if char = 0               */
         "addi   $11,   $11, -1      \n"   /* decrement count                */
         "addi   $12,   $12,  1      \n"   /* increment u_src pointer        */
@@ -178,5 +180,4 @@
 {
     uint32_t save_sr;
-
     uint32_t src = (uint32_t)k_src;
     uint32_t dst = (uint32_t)u_dst;
@@ -190,12 +191,12 @@
         "move   $12,   %1           \n"   /* $12 <= k_src                   */
         "move   $13,   %2           \n"   /* $13 <= u_dst                   */
-        "mfc2   $15,   $1           \n"   /* $15 <= MMU_MODE                */
-        "ori    $14,   $15,  0x7    \n"   /* $14 <= mode DTLB on            */
+        "mfc2   $15,   $1           \n"   /* $15 <= mode DTLB and ITLB off  */
+        "ori    $14,   $15,  0x4    \n"   /* $14 <= mode DTLB on            */
         "1:                         \n"
         "lb     $10,   0($12)       \n"   /* read char from kernel space    */
         "mtc2   $14,   $1			\n"   /* MMU_MODE <= DTLB ON            */
 	    "sb	    $10,   0($13)       \n"   /* store char to user space       */
-        "mtc2   $15,   $1			\n"   /* restore MMU_MODE               */
-        "beq    $13,   $0,   2f     \n"   /* exit if char == 0              */
+        "mtc2   $15,   $1			\n"   /* restore DTLB and ITLB off      */
+        "beq    $10,   $0,   2f     \n"   /* exit if char == 0              */
         "addi   $11,   $11, -1      \n"   /* decrement count                */
         "addi   $12,   $12,  1      \n"   /* increment k_src pointer        */
@@ -219,6 +220,5 @@
     uint32_t save_sr;
     uint32_t count = 0;
-
-    uint32_t str = (uint32_t)u_str;
+    uint32_t str   = (uint32_t)u_str;
 
     hal_disable_irq( &save_sr ); 
@@ -226,14 +226,14 @@
         asm volatile(
         ".set noreorder             \n"
-        "ori    $13,   %1,   0      \n"   /* $13 <= str                     */
-        "mfc2   $15,   $1           \n"   /* $15 <= MMU_MODE                */
-        "ori    $14,   $15,  0x7    \n"   /* $14 <= mode DTLB on            */
-        "mtc2   $14,   $1			\n"   /* MMU_MODE <= DTLB ON            */
+        "move   $13,   %1           \n"   /* $13 <= str                     */
+        "mfc2   $15,   $1           \n"   /* $15 <= DTLB and ITLB off       */
+        "ori    $14,   $15,  0x4    \n"   /* $14 <= mode DTLB on            */
         "1:                         \n"
+        "mtc2   $14,   $1			\n"   /* set DTLB on                    */
         "lb	    $12,   0($13)       \n"   /* read char from user space      */
+        "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                */
-        "mtc2   $15,   $1			\n"   /* restore MMU_MODE               */
         ".set reorder               \n"
         : "+r"(count) 
