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

Hiroshi Itoh
2004-11-16T17:46:50Z

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