Path: blob/master/arch/x86/kernel/acpi/realmode/wakeup.S
10821 views
/*1* ACPI wakeup real mode startup stub2*/3#include <asm/segment.h>4#include <asm/msr-index.h>5#include <asm/page_types.h>6#include <asm/pgtable_types.h>7#include <asm/processor-flags.h>8#include "wakeup.h"910.code1611.section ".jump", "ax"12.globl _start13_start:14cli15jmp wakeup_code1617/* This should match the structure in wakeup.h */18.section ".header", "a"19.globl wakeup_header20wakeup_header:21video_mode: .short 0 /* Video mode number */22pmode_return: .byte 0x66, 0xea /* ljmpl */23.long 0 /* offset goes here */24.short __KERNEL_CS25pmode_cr0: .long 0 /* Saved %cr0 */26pmode_cr3: .long 0 /* Saved %cr3 */27pmode_cr4: .long 0 /* Saved %cr4 */28pmode_efer: .quad 0 /* Saved EFER */29pmode_gdt: .quad 030pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */31pmode_behavior: .long 0 /* Wakeup behavior flags */32realmode_flags: .long 033real_magic: .long 034trampoline_segment: .word 035_pad1: .byte 036wakeup_jmp: .byte 0xea /* ljmpw */37wakeup_jmp_off: .word 3f38wakeup_jmp_seg: .word 039wakeup_gdt: .quad 0, 0, 040signature: .long WAKEUP_HEADER_SIGNATURE4142.text43.code1644wakeup_code:45cld4647/* Apparently some dimwit BIOS programmers don't know how to48program a PM to RM transition, and we might end up here with49junk in the data segment descriptor registers. The only way50to repair that is to go into PM and fix it ourselves... */51movw $16, %cx52lgdtl %cs:wakeup_gdt53movl %cr0, %eax54orb $X86_CR0_PE, %al55movl %eax, %cr056jmp 1f571: ljmpw $8, $2f582:59movw %cx, %ds60movw %cx, %es61movw %cx, %ss62movw %cx, %fs63movw %cx, %gs6465andb $~X86_CR0_PE, %al66movl %eax, %cr067jmp wakeup_jmp683:69/* Set up segments */70movw %cs, %ax71movw %ax, %ds72movw %ax, %es73movw %ax, %ss74lidtl wakeup_idt7576movl $wakeup_stack_end, %esp7778/* Clear the EFLAGS */79pushl $080popfl8182/* Check header signature... */83movl signature, %eax84cmpl $WAKEUP_HEADER_SIGNATURE, %eax85jne bogus_real_magic8687/* Check we really have everything... */88movl end_signature, %eax89cmpl $WAKEUP_END_SIGNATURE, %eax90jne bogus_real_magic9192/* Call the C code */93calll main9495/* Restore MISC_ENABLE before entering protected mode, in case96BIOS decided to clear XD_DISABLE during S3. */97movl pmode_behavior, %eax98btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax99jnc 1f100101movl pmode_misc_en, %eax102movl pmode_misc_en + 4, %edx103movl $MSR_IA32_MISC_ENABLE, %ecx104wrmsr1051:106107/* Do any other stuff... */108109#ifndef CONFIG_64BIT110/* This could also be done in C code... */111movl pmode_cr3, %eax112movl %eax, %cr3113114movl pmode_cr4, %ecx115jecxz 1f116movl %ecx, %cr41171:118movl pmode_efer, %eax119movl pmode_efer + 4, %edx120movl %eax, %ecx121orl %edx, %ecx122jz 1f123movl $MSR_EFER, %ecx124wrmsr1251:126127lgdtl pmode_gdt128129/* This really couldn't... */130movl pmode_cr0, %eax131movl %eax, %cr0132jmp pmode_return133#else134pushw $0135pushw trampoline_segment136pushw $0137lret138#endif139140bogus_real_magic:1411:142hlt143jmp 1b144145.data146.balign 8147148/* This is the standard real-mode IDT */149wakeup_idt:150.word 0xffff /* limit */151.long 0 /* address */152.word 0153154.globl HEAP, heap_end155HEAP:156.long wakeup_heap157heap_end:158.long wakeup_stack159160.bss161wakeup_heap:162.space 2048163wakeup_stack:164.space 2048165wakeup_stack_end:166167.section ".signature","a"168end_signature:169.long WAKEUP_END_SIGNATURE170171172