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

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

Fix several bugs to use the instruction MMU in kernel mode
in replacement of the instruction address extension register,
and remove the "kentry" segment.

This version is running on the tsar_generic_iob" platform.

One interesting bug: the cp0_ebase defining the kernel entry point
(for interrupts, exceptions and syscalls) must be initialized
early in kernel_init(), because the VFS initialisation done by
kernel_ini() uses RPCs, and RPCs uses Inter-Processor-Interrup.

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