public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Kalin KOZHUHAROV <kalin@ThinRope.net>
To: Norberto Bensa <norberto+linux-kernel@bensa.ath.cx>
Cc: linux-kernel@vger.kernel.org, Willy Tarreau <willy@w.ods.org>,
	ndiamond@despammed.com
Subject: [PATCH] kmsgdump-2.6.6.patch (was: Panics need better handling)
Date: Mon, 14 Jun 2004 22:46:07 +0900	[thread overview]
Message-ID: <40CDAC1F.6050202@ThinRope.net> (raw)
In-Reply-To: <200406140134.52859.norberto+linux-kernel@bensa.ath.cx>

[-- Attachment #1: Type: text/plain, Size: 691 bytes --]

Norberto Bensa wrote:
> Willy Tarreau wrote:
> 
>>   http://developer.odsl.org/rddunlap/kmsgdump/
> 
> 
> http://developer.osdl.org/rddunlap/kmsgdump/
> 
> ;-)
> 

OK, I reapplied the patch from the URL above to 2.6.6 (this is current for most of my machines) and I am posting it here.

I moved one line in kmsg-reboot inside the appropriate #ifdef as not to cause warnings on compile.
Apart form that only applying with the code shifted a bit.

I have prepared my floppy for a dump and everything seems ok, but I have not got any oopses yet :-)

Not sure if I need the signed-off-by, as it is not for inclusion (yet), but here it is:

Signed-off-by: Kalin KOZHUHAROV <kalin@thinrope.net>



