]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - sys/amd64/acpica/acpi_switch.S
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.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-2010 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         movq    %rax, %rcx
99         andq    $~(CR0_EM | CR0_TS), %rax
100         movq    %rax, %cr0
101
102         /* Restore CR2 and CR4. */
103         movq    PCB_CR2(%rdi), %rax
104         movq    %rax, %cr2
105         movq    PCB_CR4(%rdi), %rax
106         movq    %rax, %cr4
107
108         /* Restore descriptor tables. */
109         lidt    PCB_IDT(%rdi)
110         lldt    PCB_LDT(%rdi)
111
112 #define SDT_SYSTSS      9
113 #define SDT_SYSBSY      11
114
115         /* Clear "task busy" bit and reload TR. */
116         movq    PCPU(TSS), %rax
117         andb    $(~SDT_SYSBSY | SDT_SYSTSS), 5(%rax)
118         movw    PCB_TR(%rdi), %ax
119         ltr     %ax
120
121 #undef  SDT_SYSTSS
122 #undef  SDT_SYSBSY
123
124         /* Restore other callee saved registers. */
125         movq    PCB_R15(%rdi), %r15
126         movq    PCB_R14(%rdi), %r14
127         movq    PCB_R13(%rdi), %r13
128         movq    PCB_R12(%rdi), %r12
129         movq    PCB_RBP(%rdi), %rbp
130         movq    PCB_RSP(%rdi), %rsp
131         movq    PCB_RBX(%rdi), %rbx
132
133         /* Restore debug registers. */
134         movq    PCB_DR0(%rdi), %rax
135         movq    %rax, %dr0
136         movq    PCB_DR1(%rdi), %rax
137         movq    %rax, %dr1
138         movq    PCB_DR2(%rdi), %rax
139         movq    %rax, %dr2
140         movq    PCB_DR3(%rdi), %rax
141         movq    %rax, %dr3
142         movq    PCB_DR6(%rdi), %rax
143         movq    %rax, %dr6
144         movq    PCB_DR7(%rdi), %rax
145         movq    %rax, %dr7
146
147         /* Restore FPU state. */
148         fninit
149         fxrstor PCB_USERFPU(%rdi)
150
151         /* Reload CR0. */
152         movq    %rcx, %cr0
153
154         /* Restore return address. */
155         movq    PCB_RIP(%rdi), %rax
156         movq    %rax, (%rsp)
157
158         /* Indicate the CPU is resumed. */
159         xorl    %eax, %eax
160         movl    %eax, WAKEUP_CTX(cpu)
161
162         ret
163 END(acpi_restorecpu)