/////////////////////////////////////////////////////////////////////////////////// // File : sys_handler.c // Date : 01/04/2012 // Author : alain greiner and joel porquet // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// // The sys_handler.c and sys_handler.h files are part of the GIET-VM nano-kernel. // It define the syscall_vector[] (at the end of this file), as well as the // associated syscall handlers that are not related to peripherals. // The syscall handlers for peripherals are defined in the drivers.c file. /////////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include //////////////////////////////////////////////////////////////////////////// // Initialize the syscall vector with syscall handlers // Note: This array must be synchronised with the define in file stdio.h //////////////////////////////////////////////////////////////////////////// const void * _syscall_vector[64] = { &_get_procid, /* 0x00 */ &_get_proctime, /* 0x01 */ &_tty_write, /* 0x02 */ &_tty_read, /* 0x03 */ &_timer_start, /* 0x04 */ &_timer_stop, /* 0x05 */ &_sys_ukn, /* 0x06 */ &_sys_ukn, /* 0x07 */ &_heap_info, /* 0x08 */ &_local_task_id, /* 0x09 */ &_global_task_id, /* 0x0A */ &_fb_cma_init, /* 0x0B */ &_fb_cma_write, /* 0x0C */ &_fb_cma_stop, /* 0x0D */ &_task_exit, /* 0x0E */ &_procs_number, /* 0x0F */ &_fb_sync_write, /* 0x10 */ &_fb_sync_read, /* 0x11 */ &_thread_id, /* 0x12 */ &_tty_get_release_lock,/* 0x13 */ &_sys_ukn, /* 0x14 */ &_sys_ukn, /* 0x15 */ &_sys_ukn, /* 0x16 */ &_sys_ukn, /* 0x17 */ &_sys_ukn, /* 0x18 */ &_ctx_switch, /* 0x19 */ &_vobj_get_vbase, /* 0x1A */ &_sys_ukn, /* 0x1B */ &_nic_cma_start, /* 0x1C */ &_nic_cma_stop, /* 0x1D */ &_nic_sync_read, /* 0x1E */ &_nic_sync_write, /* 0x1F */ &_fat_user_open, /* 0x20 */ &_fat_user_read, /* 0x21 */ &_fat_user_write, /* 0x22 */ &_fat_user_lseek, /* 0x23 */ &_fat_fstat, /* 0x24 */ &_fat_close, /* 0x25 */ &_sys_ukn, /* 0x26 */ &_sys_ukn, /* 0x27 */ &_sys_ukn, /* 0x28 */ &_sys_ukn, /* 0x29 */ &_sys_ukn, /* 0x2A */ &_sys_ukn, /* 0x2B */ &_sys_ukn, /* 0x2C */ &_sys_ukn, /* 0x2D */ &_sys_ukn, /* 0x2E */ &_sys_ukn, /* 0x2F */ &_sys_ukn, /* 0x30 */ &_sys_ukn, /* 0x31 */ &_sys_ukn, /* 0x32 */ &_sys_ukn, /* 0x33 */ &_sys_ukn, /* 0x34 */ &_sys_ukn, /* 0x35 */ &_sys_ukn, /* 0x36 */ &_sys_ukn, /* 0x37 */ &_sys_ukn, /* 0x38 */ &_sys_ukn, /* 0x39 */ &_sys_ukn, /* 0x3A */ &_sys_ukn, /* 0x3B */ &_sys_ukn, /* 0x3C */ &_sys_ukn, /* 0x3D */ &_sys_ukn, /* 0x3E */ &_sys_ukn, /* 0x3F */ }; ////////////////////////////////////////////////////////////////////////////// // function executed in case of undefined syscall ////////////////////////////////////////////////////////////////////////////// void _sys_ukn() { unsigned int epc; asm volatile("mfc0 %0, $14" : "=r" (epc)); _tty_get_lock( 0 ); _puts("\n\n!!! Undefined System Call !!!\n"); _puts("\nEPC = "); _putx(epc); _tty_release_lock( 0 ); _exit(); } //////////////////////////////////////////////////////////////////////////// // _exit() // Task suicide... after printing a death message. //////////////////////////////////////////////////////////////////////////// void _task_exit() { unsigned int date = _get_proctime(); unsigned int proc_id = _get_procid(); unsigned int task_id = _get_context_slot(CTX_LTID_ID); // print death message _tty_get_lock( 0 ); _puts("\n[GIET] Exit task "); _putd(task_id); _puts(" on processor "); _putd(proc_id); _puts(" at cycle "); _putd(date); _puts("\n\n"); _tty_release_lock( 0 ); // goes to sleeping state _set_context_slot(CTX_RUN_ID, 0); // deschedule _context_switch(); } ////////////////////////////////////////////////////////////////////////////// // _procnumber() // returns in buffer argument the number of processors in the cluster // specified by the cluster_id argument. ////////////////////////////////////////////////////////////////////////////// unsigned int _procs_number(unsigned int cluster_id, unsigned int* buffer) { mapping_header_t * header = (mapping_header_t *) &seg_boot_mapping_base; mapping_cluster_t * cluster = _get_cluster_base(header); if ( cluster_id < X_SIZE * Y_SIZE ) { *buffer = cluster[cluster_id].procs; return 0; } else { return 1; } } ///////////////////////////////////////////////////////////////////////////// // _local_task_id() // Returns current task local index. ///////////////////////////////////////////////////////////////////////////// unsigned int _local_task_id() { return _get_context_slot(CTX_LTID_ID); } ///////////////////////////////////////////////////////////////////////////// // _global_task_id() // Returns current task global index. ///////////////////////////////////////////////////////////////////////////// unsigned int _global_task_id() { return _get_context_slot(CTX_GTID_ID); } ///////////////////////////////////////////////////////////////////////////// // _thread_id() // Returns current thread index. ///////////////////////////////////////////////////////////////////////////// unsigned int _thread_id() { return _get_context_slot(CTX_TRDID_ID); } ///////////////////////////////////////////////////////////////////////////// // _tty_get_release_lock(int val) // Get or release the hardware TTY lock depending on val (0: get,1: release) ///////////////////////////////////////////////////////////////////////////// int _tty_get_release_lock(unsigned int val) { unsigned int channel = _get_context_slot(CTX_TTY_ID); if ( val == 0 ) _tty_get_lock(channel); else if ( val == 1 ) _tty_release_lock(channel); else return -1; // Wrong action return 0; } ///////////////////////////////////////////////////////////////////////////// // _get_vobj() // This function writes in res_vobj a pointer on a vobj // identified by the (vspace_name / vobj_name ) couple. // The vobj_type argument is here only for the purpose of checking . // returns 0: success, else: failed. ///////////////////////////////////////////////////////////////////////////// int _get_vobj( char* vspace_name, char* vobj_name, unsigned int vobj_type, mapping_vobj_t** res_vobj ) { mapping_header_t * header = (mapping_header_t *) &seg_boot_mapping_base; mapping_vspace_t * vspace = _get_vspace_base(header); mapping_vobj_t * vobj = _get_vobj_base(header); unsigned int vspace_id; unsigned int vobj_id; // scan vspaces for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) { if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) { // scan vobjs for (vobj_id = vspace[vspace_id].vobj_offset; vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs); vobj_id++) { if (_strncmp(vobj[vobj_id].name, vobj_name, 31) == 0) { if (vobj[vobj_id].type != vobj_type) { _tty_get_lock( 0 ); _puts("*** Error in _get_obj: wrong type\n"); _tty_release_lock( 0 ); return -1; // wrong type } *res_vobj = &vobj[vobj_id]; return 0; } } } } _tty_get_lock( 0 ); _puts("*** Error in _get_obj: object not found\n"); _tty_release_lock( 0 ); return -2; //not found } ///////////////////////////////////////////////////////////////////////////// // _vobj_get_vbase() // This function writes in vobj_vaddr the virtual base address of a vobj // identified by the (vspace_name / vobj_name ) couple. // The vobj_type argument is here only for the purpose of checking . // returns 0: success, else: failed. ///////////////////////////////////////////////////////////////////////////// unsigned int _vobj_get_vbase( char* vspace_name, char* vobj_name, unsigned int vobj_type, unsigned int* vobj_vaddr ) { mapping_vobj_t* res_vobj; unsigned int ret; if ((ret = _get_vobj(vspace_name, vobj_name, vobj_type, &res_vobj))) { return ret; } *vobj_vaddr = res_vobj->vaddr; return 0; } ///////////////////////////////////////////////////////////////////////////// // _vobj_get_length() // This function writes in vobj_length the virtual base address of a vobj // identified by the (vspace_name / vobj_name ) couple. // The vobj_type argument is here only for the purpose of checking . // returns 0: success, else: failed. ///////////////////////////////////////////////////////////////////////////// unsigned int _vobj_get_length( char* vspace_name, char* vobj_name, unsigned int vobj_type, unsigned int* vobj_length ) { mapping_vobj_t * res_vobj; unsigned int ret; if ((ret = _get_vobj(vspace_name, vobj_name, vobj_type, &res_vobj))) { return ret; } *vobj_length = res_vobj->length; return 0; } //////////////////////////////////////////////////////////////// // _context_switch() // This functions masks interruptions before calling _ctx_switch // (They are usually masked when we receive a isr_switch interrupt // because we execute ISRs with interrupt masked) //////////////////////////////////////////////////////////////// void _context_switch() { _it_disable(); _ctx_switch(); } // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4