source: trunk/kernel/syscalls/sys_display.c @ 623

Last change on this file since 623 was 623, checked in by alain, 5 years ago

Introduce three new types of vsegs (KCODE,KDATA,KDEV)
to map the kernel vsegs in the process VSL and GPT.
This now used by both the TSAR and the I86 architectures.

File size: 13.1 KB
RevLine 
[421]1/*
2 * sys_display.c - display the current state of a kernel structure on TXT0
3 *
[440]4 * Author    Alain Greiner (2016,2017,2018)
[421]5 * 
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
[457]24#include <hal_kernel_types.h>
[421]25#include <hal_uspace.h>
26#include <errno.h>
[433]27#include <vmm.h>
[421]28#include <cluster.h>
29#include <thread.h>
30#include <process.h>
[433]31#include <string.h>
[443]32#include <shared_syscalls.h>
[623]33#include <remote_barrier.h>
[611]34#include <vfs.h>
35#include <mapper.h>
[421]36
[506]37#include <syscalls.h>
38
[443]39/////////////////////////////////////////////////////////////////////////////////
40// This static function returns a printable string for the type of display.
41/////////////////////////////////////////////////////////////////////////////////
[421]42
[443]43#if DEBUG_SYS_DISPLAY
44static char* display_type_str( uint32_t type )
45{
46    if     ( type == DISPLAY_STRING            ) return "STRING"; 
47    else if( type == DISPLAY_VMM               ) return "VMM"; 
48    else if( type == DISPLAY_SCHED             ) return "SCHED"; 
49    else if( type == DISPLAY_CLUSTER_PROCESSES ) return "CLUSTER_PROCESSES"; 
50    else if( type == DISPLAY_VFS               ) return "VFS"; 
51    else if( type == DISPLAY_CHDEV             ) return "CHDEV"; 
52    else if( type == DISPLAY_TXT_PROCESSES     ) return "TXT_PROCESSES"; 
[580]53    else if( type == DISPLAY_DQDT              ) return "DQDT";
54    else if( type == DISPLAY_BUSYLOCKS         ) return "BUSYLOCKS"; 
[612]55    else if( type == DISPLAY_MAPPER            ) return "MAPPER";
[623]56    else if( type == DISPLAY_BARRIER           ) return "BARRIER";
[612]57    else                                         return "undefined";
[443]58}
59#endif
60
[421]61/////////////////////////////
62int sys_display( reg_t  type,
63                 reg_t  arg0,
[611]64                 reg_t  arg1,
65                 reg_t  arg2 )
[421]66{
[433]67
[440]68    error_t     error;
69    vseg_t    * vseg;
70
71    thread_t  * this    = CURRENT_THREAD;
72    process_t * process = this->process;
73
[594]74#if (DEBUG_SYS_DISPLAY || CONFIG_INSTRUMENTATION_SYSCALLS)
75uint64_t     tm_start = hal_get_cycles();
76#endif
77
[438]78#if DEBUG_SYS_DISPLAY
[433]79tm_start = hal_get_cycles();
[438]80if( DEBUG_SYS_DISPLAY < tm_start )
[619]81printk("\n[%s] thread[%x,%x] enter / type  %s / cycle = %d\n",
[594]82__FUNCTION__, process->pid, this->trdid, display_type_str(type), (uint32_t)tm_start );
[433]83#endif
84
[623]85    switch( type )
[421]86    {
[623]87        ////////////////////
88        case DISPLAY_STRING:
89        {
90            char      kbuf[512];
91            uint32_t  length;
[421]92
[623]93            char    * string = (char *)arg0;
[440]94
[623]95            // check string in user space
96            error = vmm_get_vseg( process , (intptr_t)arg0 , &vseg );
[440]97
[623]98            if( error )
99            {
[440]100
101#if DEBUG_SYSCALLS_ERROR
[580]102printk("\n[ERROR] in %s for STRING : string buffer %x unmapped\n",
103__FUNCTION__ , (intptr_t)arg0 );
[440]104#endif
[623]105                this->errno = EINVAL;
106                return -1;
107            }
[421]108
[623]109            // ckeck string length
110            length = hal_strlen_from_uspace( string );
[440]111
[623]112            if( length >= 512 )
113            {
[440]114
115#if DEBUG_SYSCALLS_ERROR
[580]116printk("\n[ERROR] in %s for STRING : string length %d too large\n",
117__FUNCTION__ , length );
[440]118#endif
[623]119                this->errno = EINVAL;
120                return -1;
121            }
[421]122
[623]123            // copy string to kernel space
124            hal_strcpy_from_uspace( kbuf , string , 512 );
[421]125
[623]126            // print message on TXT0 kernel terminal
127            printk("\n%s / cycle %d\n", kbuf, (uint32_t)hal_get_cycles() );
[421]128
[623]129            break;
130        }
131        /////////////////
132        case DISPLAY_VMM:
[443]133        {
[623]134            cxy_t cxy = (cxy_t)arg0;
135            pid_t pid = (pid_t)arg1;
[421]136
[623]137            // check cxy argument
138                if( cluster_is_undefined( cxy ) ) 
139            {
140
[443]141#if DEBUG_SYSCALLS_ERROR
[580]142printk("\n[ERROR] in %s for VMM : process %x in cluster %x not found\n",
143__FUNCTION__ , pid , cxy );
[443]144#endif
[623]145                this->errno = EINVAL;
146                return -1;
147            }
[443]148
[623]149            // get extended pointer on process PID in cluster CXY
150            xptr_t process_xp = cluster_get_process_from_pid_in_cxy( cxy , pid );
[443]151
[623]152                if( process_xp == XPTR_NULL )
153            {
[440]154
155#if DEBUG_SYSCALLS_ERROR
[580]156printk("\n[ERROR] in %s for VMM : process %x in cluster %x not found\n",
157__FUNCTION__ , pid , cxy );
[440]158#endif
[623]159                this->errno = EINVAL;
160                return -1;
161            }
[421]162
[623]163            // get local pointer on process
164            process_t * process = (process_t *)GET_PTR( process_xp );
[421]165
[623]166            // call kernel function
167            if( cxy == local_cxy )
168            {
169                    vmm_display( process , true );
170            }
171            else
172            {
173                rpc_vmm_display_client( cxy , process , true );
174            }
175
176            break;
[421]177        }
[623]178        ///////////////////
179        case DISPLAY_SCHED:
[421]180        {
[623]181            cxy_t cxy = (cxy_t)arg0;
182            lid_t lid = (lid_t)arg1;
[421]183
[623]184            // check cxy argument
185                if( cluster_is_undefined( cxy ) ) 
186            {
[440]187
188#if DEBUG_SYSCALLS_ERROR
[580]189printk("\n[ERROR] in %s for SCHED : illegal cxy argument %x\n",
190__FUNCTION__ , cxy );
[440]191#endif
[623]192                this->errno = EINVAL;
193                return -1;
194            }
[421]195
[623]196            // check lid argument
197            if( lid >= LOCAL_CLUSTER->cores_nr )
198            {
[440]199
200#if DEBUG_SYSCALLS_ERROR
[580]201printk("\n[ERROR] in %s for SCHED : illegal lid argument %x\n",
202__FUNCTION__ , lid );
[440]203#endif
[623]204                this->errno = EINVAL;
205                return -1;
206            }
[421]207
[623]208            if( cxy == local_cxy )
209            {
210                    sched_display( lid );
211            }
212            else
213            {
214                sched_remote_display( cxy , lid );
215            }
216
217            break;
[421]218        }
[623]219        ///////////////////////////////
220        case DISPLAY_CLUSTER_PROCESSES:
[421]221        {
[623]222            cxy_t  cxy   = (cxy_t)arg0;
223            bool_t owned = (bool_t)arg1;
[421]224
[623]225            // check cxy argument
226                if( cluster_is_undefined( cxy ) )
227            {
[440]228
229#if DEBUG_SYSCALLS_ERROR
[580]230printk("\n[ERROR] in %s for CLUSTER_PROCESSES : illegal cxy argument %x\n",
231__FUNCTION__ , cxy );
[440]232#endif
[623]233                this->errno = EINVAL;
234                return -1;
235            }
236
237            cluster_processes_display( cxy , owned );
238
239            break;
[433]240        }
[623]241        /////////////////
242        case DISPLAY_VFS:
243        {
244            vfs_display( process->vfs_root_xp );
[421]245
[623]246            break;
247        }
248        ///////////////////
249        case DISPLAY_CHDEV:
250        {
251            chdev_dir_display();
[435]252
[623]253            break;
254        }
255        ///////////////////////////
256        case DISPLAY_TXT_PROCESSES:
[435]257        {
[623]258            uint32_t txt_id = (uint32_t)arg0;
[440]259
[623]260            // check argument
261                if( txt_id >= LOCAL_CLUSTER->nb_txt_channels )
262            {
263
[440]264#if DEBUG_SYSCALLS_ERROR
[580]265printk("\n[ERROR] in %s for TXT_PROCESSES : illegal txt_id argument %d\n",
266__FUNCTION__ , txt_id );
[440]267#endif
[623]268                this->errno = EINVAL;
269                return -1;
270            }
[435]271
[623]272            process_txt_display( txt_id );
[580]273
[623]274            break;
275        }
276        //////////////////
277        case DISPLAY_DQDT:
278        {
279            dqdt_display();
[580]280
[623]281            break;
282        }
283        ///////////////////////
284        case DISPLAY_BUSYLOCKS:
[580]285        {
[623]286            pid_t   pid   = (pid_t)arg0;
287            trdid_t trdid = (trdid_t)arg1;
[580]288
[623]289            // get extended pointer on target thread
290            xptr_t thread_xp = thread_get_xptr( pid , trdid );
291
292            if( thread_xp == XPTR_NULL )
293            {
294
[580]295#if DEBUG_SYSCALLS_ERROR
[594]296printk("\n[ERROR] in %s for BUSYLOCKS : thread[%x,%x] not found\n",
297__FUNCTION__ , pid, trdid );
[580]298#endif
[623]299                this->errno = EINVAL;
300                return -1;
301            }
302
303            thread_display_busylocks( thread_xp , __FUNCTION__ );
304
305            break;
[580]306        }
[623]307        ////////////////////
308        case DISPLAY_MAPPER:
309        {
310            xptr_t        root_inode_xp;
311            xptr_t        inode_xp;
312            cxy_t         inode_cxy;
313            vfs_inode_t * inode_ptr;
314            xptr_t        mapper_xp;
315            mapper_t    * mapper_ptr;
[580]316
[623]317            char          kbuf[CONFIG_VFS_MAX_PATH_LENGTH];
[611]318
[623]319            char     * path    = (char *)arg0;
320            uint32_t   page_id = (uint32_t)arg1;
321            uint32_t   nbytes  = (uint32_t)arg2;
[611]322
[623]323            // check pathname length
324            if( hal_strlen_from_uspace( path ) >= CONFIG_VFS_MAX_PATH_LENGTH )
325            {
[611]326
327#if DEBUG_SYSCALLS_ERROR
328printk("\n[ERROR] in %s for MAPPER : pathname too long\n",
329 __FUNCTION__ );
330#endif
[623]331                this->errno = ENFILE;
332                return -1;
333            }
[611]334
[623]335            // copy pathname in kernel space
336            hal_strcpy_from_uspace( kbuf , path , CONFIG_VFS_MAX_PATH_LENGTH );
[611]337
[623]338            // compute root inode for pathname
339            if( kbuf[0] == '/' )                        // absolute path
340            {
341                // use extended pointer on VFS root inode
342                root_inode_xp = process->vfs_root_xp;
343            }
344            else                                        // relative path
345            {
346                // get cluster and local pointer on reference process
347                xptr_t      ref_xp  = process->ref_xp;
348                process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
349                cxy_t       ref_cxy = GET_CXY( ref_xp );
[611]350
[623]351                // get extended pointer on CWD inode
352                root_inode_xp = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->cwd_xp ) );
353            }
[611]354
[623]355            // get extended pointer on target inode
356            error = vfs_lookup( root_inode_xp,
357                                kbuf,
358                                0,
359                                &inode_xp,
360                                NULL );
361            if( error )
362                {
[611]363
364#if DEBUG_SYSCALLS_ERROR
365printk("\n[ERROR] in %s for MAPPER : cannot found inode <%s>\n",
366__FUNCTION__ , kbuf );
367#endif
[623]368                        this->errno = ENFILE;
369                        return -1;
370                }
[611]371   
[623]372            // get target inode cluster and local pointer
373            inode_cxy = GET_CXY( inode_xp );
374            inode_ptr = GET_PTR( inode_xp );
[611]375
[623]376            // get extended pointer on target mapper
377            mapper_ptr = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
378            mapper_xp  = XPTR( inode_cxy , mapper_ptr );
[611]379
[623]380            // display mapper
381            error = mapper_display_page( mapper_xp , page_id , nbytes );
[611]382
[623]383            if( error )
384                {
[611]385
386#if DEBUG_SYSCALLS_ERROR
387printk("\n[ERROR] in %s for MAPPER : cannot display page %d\n",
388__FUNCTION__ , page_id );
389#endif
[623]390                        this->errno = ENFILE;
391                        return -1;
392                }
[440]393
[623]394            break;
395        }
396        /////////////////////
397        case DISPLAY_BARRIER:
398        {
399            // get target process PID
400            pid_t pid = (pid_t)arg0;
401
402            // get pointers on owner process
403            xptr_t      process_xp  = cluster_get_reference_process_from_pid( pid );
404            process_t * process_ptr = GET_PTR( process_xp );
405            cxy_t       process_cxy = GET_CXY( process_xp );
406
407            if( process_xp == XPTR_NULL )
408            {
409
[440]410#if DEBUG_SYSCALLS_ERROR
[623]411printk("\n[ERROR] in %s for BARRIER : process %x not found\n",
412__FUNCTION__ , pid );
413#endif
414                this->errno = EINVAL;
415                return -1;
416            }
417
418            // get extended pointer on root of list of barriers
419            xptr_t root_xp = XPTR( process_cxy , &process_ptr->barrier_root );
420
421            if( xlist_is_empty( root_xp ) )
422            {
423
424#if DEBUG_SYSCALLS_ERROR
425printk("\n[ERROR] in %s for BARRIER : no registered barrier in process %x\n",
426__FUNCTION__ , pid );
427#endif
428                this->errno = EINVAL;
429                return -1;
430            }
431
432            // get extended pointer on first registered generic barrier descriptor
433            xptr_t gen_barrier_xp  = XLIST_FIRST( root_xp , generic_barrier_t , list );
434
435            // display barrier state
436            generic_barrier_display( gen_barrier_xp );
437
438            break;
439        }
440        ////////
441        default: 
442        {
443
444#if DEBUG_SYSCALLS_ERROR
[580]445printk("\n[ERROR] in %s : undefined display type %d\n",
446        __FUNCTION__ , type );
[440]447#endif
[623]448            this->errno = EINVAL;
449            return -1;
450        }
451    }  // end switch on type
[421]452
[594]453#if (DEBUG_SYS_DISPLAY || CONFIG_INSTRUMENTATION_SYSCALLS)
454uint64_t     tm_end = hal_get_cycles();
455#endif
456
[438]457#if DEBUG_SYS_DISPLAY
458if( DEBUG_SYS_DISPLAY < tm_end )
[619]459printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
[594]460__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
[433]461#endif
462
[594]463#if CONFIG_INSTRUMENTATION_SYSCALLS
464hal_atomic_add( &syscalls_cumul_cost[SYS_DISPLAY] , tm_end - tm_start );
465hal_atomic_add( &syscalls_occurences[SYS_DISPLAY] , 1 );
466#endif
467
[433]468    return 0;
469
470}  // end sys_display()
Note: See TracBrowser for help on using the repository browser.