acpi_wakecode.S revision 121603
1117397Skan/*- 2117397Skan * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org> 3117397Skan * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org> 4117397Skan * All rights reserved. 5117397Skan * 6117397Skan * Redistribution and use in source and binary forms, with or without 7117397Skan * modification, are permitted provided that the following conditions 8117397Skan * are met: 9117397Skan * 1. Redistributions of source code must retain the above copyright 10117397Skan * notice, this list of conditions and the following disclaimer. 11117397Skan * 2. Redistributions in binary form must reproduce the above copyright 12117397Skan * notice, this list of conditions and the following disclaimer in the 13117397Skan * documentation and/or other materials provided with the distribution. 14117397Skan * 15117397Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16117397Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17117397Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18169691Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19117397Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20117397Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21117397Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22117397Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23117397Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24117397Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25117397Skan * SUCH DAMAGE. 26117397Skan */ 27117397Skan 28117397Skan#include <machine/asm.h> 29117397Skan__FBSDID("$FreeBSD: head/sys/i386/acpica/acpi_wakecode.S 121603 2003-10-27 06:26:51Z njl $"); 30169691Skan 31169691Skan#define LOCORE 32169691Skan 33169691Skan#include <machine/specialreg.h> 34169691Skan 35117397Skan .align 4 36117397Skan .code16 37117397Skanwakeup_16: 38117397Skan nop 39117397Skan cli 40117397Skan 41117397Skan /* Set up segment registers for real mode */ 42169691Skan movw %cs,%ax 43169691Skan movw %ax,%ds 44117397Skan movw %ax,%ss 45117397Skan 46117397Skan /* 47117397Skan * Re-initialize video BIOS. Restore DS and SS from CS in 48117397Skan * case the BIOS modified them. 49117397Skan */ 50117397Skan lcall $0xc000, $3 51117397Skan movw %cs, %ax 52117397Skan movw %ax, %ds 53117397Skan movw %ax, %ss 54117397Skan 55117397Skan /* Load GDT for real mode */ 56117397Skan lgdt physical_gdt 57117397Skan 58117397Skan /* Restore CR2, CR3 and CR4 */ 59117397Skan mov previous_cr2,%eax 60117397Skan mov %eax,%cr2 61117397Skan mov previous_cr3,%eax 62117397Skan mov %eax,%cr3 63117397Skan mov previous_cr4,%eax 64117397Skan mov %eax,%cr4 65117397Skan 66117397Skan /* Transfer some values to protected mode */ 67117397Skan#define NVALUES 9 68117397Skan#define TRANSFER_STACK32(val, idx) \ 69117397Skan mov val,%eax; \ 70117397Skan mov %eax,wakeup_32stack+(idx+1)+(idx*4); 71117397Skan 72117397Skan TRANSFER_STACK32(previous_ss, (NVALUES - 9)) 73117397Skan TRANSFER_STACK32(previous_fs, (NVALUES - 8)) 74117397Skan TRANSFER_STACK32(previous_ds, (NVALUES - 7)) 75169691Skan TRANSFER_STACK32(physical_gdt+2, (NVALUES - 6)) 76169691Skan TRANSFER_STACK32(where_to_recover, (NVALUES - 5)) 77 TRANSFER_STACK32(previous_idt+2, (NVALUES - 4)) 78 TRANSFER_STACK32(previous_ldt, (NVALUES - 3)) 79 TRANSFER_STACK32(previous_gdt+2, (NVALUES - 2)) 80 TRANSFER_STACK32(previous_tr, (NVALUES - 1)) 81 TRANSFER_STACK32(previous_cr0, (NVALUES - 0)) 82 83 mov physical_esp,%esi /* to be used in 32bit code */ 84 85 /* Enable protected mode */ 86 mov %cr0,%eax 87 orl $(CR0_PE),%eax 88 mov %eax,%cr0 89 90wakeup_sw32: 91 /* Switch to protected mode by intersegmental jump */ 92 ljmpl $0x8,$0x12345678 /* Code location, to be replaced */ 93 94 .code32 95wakeup_32: 96 /* 97 * Switched to protected mode w/o paging 98 * %esi: KERNEL stack pointer (physical address) 99 */ 100 101 nop 102 103 /* Set up segment registers for protected mode */ 104 movw $0x10,%ax /* KDSEL to segment registers */ 105 movw %ax,%ds 106 movw %ax,%es 107 movw %ax,%gs 108 movw %ax,%ss 109 movw $0x18,%ax /* KPSEL to %fs */ 110 movw %ax,%fs 111 movl %esi,%esp /* physical address stack pointer */ 112 113wakeup_32stack: 114 /* Operands are overwritten in 16bit code */ 115 pushl $0xabcdef09 /* ss + dummy */ 116 pushl $0xabcdef08 /* fs + gs */ 117 pushl $0xabcdef07 /* ds + es */ 118 pushl $0xabcdef06 /* gdt:base (physical address) */ 119 pushl $0xabcdef05 /* recover address */ 120 pushl $0xabcdef04 /* idt:base */ 121 pushl $0xabcdef03 /* ldt + idt:limit */ 122 pushl $0xabcdef02 /* gdt:base */ 123 pushl $0xabcdef01 /* TR + gdt:limit */ 124 pushl $0xabcdef00 /* CR0 */ 125 126 movl %esp,%ebp 127#define CR0_REGISTER 0(%ebp) 128#define TASK_REGISTER 4(%ebp) 129#define PREVIOUS_GDT 6(%ebp) 130#define PREVIOUS_LDT 12(%ebp) 131#define PREVIOUS_IDT 14(%ebp) 132#define RECOVER_ADDR 20(%ebp) 133#define PHYSICAL_GDT_BASE 24(%ebp) 134#define PREVIOUS_DS 28(%ebp) 135#define PREVIOUS_ES 30(%ebp) 136#define PREVIOUS_FS 32(%ebp) 137#define PREVIOUS_GS 34(%ebp) 138#define PREVIOUS_SS 36(%ebp) 139 140 /* Fixup TSS type field */ 141#define TSS_TYPEFIX_MASK 0xf9 142 xorl %esi,%esi 143 movl PHYSICAL_GDT_BASE,%ebx 144 movw TASK_REGISTER,%si 145 leal (%ebx,%esi),%eax /* get TSS segment descriptor */ 146 andb $TSS_TYPEFIX_MASK,5(%eax) 147 148 /* Prepare to return to sleep/wakeup code point */ 149 lgdt PREVIOUS_GDT 150 lidt PREVIOUS_IDT 151 152 xorl %eax,%eax 153 movl %eax,%ebx 154 movl %eax,%ecx 155 movl %eax,%edx 156 movl %eax,%esi 157 movl %eax,%edi 158 movl PREVIOUS_DS,%ebx 159 movl PREVIOUS_FS,%ecx 160 movl PREVIOUS_SS,%edx 161 movw TASK_REGISTER,%si 162 shll $16,%esi 163 movw PREVIOUS_LDT,%si 164 movl RECOVER_ADDR,%edi 165 166 /* Enable paging and etc. */ 167 movl CR0_REGISTER,%eax 168 movl %eax,%cr0 169 170 /* Flush the prefetch queue */ 171 jmp 1f 1721: jmp 1f 1731: 174 /* 175 * Now that we are in kernel virtual memory addressing 176 * %ebx: ds + es 177 * %ecx: fs + gs 178 * %edx: ss + dummy 179 * %esi: LDTR + TR 180 * %edi: recover address 181 */ 182 183 nop 184 185 movl %esi,%eax /* LDTR + TR */ 186 lldt %ax /* load LDT register */ 187 shrl $16,%eax 188 ltr %ax /* load task register */ 189 190 /* Restore segment registers */ 191 movl %ebx,%eax /* ds + es */ 192 movw %ax,%ds 193 shrl $16,%eax 194 movw %ax,%es 195 movl %ecx,%eax /* fs + gs */ 196 movw %ax,%fs 197 shrl $16,%eax 198 movw %ax,%gs 199 movl %edx,%eax /* ss */ 200 movw %ax,%ss 201 202 /* Jump to acpi_restorecpu() */ 203 jmp *%edi 204 205/* used in real mode */ 206physical_gdt: .word 0 207 .long 0 208physical_esp: .long 0 209previous_cr2: .long 0 210previous_cr3: .long 0 211previous_cr4: .long 0 212 213/* transfer from real mode to protected mode */ 214previous_cr0: .long 0 215previous_tr: .word 0 216previous_gdt: .word 0 217 .long 0 218previous_ldt: .word 0 219previous_idt: .word 0 220 .long 0 221where_to_recover: .long 0 222previous_ds: .word 0 223previous_es: .word 0 224previous_fs: .word 0 225previous_gs: .word 0 226previous_ss: .word 0 227dummy: .word 0 228