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

Last change on this file since 662 was 662, checked in by alain, 12 months ago

Introduce the ksocket.h & ksocket.c files in kernel/kern.

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