[-- Attachment #2: kmsgdump-2.6.6.patch --]
[-- Type: text/plain, Size: 66006 bytes --]

diff -Nuarp linux-2.6.6/Documentation/kmsgdump.txt linux-2.6.6_K1/Documentation/kmsgdump.txt
--- linux-2.6.6/Documentation/kmsgdump.txt	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.6_K1/Documentation/kmsgdump.txt	2004-06-14 16:03:52.623741443 +0900
@@ -0,0 +1,370 @@
+                     - Documentation for KMSGDUMP v0.4 -
+               [Sun Sep 19 19:30:32 CEST 1999] - Willy Tarreau
+               [updates by Randy Dunlap, Jan/Feb/Mar 2003]
+
+
+1. What is KMSGDUMP ?
+~~~~~~~~~~~~~~~~~~~~~
+
+KMSGDUMP is an extension to the Linux kernel which allows the user on the
+console to dump the last kernel messages onto a floppy diskette, thus
+avoiding to take a pen and a paper to copy them when the system is stuck.
+Only 3"1/2, 1.44 MB diskettes are supported by default. Other capacities
+might work, provided you change the geometry in the file "kmsgdump.h".
+
+
+2. How does it work ?
+~~~~~~~~~~~~~~~~~~~~~
+
+There are two ways of getting a dump :
+
+   - by pressing SysRQ+D (RightAlt - PrintScrn - D together) ;
+   - after a kernel panic has occurred, a dump may be automatically
+     generated.
+
+Before anything else, you MUST KNOW that in order to get maximal
+chances to complete the dump succesfully, the CPU is rebooted in
+real mode and disk accesses are made via the Bios. This ensures
+that even if kernel memory is really corrupted, the dump still
+has chances to work, but this also implies that after a dump has
+occurred, it is IMPOSSIBLE TO CONTINUE TO WORK WITH THE CURRENT
+KERNEL. You will have to REBOOT. So when your kernel still responds,
+you'd better get a similar dump by entering one of the following
+commands :
+
+# dmesg > /dev/fd0                   ( for RAW mode )
+
+or
+
+# dmesg | mwrite a:messages.txt      ( for FAT mode )
+
+
+Second, be sure that FLOPPY CONTENTS WILL BE LOST AFTER A DUMP.
+Even if there are cases in which you can dump at the end of a diskette without
+losing the beginning, consider that by default the beginning of the diskette
+will be ERASED and you won't be able to recover what's on it. You have been
+warned.
+
+
+3. Modes of operation
+~~~~~~~~~~~~~~~~~~~~~
+
+There are two modes of operation : manual and automated.
+
+Manual mode (or interactive mode) is always entered if you hit SysRQ+D.
+But it is also entered during a kernel panic if the current mode is set
+to "manual". This mode is recommended for a developer's workstation,
+or a kernel running under an emulator such as vmware. It's recommended
+to disable interactive mode on servers which may crash when nobody is
+near to reboot them.
+
+Automatic mode can only be entered during a kernel panic and if automatic
+mode was previously configured. Sometimes, the system is really weird and
+even kmsgdump can cause recursive crashes (this has been reported to me once).
+For this reason I've added a checkpoint mechanism to the code : every little
+part of code is checkpointed, and if a crash occurs again, the same part is
+not executed again, to prevent looping. So there are more chances to get
+to the reset routine which will, in the worst case, reboot the system, but
+not let it loop indefinitely.
+
+3.1. Manual mode
+~~~~~~~~~~~~~~~~
+
+Under manual mode, the screen initialized to color 80x25 mode (bios mode 3)
+with a blue background.
+
+ [Note: some people asked me to set other colors to avoid confusion
+        with another OS' BSOD, but I couldn't find good associations.
+        Even though I've received an interesting comment about the way
+        to choose colors readable on any color or monochrome display,
+        I'm waiting for suggestions, and for the moment we'll say that
+        these are the colors of Midnight Commander and call this "BSOL"
+        (blue screen of life) because this one is interactive.]
+
+The screen is divided in two portions. The upper one displays the current
+status (kernel version, drive unit, printer, format...), and the lower one
+the messages captured before switching to real mode. The internal speaker
+beeps if a key has not been hit within 3 seconds. This is simply to get
+someone's attention, mainly in cases where no monitor is connected to the
+PC.
+
+The interface is not case-sensitive about keys pressed. Keys used are :
+  Upper arrow : scroll messages to the beginning
+  Lower arrow : scroll messages to the end
+  B : immediately reBoot the system
+  D : Dump messages onto the selected floppy with selected format. Warning:
+      no check is done before, and the floppy will simply be overwritten by
+      the messages.
+  F : select Format, by switching between RAW and FAT12
+  H : immediately Halt the system.
+  I : display Information, little help about the keys.
+  P : Print messages on the currently selected printer. If you press this key
+      by accident, wait about one minute for the bios routine to timeout, and
+      you'll here the beeps again, stating that you can play again.
+  T : select next available prinTer. The system tests if a printer is
+      connected at the other end of the cable, and skips the empty ports.
+  U : change drive Unit. Although dump is possible on hard disks, they are
+      never proposed in the interface to avoid dramatic mistakes.
+
+Other keys are simply ignored.
+
+After a succesful dump or print, 3 quick beeps are played. In case of an error,
+only one beep is played. This is important if you act blindly with a keyboard
+and no monitor.
+
+3.2. Automatic mode
+~~~~~~~~~~~~~~~~~~~
+
+Automated operation is performed by the system only when a kernel panic
+occurs. In this case, the system waits for the "panic_timeout" delay
+to give you a few seconds if you want to try to play with SysRQ (sync,
+unmount filesystems, ...). This delay is configurable by entering a
+number of seconds in "/proc/sys/kernel/panic".
+
+After that, the system is rebooted to real mode, and depending on the
+mode of operation chosen, either the interactive mode is entered (see above)
+or it is the automatic mode, which we'll describe here.
+
+3.2.1. Start of operation
+~~~~~~~~~~~~~~~~~~~~~~~~~
+Some checks are performed. First, the system sees if the dump feature is
+enabled or not. If not, operation ends (see below). If dump is enabled,
+and if the "safe" flag is enabled, the diskette is verified to be a real
+"KMSGDUMP" diskette and not another one (read section 4 to know how to
+prepare a secure diskette for KMSGDUMP). If the diskette isn't a right one,
+operation ends. If the diskette is a right one, or if the check has been
+disabled, the dump is performed with the current parameters (unit, format...).
+
+3.2.2. End of operation
+~~~~~~~~~~~~~~~~~~~~~~~
+After completion of an automatic dump, or when a dump is aborted, the system
+can either halt or reboot. In case of redundant servers, you may prefer to halt
+a buggy system, because another one ensures the service continues to work.
+But in other cases, you may prefer rebooting to quickly restart services.
+This is also configurable (read section 4).
+
+
+4. How a crash can be prepared
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+4.1. Kernel options
+~~~~~~~~~~~~~~~~~~~
+
+First, choose the kernel compilation options which closely match your
+situation. This may seem obvious, but you can reduce the risks of crash
+by not enabling drivers designated for hardware you don't have. Specially
+on servers, use only a reduced feature set, because you know exactly what
+you need (eg: don't enable NTFS and QNX filesystems if you don't need them).
+
+Configure KMSGDUMP options to match your needs. Don't ask to auto-dump if
+you don't have a floppy drive. In this case, you might prefer to enable
+interactive mode to display messages on the screen and eventually print
+them.
+
+When you use SCSI hard disks, you can sometimes reduce the reset time to
+help the system recover faster. Eg: on my system, I have an AHA2940UW which
+waits 15 seconds by default. All peripherals still work well with 1 second,
+so 14 seconds are won.
+
+If you have changed your messages buffer size (which is 16 kB by default),
+you should modify the size in "include/asm/kmsgdump.h", parameter LOG_BUF_LEN.
+Some people required 32 kB. But you shouldn't exceed 60 kB since the dump is
+done in real mode (16 bits).
+For kernel versions 2.5.6x and later, the LOG_BUF_LEN parameter is part
+of the kernel .config file (LOG_BUF_SHIFT) so you don't need to modify
+it at all.
+
+4.2. Configure KMSGDUMP
+~~~~~~~~~~~~~~~~~~~~~~~
+
+If your kernel supports SYSCTL, you can adjust KMSGDUMP parameters by
+writing a string to /proc/sys/kernel/kmsgdump. This string consists of
+a concatenation of flags. Most of them are only booleans. For each boolean,
+a complementary flag exists to avoid any ambiguous interpretation.
+For the moment, the flags are :
+
+   Name Description         Default Complement
+   F    FAT mode              Yes   R
+   R    Raw mode                    F
+   A    Automatic mode        Yes   I
+   I    Interactive mode            A
+   B    Boot after dump       Yes   H   only used in automatic mode
+   H    Halt after dump             B   only used in automatic mode
+   S    Safe mode             Yes   O   only used in automatic mode
+   O    Overwrite disk              S   only used in automatic mode
+   E    Enable dumping        Yes   D   only used in automatic mode
+   D    Disable dumping             E   only used in automatic mode
+   Txxx Track xxx             0   (N/A) first track is 0 per default
+   Uxxx Unit xxx              0   (N/A) bios drive is 0 (A:) per default
+
+Note: default means "default if none specified".
+
+Example: if you enter the following command, a kernel panic will generate
+         a dump in FAT mode after verifying that the disk has been prepared
+         for a dump, and then it will reboot :
+
+         # echo "FABSE" > /proc/sys/kernel/kmsgdump
+
+This one will ask to dump raw messages at the end of the diskette in drive B
+and halt :
+
+         # echo "RABOET79U1" > /proc/sys/kernel/kmsgdump
+
+And this one will ask for a quick reboot :
+
+         # echo "DB" > /proc/sys/kernel/kmsgdump
+
+
+4.3. Prepare a disk for kmsgdump
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If safe mode is required, before an automatic dump, the system will read
+the beginning of the floppy in the drive and will look for the word "KMSGDUMP"
+at offset 3 of the first sector. This is the label of the diskette. The dump
+will only be performed if this word is found as-is. So if you enable safe mode
+don't forget to prepare your diskettes with the following command, provided
+your diskette is in drive A :
+
+         # echo "012KMSGDUMP" > /dev/fd0
+
+Please note that when the dump is performed in FAT mode, this word is written
+to the same place. This has two side effects :
+    - a diskette on which a dump has been done in FAT mode is re-usable without
+      intervention.
+    - you can prepare a diskette by entering kmsgdump (SysRQ+D) and doing a
+      FAT mode dump.
+
+On the other hand, when a RAW dump is done at the beginning of the disk, it
+cannot be used again as a "safe kmsgdump disk". Moreover, leaving it in the
+drive when rebooting will cause the system to hang if the bios tries to boot
+from the floppy first.
+
+4.4. Prepare the PC for a crash
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Because you'll have to leave a diskette in a drive, you may have to setup
+your bios to boot from hard disk or anything but the floppy first because
+the bios will find anything but a bootable system on this floppy. The problem
+is with older systems on which the boot sequence cannot be changed. For this
+reason, when a diskette is formatted in FAT mode, a small code is inserted on
+the boot sector which tries to redirect the boot to the first hard disk seen
+by the bios. This is *generally* the bootable disk, but this may not be the
+right on specific systems, so you may have to do some tests before considering
+this option to be the right one for you.
+
+If your system is a server, you may reduce the time the bios tests the PC to
+ensure quick reboot. On some systems, you can turn on the option "Quick
+power-on self test", and disable testing of memory above 1MB.
+
+
+5. Reading the messages back
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+5.1. FAT-formatted disks
+~~~~~~~~~~~~~~~~~~~~~~~
+
+If the disk has been formatted as FAT12, you'll find on it a file
+named "MESSAGES.TXT" which contains all of the 'messages' buffer. If the
+buffer is not full, the end of the file is filled with zeroes, so
+it's better to delete them using "tr" under linux.
+
+  - under Linux, either mount the disk :
+
+       # mount -rt msdos /dev/fd0 /mnt
+       # cat /mnt/messages.txt | tr -d '\000'
+       # umount /mnt
+
+    or read it using mtools :
+
+       # mtype a:messages.txt | tr -d '\000'
+
+  - under DOS, you can simply run EDIT :
+
+       C:\> edit a:messages.txt
+
+  - under Windows, you can open the file with Wordpad. Avoid using
+    Notepad since it doesn't understand linefeeds only.
+
+5.2. RAW disks
+~~~~~~~~~~~~~~
+
+Raw disks will be readable under linux by using the utility DD. By
+default, the dump will be performed from the first sector of the disk.
+Example with 16 kB messages buffer:
+
+       # dd if=/dev/fd0 bs=512 count=32 | tr -d '\000'
+
+If you specified "T79" in the parameters to dump on track 79 of the disk,
+you have to do some calculations :
+
+A 1.44 MB disk has 18 sectors/track, 2 heads and 512 bytes/sector so
+18*2*512 equals 18432 bytes/track. You'll have to skip 18432 bytes for
+each unwanted track. But you can also count only with kilobytes : if you
+consider that a track is exactly 18 kilobytes, then skip the number of
+tracks times 18 kilobytes :
+
+       # expr 79 \* 18
+       1422
+       # dd if=/dev/fd0 bs=1024 skip=1422 count=16 | tr -d '\000'
+
+The default dd utility reads all data from the start of the disk so this can
+be quite long. There are other implementations on the net which do an "lseek"
+before the first read.
+
+
+6. Other speed improvements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Here is some advice to make a system reboot faster, especially if
+you don't use filesystem journalling.
+
+When a file server crashes, it may FSCK for a long time. There are good docs
+about how to dramatically reduce FSCK time, but at least consider these 
+methods :
+
+    - in /etc/fstab, set the sixth field (fs_passno) to 1 for the root fs,
+      and 2 for every other fs. FSCK will know it what it can parallelize
+      depending on hardware dependencies. In the better case, you can divide
+      the total time by the number of physical disks.
+      (man fstab and man fsck for more info).
+
+    - when possible, mount filesystems read-only. On an anonymous FTP server,
+      for example, it's not always necessary to mount everything RW. So before
+      copying files onto an fs, remount it RW :
+
+         # mount -wo remount /mount/point
+
+      At the end, remount it RO :
+ 
+         # mount -ro remount /mount/point
+
+    - change the number of bytes by inode and the block size when formatting
+      your FS. I personnaly use 16384 bytes/inode, a block size of 4096 bytes,
+      the sparse flag set (reduces the number of superblocks). This makes me
+      waste about 1% space, but total mount time is about 1 second for a total
+      of 8 FS's, 11 gigs on 5 separate disks and the total FSCK time after a
+      loosy power-off is less than 3 minutes.
+
+    - use a Linux journaling file system, such as ext3fs, IBM JFS, or
+      reiserfs in Linux 2.4, or any any of those or SGI XFS in Linux 2.5
+
+And of course, don't start services you don't need ! Sendmail itself can take
+a long time if it cannot resolve the domain name.
+
+
+7. For more information and/or suggestions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For more informations, you can email me at :
+
+       willy AT meta-x.org
+
+( be patient, I read my mail when I can, and can't always reply. I'm
+  used to "tail -1000 $MAIL|less" or "less +G $MAIL" )
+
+For suggestions, you can either email them to me, or share them with
+the Linux Kernel Mailing List :
+
+       linux-kernel@vger.kernel.org
+
+Enjoy using it,
+
+Willy
+
diff -Nuarp linux-2.6.6/arch/i386/Kconfig linux-2.6.6_K1/arch/i386/Kconfig
--- linux-2.6.6/arch/i386/Kconfig	2004-05-10 11:32:01.000000000 +0900
+++ linux-2.6.6_K1/arch/i386/Kconfig	2004-06-14 16:03:52.624741294 +0900
@@ -1294,6 +1294,94 @@ config X86_MPPARSE
 	depends on X86_LOCAL_APIC && !X86_VISWS
 	default y
 
+config KMSGDUMP
+	bool "Kernel messages dumper"
+	depends on EXPERIMENTAL
+	default n
+	help
+	  If you say Y here, you will get maximal chances to save your kernel
+	  messages under weird conditions : you'll be able to display them on
+	  the screen, print them on a parallel printer, and dump them onto a
+	  floppy diskette. You will have to press SysRQ + D to access this
+	  feature, or wait for a kernel panic. In the last case, it is also
+	  possible to ask the kernel not to wait for any human operation, and
+	  automatically dump its messages onto a diskette (see the option
+	  CONFIG_KMSGDUMP_AUTO below).
+	
+	  Warning: when using this feature, the CPU is rebooted in real mode
+	  and the kernel won't recover. If messages are dumped onto a floppy,
+	  this floppy will be erased, unless you enable the option
+	  CONFIG_KMSGDUMP_SAFE below. More info can be found in the file
+	  Documentation/kmsgdump.txt.
+	
+	  All options below are used for default behaviour, but can be set
+	  by writing to /proc/sys/kernel/kmsgdump if CONFIG_SYSCTL is enabled.
+	  
+	  Don't say Y unless you really want to hack your kernel and/or help
+	  developers to debug it. This isn't a toy, you have been warned !
+
+config KMSGDUMP_FAT
+	bool "floppy as FAT by default"
+	depends on KMSGDUMP
+	help
+	  By default, when CONFIG_KMSGDUMP is enabled, all messages dumped on
+	  a floppy are in raw format, beginning at the first sector of the
+	  diskette. By enabling this option, you'll change the default format
+	  to FAT12. Although this is selectable under interactive mode, this is
+	  not the case after a kernel panic, where this option applies most.
+	
+	  When FAT is selected, the messages are saved into a file named
+	  MESSAGES.TXT. This practice is discouraged if you share your computer
+	  with anyone else, since other people may believe that if FAT is
+	  supported, the contents of the diskette would not be lost, which is
+	  false. It's better if people remember that the diskette is unusable
+	  after a dump. On the other hand, accessing the file after a crash is
+	  easier when the diskette is formatted as FAT. One other advantage of
+	  FAT is that the boot sector of the diskette is filled with a boot
+	  redirector which makes the system boot from the first hard disk even
+	  if the bios tried to boot from the floppy. If unsure, say Y.
+
+
+	
+
+config KMSGDUMP_AUTO
+	bool "Automatic dump then reboot on kernel panic"
+	depends on KMSGDUMP
+	help
+	  When the kernel panics, it normally hangs or reboots. With
+	  CONFIG_KMSGDUMP enabled, it will either enter the interactive mode
+	  you can see by pressing SysRQ + D (default), or, if you say Y here,
+	  automatically dump its messages buffer onto a diskette and then 
+	  reboot.
+	
+	  Enabling this is dangerous because if a diskette is left in the
+	  floppy drive, it may be destroyed (unless you enable the option
+	  CONFIG_KMSGDUMP_SAFE below), but in case of a server, this might
+	  be interesting since this one will automatically reboot after a
+	  panic. Don't say Y here if this kernel is to be installed on a
+	  floppy ! You would say Y in case of a server, N in case of a
+	  workstation.
+
+config KMSGDUMP_SAFE
+	bool "Limit dump to pre-initialized floppies only"
+	depends on KMSGDUMP
+	help
+	  When CONFIG_KMSGDUMP_AUTO is enabled, the kernel can automatically
+	  dump its messages onto the floppy present in the drive during a
+	  crash. This can be dangerous because if a floppy has been forgotten
+	  in the drive it may be overwritten. By enabling this option, the
+	  kernel will accept to write to the floppy only if it finds the word
+	  "KMSGDUMP" at offset 3 on the floppy.
+	
+	  So to prepare a disk to accept dumps, you just have to do this :
+	
+	        echo "012KMSGDUMP" > /dev/fd0
+	
+	  Please note that in case of interactive mode dump, this check is
+	  never made because we consider that the user knows what stands on
+	  his diskettes. If unsure, just say "Y".
+
+
 endmenu
 
 source "security/Kconfig"
diff -Nuarp linux-2.6.6/arch/i386/kernel/Makefile linux-2.6.6_K1/arch/i386/kernel/Makefile
--- linux-2.6.6/arch/i386/kernel/Makefile	2004-05-10 11:32:02.000000000 +0900
+++ linux-2.6.6_K1/arch/i386/kernel/Makefile	2004-06-14 16:03:52.625741145 +0900
@@ -30,6 +30,7 @@ obj-y				+= sysenter.o vsyscall.o
 obj-$(CONFIG_ACPI_SRAT) 	+= srat.o
 obj-$(CONFIG_HPET_TIMER) 	+= time_hpet.o
 obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
+obj-$(CONFIG_KMSGDUMP)		+= kmsg_reboot.o kmsgdump.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_X86_STD_RESOURCES)	+= std_resources.o
 
