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

Last change on this file since 619 was 619, checked in by alain, 3 years ago

1) Fix a bug in KSH : after the "load" command,

the [ksh] prompt is now printed after completion
of the loaded application.

2) Fix a bug in vmm_handle_cow() : the copy-on-write

use now a hal_remote_memcpy() to replicate the page content.


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