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

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

Introduce three new types of vsegs (KCODE,KDATA,KDEV)
to map the kernel vsegs in the process VSL and GPT.
This now used by both the TSAR and the I86 architectures.

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