diff -Nuarp linux-2.6.6/arch/i386/kernel/kmsg_reboot.c linux-2.6.6_K1/arch/i386/kernel/kmsg_reboot.c
--- linux-2.6.6/arch/i386/kernel/kmsg_reboot.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.6_K1/arch/i386/kernel/kmsg_reboot.c	2004-06-14 16:21:55.749954051 +0900
@@ -0,0 +1,315 @@
+/*
+ * kmsg_reboot.c
+ * reboots to real mode for kmsgdump
+ * author: Willy Tarreau  <willy AT meta-x.org>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mc146818rtc.h>
+
+static struct
+{
+	unsigned short       size __attribute__ ((packed));
+	unsigned long long * base __attribute__ ((packed));
+}
+no_idt = { 0, 0 };
+
+#include "mach_reboot.h"
+#include <asm/kmsgdump.h>
+#include <asm/apic.h>
+
+/* use KDEBUG to control whether kdebug() is defined */
+#undef KDEBUG
+
+#ifdef KDEBUG
+#define kdebug(fmt,arg...) \
+	printk(KERN_DEBUG fmt,##arg)
+#else
+#define kdebug(fmt,arg...) \
+	do { } while (0)
+#endif
+
+
+extern void dump_syslog(char * buf);
+
+/* checkpoint counter used to try to recover from recursive system crashes */
+static int chkpnt = 0;
+
+/* boot-time default flags. These are single character indicators except for T (track number)
+   and U (unit number) which must be followed by a number. To avoid confusion with default
+   values, each flag has its complement and you are strongly encouraged to use one of each.
+
+   flags available are :
+   Name Description         Default Complement
+   F    FAT mode              Yes   R
+   R    Raw mode                    F
+   A    Automatic mode        Yes   I
+   I    Interactive mode            A
+   B    Boot after dump       Yes   H   only used in automatic mode
+   H    Halt after dump             B   only used in automatic mode
+   S    Safe mode             Yes   O   only used in automatic mode
+   O    Overwrite disk              S   only used in automatic mode
+   E    Enable dumping        Yes   D   only used in automatic mode
+   D    Disable dumping             E   only used in automatic mode
+   Txxx Track xxx             0   (N/A) first track is 0 per default
+   Uxxx Unit xxx              0   (N/A) bios drive is 0 (A:) per default
+*/
+char kmsgdump_flags[16]=
+#ifdef CONFIG_KMSGDUMP_FAT
+	"F"	/* Fat */
+#else
+	"R"	/* Raw */
+#endif
+#ifdef CONFIG_KMSGDUMP_AUTO
+	"AEB"	/* Auto, Dump, Boot */
+#else
+	"IE"	/* Interactive, Dump */
+#endif
+#ifdef CONFIG_KMSGDUMP_SAFE
+        "S"
+#else
+        "O"
+#endif
+        "T0U0"; /* Safe,Track0,Unit0 */
+
+/*
+ * machine_dump() : Added on 19990628 by Willy Tarreau <willy AT meta-x.org>
+ *
+ * This is used to dump the kernel messages buffer onto a floppy diskette.
+ * The system is rebooted to real mode so it will be unuseable after a call
+ * to this function which never returns.
+ * The argument to this function is the caller type (DUMP_FROM_PANIC=0 or
+ * DUMP_FROM_SYSRQ=1).
+ *   
+ * Note 1 : Part of this code has been shamelessly stolen from machine_restart().
+ *          Perhaps it should be better to implement a generic rebooting function.
+ * Note 2 : I couldn't manage to get the <reboot_thru_bios> method to work
+ *          here. The bios never calls my code. After hundreds of reboots,
+ *          I finally accepted the fact that the PC is stronger than the human
+ *          and only kept the reset method. But be careful, Linus' comment
+ *          about it not working properly on some hardware still applies here.
+ * Note 3 : I don't know what means we have on other architectures to dump
+ *          messages, but it will be interesting to add this feature to all archs.
+ */
+
+#if LOG_BUF_LEN >= 0x10000
+#error LOG_BUF_LEN is too large!!!
+#error The log buffer must be < 64 KB for kmsgdump.
+#endif
+
+void machine_dump(int callertype)
+{
+	int modeflags=MASK_OUTPUTFAT | MASK_PANICDUMP | MASK_PANICBOOT | MASK_SAFEDUMP;
+	int track=0;	/* by default, track 0 */
+	int unit=0;	/* and drive A */
+	
+	if (chkpnt<100) {
+	    chkpnt=100;
+		kdebug("KMD: cp 100\n");
+	    local_irq_disable();
+	    chkpnt++;
+#ifdef CONFIG_SMP
+	    /*
+	     * Stop all CPUs and turn off local APICs and the IO-APIC, so
+	     * other OSs see a clean IRQ state.
+	     */
+	    smp_send_stop();
+	    disable_IO_APIC();
+	    chkpnt++;
+#endif
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	    /* if this CPU is using local APIC, we must disable it */
+	    if (test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability)) {
+	      unsigned long l, r;
+	      disable_local_APIC();
+	      disconnect_bsp_APIC();
+	      rdmsr(MSR_IA32_APICBASE, l, r);
+	      l &= ~MSR_IA32_APICBASE_ENABLE;
+	      wrmsr(MSR_IA32_APICBASE, l, r);
+	    }
+#endif
+	}
+	/* Write 0x09 to CMOS register number 0x0f, which the BIOS POST
+	   routine will recognize as telling it to :
+	     - re-initialize a few parts of hardware ;
+	     - load registers from a structure pointed to at [40:67] ;
+	     - branch to the program at offset 0x14 in this structure.
+
+	   [Note: funciton 0x0A is easier to use, but doesn't re-initialize
+	          anything and might not work on specific harware.          ]
+	*/
+
+	if (chkpnt<200) {
+	    unsigned long flags;
+	    chkpnt=200;
+		kdebug("KMD: cp 200\n");
+            spin_lock_irqsave(&rtc_lock, flags);
+	    outb_p (0x8f, 0x70);
+	    chkpnt++;
+	    outb_p (0x09, 0x71);
+	    chkpnt++;
+            spin_unlock_irqrestore(&rtc_lock, flags);
+	}
+
+	/* Remap the kernel at virtual address zero, as well as offset zero
+	   from the kernel segment.  This assumes the kernel segment starts at
+	   virtual address PAGE_OFFSET. */
+
+	if (chkpnt<300) {
+	    chkpnt=300;
+		kdebug("KMD: cp 300\n");
+	    memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+		    sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
+	    chkpnt++;
+	}
+
+	/* Make sure the first page is mapped to the start of physical memory.
+	   It is normally not mapped, to trap kernel NULL pointer dereferences.
+	*/
+
+	if (chkpnt<400) {
+	    int page;
+
+	    chkpnt=400;
+		kdebug("KMD: cp 400\n");
+	    for (page=0; page < ((FREEMEMORY+PAGE_SIZE-1) >> PAGE_SHIFT); page++)
+		pg0[page] = _PAGE_RW | _PAGE_PRESENT;
+	    chkpnt++;
+	}
+	
+	/*
+	 * Use `swapper_pg_dir' as our page directory.
+	 */
+
+	if (chkpnt<500) {
+	    chkpnt=500;
+		kdebug("KMD: cp 500\n");
+	    asm volatile("movl %0,%%cr3": :"r" (__pa(swapper_pg_dir)));
+	    chkpnt++;
+	}
+
+	/* to avoid that the bios thinks we pressed Ctrl-Alt-Del : */
+	if (chkpnt<600) {
+	    chkpnt=600;
+		kdebug("KMD: cp 600\n");
+#ifdef REALLY_USE_REBOOT_SETUP
+	    reboot_setup("c", NULL);
+	    chkpnt++;
+	    *((unsigned short *)0x472) = reboot_mode;
+#else
+	    *((unsigned short *)0x472) = 0x0;
+#endif
+	    chkpnt++;
+	}
+	/* For the switch to real mode, copy some code to low memory, out of
+	   the way of BIOS variables. */
+
+	if (chkpnt<700) {
+	    chkpnt=700;
+		kdebug("KMD: cp 700\n");
+	    memset ((char *)CODEORIGIN, 0, 0x1000-CODEORIGIN); /* get a clean first page */
+	    chkpnt++;
+
+	    /* the main real mode code */
+	    memcpy ((char *)CODEORIGIN, kmsgdump, kmsgdump_end-kmsgdump);
+	    chkpnt++;
+	}
+
+	/* configure parameters from kmsgdump_flags */
+	if (chkpnt<800) {
+	    char *c;
+	    int *var = NULL;
+	    int val = 0;
+	    chkpnt = 800;
+		kdebug("KMD: cp 800\n");
+
+	    c = kmsgdump_flags;
+	    while (*c) {
+		switch(*c) {
+		case 'F' : modeflags |=  MASK_OUTPUTFAT; break;
+		case 'R' : modeflags &= ~MASK_OUTPUTFAT; break;
+		case 'I' : modeflags |=  MASK_PANICMAN; break;
+		case 'A' : modeflags &= ~MASK_PANICMAN; break;
+		case 'B' : modeflags |=  MASK_PANICBOOT; break;
+		case 'H' : modeflags &= ~MASK_PANICBOOT; break;
+		case 'S' : modeflags |=  MASK_SAFEDUMP; break;
+		case 'O' : modeflags &= ~MASK_SAFEDUMP; break;
+		case 'E' : modeflags |=  MASK_PANICDUMP; break;
+		case 'D' : modeflags &= ~MASK_PANICDUMP; break;
+		case 'T' : var = &track; val = 0; break;
+		case 'U' : var = &unit;  val = 0; break;
+		}
+		if (*c>='0' && *c<='9')
+		    val=(val*10)+(*c-'0');
+		c++;
+		/* when the number ends, assign it to the variable */
+		if ((*c<'0' || *c>'9') && (var != NULL)) {
+		    *var = val;
+		}
+	    }
+	    chkpnt++;
+
+	    *(char *)DRIVENUM = unit;
+	    chkpnt++;
+	    *(char *)TRACKNUM = track;
+	    chkpnt++;
+
+	    /* this will be configurable one day too :-) */
+	    *(char *)MODEFLAGS = modeflags;
+	    chkpnt++;
+	}
+
+
+	if (chkpnt<900) {
+	    chkpnt=900;
+		kdebug("KMD: cp 900\n");
+	    if (callertype == DUMP_FROM_SYSRQ)
+		*(char *)MODEFLAGS |= MASK_SYSRQMODE;
+	    chkpnt++;
+	}
+
+
+	if (chkpnt<1000) {
+	    chkpnt=1000;
+		kdebug("KMD: cp 1000\n");
+	    memset (phys_to_virt(BEGINOFMESSAGES), 0, LOG_BUF_LEN); /* pre-initialize the messages buffer */
+	    chkpnt++;
+	    dump_syslog(phys_to_virt(BEGINOFMESSAGES)); /* get last messages */
+	    chkpnt++;
+	}
+
+	/* We only have to inform the BIOS to where we need to jump,
+	   and initialize an image of the register bank in memory. */
+	if (chkpnt<1100) {
+	    chkpnt=1100;
+		kdebug("KMD: cp 1100\n");
+	    *((unsigned short *)(BOOTSTACKFRAME+0x16)) = 0;	       	/* CS */
+	    chkpnt++;
+	    *((unsigned short *)(BOOTSTACKFRAME+0x14)) = CODEORIGIN;	/* IP */
+	    chkpnt++;
+
+	    *((unsigned short *)0x467) = ((int)BOOTSTACKFRAME)    & 0xFFFF;
+	    chkpnt++;
+	    *((unsigned short *)0x469) = ((int)BOOTSTACKFRAME)>>4 & 0xF000;
+	    chkpnt++;
+	}
+
+	/* now we have to hard-reset the CPU. */
+	if (chkpnt<1200) {
+	    chkpnt=1200;
+	    for (;;) {
+		kdebug("KMD: cp %d\n", chkpnt);
+		mach_reboot();
+
+		/* That didn't work - force a triple fault.. */
+		__asm__ __volatile__("lidt %0": :"m" (no_idt));
+		__asm__ __volatile__("int3");
+	    }
+	    chkpnt++;
+	}
+}
diff -Nuarp linux-2.6.6/arch/i386/kernel/kmsgdump.S linux-2.6.6_K1/arch/i386/kernel/kmsgdump.S
--- linux-2.6.6/arch/i386/kernel/kmsgdump.S	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.6_K1/arch/i386/kernel/kmsgdump.S	2004-06-14 16:03:52.628740699 +0900
@@ -0,0 +1,898 @@
+/*
+ *	file	: kmsgdump.S
+ *	version	: 0.4.4/2002042801
+ *	author	: Willy Tarreau  <willy AT meta-x.org>
+ *	
+ * This code is called from the Bios when the processor has been
+ * externally reset and the NVRAM has been set to tell the bios
+ * to quickly branch to the pointer at [0x40:0x67].
+ * It executes in real mode, and starts from 0:0x700.
+ *
+ * Its purpose is to dump the last kernel messages onto a floppy disk
+ * or to print them on a parallel printer.
+ *
+ * Useful information are stored at the following hexadecimal adresses :
+ *	0:0700 - 0FAF     = this code followed by the stack
+ *      0:0FB0 - 0FEF     = bios stack frame at reboot time
+ *	0:0FF0 ( 8 bits ) = destination drive number (bios number)
+ *	0:0FF1 ( 8 bits ) = track number (<256 !)
+ *	0:0FF2, bit 7     = caller mode (0=panic, 1=SysRq)
+ *	        bit 6     = output format (0=RAW, 1=FAT)
+ *	        bits 5->3 = behaviour when called from panic() :
+ *	                       000 = no dump, just halt
+ *	                       001 = no dump, just reboot
+ *	                       010 =    dump, then halt
+ *	                       011 =    dump, then reboot
+ *	                       100 = go to manual operation, just like SysRq.
+ *	                       others undefined, so don't use please. Thanks.
+ *	0:0FF3 (13 bytes) = not used yet
+ *	
+ *	0:1000 - 4FFF    = kernel messages buffer contents (16 kB).
+ *
+ * Warning: This code is 16-bits, while the rest of the kernel is 32-bits.
+ *          I couldn't find a way to link this file together with 32-bits
+ *          files, just because of relative references which caused
+ *          relocation issues. As a last resort, every variable is referenced
+ *          "variable-base+CODEORIGIN" which is absolute and links well  :-/
+ *          If someone finds a better way to do this, I'd like to learn from
+ *          him.
+ */
+#include <linux/version.h>
+#include <linux/config.h>
+#include <asm/kmsgdump.h>
+	
+#define	_pause		jmp	.+2
+.text
+.code16
+	
+.global	kmsgdump
+.global	kmsgdump_end
+
+/*
+ * I use this only for development, it's a bios bootstrap.
+ * You only have to define UNDER_DEVEL and the binary object
+ * can be copied to a raw diskette and will boot from it.
+ * Moreover, the code contains the KMSGDUMP identifier so that
+ * the diskette is useable as-is.
+ */
+#ifdef UNDER_DEVEL
+bootstrap:	
+	jmp	0f
+	.byte	0x90
+	.ascii	"KMSGDUMP"
+0:	
+	cli
+	xorw	%ax, %ax
+	movw	%ax, %ss
+	movw	$0x7C00	, %sp
+	pushw	%ss
+	popw	%es
+	movw	%cs, %ax
+	movw	%ax, %ds
+	movw	$1000,%cx
+	movw	$(kmsgdump-bootstrap+0x7c00), %si
+	movw	$CODEORIGIN, %di
+	cld
+	rep
+	movsb
+/*	movw	$MASK_SYSRQMODE, MODEFLAGS*/
+	movw	$(MASK_PANICDUMP|MASK_PANICBOOT|MASK_OUTPUTFAT|MASK_SAFEDUMP), MODEFLAGS
+
+# read remaining sectors
+	
+	movw	$0x0203, %ax
+	movw	$(bootstrap-kmsgdump+CODEORIGIN+0x200), %bx
+	movw	$0x0002, %cx
+	movw	$0x0000, %dx
+	int	$0x13
+	
+# pre-read messages
+	mov	$0x220, %ax		/* ah=2 (read), al=32 (32 sectors) */
+	mov	$(BEGINOFMESSAGES), %bx
+	mov	$0x0005, %cx
+	mov	$0, %dx			/* head always begins with 0 */
+	int	$0x13
+	
+	ljmp	$0, $CODEORIGIN
+#endif		/* UNDER_DEVEL */
+	
+kmsgdump:
+	cli
+	xorw	%ax, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
+	movw	%ax, %ss
+	movw	$(TOPOFSTACK), %sp
+	call	hardware_reset
+	sti
+	testb	$(MASK_SYSRQMODE | MASK_PANICMAN), MODEFLAGS
+	jz	automatic
+
+/* Here is the manual mode loop (either SysRq or Panic with MANUAL flag set).
+ * Each second, a short beep is sent so that the user knows the computer
+ * is waiting for him/her to press a key.
+ * When 'B' is hit, the system immediately reboots. When 'H' is hit, the
+ * system halts, and when another key is hit, the system attempts a dump
+ * and beeps two more times in case of success. It then goes on waiting
+ * for a key in case the user wants another dump.
+ */
+manual_dump:
+/* reinitialize display to color_80x25 */
+	movw	$0xe, %ax	/* force a switch to graph mode to help in reinitialization */
+	int	$0x10
+	movw	$VIDEOMODE, %ax
+	int	$0x10
+/* hide the cursor */
+	movb	$1, %ah
+	movw	$0xFFFF,%cx
+	int	$0x10
+/* redraw the screen */
+	xorw	%cx, %cx
+	call	clearwindow
+/* display title */
+	movw	$MKWORD(0,22), %dx
+	movw	$(title-kmsgdump+CODEORIGIN), %si
+	call	displayline
+/* display separation and help line */
+	movw	$MKWORD(HELPLINE, 0), %dx
+	call	movecursor
+	movw	$MKWORD(0x0A, 177), %ax	/* write a line of hashes */
+	movb	$0, %bh
+	movw	$(RIGHTCOL+1), %cx	/* a full line */
+	int	$0x10
+	movw	$MKWORD(HELPLINE, 12), %dx	/* display help at column 12 */
+	movw	$(helpline-kmsgdump+CODEORIGIN), %si
+	call	displayline
+	
+# now we'll have to print the messages buffer in the lower window.
+redrawmessages:	
+	movw	$MKWORD(HELPLINE+2,0), %cx	/* first line of the messages window */
+	pushw	%cx		/* save this, it will serve us later */
+	call	clearwindow
+	popw	%dx		/* restore top of window */
+	mov	$(BEGINOFMESSAGES), %si	/* SI points to the beginning of the messages */
+	xorw	%di,%di			/* first line */
+	jmp	findline
+1:	lodsb
+	or	%al,%al			/* end of data ? */
+	jnz	3f		
+	movw	%di, currentline-kmsgdump+CODEORIGIN	/* we fix the end at this point.  */
+	jmp	waitevent		/* and don't show anything */
+3:	cmp	$10, %al
+	jnz	1b		/* while not LF, look for an end of line */
+	inc	%di		/* count one more line */
+findline:	
+	cmpw	currentline-kmsgdump+CODEORIGIN, %di
+	jb	1b
+showmessages:
+	cmpw	$(LOG_BUF_LEN+BEGINOFMESSAGES), %si	/* end of buffer reached */
+	jnb	waitevent
+	call	displayline
+	cmp	$BOTTOMLINE, %dh	/* stop displaying when screen is full */
+	ja	waitevent
+	or	%al,%al			/* or when end of messages is reached */
+	jnz	showmessages
+# redisplay current parameters after each pressed key
+waitevent:
+	cmpb	$0, mustredraw-kmsgdump+CODEORIGIN	/* if we must redraw the messages window, let's do it */
+	movb	$0, mustredraw-kmsgdump+CODEORIGIN
+	jnz	redrawmessages
+
+/* now, we'll display current settings (drive, format, status ...) */
+	movw	$MKWORD(2, 8), %dx	/* row 2, col 8 */
+	movw	$(msgprinter-kmsgdump+CODEORIGIN), %si
+	call	displayline
+
+	movb	DRIVENUM,%al
+	addb	$'A', %al		/* A and B if < 0x80 */
+	test	$0x80, %al
+	jz	1f
+	subb	$(0x80-'C'+'A'), %al	/* C and D if >= 0x80 */
+1:	movb	%al, unitname-kmsgdump+CODEORIGIN		/* write the drive letter into the string */
+	movw	$MKWORD(2, 40), %dx	/* row 2, col 40*/
+	movw	$(msgunit-kmsgdump+CODEORIGIN), %si
+	call	displayline
+/* SI is already positionned at msgFAT, so we avoid "movw $msgFAT,%si" */
+	testb	$(MASK_OUTPUTFAT), MODEFLAGS
+	jnz	2f
+	movw	$(msgRAW-kmsgdump+CODEORIGIN), %si
+2:	call	displayline
+	movw	$MKWORD(3, 8), %dx	/* row 3, col 8 */
+	movw	$(kversion-kmsgdump+CODEORIGIN), %si
+	call	displayline
+
+1:	movb	$STATUS_WAITING, %al
+	call	showstatus
+8:	call	waitkey
+	jnz	1f		/* a key has been hit */
+	call	beep		/* no key hit: let's beep once a second */
+	jmp	waitevent	/* loop while no key is pressed */
+1:	cmpb	$0x50, %ah	/* down arrow */
+	jnz	5f
+7:	incw	currentline-kmsgdump+CODEORIGIN	/* go one line below */
+1:	movb	$1, mustredraw-kmsgdump+CODEORIGIN
+	mov	$1, %ah		/* we check if another key has been hit to speed up scrolling */
+	int	$0x16
+	jnz	8b		/* handle this new key */
+	jmp	waitevent
+5:	cmpb	$0x48, %ah	/* up arrow */
+	jnz	6f
+	subw	$1,currentline-kmsgdump+CODEORIGIN	/* one line back */
+	jc	7b		/* aie, negative line. Let's correct this */
+	jmp	1b
+6:	cmpb	$'b', %al	/* 'B' stands for 'boot' */
+	jz	do_reboot
+	cmpb	$'h', %al	/* 'H' stands for 'halt' */
+	jz	do_halt
+	cmpb	$'f', %al	/* 'F' stands for 'change Format' */
+	jnz	3f
+	xorw	$(MASK_OUTPUTFAT), MODEFLAGS
+	jmp	waitevent
+3:	cmpb	$'u', %al	/* 'U' stands for 'change Unit' */
+	jnz	4f
+	xorb	$1, DRIVENUM	/* altern first/second drive */
+	jmp	waitevent
+4:	cmpb	$'t', %al	/* 'T' stands for 'prinTer' */
+	jnz	5f
+	call	probeprinter
+	jmp	waitevent
+5:	cmpb	$'i', %al	/* 'I' stands for 'Info' (help/about) */
+	jnz	6f
+	movw	$MKWORD(HELPLINE+2,0), %cx	/* first line of the messages window */
+	pushw	%cx		/* save this, it will serve us later */
+	call	clearwindow
+	popw	%dx		/* restore top of window */
+	movw	$(aboutmsg-kmsgdump+CODEORIGIN), %si
+5:	call	displayline
+	or	%al, %al
+	jnz	5b	
+	jmp	waitevent
+6:	cmpb	$'p', %al	/* 'P' stands for 'Print' */
+	jnz	7f
+	call	printbuffer
+	jmp	8f		/* display same return codes as for diskette */
+7:	cmpb	$'d', %al	/* 'D' stands for 'dump' */
+	jnz	waitevent
+	call	do_dump
+8:	movb	$STATUS_WERR, %al	/* assume a dump error for now */
+	jc	9f		/* on error, we return immediately after only one beep */
+	movb	$STATUS_DUMPOK, %al /* else we say that's good */
+	call	beep		/* make 3 audible beeps once successfully dumped */
+	call	beep
+9:	call	showstatus
+	call	beep
+	movw	$16,%cx		/* wait 1 second after the message is displayed */
+0:	call	sleep54
+	loop	0b
+	jmp	waitevent
+
+/* clears the screen from the upper left corner defined by CX to the bottom right of the screen */
+clearwindow:
+	movw	$MKWORD(BOTTOMLINE,RIGHTCOL), %dx	/* bottom of screen */
+	movw	$0x0600, %ax	/* clear the messages window */
+	movb	$ATTRIB, %bh
+	int	$0x10
+	ret
+
+/* probes the next printer, and if not found, the next one, ... until
+   we find one which is OK, or we fall back to the current one.
+*/
+probeprinter:
+	movb	$STATUS_PROBING, %al
+	call	showstatus
+	movw	$3, %cx		/* we allow to automatically probe 3 printers */
+0:	movb	currentlpt-kmsgdump+CODEORIGIN, %al
+	incw	%ax
+	cmpb	$'3', %al
+	jbe	1f	
+	mov	$'1', %al
+1:	movb	%al, currentlpt-kmsgdump+CODEORIGIN
+	subb	$'1', %al
+	movzbw	%al, %dx	/* printer number */
+	movb	$1, %ah		/* initialize printer */
+	int	$0x17
+	testb	$0x2F, %ah	/* status = OK ? */
+	loopnz	0b		/* no, probe next printer */
+2:	ret
+	
+/* prints all the buffer on the current printer. On error, CF is set. */
+printbuffer:		
+	mov	$(BEGINOFMESSAGES), %si	/* SI points to the beginning of the messages */
+	movb	$STATUS_PRINTING, %al
+	call	showstatus
+	movb	currentlpt-kmsgdump+CODEORIGIN, %al
+	subb	$'1', %al
+	movzbw	%al, %dx	/* printer number */
+0:	cmpw	$(BEGINOFMESSAGES+LOG_BUF_LEN), %si
+	jae	9f		/* end of buffer */
+	lodsb
+	or	%al, %al	/* end of data */
+	jz	9f
+	cmp	$10, %al	/* line feed : we'll insert a carriage return */
+	jnz	1f
+	mov	$MKWORD(0, 13), %ax	/* print carriage return */
+	int	$0x17
+	mov	$10, %al	/* line feed */
+1:	movb	$0, %ah		/* print character */
+	int	$0x17
+	testb	$0x2F, %ah	/* status = OK ? */
+	jz	0b		/* fetch next char */
+	stc
+	ret
+9:	movw	$MKWORD(0, 12), %ax	/* form feed*/
+	int	$0x17
+	clc
+	ret
+	
+/* Automatic dump mode, without user operation. The function was called
+ * from panic(). Mode flags also allow an immediate reboot without a dump,
+ * which is the same than playing with "panic_timeout" in case of a kernel
+ * panic.
+ */
+automatic:
+	testb	$(MASK_PANICDUMP), MODEFLAGS
+	jz	1f
+	testb	$(MASK_SAFEDUMP), MODEFLAGS
+	jz	0f
+	/* a safe dump is requested. we must ensure the diskette contains a "KMSGDUMP"
+	   label before scratching it. */
+	xorw	%ax,%ax		/* reinitialize drive */
+	movzbw	DRIVENUM, %dx
+	int	$0x13
+
+	movw	$0x201, %ax	/* read 1 sector */
+	movw	$(FREEMEMORY), %bx	/* pointer to the buffer */
+	movw	$0x1, %cx	/* from sector 1 */
+	call	int13retry
+	jc	1f		/* read error, don't dump */
+	cmpl	$0x47534d4b, FREEMEMORY+3	/* "KMSG" */
+	jnz	1f
+	cmpl	$0x504d5544, FREEMEMORY+7	/* "DUMP" */
+	jnz	1f
+0:	call	do_dump
+1:	testb	$(MASK_PANICBOOT), MODEFLAGS
+	jnz	do_reboot
+	jmp	do_halt
+
+/* beep():
+ * Make a 54 ms beep, and silently pause during 54 ms
+ */
+beep:	call	sound_on
+	call	sleep54
+	call	sound_off
+	call	sleep54
+	ret
+	
+sleep54:
+	pushw	%ax
+	movw	CLOCKTICKS, %ax
+	incw	%ax
+0:	cmpw	CLOCKTICKS, %ax
+	jnb	0b
+	popw	%ax
+	ret
+			
+/* waitkey():
+ * Wait at most 3 second for a key press.
+ * If no key is pressed during that time, 0 is returned in AX and ZF is set.
+ * If a key is pressed, its lower case ascii code is returned in AL, its scan
+ * code in AH and the ZF is cleared.
+ */
+waitkey:
+	pushw	%cx
+	movw	CLOCKTICKS, %cx
+	addw	$55, %cx	/* 55/18.2 = 3 seconds */
+0:	movb	$1, %ah		/* function="tell if a key was pressed" */
+	int	$0x16
+	jnz	1f
+	cmpw	CLOCKTICKS, %cx
+	jnb	0b
+	xorw	%ax,%ax		/* timeout, no key */
+	jmp	2f
+1:	movb	$0, %ah
+	int	$0x16
+	cmpb	$'A',%al
+	jb	2f
+	cmpb	$'Z',%al
+	ja	2f
+	orb	$0x20,%al
+2:	popw	%cx
+	orw	%ax,%ax		/* ZF=(AX==0) */
+	ret
+
+	
+/* hardware_reset():
+   Reconfigure what can be wrong now in hardware :
+     - interrupt controller
+     - timers
+     - keyboard
+     - disk units
+*/
+hardware_reset:	
+/* PIC reconfiguration consists in mapping PIC#1 IRQ 0 to software INT 8.
+ * Although not needed, PIC#2 is initialized in case we meet buggy chipsets.
+ */
+
+	movb	$0x11, %al	/* reconfiguration */
+	out	%al, $0x20
+#	out	%al, $0xA0
+	_pause
+	movb	$8, %al		/* map irq 0 to int 0x08 */
+	out	%al, $0x21
+#	movb	$0x70, %al	/* map irq 8 to int 0x70 */
+#	out	%al, $0xA1
+	_pause
+	movb	$4, %al		/* master mode for PIC#1 */
+	out	%al, $0x21
+#	movb	$2, %al		/* slave mode for PIC#2 */
+#	out	%al, $0xa1
+	_pause
+	movb	$1, %al		/* 8086 mode */
+	out	%al, $0x21
+#	out	%al, $0xA1
+	_pause
+	movb	$0xFF, %al	/* all IRQs are masked at the moment */
+	out	%al, $0x21
+#	out	%al, $0xA1
+	_pause
+
+/* Disable internal speaker output if it was enabled */
+
+	call	sound_off
+	
+/* PIT reconfiguration : set Timer0 clock to 18.2 Hz */
+
+	movb	$0x34, %al	/* timer 0 in interrupt mode */
+	out	%al, $0x43
+	_pause
+	movb	$0, %al		/* divide by 65536 (1193182 Hz -> 18.2 Hz) */
+	out	%al, $0x40	/* LSB first */
+	_pause
+	out	%al, $0x40	/* MSB next */
+	_pause
+	
+/* PIT reconfiguration (cont'd) : set Timer2 clock to 880 Hz for the buzzer */
+
+	movb	$0xb6, %al	/* timer 2 in square wave mode */
+	out	%al, $0x43
+	_pause
+	movw	$1355, %ax	/* divider set to 1193182/1355 = 880 Hz */
+	out	%al, $0x42	/* LSB first */
+	_pause
+	movb	%ah, %al
+	out	%al, $0x42	/* MSB next */
+	_pause
+	
+	movb	$0xBC, %al	/* only irq 0,1,6 unmasked */
+	out	%al, $0x21
+	_pause
+
+/* Keyboard reset: The keyboard may be misconfigured. We will send it a
+   reconfiguration (max speed) so that the Bios will at least reconfigure it
+   and its controller (i8042).
+*/
+
+	mov	$0x305, %ax	/* set speed */
+	xorw	%bx, %bx	/* full speed */
+	int	$0x16
+
+/* Reset the minimum so that int 13 works */
+	movw	$0x3F2, %dx
+	movb	$0x0, %al
+	outb	%al, %dx
+	_pause
+	_pause
+	movb	$0xC, %al
+	outb	%al, %dx
+	_pause
+	_pause
+
+	xorw	%ax, %ax
+	xorw	%dx, %dx
+	int	$0x13
+	ret		
+
+/* sound_off(): disable internal speaker output. */
+sound_off:
+	push	%ax
+	in	$0x61, %al
+	andb	$0xFC, %al
+	jmp	1f		/* same code below */
+
+/* sound_on(): enable internal speaker output. */
+sound_on:
+	push	%ax
+	in	$0x61, %al
+	orb	$3, %al
+1:	_pause
+	out	%al, $0x61
+	pop	%ax
+	ret
+
+/* HALT the CPU */
+do_halt:
+	movb	$STATUS_HALTING, %al
+	call	showstatus
+0:	cli
+	hlt
+	jmp	0b		/* just in case of NMIs */
+
+
+/* REBOOT the CPU */
+do_reboot:
+	movb	$STATUS_BOOTING, %al
+	call	showstatus
+	cli
+/* Make sure [40:72] doesn't contain 0x1234, which the Bios will interprete as
+   Ctrl-Alt-Del. */
+	movw	$0, 0x472
+	ljmp	$0xFFFF,$0	/* branch to bios boot strap */
+
+/*
+ * do_dump():
+ * This function dumps the message buffer onto a disk. CF is set if an error
+ * occurred.
+ *
+ */
+do_dump:
+	movb	DRIVENUM, %dl
+	xorw	%ax, %ax
+	int	$0x13		/* reinitialize drive */
+	xorw	%si, %si	/* assume first data sector = 0 */
+	testb	$(MASK_OUTPUTFAT), MODEFLAGS
+	jz	1f
+	movw	$(FATSIZE*2+2), %si	/* when FAT is used, data go further */
+1:	call	makefat
+	jc	2f
+	call	dumpdata
+2:	ret
+
+/*
+ * Shows, in the status line, the message matching the status code in AL.
+ * AX, BX, DX and FLAGS contents are lost. CX and SI are kept.
+ */
+showstatus:
+	cbw
+	pushw	%si
+	pushw	%cx
+	testb	$(MASK_SYSRQMODE | MASK_PANICMAN), MODEFLAGS
+	jz	2f	/* is not in interactive mode, don't show anything */
+	pushw	%ax
+	movw	$MKWORD(3, 40), %dx
+	movw	$(msgstatus-kmsgdump+CODEORIGIN), %si
+	call	displayline
+	popw	%si
+	cmpw	$STATUS_MAXMSG, %si
+	ja	2f
+	shlw	$4, %si
+	addw	$(statwait-kmsgdump+CODEORIGIN), %si
+1:	call	displayline
+2:	popw	%cx
+	popw	%si
+	ret
+/*
+ * sets the cursor to the begin of the line in DH, col in DL, and displays the message from SI
+ * which ends with \n, \r or \0. On return, AL contains the byte that ended the line, and SI
+ * points to the next byte.
+ * if LF is encountered, the cursor is positionned at the beginning of the next line and
+ * LF is returned in AL, the cursor position in DX.
+ * If DH is set to -1, then the cursor isn't moved. The new cursor position is returned into
+ * DX so it's possible to recall displayline immediately.
+ */
+displayline:
+	cmpb	$-1,%dh
+	jz	0f
+	call	movecursor
+0:	cld
+1:	movb	$ATTRIB, %bl	/* use standard text attribute by default */
+	lodsb
+	cmp	$0377, %al	/* a 0377 char means next one will be highlit */
+	jnz	3f
+	movb	$HIGHLIGHT, %bl
+	lodsb	
+3:	cmp	$13, %al	/* CR is ignored */
+	jz	1b
+	or	%al, %al	/* end of messages */
+	jz	2f
+	cmp	$10, %al	/* LF: position onto next line and return from function */
+	jnz	5f
+	pushw	%ax
+	call	findcursor	/* DX gets the current cursor position */
+	movb	$255, %dl	/* if we pass the end of the line, we'll begin on a new row */
+	call	movecursor
+	popw	%ax		/* restore LF in AX */
+	jmp	2f		/* and we return */
+5:	movb	$0, %bh		/* current page = 0 */
+	movw	$1, %cx		/* 1 char */
+	movb	$9, %ah		/* write char with attribute */
+	int	$0x10
+	call	findcursor	/* DX gets the current cursor position */
+	inc	%dx		/* next position */
+	call	movecursor
+	jmp	1b
+movecursor:
+	cmp	$RIGHTCOL, %dl	/* did we override the end of the line ? */
+	jbe	1f		/* no */
+	inc	%dh		/* yes, so position onto the next line */
+	movb	$0, %dl
+1:	movb	$2, %ah
+4:	movb	$0, %bh
+	int	$0x10
+2:	ret
+findcursor:
+	mov	$3, %ah
+	jmp	4b
+
+#if defined(UNDER_DEVEL) & defined(DEBUG)
+showhex:
+	pushfw
+	pushaw
+	movw	%ax, %si
+	movw	$4, %cx
+0:	pushw	%cx
+	rolw	$4, %si
+	movw	%si, %ax
+	andb	$0xF, %al
+	addb	$'0', %al
+	cmpb	$'9', %al
+	jbe	1f
+	addb	$7, %al
+1:	movb	$0xE, %ah
+	int	$0x10
+	popw	%cx
+	loop	0b
+#ifdef STEP_BY_STEP	
+	movb	$0, %ah
+	int	$0x16
+#endif
+	popaw
+	popfw
+	ret
+#endif
+
+
+/*
+ * makefat():
+ * writes a 18-sectors/track FAT on the diskette, at logical sector 0.
+ * CF is set if an error occurs.
+ * SI is preserved.
+ *
+ */
+makefat:
+	cld
+	pushw	%si
+	movb	$STATUS_FORMATING, %al
+	call	showstatus
+/* make DI point to the first free memory */
+	movw	$(FREEMEMORY), %di
+	pushw	%di		/* will be used later */
+/* initialize the data area : 1 boot, 1 fat, 1 root */
+	movw	$((FATSIZE+2)<<8), %cx
+	cld
+	xorw	%ax, %ax
+	rep
+	stosw
+	popw	%di
+	pushw	%di
+/* make boot sector */
+	movw	$(bootsect-kmsgdump+CODEORIGIN), %si
+	movw	$(rootsect-bootsect), %cx
+	rep
+	movsb
+
+/* make fat1 (which is also fat2) */
+	movw	$(FREEMEMORY+0x200), %di
+	movw	$2, %bx		/* first usable cluster is always 2 */
+	movw	$(LOG_BUF_LEN >> 9), %cx	/* #of sectors per FAT */
+
+	addw	%bx, %cx	/* decide now of the "end of chain" */
+	incw	%bx
+	movb	$0xF0, %al	/* FAT ID */
+	stosb
+	movw	$-1, %ax	/* beginning of FAT */
+	stosw
+0:	movw	%bx, %ax
+	stosb
+	incw	%bx		/* next cluster */
+	cmpw	%cx, %bx	/* did we reach the last cluster ? */
+	jb	1f
+	movw	$0xFFF, %bx	/* yes: mark "end of chain" */
+1:	shlb	$4, %ah
+	movb	$0, %al
+	orw	%bx, %ax
+	rolw	$4, %ax
+	stosw			/* write 2 bytes at once */
+	incw	%bx		/* next cluster */
+	testb	$0x10, %bh	/* are we above the "end of chain" magic number ? */
+	jz	0b		/* not yet, let's go on for 2 more clusters */
+
+/* make root sector */
+	movw	$(FREEMEMORY+0x200+FATSIZE<<9), %di
+	movw	$(datasect-rootsect), %cx
+	rep
+	movsb
+	movw	$(FIRSTCLUSTER), 14(%di)	/* file begins at cluster 2 */
+	movw	$(LOG_BUF_LEN), 16(%di)	/* file length in bytes */
+
+/* in memory, we now have :
+ * BOOT | FAT | ROOT.
+ * We'll use a trick to write the two FATs : 
+ * we first write (BOOT+FAT), and then append (FAT+ROOT)
+ */
+	popw	%di			/* beginning of the area to write */
+	movw	$(1+FATSIZE), %cx	/* one boot sector + N FAT sectors */
+	xorw	%si, %si		/* write onto the first sector */
+	pushw	%cx			/* fortunately, it will be the same size after... */
+	call	wrsect			/* let's write the boot sector onto the disk */
+	popw	%cx			/* 1+FATSIZE, let's save one byte of code */
+	jc	0f	
+/* now write fat2 + root */
+	movw	$(FREEMEMORY+0x200), %di
+	call	wrsect		/* let's write the boot sector onto the disk */
+0:	popw	%si
+	ret
+
+/*
+ * dumpdata():
+ * writes <LOG_BUF_LEN> bytes of data on drive DRIVENUM, from logical sector %si.
+ * CF is set if an error occurred.
+ *
+ */
+dumpdata:
+	clc
+	pushw	%si
+	movb	$STATUS_DUMPING, %al
+	call	showstatus
+	movw	$(LOG_BUF_LEN >> 9), %cx	/* #of sectors that will be written */
+	movw	$(BEGINOFMESSAGES), %di
+	call	wrsect
+	popw	%si
+	ret
+
+/* this function calls int 13 and if any error occurs, it will retry twice.
+ * all registers are kept except flags.
+ */
+int13retry:
+	pushaw
+	clc
+	int	$0x13
+	jnc	0f
+	popaw
+	pushaw
+	clc
+	int	$0x13
+0:	popaw
+	ret
+	
+/*
+ * wrsect():
+ * starts writing CX sectors of data from ES:DI to the diskette at logical sector SI.
+ * first logical sector is numbered 0. This function can write more than one track at
+ * a time, and is limited to the buffer's address in ES segment.
+ * all registers are modified, particularly :
+ *  - SI which contains the first sector that should be written next time
+ *  - DI which points to next data to be written
+ *  - CX which tells how many sectors should be still written in case of CF=1
+ */
+wrsect:
+0:	jcxz	9f	/* when there are no more sectors to write, we return */
+	pushw	%cx	/* save this number of remaining sectors to write */
+	movw	%si, %ax
+
+	movw	$(NBHEADS*NBSECT), %cx	/* we'll compute the starting track number */
+	divb	%cl
+	xchgb	%al, %ch		/* al = 0, ch = track number */
+	xchgb	%ah, %al		/* ah = 0, al = head*nbsect + sect */
+	movb	$(NBSECT), %cl
+	divb	%cl
+	movb	%al, %dh		/* dh = head number */
+	xchgb	%cl, %ah		/* ah = NBSECT, cl = sector number (0-based) */
+	subb	%cl, %ah		/* ah = number of sectors before end of track */
+	popw	%bx			/* number of sectors to write */
+	movzbw	%ah, %ax		/* max #of sectors left on this track */
+	cmpw	%ax, %bx		/* does it fit ? */
+	ja	1f			/* no, let's use AX */
+	movw	%bx, %ax		/* take all the remainder */
+1:
+	subw	%ax, %bx		/* subtract these sectors from the rest */
+	addw	%ax, %si		/* increment the start sector for the next round */
+	pushw	%bx			/* save the actual number of sectors to be written */
+	movb	$3, %ah			/* 3=write, AL is already set to #sectors */
+	incb	%cl			/* CL was 0-based and needs to be 1-based */
+	movw	%di, %bx		/* pointer to beginning of data */
+	movb	DRIVENUM, %dl
+	/* at this point, AL=#sectors, AH=3(write), BX=buffer addr, */
+	/* CL=starting sector, CH=track, DL=drivenum, DH=head num   */
+	/* let's compute the next DI now */
+	pushw	%ax
+	shlw	$9, %ax			/* AL*512 = data size */
+	addw	%ax, %di
+	popw	%ax
+	call	int13retry
+	popw	%cx			/* restore the number of remaining sectors */
+	jnc	0b			/* if no error, let's continue */
+9:	ret
+
+/* data needed to make a tiny FAT file system. */
+bootsect:
+	/* Warning : DOS expects first byte to be either EB or E9 (jump) ! */
+	.byte	0xEB,(bootcode-bootsect-2),0x90
+	.ascii	"KMSGDUMP"
+	.hword	512	/* 512 bytes/sector */
+	.byte	1	/* 1 sector/cluster */
+	.hword	1	/* 1 reserved sector */
+	.byte	2	/* 2 FATs */
+	.hword	16	/* 16 root directory entries (1 root sector) */
+
+	.hword	NBCLUSTERS	/* total clusters */
+	.byte	0xF0	/* media descriptor */
+	.hword	FATSIZE	/* # of sectors per FAT */
+	.hword	NBSECT	/* # of sectors/track */
+	.hword	NBHEADS	/* # of heads */
+	/* now some code to redirect the boot to the first hard disk. This way,
+	   after an automatic dump, even if the diskette is left in the drive and
+	   the bios doesn't automatically go to the hard disk, the diskette will
+	   try to do it itself.
+	 */
+bootcode:
+	/* first we'll copy the boot code elsewhere. */
+	cli
+	cld
+	xorw	%ax,%ax
+	movw	%ax,%es
+	movw	%ax,%ds
+	movw	$0x7c00,%si	/* current source */
+	movw	$0x8000,%di	/* new destination */
+	movw	$256,%cx	/* 256 words = this entire sector */
+	pushw	%si
+	repz
+	movsw
+	popw	%bx		/* current code will be erased */
+	jmp	.+3+0x8000-0x7c00	/* jump to fresh copy of this code */
+	incw	%cx		/* cx=1 : read from sector 1 (cx was 0, so now it's 1).*/
+	movw	$0x80, %dx	/* 0x80 = first hard drive */
+	movw	$0x201,%ax	/* 2=read, 1=1 sector */
+	int	$0x13
+	jnc	bootsect-(0x8000-0x7c00)	/* jump to new code if no error */
+	int	$0x19		/* or try to reboot */
+	jmp	.		/* hang if int 19 returns. */
+	
+rootsect:	.ascii	"MESSAGESTXT"
+		.byte	0x20	/* archived file attribute */
+datasect:	/* end of FAT-specific data */
+	
+mustredraw:	.byte	0
+currentline:	.hword	65535	/* go directly to last line */
+title:		.asciz	"Linux Kernel Messages Dumper - v0.4.5"
+helpline:	.asciz	"> \377Boot \377Dump \377Format \377Halt \377Info \377Print prin\377Ter \377Unit \377U\377p \377D\377o\377w\377n <"
+/* it's important to respect the same order for the following parts. */
+msgprinter:	.ascii	"Printer : \377L\377P\377T\377"
+currentlpt:	.asciz	"1"
+msgunit:	.ascii	"Drive Unit and Format : \377" /* no zero string -> will display drive letter */
+unitname:	.asciz	"A/"
+msgFAT:		.asciz	"\377F\377A\377T\3771\3772"
+msgRAW:		.asciz	"\377R\377A\377W  "
+kversion:	.ascii	"Kernel version : "
+		.asciz	UTS_RELEASE
+msgstatus:	.asciz	"Status : "
+
+/* these messages must be *exactly* 15 chars long, and terminated by a 0 (ie: 16 bytes tot) */
+statwait:	.asciz	"Press a key    "
+statform:	.asciz	"Formating FAT12"
+statdump:	.asciz	"Dumping msgs   "
+statdmpd:	.asciz	"Messages dumped"
+statboot:	.asciz	"Rebooting...   "
+stathalt:	.asciz	"System halted. "
+statprob:	.asciz	"Probing printer"
+statprnt:	.asciz	"Printing msgs  "
+statwerr:	.asciz	"Dump failed !  "
+aboutmsg:	.ascii	"KMSGDUMP 0.4.5 - (C) 1999-2002 - Willy Tarreau <willy AT meta-x.org>\n"
+		.ascii	"<\377B> reboots, <\377D> dumps messages onto the floppy, <\377F> changes floppy\n"
+		.ascii	"format, <\377H> halts the system, <\377P> prints the messages on the selected\n"
+		.ascii	"printer, <\377T> selects a printer, <\377U> changes the floppy unit, \377U\377p/\377D\377o\377w\377n arrows\n"
+		.ascii	"scroll messages up/down, and <\377I> shows this help. When an action completes\n"
+		.ascii	"successfully (print, dump), you should hear 3 short beeps.\n"
+		.ascii	"When dumping data onto a floppy, be warned that FLOPPY CONTENTS WILL BE \377L\377O\377S\377T.\n"
+		.asciz	"Hit <\377U\377p> key to list kernel messages again."
+/* just a public label at the end of the code so we know its length. */
+kmsgdump_end:
diff -Nuarp linux-2.6.6/drivers/char/sysrq.c linux-2.6.6_K1/drivers/char/sysrq.c
--- linux-2.6.6/drivers/char/sysrq.c	2004-05-10 11:33:13.000000000 +0900
+++ linux-2.6.6_K1/drivers/char/sysrq.c	2004-06-14 16:03:52.000000000 +0900
@@ -77,6 +77,22 @@ static struct sysrq_key_op sysrq_SAK_op 
 };
 #endif
 
