acpi_wakecode.S revision 121743
1/*- 2 * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org> 3 * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <machine/asm.h> 29__FBSDID("$FreeBSD: head/sys/i386/acpica/acpi_wakecode.S 121743 2003-10-30 16:14:55Z iwasaki $"); 30 31#define LOCORE 32 33#include <machine/specialreg.h> 34 35 .align 4 36 .code16 37wakeup_16: 38 nop 39 cli 40 41 /* Set up segment registers for real mode */ 42 movw %cs,%ax 43 movw %ax,%ds 44 movw %ax,%ss 45 46#ifndef ACPI_NO_RESET_VIDEO 47 /* 48 * Re-initialize video BIOS. Restore DS and SS from CS in 49 * case the BIOS modified them. 50 */ 51 cmp $1, no_reset_video 52 je wakeup_16_gdt 53 lcall $0xc000, $3 54 movw %cs, %ax 55 movw %ax, %ds 56 movw %ax, %ss 57#endif 58 59wakeup_16_gdt: 60 /* Load GDT for real mode */ 61 lgdt physical_gdt 62 63 /* Restore CR2, CR3 and CR4 */ 64 mov previous_cr2,%eax 65 mov %eax,%cr2 66 mov previous_cr3,%eax 67 mov %eax,%cr3 68 mov previous_cr4,%eax 69 mov %eax,%cr4 70 71 /* Transfer some values to protected mode */ 72#define NVALUES 9 73#define TRANSFER_STACK32(val, idx) \ 74 mov val,%eax; \ 75 mov %eax,wakeup_32stack+(idx+1)+(idx*4); 76 77 TRANSFER_STACK32(previous_ss, (NVALUES - 9)) 78 TRANSFER_STACK32(previous_fs, (NVALUES - 8)) 79 TRANSFER_STACK32(previous_ds, (NVALUES - 7)) 80 TRANSFER_STACK32(physical_gdt+2, (NVALUES - 6)) 81 TRANSFER_STACK32(where_to_recover, (NVALUES - 5)) 82 TRANSFER_STACK32(previous_idt+2, (NVALUES - 4)) 83 TRANSFER_STACK32(previous_ldt, (NVALUES - 3)) 84 TRANSFER_STACK32(previous_gdt+2, (NVALUES - 2)) 85 TRANSFER_STACK32(previous_tr, (NVALUES - 1)) 86 TRANSFER_STACK32(previous_cr0, (NVALUES - 0)) 87 88 mov physical_esp,%esi /* to be used in 32bit code */ 89 90 /* Enable protected mode */ 91 mov %cr0,%eax 92 orl $(CR0_PE),%eax 93 mov %eax,%cr0 94 95wakeup_sw32: 96 /* Switch to protected mode by intersegmental jump */ 97 ljmpl $0x8,$0x12345678 /* Code location, to be replaced */ 98 99 .code32 100wakeup_32: 101 /* 102 * Switched to protected mode w/o paging 103 * %esi: KERNEL stack pointer (physical address) 104 */ 105 106 nop 107 108 /* Set up segment registers for protected mode */ 109 movw $0x10,%ax /* KDSEL to segment registers */ 110 movw %ax,%ds 111 movw %ax,%es 112 movw %ax,%gs 113 movw %ax,%ss 114 movw $0x18,%ax /* KPSEL to %fs */ 115 movw %ax,%fs 116 movl %esi,%esp /* physical address stack pointer */ 117 118wakeup_32stack: 119 /* Operands are overwritten in 16bit code */ 120 pushl $0xabcdef09 /* ss + dummy */ 121 pushl $0xabcdef08 /* fs + gs */ 122 pushl $0xabcdef07 /* ds + es */ 123 pushl $0xabcdef06 /* gdt:base (physical address) */ 124 pushl $0xabcdef05 /* recover address */ 125 pushl $0xabcdef04 /* idt:base */ 126 pushl $0xabcdef03 /* ldt + idt:limit */ 127 pushl $0xabcdef02 /* gdt:base */ 128 pushl $0xabcdef01 /* TR + gdt:limit */ 129 pushl $0xabcdef00 /* CR0 */ 130 131 movl %esp,%ebp 132#define CR0_REGISTER 0(%ebp) 133#define TASK_REGISTER 4(%ebp) 134#define PREVIOUS_GDT 6(%ebp) 135#define PREVIOUS_LDT 12(%ebp) 136#define PREVIOUS_IDT 14(%ebp) 137#define RECOVER_ADDR 20(%ebp) 138#define PHYSICAL_GDT_BASE 24(%ebp) 139#define PREVIOUS_DS 28(%ebp) 140#define PREVIOUS_ES 30(%ebp) 141#define PREVIOUS_FS 32(%ebp) 142#define PREVIOUS_GS 34(%ebp) 143#define PREVIOUS_SS 36(%ebp) 144 145 /* Fixup TSS type field */ 146#define TSS_TYPEFIX_MASK 0xf9 147 xorl %esi,%esi 148 movl PHYSICAL_GDT_BASE,%ebx 149 movw TASK_REGISTER,%si 150 leal (%ebx,%esi),%eax /* get TSS segment descriptor */ 151 andb $TSS_TYPEFIX_MASK,5(%eax) 152 153 /* Prepare to return to sleep/wakeup code point */ 154 lgdt PREVIOUS_GDT 155 lidt PREVIOUS_IDT 156 157 xorl %eax,%eax 158 movl %eax,%ebx 159 movl %eax,%ecx 160 movl %eax,%edx 161 movl %eax,%esi 162 movl %eax,%edi 163 movl PREVIOUS_DS,%ebx 164 movl PREVIOUS_FS,%ecx 165 movl PREVIOUS_SS,%edx 166 movw TASK_REGISTER,%si 167 shll $16,%esi 168 movw PREVIOUS_LDT,%si 169 movl RECOVER_ADDR,%edi 170 171 /* Enable paging and etc. */ 172 movl CR0_REGISTER,%eax 173 movl %eax,%cr0 174 175 /* Flush the prefetch queue */ 176 jmp 1f 1771: jmp 1f 1781: 179 /* 180 * Now that we are in kernel virtual memory addressing 181 * %ebx: ds + es 182 * %ecx: fs + gs 183 * %edx: ss + dummy 184 * %esi: LDTR + TR 185 * %edi: recover address 186 */ 187 188 nop 189 190 movl %esi,%eax /* LDTR + TR */ 191 lldt %ax /* load LDT register */ 192 shrl $16,%eax 193 ltr %ax /* load task register */ 194 195 /* Restore segment registers */ 196 movl %ebx,%eax /* ds + es */ 197 movw %ax,%ds 198 shrl $16,%eax 199 movw %ax,%es 200 movl %ecx,%eax /* fs + gs */ 201 movw %ax,%fs 202 shrl $16,%eax 203 movw %ax,%gs 204 movl %edx,%eax /* ss */ 205 movw %ax,%ss 206 207 /* Jump to acpi_restorecpu() */ 208 jmp *%edi 209 210/* used in real mode */ 211physical_gdt: .word 0 212 .long 0 213physical_esp: .long 0 214previous_cr2: .long 0 215previous_cr3: .long 0 216previous_cr4: .long 0 217no_reset_video: .long 0 218 219/* transfer from real mode to protected mode */ 220previous_cr0: .long 0 221previous_tr: .word 0 222previous_gdt: .word 0 223 .long 0 224previous_ldt: .word 0 225previous_idt: .word 0 226 .long 0 227where_to_recover: .long 0 228previous_ds: .word 0 229previous_es: .word 0 230previous_fs: .word 0 231previous_gs: .word 0 232previous_ss: .word 0 233dummy: .word 0 234