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

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

Introduce sigificant modifs in VFS to support the <ls> command,
and the . and .. directories entries.

File size: 10.8 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>
[611]33#include <vfs.h>
34#include <mapper.h>
[421]35
[506]36#include <syscalls.h>
37
[443]38/////////////////////////////////////////////////////////////////////////////////
39// This static function returns a printable string for the type of display.
40/////////////////////////////////////////////////////////////////////////////////
[421]41
[443]42#if DEBUG_SYS_DISPLAY
43static char* display_type_str( uint32_t type )
44{
45    if     ( type == DISPLAY_STRING            ) return "STRING"; 
46    else if( type == DISPLAY_VMM               ) return "VMM"; 
47    else if( type == DISPLAY_SCHED             ) return "SCHED"; 
48    else if( type == DISPLAY_CLUSTER_PROCESSES ) return "CLUSTER_PROCESSES"; 
49    else if( type == DISPLAY_VFS               ) return "VFS"; 
50    else if( type == DISPLAY_CHDEV             ) return "CHDEV"; 
51    else if( type == DISPLAY_TXT_PROCESSES     ) return "TXT_PROCESSES"; 
[580]52    else if( type == DISPLAY_DQDT              ) return "DQDT";
53    else if( type == DISPLAY_BUSYLOCKS         ) return "BUSYLOCKS"; 
[443]54}
55#endif
56
[421]57/////////////////////////////
58int sys_display( reg_t  type,
59                 reg_t  arg0,
[611]60                 reg_t  arg1,
61                 reg_t  arg2 )
[421]62{
[433]63
[440]64    error_t     error;
65    vseg_t    * vseg;
66
67    thread_t  * this    = CURRENT_THREAD;
68    process_t * process = this->process;
69
[594]70#if (DEBUG_SYS_DISPLAY || CONFIG_INSTRUMENTATION_SYSCALLS)
71uint64_t     tm_start = hal_get_cycles();
72#endif
73
[438]74#if DEBUG_SYS_DISPLAY
[433]75tm_start = hal_get_cycles();
[438]76if( DEBUG_SYS_DISPLAY < tm_start )
[594]77printk("\n[DBG] %s : thread[%x,%x] enter / type  %s / cycle = %d\n",
78__FUNCTION__, process->pid, this->trdid, display_type_str(type), (uint32_t)tm_start );
[433]79#endif
80
[440]81    ////////////////////////////
[421]82    if( type == DISPLAY_STRING )
83    {
84        char      kbuf[256];
[433]85        uint32_t  length;
[421]86
87        char    * string = (char *)arg0;
[440]88
[421]89        // check string in user space
[440]90        error = vmm_get_vseg( process , (intptr_t)arg0 , &vseg );
91
92        if( error )
[433]93        {
[440]94
95#if DEBUG_SYSCALLS_ERROR
[580]96printk("\n[ERROR] in %s for STRING : string buffer %x unmapped\n",
97__FUNCTION__ , (intptr_t)arg0 );
[440]98#endif
99            this->errno = EINVAL;
[433]100            return -1;
101        }
[421]102
103        // ckeck string length
[433]104        length = hal_strlen_from_uspace( string );
[440]105
[433]106        if( length >= 256 )
107        {
[440]108
109#if DEBUG_SYSCALLS_ERROR
[580]110printk("\n[ERROR] in %s for STRING : string length %d too large\n",
111__FUNCTION__ , length );
[440]112#endif
113            this->errno = EINVAL;
[433]114            return -1;
115        }
[421]116
[440]117        // copy string to kernel space
[421]118        hal_strcpy_from_uspace( kbuf , string , 256 );
119
120        // print message on TXT0 kernel terminal
[440]121        printk("\n%s / cycle %d\n", kbuf, (uint32_t)hal_get_cycles() );
[421]122    }
[440]123    //////////////////////////////
[421]124    else if( type == DISPLAY_VMM )
125    {
[443]126        cxy_t cxy = (cxy_t)arg0;
127        pid_t pid = (pid_t)arg1;
[421]128
[443]129        // check cxy argument
130            if( cluster_is_undefined( cxy ) ) 
131        {
[421]132
[443]133#if DEBUG_SYSCALLS_ERROR
[580]134printk("\n[ERROR] in %s for VMM : process %x in cluster %x not found\n",
135__FUNCTION__ , pid , cxy );
[443]136#endif
137            this->errno = EINVAL;
138            return -1;
139        }
140
141        // get extended pointer on process PID in cluster CXY
142        xptr_t process_xp = cluster_get_process_from_pid_in_cxy( cxy , pid );
143
[433]144            if( process_xp == XPTR_NULL )
145        {
[440]146
147#if DEBUG_SYSCALLS_ERROR
[580]148printk("\n[ERROR] in %s for VMM : process %x in cluster %x not found\n",
149__FUNCTION__ , pid , cxy );
[440]150#endif
151            this->errno = EINVAL;
[433]152            return -1;
153        }
[421]154
[443]155        // get local pointer on process
156        process_t * process = (process_t *)GET_PTR( process_xp );
[421]157
158        // call kernel function
[443]159        if( cxy == local_cxy )
[421]160        {
[443]161                vmm_display( process , true );
[421]162        }
163        else
164        {
[443]165            rpc_vmm_display_client( cxy , process , true );
[421]166        }
167    }
[440]168    ////////////////////////////////
[421]169    else if( type == DISPLAY_SCHED )
170    {
171        cxy_t cxy = (cxy_t)arg0;
172        lid_t lid = (lid_t)arg1;
173
[440]174        // check cxy argument
[433]175            if( cluster_is_undefined( cxy ) ) 
176        {
[440]177
178#if DEBUG_SYSCALLS_ERROR
[580]179printk("\n[ERROR] in %s for SCHED : illegal cxy argument %x\n",
180__FUNCTION__ , cxy );
[440]181#endif
182            this->errno = EINVAL;
[433]183            return -1;
184        }
[421]185
[440]186        // check lid argument
[433]187        if( lid >= LOCAL_CLUSTER->cores_nr )
188        {
[440]189
190#if DEBUG_SYSCALLS_ERROR
[580]191printk("\n[ERROR] in %s for SCHED : illegal lid argument %x\n",
192__FUNCTION__ , lid );
[440]193#endif
194            this->errno = EINVAL;
[433]195            return -1;
196        }
[421]197
198        if( cxy == local_cxy )
199        {
200                sched_display( lid );
201        }
202        else
203        {
[450]204            sched_remote_display( cxy , lid );
[421]205        }
206    }
[440]207    ////////////////////////////////////////////
[435]208    else if( type == DISPLAY_CLUSTER_PROCESSES )
[421]209    {
[584]210        cxy_t  cxy   = (cxy_t)arg0;
211        bool_t owned = (bool_t)arg1;
[421]212
[440]213        // check cxy argument
[433]214            if( cluster_is_undefined( cxy ) )
215        {
[440]216
217#if DEBUG_SYSCALLS_ERROR
[580]218printk("\n[ERROR] in %s for CLUSTER_PROCESSES : illegal cxy argument %x\n",
219__FUNCTION__ , cxy );
[440]220#endif
221            this->errno = EINVAL;
[433]222            return -1;
223        }
[421]224
[584]225        cluster_processes_display( cxy , owned );
[421]226    }
[580]227    //////////////////////////////
228    else if( type == DISPLAY_VFS )
229    {
230        vfs_display( process->vfs_root_xp );
231    }
232    ////////////////////////////////
233    else if( type == DISPLAY_CHDEV )
234    {
235        chdev_dir_display();
236    }
[440]237    ////////////////////////////////////////
[435]238    else if( type == DISPLAY_TXT_PROCESSES )
239    {
240        uint32_t txt_id = (uint32_t)arg0;
241
242        // check argument
243            if( txt_id >= LOCAL_CLUSTER->nb_txt_channels )
244        {
[440]245
246#if DEBUG_SYSCALLS_ERROR
[580]247printk("\n[ERROR] in %s for TXT_PROCESSES : illegal txt_id argument %d\n",
248__FUNCTION__ , txt_id );
[440]249#endif
250            this->errno = EINVAL;
[435]251            return -1;
252        }
253
254        process_txt_display( txt_id );
255    }
[580]256    ///////////////////////////////
257    else if( type == DISPLAY_DQDT )
[421]258    {
[580]259        dqdt_display();
[421]260    }
[580]261    ////////////////////////////////////
262    else if( type == DISPLAY_BUSYLOCKS )
[421]263    {
[594]264        pid_t   pid   = (pid_t)arg0;
[580]265        trdid_t trdid = (trdid_t)arg1;
266
267        // get extended pointer on target thread
268        xptr_t thread_xp = thread_get_xptr( pid , trdid );
269
270        if( thread_xp == XPTR_NULL )
271        {
272
273#if DEBUG_SYSCALLS_ERROR
[594]274printk("\n[ERROR] in %s for BUSYLOCKS : thread[%x,%x] not found\n",
275__FUNCTION__ , pid, trdid );
[580]276#endif
277            this->errno = EINVAL;
278            return -1;
279        }
280
281        thread_display_busylocks( thread_xp );
[421]282    }
[611]283    /////////////////////////////////
284    else if( type == DISPLAY_MAPPER )
285    {
286        xptr_t        root_inode_xp;
287        xptr_t        inode_xp;
288        cxy_t         inode_cxy;
289        vfs_inode_t * inode_ptr;
290        xptr_t        mapper_xp;
291        mapper_t    * mapper_ptr;
292
293        char          kbuf[CONFIG_VFS_MAX_PATH_LENGTH];
294
295        char     * path    = (char *)arg0;
296        uint32_t   page_id = (uint32_t)arg1;
297        uint32_t   nbytes  = (uint32_t)arg2;
298
299        // check pathname length
300        if( hal_strlen_from_uspace( path ) >= CONFIG_VFS_MAX_PATH_LENGTH )
301        {
302
303#if DEBUG_SYSCALLS_ERROR
304printk("\n[ERROR] in %s for MAPPER : pathname too long\n",
305 __FUNCTION__ );
306#endif
307            this->errno = ENFILE;
308            return -1;
309        }
310
311        // copy pathname in kernel space
312        hal_strcpy_from_uspace( kbuf , path , CONFIG_VFS_MAX_PATH_LENGTH );
313
314        // compute root inode for pathname
315        if( kbuf[0] == '/' )                        // absolute path
316        {
317            // use extended pointer on VFS root inode
318            root_inode_xp = process->vfs_root_xp;
319        }
320        else                                        // relative path
321        {
322            // get cluster and local pointer on reference process
323            xptr_t      ref_xp  = process->ref_xp;
324            process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
325            cxy_t       ref_cxy = GET_CXY( ref_xp );
326
327            // use extended pointer on CWD inode
328            root_inode_xp = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->cwd_xp ) );
329        }
330
331        // get extended pointer on target inode
332        error = vfs_lookup( root_inode_xp,
333                            kbuf,
334                            0,
335                            &inode_xp,
336                            NULL );
337        if( error )
338            {
339
340#if DEBUG_SYSCALLS_ERROR
341printk("\n[ERROR] in %s for MAPPER : cannot found inode <%s>\n",
342__FUNCTION__ , kbuf );
343#endif
344                    this->errno = ENFILE;
345                    return -1;
346            }
347   
348        // get target inode cluster and local pointer
349        inode_cxy = GET_CXY( inode_xp );
350        inode_ptr = GET_PTR( inode_xp );
351
352        // get extended pointer on target mapper
353        mapper_ptr = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
354        mapper_xp  = XPTR( inode_cxy , mapper_ptr );
355
356        // display mapper
357        error = mapper_display_page( mapper_xp , page_id , nbytes , kbuf );
358
359        if( error )
360            {
361
362#if DEBUG_SYSCALLS_ERROR
363printk("\n[ERROR] in %s for MAPPER : cannot display page %d\n",
364__FUNCTION__ , page_id );
365#endif
366                    this->errno = ENFILE;
367                    return -1;
368            }
369    }
[440]370    ////
[433]371    else 
372    {
[440]373
374#if DEBUG_SYSCALLS_ERROR
[580]375printk("\n[ERROR] in %s : undefined display type %d\n",
376        __FUNCTION__ , type );
[440]377#endif
378        this->errno = EINVAL;
[433]379        return -1;
380    }
[421]381
[594]382#if (DEBUG_SYS_DISPLAY || CONFIG_INSTRUMENTATION_SYSCALLS)
383uint64_t     tm_end = hal_get_cycles();
384#endif
385
[438]386#if DEBUG_SYS_DISPLAY
387if( DEBUG_SYS_DISPLAY < tm_end )
[594]388printk("\n[DBG] %s : thread[%x,%x] exit / cycle %d\n",
389__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
[433]390#endif
391
[594]392#if CONFIG_INSTRUMENTATION_SYSCALLS
393hal_atomic_add( &syscalls_cumul_cost[SYS_DISPLAY] , tm_end - tm_start );
394hal_atomic_add( &syscalls_occurences[SYS_DISPLAY] , 1 );
395#endif
396
[433]397    return 0;
398
399}  // end sys_display()
Note: See TracBrowser for help on using the repository browser.