/////////////////////////////////////////////////////////////////////////////////// // 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 */ &_sys_ukn, /* 0x09 */ &_tty_read_irq, /* 0x0A */ &_sys_ukn, /* 0x0B */ &_sys_ukn, /* 0x0C */ &_ctx_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 */ &_sys_ukn, /* 0x1B */ &_sys_ukn, /* 0x1C */ &_sys_ukn, /* 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 = "); _putw( 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; } } ///////////////////////////////////////////////////////////////////////////// // _vobj_get_vbase() // This function writes in vobj_buffer the virtual base address of a vobj // identified by the (vspace_name / vobj_name ) couple. // The vobj_type argument is redundant, and for checking purpose. // 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_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) return -1; //wrong type *vobj_vaddr = (unsigned int)vobj[vobj_id].vaddr; return 0; } } } } return -2; //not found }