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

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

This version is a major evolution: The physical memory allocators,
defined in the kmem.c, ppm.c, and kcm.c files have been modified
to support remote accesses. The RPCs that were previously user
to allocate physical memory in a remote cluster have been removed.
This has been done to cure a dead-lock in case of concurrent page-faults.

This version 2.2 has been tested on a (4 clusters / 2 cores per cluster)
TSAR architecture, for both the "sort" and the "fft" applications.

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