178 lines
4.3 KiB
ArmAsm
178 lines
4.3 KiB
ArmAsm
/*-
|
|
* Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
|
|
* Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
|
|
* Copyright (c) 2008-2012 Jung-uk Kim <jkim@FreeBSD.org>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
#include <machine/asmacros.h>
|
|
#include <machine/specialreg.h>
|
|
|
|
#include "acpi_wakedata.h"
|
|
#include "assym.s"
|
|
|
|
#define WAKEUP_CTX(member) wakeup_ ## member - wakeup_ctx(%rsi)
|
|
|
|
ENTRY(acpi_restorecpu)
|
|
/* Switch to KPML4phys. */
|
|
movq %rdi, %cr3
|
|
|
|
/* Restore GDT. */
|
|
lgdt WAKEUP_CTX(gdt)
|
|
jmp 1f
|
|
1:
|
|
|
|
/* Fetch PCB. */
|
|
movq WAKEUP_CTX(pcb), %rdi
|
|
|
|
/* Force kernel segment registers. */
|
|
movl $KDSEL, %eax
|
|
movw %ax, %ds
|
|
movw %ax, %es
|
|
movw %ax, %ss
|
|
movl $KUF32SEL, %eax
|
|
movw %ax, %fs
|
|
movl $KUG32SEL, %eax
|
|
movw %ax, %gs
|
|
|
|
movl $MSR_FSBASE, %ecx
|
|
movl PCB_FSBASE(%rdi), %eax
|
|
movl 4 + PCB_FSBASE(%rdi), %edx
|
|
wrmsr
|
|
movl $MSR_GSBASE, %ecx
|
|
movl PCB_GSBASE(%rdi), %eax
|
|
movl 4 + PCB_GSBASE(%rdi), %edx
|
|
wrmsr
|
|
movl $MSR_KGSBASE, %ecx
|
|
movl PCB_KGSBASE(%rdi), %eax
|
|
movl 4 + PCB_KGSBASE(%rdi), %edx
|
|
wrmsr
|
|
|
|
/* Restore EFER. */
|
|
movl $MSR_EFER, %ecx
|
|
movl WAKEUP_CTX(efer), %eax
|
|
wrmsr
|
|
|
|
/* Restore fast syscall stuff. */
|
|
movl $MSR_STAR, %ecx
|
|
movl WAKEUP_CTX(star), %eax
|
|
movl 4 + WAKEUP_CTX(star), %edx
|
|
wrmsr
|
|
movl $MSR_LSTAR, %ecx
|
|
movl WAKEUP_CTX(lstar), %eax
|
|
movl 4 + WAKEUP_CTX(lstar), %edx
|
|
wrmsr
|
|
movl $MSR_CSTAR, %ecx
|
|
movl WAKEUP_CTX(cstar), %eax
|
|
movl 4 + WAKEUP_CTX(cstar), %edx
|
|
wrmsr
|
|
movl $MSR_SF_MASK, %ecx
|
|
movl WAKEUP_CTX(sfmask), %eax
|
|
wrmsr
|
|
|
|
/* Restore CR0 except for FPU mode. */
|
|
movq PCB_CR0(%rdi), %rax
|
|
andq $~(CR0_EM | CR0_TS), %rax
|
|
movq %rax, %cr0
|
|
|
|
/* Restore CR2 and CR4. */
|
|
movq PCB_CR2(%rdi), %rax
|
|
movq %rax, %cr2
|
|
movq PCB_CR4(%rdi), %rax
|
|
movq %rax, %cr4
|
|
|
|
/* Restore descriptor tables. */
|
|
lidt PCB_IDT(%rdi)
|
|
lldt PCB_LDT(%rdi)
|
|
|
|
#define SDT_SYSTSS 9
|
|
#define SDT_SYSBSY 11
|
|
|
|
/* Clear "task busy" bit and reload TR. */
|
|
movq PCPU(TSS), %rax
|
|
andb $(~SDT_SYSBSY | SDT_SYSTSS), 5(%rax)
|
|
movw PCB_TR(%rdi), %ax
|
|
ltr %ax
|
|
|
|
#undef SDT_SYSTSS
|
|
#undef SDT_SYSBSY
|
|
|
|
/* Restore debug registers. */
|
|
movq PCB_DR0(%rdi), %rax
|
|
movq %rax, %dr0
|
|
movq PCB_DR1(%rdi), %rax
|
|
movq %rax, %dr1
|
|
movq PCB_DR2(%rdi), %rax
|
|
movq %rax, %dr2
|
|
movq PCB_DR3(%rdi), %rax
|
|
movq %rax, %dr3
|
|
movq PCB_DR6(%rdi), %rax
|
|
movq %rax, %dr6
|
|
movq PCB_DR7(%rdi), %rax
|
|
movq %rax, %dr7
|
|
|
|
/* Restore FPU state. */
|
|
fninit
|
|
movq WAKEUP_CTX(fpusave), %rbx
|
|
movq WAKEUP_CTX(xsmask), %rax
|
|
testq %rax, %rax
|
|
jz 1f
|
|
movq %rax, %rdx
|
|
shrq $32, %rdx
|
|
movl $XCR0, %ecx
|
|
/* xsetbv */
|
|
.byte 0x0f, 0x01, 0xd1
|
|
/* xrstor (%rbx) */
|
|
.byte 0x0f, 0xae, 0x2b
|
|
jmp 2f
|
|
1:
|
|
fxrstor (%rbx)
|
|
2:
|
|
|
|
/* Reload CR0. */
|
|
movq PCB_CR0(%rdi), %rax
|
|
movq %rax, %cr0
|
|
|
|
/* Restore other callee saved registers. */
|
|
movq PCB_R15(%rdi), %r15
|
|
movq PCB_R14(%rdi), %r14
|
|
movq PCB_R13(%rdi), %r13
|
|
movq PCB_R12(%rdi), %r12
|
|
movq PCB_RBP(%rdi), %rbp
|
|
movq PCB_RSP(%rdi), %rsp
|
|
movq PCB_RBX(%rdi), %rbx
|
|
|
|
/* Restore return address. */
|
|
movq PCB_RIP(%rdi), %rax
|
|
movq %rax, (%rsp)
|
|
|
|
/* Indicate the CPU is resumed. */
|
|
xorl %eax, %eax
|
|
movl %eax, WAKEUP_CTX(cpu)
|
|
|
|
ret
|
|
END(acpi_restorecpu)
|