2004-11-15 20:41:08

by Nickolai Zeldovich

[permalink] [raw]
Subject: [patch] Fix GDT re-load on ACPI resume

The ACPI resume code currently uses a real-mode 16-bit lgdt instruction to
reload the GDT. This only restores the lower 24 bits of the GDT base
address. In recent kernels, the GDT seems to have moved out of the lower
16 megs, thereby causing the ACPI resume to fail -- an invalid GDT was
being loaded.

This simple patch adds the 0x66 prefix to lgdt, which forces it to load
all 32 bits of the GDT base address, thereby removing any restrictions on
where the GDT can be placed in memory. This makes ACPI resume work for me
on a Thinkpad T40 laptop.

-- kolya

--- linux-2.6.9/arch/i386/kernel/acpi/wakeup.S 2004/11/15 09:00:34 1.1
+++ linux-2.6.9/arch/i386/kernel/acpi/wakeup.S 2004/11/15 20:33:27
@@ -67,6 +67,8 @@
movw $0x0e00 + 'i', %fs:(0x12)

# need a gdt
+ .byte 0x66 # force 32-bit operands in case
+ # the GDT is past 16 megabytes
lgdt real_save_gdt - wakeup_code

movl real_save_cr0 - wakeup_code, %eax


2004-11-15 23:04:40

by David Weinehall

[permalink] [raw]
Subject: Re: [patch] Fix GDT re-load on ACPI resume

On Mon, Nov 15, 2004 at 03:35:14PM -0500, Nickolai Zeldovich wrote:
> The ACPI resume code currently uses a real-mode 16-bit lgdt instruction to
> reload the GDT. This only restores the lower 24 bits of the GDT base
> address. In recent kernels, the GDT seems to have moved out of the lower
> 16 megs, thereby causing the ACPI resume to fail -- an invalid GDT was
> being loaded.
>
> This simple patch adds the 0x66 prefix to lgdt, which forces it to load
> all 32 bits of the GDT base address, thereby removing any restrictions on
> where the GDT can be placed in memory. This makes ACPI resume work for me
> on a Thinkpad T40 laptop.

Sadly doesn't work for me. ACPI resume broke for me with
2.6.10-rc1-bk15 (possibly 14, but that one didn't compile), and this
patch does not fix it.


Regards: David Weinehall
--
/) David Weinehall <[email protected]> /) Northern lights wander (\
// Maintainer of the v2.0 kernel // Dance across the winter sky //
\) http://www.acc.umu.se/~tao/ (/ Full colour fire (/

2004-11-15 23:15:07

by Nickolai Zeldovich

[permalink] [raw]
Subject: Re: [patch] Fix GDT re-load on ACPI resume

On Tue, 16 Nov 2004, David Weinehall wrote:

> Sadly doesn't work for me. ACPI resume broke for me with
> 2.6.10-rc1-bk15 (possibly 14, but that one didn't compile), and this
> patch does not fix it.

For the record, the symptoms of the problem fixed by the GDT patch in
question are that, upon ACPI resume, your screen shows the letters "Lin"
in yellow, hangs for a little bit, and then reboots.

-- kolya

2004-11-15 23:26:40

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: [patch] Fix GDT re-load on ACPI resume

On Mon, 15 Nov 2004, Nickolai Zeldovich wrote:

> This simple patch adds the 0x66 prefix to lgdt, which forces it to load
> all 32 bits of the GDT base address, thereby removing any restrictions on
> where the GDT can be placed in memory. This makes ACPI resume work for me
> on a Thinkpad T40 laptop.
[...]
> + .byte 0x66 # force 32-bit operands in case
> + # the GDT is past 16 megabytes
> lgdt real_save_gdt - wakeup_code

You should use "lgdtl" and let gas figure out the rest.

Maciej

2004-11-15 23:54:21

by Nickolai Zeldovich

[permalink] [raw]
Subject: Re: [patch] Fix GDT re-load on ACPI resume

On Mon, 15 Nov 2004, Maciej W. Rozycki wrote:

> You should use "lgdtl" and let gas figure out the rest.

Thanks for the pointer; here's an updated patch.

-- kolya

--- linux-2.6.9/arch/i386/kernel/acpi/wakeup.S 2004/11/15 09:00:34 1.1
+++ linux-2.6.9/arch/i386/kernel/acpi/wakeup.S 2004/11/15 23:50:38
@@ -66,8 +66,9 @@
movw %ax,%fs
movw $0x0e00 + 'i', %fs:(0x12)

- # need a gdt
- lgdt real_save_gdt - wakeup_code
+ # need a gdt -- use lgdtl to force 32-bit operands, in case
+ # the GDT is located past 16 megabytes.
+ lgdtl real_save_gdt - wakeup_code

movl real_save_cr0 - wakeup_code, %eax
movl %eax, %cr0

2004-11-16 05:38:28

by Shaohua Li

[permalink] [raw]
Subject: RE: [patch] Fix GDT re-load on ACPI resume

>The ACPI resume code currently uses a real-mode 16-bit lgdt instruction
to
>reload the GDT. This only restores the lower 24 bits of the GDT base
>address. In recent kernels, the GDT seems to have moved out of the
lower
>16 megs, thereby causing the ACPI resume to fail -- an invalid GDT was
>being loaded.
>
>This simple patch adds the 0x66 prefix to lgdt, which forces it to load
>all 32 bits of the GDT base address, thereby removing any restrictions
on
>where the GDT can be placed in memory. This makes ACPI resume work for
me
>on a Thinkpad T40 laptop.
>
>-- kolya
>
>--- linux-2.6.9/arch/i386/kernel/acpi/wakeup.S 2004/11/15 09:00:34
1.1
>+++ linux-2.6.9/arch/i386/kernel/acpi/wakeup.S 2004/11/15 20:33:27
>@@ -67,6 +67,8 @@
> movw $0x0e00 + 'i', %fs:(0x12)
>
> # need a gdt
>+ .byte 0x66 # force 32-bit operands in case
>+ # the GDT is past 16 megabytes
> lgdt real_save_gdt - wakeup_code
>
> movl real_save_cr0 - wakeup_code, %eax
There is a patch from [email protected] to fix the GDT issue. You can try
it.
Please cc '[email protected]' for suspend/resume issue.

Thanks,
Shaohua


Attachments:
wakeup_gdt2.patch (2.16 kB)
wakeup_gdt2.patch

2004-11-16 12:43:22

by Maciej W. Rozycki

[permalink] [raw]
Subject: RE: [patch] Fix GDT re-load on ACPI resume

On Tue, 16 Nov 2004, Li, Shaohua wrote:

> There is a patch from [email protected] to fix the GDT issue. You can try
> it.
> Please cc '[email protected]' for suspend/resume issue.

What is the "gdt body must be addressable from real mode" requirement
about? GDT is addressed by the CPU using a linear address as obtained
from GDTR (bypassing segmentation, for obvious reasons) and is accessible
regardless of its placement within the 32-bit linear address space in all
CPU modes. As its a linear address it only undergoes translation at the
page level, if enabled. The same applies to IDT.

Maciej

2004-11-16 17:46:50

by Hiroshi Itoh

[permalink] [raw]
Subject: Re: [patch] Fix GDT re-load on ACPI resume

Hi, Maciej-san

> What is the "gdt body must be addressable from real mode" requirement
>about? GDT is addressed by the CPU using a linear address as obtained
>from GDTR (bypassing segmentation, for obvious reasons) and is accessible
>regardless of its placement within the 32-bit linear address space in all
>CPU modes. As its a linear address it only undergoes translation at the
>page level, if enabled. The same applies to IDT.

I believe this patch is required because the original gdt is not addressable
via the low mapping page table (set by acpi_save_state_mem and used for wakeup
code), not the GDTR's linear address size reason.

cc:Shaohua and Len

wakeup_gdt2.patch should be slightestly modified to wakeup_gdt_2.6.10.patch
because %edx is conflict with msr's patch in 2.6.10-rc2 or later.

thanks
-Hiro


Attachments:
wakeup_gdt_2.6.10.patch (2.10 kB)

2004-11-17 01:02:52

by Maciej W. Rozycki

[permalink] [raw]
Subject: Re: [patch] Fix GDT re-load on ACPI resume

Hi Hiroshi-san,

> I believe this patch is required because the original gdt is not addressable
> via the low mapping page table (set by acpi_save_state_mem and used for wakeup
> code), not the GDTR's linear address size reason.

That makes sense, indeed. Using "lgdtl" (and likewise "lidtl")
universally is a bit safer anyway.

Maciej

2004-11-17 19:00:47

by Pavel Machek

[permalink] [raw]
Subject: Re: [patch] Fix GDT re-load on ACPI resume

Hi!

> > movw _0x0e00 + 'i', %fs:(0x12)
> >
> > # need a gdt
> >+ .byte 0x66 # force 32-bit operands in case
> >+ # the GDT is past 16 megabytes
> > lgdt real_save_gdt - wakeup_code
> >
> > movl real_save_cr0 - wakeup_code, %eax
> There is a patch from [email protected] to fix the GDT issue. You can try
> it.

Well, replacing lgdt with lgdtl (above) seems like nicer solution than
attachment...
--
64 bytes from 195.113.31.123: icmp_seq=28 ttl=51 time=448769.1 ms

2004-11-18 02:29:27

by Shaohua Li

[permalink] [raw]
Subject: RE: [patch] Fix GDT re-load on ACPI resume

>> > movw _0x0e00 + 'i', %fs:(0x12)
>> >
>> > # need a gdt
>> >+ .byte 0x66 # force 32-bit operands in case
>> >+ # the GDT is past 16 megabytes
>> > lgdt real_save_gdt - wakeup_code
>> >
>> > movl real_save_cr0 - wakeup_code, %eax
>> There is a patch from [email protected] to fix the GDT issue. You can
try
>> it.
>
>Well, replacing lgdt with lgdtl (above) seems like nicer solution than
>attachment...
Copy GDT to low mem seems safer. Now the GDT table is in per-cpu region,
possibly it's not in low memory. Or am I missing anything?

Shaohua