+#if defined(__i386__) && defined(CONFIG_KMSGDUMP)
+extern void machine_dump(int);
+	
+static void sysrq_handle_dump(int key, struct pt_regs *pt_regs,
+		struct tty_struct *tty) {
+		machine_dump(1);/* 1 = "dump called from SysRq, so interactive mode expected" */
+}
+
+static struct sysrq_key_op sysrq_dump_op = {
+	handler:        sysrq_handle_dump,
+	help_msg:       "Dump",
+	action_msg:     "Trying to dump through real mode\n",
+};
+#endif
+
+
 #ifdef CONFIG_VT
 /* unraw sysrq handler */
 static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
@@ -236,7 +252,11 @@ static struct sysrq_key_op *sysrq_key_ta
 		 and will never arrive */
 /* b */	&sysrq_reboot_op,
 /* c */ NULL,
-/* d */	NULL,
+#if defined(__i386__) && defined(CONFIG_KMSGDUMP)
+/* d */       &sysrq_dump_op,
+#else
+/* d */       NULL,
+#endif
 /* e */	&sysrq_term_op,
 /* f */	NULL,
 /* g */	NULL,
diff -Nuarp linux-2.6.6/include/asm-i386/kmsgdump.h linux-2.6.6_K1/include/asm-i386/kmsgdump.h
--- linux-2.6.6/include/asm-i386/kmsgdump.h	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.6_K1/include/asm-i386/kmsgdump.h	2004-06-14 16:03:52.000000000 +0900
@@ -0,0 +1,93 @@
+/*
+ *	file	: asm/kmsgdump.h
+ *	version	: 0.4.1/1999102301
+ *	author	: Willy Tarreau <willy AT meta-x.org>
+ *
+ * Contents: several constants common to the ASM and C parts
+ *
+ */
+
+/* LOG_BUF_LEN : should match </usr/src/linux/kernel/printk.c>'s */
+/* After 2.5.6x, this uses CONFIG_LOG_BUF_SHIFT instead. */
+#ifndef LOG_BUF_LEN
+/* #define LOG_BUF_LEN     (16384) */
+#define LOG_BUF_LEN	(1 << CONFIG_LOG_BUF_SHIFT)
+#endif
+
+#define	CODEORIGIN	0x0700
+#define	TOPOFSTACK	0x0FB0
+#define	BEGINOFMESSAGES	0x1000
+#define FREEMEMORY	(BEGINOFMESSAGES+LOG_BUF_LEN)
+
+#define BOOTSTACKFRAME	0xFB0	
+#define	DRIVENUM	0xFF0
+#define	TRACKNUM	0xFF1
+#define MODEFLAGS	0xFF2
+
+/* bits definitions for MODEFLAGS */
+#define MASK_SYSRQMODE	0x80
+#define MASK_OUTPUTFAT	0x40
+#define MASK_PANICMAN	0x20
+#define MASK_PANICDUMP	0x10
+#define MASK_PANICBOOT	0x08
+#define MASK_SAFEDUMP	0x04
+
+/* type of function which requested a dump */
+#define	DUMP_FROM_PANIC	0
+#define	DUMP_FROM_SYSRQ	1
+
+#ifdef __ASSEMBLY__
+
+#define	CLOCKTICKS		0x46C
+#define	VIDEOMODE		3
+#define	HELPLINE		5
+#define	BOTTOMLINE		24
+#define	RIGHTCOL		79
+#define	ATTRIB			0x1B
+#define	HIGHLIGHT		0x1F
+
+/* specify here the format of the diskette, 1.44 MB by default */
+#define NBHEADS			2
+#define	NBSECT			18
+#define	NBTRACKS		80
+
+/* let's compute some useful parameters from the diskette geometry */
+#define	SECTPERCLUST		1
+#define FIRSTCLUSTER		2
+
+/* At the moment, most versions of gas are broken so you can't activate
+   the following line which is the correct one. However, as long as the
+   constant SECTPERCLUST equals 1, the next line can be used as a replacement.
+   If you change the value of SECTPERCLUST, you'll have to change the
+   definition of NBCLUSTERS WITHOUT involving the divide operation which older
+   gas interpret as a comment. Versions from binutils 2.9.4 and later seem OK.
+*/
+
+#if THIS_GAS_IS_REALLY_GOOD
+#  define	NBCLUSTERS		((NBHEADS*NBTRACKS*NBSECT)/SECTPERCLUST)
+#else
+#  define	NBCLUSTERS		(NBHEADS*NBTRACKS*NBSECT)
+#endif
+
+#define	FATSIZE			((NBCLUSTERS*3+1023)>>10)
+
+#define STATUS_WAITING		0
+#define STATUS_FORMATING	1
+#define STATUS_DUMPING		2
+#define STATUS_DUMPOK		3
+#define STATUS_BOOTING		4
+#define STATUS_HALTING		5
+#define STATUS_PROBING		6
+#define STATUS_PRINTING		7
+#define STATUS_WERR		8
+#define STATUS_MAXMSG		8
+
+#define MKWORD(h,l)		((h)<<8|(l))
+
+#else  /* C headers */
+
+extern void kmsgdump(void);
+extern void kmsgdump_end(void);
+
+#endif
+
diff -Nuarp linux-2.6.6/include/linux/sysctl.h linux-2.6.6_K1/include/linux/sysctl.h
--- linux-2.6.6/include/linux/sysctl.h	2004-05-10 11:32:38.000000000 +0900
+++ linux-2.6.6_K1/include/linux/sysctl.h	2004-06-14 16:03:52.000000000 +0900
@@ -112,6 +112,7 @@ enum
  	KERN_MSGMNI=42,		/* int: msg queue identifiers */
  	KERN_SEM=43,		/* struct: sysv semaphore limits */
  	KERN_SPARC_STOP_A=44,	/* int: Sparc Stop-A enable */
