]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/amd64/acpica/acpi_switch.S
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / amd64 / acpica / acpi_switch.S
1 /*-
2  * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
3  * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
4  * Copyright (c) 2008-2012 Jung-uk Kim <jkim@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30
31 #include <machine/asmacros.h>
32 #include <machine/specialreg.h>
33
34 #include "acpi_wakedata.h"
35 #include "assym.s"
36
37 #define WAKEUP_CTX(member)      wakeup_ ## member - wakeup_ctx(%rsi)
38
39 ENTRY(acpi_restorecpu)
40         /* Switch to KPML4phys. */
41         movq    %rdi, %cr3
42
43         /* Restore GDT. */
44         lgdt    WAKEUP_CTX(gdt)
45         jmp     1f
46 1:
47
48         /* Fetch PCB. */
49         movq    WAKEUP_CTX(pcb), %rdi
50
51         /* Force kernel segment registers. */
52         movl    $KDSEL, %eax
53         movw    %ax, %ds
54         movw    %ax, %es
55         movw    %ax, %ss
56         movl    $KUF32SEL, %eax
57         movw    %ax, %fs
58         movl    $KUG32SEL, %eax
59         movw    %ax, %gs
60
61         movl    $MSR_FSBASE, %ecx
62         movl    PCB_FSBASE(%rdi), %eax
63         movl    4 + PCB_FSBASE(%rdi), %edx
64         wrmsr
65         movl    $MSR_GSBASE, %ecx
66         movl    PCB_GSBASE(%rdi), %eax
67         movl    4 + PCB_GSBASE(%rdi), %edx
68         wrmsr
69         movl    $MSR_KGSBASE, %ecx
70         movl    PCB_KGSBASE(%rdi), %eax
71         movl    4 + PCB_KGSBASE(%rdi), %edx
72         wrmsr
73
74         /* Restore EFER. */
75         movl    $MSR_EFER, %ecx
76         movl    WAKEUP_CTX(efer), %eax
77         wrmsr
78
79         /* Restore fast syscall stuff. */
80         movl    $MSR_STAR, %ecx
81         movl    WAKEUP_CTX(star), %eax
82         movl    4 + WAKEUP_CTX(star), %edx
83         wrmsr
84         movl    $MSR_LSTAR, %ecx
85         movl    WAKEUP_CTX(lstar), %eax
86         movl    4 + WAKEUP_CTX(lstar), %edx
87         wrmsr
88         movl    $MSR_CSTAR, %ecx
89         movl    WAKEUP_CTX(cstar), %eax
90         movl    4 + WAKEUP_CTX(cstar), %edx
91         wrmsr
92         movl    $MSR_SF_MASK, %ecx
93         movl    WAKEUP_CTX(sfmask), %eax
94         wrmsr
95
96         /* Restore CR0 except for FPU mode. */
97         movq    PCB_CR0(%rdi), %rax
98         andq    $~(CR0_EM | CR0_TS), %rax
99         movq    %rax, %cr0
100
101         /* Restore CR2 and CR4. */
102         movq    PCB_CR2(%rdi), %rax
103         movq    %rax, %cr2
104         movq    PCB_CR4(%rdi), %rax
105         movq    %rax, %cr4
106
107         /* Restore descriptor tables. */
108         lidt    PCB_IDT(%rdi)
109         lldt    PCB_LDT(%rdi)
110
111 #define SDT_SYSTSS      9
112 #define SDT_SYSBSY      11
113
114         /* Clear "task busy" bit and reload TR. */
115         movq    PCPU(TSS), %rax
116         andb    $(~SDT_SYSBSY | SDT_SYSTSS), 5(%rax)
117         movw    PCB_TR(%rdi), %ax
118         ltr     %ax
119
120 #undef  SDT_SYSTSS
121 #undef  SDT_SYSBSY
122
123         /* Restore debug registers. */
124         movq    PCB_DR0(%rdi), %rax
125         movq    %rax, %dr0
126         movq    PCB_DR1(%rdi), %rax
127         movq    %rax, %dr1
128         movq    PCB_DR2(%rdi), %rax
129         movq    %rax, %dr2
130         movq    PCB_DR3(%rdi), %rax
131         movq    %rax, %dr3
132         movq    PCB_DR6(%rdi), %rax
133         movq    %rax, %dr6
134         movq    PCB_DR7(%rdi), %rax
135         movq    %rax, %dr7
136
137         /* Restore FPU state. */
138         fninit
139         movq    WAKEUP_CTX(fpusave), %rbx
140         movq    WAKEUP_CTX(xsmask), %rax
141         testq   %rax, %rax
142         jz      1f
143         movq    %rax, %rdx
144         shrq    $32, %rdx
145         movl    $XCR0, %ecx
146         xsetbv
147         xrstor  (%rbx)
148         jmp     2f
149 1:
150         fxrstor (%rbx)
151 2:
152
153         /* Reload CR0. */
154         movq    PCB_CR0(%rdi), %rax
155         movq    %rax, %cr0
156
157         /* Restore other callee saved registers. */
158         movq    PCB_R15(%rdi), %r15
159         movq    PCB_R14(%rdi), %r14
160         movq    PCB_R13(%rdi), %r13
161         movq    PCB_R12(%rdi), %r12
162         movq    PCB_RBP(%rdi), %rbp
163         movq    PCB_RSP(%rdi), %rsp
164         movq    PCB_RBX(%rdi), %rbx
165
166         /* Restore return address. */
167         movq    PCB_RIP(%rdi), %rax
168         movq    %rax, (%rsp)
169
170         /* Indicate the CPU is resumed. */
171         xorl    %eax, %eax
172         movl    %eax, WAKEUP_CTX(cpu)
173
174         ret
175 END(acpi_restorecpu)