Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/x86/kernel/acpi/realmode/wakeup.S
10821 views
1
/*
2
* ACPI wakeup real mode startup stub
3
*/
4
#include <asm/segment.h>
5
#include <asm/msr-index.h>
6
#include <asm/page_types.h>
7
#include <asm/pgtable_types.h>
8
#include <asm/processor-flags.h>
9
#include "wakeup.h"
10
11
.code16
12
.section ".jump", "ax"
13
.globl _start
14
_start:
15
cli
16
jmp wakeup_code
17
18
/* This should match the structure in wakeup.h */
19
.section ".header", "a"
20
.globl wakeup_header
21
wakeup_header:
22
video_mode: .short 0 /* Video mode number */
23
pmode_return: .byte 0x66, 0xea /* ljmpl */
24
.long 0 /* offset goes here */
25
.short __KERNEL_CS
26
pmode_cr0: .long 0 /* Saved %cr0 */
27
pmode_cr3: .long 0 /* Saved %cr3 */
28
pmode_cr4: .long 0 /* Saved %cr4 */
29
pmode_efer: .quad 0 /* Saved EFER */
30
pmode_gdt: .quad 0
31
pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */
32
pmode_behavior: .long 0 /* Wakeup behavior flags */
33
realmode_flags: .long 0
34
real_magic: .long 0
35
trampoline_segment: .word 0
36
_pad1: .byte 0
37
wakeup_jmp: .byte 0xea /* ljmpw */
38
wakeup_jmp_off: .word 3f
39
wakeup_jmp_seg: .word 0
40
wakeup_gdt: .quad 0, 0, 0
41
signature: .long WAKEUP_HEADER_SIGNATURE
42
43
.text
44
.code16
45
wakeup_code:
46
cld
47
48
/* Apparently some dimwit BIOS programmers don't know how to
49
program a PM to RM transition, and we might end up here with
50
junk in the data segment descriptor registers. The only way
51
to repair that is to go into PM and fix it ourselves... */
52
movw $16, %cx
53
lgdtl %cs:wakeup_gdt
54
movl %cr0, %eax
55
orb $X86_CR0_PE, %al
56
movl %eax, %cr0
57
jmp 1f
58
1: ljmpw $8, $2f
59
2:
60
movw %cx, %ds
61
movw %cx, %es
62
movw %cx, %ss
63
movw %cx, %fs
64
movw %cx, %gs
65
66
andb $~X86_CR0_PE, %al
67
movl %eax, %cr0
68
jmp wakeup_jmp
69
3:
70
/* Set up segments */
71
movw %cs, %ax
72
movw %ax, %ds
73
movw %ax, %es
74
movw %ax, %ss
75
lidtl wakeup_idt
76
77
movl $wakeup_stack_end, %esp
78
79
/* Clear the EFLAGS */
80
pushl $0
81
popfl
82
83
/* Check header signature... */
84
movl signature, %eax
85
cmpl $WAKEUP_HEADER_SIGNATURE, %eax
86
jne bogus_real_magic
87
88
/* Check we really have everything... */
89
movl end_signature, %eax
90
cmpl $WAKEUP_END_SIGNATURE, %eax
91
jne bogus_real_magic
92
93
/* Call the C code */
94
calll main
95
96
/* Restore MISC_ENABLE before entering protected mode, in case
97
BIOS decided to clear XD_DISABLE during S3. */
98
movl pmode_behavior, %eax
99
btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax
100
jnc 1f
101
102
movl pmode_misc_en, %eax
103
movl pmode_misc_en + 4, %edx
104
movl $MSR_IA32_MISC_ENABLE, %ecx
105
wrmsr
106
1:
107
108
/* Do any other stuff... */
109
110
#ifndef CONFIG_64BIT
111
/* This could also be done in C code... */
112
movl pmode_cr3, %eax
113
movl %eax, %cr3
114
115
movl pmode_cr4, %ecx
116
jecxz 1f
117
movl %ecx, %cr4
118
1:
119
movl pmode_efer, %eax
120
movl pmode_efer + 4, %edx
121
movl %eax, %ecx
122
orl %edx, %ecx
123
jz 1f
124
movl $MSR_EFER, %ecx
125
wrmsr
126
1:
127
128
lgdtl pmode_gdt
129
130
/* This really couldn't... */
131
movl pmode_cr0, %eax
132
movl %eax, %cr0
133
jmp pmode_return
134
#else
135
pushw $0
136
pushw trampoline_segment
137
pushw $0
138
lret
139
#endif
140
141
bogus_real_magic:
142
1:
143
hlt
144
jmp 1b
145
146
.data
147
.balign 8
148
149
/* This is the standard real-mode IDT */
150
wakeup_idt:
151
.word 0xffff /* limit */
152
.long 0 /* address */
153
.word 0
154
155
.globl HEAP, heap_end
156
HEAP:
157
.long wakeup_heap
158
heap_end:
159
.long wakeup_stack
160
161
.bss
162
wakeup_heap:
163
.space 2048
164
wakeup_stack:
165
.space 2048
166
wakeup_stack_end:
167
168
.section ".signature","a"
169
end_signature:
170
.long WAKEUP_END_SIGNATURE
171
172