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

Last change on this file since 666 was 662, checked in by alain, 4 years ago

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

File size: 17.7 KB
RevLine 
[1]1/*
2 * printk.c - Kernel Log & debug messages API implementation.
3 *
[437]4 * authors  Alain Greiner (2016,2017,2018)
[1]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
[457]24#include <hal_kernel_types.h>
[1]25#include <hal_irqmask.h>
[5]26#include <hal_special.h>
[1]27#include <dev_txt.h>
[564]28#include <remote_busylock.h>
[1]29#include <cluster.h>
[446]30#include <thread.h>
[14]31#include <chdev.h>
[5]32#include <printk.h>
[445]33#include <shared_syscalls.h>
[1]34
35///////////////////////////////////////////////////////////////////////////////////
[14]36//      Extern variables
37///////////////////////////////////////////////////////////////////////////////////
38
[188]39extern chdev_directory_t  chdev_dir;  // defined in chdev.h / allocated in kernel_init.c
[14]40
[23]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
[623]50    uint32_t   ps;        // pointer to the string buffer
[23]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            }
[623]99            case ('b'):             // excactly 2 digits hexadecimal integer
[23]100            {
[623]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            {
[23]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            }
[623]127            case ('u'):             // up to 10 digits decimal unsigned integer
[23]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            }
[623]139            case ('x'):             // up to 8 digits hexadecimal
140            case ('l'):             // up to 16 digits hexadecimal
[23]141            {
[246]142                uint32_t imax;
[23]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            }
[623]168            case ('X'):             // exactly 8 digits hexadecimal
[246]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            }
[23]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    }
[407]203} // end snprintf()
[23]204
[5]205//////////////////////////////////////////////////////////////////////////////////////
[407]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.
[5]208//////////////////////////////////////////////////////////////////////////////////////
209// @ format    : printf like format.
[407]210// @ args      : va_list of arguments.
[5]211//////////////////////////////////////////////////////////////////////////////////////
[564]212static void kernel_printf( const char * format, 
213                           va_list    * args ) 
[1]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        {
[407]224            dev_txt_sync_write( format, i );
[1]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            {
[623]249                int  val = va_arg( *args , int );
[1]250                len = 1;
[623]251                buf[0] = (char)val;
[1]252                pbuf = &buf[0];
253                break;
254            }
[625]255            case ('b'):             /* exactly 2 digits hexadecimal */
[1]256            {
[623]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            {
[1]268                int val = va_arg( *args , int );
269                if (val < 0) 
270                {
271                    val = -val;
[407]272                    dev_txt_sync_write( "-" , 1 );
[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            }
[623]283            case ('u'):             /* up to 10 digits unsigned decimal */
[1]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            }
[623]295            case ('x'):             /* up to 8 digits hexadecimal */
[1]296            {
297                uint32_t val = va_arg( *args , uint32_t );
[407]298                dev_txt_sync_write( "0x" , 2 );
[1]299                for(i = 0; i < 8; i++) 
300                {
[5]301                    buf[7 - i] = HexaTab[val & 0xF];
[1]302                    if (!(val = (val>>4)))  break;
303                }
304                len =  i + 1;
305                pbuf = &buf[7 - i];
306                break;
307            }
[623]308            case ('X'):             /* exactly 8 digits hexadecimal */
[1]309            {
310                uint32_t val = va_arg( *args , uint32_t );
[407]311                dev_txt_sync_write( "0x" , 2 );
[1]312                for(i = 0; i < 8; i++) 
313                {
[5]314                    buf[7 - i] = HexaTab[val & 0xF];
[1]315                    val = (val>>4);
316                }
317                len =  8;
318                pbuf = buf;
319                break;
320            }
[623]321            case ('l'):            /* up to 16 digits hexadecimal */
[1]322            {
[623]323                uint64_t val = va_arg( *args , uint64_t );
[407]324                dev_txt_sync_write( "0x" , 2 );
[1]325                for(i = 0; i < 16; i++) 
326                {
[5]327                    buf[15 - i] = HexaTab[val & 0xF];
328                    if (!(val = (val>>4)))  break;
[1]329                }
330                len =  i + 1;
331                pbuf = &buf[15 - i];
332                break;
333            }
[623]334            case ('L'):           /* exactly 16 digits hexadecimal */ 
[5]335            {
[623]336                uint64_t val = va_arg( *args , uint64_t );
[407]337                dev_txt_sync_write( "0x" , 2 );
[5]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            }
[1]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            {
[407]359                dev_txt_sync_write( "\n[PANIC] in kernel_printf() : illegal format\n", 45 );
[1]360            }
361        }
362
[407]363        if( pbuf != NULL ) dev_txt_sync_write( pbuf, len );
[1]364       
365        goto printf_text;
366    }
367
368}  // end kernel_printf()
369
[337]370//////////////////////////////////
371void printk( char * format , ... )
[1]372{
373    va_list       args;
374
[188]375    // get pointers on TXT0 chdev
[407]376    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
[188]377    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
378    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
379
[564]380    // get extended pointer on remote TXT0 lock
[188]381    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
[14]382
[564]383    // get TXT0 lock
384    remote_busylock_acquire( lock_xp );
[14]385
[564]386    // display format on TXT0 in busy waiting mode
[1]387    va_start( args , format );
[407]388    kernel_printf( format , &args );
[1]389    va_end( args );
[14]390
[564]391    // release TXT0 lock
392    remote_busylock_release( lock_xp );
[1]393}
394
[337]395/////////////////////////////////////////
396void nolock_printk( char * format , ... )
[296]397{
398    va_list       args;
399
400    // call kernel_printf on TXT0, in busy waiting mode
401    va_start( args , format );
[407]402    kernel_printf( format , &args );
[296]403    va_end( args );
404}
405
[337]406////////////////////////////////////
[583]407void panic( const char * function_name,
[564]408            uint32_t     line,
409            cycle_t      cycle,
410            const char * format,
411            ... )
[5]412{
[491]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);
[337]417
[491]418    // get extended pointer on remote TXT0 lock
[564]419    xptr_t lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
[491]420
[564]421    // get TXT0 lock
422    remote_busylock_acquire( lock_xp );
[337]423
[564]424    // get calling thread
425    thread_t * current = CURRENT_THREAD;
426
427    // print generic infos
[625]428    nolock_printk("\n\n[PANIC] in %s: line %d | cycle %d\n"
[583]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 );
[337]434
[564]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);
[337]440
[564]441    // release TXT0 lock
442    remote_busylock_release( lock_xp );
[337]443
[491]444    // suicide
445    hal_core_sleep();
[5]446}
[1]447
[408]448//////////////////////////
449void puts( char * string ) 
450{
451    uint32_t   n = 0;
[23]452
[408]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
[564]461    // get extended pointer on remote TXT0 lock
[408]462    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
463
[564]464    // get TXT0 lock
465    remote_busylock_acquire( lock_xp );
[408]466
467    // display string on TTY0
468    dev_txt_sync_write( string , n );
469
[564]470    // release TXT0 lock
471    remote_busylock_release( lock_xp );
[408]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
[564]501    // get TXT0 lock
502    remote_busylock_acquire( lock_xp );
[408]503
[625]504    // display buf on TTY0
[408]505    dev_txt_sync_write( buf , 10 );
506
[564]507    // release TXT0 lock
508    remote_busylock_release( lock_xp );
[408]509}
510
[625]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
[408]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
[564]575    // get TXT0 lock
576    remote_busylock_acquire( lock_xp );
[408]577
578    // display string on TTY0
579    dev_txt_sync_write( buf , 18 );
580
[564]581    // release TXT0 lock
582    remote_busylock_release( lock_xp );
[408]583}
584
[623]585/////////////////////////////
586void putb( char     * string,
587           uint8_t  * buffer,
588           uint32_t   size )
589{
590    uint32_t line;
[662]591    uint32_t byte;
592    uint32_t nlines;
[408]593
[662]594    nlines = size >> 4;
595    if( size & 0xF ) nlines++;
596
[623]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
[662]611    for ( line = 0 , byte = 0 ; line < nlines ; line++ )
[623]612    {
[662]613         nolock_printk(" %X | %b %b %b %b | %b %b %b %b | %b %b %b %b | %b %b %b %b |\n",
614         buffer + byte,
[623]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
[1]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.