public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "H. Peter Anvin" <hpa@zytor.com>
To: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Pavel Machek <pavel@ucw.cz>,
	kernel list <linux-kernel@vger.kernel.org>,
	Linux-pm mailing list <linux-pm@lists.osdl.org>
Subject: Re: [rft] s2ram wakeup moves to .c, could fix few machines
Date: Thu, 07 Feb 2008 14:38:54 -0800	[thread overview]
Message-ID: <47AB887E.7010000@zytor.com> (raw)
In-Reply-To: <200802072312.31430.rjw@sisk.pl>

Rafael J. Wysocki wrote:
> Index: linux-2.6/arch/x86/kernel/acpi/realmode/wakeup.S
> ===================================================================
> --- /dev/null
> +++ linux-2.6/arch/x86/kernel/acpi/realmode/wakeup.S
> @@ -0,0 +1,122 @@
> +/*
> + * ACPI wakeup real mode startup stub
> + */
> +#include <asm/segment.h>
> +#include <asm/msr-index.h>
> +#include <asm/page_64.h>
> +#include <asm/pgtable_64.h>
> +
> +	.code16
> +	.section ".header", "a"
> +
> +/* This should match the structure in wakeup.h */
> +		.globl	wakeup_header
> +wakeup_header:
> +video_mode:	.short	0	/* Video mode number */
> +pmode_return:	.byte	0x66, 0xea	/* ljmpl */
> +		.long	0	/* offset goes here */
> +		.short	__KERNEL_CS

Missing a .short pad here... Pavel fixed that at some point, I thought.

