make panic() work for multiboot/elf case

. we cannot use the boot monitor to print the system diag buffer
	. for serial, we do nothing, just reset, everything is already printed
	. for not-serial, we print the current diag buffer using direct video
	  memory access from the kernel
This commit is contained in:
Evgeniy Ivanov 2012-02-12 19:11:47 +04:00 committed by Ben Gras
parent a73c217bf6
commit 2487445f5f
5 changed files with 118 additions and 70 deletions

View file

@ -25,6 +25,7 @@
#include "oxpcie.h"
#include "kernel/proc.h"
#include "kernel/debug.h"
#include "mb_utils.h"
#include <machine/multiboot.h>
#include "glo.h"
@ -85,15 +86,14 @@ PUBLIC int cpu_has_tsc;
PUBLIC __dead void arch_shutdown(int how)
{
static char mybuffer[sizeof(params_buffer)];
u16_t magic;
vm_stop();
/* Mask all interrupts, including the clock. */
outb( INT_CTLMASK, ~0);
#if USE_BOOTPARAM
if(minix_panicing) {
unsigned char unused_ch;
/* We're panicing? Then retrieve and decode currently
* loaded segment selectors.
*/
@ -102,8 +102,22 @@ PUBLIC __dead void arch_shutdown(int how)
if(read_ds() != read_ss()) {
printseg("ss: ", 0, NULL, read_ss());
}
/* Printing is done synchronously over serial. */
if (do_serial_debug)
reset();
/* Print accumulated diagnostics buffer and reset. */
mb_cls();
mb_print("Minix panic. System diagnostics buffer:\n\n");
mb_print(kmess_buf);
mb_print("\nSystem has panicked, press any key to reboot");
while (!mb_read_char(&unused_ch))
;
reset();
}
#if USE_BOOTPARAM
if (how == RBT_DEFAULT) {
how = mon_return ? RBT_HALT : RBT_RESET;
}
@ -119,37 +133,7 @@ PUBLIC __dead void arch_shutdown(int how)
*/
if (how != RBT_MONITOR)
arch_set_params("", 1);
if(minix_panicing) {
int source, dest;
const char *lead = "echo \\n*** kernel messages:\\n";
const int leadlen = strlen(lead);
strcpy(mybuffer, lead);
#define DECSOURCE source = (source - 1 + _KMESS_BUF_SIZE) % _KMESS_BUF_SIZE
dest = sizeof(mybuffer)-1;
mybuffer[dest--] = '\0';
source = kmess.km_next;
DECSOURCE;
while(dest >= leadlen) {
const char c = kmess.km_buf[source];
if(c == '\n') {
mybuffer[dest--] = 'n';
mybuffer[dest] = '\\';
} else if(isprint(c) &&
c != '\'' && c != '"' &&
c != '\\' && c != ';') {
mybuffer[dest] = c;
} else mybuffer[dest] = ' ';
DECSOURCE;
dest--;
}
arch_set_params(mybuffer, strlen(mybuffer)+1);
}
if (mon_return)
arch_monitor();
@ -157,14 +141,7 @@ PUBLIC __dead void arch_shutdown(int how)
* depending on the parameters
*/
if (how == RBT_MONITOR) {
mybuffer[0] = '\0';
arch_get_params(mybuffer, sizeof(mybuffer));
if (strstr(mybuffer, "boot") ||
strstr(mybuffer, "menu") ||
strstr(mybuffer, "reset"))
how = RBT_RESET;
else
how = RBT_HALT;
}
}
@ -643,8 +620,6 @@ PUBLIC void arch_ack_profile_clock(void)
#endif
#define COLOR_BASE 0xB8000L
/* Saved by mpx386.s into these variables. */
u32_t params_size, params_offset, mon_ds;

View file

@ -0,0 +1,12 @@
#ifndef MB_UTILS_H
#define MB_UTILS_H
#include "kernel/kernel.h"
_PROTOTYPE(void mb_cls, (void));
_PROTOTYPE(void mb_print, (char*));
_PROTOTYPE(void mb_print_char, (char));
_PROTOTYPE(int mb_read_char, (unsigned char*));
#endif

View file

