source: trunk/hal/tsar_mips32/core/hal_exception.c @ 527

Last change on this file since 527 was 527, checked in by viala@…, 6 years ago

Rewrite if-then-else return function into switch case.

For safety reason and performance:

1) Safety: GCC complain with a warning if you forgot an enum variant.
2) code-gen just outperform naive if-then-else.

File size: 19.5 KB
RevLine 
[16]1/*
2 * hal_exception.c - implementation of exception handler for TSAR-MIPS32.
3 *
4 * Author   Alain Greiner (2016, 2017)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
[457]24#include <hal_kernel_types.h>
[16]25#include <hal_irqmask.h>
[406]26#include <hal_special.h>
[16]27#include <hal_exception.h>
28#include <thread.h>
29#include <printk.h>
[380]30#include <chdev.h>
[16]31#include <vmm.h>
32#include <errno.h>
33#include <scheduler.h>
34#include <core.h>
35#include <syscalls.h>
[440]36#include <shared_syscalls.h>
[16]37#include <remote_spinlock.h>
[406]38#include <hal_kentry.h>
[16]39
[505]40#include <hal_exception.h>
[380]41
[16]42//////////////////////////////////////////////////////////////////////////////////////////
43//  Extern global variables
44//////////////////////////////////////////////////////////////////////////////////////////
45
[380]46extern   chdev_directory_t    chdev_dir;  // allocated in the kernel_init.c file.
[16]47
48//////////////////////////////////////////////////////////////////////////////////////////
[381]49// This enum defines the global exception types after analysis by the exception handler.
50//////////////////////////////////////////////////////////////////////////////////////////
51
52typedef enum
53{
54    EXCP_NON_FATAL,
55    EXCP_USER_ERROR,
56    EXCP_KERNEL_PANIC,
57}
58exception_handling_type_t;
59
60//////////////////////////////////////////////////////////////////////////////////////////
[407]61// This enum defines the mask values for an MMU exception code reported by the mips32.
[381]62//////////////////////////////////////////////////////////////////////////////////////////
63
64typedef enum
65{
[407]66    MMU_WRITE_PT1_UNMAPPED        = 0x0001,
67    MMU_WRITE_PT2_UNMAPPED        = 0x0002,
68    MMU_WRITE_PRIVILEGE_VIOLATION = 0x0004,
69    MMU_WRITE_ACCESS_VIOLATION    = 0x0008,
70    MMU_WRITE_UNDEFINED_XTN       = 0x0020,
71    MMU_WRITE_PT1_ILLEGAL_ACCESS  = 0x0040,
72    MMU_WRITE_PT2_ILLEGAL_ACCESS  = 0x0080,
73    MMU_WRITE_DATA_ILLEGAL_ACCESS = 0x0100,
74
75    MMU_READ_PT1_UNMAPPED         = 0x1001,
76    MMU_READ_PT2_UNMAPPED         = 0x1002,
77    MMU_READ_PRIVILEGE_VIOLATION  = 0x1004,
78    MMU_READ_EXEC_VIOLATION       = 0x1010,
79    MMU_READ_UNDEFINED_XTN        = 0x1020,
80    MMU_READ_PT1_ILLEGAL_ACCESS   = 0x1040,
81    MMU_READ_PT2_ILLEGAL_ACCESS   = 0x1080,
82    MMU_READ_DATA_ILLEGAL_ACCESS  = 0x1100,
[381]83}
84mmu_exception_subtype_t;
85
86//////////////////////////////////////////////////////////////////////////////////////////
[16]87// This enum defines the relevant values for XCODE field in mips32 CP0_CR register.
88//////////////////////////////////////////////////////////////////////////////////////////
89
90typedef enum
91{
[296]92    XCODE_ADEL = 0x4,        // Illegal address for data load
93    XCODE_ADES = 0x5,        // Illegal address for data store
94    XCODE_IBE  = 0x6,        // Instruction MMU exception       (can be NON-FATAL)
95    XCODE_DBE  = 0x7,        // Data MMU exception              (can be NON-FATAL)
96    XCODE_RI   = 0xA,        // Reserved instruction exception
97    XCODE_CPU  = 0xB,        // Coprocessor unusable exception  (can be NON-FATAl)
98    XCODE_OVR  = 0xC,        // Arithmetic Overflow exception
[16]99}
100xcode_values_t;
101
[409]102/////////////////////////////////////////////
103char * hal_mmu_exception_str( uint32_t code )
[408]104{
[527]105  switch (code) {
106    case (MMU_WRITE_PT1_UNMAPPED):        return "WRITE_PT1_UNMAPPED";
107    case (MMU_WRITE_PT2_UNMAPPED):        return "WRITE_PT2_UNMAPPED";
108    case (MMU_WRITE_PRIVILEGE_VIOLATION): return "WRITE_PRIVILEGE_VIOLATION";
109    case (MMU_WRITE_ACCESS_VIOLATION):    return "WRITE_ACCESS_VIOLATION";
110    case (MMU_WRITE_UNDEFINED_XTN):       return "WRITE_UNDEFINED_XTN";
111    case (MMU_WRITE_PT1_ILLEGAL_ACCESS):  return "WRITE_PT1_ILLEGAL_ACCESS";
112    case (MMU_WRITE_PT2_ILLEGAL_ACCESS):  return "WRITE_PT2_ILLEGAL_ACCESS";
113    case (MMU_WRITE_DATA_ILLEGAL_ACCESS): return "WRITE_DATA_ILLEGAL_ACCESS";
114    case (MMU_READ_PT1_UNMAPPED):         return "READ_PT1_UNMAPPED";
115    case (MMU_READ_PT2_UNMAPPED):         return "READ_PT2_UNMAPPED";
116    case (MMU_READ_PRIVILEGE_VIOLATION):  return "READ_PRIVILEGE_VIOLATION";
117    case (MMU_READ_EXEC_VIOLATION):       return "READ_EXEC_VIOLATION";
118    case (MMU_READ_UNDEFINED_XTN):        return "READ_UNDEFINED_XTN";
119    case (MMU_READ_PT1_ILLEGAL_ACCESS):   return "READ_PT1_ILLEGAL_ACCESS";
120    case (MMU_READ_PT2_ILLEGAL_ACCESS):   return "READ_PT2_ILLEGAL_ACCESS";
121    case (MMU_READ_DATA_ILLEGAL_ACCESS):  return "READ_DATA_ILLEGAL_ACCESS";
122    default:                              return "undefined";
123  }
[408]124}
125
[380]126//////////////////////////////////////////////////////////////////////////////////////////
[406]127// This function is called when a FPU Coprocessor Unavailable exception has been
[380]128// detected for the calling thread.
129// It enables the FPU, It saves the current FPU context in the current owner thread
130// descriptor if required, and restore the FPU context from the calling thread descriptor.
131//////////////////////////////////////////////////////////////////////////////////////////
132// @ this     : pointer on faulty thread descriptor.
133// @ return always EXCP_NON_FATAL
134//////////////////////////////////////////////////////////////////////////////////////////
[406]135error_t hal_fpu_exception( thread_t * this )
[380]136{
137        core_t   * core = this->core; 
138
[457]139    // enable FPU (in core SR) 
[380]140        hal_fpu_enable();
141
[457]142    // save FPU register values in current owner thread if required
[380]143        if( core->fpu_owner != NULL )
144    {
145        if( core->fpu_owner != this )
146            {
[457]147            // save the FPU registers to current owner thread context
[408]148                    hal_fpu_context_save( XPTR( local_cxy , core->fpu_owner ) );
[457]149
150            // restore FPU registers from requesting thread context
[469]151                hal_fpu_context_restore( this );
[457]152
153            // attach the FPU to the requesting thread
154                core->fpu_owner = this;
[380]155        }
156        }
[457]157    else
158    {
159        // restore FPU registers from requesting thread context
[469]160            hal_fpu_context_restore( this );
[380]161
[457]162        // attach the FPU to the requesting thread
163            core->fpu_owner = this;
164    }
[380]165
166        return EXCP_NON_FATAL;
167
168}  // end hal_fpu_exception()
169
170//////////////////////////////////////////////////////////////////////////////////////////
[437]171// This function is called when an MMU exception has been detected (IBE / DBE).
[380]172// It get the relevant exception arguments from the MMU.
173// It signal a fatal error in case of illegal access. In case of page unmapped
174// it checks that the faulty address belongs to a registered vseg. It update the local
175// vseg list from the reference cluster if required, and signal a fatal user error
176// in case of illegal virtual address. Finally, it updates the local page table from the
177// reference cluster.
178//////////////////////////////////////////////////////////////////////////////////////////
179// @ this     : pointer on faulty thread descriptor.
[440]180// @ excPC    :
[406]181// @ is_ins   : IBE if true / DBE if false.
[380]182// @ return EXCP_NON_FATAL / EXCP_USER_ERROR / EXCP_KERNEL_PANIC
183//////////////////////////////////////////////////////////////////////////////////////////
[406]184error_t hal_mmu_exception( thread_t * this,
[437]185                           uint32_t   excPC,
[406]186                           bool_t     is_ins ) 
[380]187{
[406]188        process_t      * process;
189    error_t          error;
[380]190
[406]191    uint32_t         mmu_ins_excp_code;
192    uint32_t         mmu_ins_bad_vaddr;
193    uint32_t         mmu_dat_excp_code;
194    uint32_t         mmu_dat_bad_vaddr;
[380]195
[406]196    uint32_t         bad_vaddr;
[380]197    uint32_t         excp_code;
198       
[406]199    process = this->process;
[380]200
201    // get relevant values from MMU
202        hal_get_mmu_excp( &mmu_ins_excp_code,
203                          &mmu_ins_bad_vaddr,
204                          &mmu_dat_excp_code, 
205                          &mmu_dat_bad_vaddr );
206
[406]207    // get exception code and faulty vaddr, depending on IBE/DBE
208    if( is_ins )
[380]209    {
210        excp_code = mmu_ins_excp_code;
211        bad_vaddr = mmu_ins_bad_vaddr;
212    }
[406]213    else 
[380]214    {
215        excp_code = mmu_dat_excp_code;
216        bad_vaddr = mmu_dat_bad_vaddr;
217    }
218
[438]219#if DEBUG_HAL_EXCEPTIONS
[432]220uint32_t cycle = (uint32_t)hal_get_cycles();
[438]221if( DEBUG_HAL_EXCEPTIONS < cycle )
[457]222printk("\n[DBG] %s : thread %x in process %x enter / is_ins %d / %s / vaddr %x / cycle %d\n",
[469]223__FUNCTION__, this->trdid, process->pid,
224is_ins, hal_mmu_exception_str(excp_code), bad_vaddr, cycle);
[432]225#endif
[408]226
[407]227   // analyse exception code
228    switch( excp_code )
[380]229    {
[407]230        case MMU_WRITE_PT1_UNMAPPED:      // non fatal
231        case MMU_WRITE_PT2_UNMAPPED:
232        case MMU_READ_PT1_UNMAPPED:
233        case MMU_READ_PT2_UNMAPPED:
234        {
235            // try to map the unmapped PTE
236            error = vmm_handle_page_fault( process, 
[440]237                                           bad_vaddr >> CONFIG_PPM_PAGE_SHIFT,  // vpn
238                                           false );                             // not a COW
[407]239            if( error )   
240            {
[469]241                printk("\n[USER ERROR] in %s for thread %x in process %x\n"
242                "   cannot map vaddr = %x / is_ins %d / epc %x\n",
243                __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
[406]244
[407]245                        return EXCP_USER_ERROR;
246            } 
247            else            // page fault successfull
248            {
[391]249
[438]250#if DEBUG_HAL_EXCEPTIONS
[432]251cycle = (uint32_t)hal_get_cycles();
[438]252if( DEBUG_HAL_EXCEPTIONS < cycle )
[457]253printk("\n[DBG] %s : thread %x in process %x exit / page-fault handled for vaddr = %x\n",
254__FUNCTION__, this->trdid, process->pid, bad_vaddr );
[432]255#endif
[407]256 
257                return EXCP_NON_FATAL;
258            }
259        }
260        case MMU_WRITE_PRIVILEGE_VIOLATION:  // illegal access user error
261        case MMU_READ_PRIVILEGE_VIOLATION:
[380]262        {
[469]263            printk("\n[USER ERROR] in %s for thread %x in process %x\n"
264            "   illegal user access to vaddr = %x / is_ins %d / epc %x\n",
265            __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
[380]266
[407]267            return EXCP_USER_ERROR;
268        }
[408]269        case MMU_WRITE_ACCESS_VIOLATION:     // user error, or Copy-on-Write
[380]270        {
[407]271            // access page table to get GPT_COW flag
272            bool_t cow = hal_gpt_pte_is_cow( &(process->vmm.gpt),
[408]273                                             bad_vaddr >> CONFIG_PPM_PAGE_SHIFT ); 
[380]274
[407]275            if( cow )                        // Copy-on-Write
276            {
277                // try to allocate and copy the page
[440]278                error = vmm_handle_page_fault( process,
279                                               bad_vaddr >> CONFIG_PPM_PAGE_SHIFT,  // vpn
280                                               true );                              // COW
[407]281                if( error )
282                {
[469]283                    printk("\n[USER ERROR] in %s for thread %x in process %x\n"
284                    "   cannot cow vaddr = %x / is_ins %d / epc %x\n",
285                    __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
[380]286
[407]287                            return EXCP_USER_ERROR;
288                }
289                else         // Copy on write successfull
290                {
[380]291
[438]292#if DEBUG_HAL_EXCEPTIONS
[432]293cycle = (uint32_t)hal_get_cycles();
[438]294if( DEBUG_HAL_EXCEPTIONS < cycle )
[457]295printk("\n[DBG] %s : thread %x in process %x exit / copy-on-write handled for vaddr = %x\n",
296__FUNCTION__, this->trdid, process->pid, bad_vaddr );
[432]297#endif
[380]298
[407]299                    return EXCP_NON_FATAL;
300                } 
301            }
302            else                             // non writable user error
303            {
[469]304                printk("\n[USER ERROR] in %s for thread %x in process %x\n"
305                "   non-writable vaddr = %x / is_ins %d / epc %x\n",
306                __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
[407]307
308                return EXCP_USER_ERROR;
309            }
310        }
311        case MMU_READ_EXEC_VIOLATION:        // user error
312        {
[469]313            printk("\n[USER_ERROR] in %s for thread %x in process %x\n"
314            "   non-executable vaddr = %x / is_ins %d / epc %x\n",
315            __FUNCTION__, this->trdid, this->process->pid, bad_vaddr, is_ins, excPC );
[407]316
317            return EXCP_USER_ERROR;
318        }
[469]319        default:                             // this is a kernel error   
[407]320        {
[469]321            printk("\n[KERNEL ERROR] in %s for thread %x in process %x\n"
322            "  epc %x / badvaddr %x / is_ins %d\n",
323            __FUNCTION__, this->trdid, this->process->pid, excPC, bad_vaddr, is_ins );
[407]324
325            return EXCP_KERNEL_PANIC;
326        }
327    } 
[380]328} // end hal_mmu_exception()
329
330//////////////////////////////////////////////////////////////////////////////////////////
331// This static function prints on the kernel terminal the saved context (core registers)
332// and the thread state of a faulty thread.
333//////////////////////////////////////////////////////////////////////////////////////////
334// @ this     : pointer on faulty thread descriptor.
[425]335// @ uzone    : pointer on register array.
[407]336// @ error    : EXCP_USER_ERROR or EXCP_KERNEL_PANIC
[380]337//////////////////////////////////////////////////////////////////////////////////////////
338static void hal_exception_dump( thread_t * this,
[408]339                                reg_t    * uzone,
[407]340                                error_t    error )
[380]341{
[408]342    uint32_t    save_sr;
343    core_t    * core    = this->core;
344    process_t * process = this->process;
[380]345
346    // get pointers on TXT0 chdev
[407]347    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
[380]348    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
349    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
350
351    // get extended pointer on remote TXT0 chdev lock
352    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
353
354    // get TXT0 lock in busy waiting mode
355    remote_spinlock_lock_busy( lock_xp , &save_sr );
356
[407]357    if( error == EXCP_USER_ERROR )
358    {
[408]359        nolock_printk("\n=== USER ERROR / trdid %x / pid %x / core[%x,%d] / cycle %d ===\n",
360        this->trdid, process->pid, local_cxy, core->lid , (uint32_t)hal_get_cycles() );
[407]361    }
[380]362    else
[407]363    {
[469]364        nolock_printk("\n=== KERNEL ERROR / trdid %x / pid %x / core[%x,%d] / cycle %d ===\n",
[408]365        this->trdid, process->pid, local_cxy, core->lid , (uint32_t)hal_get_cycles() );
[407]366    }
[380]367
[408]368        nolock_printk("local locks = %d / remote locks = %d / blocked_vector = %X\n\n",
369    this->local_locks, this->remote_locks, this->blocked );
[380]370
[408]371    nolock_printk("c0_cr   %X  c0_epc  %X  c0_sr  %X  c0_th  %X\n",
372    uzone[UZ_CR], uzone[UZ_EPC], uzone[UZ_SR], uzone[UZ_TH] );
[380]373
[408]374    nolock_printk("c2_mode %X  c2_ptpr %X\n",
375    uzone[UZ_MODE], uzone[UZ_PTPR] );
[380]376
[408]377    nolock_printk("at_01   %X  v0_2    %X  v1_3   %X  a0_4   %X  a1_5   %X\n",
378        uzone[UZ_AT], uzone[UZ_V0], uzone[UZ_V1], uzone[UZ_A0], uzone[UZ_A1] );
379
380    nolock_printk("a2_6    %X  a3_7    %X  t0_8   %X  t1_9   %X  t2_10  %X\n",
381        uzone[UZ_A2], uzone[UZ_A3], uzone[UZ_T0], uzone[UZ_T1], uzone[UZ_T2] );
[380]382 
[408]383    nolock_printk("t3_11   %X  t4_12   %X  t5_13  %X  t6_14  %X  t7_15  %X\n",
384        uzone[UZ_T3], uzone[UZ_T4], uzone[UZ_T5], uzone[UZ_T6], uzone[UZ_T7] );
[380]385
[408]386    nolock_printk("s0_16   %X  s1_17   %X  s2_18  %X  s3_19  %X  s4_20  %X\n",
387        uzone[UZ_S0], uzone[UZ_S1], uzone[UZ_S2], uzone[UZ_S3], uzone[UZ_S4] );
[380]388 
[408]389    nolock_printk("s5_21   %X  s6_22   %X  s7_23  %X  s8_24  %X  ra_25  %X\n",
390        uzone[UZ_S5], uzone[UZ_S6], uzone[UZ_S7], uzone[UZ_T8], uzone[UZ_T9] );
[380]391
[408]392    nolock_printk("gp_28   %X  sp_29   %X  S8_30  %X  ra_31  %X\n",
393        uzone[UZ_GP], uzone[UZ_SP], uzone[UZ_S8], uzone[UZ_RA] );
[407]394
[380]395    // release the lock
396    remote_spinlock_unlock_busy( lock_xp , save_sr );
397
398}  // end hal_exception_dump()
399
[408]400///////////////////////
[481]401void hal_do_exception( void )
[16]402{
[408]403    uint32_t   * uzone;
404    thread_t   * this;
405        error_t      error;
406        uint32_t     excCode;                  // 4 bits XCODE from CP0_CR
[437]407        uint32_t     excPC;                    // fauty instruction address
[16]408
[408]409    // get pointer on faulty thread uzone
410    this  = CURRENT_THREAD;
[425]411    uzone = (uint32_t *)CURRENT_THREAD->uzone_current;
[408]412
[437]413    // get XCODE and EPC from UZONE
[408]414        excCode        = (uzone[UZ_CR] >> 2) & 0xF;
[437]415    excPC          = uzone[UZ_EPC];
[16]416
[438]417#if DEBUG_HAL_EXCEPTIONS
[432]418uint32_t cycle = (uint32_t)hal_get_cycles();
[438]419if( DEBUG_HAL_EXCEPTIONS < cycle )
[457]420printk("\n[DBG] %s : thread %x in process %x enter / core[%x,%d] / epc %x / xcode %x / cycle %d\n",
421__FUNCTION__, this->trdid, this->process->pid, local_cxy, this->core->lid, excPC, excCode, cycle );
[432]422#endif
[406]423
[16]424        switch(excCode)
425        {
[469]426        case XCODE_DBE:     // Data Bus Error : can be non fatal if page fault
[406]427        {
[437]428                    error = hal_mmu_exception( this , excPC , false );  // data MMU exception
[406]429            break;
430        }
[469]431            case XCODE_IBE:     // Instruction Bus Error : can be non fatal if page fault
[16]432        {
[437]433                    error = hal_mmu_exception( this , excPC , true );   // ins MMU exception
[406]434                    break;
[16]435        }
[469]436            case XCODE_CPU:    // Coprocessor unavailable : can be non fatal if FPU
[16]437        {
[469]438            if( ((uzone[UZ_CR] >> 28) & 0x3) == 1 )             // FPU
[16]439            {
[469]440                error = hal_fpu_exception( this );
[16]441            }
[469]442            else                                                // undefined coprocessor
[16]443            {
[469]444                printk("\n[USER_ERROR] in %s for thread %x in process %x\n"
445                "   undefined coprocessor / epc %x\n",
446                __FUNCTION__, this->trdid, this->process->pid, excPC );
447
[16]448                        error = EXCP_USER_ERROR;
449            }
[406]450                    break;
[16]451        }
[469]452        case XCODE_OVR:    // Arithmetic Overflow : user fatal error
453        {
454            printk("\n[USER_ERROR] in %s for thread %x in process %x\n"
455            "   arithmetic overflow / epc %x\n",
456            __FUNCTION__, this->trdid, this->process->pid, excPC );
457
458                    error = EXCP_USER_ERROR;
459                break;
460        }
461        case XCODE_RI:     // Reserved Instruction : user fatal error
462        {
463            printk("\n[USER_ERROR] in %s for thread %x in process %x\n"
464            "   reserved instruction / epc %x\n",
465            __FUNCTION__, this->trdid, this->process->pid, excPC );
466
467                    error = EXCP_USER_ERROR;
468                break;
469        }
[380]470        case XCODE_ADEL:   // user fatal error
[16]471        {
[469]472            printk("\n[USER_ERROR] in %s for thread %x in process %x\n"
473            "   illegal data load address / epc %x\n",
474            __FUNCTION__, this->trdid, this->process->pid, excPC );
475
[16]476                    error = EXCP_USER_ERROR;
[406]477                break;
[16]478        }
[469]479        case XCODE_ADES:   //   user fatal error
480        {
481            printk("\n[USER_ERROR] in %s for thread %x in process %x\n"
482            "   illegal data store address / epc %x\n",
483            __FUNCTION__, this->trdid, this->process->pid, excPC );
484
485                    error = EXCP_USER_ERROR;
486                break;
487        }
[16]488        default:
489        {
[317]490                    error = EXCP_KERNEL_PANIC;
[16]491        }
492        }
493   
494    // analyse error code
[317]495        if( error == EXCP_USER_ERROR )          //  user error => kill user process
[16]496        {
[408]497        hal_exception_dump( this , uzone , error );
[407]498
[440]499        sys_exit( EXIT_FAILURE );
[16]500        }
501    else if( error == EXCP_KERNEL_PANIC )   // kernel error => kernel panic
502    {
[408]503        hal_exception_dump( this , uzone , error );
[425]504
[492]505        assert( false , "Exception raised kernel panic see information below.\n" );
[16]506    }
[406]507
[438]508#if DEBUG_HAL_EXCEPTIONS
[432]509cycle = (uint32_t)hal_get_cycles();
[438]510if( DEBUG_HAL_EXCEPTIONS < cycle )
[457]511printk("\n[DBG] %s : thread %x in process %x exit / core[%x,%d] / epc %x / xcode %x / cycle %d\n",
512__FUNCTION__, this->trdid, this->process->pid, local_cxy, this->core->lid, excPC, excCode, cycle );
[432]513#endif
[406]514
[16]515}  // end hal_do_exception()
516
517
Note: See TracBrowser for help on using the repository browser.