public inbox for linux-pm@vger.kernel.org
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Pavel Machek <pavel@ucw.cz>
Cc: kernel list <linux-kernel@vger.kernel.org>,
	Linux-pm mailing list <linux-pm@lists.osdl.org>,
	"H. Peter Anvin" <hpa@zytor.com>
Subject: Re: [rft] s2ram wakeup moves to .c, could fix few machines
Date: Thu, 7 Feb 2008 00:37:33 +0100	[thread overview]
Message-ID: <200802070037.34886.rjw@sisk.pl> (raw)
In-Reply-To: <20080205190600.GB11613@elf.ucw.cz>

On Tuesday, 5 of February 2008, Pavel Machek wrote:
> 
> This rewrites wakeup code to .c, and it fixes stack (should use movl
> ,%esp, not movw). Testers wanted. Makefile infrastructure was done by
> hpa, cleanups by rjw.
> 
> Signed-off-by: Pavel Machek <pavel@suse.cz>
> 
[--snip--]
> diff --git a/arch/x86_64/kernel/acpi/wakeup.S b/arch/x86_64/kernel/acpi/wakeup.S
> new file mode 100644
> index 0000000..d0f40d9
> --- /dev/null
> +++ b/arch/x86_64/kernel/acpi/wakeup.S

Surely this is not intentional?