@ -16,6 +16,8 @@
#include "string.h"
#include "arch_proto.h"
#include "libexec.h"
#include "mb_utils.h"
#include "serial.h"
#include <machine/multiboot.h>
#if USE_SYSDEBUG
@ -38,8 +40,6 @@
#define mb_save_phymem(buf, phy, len) \
phys_copy((u32_t)(buf), (phy), (len))
FORWARD _PROTOTYPE(void mb_print, (char *str));
PRIVATE void mb_itoa(u32_t val, char * out)
{
char ret[ITOA_BUFFER_SIZE];
@ -118,49 +118,103 @@ PRIVATE char mb_get_char(int line, int col)
/* Give non-zero values to avoid them in BSS */
PRIVATE int print_line = 1, print_col = 1;
PRIVATE void mb_cls(void)
#include <sys/video.h>
PUBLIC void mb_cls(void)
{
#if MULTIBOOT_VERBOSE
int i, j;
/* Clear screen */
for (i = 0; i < MULTIBOOT_CONSOLE_LINES; i++ )
for (j = 0; j < MULTIBOOT_CONSOLE_COLS; j++ )
mb_put_char(0, i, j);
print_line = print_col = 0;
#endif
/* Tell video hardware origin is 0. */
outb(C_6845+INDEX, VID_ORG);
outb(C_6845+DATA, 0);
outb(C_6845+INDEX, VID_ORG+1);
outb(C_6845+DATA, 0);
}
PRIVATE void mb_scroll_up(int lines)
{
int i, j;
for (i = 0; i < MULTIBOOT_CONSOLE_LINES - lines; i++ ) {
for (j = 0; j < MULTIBOOT_CONSOLE_COLS; j++ )
mb_put_char(mb_get_char(i + lines, j), i, j);
for (i = 0; i < MULTIBOOT_CONSOLE_LINES; i++ ) {
for (j = 0; j < MULTIBOOT_CONSOLE_COLS; j++ ) {
char c = 0;
if(i < MULTIBOOT_CONSOLE_LINES-lines)
c = mb_get_char(i + lines, j);
mb_put_char(c, i, j);
}
}
print_line-= lines;
}
PRIVATE void mb_print(char *str)
PUBLIC void mb_print_char(char c)
{
#if MULTIBOOT_VERBOSE
while (*str) {
if (*str == '\n') {
str++;
while (print_line >= MULTIBOOT_CONSOLE_LINES)
mb_scroll_up(1);
if (c == '\n') {
while (print_col < MULTIBOOT_CONSOLE_COLS)
mb_put_char(' ', print_line, print_col++);
print_line++;
print_col = 0;
continue;
return;
}
mb_put_char(*str++, print_line, print_col++);
mb_put_char(c, print_line, print_col++);
if (print_col >= MULTIBOOT_CONSOLE_COLS) {
print_line++;
print_col = 0;
}
while (print_line >= MULTIBOOT_CONSOLE_LINES)
mb_scroll_up(1);
}
#endif /* MULTIBOOT_VERBOSE */
PUBLIC void mb_print(char *str)
{
while (*str) {
mb_print_char(*str);
str++;
}
}
/* Standard and AT keyboard. (PS/2 MCA implies AT throughout.) */
#define KEYBD 0x60 /* I/O port for keyboard data */
#define KB_STATUS 0x64 /* I/O port for status on AT */
#define KB_OUT_FULL 0x01 /* status bit set when keypress char pending */
#define KB_AUX_BYTE 0x20 /* Auxiliary Device Output Buffer Full */
PUBLIC int mb_read_char(unsigned char *ch)
{
unsigned long b, sb;
#ifdef DEBUG_SERIAL
u8_t c, lsr;
if (do_serial_debug) {
lsr= inb(COM1_LSR);
if (!(lsr & LSR_DR))
return 0;
c = inb(COM1_RBR);
return 1;
}
#endif /* DEBUG_SERIAL */
sb = inb(KB_STATUS);
if (!(sb & KB_OUT_FULL)) {
return 0;
}
b = inb(KEYBD);
if (!(sb & KB_AUX_BYTE))
return 1;
return 0;
}
PRIVATE void mb_print_hex(u32_t value)

View file

@ -22,6 +22,7 @@
EXTERN struct kinfo kinfo; /* kernel information for users */
EXTERN struct machine machine; /* machine information for users */
EXTERN struct kmessages kmess; /* diagnostic messages in kernel */
EXTERN char kmess_buf[80*25]; /* printable copy of message buffer */
EXTERN struct k_randomness krandom; /* gather kernel random information */
EXTERN struct loadinfo kloadinfo; /* status of load average */

View file

@ -23,7 +23,7 @@ PUBLIC void panic(const char *fmt, ...)
va_list arg;
/* The system has run aground of a fatal kernel error. Terminate execution. */
if (minix_panicing == ARE_PANICING) {
arch_monitor();
reset();
}
minix_panicing = ARE_PANICING;
if (fmt != NULL) {
@ -53,6 +53,8 @@ int c; /* character to append */
* to the output driver if an END_OF_KMESS is encountered.
*/
if (c != END_OF_KMESS) {
static int blpos = 0;
int maxblpos = sizeof(kmess_buf) - 2;
#ifdef DEBUG_SERIAL
if (do_serial_debug) {
if(c == '\n')
@ -61,9 +63,13 @@ int c; /* character to append */
}
#endif
kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
kmess_buf[blpos] = c;
if (kmess.km_size < sizeof(kmess.km_buf))
kmess.km_size += 1;
kmess.km_next = (kmess.km_next + 1) % _KMESS_BUF_SIZE;
if(blpos == maxblpos) {
memmove(kmess_buf, kmess_buf+1, sizeof(kmess_buf)-1);
} else blpos++;
} else {
int p;
endpoint_t outprocs[] = OUTPUT_PROCS_ARRAY;