Re: wakeup code translated to .c

From: Pavel Machek
Date: Sun Feb 03 2008 - 19:04:55 EST


On Mon 2008-02-04 00:59:38, Rafael J. Wysocki wrote:
> On Monday, 4 of February 2008, Pavel Machek wrote:
> > Hi!
> >
> > > BTW, I don't like the way in which the 'struct wakeup_header' fields are
> > > reproduced in rm/wakeup.S very much, because it makes the code fragile.
> > > It might be better to define the offsets in asm-offsets*.c and refer to them
> > > relative to wakeup_header (if possible).
> >
> > If you can do that.. yes, that would be nice. I triple-checked it, but
> > indeed is fragile.
>
> Do you want me to remove the unused fields from 'struct wakeup_header' too?

I think I did that already. My wakeup.S/wakeup.h is attached. If you
can find more unused fields, kill them for sure.

(I'm not sure about fields needed on 32-bit only. I'm leaving them in
because it does not really matter).


--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
/*
* 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 entry; /* unused */
u16 total; /* unused */
u16 video_mode; /* Video mode number */
u16 _jmp1;
u32 pmode_entry; /* Protected mode resume point */
u16 _jmp2;
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;
u32 signature; /* To check we have correct structure */
} __attribute__((__packed__));

#endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */
/*
* 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:
entry: .short _start /* unused */
total: .short _end /* unused */
video_mode: .short 0 /* Video mode number */
pmode_return: .byte 0x66, 0xea /* ljmpl */
.long 0 /* offset goes here */
.short __KERNEL_CS
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: