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

Last change on this file since 569 was 564, checked in by alain, 6 years ago

Complete restructuration of kernel locks.

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