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

Last change on this file since 657 was 657, checked in by alain, 4 years ago

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

File size: 14.5 KB
RevLine 
[421]1/*
2 * sys_display.c - display the current state of a kernel structure on TXT0
3 *
[657]4 * Author    Alain Greiner (2016,2017,2018,2019,2020)
[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>
[624]26#include <hal_vmm.h>
[421]27#include <errno.h>
[433]28#include <vmm.h>
[421]29#include <cluster.h>
30#include <thread.h>
31#include <process.h>
[433]32#include <string.h>
[443]33#include <shared_syscalls.h>
[623]34#include <remote_barrier.h>
[611]35#include <vfs.h>
36#include <mapper.h>
[421]37
[506]38#include <syscalls.h>
39
[443]40/////////////////////////////////////////////////////////////////////////////////
41// This static function returns a printable string for the type of display.
42/////////////////////////////////////////////////////////////////////////////////
[421]43
[443]44#if DEBUG_SYS_DISPLAY
45static char* display_type_str( uint32_t type )
46{
47    if     ( type == DISPLAY_STRING            ) return "STRING"; 
48    else if( type == DISPLAY_VMM               ) return "VMM"; 
49    else if( type == DISPLAY_SCHED             ) return "SCHED"; 
50    else if( type == DISPLAY_CLUSTER_PROCESSES ) return "CLUSTER_PROCESSES"; 
51    else if( type == DISPLAY_VFS               ) return "VFS"; 
52    else if( type == DISPLAY_CHDEV             ) return "CHDEV"; 
53    else if( type == DISPLAY_TXT_PROCESSES     ) return "TXT_PROCESSES"; 
[580]54    else if( type == DISPLAY_DQDT              ) return "DQDT";
55    else if( type == DISPLAY_BUSYLOCKS         ) return "BUSYLOCKS"; 
[612]56    else if( type == DISPLAY_MAPPER            ) return "MAPPER";
[623]57    else if( type == DISPLAY_BARRIER           ) return "BARRIER";
[626]58    else if( type == DISPLAY_FAT               ) return "FAT";
[612]59    else                                         return "undefined";
[443]60}
61#endif
62
[421]63/////////////////////////////
64int sys_display( reg_t  type,
65                 reg_t  arg0,
[611]66                 reg_t  arg1,
67                 reg_t  arg2 )
[421]68{
[433]69
[440]70    error_t     error;
71    vseg_t    * vseg;
72
73    thread_t  * this    = CURRENT_THREAD;
74    process_t * process = this->process;
75
[594]76#if (DEBUG_SYS_DISPLAY || CONFIG_INSTRUMENTATION_SYSCALLS)
77uint64_t     tm_start = hal_get_cycles();
78#endif
79
[438]80#if DEBUG_SYS_DISPLAY
[433]81tm_start = hal_get_cycles();
[438]82if( DEBUG_SYS_DISPLAY < tm_start )
[619]83printk("\n[%s] thread[%x,%x] enter / type  %s / cycle = %d\n",
[594]84__FUNCTION__, process->pid, this->trdid, display_type_str(type), (uint32_t)tm_start );
[433]85#endif
86
[623]87    switch( type )
[421]88    {
[623]89        ////////////////////
90        case DISPLAY_STRING:
91        {
92            char      kbuf[512];
93            uint32_t  length;
[421]94
[623]95            char    * string = (char *)arg0;
[440]96
[623]97            // check string in user space
98            error = vmm_get_vseg( process , (intptr_t)arg0 , &vseg );
99            if( error )
100            {
[440]101
102#if DEBUG_SYSCALLS_ERROR
[580]103printk("\n[ERROR] in %s for STRING : string buffer %x unmapped\n",
104__FUNCTION__ , (intptr_t)arg0 );
[440]105#endif
[623]106                this->errno = EINVAL;
107                return -1;
108            }
[421]109
[623]110            // ckeck string length
111            length = hal_strlen_from_uspace( string );
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
[637]124            hal_strcpy_from_uspace( XPTR( local_cxy , kbuf ),
125                                    string,
126                                    512 );
[421]127
[623]128            // print message on TXT0 kernel terminal
129            printk("\n%s / cycle %d\n", kbuf, (uint32_t)hal_get_cycles() );
[421]130
[623]131            break;
132        }
133        /////////////////
134        case DISPLAY_VMM:
[443]135        {
[640]136            cxy_t cxy      = (cxy_t)arg0;
137            pid_t pid      = (pid_t)arg1;
138            bool_t mapping = (arg2 != 0);
[421]139
[623]140            // check cxy argument
[637]141                if( cluster_is_active( cxy ) == false ) 
[623]142            {
143
[443]144#if DEBUG_SYSCALLS_ERROR
[580]145printk("\n[ERROR] in %s for VMM : process %x in cluster %x not found\n",
146__FUNCTION__ , pid , cxy );
[443]147#endif
[623]148                this->errno = EINVAL;
149                return -1;
150            }
[443]151
[623]152            // get extended pointer on process PID in cluster CXY
153            xptr_t process_xp = cluster_get_process_from_pid_in_cxy( cxy , pid );
154                if( process_xp == XPTR_NULL )
155            {
[440]156
157#if DEBUG_SYSCALLS_ERROR
[580]158printk("\n[ERROR] in %s for VMM : process %x in cluster %x not found\n",
159__FUNCTION__ , pid , cxy );
[440]160#endif
[623]161                this->errno = EINVAL;
162                return -1;
163            }
[421]164
[623]165            // call kernel function
[640]166                hal_vmm_display( process_xp , mapping );
[623]167
168            break;
[421]169        }
[623]170        ///////////////////
171        case DISPLAY_SCHED:
[421]172        {
[623]173            cxy_t cxy = (cxy_t)arg0;
174            lid_t lid = (lid_t)arg1;
[421]175
[623]176            // check cxy argument
[637]177                if( cluster_is_active( cxy ) == false ) 
[623]178            {
[440]179
180#if DEBUG_SYSCALLS_ERROR
[580]181printk("\n[ERROR] in %s for SCHED : illegal cxy argument %x\n",
182__FUNCTION__ , cxy );
[440]183#endif
[623]184                this->errno = EINVAL;
185                return -1;
186            }
[421]187
[623]188            // check lid argument
189            if( lid >= LOCAL_CLUSTER->cores_nr )
190            {
[440]191
192#if DEBUG_SYSCALLS_ERROR
[580]193printk("\n[ERROR] in %s for SCHED : illegal lid argument %x\n",
194__FUNCTION__ , lid );
[440]195#endif
[623]196                this->errno = EINVAL;
197                return -1;
198            }
[421]199
[640]200            // call kernel function
201            sched_remote_display( cxy , lid );
[623]202
203            break;
[421]204        }
[623]205        ///////////////////////////////
206        case DISPLAY_CLUSTER_PROCESSES:
[421]207        {
[623]208            cxy_t  cxy   = (cxy_t)arg0;
209            bool_t owned = (bool_t)arg1;
[421]210
[623]211            // check cxy argument
[637]212                if( cluster_is_active( cxy ) == false )
[623]213            {
[440]214
215#if DEBUG_SYSCALLS_ERROR
[580]216printk("\n[ERROR] in %s for CLUSTER_PROCESSES : illegal cxy argument %x\n",
217__FUNCTION__ , cxy );
[440]218#endif
[623]219                this->errno = EINVAL;
220                return -1;
221            }
222
223            cluster_processes_display( cxy , owned );
224
225            break;
[433]226        }
[623]227        /////////////////
228        case DISPLAY_VFS:
229        {
230            vfs_display( process->vfs_root_xp );
[421]231
[623]232            break;
233        }
234        ///////////////////
235        case DISPLAY_CHDEV:
236        {
237            chdev_dir_display();
[435]238
[623]239            break;
240        }
241        ///////////////////////////
242        case DISPLAY_TXT_PROCESSES:
[435]243        {
[623]244            uint32_t txt_id = (uint32_t)arg0;
[440]245
[623]246            // check argument
247                if( txt_id >= LOCAL_CLUSTER->nb_txt_channels )
248            {
249
[440]250#if DEBUG_SYSCALLS_ERROR
[580]251printk("\n[ERROR] in %s for TXT_PROCESSES : illegal txt_id argument %d\n",
252__FUNCTION__ , txt_id );
[440]253#endif
[623]254                this->errno = EINVAL;
255                return -1;
256            }
[435]257
[623]258            process_txt_display( txt_id );
[580]259
[623]260            break;
261        }
262        //////////////////
263        case DISPLAY_DQDT:
264        {
265            dqdt_display();
[580]266
[623]267            break;
268        }
269        ///////////////////////
270        case DISPLAY_BUSYLOCKS:
[580]271        {
[623]272            pid_t   pid   = (pid_t)arg0;
273            trdid_t trdid = (trdid_t)arg1;
[580]274
[623]275            // get extended pointer on target thread
276            xptr_t thread_xp = thread_get_xptr( pid , trdid );
277
278            if( thread_xp == XPTR_NULL )
279            {
280
[580]281#if DEBUG_SYSCALLS_ERROR
[594]282printk("\n[ERROR] in %s for BUSYLOCKS : thread[%x,%x] not found\n",
283__FUNCTION__ , pid, trdid );
[580]284#endif
[623]285                this->errno = EINVAL;
286                return -1;
287            }
288
289            thread_display_busylocks( thread_xp , __FUNCTION__ );
290
291            break;
[580]292        }
[623]293        ////////////////////
294        case DISPLAY_MAPPER:
295        {
296            xptr_t        root_inode_xp;
297            xptr_t        inode_xp;
298            cxy_t         inode_cxy;
299            vfs_inode_t * inode_ptr;
300            xptr_t        mapper_xp;
301            mapper_t    * mapper_ptr;
[656]302            xptr_t        page_xp;
[580]303
[623]304            char          kbuf[CONFIG_VFS_MAX_PATH_LENGTH];
[611]305
[623]306            char     * path    = (char *)arg0;
307            uint32_t   page_id = (uint32_t)arg1;
308            uint32_t   nbytes  = (uint32_t)arg2;
[611]309
[623]310            // check pathname length
311            if( hal_strlen_from_uspace( path ) >= CONFIG_VFS_MAX_PATH_LENGTH )
312            {
[611]313
314#if DEBUG_SYSCALLS_ERROR
315printk("\n[ERROR] in %s for MAPPER : pathname too long\n",
316 __FUNCTION__ );
317#endif
[656]318                this->errno = EINVAL;
[623]319                return -1;
320            }
[611]321
[656]322            // check nbytes
323            if( nbytes >= 4096 )
324            {
325
326#if DEBUG_SYSCALLS_ERROR
327printk("\n[ERROR] in %s for MAPPER : nbytes cannot be larger than 4096\n",
328 __FUNCTION__ );
329#endif
330                this->errno = EINVAL;
331                return -1;
332            }
333           
[623]334            // copy pathname in kernel space
[637]335            hal_strcpy_from_uspace( XPTR( local_cxy , kbuf ),
336                                    path,
337                                    CONFIG_VFS_MAX_PATH_LENGTH );
[611]338
[623]339            // compute root inode for pathname
340            if( kbuf[0] == '/' )                        // absolute path
341            {
342                // use extended pointer on VFS root inode
343                root_inode_xp = process->vfs_root_xp;
344            }
345            else                                        // relative path
346            {
347                // get cluster and local pointer on reference process
348                xptr_t      ref_xp  = process->ref_xp;
349                process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
350                cxy_t       ref_cxy = GET_CXY( ref_xp );
[611]351
[623]352                // get extended pointer on CWD inode
353                root_inode_xp = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->cwd_xp ) );
354            }
[611]355
[623]356            // get extended pointer on target inode
357            error = vfs_lookup( root_inode_xp,
358                                kbuf,
359                                0,
360                                &inode_xp,
361                                NULL );
362            if( error )
363                {
[611]364
365#if DEBUG_SYSCALLS_ERROR
366printk("\n[ERROR] in %s for MAPPER : cannot found inode <%s>\n",
367__FUNCTION__ , kbuf );
368#endif
[623]369                        this->errno = ENFILE;
370                        return -1;
371                }
[611]372   
[623]373            // get target inode cluster and local pointer
374            inode_cxy = GET_CXY( inode_xp );
375            inode_ptr = GET_PTR( inode_xp );
[611]376
[623]377            // get extended pointer on target mapper
378            mapper_ptr = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
379            mapper_xp  = XPTR( inode_cxy , mapper_ptr );
[611]380
[656]381            // get extended pointer on target page
[657]382            page_xp = mapper_get_page( mapper_xp , page_id );
[611]383
[656]384            if( page_xp == XPTR_NULL )
[623]385                {
[611]386
387#if DEBUG_SYSCALLS_ERROR
[656]388printk("\n[ERROR] in %s for MAPPER : cannot get page %d\n",
[611]389__FUNCTION__ , page_id );
390#endif
[623]391                        this->errno = ENFILE;
392                        return -1;
393                }
[440]394
[656]395            // display mapper
396            mapper_display_page( mapper_xp , page_xp , nbytes );
397
398
[623]399            break;
400        }
401        /////////////////////
402        case DISPLAY_BARRIER:
403        {
404            // get target process PID
405            pid_t pid = (pid_t)arg0;
406
407            // get pointers on owner process
408            xptr_t      process_xp  = cluster_get_reference_process_from_pid( pid );
409            process_t * process_ptr = GET_PTR( process_xp );
410            cxy_t       process_cxy = GET_CXY( process_xp );
411
412            if( process_xp == XPTR_NULL )
413            {
414
[440]415#if DEBUG_SYSCALLS_ERROR
[623]416printk("\n[ERROR] in %s for BARRIER : process %x not found\n",
417__FUNCTION__ , pid );
418#endif
419                this->errno = EINVAL;
420                return -1;
421            }
422
423            // get extended pointer on root of list of barriers
424            xptr_t root_xp = XPTR( process_cxy , &process_ptr->barrier_root );
425
426            if( xlist_is_empty( root_xp ) )
427            {
428
429#if DEBUG_SYSCALLS_ERROR
430printk("\n[ERROR] in %s for BARRIER : no registered barrier in process %x\n",
431__FUNCTION__ , pid );
432#endif
433                this->errno = EINVAL;
434                return -1;
435            }
436
437            // get extended pointer on first registered generic barrier descriptor
438            xptr_t gen_barrier_xp  = XLIST_FIRST( root_xp , generic_barrier_t , list );
439
440            // display barrier state
441            generic_barrier_display( gen_barrier_xp );
442
443            break;
444        }
[626]445        /////////////////
446        case DISPLAY_FAT:
447        {
[657]448            uint32_t  slots = (uint32_t)arg1;
[626]449
[657]450            if( slots > 1024 )
[626]451                {
452
453#if DEBUG_SYSCALLS_ERROR
[657]454printk("\n[ERROR] in %s for FAT : nb_slots larger than 1024\n",
[626]455__FUNCTION__ );
456#endif
457                        this->errno = EINVAL;
458                        return -1;
459                }
460
[657]461            if( slots == 0 )  // display fat context in cluster cxy
[626]462            {
463                uint32_t  cxy = (uint32_t)arg0;
464
[637]465                if( cluster_is_active( cxy ) == false ) 
[626]466                {
467
468#if DEBUG_SYSCALLS_ERROR
469printk("\n[ERROR] in %s for FAT : illegal cxy argument %x\n",
470__FUNCTION__ , cxy );
471#endif
472                     this->errno = EINVAL;
473                     return -1;
474                }
475
476                fatfs_display_ctx( cxy );
477            }
[657]478            else                  // display nb_slots in page
[626]479            {                       
[657]480                uint32_t min  = (uint32_t)arg0;
[626]481
[657]482                fatfs_display_fat( min , slots );
[626]483            }
484
485            break;
486        }
[623]487        ////////
488        default: 
489        {
490
491#if DEBUG_SYSCALLS_ERROR
[580]492printk("\n[ERROR] in %s : undefined display type %d\n",
493        __FUNCTION__ , type );
[440]494#endif
[623]495            this->errno = EINVAL;
496            return -1;
497        }
498    }  // end switch on type
[421]499
[594]500#if (DEBUG_SYS_DISPLAY || CONFIG_INSTRUMENTATION_SYSCALLS)
501uint64_t     tm_end = hal_get_cycles();
502#endif
503
[438]504#if DEBUG_SYS_DISPLAY
505if( DEBUG_SYS_DISPLAY < tm_end )
[619]506printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
[594]507__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
[433]508#endif
509
[594]510#if CONFIG_INSTRUMENTATION_SYSCALLS
511hal_atomic_add( &syscalls_cumul_cost[SYS_DISPLAY] , tm_end - tm_start );
512hal_atomic_add( &syscalls_occurences[SYS_DISPLAY] , 1 );
513#endif
514
[433]515    return 0;
516
517}  // end sys_display()
Note: See TracBrowser for help on using the repository browser.