lkml.org 
[lkml]   [1999]   [Jun]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: Kernel Opps on MVP3GM
On Mon, 7 Jun 1999, Menaka Lashitha Bandara wrote:

This message is directed at those almighty kernel developers.

I have a Epox MVP3GM Mother board. When I shut down the system, that is
power off, the kernel simply responds by crashing (After it's killed all
the service). For some reason, it isn't the VIA82c586 Chipset. I've
installed on a similar motherboard (slightly inferior - Epox MVP3CM,
which has the same chipset) and this hasn't had any kernel oopses when
shutting down.

I've used Kernel 2.2.5-15, and 2.2.9, and the oops happens on both
kernels. I've tried with and without the experimental VIA82c586 driver,
and it's still the case.

Hi Menaka,

The experimental Via driver is for IDE, and doesn't do anything for
your power-off problem, which is a BIOS bug.

The reason for this oops is apparently because your BIOS expects only
to be called from real mode, and can't handle the cpu being in
protected mode. Ask Epox if they could fix this bug and release a
BIOS update. (i have the same problem with my TMC board,
unfortunately TMC can't be bothered to fix it.)

In the meantime, A guy called Walter Hofmann has released a patch to
work-around it, to change to real-mode before calling the BIOS
power-off routine. It should apply cleanly to any recent 2.2 kernel.

regards,
--
Paul Jakma
paul@clubi.ie http://hibernia.clubi.ie
PGP5 key: http://www.clubi.ie/jakma/publickey.txt
-------------------------------------------
Fortune:
The attacker must vanquish; the defender need only survive.
--- linux/arch/i386/kernel/process.c~ Sun Feb 28 23:09:29 1999
+++ linux/arch/i386/kernel/process.c Mon Mar 1 00:04:01 1999
@@ -2,6 +2,10 @@
* linux/arch/i386/kernel/process.c
*
* Copyright (C) 1995 Linus Torvalds
+ *
+ * Change back to real mode for APM power off
+ * Walter Hofmann, March 1999
+ *
*/

/*
@@ -380,10 +384,106 @@
{
}

+#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
+
+/* This is 16-bit protected mode code to disable paging and the cache,
+ switch to real mode and jump to the BIOS APM poweroff code. */
+
+unsigned char apm_real_mode_poweroff [] =
+{
+ 0x66, 0x0f, 0x20, 0xc0, /* movl %cr0,%eax */
+ 0x66, 0x83, 0xe0, 0x11, /* andl $0x00000011,%eax */
+ 0x66, 0x0d, 0x00, 0x00, 0x00, 0x60, /* orl $0x60000000,%eax */
+ 0x66, 0x0f, 0x22, 0xc0, /* movl %eax,%cr0 */
+ 0x66, 0x0f, 0x22, 0xd8, /* movl %eax,%cr3 */
+ 0x66, 0x0f, 0x20, 0xc3, /* movl %cr0,%ebx */
+ 0x66, 0x81, 0xe3, 0x00, 0x00, 0x00, 0x60, /* andl $0x60000000,%ebx */
+ 0x74, 0x02, /* jz f */
+ 0x0f, 0x08, /* invd */
+ 0x24, 0x10, /* f: andb $0x10,al */
+ 0x66, 0x0f, 0x22, 0xc0, /* movl %eax,%cr0 */
+ 0xea, 0xed, 0x0f, 0x00, 0x00, /* ljmp g */
+ 0xb8, 0x00, 0x10, /* g: movw $0x1000,ax */
+ 0x8e, 0xd0, /* movw ax,ss */
+ 0xbc, 0x00, 0xf0, /* movw $0xf000,sp */
+ 0xb8, 0x07, 0x53, /* movw $0x5307,ax */
+ 0xbb, 0x01, 0x00, /* movw $0x0001,bx */
+ 0xb9, 0x03, 0x00, /* movw $0x0003,cx */
+ 0xcd, 0x15 /* int $0x15 */
+};
+
+void apm_realmode_poweroff(void)
+{
+ cli ();
+
+ /* 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 0xc0000000. */
+
+ memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+ sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
+
+ /* Make sure the first page is mapped to the start of physical memory.
+ It is normally not mapped, to trap kernel NULL pointer dereferences. */
+
+ pg0 [0] = 7;
+
+ /*
+ * Use `swapper_pg_dir' as our page directory. We bother with
+ * `SET_PAGE_DIR' because although might be rebooting, but if we change
+ * the way we set root page dir in the future, then we wont break a
+ * seldom used feature ;)
+ */
+
+ SET_PAGE_DIR(current,swapper_pg_dir);
+
+ /* For the switch to real mode, copy some code to low memory. It has
+ to be in the first 64k because it is running in 16-bit mode, and it
+ has to have the same physical and virtual address, because it turns
+ off paging. Copy it near the end of the first page, out of the way
+ of BIOS variables. */
+
+ memcpy ((void *) (0x1000 - sizeof (apm_real_mode_poweroff)),
+ apm_real_mode_poweroff, sizeof (apm_real_mode_poweroff));
+
+ /* Set up the IDT for real mode. */
+
+ __asm__ __volatile__ ("lidt %0" : : "m" (real_mode_idt));
+
+ /* Set up a GDT from which we can load segment descriptors for real
+ mode. The GDT is not used in real mode; it is just needed here to
+ prepare the descriptors. */
+
+ __asm__ __volatile__ ("lgdt %0" : : "m" (real_mode_gdt));
+
+ /* Load the data segment registers, and thus the descriptors ready for
+ real mode. The base address of each segment is 0x100, 16 times the
+ selector value being loaded here. This is so that the segment
+ registers don't have to be reloaded after switching to real mode:
+ the values are consistent for real mode operation already. */
+
+ __asm__ __volatile__ ("movw $0x0010,%%ax\n"
+ "\tmovw %%ax,%%ds\n"
+ "\tmovw %%ax,%%es\n"
+ "\tmovw %%ax,%%fs\n"
+ "\tmovw %%ax,%%gs\n"
+ "\tmovw %%ax,%%ss" : : : "eax");
+
+ /* Jump to the 16-bit code that we copied earlier. It disables paging
+ and the cache, switches to real mode, and jumps to the BIOS APM
+ entry point. */
+
+ __asm__ __volatile__ ("ljmp $0x0008,%0"
+ :
+ : "i" ((void *) (0x1000 - sizeof (apm_real_mode_poweroff))));
+
+}
+#endif
+
void machine_power_off(void)
{
#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
- apm_power_off();
+ apm_realmode_poweroff();
#endif
}
\
 
 \ /
  Last update: 2005-03-22 13:52    [W:0.045 / U:0.028 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site