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

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

1) introduce a dev_ioc_sync_write() function in IOC API,

to improve the DEVFS synchronous update.

2) fix a big bug in both the user_dir_create() and user_dir_destroy()

functions: add an extended pointer on the reference client process
in the function's arguments.

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