> +pmode_cr0:	.long	0	/* Saved %cr0 */
> +pmode_cr3:	.long	0	/* Saved %cr3 */
> +pmode_cr4:	.long	0	/* Saved %cr4 */
> +pmode_efer:	.quad	0	/* Saved EFER */
> +pmode_gdt:	.quad	0
> +realmode_flags:	.long	0
> +real_magic:	.long	0
> +trampoline_segment:	.word 0
> +signature:	.long	0x51ee1111
> +
> +	.text
> +	.globl	_start
> +	.code16
> +wakeup_code:
> +_start:
> +	cli
> +	cld
> +
> +	/* Set up segments */
> +	movw	%cs, %ax
> +	movw	%ax, %ds
> +	movw	%ax, %es
> +	movw	%ax, %ss
> +
> +	movl	$wakeup_stack_end, %esp
> +
> +	/* Clear the EFLAGS */
> +	pushl	$0
> +	popfl
> +
> +	/* Check header signature... */
> +	movl	signature, %eax
> +	cmpl	$0x51ee1111, %eax
> +	jne	bogus_real_magic
> +
> +	/* Check we really have everything... */
> +	movl	end_signature, %eax
> +	cmpl	$0x65a22c82, %eax
> +	jne	bogus_real_magic
> +
> +	/* Zero the bss */
> +	xorl	%eax, %eax
> +	movw	$__bss_start, %di
> +	movw	$__bss_end + 3, %cx
> +	subw	%di, %cx
> +	shrw	$2, %cx
> +	rep
> +	stosl
> +
> +	/* Call the C code */
> +	calll	main
> +
> +	/* Do any other stuff... */
> +
> +#ifndef CONFIG_64BIT
> +	/* This could also be done in C code... */
> +	movl	pmode_cr3, %eax
> +	movl	%eax, %cr3
> +
> +	movl	pmode_cr4, %ecx
> +	jecxz	1f
> +	movl	%ecx, %cr4
> +1:
> +	movl	pmode_efer, %eax
> +	movl	pmode_efer + 4, %edx
> +	movl	%eax, %ecx
> +	orl	%edx, %ecx
> +	jz	1f
> +	movl	$0xc0000080, %ecx
> +	wrmsr
> +1:
> +
> +	lgdtl	pmode_gdt
> +
> +	/* This really couldn't... */
> +	movl	pmode_cr0, %eax
> +	movl	%eax, %cr0
> +	jmp	pmode_return
> +#else
> +	pushw	$0
> +	pushw	trampoline_segment
> +	pushw	$0
> +	lret
> +#endif
> +
> +bogus_real_magic:
> +1:
> +	hlt
> +	jmp	1b
> +
> +	.data
> +	.balign	4
> +	.globl	HEAP, heap_end
> +HEAP:
> +	.long	wakeup_heap
> +heap_end:
> +	.long	wakeup_stack
> +
> +	.bss
> +wakeup_heap:
> +	.space	2048
> +wakeup_stack:
> +	.space	2048
> +wakeup_stack_end:
> Index: linux-2.6/arch/x86/kernel/acpi/realmode/wakeup.h
> ===================================================================
> --- /dev/null
> +++ linux-2.6/arch/x86/kernel/acpi/realmode/wakeup.h
> @@ -0,0 +1,29 @@
> +/*
> + * Definitions for the wakeup data structure at the head of the
> + * wakeup code.
> + */
> +
> +#ifndef ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H
> +#define ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H
> +
> +#include <linux/types.h>
> +
> +/* This must match data at wakeup.S */
> +struct wakeup_header {
> +	u16 video_mode;		/* Video mode number */
> +	u16 _jmp1;		/* ljmpl opcode, 32-bit only */
> +	u32 pmode_entry;	/* Protected mode resume point, 32-bit only */
> +	u16 _jmp2;		/* CS value, 32-bit only */
> +	u32 pmode_cr0;		/* Protected mode cr0 */
> +	u32 pmode_cr3;		/* Protected mode cr3 */
> +	u32 pmode_cr4;		/* Protected mode cr4 */
> +	u32 pmode_efer_low;	/* Protected mode EFER */
> +	u32 pmode_efer_high;
> +	u64 pmode_gdt;
> +	u32 realmode_flags;
> +	u32 real_magic;
> +	u16 trampoline_segment;	/* segment with trampoline code, 64-bit only */
> +	u32 signature;		/* To check we have correct structure */
> +} __attribute__((__packed__));
> +
> +#endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */
> Index: linux-2.6/arch/x86/kernel/acpi/realmode/wakeup.ld
> ===================================================================
> --- /dev/null
> +++ linux-2.6/arch/x86/kernel/acpi/realmode/wakeup.ld
> @@ -0,0 +1,51 @@
> +/*
> + * wakeup.ld
> + *
> + * Linker script for the real-mode wakeup code
> + */
> +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
> +OUTPUT_ARCH(i386)
> +ENTRY(_start)
> +
> +SECTIONS
> +{
> +	. = 0x3f00;
> +	.header		: { *(.header) }
> +
> +	. = 0;
> +	.text		: { *(.text*) }
> +
> +	. = ALIGN(16);
> +	.rodata		: { *(.rodata*) }
> +
> +	.videocards	: {
> +		video_cards = .;
> +		*(.videocards)
> +		video_cards_end = .;
> +	}
> +
> +	. = ALIGN(16);
> +	.data		: { *(.data*) }
> +
> +	.signature	: {
> +		end_signature = .;
> +		LONG(0x65a22c82)
> +	}
> +
> +	. = ALIGN(16);
> +	.bss		:
> +	{
> +		__bss_start = .;
> +		*(.bss)
> +		__bss_end = .;
> +	}
> +
> +	. = ALIGN(16);
> +	_end = .;
> +
> +	/DISCARD/ : { *(.note*) }
> +
> +	/* Adjust this as appropriate */
> +	/* This allows 4 pages (16K) */
> +	. = ASSERT(_end <= 0x4000, "Wakeup too big!");
> +}
> 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
> @@ -11,29 +11,84 @@
>  #include <linux/cpumask.h>
>  
>  #include <asm/smp.h>
> +#include "realmode/wakeup.h"
>  
>  /* address in low memory of the wakeup routine. */
> -unsigned long acpi_wakeup_address = 0;
> +static unsigned long acpi_realmode;
> +unsigned long acpi_wakeup_address;
>  unsigned long acpi_realmode_flags;
> -extern char wakeup_start, wakeup_end;
>  
> +extern char wakeup_code_start, wakeup_code_end;
>  extern unsigned long acpi_copy_wakeup_routine(unsigned long);
> +extern unsigned long setup_trampoline(void);
> +extern void wakeup_long64(void);
> +
> +extern unsigned long saved_video_mode;
> +extern long saved_magic;
> +extern volatile unsigned long init_rsp;
> +extern void (*initial_code)(void);
> +#ifndef CONFIG_64BIT
> +extern int wakeup_pmode_return;
> +extern char swsusp_pg_dir[PAGE_SIZE];
> +#else
> +static char temp_stack[10240];
> +#endif
> +
> +extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
>  
>  /**
>   * acpi_save_state_mem - save kernel state
>   *
>   * Create an identity mapped page table and copy the wakeup routine to
>   * low memory.
> + *
> + * Note that this is too late to change acpi_wakeup_address.
>   */
>  int acpi_save_state_mem(void)
>  {
> -	if (!acpi_wakeup_address) {
> -		printk(KERN_ERR "Could not allocate memory during boot, S3 disabled\n");
> +	struct wakeup_header *header;
> +
> +	if (!acpi_realmode) {
> +		printk(KERN_ERR "Could not allocate memory during boot, "
> +		       "S3 disabled\n");
>  		return -ENOMEM;
>  	}
> -	memcpy((void *)acpi_wakeup_address, &wakeup_start,
> -	       &wakeup_end - &wakeup_start);
> -	acpi_copy_wakeup_routine(acpi_wakeup_address);
> +	memcpy((void *)acpi_realmode, &wakeup_code_start, 4*PAGE_SIZE);

Using a PAGE_SIZE multiplier here isn't a good thing...

> +	header = (struct wakeup_header *)(acpi_realmode + 0x3f00);

... especially not with magic constants like this.

If you're putting the "header" at the end, then you should also replace 
the end_signature stuff since that's, then, redundant.  Furthermore, by 
doing so, you're also padding the binary out to its maximum length, so 
you might as well just remove the .bss-clearing stuff.

It's not really clear to me why to do this what way...

> +	if (header->signature != 0x51ee1111) {
> +		printk(KERN_ERR "wakeup header does not match\n");
> +		return -EINVAL;
> +	}
> +
> +	header->video_mode = saved_video_mode;
> +
> +#ifndef CONFIG_64BIT
> +	store_gdt(&header->pmode_gdt);
> +
> +	header->pmode_efer_low = nx_enabled;
> +	if (header->pmode_efer_low & 1) {
> +		/* This is strange, why not save efer, always? */
> +		rdmsr(MSR_EFER, header->pmode_efer_low,
> +			header->pmode_efer_high);
> +	}

Yes, why not save EFER every time?

	-hpa

  parent reply	other threads:[~2008-02-07 22:39 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 [this message]
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

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=47AB887E.7010000@zytor.com \
    --to=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@lists.osdl.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox