/////////////////////////////////////////////////////////////////////////////////// // 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 */ &_tty_get_lock, /* 0x06 */ &_tty_release_lock, /* 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 */ &_sys_ukn, /* 0x13 */ &_sys_ukn, /* 0x14 */ &_sys_ukn, /* 0x15 */ &_sys_ukn, /* 0x16 */ &_sys_ukn, /* 0x17 */ &_sys_ukn, /* 0x18 */ &_context_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() { _printf("\n\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() ); _exit(); } //////////////////////////////////////////////////////////////////////////// // Task suicide... after printing a death message. //////////////////////////////////////////////////////////////////////////// void _task_exit( char* string ) { unsigned int date = _get_proctime(); unsigned int proc_id = _get_procid(); unsigned int cluster_xy = proc_id / NB_PROCS_MAX; unsigned int y = cluster_xy & ((1<> Y_WIDTH; unsigned int lpid = proc_id % NB_PROCS_MAX; unsigned int task_id = _get_context_slot(CTX_LTID_ID); // print death message _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d" "\n Cause : %s\n\n", task_id, x, y, lpid, date, string ); // goes to sleeping state _set_context_slot(CTX_RUN_ID, 0); // deschedule _context_switch(); } ////////////////////////////////////////////////////////////////////////////// // 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; } } ///////////////////////////////////////////////////////////////////////////// // Returns current task local index. ///////////////////////////////////////////////////////////////////////////// unsigned int _local_task_id() { return _get_context_slot(CTX_LTID_ID); } ///////////////////////////////////////////////////////////////////////////// // Returns current task global index. ///////////////////////////////////////////////////////////////////////////// unsigned int _global_task_id() { return _get_context_slot(CTX_GTID_ID); } ///////////////////////////////////////////////////////////////////////////// // Returns current thread index. ///////////////////////////////////////////////////////////////////////////// unsigned int _thread_id() { return _get_context_slot(CTX_TRDID_ID); } ///////////////////////////////////////////////////////////////////////////// // This function writes in res_vobj a pointer on a vobj // identified by the (vspace_name / vobj_name ) couple. // returns 0 if success, >0 if not found ///////////////////////////////////////////////////////////////////////////// int _get_vobj( char* vspace_name, char* vobj_name, 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) { *res_vobj = &vobj[vobj_id]; return 0; } } } } return 1; //not found } ///////////////////////////////////////////////////////////////////////////// // This function writes in vobj_vaddr the virtual base address of a vobj // identified by the (vspace_name / vobj_name ) couple. // returns 0 if success, >0 if not found ///////////////////////////////////////////////////////////////////////////// unsigned int _vobj_get_vbase( char* vspace_name, char* vobj_name, unsigned int* vobj_vbase ) { mapping_vobj_t* res_vobj; unsigned int ret; if ((ret = _get_vobj(vspace_name, vobj_name, &res_vobj))) { return ret; } *vobj_vbase = res_vobj->vaddr; return 0; } ///////////////////////////////////////////////////////////////////////////// // This function writes in vobj_length the length of a vobj // identified by the (vspace_name / vobj_name ) couple. // returns 0 if success, >0 if not found ///////////////////////////////////////////////////////////////////////////// unsigned int _vobj_get_length( char* vspace_name, char* vobj_name, unsigned int* vobj_length ) { mapping_vobj_t * res_vobj; unsigned int ret; if ((ret = _get_vobj(vspace_name, vobj_name, &res_vobj))) { return ret; } *vobj_length = res_vobj->length; return 0; } //////////////////////////////////////////////////////////////////////////// // This sysrem function deschedule the requestint task. // It mask interrupts before calling the _ctx_switch, and restore it // when the task is rescheduled. //////////////////////////////////////////////////////////////////////////// void _context_switch() { unsigned int save_sr; _it_disable( &save_sr ); _ctx_switch(); _it_restore( &save_sr ); } // 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