source: trunk/kernel/kern/printk.c @ 422

Last change on this file since 422 was 408, checked in by alain, 7 years ago

Fix several bugs in the fork() syscall.

File size: 15.9 KB
Line 
1/*
2 * printk.c - Kernel Log & debug messages API implementation.
3 *
4 * authors  Alain Greiner (2016)
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_types.h>
25#include <hal_irqmask.h>
26#include <hal_special.h>
27#include <dev_txt.h>
28#include <remote_spinlock.h>
29#include <cluster.h>
30#include <chdev.h>
31#include <printk.h>
32
33///////////////////////////////////////////////////////////////////////////////////
34//      Extern variables
35///////////////////////////////////////////////////////////////////////////////////
36
37extern chdev_directory_t  chdev_dir;  // defined in chdev.h / allocated in kernel_init.c
38
39/////////////////////////////////////
40uint32_t snprintf( char     * string,
41                   uint32_t   length,
42                   char     * format, ... )
43{
44
45#define TO_STREAM(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0);
46
47    va_list    args;      // printf arguments
48    uint32_t   ps;        // write pointer to the string buffer
49
50    ps = 0;   
51    va_start( args , format );
52
53xprintf_text:
54
55    while ( *format != 0 ) 
56    {
57
58        if (*format == '%')   // copy argument to string
59        {
60            format++;
61            goto xprintf_arguments;
62        }
63        else                  // copy one char to string
64        {
65            TO_STREAM( *format );
66            format++;
67        }
68    }
69
70    va_end( args );
71   
72    // add terminating NUL chracter
73    TO_STREAM( 0 );
74    return ps;
75
76xprintf_arguments:
77
78    {
79        char              buf[30];    // buffer to display one number
80        char *            pbuf;       // pointer on first char to display
81        uint32_t          len = 0;    // number of char to display
82        static const char HexaTab[] = "0123456789ABCDEF";
83        uint32_t          i;
84       
85        // Ignore fields width and precision
86        for ( ; (*format >= '0' && *format <= '9') || (*format == '.') ; format++ );
87
88        switch (*format) 
89        {
90            case ('c'):             // char conversion
91            {
92                int val = va_arg( args, int );
93                buf[0] = val;
94                pbuf   = buf;
95                len    = 1;
96                break;
97            }
98            case ('d'):             // decimal signed integer
99            {
100                int val = va_arg( args, int );
101                if (val < 0) 
102                {
103                    TO_STREAM( '-' );
104                    val = -val;
105                }
106                for(i = 0; i < 10; i++) 
107                {
108
109                    buf[9 - i] = HexaTab[val % 10];
110                    if (!(val /= 10)) break;
111                }
112                len =  i + 1;
113                pbuf = &buf[9 - i];
114                break;
115            }
116            case ('u'):             // decimal unsigned integer
117            {
118                uint32_t val = va_arg( args, uint32_t );
119                for(i = 0; i < 10; i++) 
120                {
121                    buf[9 - i] = HexaTab[val % 10];
122                    if (!(val /= 10)) break;
123                }
124                len =  i + 1;
125                pbuf = &buf[9 - i];
126                break;
127            }
128            case ('x'):             // 32 bits hexadecimal
129            case ('l'):             // 64 bits hexadecimal
130            {
131                uint32_t imax;
132                uint64_t val;
133               
134                if ( *format == 'l' )   // 64 bits
135                {
136                    val = va_arg( args, uint64_t);
137                    imax = 16;
138                }
139                else                    // 32 bits
140                {
141                    val = va_arg( args, uint32_t);
142                    imax = 8;
143                }
144               
145                TO_STREAM( '0' );
146                TO_STREAM( 'x' );
147               
148                for(i = 0; i < imax; i++) 
149                {
150                    buf[(imax-1) - i] = HexaTab[val % 16];
151                    if (!(val /= 16))  break;
152                }
153                len =  i + 1;
154                pbuf = &buf[(imax-1) - i];
155                break;
156            }
157            case ('X'):             // 32 bits hexadecimal on 8 characters
158            {
159                uint32_t val = va_arg( args , uint32_t );
160                for(i = 0; i < 8; i++) 
161                {
162                    buf[7 - i] = HexaTab[val % 16];
163                    val = (val>>4);
164                }
165                len =  8;
166                pbuf = buf;
167                break;
168            }
169            case ('s'):             /* string */
170            {
171                char* str = va_arg( args, char* );
172                while (str[len]) { len++; }
173                pbuf = str;
174                break;
175            }
176            default:       // unsupported argument type
177            {
178                return -1;
179            }
180        }  // end switch on  argument type
181
182        format++;
183
184        // copy argument to string
185        for( i = 0 ; i < len ; i++ )
186        {
187            TO_STREAM( pbuf[i] );
188        }
189       
190        goto xprintf_text;
191    }
192} // end snprintf()
193
194//////////////////////////////////////////////////////////////////////////////////////
195// This static function is called by printk(), assert() and nolock_printk()
196// to display a formated string on TXT0, using a busy waiting policy.
197//////////////////////////////////////////////////////////////////////////////////////
198// @ format    : printf like format.
199// @ args      : va_list of arguments.
200//////////////////////////////////////////////////////////////////////////////////////
201static void kernel_printf( char     * format, 
202                           va_list  * args ) 
203{
204
205printf_text:
206
207    while (*format) 
208    {
209        uint32_t i;
210        for (i = 0 ; format[i] && (format[i] != '%') ; i++);
211        if (i) 
212        {
213            dev_txt_sync_write( format, i );
214            format += i;
215        }
216        if (*format == '%') 
217        {
218            format++;
219            goto printf_arguments;
220        }
221    }
222
223    return;
224
225printf_arguments:
226
227    {
228        char      buf[20];
229        char    * pbuf = NULL;
230        uint32_t  len  = 0;
231        static const char HexaTab[] = "0123456789ABCDEF";
232        uint32_t i;
233
234        switch (*format++) 
235        {
236            case ('c'):             /* char conversion */
237            {
238                int val = va_arg( *args , int );
239                len = 1;
240                buf[0] = val;
241                pbuf = &buf[0];
242                break;
243            }
244            case ('d'):             /* 32 bits decimal signed  */
245            {
246                int val = va_arg( *args , int );
247                if (val < 0) 
248                {
249                    val = -val;
250                    dev_txt_sync_write( "-" , 1 );
251                }
252                for(i = 0; i < 10; i++) 
253                {
254                    buf[9 - i] = HexaTab[val % 10];
255                    if (!(val /= 10)) break;
256                }
257                len =  i + 1;
258                pbuf = &buf[9 - i];
259                break;
260            }
261            case ('u'):             /* 32 bits decimal unsigned  */
262            {
263                uint32_t val = va_arg( *args , uint32_t );
264                for(i = 0; i < 10; i++) 
265                {
266                    buf[9 - i] = HexaTab[val % 10];
267                    if (!(val /= 10)) break;
268                }
269                len =  i + 1;
270                pbuf = &buf[9 - i];
271                break;
272            }
273            case ('x'):             /* 32 bits hexadecimal unsigned */
274            {
275                uint32_t val = va_arg( *args , uint32_t );
276                dev_txt_sync_write( "0x" , 2 );
277                for(i = 0; i < 8; i++) 
278                {
279                    buf[7 - i] = HexaTab[val & 0xF];
280                    if (!(val = (val>>4)))  break;
281                }
282                len =  i + 1;
283                pbuf = &buf[7 - i];
284                break;
285            }
286            case ('X'):             /* 32 bits hexadecimal unsigned  on 10 char */
287            {
288                uint32_t val = va_arg( *args , uint32_t );
289                dev_txt_sync_write( "0x" , 2 );
290                for(i = 0; i < 8; i++) 
291                {
292                    buf[7 - i] = HexaTab[val & 0xF];
293                    val = (val>>4);
294                }
295                len =  8;
296                pbuf = buf;
297                break;
298            }
299            case ('l'):            /* 64 bits hexadecimal unsigned */
300            {
301                unsigned long long val = va_arg( *args , unsigned long long );
302                dev_txt_sync_write( "0x" , 2 );
303                for(i = 0; i < 16; i++) 
304                {
305                    buf[15 - i] = HexaTab[val & 0xF];
306                    if (!(val = (val>>4)))  break;
307                }
308                len =  i + 1;
309                pbuf = &buf[15 - i];
310                break;
311            }
312            case ('L'):           /* 64 bits hexadecimal unsigned on 18 char */ 
313            {
314                unsigned long long val = va_arg( *args , unsigned long long );
315                dev_txt_sync_write( "0x" , 2 );
316                for(i = 0; i < 16; i++) 
317                {
318                    buf[15 - i] = HexaTab[val & 0xF];
319                    val = (val>>4);
320                }
321                len =  16;
322                pbuf = buf;
323                break;
324            }
325            case ('s'):             /* string */
326            {
327                char* str = va_arg( *args , char* );
328                while (str[len]) 
329                {
330                    len++;
331                }
332                pbuf = str;
333                break;
334            }
335            default:
336            {
337                dev_txt_sync_write( "\n[PANIC] in kernel_printf() : illegal format\n", 45 );
338            }
339        }
340
341        if( pbuf != NULL ) dev_txt_sync_write( pbuf, len );
342       
343        goto printf_text;
344    }
345
346}  // end kernel_printf()
347
348//////////////////////////////////
349void printk( char * format , ... )
350{
351    va_list       args;
352    uint32_t      save_sr;
353
354    // get pointers on TXT0 chdev
355    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
356    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
357    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
358
359    // get extended pointer on remote TXT0 chdev lock
360    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
361
362    // get TXT0 lock in busy waiting mode
363    remote_spinlock_lock_busy( lock_xp , &save_sr );
364
365    // call kernel_printf on TXT0, in busy waiting mode
366    va_start( args , format );
367    kernel_printf( format , &args );
368    va_end( args );
369
370    // release lock
371    remote_spinlock_unlock_busy( lock_xp , save_sr );
372}
373
374/////////////////////////////////////////
375void nolock_printk( char * format , ... )
376{
377    va_list       args;
378
379    // call kernel_printf on TXT0, in busy waiting mode
380    va_start( args , format );
381    kernel_printf( format , &args );
382    va_end( args );
383}
384
385/////////////////////////////////
386void _panic( char * format , ... )
387{
388    va_list       args;
389    uint32_t      save_sr;
390
391    // get pointers on TXT0 chdev
392    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
393    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
394    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
395
396    // get extended pointer on remote TXT0 chdev lock
397    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
398
399    // get TXT0 lock in busy waiting mode
400    remote_spinlock_lock_busy( lock_xp , &save_sr );
401
402    // call kernel_printf on TXT0, in busy waiting mode
403    va_start( args , format );
404    kernel_printf( format , &args );
405    va_end( args );
406
407    // release lock
408    remote_spinlock_unlock_busy( lock_xp , save_sr );
409
410    hal_disable_irq( NULL );
411
412    while (1)
413    {
414        hal_core_sleep();
415    }
416}
417
418////////////////////////////////////
419void assert( bool_t       condition,
420             const char * function_name,
421             char       * format, ... )
422{
423    va_list       args;
424    uint32_t      save_sr;
425
426    if( condition == false )
427    {
428        // get pointers on TXT0 chdev
429        xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
430        cxy_t     txt0_cxy = GET_CXY( txt0_xp );
431        chdev_t * txt0_ptr = GET_PTR( txt0_xp );
432
433        // get extended pointer on remote TXT0 chdev lock
434        xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
435
436        // get TXT0 lock in busy waiting mode
437        remote_spinlock_lock_busy( lock_xp , &save_sr );
438
439        // call nolock_printk to print function_name
440        nolock_printk("\n[PANIC] in %s : " , function_name );
441
442        // call kernel_printf on TXT0, in busy waiting to print format
443        va_start( args , format );
444        kernel_printf( format , &args );
445        va_end( args );
446
447        // release TXT0 lock
448        remote_spinlock_unlock_busy( lock_xp , save_sr );
449
450        // suicide
451        hal_core_sleep();
452    }
453}
454
455//////////////////////////
456void puts( char * string ) 
457{
458    uint32_t   save_sr;
459    uint32_t   n = 0;
460
461    // compute string length
462    while ( string[n] > 0 ) n++;
463
464    // get pointers on TXT0 chdev
465    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
466    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
467    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
468
469    // get extended pointer on remote TXT0 chdev lock
470    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
471
472    // get TXT0 lock in busy waiting mode
473    remote_spinlock_lock_busy( lock_xp , &save_sr );
474
475    // display string on TTY0
476    dev_txt_sync_write( string , n );
477
478    // release TXT0 lock in busy waiting mode
479    remote_spinlock_unlock_busy( lock_xp , save_sr );
480}
481
482
483/////////////////////////
484void putx( uint32_t val )
485{
486    static const char HexaTab[] = "0123456789ABCDEF";
487
488    char      buf[10];
489    uint32_t  c;
490    uint32_t  save_sr;
491
492    buf[0] = '0';
493    buf[1] = 'x';
494
495    // build buffer
496    for (c = 0; c < 8; c++) 
497    { 
498        buf[9 - c] = HexaTab[val & 0xF];
499        val = val >> 4;
500    }
501
502    // get pointers on TXT0 chdev
503    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
504    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
505    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
506
507    // get extended pointer on remote TXT0 chdev lock
508    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
509
510    // get TXT0 lock in busy waiting mode
511    remote_spinlock_lock_busy( lock_xp , &save_sr );
512
513    // display string on TTY0
514    dev_txt_sync_write( buf , 10 );
515
516    // release TXT0 lock in busy waiting mode
517    remote_spinlock_unlock_busy( lock_xp , save_sr );
518}
519
520/////////////////////////
521void putl( uint64_t val )
522{
523    static const char HexaTab[] = "0123456789ABCDEF";
524
525    char      buf[18];
526    uint32_t  c;
527    uint32_t  save_sr;
528
529    buf[0] = '0';
530    buf[1] = 'x';
531
532    // build buffer
533    for (c = 0; c < 16; c++) 
534    { 
535        buf[17 - c] = HexaTab[(unsigned int)val & 0xF];
536        val = val >> 4;
537    }
538
539    // get pointers on TXT0 chdev
540    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
541    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
542    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
543
544    // get extended pointer on remote TXT0 chdev lock
545    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
546
547    // get TXT0 lock in busy waiting mode
548    remote_spinlock_lock_busy( lock_xp , &save_sr );
549
550    // display string on TTY0
551    dev_txt_sync_write( buf , 18 );
552
553    // release TXT0 lock in busy waiting mode
554    remote_spinlock_unlock_busy( lock_xp , save_sr );
555}
556
557
558// Local Variables:
559// tab-width: 4
560// c-basic-offset: 4
561// c-file-offsets:((innamespace . 0)(inline-open . 0))
562// indent-tabs-mode: nil
563// End:
564// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
565
Note: See TracBrowser for help on using the repository browser.