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

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

Introduce three new types of vsegs (KCODE,KDATA,KDEV)
to map the kernel vsegs in the process VSL and GPT.
This now used by both the TSAR and the I86 architectures.

File size: 16.8 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'):             // excactly 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[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 string on TTY0
505    dev_txt_sync_write( buf , 10 );
506
507    // release TXT0 lock
508    remote_busylock_release( lock_xp );
509}
510
511/////////////////////////
512void putl( uint64_t val )
513{
514    static const char HexaTab[] = "0123456789ABCDEF";
515
516    char      buf[18];
517    uint32_t  c;
518
519    buf[0] = '0';
520    buf[1] = 'x';
521
522    // build buffer
523    for (c = 0; c < 16; c++) 
524    { 
525        buf[17 - c] = HexaTab[(unsigned int)val & 0xF];
526        val = val >> 4;
527    }
528
529    // get pointers on TXT0 chdev
530    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
531    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
532    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
533
534    // get extended pointer on remote TXT0 chdev lock
535    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
536
537    // get TXT0 lock
538    remote_busylock_acquire( lock_xp );
539
540    // display string on TTY0
541    dev_txt_sync_write( buf , 18 );
542
543    // release TXT0 lock
544    remote_busylock_release( lock_xp );
545}
546
547/////////////////////////////
548void putb( char     * string,
549           uint8_t  * buffer,
550           uint32_t   size )
551{
552    uint32_t line;
553    uint32_t byte = 0;
554
555    // get pointers on TXT0 chdev
556    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
557    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
558    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
559
560    // get extended pointer on remote TXT0 chdev lock
561    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
562
563    // get TXT0 lock
564    remote_busylock_acquire( lock_xp );
565
566    // display string on TTY0
567    nolock_printk("\n***** %s *****\n", string );
568
569    for ( line = 0 ; line < (size>>4) ; line++ )
570    {
571         nolock_printk(" %X | %b %b %b %b | %b %b %b %b | %b %b %b %b | %b %b %b %b \n",
572         byte,
573         buffer[byte+ 0],buffer[byte+ 1],buffer[byte+ 2],buffer[byte+ 3],
574         buffer[byte+ 4],buffer[byte+ 5],buffer[byte+ 6],buffer[byte+ 7],
575         buffer[byte+ 8],buffer[byte+ 9],buffer[byte+10],buffer[byte+11],
576         buffer[byte+12],buffer[byte+13],buffer[byte+14],buffer[byte+15] );
577
578         byte += 16;
579    }
580
581    // release TXT0 lock
582    remote_busylock_release( lock_xp );
583}
584
585
586
587// Local Variables:
588// tab-width: 4
589// c-basic-offset: 4
590// c-file-offsets:((innamespace . 0)(inline-open . 0))
591// indent-tabs-mode: nil
592// End:
593// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
594
Note: See TracBrowser for help on using the repository browser.