1*ee1c6cfcSmaxv/* $NetBSD: acpi_wakecode.S,v 1.13 2016/07/24 13:04:58 maxv Exp $ */ 24c1d81b2Sjmcneill 34c1d81b2Sjmcneill/*- 44c1d81b2Sjmcneill * Copyright (c) 2007 Joerg Sonnenberger <joerg@netbsd.org> 54c1d81b2Sjmcneill * 64c1d81b2Sjmcneill * Copyright (c) 2002 The NetBSD Foundation, Inc. 74c1d81b2Sjmcneill * All rights reserved. 84c1d81b2Sjmcneill * 94c1d81b2Sjmcneill * This code is derived from software contributed to The NetBSD Foundation 104c1d81b2Sjmcneill * by Takuya SHIOZAKI. 114c1d81b2Sjmcneill * 124c1d81b2Sjmcneill * Redistribution and use in source and binary forms, with or without 134c1d81b2Sjmcneill * modification, are permitted provided that the following conditions 144c1d81b2Sjmcneill * are met: 154c1d81b2Sjmcneill * 1. Redistributions of source code must retain the above copyright 164c1d81b2Sjmcneill * notice, this list of conditions and the following disclaimer. 174c1d81b2Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright 184c1d81b2Sjmcneill * notice, this list of conditions and the following disclaimer in the 194c1d81b2Sjmcneill * documentation and/or other materials provided with the distribution. 204c1d81b2Sjmcneill * 214c1d81b2Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 224c1d81b2Sjmcneill * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 234c1d81b2Sjmcneill * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 244c1d81b2Sjmcneill * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 254c1d81b2Sjmcneill * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 264c1d81b2Sjmcneill * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 274c1d81b2Sjmcneill * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 284c1d81b2Sjmcneill * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 294c1d81b2Sjmcneill * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 304c1d81b2Sjmcneill * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 314c1d81b2Sjmcneill * POSSIBILITY OF SUCH DAMAGE. 324c1d81b2Sjmcneill */ 334c1d81b2Sjmcneill 344c1d81b2Sjmcneill/* 354c1d81b2Sjmcneill * This code is derived from FreeBSD. Original copyrights: 364c1d81b2Sjmcneill * 374c1d81b2Sjmcneill * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org> 384c1d81b2Sjmcneill * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org> 394c1d81b2Sjmcneill * All rights reserved. 404c1d81b2Sjmcneill * 414c1d81b2Sjmcneill * Redistribution and use in source and binary forms, with or without 424c1d81b2Sjmcneill * modification, are permitted provided that the following conditions 434c1d81b2Sjmcneill * are met: 444c1d81b2Sjmcneill * 1. Redistributions of source code must retain the above copyright 454c1d81b2Sjmcneill * notice, this list of conditions and the following disclaimer. 464c1d81b2Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright 474c1d81b2Sjmcneill * notice, this list of conditions and the following disclaimer in the 484c1d81b2Sjmcneill * documentation and/or other materials provided with the distribution. 494c1d81b2Sjmcneill * 504c1d81b2Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 514c1d81b2Sjmcneill * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 524c1d81b2Sjmcneill * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 534c1d81b2Sjmcneill * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 544c1d81b2Sjmcneill * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 554c1d81b2Sjmcneill * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 564c1d81b2Sjmcneill * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 574c1d81b2Sjmcneill * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 584c1d81b2Sjmcneill * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 594c1d81b2Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 604c1d81b2Sjmcneill * SUCH DAMAGE. 614c1d81b2Sjmcneill * 624c1d81b2Sjmcneill * FreeBSD: src/sys/i386/acpica/acpi_wakecode.S,v 1.1 2001/07/20 06:07:31 takawata Exp 634c1d81b2Sjmcneill */ 644c1d81b2Sjmcneill 654c1d81b2Sjmcneill#define _LOCORE 664c1d81b2Sjmcneill 674c1d81b2Sjmcneill#include <machine/psl.h> 684c1d81b2Sjmcneill#include <machine/segments.h> 69870cffb0Sjoerg#include <machine/specialreg.h> 704c1d81b2Sjmcneill 714c1d81b2Sjmcneill#define ACPI_WAKEUP_ADDR 0x3000 724c1d81b2Sjmcneill 734c1d81b2Sjmcneill .text 744c1d81b2Sjmcneill .code16 754c1d81b2Sjmcneill .org 0 /* ACPI spec says: cs==(phys>>8), ip==(phys&0x000F) */ 764c1d81b2Sjmcneill .globl wakeup_16 774c1d81b2Sjmcneillwakeup_16: 784c1d81b2Sjmcneill nop 794c1d81b2Sjmcneill cli 804c1d81b2Sjmcneill cld 814c1d81b2Sjmcneill 824c1d81b2Sjmcneill /* Set up segment registers for real mode */ 834c1d81b2Sjmcneill movw %cs,%ax 844c1d81b2Sjmcneill movw %ax,%ds 854c1d81b2Sjmcneill movw %ax,%ss 864c1d81b2Sjmcneill 874c1d81b2Sjmcneill /* Small call stack */ 884c1d81b2Sjmcneill mov $0x1000,%sp 894c1d81b2Sjmcneill 904c1d81b2Sjmcneill /* Clear flags */ 914c1d81b2Sjmcneill pushl $0 924c1d81b2Sjmcneill popfl 934c1d81b2Sjmcneill 944c1d81b2Sjmcneill /* Only beep on reset if machdep.acpi_beep_on_reset=1 */ 954c1d81b2Sjmcneill cmpb $1,WAKEUP_beep_on_reset 964c1d81b2Sjmcneill jne 1f 974c1d81b2Sjmcneill movb $0xc0,%al 984c1d81b2Sjmcneill outb %al,$0x42 994c1d81b2Sjmcneill movb $0x04,%al 1004c1d81b2Sjmcneill outb %al,$0x42 1014c1d81b2Sjmcneill inb $0x61,%al 1024c1d81b2Sjmcneill orb $0x3,%al 1034c1d81b2Sjmcneill outb %al,$0x61 1044c1d81b2Sjmcneill1: 1054c1d81b2Sjmcneill 1064c1d81b2Sjmcneill /* Only reset the VBIOS if machdep.acpi_vbios_reset=1 */ 1074c1d81b2Sjmcneill cmpb $1,WAKEUP_vbios_reset 1084c1d81b2Sjmcneill jne 1f 1094c1d81b2Sjmcneill 1104c1d81b2Sjmcneill /* Kick the VBIOS. */ 1114c1d81b2Sjmcneill lcall $0xc000,$3 1124c1d81b2Sjmcneill 1134c1d81b2Sjmcneill /* Reset registers in case the VBIOS changed them. */ 1144c1d81b2Sjmcneill movw %cs,%ax 1154c1d81b2Sjmcneill movw %ax,%ds 1164c1d81b2Sjmcneill movw %ax,%ss 1174c1d81b2Sjmcneill 118b585cf85Sjmcneill /* If we need to restore a VESA VBE mode, do it now */ 119b585cf85Sjmcneill cmpb $0,WAKEUP_vesa_modenum 120b585cf85Sjmcneill je 1f 121b585cf85Sjmcneill movw WAKEUP_vesa_modenum,%bx 122b585cf85Sjmcneill orw $0x4000,%bx 123b585cf85Sjmcneill movw $0x4f02,%ax 124b585cf85Sjmcneill int $0x10 125b585cf85Sjmcneill 126b585cf85Sjmcneill movw %cs,%ax 127b585cf85Sjmcneill movw %ax,%ds 128b585cf85Sjmcneill movw %ax,%ss 129b585cf85Sjmcneill1: 130b585cf85Sjmcneill 131e1f40929Sjmcneill /* Disable beep again if machdep.acpi_beep_on_reset=1 */ 132e1f40929Sjmcneill cmpb $1,WAKEUP_beep_on_reset 133e1f40929Sjmcneill jne 1f 134e1f40929Sjmcneill inb $0x61,%al 135e1f40929Sjmcneill andb $0xfc,%al 136e1f40929Sjmcneill outb %al,$0x61 137e1f40929Sjmcneill1: 138e1f40929Sjmcneill 1394c1d81b2Sjmcneill /* Load temporary 32bit GDT */ 1407ef87bccSjoerg#ifdef __clang__ 1417ef87bccSjoerg lgdt tmp_gdt 1427ef87bccSjoerg#else 1434c1d81b2Sjmcneill data32 addr32 lgdt tmp_gdt 1447ef87bccSjoerg#endif 1454c1d81b2Sjmcneill 146*ee1c6cfcSmaxv /* Enable protected mode without paging */ 1474c1d81b2Sjmcneill mov %cr0,%eax 1484c1d81b2Sjmcneill orl $(CR0_PE),%eax 1494c1d81b2Sjmcneill mov %eax,%cr0 1504c1d81b2Sjmcneill 1514c1d81b2Sjmcneillwakeup_sw32: 1524c1d81b2Sjmcneill /* 1534c1d81b2Sjmcneill * Switch to protected mode by intersegmental jump. 1544c1d81b2Sjmcneill * Target and everything else has to compensate for the new origin 1554c1d81b2Sjmcneill * as this is using the flat memory model now. 1564c1d81b2Sjmcneill */ 1574c1d81b2Sjmcneill 1584c1d81b2Sjmcneill ljmpl $0x8,$wakeup_32 + ACPI_WAKEUP_ADDR 1594c1d81b2Sjmcneill 1604c1d81b2Sjmcneill .code32 1614c1d81b2Sjmcneill .align 16 1624c1d81b2Sjmcneillwakeup_32: 1634c1d81b2Sjmcneill /* 1644c1d81b2Sjmcneill * Switched to protected mode w/o paging 1654c1d81b2Sjmcneill */ 1664c1d81b2Sjmcneill nop 167*ee1c6cfcSmaxv 1684c1d81b2Sjmcneill /* Set up segment registers and initial stack for protected mode */ 1694c1d81b2Sjmcneill movw $0x10,%ax 1704c1d81b2Sjmcneill movw %ax,%ds 1714c1d81b2Sjmcneill movw %ax,%ss 1724c1d81b2Sjmcneill 1734c1d81b2Sjmcneill movl $(ACPI_WAKEUP_ADDR + 4096),%esp 1744c1d81b2Sjmcneill 1754c1d81b2Sjmcneill /* First, reset the PSL. */ 1764c1d81b2Sjmcneill pushl $PSL_MBO 1774c1d81b2Sjmcneill popfl 1784c1d81b2Sjmcneill 1794c1d81b2Sjmcneill /* Enable PAE and potentially PSE */ 1804c1d81b2Sjmcneill movl $(CR4_PAE|CR4_OSFXSR|CR4_OSXMMEXCPT|CR4_PSE),%eax 1814c1d81b2Sjmcneill movl %eax,%cr4 1824c1d81b2Sjmcneill 183ae85e6b9Sjoerg /* 184ae85e6b9Sjoerg * First switch to Long Mode. Do not restore the original 185ae85e6b9Sjoerg * MSR EFER value directly, as enabling the NX bit without 186ae85e6b9Sjoerg * paging will result in a GPF on AMD CPUs. 187ae85e6b9Sjoerg * 188ae85e6b9Sjoerg * Load the correct MSR EFER value now to not depend on the 189ae85e6b9Sjoerg * data segment register directly after switching to Long Mode. 190ae85e6b9Sjoerg * After this point, no instruction is allowed to clobber %ebx. 191ae85e6b9Sjoerg */ 192ae85e6b9Sjoerg movl WAKEUP_efer + ACPI_WAKEUP_ADDR,%ebx 1934c1d81b2Sjmcneill movl $MSR_EFER,%ecx 194ae85e6b9Sjoerg rdmsr 195ae85e6b9Sjoerg orl $EFER_LME,%eax 1964c1d81b2Sjmcneill wrmsr 1974c1d81b2Sjmcneill 1984c1d81b2Sjmcneill /* Load temporary PML4, code will switch to full PML4 later */ 1994c1d81b2Sjmcneill movl WAKEUP_r_cr3 + ACPI_WAKEUP_ADDR,%eax 2004c1d81b2Sjmcneill movl %eax,%cr3 2014c1d81b2Sjmcneill 2024c1d81b2Sjmcneill /* Enable paging */ 2034c1d81b2Sjmcneill movl %cr0,%eax 204b053fe26Sjym orl $(CR0_PE|CR0_PG|CR0_NE|CR0_TS|CR0_MP|CR0_WP|CR0_AM),%eax 2054c1d81b2Sjmcneill movl %eax,%cr0 206*ee1c6cfcSmaxv 207*ee1c6cfcSmaxv /* Flush the prefetch queue */ 2084c1d81b2Sjmcneill jmp 1f 2094c1d81b2Sjmcneill1: 210*ee1c6cfcSmaxv 2114c1d81b2Sjmcneill /* Switch to temporary 64bit GDT */ 2124c1d81b2Sjmcneill lgdt tmp_gdt64 + ACPI_WAKEUP_ADDR 2134c1d81b2Sjmcneill 2144c1d81b2Sjmcneill /* Switch to long mode using intersegmental jump. */ 2154c1d81b2Sjmcneill ljmp $0x8, $wakeup_64 + ACPI_WAKEUP_ADDR 2164c1d81b2Sjmcneill 2174c1d81b2Sjmcneill .code64 2184c1d81b2Sjmcneillwakeup_64: 2194c1d81b2Sjmcneill 220ae85e6b9Sjoerg /* 221ae85e6b9Sjoerg * Load the normal system value of MSR EFER. This includes 222ae85e6b9Sjoerg * enabling the SYSCALL extension and NXE (if supported). 223ae85e6b9Sjoerg */ 224ae85e6b9Sjoerg movl %ebx,%eax 225ae85e6b9Sjoerg movl $MSR_EFER,%ecx 226ae85e6b9Sjoerg wrmsr 227ae85e6b9Sjoerg 228870cffb0Sjoerg /* Reload data segment with default value */ 2294c1d81b2Sjmcneill movw $GSEL(GDATA_SEL, SEL_KPL),%ax 2304c1d81b2Sjmcneill movw %ax,%ds 2314c1d81b2Sjmcneill 232*ee1c6cfcSmaxv /* Restore registers */ 233870cffb0Sjoerg movq WAKEUP_curcpu + ACPI_WAKEUP_ADDR,%r8 2344c1d81b2Sjmcneill movq WAKEUP_restorecpu + ACPI_WAKEUP_ADDR,%rbx 2354c1d81b2Sjmcneill 2364c1d81b2Sjmcneill /* Continue with wakeup in the high-level wakeup code */ 2374c1d81b2Sjmcneill jmp *%rbx 2384c1d81b2Sjmcneill 2394c1d81b2Sjmcneill .align 8 2404c1d81b2Sjmcneilltmp_gdt: 2414c1d81b2Sjmcneill .word 0xffff 2424c1d81b2Sjmcneill .long tmp_gdtable + ACPI_WAKEUP_ADDR 2434c1d81b2Sjmcneill 2444c1d81b2Sjmcneill .align 8, 0 2454c1d81b2Sjmcneilltmp_gdtable: 2464c1d81b2Sjmcneill /* null */ 2474c1d81b2Sjmcneill .word 0, 0 2484c1d81b2Sjmcneill .byte 0, 0, 0, 0 2494c1d81b2Sjmcneill /* code */ 2504c1d81b2Sjmcneill .word 0xffff, 0 2514c1d81b2Sjmcneill .byte 0, 0x9f, 0xcf, 0 2524c1d81b2Sjmcneill /* data */ 2534c1d81b2Sjmcneill .word 0xffff, 0 2544c1d81b2Sjmcneill .byte 0, 0x93, 0xcf, 0 2554c1d81b2Sjmcneill 2564c1d81b2Sjmcneilltmp_gdt64: 2574c1d81b2Sjmcneill .word 0xffff 2584c1d81b2Sjmcneill .long tmp_gdtable64 + ACPI_WAKEUP_ADDR 2594c1d81b2Sjmcneill 2604c1d81b2Sjmcneilltmp_gdtable64: 2614c1d81b2Sjmcneill .quad 0x0000000000000000 2624c1d81b2Sjmcneill .quad 0x00af9a000000ffff 2634c1d81b2Sjmcneill .quad 0x00cf92000000ffff 2644c1d81b2Sjmcneill 2654c1d81b2Sjmcneill .align 16, 0 2664c1d81b2Sjmcneill .global WAKEUP_r_cr3 2674c1d81b2SjmcneillWAKEUP_r_cr3: .quad 0 2684c1d81b2Sjmcneill 2694c1d81b2Sjmcneill .global WAKEUP_restorecpu 2704c1d81b2SjmcneillWAKEUP_restorecpu: .quad 0 2714c1d81b2Sjmcneill 2724c1d81b2Sjmcneill .global WAKEUP_vbios_reset 2734c1d81b2SjmcneillWAKEUP_vbios_reset: .byte 0 274dd324f84Sjmcneill .global WAKEUP_vesa_modenum 275dd324f84SjmcneillWAKEUP_vesa_modenum: .word 0 2764c1d81b2Sjmcneill .global WAKEUP_beep_on_reset 2774c1d81b2SjmcneillWAKEUP_beep_on_reset: .byte 0 278870cffb0Sjoerg 279870cffb0Sjoerg .global WAKEUP_curcpu 280870cffb0SjoergWAKEUP_curcpu: .quad 0 281f674d967Sad .global WAKEUP_efer 282f674d967SadWAKEUP_efer: .long 0 283