lkml.org 
[lkml]   [1999]   [May]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: Oops assist... [Solution + Patch]
On many systems, you can find memory that isn't zeroed by the BIOS
on boot. I have a patch that saves the console log into such memory
as it gets written -- this lets you get to the oops after the reboot.

The problem is that motherboards and BIOSes are all different. For
example,
on an ASUS P2B, I use the RAM between 0xb0000-0xc0000. Ahah I hear you
say,
this is VGA memory, this must be flushed on reboot.

It turns out that there is main memory (i.e. on the DIMM) at this
location
as well. This is normally disabled so that accesses go to the VGA. You
can
fiddle with the 82443 chip to route memory accesses into the underlying
memory.

Problems:

This doesn't work in an SMP environment (I think) as there needs to be
coordination between the two processors.

It is very slow as (I think) I need to flush the CPU caches to ensure
that memory accesses happen in the right order.

It is very motherboard/BIOS dependant -- basically it relies on the
'bug' that the BIOS fails to clear out this hidden memory.

It doesn't work (for example) on Compaq boxes as they lock access to
this area.

Anyway, I attach a patch for 2.0.36 that allows a module to get a copy
of all console output (by using the register_logger function). This
is the basic hook required.

Future approaches:

If *all* you want is the oops log, then it may be possible to save it
in some of the CMOS ram that is available. It turns out that there
is more CMOS battery backed ram than you might expect! For example,
on the P2B there are *two* RTCs -- one embedded inside the southbridge
and one inside the super i/o chip. With enough careful fiddling, it
might be possible to write to the one that isn't being used. I'll
bet that having 220 bytes of Oops is a lot better than nothing - note
that you only want to save the binary data, not the text.

For all I know, you can hide data on a VGA card -- who knows if they
clear out all the memory on a reset!!

Philip

Manfred Spraul wrote:
>
> David Weinehall wrote:
> > Wouldn't it be quite reasonable to make "Reboot on Oops" an config-option
> > or a sysctl?
>
> Obviously, yes. (I think that reboot on Oops should be the default).
> But what about the oops report? I think that this report must be stored
> somewhere. How do you want to find a bug without it?
> (new bug report: Hey, my computer crashed yesterday at 21:15.
> What's wrong?)
> IMHO, the swapfile is the best & portable solution: NT uses
> the swapfile, I've read the Solaris uses the swapfile, too.
>
> Regards,
> Manfred
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.rutgers.edu
> Please read the FAQ at http://www.tux.org/lkml/

--
Philip Gladstone +1 781 530 2461
Axent Technologies, Waltham, MA--- linux/kernel/printk.c.orig Fri Jun 7 04:54:06 1996
+++ linux/kernel/printk.c Mon Sep 29 18:12:37 1997
@@ -41,6 +41,7 @@
int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;

static void (*console_print_proc)(const char *) = 0;
+static void (*logger_proc)(const char *, int) = 0;
static char log_buf[LOG_BUF_LEN];
static unsigned long log_start = 0;
static unsigned long logged_chars = 0;
@@ -154,6 +155,7 @@
char *msg, *p, *buf_end;
static char msg_level = -1;
long flags;
+ char *whole_msg;

save_flags(flags);
cli();
@@ -162,7 +164,7 @@
buf_end = buf + 3 + i;
va_end(args);
for (p = buf + 3; p < buf_end; p++) {
- msg = p;
+ whole_msg = msg = p;
if (msg_level < 0) {
if (
p[0] != '<' ||
@@ -190,6 +192,11 @@
if (*p == '\n')
break;
}
+
+ if (logger_proc)
+ (*logger_proc)(whole_msg,
+ ((p < buf_end) ? (p + 1) : p) - whole_msg);
+
if (msg_level < console_loglevel && console_print_proc) {
char tmp = p[1];
p[1] = '\0';
@@ -235,6 +242,40 @@
(*proc)(q);
if (buf[j-1] == '\n')
msg_level = -1;
+ j = 0;
+ }
+}
+
+void register_logger(void (*proc)(const char *, int))
+{
+ int i,j;
+ int p;
+ char buf[80];
+ int nchars;
+
+ logger_proc = proc;
+
+ if (!logger_proc)
+ return;
+
+ if (log_size == LOG_BUF_LEN)
+ p = (log_start + log_size) & (LOG_BUF_LEN - 1);
+ else
+ p = 0;
+
+ if (logged_chars > LOG_BUF_LEN)
+ nchars = LOG_BUF_LEN;
+ else
+ nchars = logged_chars;
+
+ for (i=0,j=0; i < nchars; i++) {
+ buf[j++] = log_buf[p];
+ p++; p &= LOG_BUF_LEN-1;
+ if (buf[j-1] != '\n' && i < log_size - 1 && j < sizeof(buf))
+ continue;
+
+ (*logger_proc)(buf, j);
+
j = 0;
}
}
--- linux/kernel/ksyms.c.orig Mon Sep 29 16:07:37 1997
+++ linux/kernel/ksyms.c Mon Sep 29 16:10:28 1997
@@ -83,6 +83,9 @@
extern void select_free_wait(select_table * p);
extern int select_check(int flag, select_table * wait, struct file * file);

+extern void register_logger(void (*) (const char *, int));
+extern void (*kd_mksound)(unsigned int, unsigned int);
+
struct symbol_table symbol_table = {
#include <linux/symtab_begin.h>
#ifdef MODVERSIONS
@@ -375,6 +378,8 @@
X(disk_name), /* for md.c */
#endif

+ X(register_logger),
+ X(kd_mksound),
X(watchdog_info),

/* binfmt_aout */[unhandled content-type:application/x-pkcs7-signature]
\
 
 \ /
  Last update: 2005-03-22 13:51    [W:0.165 / U:0.636 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site