debuggers.hg

view xen/arch/x86/boot/wakeup.S @ 19808:64a932c92a7c

x86: fix s3 resume on AMD CPUs

Avoid longjmp as it has different semantics than on Intel CPUs in long
mode. Also add a few comments and remove a pointless reload of DS.

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