/* * sys_display.c - display the current state of a kernel structure on TXT0 * * Author Alain Greiner (2016,2017,2018) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include #include #include ///////////////////////////////////////////////////////////////////////////////// // This static function returns a printable string for the type of display. ///////////////////////////////////////////////////////////////////////////////// #if DEBUG_SYS_DISPLAY static char* display_type_str( uint32_t type ) { if ( type == DISPLAY_STRING ) return "STRING"; else if( type == DISPLAY_VMM ) return "VMM"; else if( type == DISPLAY_SCHED ) return "SCHED"; else if( type == DISPLAY_CLUSTER_PROCESSES ) return "CLUSTER_PROCESSES"; else if( type == DISPLAY_VFS ) return "VFS"; else if( type == DISPLAY_CHDEV ) return "CHDEV"; else if( type == DISPLAY_TXT_PROCESSES ) return "TXT_PROCESSES"; else if( type == DISPLAY_DQDT ) return "DQDT"; else if( type == DISPLAY_BUSYLOCKS ) return "BUSYLOCKS"; } #endif ///////////////////////////// int sys_display( reg_t type, reg_t arg0, reg_t arg1 ) { error_t error; vseg_t * vseg; thread_t * this = CURRENT_THREAD; process_t * process = this->process; #if DEBUG_SYS_DISPLAY uint64_t tm_start; uint64_t tm_end; tm_start = hal_get_cycles(); if( DEBUG_SYS_DISPLAY < tm_start ) printk("\n[DBG] %s : thread %d enter / process %x / type %s / cycle = %d\n", __FUNCTION__, this, this->process->pid, display_type_str(type), (uint32_t)tm_start ); #endif //////////////////////////// if( type == DISPLAY_STRING ) { char kbuf[256]; uint32_t length; char * string = (char *)arg0; // check string in user space error = vmm_get_vseg( process , (intptr_t)arg0 , &vseg ); if( error ) { #if DEBUG_SYSCALLS_ERROR printk("\n[ERROR] in %s for STRING : string buffer %x unmapped\n", __FUNCTION__ , (intptr_t)arg0 ); #endif this->errno = EINVAL; return -1; } // ckeck string length length = hal_strlen_from_uspace( string ); if( length >= 256 ) { #if DEBUG_SYSCALLS_ERROR printk("\n[ERROR] in %s for STRING : string length %d too large\n", __FUNCTION__ , length ); #endif this->errno = EINVAL; return -1; } // copy string to kernel space hal_strcpy_from_uspace( kbuf , string , 256 ); // print message on TXT0 kernel terminal printk("\n%s / cycle %d\n", kbuf, (uint32_t)hal_get_cycles() ); } ////////////////////////////// else if( type == DISPLAY_VMM ) { cxy_t cxy = (cxy_t)arg0; pid_t pid = (pid_t)arg1; // check cxy argument if( cluster_is_undefined( cxy ) ) { #if DEBUG_SYSCALLS_ERROR printk("\n[ERROR] in %s for VMM : process %x in cluster %x not found\n", __FUNCTION__ , pid , cxy ); #endif this->errno = EINVAL; return -1; } // get extended pointer on process PID in cluster CXY xptr_t process_xp = cluster_get_process_from_pid_in_cxy( cxy , pid ); if( process_xp == XPTR_NULL ) { #if DEBUG_SYSCALLS_ERROR printk("\n[ERROR] in %s for VMM : process %x in cluster %x not found\n", __FUNCTION__ , pid , cxy ); #endif this->errno = EINVAL; return -1; } // get local pointer on process process_t * process = (process_t *)GET_PTR( process_xp ); // call kernel function if( cxy == local_cxy ) { vmm_display( process , true ); } else { rpc_vmm_display_client( cxy , process , true ); } } //////////////////////////////// else if( type == DISPLAY_SCHED ) { cxy_t cxy = (cxy_t)arg0; lid_t lid = (lid_t)arg1; // check cxy argument if( cluster_is_undefined( cxy ) ) { #if DEBUG_SYSCALLS_ERROR printk("\n[ERROR] in %s for SCHED : illegal cxy argument %x\n", __FUNCTION__ , cxy ); #endif this->errno = EINVAL; return -1; } // check lid argument if( lid >= LOCAL_CLUSTER->cores_nr ) { #if DEBUG_SYSCALLS_ERROR printk("\n[ERROR] in %s for SCHED : illegal lid argument %x\n", __FUNCTION__ , lid ); #endif this->errno = EINVAL; return -1; } if( cxy == local_cxy ) { sched_display( lid ); } else { sched_remote_display( cxy , lid ); } } //////////////////////////////////////////// else if( type == DISPLAY_CLUSTER_PROCESSES ) { cxy_t cxy = (cxy_t)arg0; // check cxy argument if( cluster_is_undefined( cxy ) ) { #if DEBUG_SYSCALLS_ERROR printk("\n[ERROR] in %s for CLUSTER_PROCESSES : illegal cxy argument %x\n", __FUNCTION__ , cxy ); #endif this->errno = EINVAL; return -1; } cluster_processes_display( cxy ); } ////////////////////////////// else if( type == DISPLAY_VFS ) { vfs_display( process->vfs_root_xp ); } //////////////////////////////// else if( type == DISPLAY_CHDEV ) { chdev_dir_display(); } //////////////////////////////////////// else if( type == DISPLAY_TXT_PROCESSES ) { uint32_t txt_id = (uint32_t)arg0; // check argument if( txt_id >= LOCAL_CLUSTER->nb_txt_channels ) { #if DEBUG_SYSCALLS_ERROR printk("\n[ERROR] in %s for TXT_PROCESSES : illegal txt_id argument %d\n", __FUNCTION__ , txt_id ); #endif this->errno = EINVAL; return -1; } process_txt_display( txt_id ); } /////////////////////////////// else if( type == DISPLAY_DQDT ) { dqdt_display(); } //////////////////////////////////// else if( type == DISPLAY_BUSYLOCKS ) { pid_t pid = (cxy_t)arg0; trdid_t trdid = (trdid_t)arg1; // get extended pointer on target thread xptr_t thread_xp = thread_get_xptr( pid , trdid ); if( thread_xp == XPTR_NULL ) { #if DEBUG_SYSCALLS_ERROR printk("\n[ERROR] in %s for BUSYLOCKS : thread %x in process %x not found\n", __FUNCTION__ , trdid , pid ); #endif this->errno = EINVAL; return -1; } thread_display_busylocks( thread_xp ); } //// else { #if DEBUG_SYSCALLS_ERROR printk("\n[ERROR] in %s : undefined display type %d\n", __FUNCTION__ , type ); #endif this->errno = EINVAL; return -1; } #if DEBUG_SYS_DISPLAY tm_end = hal_get_cycles(); if( DEBUG_SYS_DISPLAY < tm_end ) printk("\n[DBG] %s : thread %x exit / process %x / cost = %d / cycle %d\n", __FUNCTION__, this, this->process->pid, (uint32_t)(tm_end - tm_start) , (uint32_t)tm_end ); #endif return 0; } // end sys_display()