All of lore.kernel.org
 help / color / mirror / Atom feed
From: Len Brown <lenb@kernel.org>
To: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
	Ingo Molnar <mingo@elte.hu>, LKML <linux-kernel@vger.kernel.org>,
	Pavel Machek <pavel@ucw.cz>,
	pm list <linux-pm@lists.linux-foundation.org>
Subject: Re: [PATCH] x86 ACPI: normalize segment descriptor register on resume
Date: Tue, 24 Jun 2008 17:47:20 -0400 (EDT)	[thread overview]
Message-ID: <alpine.LFD.1.10.0806241747071.3014@localhost.localdomain> (raw)
In-Reply-To: <200806242303.49498.rjw@sisk.pl>

Applied.

thanks,
-Len

On Tue, 24 Jun 2008, Rafael J. Wysocki wrote:

> Hi,
> 
> The patch below fixes the regression described at
> http://bugzilla.kernel.org/show_bug.cgi?id=10927
> which is caused by the fact that some BIOSes call the kernel's resume code with
> post-protected mode garbage in segment registers.
> 
> Apart from Dell laptops referred to in the chagelog it has a potential to fix
> some other systems on which resume from suspend to RAM fails in a mysterious
> way and the probability of it breaking things is rather small, so IMO it would
> be nice to have in 2.6.26.
> 
> Thanks,
> Rafael
> 
> 
> ---
> From: H. Peter Anvin <hpa@zytor.com>
> 
> x86 ACPI: normalize segment descriptor register on resume
> 
> Some Dell laptops enter resume with apparent garbage in the segment
> descriptor registers (almost certainly the result of a botched
> transition from protected to real mode.)  The only way to clean that
> up is to enter protected mode ourselves and clean out the descriptor
> registers.
> 
> This fixes resume on Dell XPS M1210 and Dell D620.
> 
> Reference: http://bugzilla.kernel.org/show_bug.cgi?id=10927
> 
> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
> Tested-by: Kirill A. Shutemov <kirill@shutemov.name>
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> ---
>  arch/x86/kernel/acpi/realmode/wakeup.S |   38 ++++++++++++++++++++++++++++++++-
>  arch/x86/kernel/acpi/realmode/wakeup.h |    5 ++++
>  arch/x86/kernel/acpi/sleep.c           |   16 +++++++++++++
>  drivers/acpi/sleep/main.c              |    5 +---
>  4 files changed, 59 insertions(+), 5 deletions(-)
> 
> Index: linux-2.6/arch/x86/kernel/acpi/realmode/wakeup.S
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/acpi/realmode/wakeup.S
> +++ linux-2.6/arch/x86/kernel/acpi/realmode/wakeup.S
> @@ -5,6 +5,7 @@
>  #include <asm/msr-index.h>
>  #include <asm/page.h>
>  #include <asm/pgtable.h>
> +#include <asm/processor-flags.h>
>  
>  	.code16
>  	.section ".header", "a"
> @@ -24,6 +25,11 @@ pmode_gdt:	.quad	0
>  realmode_flags:	.long	0
>  real_magic:	.long	0
>  trampoline_segment:	.word 0
> +_pad1:		.byte	0
> +wakeup_jmp:	.byte	0xea	/* ljmpw */
> +wakeup_jmp_off:	.word	3f
> +wakeup_jmp_seg:	.word	0
> +wakeup_gdt:	.quad	0, 0, 0
>  signature:	.long	0x51ee1111
>  
>  	.text
> @@ -34,11 +40,34 @@ _start:
>  	cli
>  	cld
>  
> +	/* Apparently some dimwit BIOS programmers don't know how to
> +	   program a PM to RM transition, and we might end up here with
> +	   junk in the data segment descriptor registers.  The only way
> +	   to repair that is to go into PM and fix it ourselves... */
> +	movw	$16, %cx
> +	lgdtl	%cs:wakeup_gdt
> +	movl	%cr0, %eax
> +	orb	$X86_CR0_PE, %al
> +	movl	%eax, %cr0
> +	jmp	1f
> +1:	ljmpw	$8, $2f
> +2:
> +	movw	%cx, %ds
> +	movw	%cx, %es
> +	movw	%cx, %ss
> +	movw	%cx, %fs
> +	movw	%cx, %gs
> +
> +	andb	$~X86_CR0_PE, %al
> +	movl	%eax, %cr0
> +	jmp	wakeup_jmp
> +3:
>  	/* Set up segments */
>  	movw	%cs, %ax
>  	movw	%ax, %ds
>  	movw	%ax, %es
>  	movw	%ax, %ss
> +	lidtl	wakeup_idt
>  
>  	movl	$wakeup_stack_end, %esp
>  
> @@ -98,7 +127,14 @@ bogus_real_magic:
>  	jmp	1b
>  
>  	.data
> -	.balign	4
> +	.balign	8
> +
> +	/* This is the standard real-mode IDT */
> +wakeup_idt:
> +	.word	0xffff		/* limit */
> +	.long	0		/* address */
> +	.word	0
> +
>  	.globl	HEAP, heap_end
>  HEAP:
>  	.long	wakeup_heap
> Index: linux-2.6/arch/x86/kernel/acpi/realmode/wakeup.h
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/acpi/realmode/wakeup.h
> +++ linux-2.6/arch/x86/kernel/acpi/realmode/wakeup.h
> @@ -24,6 +24,11 @@ struct wakeup_header {
>  	u32 realmode_flags;
>  	u32 real_magic;
>  	u16 trampoline_segment;	/* segment with trampoline code, 64-bit only */
> +	u8  _pad1;
> +	u8  wakeup_jmp;
> +	u16 wakeup_jmp_off;
> +	u16 wakeup_jmp_seg;
> +	u64 wakeup_gdt[3];
>  	u32 signature;		/* To check we have correct structure */
>  } __attribute__((__packed__));
>  
> Index: linux-2.6/arch/x86/kernel/acpi/sleep.c
> ===================================================================
> --- linux-2.6.orig/arch/x86/kernel/acpi/sleep.c
> +++ linux-2.6/arch/x86/kernel/acpi/sleep.c
> @@ -50,6 +50,20 @@ int acpi_save_state_mem(void)
>  
>  	header->video_mode = saved_video_mode;
>  
> +	header->wakeup_jmp_seg = acpi_wakeup_address >> 4;
> +	/* GDT[0]: GDT self-pointer */
> +	header->wakeup_gdt[0] =
> +		(u64)(sizeof(header->wakeup_gdt) - 1) +
> +		((u64)(acpi_wakeup_address +
> +			((char *)&header->wakeup_gdt - (char *)acpi_realmode))
> +				<< 16);
> +	/* GDT[1]: real-mode-like code segment */
> +	header->wakeup_gdt[1] = (0x009bULL << 40) +
> +		((u64)acpi_wakeup_address << 16) + 0xffff;
> +	/* GDT[2]: real-mode-like data segment */
> +	header->wakeup_gdt[2] = (0x0093ULL << 40) +
> +		((u64)acpi_wakeup_address << 16) + 0xffff;
> +
>  #ifndef CONFIG_64BIT
>  	store_gdt((struct desc_ptr *)&header->pmode_gdt);
>  
> @@ -111,7 +125,7 @@ void __init acpi_reserve_bootmem(void)
>  		return;
>  	}
>  
> -	acpi_wakeup_address = acpi_realmode;
> +	acpi_wakeup_address = virt_to_phys((void *)acpi_realmode);
>  }
>  
>  
> Index: linux-2.6/drivers/acpi/sleep/main.c
> ===================================================================
> --- linux-2.6.orig/drivers/acpi/sleep/main.c
> +++ linux-2.6/drivers/acpi/sleep/main.c
> @@ -32,9 +32,8 @@ static int acpi_sleep_prepare(u32 acpi_s
>  		if (!acpi_wakeup_address) {
>  			return -EFAULT;
>  		}
> -		acpi_set_firmware_waking_vector((acpi_physical_address)
> -						virt_to_phys((void *)
> -							     acpi_wakeup_address));
> +		acpi_set_firmware_waking_vector(
> +				(acpi_physical_address)acpi_wakeup_address);
>  
>  	}
>  	ACPI_FLUSH_CPU_CACHE();
> 

  parent reply	other threads:[~2008-06-24 21:47 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-06-24 21:03 [PATCH] x86 ACPI: normalize segment descriptor register on resume Rafael J. Wysocki
2008-06-24 21:46 ` Pavel Machek
2008-06-24 21:46 ` Pavel Machek
2008-06-25 17:01   ` Ingo Molnar
2008-06-25 20:17     ` Rafael J. Wysocki
2008-06-26  8:17       ` Andrew Morton
2008-06-26  8:29         ` Ingo Molnar
2008-06-26  8:39           ` Rafael J. Wysocki
2008-06-26  8:39           ` Rafael J. Wysocki
2008-06-26  8:51             ` Ingo Molnar
2008-06-26  8:51             ` Ingo Molnar
2008-06-26  8:56               ` Rafael J. Wysocki
2008-06-26  8:56               ` Rafael J. Wysocki
2008-06-26  8:29         ` Ingo Molnar
2008-06-26  8:35         ` Rafael J. Wysocki
2008-06-26  8:35         ` Rafael J. Wysocki
2008-06-26  8:17       ` Andrew Morton
2008-06-25 20:17     ` Rafael J. Wysocki
2008-06-25 17:01   ` Ingo Molnar
2008-06-24 21:47 ` Len Brown
2008-06-24 21:47 ` Len Brown [this message]
  -- strict thread matches above, loose matches on Subject: below --
2008-06-24 21:03 Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.LFD.1.10.0806241747071.3014@localhost.localdomain \
    --to=lenb@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=mingo@elte.hu \
    --cc=pavel@ucw.cz \
    --cc=rjw@sisk.pl \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.