Re: Kernel Crash on Shutdown

georg.funke@netcologne.de
Sat, 12 Jun 1999 19:23:34 +0200 (CEST)


---1463786495-1804289383-929208221=:966
Content-Type: TEXT/plain; CHARSET=US-ASCII

Hi,

On 13 Jun, Menaka Lashitha Bandara wrote:
> Sorry for responding after such a long time. I had to take my
> motherboard back because there was an error with the RTC. Now I've got a
> replacement motherboard, and the kernel still crashes on "halt." When
> I first wrote the problem to this Mailing list, Alan Cox said it could
> be a bios problem. I have a new bios now (because I got a replacment
> m/b), but the kernel still crashes on shutdown. I've tried exchanging
> the CPU (to the same one) from my friend's system which shuts down
> properley, but this didn't solve anything. If it helps, here are the
> devices on my system:
>

Try the attached patch for apm. It was posted here some time apo.

I had the same problem and the patch works for me.

Georg

-- 
Georg Funke
Crowns & Flames SDC Cologne, Germany; http://www.geocities.com/Colosseum/4893
"Friendship is Square Dancing's greatest Reward"

---1463786495-1804289383-929208221=:966 Content-Type: TEXT/plain; CHARSET=US-ASCII Content-ID: apm-patch-2.2.2 Content-Description: apm-patch-2.2.2

--- 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 }

---1463786495-1804289383-929208221=:966--

- 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/