Ignore:
Timestamp:
Dec 5, 2017, 4:20:07 PM (6 years ago)
Author:
alain
Message:

Fix several bugs in the fork() syscall.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/hal/tsar_mips32/core/hal_context.c

    r407 r408  
    3636
    3737/////////////////////////////////////////////////////////////////////////////////////////
    38 //       Define various SR values for TSAR-MIPS32
    39 /////////////////////////////////////////////////////////////////////////////////////////
    40 
    41 #define SR_USR_MODE       0x0000FC13
    42 #define SR_USR_MODE_FPU   0x2000FC13
    43 #define SR_SYS_MODE       0x0000FC00
     38//       Define various SR initialisation values for TSAR-MIPS32
     39/////////////////////////////////////////////////////////////////////////////////////////
     40
     41#define SR_USR_MODE       0x0000FF13
     42#define SR_USR_MODE_FPU   0x2000FF13
     43#define SR_SYS_MODE       0x0000FF00
    4444
    4545/////////////////////////////////////////////////////////////////////////////////////////
     
    191191}  // end hal_cpu_context_create()
    192192
     193////////////////////////////////////////////
     194void hal_cpu_context_fork( xptr_t child_xp )
     195{
     196    // allocate a local CPU context in kernel stack
     197    // It is initialized from local parent context
     198    // and from child specific values, and is copied in
     199    // in the remote child context using a remote_memcpy()
     200    hal_cpu_context_t  context;
     201
     202    // get local parent thread local pointer
     203    thread_t * parent_ptr = CURRENT_THREAD;
     204
     205    // get remote child thread cluster and local pointer
     206    cxy_t      child_cxy = GET_CXY( child_xp );
     207    thread_t * child_ptr = (thread_t *)GET_PTR( child_xp );
     208
     209    // get remote child cpu_context local pointer
     210    char * child_context_ptr = hal_remote_lpt( XPTR(child_cxy , &child_ptr->cpu_context) );
     211
     212    // get local pointer on remote child process
     213    process_t * process = (process_t *)hal_remote_lpt( XPTR(child_cxy , &child_ptr->process) );
     214
     215    // get ppn of remote child process page table
     216    uint32_t    pt_ppn = hal_remote_lw( XPTR(child_cxy , &process->vmm.gpt.ppn) );
     217
     218    // save CPU registers in local CPU context
     219    hal_do_cpu_save( &context );
     220
     221    // From this point, both parent and child threads execute the following code.
     222    // They can be distinguished by the CURRENT_THREAD value, and child will only
     223    // execute it when it is unblocked by parent, after return to sys_fork().
     224    // - parent thread copies user stack, and patch sp_29 / c0_th / C0_sr / c2_ptpr
     225    // - child thread does nothing
     226
     227    thread_t * current = CURRENT_THREAD;
     228
     229    if( current == parent_ptr )    // current == parent thread
     230    {
     231        // get parent and child stack pointers
     232        char * parent_sp = (char *)context.sp_29;
     233        char * child_sp  = (char *)((intptr_t)parent_sp +
     234                                    (intptr_t)child_ptr -
     235                                    (intptr_t)parent_ptr );
     236 
     237        // patch kernel_stack pointer, current thread, and status slots
     238        context.sp_29   = (uint32_t)child_sp;
     239        context.c0_th   = (uint32_t)child_ptr;
     240        context.c0_sr   = SR_SYS_MODE;
     241        context.c2_ptpr = pt_ppn >> 1;
     242
     243        // copy local context to remote child context)
     244        hal_remote_memcpy( XPTR( child_cxy , child_context_ptr ),
     245                           XPTR( local_cxy  , &context ) ,
     246                           sizeof( hal_cpu_context_t ) );
     247
     248        // copy kernel stack content from local parent thread to remote child thread
     249        uint32_t size = (uint32_t)parent_ptr + CONFIG_THREAD_DESC_SIZE - (uint32_t)parent_sp;
     250        hal_remote_memcpy( XPTR( child_cxy , child_sp ),
     251                           XPTR( local_cxy , parent_sp ),
     252                           size );
     253    }
     254    else                           // current == child thread
     255    {
     256        assert( (current == child_ptr) , __FUNCTION__ , "current = %x / child = %x\n");
     257    }
     258
     259}  // end hal_cpu_context_fork()
     260
    193261/////////////////////////////////////////////////
    194 void hal_cpu_context_display( thread_t * thread )
    195 {
    196     hal_cpu_context_t * ctx = (hal_cpu_context_t *)thread->cpu_context;
    197 
     262void hal_cpu_context_display( xptr_t  thread_xp )
     263{
     264    hal_cpu_context_t * ctx;
     265
     266    // get thread cluster and local pointer
     267    cxy_t      cxy = GET_CXY( thread_xp );
     268    thread_t * ptr = (thread_t *)GET_PTR( thread_xp );
     269
     270    // get context pointer
     271    ctx = (hal_cpu_context_t *)hal_remote_lpt( XPTR( cxy , &ptr->cpu_context ) );
     272
     273    // get relevant context slots values
     274    uint32_t sp_29   = hal_remote_lw( XPTR( cxy , &ctx->sp_29   ) );
     275    uint32_t ra_31   = hal_remote_lw( XPTR( cxy , &ctx->ra_31   ) );
     276    uint32_t c0_sr   = hal_remote_lw( XPTR( cxy , &ctx->c0_sr   ) );
     277    uint32_t c0_epc  = hal_remote_lw( XPTR( cxy , &ctx->c0_epc  ) );
     278    uint32_t c0_th   = hal_remote_lw( XPTR( cxy , &ctx->c0_th   ) );
     279    uint32_t c2_ptpr = hal_remote_lw( XPTR( cxy , &ctx->c2_ptpr ) );
     280    uint32_t c2_mode = hal_remote_lw( XPTR( cxy , &ctx->c2_mode ) );
     281   
    198282    printk("\n***** CPU context for thread %x in process %x / cycle %d\n"
    199            " gp_28   = %X    sp_29   = %X    ra_31   = %X\n"
     283           " sp_29   = %X    ra_31   = %X\n"
    200284           " c0_sr   = %X    c0_epc  = %X    c0_th = %X\n"
    201285           " c2_ptpr = %X    c2_mode = %X\n",
    202            thread->trdid, thread->process->pid, hal_time_stamp(),
    203            ctx->gp_28   , ctx->sp_29   , ctx->ra_31,
    204            ctx->c0_sr   , ctx->c0_epc  , ctx->c0_th,
    205            ctx->c2_ptpr , ctx->c2_mode );
     286           ptr->trdid, ptr->process->pid, hal_time_stamp(),
     287           sp_29   , ra_31,
     288           c0_sr   , c0_epc  , c0_th,
     289           c2_ptpr , c2_mode );
    206290
    207291}  // end hal_cpu_context_display()
     
    270354
    271355//////////////////////////////////////////////
    272 void hal_fpu_context_save( thread_t * thread )
    273 {
    274     uint32_t ctx = (uint32_t)thread->fpu_context;
     356void hal_fpu_context_save( xptr_t  thread_xp )
     357{
     358    // allocate a local FPU context in kernel stack
     359    hal_fpu_context_t  context;
     360
     361    // get remote child cluster and local pointer
     362    cxy_t      thread_cxy = GET_CXY( thread_xp );
     363    thread_t * thread_ptr = (thread_t *)GET_PTR( thread_xp );
    275364
    276365    asm volatile(
     
    309398    "swc1    $f31,  31*4(%0)  \n"   
    310399    ".set reorder             \n"
    311     : : "r"(ctx) );
    312 
    313 }  // end hal_cpu_context_save()
     400    : : "r"(&context) );
     401
     402    // copy local context to remote child context)
     403    hal_remote_memcpy( XPTR( thread_cxy , &thread_ptr->fpu_context ),
     404                       XPTR( local_cxy  , &context ) ,
     405                       sizeof( hal_fpu_context_t ) );
     406
     407}  // end hal_fpu_context_save()
    314408
    315409/////////////////////////////////////////////////
Note: See TracChangeset for help on using the changeset viewer.