Index: trunk/hal/tsar_mips32/core/hal_exception.c
===================================================================
--- trunk/hal/tsar_mips32/core/hal_exception.c	(revision 406)
+++ trunk/hal/tsar_mips32/core/hal_exception.c	(revision 407)
@@ -58,13 +58,26 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
-// This enum defines the mask valuesi for an MMU exception code reported by the mips32.
+// This enum defines the mask values for an MMU exception code reported by the mips32.
 //////////////////////////////////////////////////////////////////////////////////////////
 
 typedef enum
 {
-    MMU_EXCP_PAGE_UNMAPPED   = 0x0003,
-    MMU_EXCP_USER_PRIVILEGE  = 0x0004,
-    MMU_EXCP_USER_WRITE      = 0x0008,
-    MMU_EXCP_USER_EXEC       = 0x1010,
+    MMU_WRITE_PT1_UNMAPPED        = 0x0001,
+    MMU_WRITE_PT2_UNMAPPED        = 0x0002,
+    MMU_WRITE_PRIVILEGE_VIOLATION = 0x0004,
+    MMU_WRITE_ACCESS_VIOLATION    = 0x0008,
+    MMU_WRITE_UNDEFINED_XTN       = 0x0020,
+    MMU_WRITE_PT1_ILLEGAL_ACCESS  = 0x0040,
+    MMU_WRITE_PT2_ILLEGAL_ACCESS  = 0x0080,
+    MMU_WRITE_DATA_ILLEGAL_ACCESS = 0x0100,
+
+    MMU_READ_PT1_UNMAPPED         = 0x1001,
+    MMU_READ_PT2_UNMAPPED         = 0x1002,
+    MMU_READ_PRIVILEGE_VIOLATION  = 0x1004,
+    MMU_READ_EXEC_VIOLATION       = 0x1010,
+    MMU_READ_UNDEFINED_XTN        = 0x1020,
+    MMU_READ_PT1_ILLEGAL_ACCESS   = 0x1040,
+    MMU_READ_PT2_ILLEGAL_ACCESS   = 0x1080,
+    MMU_READ_DATA_ILLEGAL_ACCESS  = 0x1100,
 }
 mmu_exception_subtype_t;
@@ -148,7 +161,4 @@
     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
 	hal_get_mmu_excp( &mmu_ins_excp_code,
@@ -157,8 +167,4 @@
 	                  &mmu_dat_bad_vaddr );
 
-    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 )
@@ -173,65 +179,92 @@
     }
 