+	KERN_KMSGDUMP=44,	/* string: kmsgdump flags. Reuse Stop-A ID */
  	KERN_SHMMNI=45,		/* int: shm array identifiers */
 	KERN_OVERFLOWUID=46,	/* int: overflow UID */
 	KERN_OVERFLOWGID=47,	/* int: overflow GID */
diff -Nuarp linux-2.6.6/kernel/panic.c linux-2.6.6_K1/kernel/panic.c
--- linux-2.6.6/kernel/panic.c	2004-05-10 11:33:20.000000000 +0900
+++ linux-2.6.6_K1/kernel/panic.c	2004-06-14 16:03:52.000000000 +0900
@@ -20,6 +20,12 @@
 #include <linux/interrupt.h>
 #include <linux/nmi.h>
 
+#if defined(__i386__) && defined(CONFIG_KMSGDUMP)
+#include <linux/fs.h>
+extern void machine_dump(int);
+#endif
+
+
 int panic_timeout;
 int panic_on_oops;
 int tainted;
@@ -72,6 +78,26 @@ NORET_TYPE void panic(const char * fmt, 
 	smp_send_stop();
 #endif
 
+#if defined(__i386__) && defined(CONFIG_KMSGDUMP)
+	/* We allow SysRq to be used for <panic_timeout> seconds, and
+	   then the dump is forced. This way, if IRQs are frozen and
+	   keyboard doesn't respond anymore, the system can dump messages
+	   and reboot itself.
+	   This code has been voluntarily inserted before notifier_call_chain
+	   to ensure proper execution in case of crash. Please tell me if this
+	   can be wrong.
+	*/
+	printk(KERN_EMERG "Dumping messages in %d seconds : last chance for Alt-SysRq...",
+		panic_timeout);
+	local_irq_enable();
+	for (panic_timeout *= 10; panic_timeout > 0; panic_timeout--) {
+		emergency_sync();
+		mdelay(100);
+	}
+	machine_dump(0);        /* 0 tells machine_dump that it's called from panic() */
+#endif
+		
+	
        notifier_call_chain(&panic_notifier_list, 0, buf);
 
 	if (panic_timeout > 0)
diff -Nuarp linux-2.6.6/kernel/printk.c linux-2.6.6_K1/kernel/printk.c
--- linux-2.6.6/kernel/printk.c	2004-05-10 11:33:21.000000000 +0900
+++ linux-2.6.6_K1/kernel/printk.c	2004-06-14 16:03:52.000000000 +0900
@@ -371,6 +371,38 @@ out:
 	return error;
 }
 
