* RE: [patch] Fix GDT re-load on ACPI resume
@ 2004-11-16 5:37 Li, Shaohua
2004-11-16 12:42 ` Maciej W. Rozycki
2004-11-17 18:57 ` Pavel Machek
0 siblings, 2 replies; 11+ messages in thread
From: Li, Shaohua @ 2004-11-16 5:37 UTC (permalink / raw)
To: Nickolai Zeldovich, linux-kernel; +Cc: csapuntz, hiroit
[-- Attachment #1: Type: text/plain, Size: 1153 bytes --]
>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 hiroit@mcn.ne.jp to fix the GDT issue. You can try
it.
Please cc 'acpi-devel@lists.sourceforge.net' for suspend/resume issue.
Thanks,
Shaohua
[-- Attachment #2: wakeup_gdt2.patch --]
[-- Type: application/octet-stream, Size: 2214 bytes --]
diff -Nru a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c
--- a/arch/i386/kernel/acpi/sleep.c 2004-10-15 11:29:15.000000000 +0900
+++ b/arch/i386/kernel/acpi/sleep.c 2004-10-19 00:59:32.000000000 +0900
@@ -17,7 +17,7 @@
extern void zap_low_mappings(void);
-extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
+extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long,unsigned long));
static void init_low_mapping(pgd_t *pgd, int pgd_limit)
{
@@ -41,7 +41,8 @@
return 1;
init_low_mapping(swapper_pg_dir, USER_PTRS_PER_PGD);
memcpy((void *) acpi_wakeup_address, &wakeup_start, &wakeup_end - &wakeup_start);
- acpi_copy_wakeup_routine(acpi_wakeup_address);
+ acpi_copy_wakeup_routine(acpi_wakeup_address,
+ virt_to_phys((void *)acpi_wakeup_address));
return 0;
}
diff -Nru a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S
--- a/arch/i386/kernel/acpi/wakeup.S 2004-08-14 14:36:31.000000000 +0900
+++ b/arch/i386/kernel/acpi/wakeup.S 2004-10-19 05:24:42.000000000 +0900
@@ -89,6 +89,7 @@
real_magic: .long 0
video_mode: .long 0
video_flags: .long 0
+real_gdt_table: .fill GDT_ENTRIES, 8, 0
bogus_real_magic:
movw $0x0e00 + 'B', %fs:(0x12)
@@ -213,6 +214,7 @@
#
# Parameters:
# %eax: place to copy wakeup routine to
+# %edx: the second argument (physical address)
#
# Returned address is location of code in low memory (past data and stack)
#
@@ -223,6 +225,9 @@
sldt saved_ldt
str saved_tss
+ # save wakeup_start physical address in ecx
+ movl %edx, %ecx
+
movl %cr3, %edx
movl %edx, real_save_cr3 - wakeup_start (%eax)
movl %cr4, %edx
@@ -231,6 +236,16 @@
movl %edx, real_save_cr0 - wakeup_start (%eax)
sgdt real_save_gdt - wakeup_start (%eax)
+ # gdt body must be addressable from real mode by
+ # copying it to the lower mem
+ lea real_gdt_table - wakeup_start (%ecx), %ecx
+ movl %ecx, real_save_gdt + 2 - wakeup_start (%eax)
+ xor %ecx, %ecx
+ movw saved_gdt, %cx
+ movl saved_gdt + 2, %esi
+ lea real_gdt_table - wakeup_start (%eax), %edi
+ rep movsb
+
movl saved_videomode, %edx
movl %edx, video_mode - wakeup_start (%eax)
movl acpi_video_flags, %edx
^ permalink raw reply [flat|nested] 11+ messages in thread* RE: [patch] Fix GDT re-load on ACPI resume
2004-11-16 5:37 [patch] Fix GDT re-load on ACPI resume Li, Shaohua
@ 2004-11-16 12:42 ` Maciej W. Rozycki
2004-11-16 17:46 ` Hiroshi Itoh
2004-11-17 18:57 ` Pavel Machek
1 sibling, 1 reply; 11+ messages in thread
From: Maciej W. Rozycki @ 2004-11-16 12:42 UTC (permalink / raw)
To: Li, Shaohua; +Cc: Nickolai Zeldovich, linux-kernel, csapuntz, hiroit
On Tue, 16 Nov 2004, Li, Shaohua wrote:
> There is a patch from hiroit@mcn.ne.jp to fix the GDT issue. You can try
> it.
> Please cc 'acpi-devel@lists.sourceforge.net' 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
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [patch] Fix GDT re-load on ACPI resume
2004-11-16 12:42 ` Maciej W. Rozycki
@ 2004-11-16 17:46 ` Hiroshi Itoh
2004-11-17 1:02 ` Maciej W. Rozycki
0 siblings, 1 reply; 11+ messages in thread
From: Hiroshi Itoh @ 2004-11-16 17:46 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: Li, Shaohua, csapuntz, linux-kernel, Nickolai Zeldovich
[-- Attachment #1: Type: text/plain, Size: 819 bytes --]
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
[-- Attachment #2: wakeup_gdt_2.6.10.patch --]
[-- Type: application/octet-stream, Size: 2216 bytes --]
--- a/arch/i386/kernel/acpi/sleep.c 2004-11-04 04:54:41.000000000 +0900
+++ b/arch/i386/kernel/acpi/sleep.c 2004-11-04 05:20:34.864501960 +0900
@@ -17,7 +17,7 @@
extern void zap_low_mappings(void);
-extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
+extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long,unsigned long));
static void init_low_mapping(pgd_t *pgd, int pgd_limit)
{
@@ -41,7 +41,8 @@
return 1;
init_low_mapping(swapper_pg_dir, USER_PTRS_PER_PGD);
memcpy((void *) acpi_wakeup_address, &wakeup_start, &wakeup_end - &wakeup_start);
- acpi_copy_wakeup_routine(acpi_wakeup_address);
+ acpi_copy_wakeup_routine(acpi_wakeup_address,
+ virt_to_phys((void *)acpi_wakeup_address));
return 0;
}
--- a/arch/i386/kernel/acpi/wakeup.S 2004-11-04 04:54:41.000000000 +0900
+++ b/arch/i386/kernel/acpi/wakeup.S 2004-11-04 05:23:46.490370400 +0900
@@ -100,6 +100,7 @@
real_efer_save_restore: .long 0
real_save_efer_edx: .long 0
real_save_efer_eax: .long 0
+real_gdt_table: .fill GDT_ENTRIES, 8, 0
bogus_real_magic:
movw $0x0e00 + 'B', %fs:(0x12)
@@ -224,6 +225,7 @@
#
# Parameters:
# %eax: place to copy wakeup routine to
+# %edx: the second argument (physical address)
#
# Returned address is location of code in low memory (past data and stack)
#
@@ -234,6 +236,9 @@
sldt saved_ldt
str saved_tss
+ # save wakeup_start physical address in edx
+ pushl %edx
+
movl nx_enabled, %edx
movl %edx, real_efer_save_restore - wakeup_start (%eax)
testl $1, real_efer_save_restore - wakeup_start (%eax)
@@ -256,6 +261,17 @@
movl %edx, real_save_cr0 - wakeup_start (%eax)
sgdt real_save_gdt - wakeup_start (%eax)
+ # gdt body must be addressable from real mode by
+ # copying it to the lower mem
+ popl %edx
+ lea real_gdt_table - wakeup_start (%edx), %edx
+ movl %edx, real_save_gdt + 2 - wakeup_start (%eax)
+ xor %ecx, %ecx
+ movw saved_gdt, %cx
+ movl saved_gdt + 2, %esi
+ lea real_gdt_table - wakeup_start (%eax), %edi
+ rep movsb
+
movl saved_videomode, %edx
movl %edx, video_mode - wakeup_start (%eax)
movl acpi_video_flags, %edx
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [patch] Fix GDT re-load on ACPI resume
2004-11-16 17:46 ` Hiroshi Itoh
@ 2004-11-17 1:02 ` Maciej W. Rozycki
0 siblings, 0 replies; 11+ messages in thread
From: Maciej W. Rozycki @ 2004-11-17 1:02 UTC (permalink / raw)
To: Hiroshi Itoh; +Cc: Li, Shaohua, csapuntz, linux-kernel, Nickolai Zeldovich
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
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [patch] Fix GDT re-load on ACPI resume
2004-11-16 5:37 [patch] Fix GDT re-load on ACPI resume Li, Shaohua
2004-11-16 12:42 ` Maciej W. Rozycki
@ 2004-11-17 18:57 ` Pavel Machek
1 sibling, 0 replies; 11+ messages in thread
From: Pavel Machek @ 2004-11-17 18:57 UTC (permalink / raw)
To: Li, Shaohua; +Cc: Nickolai Zeldovich, linux-kernel, csapuntz, hiroit
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 hiroit@mcn.ne.jp 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
^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: [patch] Fix GDT re-load on ACPI resume
@ 2004-11-18 1:59 Li, Shaohua
0 siblings, 0 replies; 11+ messages in thread
From: Li, Shaohua @ 2004-11-18 1:59 UTC (permalink / raw)
To: Pavel Machek; +Cc: Nickolai Zeldovich, linux-kernel, csapuntz, hiroit
>> > 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 hiroit@mcn.ne.jp 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
^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch] Fix GDT re-load on ACPI resume
@ 2004-11-15 20:35 Nickolai Zeldovich
2004-11-15 23:02 ` David Weinehall
2004-11-15 23:26 ` Maciej W. Rozycki
0 siblings, 2 replies; 11+ messages in thread
From: Nickolai Zeldovich @ 2004-11-15 20:35 UTC (permalink / raw)
To: linux-kernel; +Cc: csapuntz
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
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [patch] Fix GDT re-load on ACPI resume
2004-11-15 20:35 Nickolai Zeldovich
@ 2004-11-15 23:02 ` David Weinehall
2004-11-15 23:13 ` Nickolai Zeldovich
2004-11-15 23:26 ` Maciej W. Rozycki
1 sibling, 1 reply; 11+ messages in thread
From: David Weinehall @ 2004-11-15 23:02 UTC (permalink / raw)
To: Nickolai Zeldovich; +Cc: linux-kernel, csapuntz
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 <tao@acc.umu.se> /) Northern lights wander (\
// Maintainer of the v2.0 kernel // Dance across the winter sky //
\) http://www.acc.umu.se/~tao/ (/ Full colour fire (/
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [patch] Fix GDT re-load on ACPI resume
2004-11-15 23:02 ` David Weinehall
@ 2004-11-15 23:13 ` Nickolai Zeldovich
0 siblings, 0 replies; 11+ messages in thread
From: Nickolai Zeldovich @ 2004-11-15 23:13 UTC (permalink / raw)
To: David Weinehall; +Cc: linux-kernel, csapuntz
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
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [patch] Fix GDT re-load on ACPI resume
2004-11-15 20:35 Nickolai Zeldovich
2004-11-15 23:02 ` David Weinehall
@ 2004-11-15 23:26 ` Maciej W. Rozycki
2004-11-15 23:52 ` Nickolai Zeldovich
1 sibling, 1 reply; 11+ messages in thread
From: Maciej W. Rozycki @ 2004-11-15 23:26 UTC (permalink / raw)
To: Nickolai Zeldovich; +Cc: linux-kernel, csapuntz
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
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [patch] Fix GDT re-load on ACPI resume
2004-11-15 23:26 ` Maciej W. Rozycki
@ 2004-11-15 23:52 ` Nickolai Zeldovich
0 siblings, 0 replies; 11+ messages in thread
From: Nickolai Zeldovich @ 2004-11-15 23:52 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: linux-kernel, csapuntz
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
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2004-11-18 2:29 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-11-16 5:37 [patch] Fix GDT re-load on ACPI resume Li, Shaohua
2004-11-16 12:42 ` Maciej W. Rozycki
2004-11-16 17:46 ` Hiroshi Itoh
2004-11-17 1:02 ` Maciej W. Rozycki
2004-11-17 18:57 ` Pavel Machek
-- strict thread matches above, loose matches on Subject: below --
2004-11-18 1:59 Li, Shaohua
2004-11-15 20:35 Nickolai Zeldovich
2004-11-15 23:02 ` David Weinehall
2004-11-15 23:13 ` Nickolai Zeldovich
2004-11-15 23:26 ` Maciej W. Rozycki
2004-11-15 23:52 ` Nickolai Zeldovich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox