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

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

Fix several bugs to use the instruction MMU in kernel mode
in replacement of the instruction address extension register,
and remove the "kentry" segment.

This version is running on the tsar_generic_iob" platform.

One interesting bug: the cp0_ebase defining the kernel entry point
(for interrupts, exceptions and syscalls) must be initialized
early in kernel_init(), because the VFS initialisation done by
kernel_ini() uses RPCs, and RPCs uses Inter-Processor-Interrup.

File size: 13.1 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";
[612]58    else                                         return "undefined";
[443]59}
60#endif
61
[421]62/////////////////////////////
63int sys_display( reg_t  type,
64                 reg_t  arg0,
[611]65                 reg_t  arg1,
66                 reg_t  arg2 )
[421]67{
[433]68
[440]69    error_t     error;
70    vseg_t    * vseg;
71
72    thread_t  * this    = CURRENT_THREAD;
73    process_t * process = this->process;
74
[594]75#if (DEBUG_SYS_DISPLAY || CONFIG_INSTRUMENTATION_SYSCALLS)
76uint64_t     tm_start = hal_get_cycles();
77#endif
78
[438]79#if DEBUG_SYS_DISPLAY
[433]80tm_start = hal_get_cycles();
[438]81if( DEBUG_SYS_DISPLAY < tm_start )
[619]82printk("\n[%s] thread[%x,%x] enter / type  %s / cycle = %d\n",
[594]83__FUNCTION__, process->pid, this->trdid, display_type_str(type), (uint32_t)tm_start );
[433]84#endif
85
[623]86    switch( type )
[421]87    {
[623]88        ////////////////////
89        case DISPLAY_STRING:
90        {
91            char      kbuf[512];
92            uint32_t  length;
[421]93
[623]94            char    * string = (char *)arg0;
[440]95
[623]96            // check string in user space
97            error = vmm_get_vseg( process , (intptr_t)arg0 , &vseg );
[440]98
[623]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 );
[440]112
[623]113            if( length >= 512 )
114            {
[440]115
116#if DEBUG_SYSCALLS_ERROR
[580]117printk("\n[ERROR] in %s for STRING : string length %d too large\n",
118__FUNCTION__ , length );
[440]119#endif
[623]120                this->errno = EINVAL;
121                return -1;
122            }
[421]123
[623]124            // copy string to kernel space
125            hal_strcpy_from_uspace( kbuf , string , 512 );
[421]126
[623]127            // print message on TXT0 kernel terminal
128            printk("\n%s / cycle %d\n", kbuf, (uint32_t)hal_get_cycles() );
[421]129
[623]130            break;
131        }
132        /////////////////
133        case DISPLAY_VMM:
[443]134        {
[623]135            cxy_t cxy = (cxy_t)arg0;
136            pid_t pid = (pid_t)arg1;
[421]137
[623]138            // check cxy argument
139                if( cluster_is_undefined( cxy ) ) 
140            {
141
[443]142#if DEBUG_SYSCALLS_ERROR
[580]143printk("\n[ERROR] in %s for VMM : process %x in cluster %x not found\n",
144__FUNCTION__ , pid , cxy );
[443]145#endif
[623]146                this->errno = EINVAL;
147                return -1;
148            }
[443]149
[623]150            // get extended pointer on process PID in cluster CXY
151            xptr_t process_xp = cluster_get_process_from_pid_in_cxy( cxy , pid );
[443]152
[623]153                if( process_xp == XPTR_NULL )
154            {
[440]155
156#if DEBUG_SYSCALLS_ERROR
[580]157printk("\n[ERROR] in %s for VMM : process %x in cluster %x not found\n",
158__FUNCTION__ , pid , cxy );
[440]159#endif
[623]160                this->errno = EINVAL;
161                return -1;
162            }
[421]163
[623]164            // get local pointer on process
165            process_t * process = (process_t *)GET_PTR( process_xp );
[421]166
[623]167            // call kernel function
168            if( cxy == local_cxy )
169            {
[624]170                    hal_vmm_display( process , true );
[623]171            }
172            else
173            {
[624]174                rpc_hal_vmm_display_client( cxy , process , true );
[623]175            }
176
177            break;
[421]178        }
[623]179        ///////////////////
180        case DISPLAY_SCHED:
[421]181        {
[623]182            cxy_t cxy = (cxy_t)arg0;
183            lid_t lid = (lid_t)arg1;
[421]184
[623]185            // check cxy argument
186                if( cluster_is_undefined( cxy ) ) 
187            {
[440]188
189#if DEBUG_SYSCALLS_ERROR
[580]190printk("\n[ERROR] in %s for SCHED : illegal cxy argument %x\n",
191__FUNCTION__ , cxy );
[440]192#endif
[623]193                this->errno = EINVAL;
194                return -1;
195            }
[421]196
[623]197            // check lid argument
198            if( lid >= LOCAL_CLUSTER->cores_nr )
199            {
[440]200
201#if DEBUG_SYSCALLS_ERROR
[580]202printk("\n[ERROR] in %s for SCHED : illegal lid argument %x\n",
203__FUNCTION__ , lid );
[440]204#endif
[623]205                this->errno = EINVAL;
206                return -1;
207            }
[421]208
[623]209            if( cxy == local_cxy )
210            {
211                    sched_display( lid );
212            }
213            else
214            {
215                sched_remote_display( cxy , lid );
216            }
217
218            break;
[421]219        }
[623]220        ///////////////////////////////
221        case DISPLAY_CLUSTER_PROCESSES:
[421]222        {
[623]223            cxy_t  cxy   = (cxy_t)arg0;
224            bool_t owned = (bool_t)arg1;
[421]225
[623]226            // check cxy argument
227                if( cluster_is_undefined( cxy ) )
228            {
[440]229
230#if DEBUG_SYSCALLS_ERROR
[580]231printk("\n[ERROR] in %s for CLUSTER_PROCESSES : illegal cxy argument %x\n",
232__FUNCTION__ , cxy );
[440]233#endif
[623]234                this->errno = EINVAL;
235                return -1;
236            }
237
238            cluster_processes_display( cxy , owned );
239
240            break;
[433]241        }
[623]242        /////////////////
243        case DISPLAY_VFS:
244        {
245            vfs_display( process->vfs_root_xp );
[421]246
[623]247            break;
248        }
249        ///////////////////
250        case DISPLAY_CHDEV:
251        {
252            chdev_dir_display();
[435]253
[623]254            break;
255        }
256        ///////////////////////////
257        case DISPLAY_TXT_PROCESSES:
[435]258        {
[623]259            uint32_t txt_id = (uint32_t)arg0;
[440]260
[623]261            // check argument
262                if( txt_id >= LOCAL_CLUSTER->nb_txt_channels )
263            {
264
[440]265#if DEBUG_SYSCALLS_ERROR
[580]266printk("\n[ERROR] in %s for TXT_PROCESSES : illegal txt_id argument %d\n",
267__FUNCTION__ , txt_id );
[440]268#endif
[623]269                this->errno = EINVAL;
270                return -1;
271            }
[435]272
[623]273            process_txt_display( txt_id );
[580]274
[623]275            break;
276        }
277        //////////////////
278        case DISPLAY_DQDT:
279        {
280            dqdt_display();
[580]281
[623]282            break;
283        }
284        ///////////////////////
285        case DISPLAY_BUSYLOCKS:
[580]286        {
[623]287            pid_t   pid   = (pid_t)arg0;
288            trdid_t trdid = (trdid_t)arg1;
[580]289
[623]290            // get extended pointer on target thread
291            xptr_t thread_xp = thread_get_xptr( pid , trdid );
292
293            if( thread_xp == XPTR_NULL )
294            {
295
[580]296#if DEBUG_SYSCALLS_ERROR
[594]297printk("\n[ERROR] in %s for BUSYLOCKS : thread[%x,%x] not found\n",
298__FUNCTION__ , pid, trdid );
[580]299#endif
[623]300                this->errno = EINVAL;
301                return -1;
302            }
303
304            thread_display_busylocks( thread_xp , __FUNCTION__ );
305
306            break;
[580]307        }
[623]308        ////////////////////
309        case DISPLAY_MAPPER:
310        {
311            xptr_t        root_inode_xp;
312            xptr_t        inode_xp;
313            cxy_t         inode_cxy;
314            vfs_inode_t * inode_ptr;
315            xptr_t        mapper_xp;
316            mapper_t    * mapper_ptr;
[580]317
[623]318            char          kbuf[CONFIG_VFS_MAX_PATH_LENGTH];
[611]319
[623]320            char     * path    = (char *)arg0;
321            uint32_t   page_id = (uint32_t)arg1;
322            uint32_t   nbytes  = (uint32_t)arg2;
[611]323
[623]324            // check pathname length
325            if( hal_strlen_from_uspace( path ) >= CONFIG_VFS_MAX_PATH_LENGTH )
326            {
[611]327
328#if DEBUG_SYSCALLS_ERROR
329printk("\n[ERROR] in %s for MAPPER : pathname too long\n",
330 __FUNCTION__ );
331#endif
[623]332                this->errno = ENFILE;
333                return -1;
334            }
[611]335
[623]336            // copy pathname in kernel space
337            hal_strcpy_from_uspace( kbuf , path , 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
[623]381            // display mapper
382            error = mapper_display_page( mapper_xp , page_id , nbytes );
[611]383
[623]384            if( error )
385                {
[611]386
387#if DEBUG_SYSCALLS_ERROR
388printk("\n[ERROR] in %s for MAPPER : cannot display page %d\n",
389__FUNCTION__ , page_id );
390#endif
[623]391                        this->errno = ENFILE;
392                        return -1;
393                }
[440]394
[623]395            break;
396        }
397        /////////////////////
398        case DISPLAY_BARRIER:
399        {
400            // get target process PID
401            pid_t pid = (pid_t)arg0;
402
403            // get pointers on owner process
404            xptr_t      process_xp  = cluster_get_reference_process_from_pid( pid );
405            process_t * process_ptr = GET_PTR( process_xp );
406            cxy_t       process_cxy = GET_CXY( process_xp );
407
408            if( process_xp == XPTR_NULL )
409            {
410
[440]411#if DEBUG_SYSCALLS_ERROR
[623]412printk("\n[ERROR] in %s for BARRIER : process %x not found\n",
413__FUNCTION__ , pid );
414#endif
415                this->errno = EINVAL;
416                return -1;
417            }
418
419            // get extended pointer on root of list of barriers
420            xptr_t root_xp = XPTR( process_cxy , &process_ptr->barrier_root );
421
422            if( xlist_is_empty( root_xp ) )
423            {
424
425#if DEBUG_SYSCALLS_ERROR
426printk("\n[ERROR] in %s for BARRIER : no registered barrier in process %x\n",
427__FUNCTION__ , pid );
428#endif
429                this->errno = EINVAL;
430                return -1;
431            }
432
433            // get extended pointer on first registered generic barrier descriptor
434            xptr_t gen_barrier_xp  = XLIST_FIRST( root_xp , generic_barrier_t , list );
435
436            // display barrier state
437            generic_barrier_display( gen_barrier_xp );
438
439            break;
440        }
441        ////////
442        default: 
443        {
444
445#if DEBUG_SYSCALLS_ERROR
[580]446printk("\n[ERROR] in %s : undefined display type %d\n",
447        __FUNCTION__ , type );
[440]448#endif
[623]449            this->errno = EINVAL;
450            return -1;
451        }
452    }  // end switch on type
[421]453
[594]454#if (DEBUG_SYS_DISPLAY || CONFIG_INSTRUMENTATION_SYSCALLS)
455uint64_t     tm_end = hal_get_cycles();
456#endif
457
[438]458#if DEBUG_SYS_DISPLAY
459if( DEBUG_SYS_DISPLAY < tm_end )
[619]460printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
[594]461__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
[433]462#endif
463
[594]464#if CONFIG_INSTRUMENTATION_SYSCALLS
465hal_atomic_add( &syscalls_cumul_cost[SYS_DISPLAY] , tm_end - tm_start );
466hal_atomic_add( &syscalls_occurences[SYS_DISPLAY] , 1 );
467#endif
468
[433]469    return 0;
470
471}  // end sys_display()
Note: See TracBrowser for help on using the repository browser.