-    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 );
-
-        // try to map the unmapped PTE
-        error = vmm_handle_page_fault( process, 
-                                       bad_vaddr >> CONFIG_PPM_PAGE_SHIFT );  // vpn
-        // disable IRQs
-        // hal_disable_irq( NULL );
-
-        if( error )     // not enough memory
-        {
-            printk("\n[ERROR] in %s for thread %x : cannot map vaddr = %x\n",
-               __FUNCTION__ , this->trdid , bad_vaddr );
-
-		    return EXCP_USER_ERROR;
-        } 
-        else            // page fault successfully handled
-        {
-            excp_dmsg("\n[DMSG] %s : page fault handled / bad_vaddr = %x / excp_code = %x\n",
-		             __FUNCTION__ , bad_vaddr , excp_code );
+ excp_dmsg("\n[DBG] %s : core[%x,%d] / is_ins %d / code %x / vaddr %x\n",
+__FUNCTION__ , local_cxy , this->core->lid , is_ins, excp_code, bad_vaddr );
+
+   // analyse exception code
+    switch( excp_code )
+    {
+        case MMU_WRITE_PT1_UNMAPPED:      // non fatal
+        case MMU_WRITE_PT2_UNMAPPED:
+        case MMU_READ_PT1_UNMAPPED:
+        case MMU_READ_PT2_UNMAPPED:
+        {
+            // try to map the unmapped PTE
+            error = vmm_handle_page_fault( process, 
+                                           bad_vaddr >> CONFIG_PPM_PAGE_SHIFT );  // vpn
+            if( error )   
+            {
+                printk("\n[ERROR] in %s for thread %x : cannot map vaddr = %x\n",
+                __FUNCTION__ , this->trdid , bad_vaddr );
+
+		        return EXCP_USER_ERROR;
+            } 
+            else            // page fault successfull
+            {
+
+excp_dmsg("\n[DBG] %s : core[%x,%d] / page-fault handled for vaddr = %x\n",
+__FUNCTION__ , local_cxy , this->core->lid , bad_vaddr );
   
-            return EXCP_NON_FATAL;
-        }
-    }
-    else if( excp_code & MMU_EXCP_USER_PRIVILEGE )
-    {
-        printk("\n[ERROR] in %s for thread %x : user access to kernel vseg at vaddr = %x\n",
-               __FUNCTION__ , this->trdid , bad_vaddr );
-
-        return EXCP_USER_ERROR;
-    }
-    else if( excp_code & MMU_EXCP_USER_EXEC )
-    {
-        printk("\n[ERROR] in %s for thread %x : access to non-exec vseg at vaddr = %x\n",
-               __FUNCTION__ , this->trdid , bad_vaddr );
-
-        return EXCP_USER_ERROR;
-    }
-    else if( excp_code & MMU_EXCP_USER_WRITE )
-    {
-        printk("\n[ERROR] in %s for thread %x : write to non-writable vseg at vaddr = %x\n",
-               __FUNCTION__ , this->trdid , bad_vaddr );
-
-        return EXCP_USER_ERROR;
-    }
-    else  // 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 );
-
-        return EXCP_KERNEL_PANIC;
-    }
-  
+                return EXCP_NON_FATAL;
+            }
+        }
+        case MMU_WRITE_PRIVILEGE_VIOLATION:  // illegal access user error
+        case MMU_READ_PRIVILEGE_VIOLATION:
+        {
+            printk("\n[ERROR] in %s for thread %x : illegal user access to vaddr = %x\n",
+            __FUNCTION__ , this->trdid , bad_vaddr );
+
+            return EXCP_USER_ERROR;
+        }
+        case MMU_WRITE_ACCESS_VIOLATION:     // user error or Copy-on-Write
+        {
+            // access page table to get GPT_COW flag
+            bool_t cow = hal_gpt_pte_is_cow( &(process->vmm.gpt),
+                                             bad_vaddr >> CONFIG_PPM_PAGE_SHIFT );  // vpn
+
+            if( cow )                        // Copy-on-Write 
+            {
+                // try to allocate and copy the page
+                error = vmm_copy_on_write( process,
+                                           bad_vaddr >> CONFIG_PPM_PAGE_SHIFT );  // vpn
+                if( error )
+                {
+                    printk("\n[ERROR] in %s for thread %x : cannot cow vaddr = %x\n",
+                    __FUNCTION__ , this->trdid , bad_vaddr );
+
+		            return EXCP_USER_ERROR;
+                }
+                else         // Copy on write successfull
+                {
+
+excp_dmsg("\n[DBG] %s : core[%x,%d] / copy-on-write handled for vaddr = %x\n",
+__FUNCTION__ , local_cxy , this->core->lid , bad_vaddr );
+
+                    return EXCP_NON_FATAL;
+                } 
+            }
+            else                             // non writable user error
+            {
+                printk("\n[ERROR] in %s for thread %x : write to non-writable vaddr = %x\n",
+                __FUNCTION__ , this->trdid , bad_vaddr );
+
+                return EXCP_USER_ERROR;
+            }
+        }
+        case MMU_READ_EXEC_VIOLATION:        // user error
+        {
+            printk("\n[ERROR] in %s for thread %x : read to non-executable vaddr = %x\n",
+            __FUNCTION__ , this->trdid , bad_vaddr );
+
+            return EXCP_USER_ERROR;
+        }
+        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 );
+
+            return EXCP_KERNEL_PANIC;
+        }
+    }  
 } // end hal_mmu_exception()
 
@@ -242,13 +275,15 @@
 // @ this     : pointer on faulty thread descriptor.
 // @ regs_tbl : pointer on register array.
