1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
.code16
#define wakesym(sym) (sym - wakeup_start)
.align 16
ENTRY(wakeup_start)
cli
cld
# setup data segment
movw %cs, %ax
movw %ax, %ds
movw %ax, %ss # A stack required for BIOS call
movw $wakesym(early_stack), %sp
pushl $0 # Kill dangerous flag early
popfl
# check magic number
movl wakesym(real_magic), %eax
cmpl $0x12345678, %eax
jne bogus_real_magic
# for acpi_sleep=s3_bios
testl $1, wakesym(video_flags)
jz 1f
lcall $0xc000, $3
movw %cs, %ax # In case messed by BIOS
movw %ax, %ds
movw %ax, %ss # Need this? How to ret if clobbered?
1: # for acpi_sleep=s3_mode
testl $2, wakesym(video_flags)
jz 1f
movl wakesym(video_mode), %eax
call mode_setw
1: # Show some progress if VGA is resumed
movw $0xb800, %ax
movw %ax, %fs
movw $0x0e00 + 'L', %fs:(0x10)
# boot trampoline is under 1M, and shift its start into
# %fs to reference symbols in that area
movl $BOOT_TRAMPOLINE, %eax
shrl $4, %eax
movl %eax, %fs
lidt %fs:bootsym(idt_48)
lgdt %fs:bootsym(gdt_48)
movw $1, %ax
lmsw %ax # Turn on CR0.PE
jmp 1f
1: ljmpl $BOOT_CS32, $bootsym_phys(wakeup_32)
/* This code uses an extended set of video mode numbers. These include:
* Aliases for standard modes
* NORMAL_VGA (-1)
* EXTENDED_VGA (-2)
* ASK_VGA (-3)
* Video modes numbered by menu position -- NOT RECOMMENDED because of lack
* of compatibility when extending the table. These are between 0x00 and 0xff.
*/
#define VIDEO_FIRST_MENU 0x0000
/* Standard BIOS video modes (BIOS number + 0x0100) */
#define VIDEO_FIRST_BIOS 0x0100
/* VESA BIOS video modes (VESA number + 0x0200) */
#define VIDEO_FIRST_VESA 0x0200
/* Video7 special modes (BIOS number + 0x0900) */
#define VIDEO_FIRST_V7 0x0900
# Setting of user mode (AX=mode ID) => CF=success
mode_setw:
movw %ax, %bx
cmpb $VIDEO_FIRST_VESA>>8, %ah
jnc check_vesaw
decb %ah
setbadw: clc
ret
check_vesaw:
subb $VIDEO_FIRST_VESA>>8, %bh
orw $0x4000, %bx # Use linear frame buffer
movw $0x4f02, %ax # VESA BIOS mode set call
int $0x10
cmpw $0x004f, %ax # AL=4f if implemented
jnz _setbadw # AH=0 if OK
stc
ret
_setbadw: jmp setbadw
bogus_real_magic:
movw $0x0e00 + 'B', %fs:(0x12)
jmp bogus_real_magic
.align 4
real_magic: .long 0x12345678
.globl video_mode, video_flags
video_mode: .long 0
video_flags: .long 0
.code32
# Now in protect mode, with paging disabled
# Add offset for any reference to xen specific symbols
wakeup_32:
mov $BOOT_DS, %eax
mov %eax, %ds
mov %eax, %ss
mov $bootsym_phys(early_stack), %esp
# check saved magic again
mov $sym_phys(saved_magic), %eax
add bootsym_phys(trampoline_xen_phys_start), %eax
mov (%eax), %eax
cmp $0x9abcdef0, %eax
jne bogus_saved_magic
/* fpu init? */
/* Initialise CR4. */
#if CONFIG_PAGING_LEVELS == 2
mov $X86_CR4_PSE, %ecx
#else
mov $X86_CR4_PAE, %ecx
#endif
mov %ecx, %cr4
/* Load pagetable base register */
mov $sym_phys(idle_pg_table),%eax
add bootsym_phys(trampoline_xen_phys_start),%eax
mov %eax,%cr3
/* Will cpuid feature change after resume? */
#if CONFIG_PAGING_LEVELS != 2
/* Set up EFER (Extended Feature Enable Register). */
mov bootsym_phys(cpuid_ext_features),%edi
test $0x20100800,%edi /* SYSCALL/SYSRET, No Execute, Long Mode? */
jz .Lskip_eferw
movl $MSR_EFER,%ecx
rdmsr
#if CONFIG_PAGING_LEVELS == 4
btsl $_EFER_LME,%eax /* Long Mode */
btsl $_EFER_SCE,%eax /* SYSCALL/SYSRET */
#endif
btl $20,%edi /* No Execute? */
jnc 1f
btsl $_EFER_NX,%eax /* No Execute */
1: wrmsr
.Lskip_eferw:
#endif
wbinvd
mov $0x80050033,%eax /* hi-to-lo: PG,AM,WP,NE,ET,MP,PE */
mov %eax,%cr0
jmp 1f
1:
#if defined(__x86_64__)
/* Now in compatibility mode. Long-jump to 64-bit mode */
ljmp $BOOT_CS64, $bootsym_phys(wakeup_64)
.code64
.align 8
.word 0,0,0
lgdt_descr:
.word LAST_RESERVED_GDT_BYTE
.quad gdt_table - FIRST_RESERVED_GDT_BYTE
wakeup_64:
lgdt lgdt_descr(%rip)
mov $(__HYPERVISOR_DS64), %eax
mov %eax, %ds
# long jump to return point, with cs reload
rex64 ljmp *ret_point(%rip)
.align 8
ret_point:
.quad __ret_point
.word __HYPERVISOR_CS64
#else /* !defined(__x86_64__) */
lgdt gdt_descr
mov $(__HYPERVISOR_DS), %eax
mov %eax, %ds
ljmp $(__HYPERVISOR_CS), $__ret_point
#endif
bogus_saved_magic:
movw $0x0e00 + 'S', 0xb8014
jmp bogus_saved_magic
|