Ignore:
Timestamp:
Jun 18, 2017, 10:06:41 PM (7 years ago)
Author:
alain
Message:

Introduce syscalls.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kernel/syscalls/sys_exec.c

    r14 r23  
    11/*
    2  * sys_exec.c - Kernel function implementing the "exec" syscall
     2 * sys_exec.c - Kernel function implementing the "exec" system call.
    33 *
    4  * Authors    Mohamed Lamine Karaoui (2015)
    5  *            Alain Greiner          (2016)
     4 * Authors   Alain Greiner (2016,2017)
    65 *
    76 * Copyright (c) UPMC Sorbonne Universites
     
    2524#include <kernel_config.h>
    2625#include <hal_types.h>
     26#include <hal_uspace.h>
    2727#include <errno.h>
    2828#include <printk.h>
     
    5151
    5252    // get string length
    53         hal_strlen_from_uspace( pathname , &length );
    54         if( length > 255 )
    55     {
    56         printk(ERROR, "%s: elf file pathname larger than 255 bytes\n", __FUNCTION__ );
    57         return EINVAL;
    58     }
     53        length = hal_strlen_from_uspace( pathname );
     54
     55        if( length >= CONFIG_VFS_MAX_PATH_LENGTH ) return EINVAL;
    5956
    6057    // copy string to exec_info
     
    7572// The max number of strings is 1024 (for both args and envs). The numbers of pages
    7673// to store the (args) and (envs) strings are configuration parameters.
    77 ////////////////////////////////////////////////i//////////////////////////////////////
     74///////////////////////////////////////////////////////////////////////////////////////
    7875// @ exec_info : pointer on the exec_info structure.
    7976// @ is_args   : true if called for (args) / false if called for (envs).
     
    8885    uint32_t     found_null;  // NULL pointer found in array of pointers
    8986    uint32_t     length;      // string length
    90     uint32_t     strings;     // actual number of strings
    9187    kmem_req_t   req;         // kmem request
    9288    page_t     * page;        // page descriptor
    9389    uint32_t     order;       // ln2( number of pages to store strings )
    94     char      ** k_pointers;  // base of kernel buffer containing array of pointers
    95     char       * buf_ptr;     // pointer on first empty slot in kernel strings buffer
    96     char       * buf_base;    // base address of the kernel strings buffer
     90    char      ** k_pointers;  // base of kernel array of pointers
     91    char       * k_buf_ptr;   // pointer on first empty slot in kernel strings buffer
     92    char       * k_buf_base;  // base address of the kernel strings buffer
    9793
    9894    // compute ln2( number of pages for kernel strings buffer )
    99     if( is_args ) order = CONFIG_PROCESS_ARGS_ORDER;
    100     else          order = CONFIG_PROCESS_ENVS_ORDER;
     95    if( is_args ) order = bits_log2( CONFIG_VMM_ARGS_SIZE );
     96    else          order = bits_log2( CONFIG_VMM_ENVS_SIZE );
    10197
    10298        req.type   = KMEM_PAGE;
     
    106102    req.type   = 0;
    107103    page       = kmem_alloc( &req );
    108     if( page == NULL )
    109     {
    110         printk("ERROR in %s : cannot allocate memory for pointers\n", __FUNCTION__ );
    111         return ENOMEM;
    112     }
     104
     105    if( page == NULL ) return ENOMEM;
     106
    113107    k_pointers = ppm_page2base( page );
    114108   
     
    116110    req.type   = order;
    117111    page       = kmem_alloc( &req );
    118     if( page == NULL )
    119     {
    120         printk("ERROR in %s : cannot allocate memory for strings\n", __FUNCTION__ );
    121         return ENOMEM;
    122     }
    123     buf_base    = ppm_page2base( page );
     112
     113    if( page == NULL ) return ENOMEM;
     114
     115    k_buf_base = ppm_page2base( page );
    124116   
    125117    // copy the array of pointers to kernel buffer
     
    128120                          CONFIG_PPM_PAGE_SIZE );
    129121
    130     // scan local copy of array of pointers to copy the strings
     122    // scan kernel array of pointers to copy the strings
    131123    found_null = 0;
    132     buf_ptr    = buf_base;
     124    k_buf_ptr  = k_buf_base;
    133125    for( index = 0 ; index < 1024 ; index++ )
    134126    {
     
    140132
    141133        // compute string length
    142             hal_strlen_from_uspace( k_pointers[index] , &length );
     134            length = hal_strlen_from_uspace( k_pointers[index] );
    143135 
    144136        // copy the user string to kernel buffer
    145         hal_copy_from_uspace( k_strings,
    146                               k_pointers[index];
     137        hal_copy_from_uspace( k_buf_ptr,
     138                              k_pointers[index],
    147139                              length );
    148140
    149141        // update k_pointer[index] entry
    150         k_pointers[index] = buf_ptr;
     142        k_pointers[index] = k_buf_ptr;
    151143
    152144        // increment pointer on kernel strings buffer
    153         buf_ptr += (length + 1);
     145        k_buf_ptr += (length + 1);
    154146    }
    155147
     
    158150    {
    159151        exec_info->args_pointers  =  k_pointers;
    160         exec_info->args_buf_base  =  buf_base;
     152        exec_info->args_buf_base  =  k_buf_base;
    161153        exec_info->args_nr        =  index;
    162154    }
     
    164156    {
    165157        exec_info->envs_pointers  =  k_pointers;
    166         exec_info->envs_buf_base  =  buf_base;
    167         exec_info->envs_buf_free  =  buf_ptr;
     158        exec_info->envs_buf_base  =  k_buf_base;
     159        exec_info->envs_buf_free  =  k_buf_ptr;
    168160        exec_info->envs_nr        =  index;
    169161    }
    170162    else
    171163    {
    172         printk("ERROR in %s : number of strings larger than 1024\n", __FUNCTION__ );
    173164        return EINVAL;
    174165    }
     
    177168} // end process_exec_get_strings()
    178169
    179 /////////////////////////////////////////////////////////////////////////////////////////
    180 // This function is executed in a "client" cluster by a process whose PID can belong
    181 // to another "server" cluster (defined by the MSB bits of the calling process PID).
    182 // A new process descriptor, and the associated main thread descriptor must be created
    183 // in the "server" cluster, using directly the process_make_exec() function if local,
    184 // or the rpc_process_exec_client() function if server is remote.
    185170/////////////////////////////////////////////////////////////////////////////////////////
    186171// Implementation note:
     
    189174// It calls the static process_exec_get_path() and process_exec_get_strings() functions
    190175// to copy the .elf pathname, the main() arguments and the environment variables from
    191 // user buffers to the exec_info_t, and calls the static process_make_exec() function.
     176// user buffers to the exec_info_t structure, and call the process_make_exec() function.
    192177/////////////////////////////////////////////////////////////////////////////////////////
    193178int sys_exec( char  * filename,     // .elf file pathname
    194               char ** argv,         // process arguments
    195               char ** envp )        // environment variables
     179              char ** args,         // process arguments
     180              char ** envs )        // environment variables
    196181{
    197182    exec_info_t  exec_info;         // structure to pass to process_make_exec()
    198     thread_t   * thread;            // pointer on thread created in server cluster
    199         error_t      error   = 0;
    200         process_t  * process = CURRENT_PROCESS;
    201 
    202     // check arguments
    203         if((filename == NULL) || (argv == NULL) || (envp == NULL))
    204     {
    205         printk("\n[ERROR] in %s : missing arguments / file = %x / argv = %x / envp = %x\n",
    206                __FUNCTION__ , filename , argv , envp );
    207         return EINVAL;
     183        error_t      error;
     184    paddr_t      paddr;
     185
     186    thread_t   * this    = CURRENT_THREAD;
     187        process_t  * process = this->process;
     188
     189    // check argument fileme
     190    error = vmm_v2p_translate( false , filename , &paddr );
     191
     192        if( error )
     193    {
     194        printk("\n[ERROR] in %s : filename unmapped\n", __FUNCTION__ );
     195        this->errno = EINVAL;
     196        return -1;
     197    }
     198
     199    // check argument fileme
     200    error = vmm_v2p_translate( false , args , &paddr );
     201
     202        if( error )
     203    {
     204        printk("\n[ERROR] in %s : args unmapped\n", __FUNCTION__ );
     205        this->errno = EINVAL;
     206        return -1;
     207    }
     208
     209    // check argument fileme
     210    error = vmm_v2p_translate( false , envs , &paddr );
     211
     212        if( error )
     213    {
     214        printk("\n[ERROR] in %s : envs unmapped\n", __FUNCTION__ );
     215        this->errno = EINVAL;
     216        return -1;
    208217    }
    209218
     
    218227                 cxy_client, cxy_server, hal_time_stamp());
    219228
    220     // Change process's state to prevent any concurent access TODO ??? [AG]
    221 
    222229    // initialize exec_info structure
    223     exec_info->pid      = process->pid;
    224     exec_info->ppid     = process->ppid;
    225     exec_info->fd_array = &process->fd_array;
    226     exec_info->vfs_root = &process->vfs_root;
    227     exec_info->vfs_cwd  = &process->vfs_cwd;
    228     exec_info->vfs_bin  = &process->vfs_bin;
     230    exec_info.pid         = process->pid;
     231    exec_info.ppid        = process->ppid;
     232    exec_info.fd_array_xp = XPTR( local_cxy , &process->fd_array );
     233    exec_info.vfs_root_xp = process->vfs_root_xp;
     234    exec_info.vfs_cwd_xp  = process->vfs_cwd_xp;
     235    exec_info.vfs_bin_xp  = process->vfs_bin_xp;
    229236
    230237        // check pathname and store it in exec_info structure
    231238        error = process_exec_get_path( &exec_info , filename );
    232         if ( error ) return EINVAL;
    233 
    234         // check and store argv in exec_info structure
    235         error = process_exec_get_strings( &exec_info , true , argv );
    236         if( error )  return EINVAL;
     239
     240        if ( error )
     241    {
     242        printk("\n[ERROR] in %s : elf pathname too long\n", __FUNCTION__ );
     243        this->errno = error;
     244        return -1;
     245    }
     246
     247        // check and store args in exec_info structure
     248        error = process_exec_get_strings( &exec_info , true , args );
     249
     250        if( error ) 
     251    {
     252        printk("\n[ERROR] in %s : cannot access args\n", __FUNCTION__ );
     253        this->errno = error;
     254        return -1;
     255    }
    237256       
    238         // check and store envp in exec_info structure
    239         error = process_exec_get_strings( &exec_info , false , envp );
    240         if( error )  return EINVAL;
     257        // check and store envs in exec_info structure
     258        error = process_exec_get_strings( &exec_info , false , envs );
     259
     260        if( error )
     261    {
     262        printk("\n[ERROR] in %s : cannot access envs\n", __FUNCTION__ );
     263        this->errno = error;
     264        return -1;
     265    }
    241266       
    242     if( is_local )  ////////////// local exec //////////////////////////
    243     {
    244         exec_dmsg("\n[INFO] %s starts local exec for process %x at cycle %d\n",
    245                   __FUNCTION__, process->pid, hal_time_stamp());
    246 
    247         // call directly the local process_make_exec() function
    248         error = process_make_exec( &exec_info , &thread );
    249         if error
    250         {
    251             printk("\n[ERROR] in %s : failed in local exec for process %x\n",
    252                    __FUNCTION__ , process->pid );
    253             return EINVAL;
    254         }
    255 
    256         exec_dmsg("\n[INFO] %s completes local exec for process %x at cycle %d\n",
    257                   __FUNCTION__, process->pid , hal_time_stamp() );
    258     }
    259     else             ///////////// remote exec /////////////////////////
    260     {
    261         exec_dmsg("\n[INFO] %s starts remote exec for process %x at cycle %d\n",
    262                   __FUNCTION__, process->pid, hal_time_stamp() );
    263 
    264         // call the rpc_process_exec_client() function   
    265         rpc_process_exec_client( cxy_server , &exec_info , &thread , &error );
    266 
    267         if( error )
    268         {
    269             printk("\n[ERROR] in %s : failed in remote exec for process %x\n",
    270                    __FUNCTION__ , process->pid );
    271             return EINVAL;
    272         }
    273 
    274         exec_dmsg("\n[INFO] %s completes remote exec for process %x at cycle %d\n",
    275                   __FUNCTION__, process->pid , hal_time_stamp() );
    276     }
    277 
    278     // If no error, delete the current thread an process descriptors.
     267    exec_dmsg("\n[INFO] %s starts exec for process %x at cycle %d\n",
     268              __FUNCTION__, process->pid, hal_time_stamp() );
     269
     270    if( is_local )  error = process_make_exec( &exec_info );
     271    else            rpc_process_exec_client( cxy_server , &exec_info , &error );
     272
     273    if( error )
     274    {
     275        printk("\n[ERROR] in %s : cannot create new process %x\n",
     276               __FUNCTION__ , process->pid );
     277        this->errno = error;
     278        return -1;
     279    }
     280
     281    exec_dmsg("\n[INFO] %s completes exec for process %x at cycle %d\n",
     282              __FUNCTION__, process->pid , hal_time_stamp() );
     283
     284    // delete the calling thread an process
    279285    thread_kill( CURRENT_THREAD );
    280     process_kill( CURRENT_PROCESS );
     286    process_kill( CURRENT_THREAD->process );
    281287
    282288    return 0;
     289
    283290} // end sys_exec()
    284291
Note: See TracChangeset for help on using the changeset viewer.