acpi_wakecode.S revision 121743
169626Sru/*- 269626Sru * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org> 369626Sru * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org> 469626Sru * All rights reserved. 569626Sru * 669626Sru * Redistribution and use in source and binary forms, with or without 769626Sru * modification, are permitted provided that the following conditions 869626Sru * are met: 969626Sru * 1. Redistributions of source code must retain the above copyright 1069626Sru * notice, this list of conditions and the following disclaimer. 1169626Sru * 2. Redistributions in binary form must reproduce the above copyright 1269626Sru * notice, this list of conditions and the following disclaimer in the 1369626Sru * documentation and/or other materials provided with the distribution. 1469626Sru * 1569626Sru * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1669626Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1769626Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1869626Sru * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1969626Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2069626Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2169626Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2269626Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2369626Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2455839Sasmodai * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2555839Sasmodai * SUCH DAMAGE. 2655839Sasmodai */ 2755839Sasmodai 2869626Sru#include <machine/asm.h> 2969626Sru__FBSDID("$FreeBSD: head/sys/i386/acpica/acpi_wakecode.S 121743 2003-10-30 16:14:55Z iwasaki $"); 3055839Sasmodai 3169626Sru#define LOCORE 3255839Sasmodai 3355839Sasmodai#include <machine/specialreg.h> 3455839Sasmodai 3555839Sasmodai .align 4 3655839Sasmodai .code16 3755839Sasmodaiwakeup_16: 3855839Sasmodai nop 3955839Sasmodai cli 4055839Sasmodai 4155839Sasmodai /* Set up segment registers for real mode */ 4255839Sasmodai movw %cs,%ax 4355839Sasmodai movw %ax,%ds 4469626Sru movw %ax,%ss 4555839Sasmodai 4655839Sasmodai#ifndef ACPI_NO_RESET_VIDEO 4755839Sasmodai /* 4855839Sasmodai * Re-initialize video BIOS. Restore DS and SS from CS in 4955839Sasmodai * case the BIOS modified them. 5069626Sru */ 5169626Sru cmp $1, no_reset_video 5269626Sru je wakeup_16_gdt 5369626Sru lcall $0xc000, $3 5469626Sru movw %cs, %ax 5569626Sru movw %ax, %ds 5669626Sru movw %ax, %ss 5755839Sasmodai#endif 5869626Sru 5969626Sruwakeup_16_gdt: 6069626Sru /* Load GDT for real mode */ 6169626Sru lgdt physical_gdt 6269626Sru 6369626Sru /* Restore CR2, CR3 and CR4 */ 6469626Sru mov previous_cr2,%eax 6569626Sru mov %eax,%cr2 6669626Sru mov previous_cr3,%eax 6769626Sru mov %eax,%cr3 6869626Sru mov previous_cr4,%eax 6969626Sru mov %eax,%cr4 7069626Sru 7169626Sru /* Transfer some values to protected mode */ 7269626Sru#define NVALUES 9 7369626Sru#define TRANSFER_STACK32(val, idx) \ 7469626Sru mov val,%eax; \ 7569626Sru mov %eax,wakeup_32stack+(idx+1)+(idx*4); 7669626Sru 7769626Sru TRANSFER_STACK32(previous_ss, (NVALUES - 9)) 7869626Sru TRANSFER_STACK32(previous_fs, (NVALUES - 8)) 7969626Sru TRANSFER_STACK32(previous_ds, (NVALUES - 7)) 8069626Sru TRANSFER_STACK32(physical_gdt+2, (NVALUES - 6)) 8169626Sru TRANSFER_STACK32(where_to_recover, (NVALUES - 5)) 8269626Sru TRANSFER_STACK32(previous_idt+2, (NVALUES - 4)) 8369626Sru TRANSFER_STACK32(previous_ldt, (NVALUES - 3)) 8469626Sru TRANSFER_STACK32(previous_gdt+2, (NVALUES - 2)) 8569626Sru TRANSFER_STACK32(previous_tr, (NVALUES - 1)) 8669626Sru TRANSFER_STACK32(previous_cr0, (NVALUES - 0)) 8769626Sru 8869626Sru mov physical_esp,%esi /* to be used in 32bit code */ 8969626Sru 9069626Sru /* Enable protected mode */ 9169626Sru mov %cr0,%eax 9269626Sru orl $(CR0_PE),%eax 9369626Sru mov %eax,%cr0 9469626Sru 9569626Sruwakeup_sw32: 9669626Sru /* Switch to protected mode by intersegmental jump */ 9769626Sru ljmpl $0x8,$0x12345678 /* Code location, to be replaced */ 9855839Sasmodai 9955839Sasmodai .code32 10055839Sasmodaiwakeup_32: 10155839Sasmodai /* 10255839Sasmodai * Switched to protected mode w/o paging 10355839Sasmodai * %esi: KERNEL stack pointer (physical address) 10455839Sasmodai */ 10555839Sasmodai 10655839Sasmodai nop 10769626Sru 10869626Sru /* Set up segment registers for protected mode */ 10969626Sru movw $0x10,%ax /* KDSEL to segment registers */ 11069626Sru movw %ax,%ds 11169626Sru movw %ax,%es 11269626Sru movw %ax,%gs 11369626Sru movw %ax,%ss 11469626Sru movw $0x18,%ax /* KPSEL to %fs */ 11569626Sru movw %ax,%fs 11669626Sru movl %esi,%esp /* physical address stack pointer */ 11769626Sru 11869626Sruwakeup_32stack: 11969626Sru /* Operands are overwritten in 16bit code */ 12069626Sru pushl $0xabcdef09 /* ss + dummy */ 12169626Sru pushl $0xabcdef08 /* fs + gs */ 12269626Sru pushl $0xabcdef07 /* ds + es */ 12369626Sru pushl $0xabcdef06 /* gdt:base (physical address) */ 12469626Sru pushl $0xabcdef05 /* recover address */ 12569626Sru pushl $0xabcdef04 /* idt:base */ 12669626Sru pushl $0xabcdef03 /* ldt + idt:limit */ 12769626Sru pushl $0xabcdef02 /* gdt:base */ 12869626Sru pushl $0xabcdef01 /* TR + gdt:limit */ 12969626Sru pushl $0xabcdef00 /* CR0 */ 13069626Sru 13169626Sru movl %esp,%ebp 13255839Sasmodai#define CR0_REGISTER 0(%ebp) 13369626Sru#define TASK_REGISTER 4(%ebp) 13469626Sru#define PREVIOUS_GDT 6(%ebp) 13569626Sru#define PREVIOUS_LDT 12(%ebp) 13669626Sru#define PREVIOUS_IDT 14(%ebp) 13769626Sru#define RECOVER_ADDR 20(%ebp) 13869626Sru#define PHYSICAL_GDT_BASE 24(%ebp) 13969626Sru#define PREVIOUS_DS 28(%ebp) 14069626Sru#define PREVIOUS_ES 30(%ebp) 14169626Sru#define PREVIOUS_FS 32(%ebp) 14269626Sru#define PREVIOUS_GS 34(%ebp) 14355839Sasmodai#define PREVIOUS_SS 36(%ebp) 14469626Sru 14569626Sru /* Fixup TSS type field */ 14669626Sru#define TSS_TYPEFIX_MASK 0xf9 14769626Sru xorl %esi,%esi 14869626Sru movl PHYSICAL_GDT_BASE,%ebx 14969626Sru movw TASK_REGISTER,%si 15069626Sru leal (%ebx,%esi),%eax /* get TSS segment descriptor */ 15169626Sru andb $TSS_TYPEFIX_MASK,5(%eax) 15269626Sru 15369626Sru /* Prepare to return to sleep/wakeup code point */ 15455839Sasmodai lgdt PREVIOUS_GDT 15555839Sasmodai lidt PREVIOUS_IDT 15669626Sru 15755839Sasmodai xorl %eax,%eax 15855839Sasmodai movl %eax,%ebx 15969626Sru movl %eax,%ecx 16069626Sru movl %eax,%edx 16155839Sasmodai movl %eax,%esi 16255839Sasmodai movl %eax,%edi 16355839Sasmodai movl PREVIOUS_DS,%ebx 16455839Sasmodai movl PREVIOUS_FS,%ecx 16555839Sasmodai movl PREVIOUS_SS,%edx 16655839Sasmodai movw TASK_REGISTER,%si 16755839Sasmodai shll $16,%esi 16855839Sasmodai movw PREVIOUS_LDT,%si 16955839Sasmodai movl RECOVER_ADDR,%edi 17069626Sru 17169626Sru /* Enable paging and etc. */ 17269626Sru movl CR0_REGISTER,%eax 17369626Sru movl %eax,%cr0 17469626Sru 17569626Sru /* Flush the prefetch queue */ 17655839Sasmodai jmp 1f 17769626Sru1: jmp 1f 17869626Sru1: 17969626Sru /* 18069626Sru * Now that we are in kernel virtual memory addressing 18169626Sru * %ebx: ds + es 18255839Sasmodai * %ecx: fs + gs 18355839Sasmodai * %edx: ss + dummy 18469626Sru * %esi: LDTR + TR 18569626Sru * %edi: recover address 18669626Sru */ 18769626Sru 18869626Sru nop 18955839Sasmodai 19055839Sasmodai movl %esi,%eax /* LDTR + TR */ 19155839Sasmodai lldt %ax /* load LDT register */ 19255839Sasmodai shrl $16,%eax 19355839Sasmodai ltr %ax /* load task register */ 19469626Sru 19555839Sasmodai /* Restore segment registers */ 19669626Sru movl %ebx,%eax /* ds + es */ 19769626Sru movw %ax,%ds 19869626Sru shrl $16,%eax 19969626Sru movw %ax,%es 20069626Sru movl %ecx,%eax /* fs + gs */ 20169626Sru movw %ax,%fs 20255839Sasmodai shrl $16,%eax 20355839Sasmodai movw %ax,%gs 20469626Sru movl %edx,%eax /* ss */ 20569626Sru movw %ax,%ss 20655839Sasmodai 20769626Sru /* Jump to acpi_restorecpu() */ 20869626Sru jmp *%edi 20969626Sru 21055839Sasmodai/* used in real mode */ 21155839Sasmodaiphysical_gdt: .word 0 21269626Sru .long 0 21369626Sruphysical_esp: .long 0 21455839Sasmodaiprevious_cr2: .long 0 21555839Sasmodaiprevious_cr3: .long 0 21669626Sruprevious_cr4: .long 0 21769626Sruno_reset_video: .long 0 21869626Sru 21969626Sru/* transfer from real mode to protected mode */ 22055839Sasmodaiprevious_cr0: .long 0 22155839Sasmodaiprevious_tr: .word 0 22269626Sruprevious_gdt: .word 0 22355839Sasmodai .long 0 22455839Sasmodaiprevious_ldt: .word 0 22569626Sruprevious_idt: .word 0 22669626Sru .long 0 22769626Sruwhere_to_recover: .long 0 22869626Sruprevious_ds: .word 0 22969626Sruprevious_es: .word 0 23069626Sruprevious_fs: .word 0 23169626Sruprevious_gs: .word 0 23269626Sruprevious_ss: .word 0 23369626Srudummy: .word 0 23469626Sru