/////////////////////////////////////////////////////////////////////////////////// // 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 //////////////////////////////////////////////////////////////////////////// // Initialize the syscall vector with syscall handlers //////////////////////////////////////////////////////////////////////////// const void * _syscall_vector[32] = { &_procid, /* 0x00 */ &_proctime, /* 0x01 */ &_tty_write, /* 0x02 */ &_tty_read, /* 0x03 */ &_timer_start, /* 0x04 */ &_timer_stop, /* 0x05 */ &_gcd_write, /* 0x06 */ &_gcd_read, /* 0x07 */ &_sys_ukn, /* 0x08 */ &_get_current_task_id, /* 0x09 */ &_sys_ukn, /* 0x0A */ &_sys_ukn, /* 0x0B */ &_sys_ukn, /* 0x0C */ &_context_switch, /* 0x0D */ &_exit, /* 0x0E */ &_procs_number, /* 0x0F */ &_fb_sync_write, /* 0x10 */ &_fb_sync_read, /* 0x11 */ &_fb_write, /* 0x12 */ &_fb_read, /* 0x13 */ &_fb_completed, /* 0x14 */ &_ioc_write, /* 0x15 */ &_ioc_read, /* 0x16 */ &_ioc_completed, /* 0x17 */ &_sys_ukn, /* 0x18 */ &_sys_ukn, /* 0x19 */ &_vobj_get_vbase, /* 0x1A */ &_nic_write, /* 0x1B */ &_nic_read, /* 0x1C */ &_nic_completed, /* 0x1D */ &_sys_ukn, /* 0x1E */ &_sys_ukn, /* 0x1F */ }; ////////////////////////////////////////////////////////////////////////////// // function executed in case of undefined syscall ////////////////////////////////////////////////////////////////////////////// void _sys_ukn() { unsigned int epc; asm volatile("mfc0 %0, $14" : "=r" (epc)); _puts("\n\n!!! Undefined System Call !!!\n"); _puts("\nEPC = "); _putx(epc); _exit(); } //////////////////////////////////////////////////////////////////////////// // _exit() // Task suicide... after printing a death message. //////////////////////////////////////////////////////////////////////////// void _exit() { unsigned int date = _proctime(); unsigned int proc_id = _procid(); unsigned int task_id = _get_current_task_id(); // print death message _get_lock(&_tty_put_lock); _puts("\n[GIET] Exit task "); _putd(task_id); _puts(" on processor "); _putd(proc_id); _puts(" at cycle "); _putd(date); _puts("\n\n"); _release_lock(&_tty_put_lock); // goes to sleeping state _set_context_slot( task_id, CTX_RUN_ID, 0); // deschedule _ctx_switch(); } ////////////////////////////////////////////////////////////////////////////// // _procid() // Access CP0 and returns current processor's identifier. // Max number or processors is 1024. ////////////////////////////////////////////////////////////////////////////// unsigned int _procid() { unsigned int ret; asm volatile("mfc0 %0, $15, 1" : "=r" (ret)); return (ret & 0xFFF); } ////////////////////////////////////////////////////////////////////////////// // _proctime() // Access CP0 and returns current processor's elapsed clock cycles since boot. ////////////////////////////////////////////////////////////////////////////// unsigned int _proctime() { unsigned int ret; asm volatile("mfc0 %0, $9" : "=r" (ret)); return ret; } ////////////////////////////////////////////////////////////////////////////// // _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_mapping_base; mapping_cluster_t * cluster = _get_cluster_base(header); if (cluster_id < header->clusters) { *buffer = cluster[cluster_id].procs; return 0; } else { return 1; } } 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_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) { _get_lock(&_tty_put_lock); _puts("*** Error in _get_obj: wrong type\n"); _release_lock(&_tty_put_lock); return -1; // wrong type } *res_vobj = &vobj[vobj_id]; return 0; } } } } _get_lock(&_tty_put_lock); _puts("*** Error in _get_obj: object not found\n"); _release_lock(&_tty_put_lock); 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_mask(); _ctx_switch(); _it_restore(); } // 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