0001
0002
0003
0004
0005 #include <linux/linkage.h>
0006 #include <asm/segment.h>
0007 #include <asm/msr-index.h>
0008 #include <asm/page_types.h>
0009 #include <asm/pgtable_types.h>
0010 #include <asm/processor-flags.h>
0011 #include "realmode.h"
0012 #include "wakeup.h"
0013
0014 .code16
0015
0016
0017 .section ".data", "aw"
0018
0019 .balign 16
0020 SYM_DATA_START(wakeup_header)
0021 video_mode: .short 0
0022 pmode_entry: .long 0
0023 pmode_cs: .short __KERNEL_CS
0024 pmode_cr0: .long 0
0025 pmode_cr3: .long 0
0026 pmode_cr4: .long 0
0027 pmode_efer: .quad 0
0028 pmode_gdt: .quad 0
0029 pmode_misc_en: .quad 0
0030 pmode_behavior: .long 0
0031 realmode_flags: .long 0
0032 real_magic: .long 0
0033 signature: .long WAKEUP_HEADER_SIGNATURE
0034 SYM_DATA_END(wakeup_header)
0035
0036 .text
0037 .code16
0038
0039 .balign 16
0040 SYM_CODE_START(wakeup_start)
0041 cli
0042 cld
0043
0044 LJMPW_RM(3f)
0045 3:
0046
0047
0048
0049
0050 movw $16, %cx
0051 lgdtl %cs:wakeup_gdt
0052 movl %cr0, %eax
0053 orb $X86_CR0_PE, %al
0054 movl %eax, %cr0
0055 ljmpw $8, $2f
0056 2:
0057 movw %cx, %ds
0058 movw %cx, %es
0059 movw %cx, %ss
0060 movw %cx, %fs
0061 movw %cx, %gs
0062
0063 andb $~X86_CR0_PE, %al
0064 movl %eax, %cr0
0065 LJMPW_RM(3f)
0066 3:
0067
0068 movw %cs, %ax
0069 movw %ax, %ss
0070 movl $rm_stack_end, %esp
0071 movw %ax, %ds
0072 movw %ax, %es
0073 movw %ax, %fs
0074 movw %ax, %gs
0075
0076 lidtl .Lwakeup_idt
0077
0078
0079 pushl $0
0080 popfl
0081
0082
0083 movl signature, %eax
0084 cmpl $WAKEUP_HEADER_SIGNATURE, %eax
0085 jne bogus_real_magic
0086
0087
0088 movl end_signature, %eax
0089 cmpl $REALMODE_END_SIGNATURE, %eax
0090 jne bogus_real_magic
0091
0092
0093 calll main
0094
0095
0096
0097 movl pmode_behavior, %edi
0098 btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %edi
0099 jnc 1f
0100
0101 movl pmode_misc_en, %eax
0102 movl pmode_misc_en + 4, %edx
0103 movl $MSR_IA32_MISC_ENABLE, %ecx
0104 wrmsr
0105 1:
0106
0107
0108
0109 #ifndef CONFIG_64BIT
0110
0111 movl pmode_cr3, %eax
0112 movl %eax, %cr3
0113
0114 btl $WAKEUP_BEHAVIOR_RESTORE_CR4, %edi
0115 jnc 1f
0116 movl pmode_cr4, %eax
0117 movl %eax, %cr4
0118 1:
0119 btl $WAKEUP_BEHAVIOR_RESTORE_EFER, %edi
0120 jnc 1f
0121 movl pmode_efer, %eax
0122 movl pmode_efer + 4, %edx
0123 movl $MSR_EFER, %ecx
0124 wrmsr
0125 1:
0126
0127 lgdtl pmode_gdt
0128
0129
0130 movl pmode_entry, %eax
0131 movl pmode_cr0, %ecx
0132 movl %ecx, %cr0
0133 ljmpl $__KERNEL_CS, $pa_startup_32
0134
0135 #else
0136 jmp trampoline_start
0137 #endif
0138 SYM_CODE_END(wakeup_start)
0139
0140 bogus_real_magic:
0141 1:
0142 hlt
0143 jmp 1b
0144
0145 .section ".rodata","a"
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 .balign 16
0156 SYM_DATA_START(wakeup_gdt)
0157 .word 3*8-1
0158 .long pa_wakeup_gdt
0159 .word 0
0160
0161 .word 0xffff
0162 .long 0x9b000000 + pa_real_mode_base
0163 .word 0x008f
0164
0165 .word 0xffff
0166 .long 0x93000000 + pa_real_mode_base
0167 .word 0x008f
0168 SYM_DATA_END(wakeup_gdt)
0169
0170 .section ".rodata","a"
0171 .balign 8
0172
0173
0174 .balign 16
0175 SYM_DATA_START_LOCAL(.Lwakeup_idt)
0176 .word 0xffff
0177 .long 0
0178 .word 0
0179 SYM_DATA_END(.Lwakeup_idt)