> @@ -0,0 +1,425 @@
> +.text
> +#include <linux/linkage.h>
> +#include <asm/segment.h>
> +#include <asm/pgtable.h>
> +#include <asm/page.h>
> +#include <asm/msr.h>
> +
> +# Copyright 2003 Pavel Machek <pavel@suse.cz>, distribute under GPLv2
> +#
> +# wakeup_code runs in real mode, and at unknown address (determined at run-time).
> +# Therefore it must only use relative jumps/calls. 
> +#
> +# Do we need to deal with A20? It is okay: ACPI specs says A20 must be enabled
> +#
> +# If physical address of wakeup_code is 0x12345, BIOS should call us with
> +# cs = 0x1234, eip = 0x05
> +#
> +
> +#define BEEP \
> +	inb	$97, %al; 	\
> +	outb	%al, $0x80; 	\
> +	movb	$3, %al; 	\
> +	outb	%al, $97; 	\
> +	outb	%al, $0x80; 	\
> +	movb	$-74, %al; 	\
> +	outb	%al, $67; 	\
> +	outb	%al, $0x80; 	\
> +	movb	$-119, %al; 	\
> +	outb	%al, $66; 	\
> +	outb	%al, $0x80; 	\
> +	movb	$15, %al; 	\
> +	outb	%al, $66;
> +
> +
> +ALIGN
> +	.align	16
> +ENTRY(wakeup_start)
> +wakeup_code:
> +	wakeup_code_start = .
> +	.code16
> +
> +# Running in *copy* of this code, somewhere in low 1MB.
> +
> +	cli
> +	cld
> +	# setup data segment
> +	movw	%cs, %ax
> +	movw	%ax, %ds		# Make ds:0 point to wakeup_start
> +	movw	%ax, %ss
> +
> +	# Data segment must be set up before we can see whether to beep.
> +	testl   $4, realmode_flags - wakeup_code
> +	jz      1f
> +	BEEP
> +1:
> +
> +					# Private stack is needed for ASUS board
> +	mov	$(wakeup_stack - wakeup_code), %sp
> +
> +	pushl	$0			# Kill any dangerous flags
> +	popfl
> +
> +	movl	real_magic - wakeup_code, %eax
> +	cmpl	$0x12345678, %eax
> +	jne	bogus_real_magic
> +
> +	testl	$1, realmode_flags - wakeup_code
> +	jz	1f
> +	lcall   $0xc000,$3
> +	movw	%cs, %ax
> +	movw	%ax, %ds		# Bios might have played with that
> +	movw	%ax, %ss
> +1:
> +
> +	testl	$2, realmode_flags - wakeup_code
> +	jz	1f
> +	mov	video_mode - wakeup_code, %ax
> +	call	mode_set
> +1:
> +
> +	mov	%ds, %ax			# Find 32bit wakeup_code addr
> +	movzx   %ax, %esi			# (Convert %ds:gdt to a liner ptr)
> +	shll    $4, %esi
> +						# Fix up the vectors
> +	addl    %esi, wakeup_32_vector - wakeup_code
> +	addl    %esi, wakeup_long64_vector - wakeup_code
> +	addl    %esi, gdt_48a + 2 - wakeup_code # Fixup the gdt pointer
> +
> +	lidtl	%ds:idt_48a - wakeup_code
> +	lgdtl	%ds:gdt_48a - wakeup_code	# load gdt with whatever is
> +						# appropriate
> +
> +	movl	$1, %eax			# protected mode (PE) bit
> +	lmsw	%ax				# This is it!
> +	jmp	1f
> +1:
> +
> +	ljmpl   *(wakeup_32_vector - wakeup_code)
> +
> +	.balign 4
> +wakeup_32_vector:
> +	.long   wakeup_32 - wakeup_code
> +	.word   __KERNEL32_CS, 0
> +
> +	.code32
> +wakeup_32:
> +# Running in this code, but at low address; paging is not yet turned on.
> +
> +	movl	$__KERNEL_DS, %eax
> +	movl	%eax, %ds
> +
> +	/*
> +	 * Prepare for entering 64bits mode
> +	 */
> +
> +	/* Enable PAE */
> +	xorl	%eax, %eax
> +	btsl	$5, %eax
> +	movl	%eax, %cr4
> +
> +	/* Setup early boot stage 4 level pagetables */
> +	leal    (wakeup_level4_pgt - wakeup_code)(%esi), %eax
> +	movl	%eax, %cr3
> +
> +        /* Check if nx is implemented */
> +        movl    $0x80000001, %eax
> +        cpuid
> +        movl    %edx,%edi
> +
> +	/* Enable Long Mode */
> +	xorl    %eax, %eax
> +	btsl	$_EFER_LME, %eax
> +
> +	/* No Execute supported? */
> +	btl	$20,%edi
> +	jnc     1f
> +	btsl	$_EFER_NX, %eax
> +				
> +	/* Make changes effective */
> +1:	movl    $MSR_EFER, %ecx
> +	xorl    %edx, %edx
> +	wrmsr
> +
> +	xorl	%eax, %eax
> +	btsl	$31, %eax			/* Enable paging and in turn activate Long Mode */
> +	btsl	$0, %eax			/* Enable protected mode */
> +
> +	/* Make changes effective */
> +	movl	%eax, %cr0
> +
> +	/* At this point:
> +		CR4.PAE must be 1
> +		CS.L must be 0
> +		CR3 must point to PML4
> +		Next instruction must be a branch
> +		This must be on identity-mapped page
> +	*/
> +	/*
> +	 * At this point we're in long mode but in 32bit compatibility mode
> +	 * with EFER.LME = 1, CS.L = 0, CS.D = 1 (and in turn
> +	 * EFER.LMA = 1). Now we want to jump in 64bit mode, to do that we load
> +	 * the new gdt/idt that has __KERNEL_CS with CS.L = 1.
> +	 */
> +
> +	/* Finally jump in 64bit mode */
> +        ljmp    *(wakeup_long64_vector - wakeup_code)(%esi)
> +
> +	.balign 4
> +wakeup_long64_vector:
> +	.long   wakeup_long64 - wakeup_code
> +	.word   __KERNEL_CS, 0
> +
> +.code64
> +
> +	/* Hooray, we are in Long 64-bit mode (but still running in
> +	 * low memory)
> +	 */
> +wakeup_long64:
> +	/*
> +	 * We must switch to a new descriptor in kernel space for the GDT
> +	 * because soon the kernel won't have access anymore to the userspace
> +	 * addresses where we're currently running on. We have to do that here
> +	 * because in 32bit we couldn't load a 64bit linear address.
> +	 */
> +	lgdt	cpu_gdt_descr
> +
> +	movq    saved_magic, %rax
> +	movq    $0x123456789abcdef0, %rdx
> +	cmpq    %rdx, %rax
> +	jne     bogus_64_magic
> +
> +	nop
> +	nop
> +	movw	$__KERNEL_DS, %ax
> +	movw	%ax, %ss	
> +	movw	%ax, %ds
> +	movw	%ax, %es
> +	movw	%ax, %fs
> +	movw	%ax, %gs
> +	movq	saved_rsp, %rsp
> +
> +	movq	saved_rbx, %rbx
> +	movq	saved_rdi, %rdi
> +	movq	saved_rsi, %rsi
> +	movq	saved_rbp, %rbp
> +
> +	movq	saved_rip, %rax
> +	jmp	*%rax
> +
> +.code32
> +
> +	.align	64	
> +gdta:
> +	/* Its good to keep gdt in sync with one in trampoline.S */
> +	.word	0, 0, 0, 0			# dummy
> +	/* ??? Why I need the accessed bit set in order for this to work? */
> +	.quad   0x00cf9b000000ffff              # __KERNEL32_CS
> +	.quad   0x00af9b000000ffff              # __KERNEL_CS
> +	.quad   0x00cf93000000ffff              # __KERNEL_DS
> +
> +idt_48a:
> +	.word	0				# idt limit = 0
> +	.word	0, 0				# idt base = 0L
> +
> +gdt_48a:
> +	.word	0x800				# gdt limit=2048,
> +						#  256 GDT entries
> +	.long   gdta - wakeup_code              # gdt base (relocated in later)
> +	
> +real_magic:	.quad 0
> +video_mode:	.quad 0
> +realmode_flags:	.quad 0
> +
> +.code16
> +bogus_real_magic:
> +	jmp bogus_real_magic
> +
> +.code64
> +bogus_64_magic:
> +	jmp bogus_64_magic
> +
> +	
> +/* This code uses an extended set of video mode numbers. These include:
> + * Aliases for standard modes
> + *	NORMAL_VGA (-1)
> + *	EXTENDED_VGA (-2)
> + *	ASK_VGA (-3)
> + * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
> + * of compatibility when extending the table. These are between 0x00 and 0xff.
> + */
> +#define VIDEO_FIRST_MENU 0x0000
> +
> +/* Standard BIOS video modes (BIOS number + 0x0100) */
> +#define VIDEO_FIRST_BIOS 0x0100
> +
> +/* VESA BIOS video modes (VESA number + 0x0200) */
> +#define VIDEO_FIRST_VESA 0x0200
> +
> +/* Video7 special modes (BIOS number + 0x0900) */
> +#define VIDEO_FIRST_V7 0x0900
> +
> +# Setting of user mode (AX=mode ID) => CF=success
> +
> +# For now, we only handle VESA modes (0x0200..0x03ff).  To handle other
> +# modes, we should probably compile in the video code from the boot
> +# directory.
> +.code16
> +mode_set:
> +	movw	%ax, %bx
> +	subb	$VIDEO_FIRST_VESA>>8, %bh
> +	cmpb	$2, %bh
> +	jb	check_vesa
> +
> +setbad:
> +	clc
> +	ret
> +
> +check_vesa:
> +	orw	$0x4000, %bx			# Use linear frame buffer
> +	movw	$0x4f02, %ax			# VESA BIOS mode set call
> +	int	$0x10
> +	cmpw	$0x004f, %ax			# AL=4f if implemented
> +	jnz	setbad				# AH=0 if OK
> +
> +	stc
> +	ret
> +
> +wakeup_stack_begin:	# Stack grows down
> +
> +.org	0xff0
> +wakeup_stack:		# Just below end of page
> +
> +.org   0x1000
> +ENTRY(wakeup_level4_pgt)
> +	.quad   level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE
> +	.fill   510,8,0
> +	/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
> +	.quad   level3_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE
> +
> +ENTRY(wakeup_end)
> +	
> +##
> +# acpi_copy_wakeup_routine
> +#
> +# Copy the above routine to low memory.
> +#
> +# Parameters:
> +# %rdi:	place to copy wakeup routine to
> +#
> +# Returned address is location of code in low memory (past data and stack)
> +#
> +	.code64
> +ENTRY(acpi_copy_wakeup_routine)
> +	pushq	%rax
> +	pushq	%rdx
> +
> +	movl	saved_video_mode, %edx
> +	movl	%edx, video_mode - wakeup_start (,%rdi)
> +	movl	acpi_realmode_flags, %edx
> +	movl	%edx, realmode_flags - wakeup_start (,%rdi)
> +	movq	$0x12345678, real_magic - wakeup_start (,%rdi)
> +	movq	$0x123456789abcdef0, %rdx
> +	movq	%rdx, saved_magic
> +
> +	movq    saved_magic, %rax
> +	movq    $0x123456789abcdef0, %rdx
> +	cmpq    %rdx, %rax
> +	jne     bogus_64_magic
> +
> +	# restore the regs we used
> +	popq	%rdx
> +	popq	%rax
> +ENTRY(do_suspend_lowlevel_s4bios)
> +	ret
> +
> +	.align 2
> +	.p2align 4,,15
> +.globl do_suspend_lowlevel
> +	.type	do_suspend_lowlevel,@function
> +do_suspend_lowlevel:
> +.LFB5:
> +	subq	$8, %rsp
> +	xorl	%eax, %eax
> +	call	save_processor_state
> +
> +	movq %rsp, saved_context_esp(%rip)
> +	movq %rax, saved_context_eax(%rip)
> +	movq %rbx, saved_context_ebx(%rip)
> +	movq %rcx, saved_context_ecx(%rip)
> +	movq %rdx, saved_context_edx(%rip)
> +	movq %rbp, saved_context_ebp(%rip)
> +	movq %rsi, saved_context_esi(%rip)
> +	movq %rdi, saved_context_edi(%rip)
> +	movq %r8,  saved_context_r08(%rip)
> +	movq %r9,  saved_context_r09(%rip)
> +	movq %r10, saved_context_r10(%rip)
> +	movq %r11, saved_context_r11(%rip)
> +	movq %r12, saved_context_r12(%rip)
> +	movq %r13, saved_context_r13(%rip)
> +	movq %r14, saved_context_r14(%rip)
> +	movq %r15, saved_context_r15(%rip)
> +	pushfq ; popq saved_context_eflags(%rip)
> +
> +	movq	$.L97, saved_rip(%rip)
> +
> +	movq %rsp,saved_rsp
> +	movq %rbp,saved_rbp
> +	movq %rbx,saved_rbx
> +	movq %rdi,saved_rdi
> +	movq %rsi,saved_rsi
> +
> +	addq	$8, %rsp
> +	movl	$3, %edi
> +	xorl	%eax, %eax
> +	jmp	acpi_enter_sleep_state
> +.L97:
> +	.p2align 4,,7
> +.L99:
> +	.align 4
> +	movl	$24, %eax
> +	movw %ax, %ds
> +	movq	saved_context+58(%rip), %rax
> +	movq %rax, %cr4
> +	movq	saved_context+50(%rip), %rax
> +	movq %rax, %cr3
> +	movq	saved_context+42(%rip), %rax
> +	movq %rax, %cr2
> +	movq	saved_context+34(%rip), %rax
> +	movq %rax, %cr0
> +	pushq saved_context_eflags(%rip) ; popfq
> +	movq saved_context_esp(%rip), %rsp
> +	movq saved_context_ebp(%rip), %rbp
> +	movq saved_context_eax(%rip), %rax
> +	movq saved_context_ebx(%rip), %rbx
> +	movq saved_context_ecx(%rip), %rcx
> +	movq saved_context_edx(%rip), %rdx
> +	movq saved_context_esi(%rip), %rsi
> +	movq saved_context_edi(%rip), %rdi
> +	movq saved_context_r08(%rip), %r8
> +	movq saved_context_r09(%rip), %r9
> +	movq saved_context_r10(%rip), %r10
> +	movq saved_context_r11(%rip), %r11
> +	movq saved_context_r12(%rip), %r12
> +	movq saved_context_r13(%rip), %r13
> +	movq saved_context_r14(%rip), %r14
> +	movq saved_context_r15(%rip), %r15
> +
> +	xorl	%eax, %eax
> +	addq	$8, %rsp
> +	jmp	restore_processor_state
> +.LFE5:
> +.Lfe5:
> +	.size	do_suspend_lowlevel,.Lfe5-do_suspend_lowlevel
> +	
> +.data
> +ALIGN
> +ENTRY(saved_rbp)	.quad	0
> +ENTRY(saved_rsi)	.quad	0
> +ENTRY(saved_rdi)	.quad	0
> +ENTRY(saved_rbx)	.quad	0
> +
> +ENTRY(saved_rip)	.quad	0
> +ENTRY(saved_rsp)	.quad	0
> +
> +ENTRY(saved_magic)	.quad	0
> diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
> index 485de13..56e09cf 100644
> --- a/drivers/acpi/sleep/main.c
> +++ b/drivers/acpi/sleep/main.c
> @@ -170,7 +170,7 @@ static int acpi_pm_enter(suspend_state_t
>  	/* Reprogram control registers and execute _BFS */
>  	acpi_leave_sleep_state_prep(acpi_state);
>  
> -	/* ACPI 3.0 specs (P62) says that it's the responsabilty
> +	/* ACPI 3.0 specs (P62) says that it's the responsibilty
>  	 * of the OSPM to clear the status bit [ implying that the
>  	 * POWER_BUTTON event should not reach userspace ]
>  	 */
> 



-- 
"Premature optimization is the root of all evil." - Donald Knuth

      parent reply	other threads:[~2008-02-06 23:37 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-02-05 19:06 [rft] s2ram wakeup moves to .c, could fix few machines Pavel Machek
2008-02-06  1:27 ` Rafael J. Wysocki
2008-02-06  1:36   ` H. Peter Anvin
2008-02-06  1:42     ` Rafael J. Wysocki
2008-02-06  1:51       ` H. Peter Anvin
2008-02-06  1:56         ` Rafael J. Wysocki
2008-02-06 11:29         ` Pavel Machek
2008-02-14  2:54         ` Bill Davidsen
2008-02-06 23:48   ` Rafael J. Wysocki
2008-02-07 22:12     ` Rafael J. Wysocki
2008-02-07 22:28       ` Sam Ravnborg
2008-02-07 22:34         ` H. Peter Anvin
2008-02-08 21:31         ` Pavel Machek
2008-02-08 21:34         ` Pavel Machek
2008-02-08 21:41         ` Pavel Machek
2008-02-08 21:47           ` Sam Ravnborg
2008-02-08 21:49         ` Pavel Machek
2008-02-07 22:28       ` Pavel Machek
2008-02-07 22:40         ` Rafael J. Wysocki
2008-02-07 22:44           ` H. Peter Anvin
2008-02-07 22:53             ` Rafael J. Wysocki
2008-02-07 22:45           ` H. Peter Anvin
2008-02-07 22:49             ` Pavel Machek
2008-02-08 21:13           ` Pavel Machek
2008-02-08 21:41             ` Maxim Levitsky
2008-02-08 21:51               ` Pavel Machek
2008-02-07 22:46         ` H. Peter Anvin
2008-02-07 22:51           ` Pavel Machek
2008-02-07 23:09             ` Rafael J. Wysocki
2008-02-07 22:57           ` Rafael J. Wysocki
2008-02-07 23:14             ` H. Peter Anvin
2008-02-08 21:35               ` Pavel Machek
2008-02-07 22:38       ` H. Peter Anvin
2008-02-07 23:06         ` Rafael J. Wysocki
2008-02-07 23:13           ` H. Peter Anvin
2008-02-07 23:35           ` Pavel Machek
2008-02-07 23:36             ` Rafael J. Wysocki
2008-02-07 23:41               ` Pavel Machek
2008-02-07 23:42             ` H. Peter Anvin
2008-02-08  7:04               ` Pavel Machek
2008-02-08  7:40                 ` H. Peter Anvin
2008-02-08 16:23                 ` Rafael J. Wysocki
2008-02-08 21:00                   ` Pavel Machek
2008-02-08 21:02                     ` H. Peter Anvin
2008-02-08 21:09                       ` Pavel Machek
2008-02-08 21:18                         ` H. Peter Anvin
2008-02-08 21:20                     ` [linux-pm] " Alan Stern
2008-02-08 21:23                       ` Pavel Machek
2008-02-08 21:27                         ` H. Peter Anvin
2008-02-08 21:31                           ` Pavel Machek
2008-02-08 21:56                             ` Rafael J. Wysocki
2008-02-08 21:59                               ` Pavel Machek
2008-02-08 21:56         ` Pavel Machek
2008-02-08 21:58         ` Pavel Machek
2008-02-08 22:01           ` Rafael J. Wysocki
2008-02-08 22:08             ` Pavel Machek
2008-02-09  0:18               ` Rafael J. Wysocki
2008-02-09  0:32                 ` H. Peter Anvin
2008-02-09 13:48                   ` Rafael J. Wysocki
2008-02-10 21:14                   ` Pavel Machek
2008-02-10 21:21                     ` Sam Ravnborg
2008-02-06 23:37 ` Rafael J. Wysocki [this message]

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=200802070037.34886.rjw@sisk.pl \
    --to=rjw@sisk.pl \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@lists.osdl.org \
    --cc=pavel@ucw.cz \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox