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

Last change on this file since 625 was 625, checked in by alain, 3 years ago

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

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