summaryrefslogtreecommitdiff
path: root/lib/klibc.c
blob: 6a06a9669d9da8b14a1611ce8eeaf0e5bfcd4b2f (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
/*
** @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");
}