summaryrefslogtreecommitdiff
path: root/lib/klibc.c
blob: ded0c780def656f99f719b72143ae9dc8757b6ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
** @file klibc.c
**
** @author  Warren R. Carithers
**
** Additional support functions for the kernel.
**
*/

#define KERNEL_SRC

#include <klib.h>
#include <cio.h>
#include <procs.h>
#include <support.h>

/**
** Name:    put_char_or_code( ch )
**
** Description: Prints a character on the console, unless it
** is a non-printing character, in which case its hex code
** is printed
**
** @param ch    The character to be printed
*/
void put_char_or_code( int ch ) {

	if( ch >= ' ' && ch < 0x7f ) {
		cio_putchar( ch );
	} else {
		cio_printf( "\\x%02x", ch );
	}
}

/**
** Name:    backtrace
**
** Perform a stack backtrace
**
** @param ebp   Initial EBP to use
** @param args  Number of function argument values to print
*/
void backtrace( uint32_t *ebp, uint_t args ) {

	cio_puts( "Trace:  " );
	if( ebp == NULL ) {
		cio_puts( "NULL ebp, no trace possible\n" );
		return;
	} else {
		cio_putchar( '\n' );
	}

	while( ebp != NULL ){

		// get return address and report it and EBP
		uint32_t ret = ebp[1];
		cio_printf( " ebp %08x ret %08x args", (uint32_t) ebp, ret );

		// print the requested number of function arguments
		for( uint_t i = 0; i < args; ++i ) {
			cio_printf( " [%u] %08x", i+1, ebp[2+i] );
		}
		cio_putchar( '\n' );

		// follow the chain
		ebp = (uint32_t *) *ebp;
	}
}

/**
** kpanic - kernel-level panic routine
**
** usage:  kpanic( msg )
**
** Prefix routine for panic() - can be expanded to do other things
** (e.g., printing a stack traceback)
**
** @param msg[in]  String containing a relevant message to be printed,
**				   or NULL
*/
void kpanic( const char *msg ) {

	cio_puts( "\n\n***** KERNEL PANIC *****\n\n" );

	if( msg ) {
		cio_printf( "%s\n", msg );
	}

	delay( DELAY_5_SEC );   // approximately

	// dump a bunch of potentially useful information

	// dump the contents of the current PCB
	pcb_dump( "Current", current, true );

	// dump the basic info about what's in the process table
	ptable_dump_counts();

	// dump information about the queues
	pcb_queue_dump( "R", ready, true );
	pcb_queue_dump( "W", waiting, true );
	pcb_queue_dump( "S", sleeping, true );
	pcb_queue_dump( "Z", zombie, true );
	pcb_queue_dump( "I", sioread, true );

	// perform a stack backtrace
	backtrace( (uint32_t *) r_ebp(), 3 );

	// could dump other stuff here, too

	panic( "KERNEL PANIC" );
}