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

Last change on this file since 638 was 625, checked in by alain, 6 years ago

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

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 = 0;
592
593    // get pointers on TXT0 chdev
594    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
595    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
596    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
597
598    // get extended pointer on remote TXT0 chdev lock
599    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
600
601    // get TXT0 lock
602    remote_busylock_acquire( lock_xp );
603
604    // display string on TTY0
605    nolock_printk("\n***** %s *****\n", string );
606
607    for ( line = 0 ; line < (size>>4) ; line++ )
608    {
609         nolock_printk(" %X | %b %b %b %b | %b %b %b %b | %b %b %b %b | %b %b %b %b \n",
610         byte,
611         buffer[byte+ 0],buffer[byte+ 1],buffer[byte+ 2],buffer[byte+ 3],
612         buffer[byte+ 4],buffer[byte+ 5],buffer[byte+ 6],buffer[byte+ 7],
613         buffer[byte+ 8],buffer[byte+ 9],buffer[byte+10],buffer[byte+11],
614         buffer[byte+12],buffer[byte+13],buffer[byte+14],buffer[byte+15] );
615
616         byte += 16;
617    }
618
619    // release TXT0 lock
620    remote_busylock_release( lock_xp );
621}
622
623
624
625// Local Variables:
626// tab-width: 4
627// c-basic-offset: 4
628// c-file-offsets:((innamespace . 0)(inline-open . 0))
629// indent-tabs-mode: nil
630// End:
631// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
632
Note: See TracBrowser for help on using the repository browser.