+#if defined(__i386__) && defined(CONFIG_KMSGDUMP)
+#include <asm/kmsgdump.h>
+
+/*
+ * dump_syslog() : Added on 19991020 by Willy Tarreau <willy AT meta-x.org>
+ * This function is only used by machine_dump. It basically does the same
+ * as do_syslog(3), but avoids to check if *buf is writeable because this
+ * sometimes made the system crash in case of real instability (common
+ * case when machine_dump is called).
+ */
+
+void dump_syslog(char *buf) {
+	unsigned long i, j, count;
+
+	if (!buf)
+		return;	
+	/*
+	 * The logged_chars, log_start, and log_size values may
+	 * change from an interrupt, so we disable interrupts.
+	 */
+	spin_lock_irq(&logbuf_lock);
+	count = LOG_BUF_LEN;
+	if (count > logged_chars)
+		count = logged_chars;
+	j = log_start;
+	for (i = 0; (i < count) && (j != log_end); i++, j++) {
+		buf[i] = LOG_BUF(j);
+	}
+	spin_unlock_irq(&logbuf_lock);
+}
+#endif
+
 asmlinkage long sys_syslog(int type, char __user * buf, int len)
 {
 	return do_syslog(type, buf, len);
diff -Nuarp linux-2.6.6/kernel/sysctl.c linux-2.6.6_K1/kernel/sysctl.c
--- linux-2.6.6/kernel/sysctl.c	2004-05-10 11:32:00.000000000 +0900
+++ linux-2.6.6_K1/kernel/sysctl.c	2004-06-14 16:03:52.000000000 +0900
@@ -90,6 +90,10 @@ extern int msg_ctlmni;
 extern int sem_ctls[];
 #endif
 
+#if defined(__i386__) && defined(CONFIG_KMSGDUMP)
+extern char kmsgdump_flags[];
+#endif
+
 #ifdef __sparc__
 extern char reboot_command [];
 extern int stop_a_enabled;
@@ -513,6 +517,17 @@ static ctl_table kern_table[] = {
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
+#if defined(__i386__) && defined(CONFIG_KMSGDUMP)
+	{
+		.ctl_name	= KERN_KMSGDUMP,
+		.procname	= "kmsgdump",
+		.data		= &kmsgdump_flags,
+		.maxlen		= 16,
+	 	.mode		= 0644,
+		.proc_handler	= &proc_dostring,
+		.strategy	= &sysctl_string,
+	},
+#endif
 	{
 		.ctl_name	= KERN_CADPID,
 		.procname	= "cad_pid",


  reply	other threads:[~2004-06-14 13:47 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-06-14  2:23 Panics need better handling ndiamond
2004-06-14  4:21 ` Willy Tarreau
2004-06-14  4:34   ` Norberto Bensa
2004-06-14 13:46     ` Kalin KOZHUHAROV [this message]
2004-06-14  7:28 ` Helge Hafting
2004-06-14  7:44   ` John Bradford

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=40CDAC1F.6050202@ThinRope.net \
    --to=kalin@thinrope.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=ndiamond@despammed.com \
    --cc=norberto+linux-kernel@bensa.ath.cx \
    --cc=willy@w.ods.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox