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

Last change on this file since 628 was 626, checked in by alain, 6 years ago

This version has been tested on the sort multithreaded application
for TSAR_IOB architectures ranging from 1 to 8 clusters.
It fixes three bigs bugs:
1) the dev_ioc device API has been modified: the dev_ioc_sync_read()
and dev_ioc_sync_write() function use now extended pointers on the
kernel buffer to access a mapper stored in any cluster.
2) the hal_uspace API has been modified: the hal_copy_to_uspace()
and hal_copy_from_uspace() functions use now a (cxy,ptr) couple
to identify the target buffer (equivalent to an extended pointer.
3) an implementation bug has been fixed in the assembly code contained
in the hal_copy_to_uspace() and hal_copy_from_uspace() functions.

File size: 14.2 KB
RevLine 
[421]1/*
2 * sys_display.c - display the current state of a kernel structure on TXT0
3 *
[624]4 * Author    Alain Greiner (2016,2017,2018, 2019)
[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
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 );
151                if( process_xp == XPTR_NULL )
152            {
[440]153
154#if DEBUG_SYSCALLS_ERROR
[580]155printk("\n[ERROR] in %s for VMM : process %x in cluster %x not found\n",
156__FUNCTION__ , pid , cxy );
[440]157#endif
[623]158                this->errno = EINVAL;
159                return -1;
160            }
[421]161
[623]162            // get local pointer on process
163            process_t * process = (process_t *)GET_PTR( process_xp );
[421]164
[623]165            // call kernel function
166            if( cxy == local_cxy )
167            {
[624]168                    hal_vmm_display( process , true );
[623]169            }
170            else
171            {
[624]172                rpc_hal_vmm_display_client( cxy , process , true );
[623]173            }
174
175            break;
[421]176        }
[623]177        ///////////////////
178        case DISPLAY_SCHED:
[421]179        {
[623]180            cxy_t cxy = (cxy_t)arg0;
181            lid_t lid = (lid_t)arg1;
[421]182
[623]183            // check cxy argument
184                if( cluster_is_undefined( cxy ) ) 
185            {
[440]186
187#if DEBUG_SYSCALLS_ERROR
[580]188printk("\n[ERROR] in %s for SCHED : illegal cxy argument %x\n",
189__FUNCTION__ , cxy );
[440]190#endif
[623]191                this->errno = EINVAL;
192                return -1;
193            }
[421]194
[623]195            // check lid argument
196            if( lid >= LOCAL_CLUSTER->cores_nr )
197            {
[440]198
199#if DEBUG_SYSCALLS_ERROR
[580]200printk("\n[ERROR] in %s for SCHED : illegal lid argument %x\n",
201__FUNCTION__ , lid );
[440]202#endif
[623]203                this->errno = EINVAL;
204                return -1;
205            }
[421]206
[623]207            if( cxy == local_cxy )
208            {
209                    sched_display( lid );
210            }
211            else
212            {
213                sched_remote_display( cxy , lid );
214            }
215
216            break;
[421]217        }
[623]218        ///////////////////////////////
219        case DISPLAY_CLUSTER_PROCESSES:
[421]220        {
[623]221            cxy_t  cxy   = (cxy_t)arg0;
222            bool_t owned = (bool_t)arg1;
[421]223
[623]224            // check cxy argument
225                if( cluster_is_undefined( cxy ) )
226            {
[440]227
228#if DEBUG_SYSCALLS_ERROR
[580]229printk("\n[ERROR] in %s for CLUSTER_PROCESSES : illegal cxy argument %x\n",
230__FUNCTION__ , cxy );
[440]231#endif
[623]232                this->errno = EINVAL;
233                return -1;
234            }
235
236            cluster_processes_display( cxy , owned );
237
238            break;
[433]239        }
[623]240        /////////////////
241        case DISPLAY_VFS:
242        {
243            vfs_display( process->vfs_root_xp );
[421]244
[623]245            break;
246        }
247        ///////////////////
248        case DISPLAY_CHDEV:
249        {
250            chdev_dir_display();
[435]251
[623]252            break;
253        }
254        ///////////////////////////
255        case DISPLAY_TXT_PROCESSES:
[435]256        {
[623]257            uint32_t txt_id = (uint32_t)arg0;
[440]258
[623]259            // check argument
260                if( txt_id >= LOCAL_CLUSTER->nb_txt_channels )
261            {
262
[440]263#if DEBUG_SYSCALLS_ERROR
[580]264printk("\n[ERROR] in %s for TXT_PROCESSES : illegal txt_id argument %d\n",
265__FUNCTION__ , txt_id );
[440]266#endif
[623]267                this->errno = EINVAL;
268                return -1;
269            }
[435]270
[623]271            process_txt_display( txt_id );
[580]272
[623]273            break;
274        }
275        //////////////////
276        case DISPLAY_DQDT:
277        {
278            dqdt_display();
[580]279
[623]280            break;
281        }
282        ///////////////////////
283        case DISPLAY_BUSYLOCKS:
[580]284        {
[623]285            pid_t   pid   = (pid_t)arg0;
286            trdid_t trdid = (trdid_t)arg1;
[580]287
[623]288            // get extended pointer on target thread
289            xptr_t thread_xp = thread_get_xptr( pid , trdid );
290
291            if( thread_xp == XPTR_NULL )
292            {
293
[580]294#if DEBUG_SYSCALLS_ERROR
[594]295printk("\n[ERROR] in %s for BUSYLOCKS : thread[%x,%x] not found\n",
296__FUNCTION__ , pid, trdid );
[580]297#endif
[623]298                this->errno = EINVAL;
299                return -1;
300            }
301
302            thread_display_busylocks( thread_xp , __FUNCTION__ );
303
304            break;
[580]305        }
[623]306        ////////////////////
307        case DISPLAY_MAPPER:
308        {
309            xptr_t        root_inode_xp;
310            xptr_t        inode_xp;
311            cxy_t         inode_cxy;
312            vfs_inode_t * inode_ptr;
313            xptr_t        mapper_xp;
314            mapper_t    * mapper_ptr;
[580]315
[623]316            char          kbuf[CONFIG_VFS_MAX_PATH_LENGTH];
[611]317
[623]318            char     * path    = (char *)arg0;
319            uint32_t   page_id = (uint32_t)arg1;
320            uint32_t   nbytes  = (uint32_t)arg2;
[611]321
[623]322            // check pathname length
323            if( hal_strlen_from_uspace( path ) >= CONFIG_VFS_MAX_PATH_LENGTH )
324            {
[611]325
326#if DEBUG_SYSCALLS_ERROR
327printk("\n[ERROR] in %s for MAPPER : pathname too long\n",
328 __FUNCTION__ );
329#endif
[623]330                this->errno = ENFILE;
331                return -1;
332            }
[611]333
[623]334            // copy pathname in kernel space
335            hal_strcpy_from_uspace( kbuf , path , CONFIG_VFS_MAX_PATH_LENGTH );
[611]336
[623]337            // compute root inode for pathname
338            if( kbuf[0] == '/' )                        // absolute path
339            {
340                // use extended pointer on VFS root inode
341                root_inode_xp = process->vfs_root_xp;
342            }
343            else                                        // relative path
344            {
345                // get cluster and local pointer on reference process
346                xptr_t      ref_xp  = process->ref_xp;
347                process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
348                cxy_t       ref_cxy = GET_CXY( ref_xp );
[611]349
[623]350                // get extended pointer on CWD inode
351                root_inode_xp = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->cwd_xp ) );
352            }
[611]353
[623]354            // get extended pointer on target inode
355            error = vfs_lookup( root_inode_xp,
356                                kbuf,
357                                0,
358                                &inode_xp,
359                                NULL );
360            if( error )
361                {
[611]362
363#if DEBUG_SYSCALLS_ERROR
364printk("\n[ERROR] in %s for MAPPER : cannot found inode <%s>\n",
365__FUNCTION__ , kbuf );
366#endif
[623]367                        this->errno = ENFILE;
368                        return -1;
369                }
[611]370   
[623]371            // get target inode cluster and local pointer
372            inode_cxy = GET_CXY( inode_xp );
373            inode_ptr = GET_PTR( inode_xp );
[611]374
[623]375            // get extended pointer on target mapper
376            mapper_ptr = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
377            mapper_xp  = XPTR( inode_cxy , mapper_ptr );
[611]378
[623]379            // display mapper
380            error = mapper_display_page( mapper_xp , page_id , nbytes );
[611]381
[623]382            if( error )
383                {
[611]384
385#if DEBUG_SYSCALLS_ERROR
386printk("\n[ERROR] in %s for MAPPER : cannot display page %d\n",
387__FUNCTION__ , page_id );
388#endif
[623]389                        this->errno = ENFILE;
390                        return -1;
391                }
[440]392
[623]393            break;
394        }
395        /////////////////////
396        case DISPLAY_BARRIER:
397        {
398            // get target process PID
399            pid_t pid = (pid_t)arg0;
400
401            // get pointers on owner process
402            xptr_t      process_xp  = cluster_get_reference_process_from_pid( pid );
403            process_t * process_ptr = GET_PTR( process_xp );
404            cxy_t       process_cxy = GET_CXY( process_xp );
405
406            if( process_xp == XPTR_NULL )
407            {
408
[440]409#if DEBUG_SYSCALLS_ERROR
[623]410printk("\n[ERROR] in %s for BARRIER : process %x not found\n",
411__FUNCTION__ , pid );
412#endif
413                this->errno = EINVAL;
414                return -1;
415            }
416
417            // get extended pointer on root of list of barriers
418            xptr_t root_xp = XPTR( process_cxy , &process_ptr->barrier_root );
419
420            if( xlist_is_empty( root_xp ) )
421            {
422
423#if DEBUG_SYSCALLS_ERROR
424printk("\n[ERROR] in %s for BARRIER : no registered barrier in process %x\n",
425__FUNCTION__ , pid );
426#endif
427                this->errno = EINVAL;
428                return -1;
429            }
430
431            // get extended pointer on first registered generic barrier descriptor
432            xptr_t gen_barrier_xp  = XLIST_FIRST( root_xp , generic_barrier_t , list );
433
434            // display barrier state
435            generic_barrier_display( gen_barrier_xp );
436
437            break;
438        }
[626]439        /////////////////
440        case DISPLAY_FAT:
441        {
442            uint32_t  entries = (uint32_t)arg1;
443
444            if( entries > 4096 )
445                {
446
447#if DEBUG_SYSCALLS_ERROR
448printk("\n[ERROR] in %s for FAT : nb_entries larger than 4096\n",
449__FUNCTION__ );
450#endif
451                        this->errno = EINVAL;
452                        return -1;
453                }
454
455            if( entries == 0 )  // display fat context in cluster cxy
456            {
457                uint32_t  cxy = (uint32_t)arg0;
458
459                if( cluster_is_undefined( cxy ) ) 
460                {
461
462#if DEBUG_SYSCALLS_ERROR
463printk("\n[ERROR] in %s for FAT : illegal cxy argument %x\n",
464__FUNCTION__ , cxy );
465#endif
466                     this->errno = EINVAL;
467                     return -1;
468                }
469
470                fatfs_display_ctx( cxy );
471            }
472            else                  // display nb_entries in page
473            {                       
474                uint32_t page = (uint32_t)arg0;
475
476                fatfs_display_fat( page , entries );
477            }
478
479            break;
480        }
[623]481        ////////
482        default: 
483        {
484
485#if DEBUG_SYSCALLS_ERROR
[580]486printk("\n[ERROR] in %s : undefined display type %d\n",
487        __FUNCTION__ , type );
[440]488#endif
[623]489            this->errno = EINVAL;
490            return -1;
491        }
492    }  // end switch on type
[421]493
[594]494#if (DEBUG_SYS_DISPLAY || CONFIG_INSTRUMENTATION_SYSCALLS)
495uint64_t     tm_end = hal_get_cycles();
496#endif
497
[438]498#if DEBUG_SYS_DISPLAY
499if( DEBUG_SYS_DISPLAY < tm_end )
[619]500printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
[594]501__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
[433]502#endif
503
[594]504#if CONFIG_INSTRUMENTATION_SYSCALLS
505hal_atomic_add( &syscalls_cumul_cost[SYS_DISPLAY] , tm_end - tm_start );
506hal_atomic_add( &syscalls_occurences[SYS_DISPLAY] , 1 );
507#endif
508
[433]509    return 0;
510
511}  // end sys_display()
Note: See TracBrowser for help on using the repository browser.