-// @ return always EXCP_NON_FATAL
+// @ error    : EXCP_USER_ERROR or EXCP_KERNEL_PANIC
 //////////////////////////////////////////////////////////////////////////////////////////
 static void hal_exception_dump( thread_t * this,
-                                reg_t    * regs_tbl )
+                                reg_t    * regs_tbl,
+                                error_t    error )
 {
     uint32_t  save_sr;
+    core_t  * core = this->core;
 
     // get pointers on TXT0 chdev
-    xptr_t    txt0_xp  = chdev_dir.txt[0];
+    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
     cxy_t     txt0_cxy = GET_CXY( txt0_xp );
     chdev_t * txt0_ptr = GET_PTR( txt0_xp );
@@ -260,10 +295,14 @@
     remote_spinlock_lock_busy( lock_xp , &save_sr );
 
-    if( this->type == THREAD_USER )
-    nolock_printk("\n================= USER ERROR / cycle %d ====================\n",
-           hal_time_stamp() );
+    if( error == EXCP_USER_ERROR )
+    {
+        nolock_printk("\n========= USER ERROR / core[%x,%d] / cycle %d ==============\n",
+        local_cxy , core->lid , (uint32_t)hal_get_cycles() );
+    }
     else
-    nolock_printk("\n================= KERNEL PANIC / cycle %d ==================\n",
-           hal_time_stamp() );
+    {
+        nolock_printk("\n======= KERNEL PANIC / core[%x,%d] / cycle %d ==============\n",
+        local_cxy , core->lid , (uint32_t)hal_get_cycles() );
+    }
 
 	nolock_printk("  thread type = %s / trdid = %x / pid %x / core[%x,%d]\n"
@@ -272,9 +311,9 @@
            this->core->lid, this->local_locks, this->remote_locks, this->blocked );
 
-	nolock_printk("CR    %X  EPC   %X  SR    %X  SP     %X\n",
-		   regs_tbl[UZ_CR], regs_tbl[UZ_EPC], regs_tbl[UZ_SR], regs_tbl[UZ_SP]);
-
-    nolock_printk("at_1  %X  v0_2  %X  v1_3  %X  a0_4   %X  a1_5   %X\n",
-   	       regs_tbl[UZ_AT], regs_tbl[UZ_V0], regs_tbl[UZ_V1], regs_tbl[UZ_A0], regs_tbl[UZ_A1]);
+	nolock_printk("cp0_cr %X   cp0_epc %X   cp0_sr %X   cp2_mode %X\n",
+		   regs_tbl[UZ_CR], regs_tbl[UZ_EPC], regs_tbl[UZ_SR], regs_tbl[UZ_MODE]);
+
+    nolock_printk("at_01 %X  v0_2  %X  v1_3  %X  a0_4   %X  a1_5   %X\n",
+   	       regs_tbl[UZ_AT],regs_tbl[UZ_V0],regs_tbl[UZ_V1],regs_tbl[UZ_A0],regs_tbl[UZ_A1]);
 
     nolock_printk("a2_6  %X  a3_7  %X  t0_8  %X  t1_9   %X  t2_10  %X\n",
@@ -284,12 +323,12 @@
 		   regs_tbl[UZ_T3],regs_tbl[UZ_T4],regs_tbl[UZ_T5],regs_tbl[UZ_T6],regs_tbl[UZ_T7]);
 
-    nolock_printk("t8_24 %X  t9_25 %X  gp_28 %X  c0_hi  %X  c0_lo  %X\n",
-		   regs_tbl[UZ_T8],regs_tbl[UZ_T9],regs_tbl[UZ_GP],regs_tbl[UZ_HI],regs_tbl[UZ_LO]);
-
     nolock_printk("s0_16 %X  s1_17 %X  s2_18 %X  s3_19  %X  s4_20  %X\n",
 		   regs_tbl[UZ_S0],regs_tbl[UZ_S1],regs_tbl[UZ_S2],regs_tbl[UZ_S3],regs_tbl[UZ_S4]);
   
-    nolock_printk("s5_21 %X  s6_22 %X  s7_23 %X  s8_30  %X  ra_31  %X\n",
-	       regs_tbl[UZ_S5],regs_tbl[UZ_S6],regs_tbl[UZ_S7],regs_tbl[UZ_S8],regs_tbl[UZ_RA]);
+    nolock_printk("s5_21 %X  s6_22 %X  s7_23 %X  s8_24  %X  ra_25  %X\n",
+	       regs_tbl[UZ_S5],regs_tbl[UZ_S6],regs_tbl[UZ_S7],regs_tbl[UZ_T8],regs_tbl[UZ_T9]);
+
+    nolock_printk("gp_28 %X  sp_29 %X  S8_30 %X  ra_31  %X\n",
+		   regs_tbl[UZ_GP],regs_tbl[UZ_SP],regs_tbl[UZ_S8],regs_tbl[UZ_RA]);
 
     // release the lock
@@ -311,6 +350,7 @@
 	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() );
+excp_dmsg("\n[DBG] %s : core[%x,%d] / thread %x in process %x / xcode %x / cycle %d\n",
+__FUNCTION__, local_cxy, this->core->lid, this->trdid, 
+this->process->pid, excCode, (uint32_t)hal_get_cycle() );
 
 	switch(excCode)
@@ -355,15 +395,18 @@
 	if( error == EXCP_USER_ERROR )          //  user error => kill user process
 	{
-        hal_exception_dump( this , regs_tbl );
-        sys_kill( this->process->pid , SIGKILL );
+        hal_exception_dump( this , regs_tbl , error );
+
+        // FIXME : replace this loop by sys_kill()
+        while( 1 ) asm volatile ("nop");
+        // sys_kill( this->process->pid , SIGKILL );
 	}
     else if( error == EXCP_KERNEL_PANIC )   // kernel error => kernel panic
     {
-        hal_exception_dump( this , regs_tbl );
+        hal_exception_dump( this , regs_tbl , error );
         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() );
+excp_dmsg("\n[DBG] %s : core[%x,%d] exit / thread %x in process %x / cycle %d\n",
+__FUNCTION__, local_cxy, this->core->lid, this->trdid, this->process->pid, hal_time_stamp() );
 
 }  // end hal_do_exception()
