1/*
2 * Copyright (C) 2018-2022 Intel Corporation.
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6/* NOTE:
7 *
8 * MISRA C requires that all unsigned constants should have the suffix 'U'
9 * (e.g. 0xffU), but the assembler may not accept such C-style constants. For
10 * example, binutils 2.26 fails to compile assembly in that case. To work this
11 * around, all unsigned constants must be explicitly spells out in assembly
12 * with a comment tracking the original expression from which the magic
13 * number is calculated. As an example:
14 *
15 *    /* 0x00000668 =
16 *     *    (CR4_DE | CR4_PAE | CR4_MCE | CR4_OSFXSR | CR4_OSXMMEXCPT) *\/
17 *    movl    $0x00000668, %eax
18 *
19 * Make sure that these numbers are updated accordingly if the definition of
20 * the macros involved are changed.
21 */
22   .text
23   .align   8
24   .code64
25   .extern    restore_msrs
26   .extern    cpu_ctx
27   .extern    load_gdtr_and_tr
28   .extern    do_acpi_sx
29
30   .global    asm_enter_s3
31asm_enter_s3:
32	/*
33	 * 0U=0x0=CPU_CONTEXT_OFFSET_RAX
34	 * 8U=0x8=CPU_CONTEXT_OFFSET_RCX
35	 * 16U=0x10=CPU_CONTEXT_OFFSET_RDX
36	 * 24U=0x18=CPU_CONTEXT_OFFSET_RBX
37	 * 32U=0x20=CPU_CONTEXT_OFFSET_RSP
38	 * 40U=0x28=CPU_CONTEXT_OFFSET_RBP
39	 * 48U=0x30=CPU_CONTEXT_OFFSET_RSI
40	 * 56U=0x38=CPU_CONTEXT_OFFSET_RDI
41	 * 64U=0x40=CPU_CONTEXT_OFFSET_R8
42	 * 72U=0x48=CPU_CONTEXT_OFFSET_R9
43	 * 80U=0x50=CPU_CONTEXT_OFFSET_R10
44	 * 88U=0x58=CPU_CONTEXT_OFFSET_R11
45	 * 96U=0x60=CPU_CONTEXT_OFFSET_R12
46	 * 104U=0x68=CPU_CONTEXT_OFFSET_R13
47	 * 112U=0x70=CPU_CONTEXT_OFFSET_R14
48	 * 120U=0x78=CPU_CONTEXT_OFFSET_R15
49	 */
50	movq %rax, 0x0 + cpu_ctx(%rip)
51	movq %rcx, 0x8 + cpu_ctx(%rip)
52	movq %rdx, 0x10 + cpu_ctx(%rip)
53	movq %rbx, 0x18 + cpu_ctx(%rip)
54	movq %rsp, 0x20 + cpu_ctx(%rip)
55	movq %rbp, 0x28 + cpu_ctx(%rip)
56	movq %rsi, 0x30 + cpu_ctx(%rip)
57	movq %rdi, 0x38 + cpu_ctx(%rip)
58	movq %r8,  0x40 + cpu_ctx(%rip)
59	movq %r9,  0x48 + cpu_ctx(%rip)
60	movq %r10, 0x50 + cpu_ctx(%rip)
61	movq %r11, 0x58 + cpu_ctx(%rip)
62	movq %r12, 0x60 + cpu_ctx(%rip)
63	movq %r13, 0x68 + cpu_ctx(%rip)
64	movq %r14, 0x70 + cpu_ctx(%rip)
65	movq %r15, 0x78 + cpu_ctx(%rip)
66
67	pushfq
68	/*160U=0xa0=CPU_CONTEXT_OFFSET_RFLAGS*/
69	popq 0xa0 + cpu_ctx(%rip)
70
71	/*192U=0xc0=CPU_CONTEXT_OFFSET_IDTR*/
72	sidt 0xc0 + cpu_ctx(%rip)
73	/*216U=0xd8=CPU_CONTEXT_OFFSET_LDTR*/
74	sldt 0xd8 + cpu_ctx(%rip)
75
76	mov %cr0, %rax
77	/*128U=0x80=CPU_CONTEXT_OFFSET_CR0*/
78	mov %rax, 0x80 + cpu_ctx(%rip)
79
80	mov %cr3, %rax
81	/*184U=0xb8=CPU_CONTEXT_OFFSET_CR3*/
82	mov %rax, 0xb8 + cpu_ctx(%rip)
83
84	mov %cr4, %rax
85	/*144U=0x90=CPU_CONTEXT_OFFSET_CR4*/
86	mov %rax, 0x90 + cpu_ctx(%rip)
87
88	wbinvd
89
90	/*16U=0x10=CPU_CONTEXT_OFFSET_RDX*/
91	movq 0x10 + cpu_ctx(%rip), %rdx  /* pm1b_cnt_val */
92	/*56U=0x38=CPU_CONTEXT_OFFSET_RDI*/
93	movq 0x38 + cpu_ctx(%rip), %rdi  /* pm sstate_data */
94	/*48U=0x30=CPU_CONTEXT_OFFSET_RSI*/
95	movq 0x30 + cpu_ctx(%rip), %rsi  /* pm1a_cnt_val */
96
97	call do_acpi_sx
98
99/*
100 * When system resume from S3, trampoline_start64 will
101 * jump to restore_s3_context after setup temporary stack.
102 */
103.global restore_s3_context
104restore_s3_context:
105	/*144U=0x90=CPU_CONTEXT_OFFSET_CR4*/
106	mov 0x90 + cpu_ctx(%rip), %rax
107	mov %rax, %cr4
108
109	/*184U=0xb8=CPU_CONTEXT_OFFSET_CR3*/
110	mov 0xb8 + cpu_ctx(%rip), %rax
111	mov %rax, %cr3
112
113	/*128U=0x80=CPU_CONTEXT_OFFSET_CR0*/
114	mov 0x80 + cpu_ctx(%rip), %rax
115	mov %rax, %cr0
116
117	/*192U=0xc0=CPU_CONTEXT_OFFSET_IDTR*/
118	lidt 0xc0 + cpu_ctx(%rip)
119	/*216U=0xd8=CPU_CONTEXT_OFFSET_LDTR*/
120	lldt 0xd8 + cpu_ctx(%rip)
121
122	/*32=0x20=CPU_CONTEXT_OFFSET_RSP*/
123	movq 0x20 + cpu_ctx(%rip), %rsp
124
125	/*160U=0xa0=CPU_CONTEXT_OFFSET_RFLAGS*/
126	pushq 0xa0 + cpu_ctx(%rip)
127	popfq
128
129	stac
130	call load_gdtr_and_tr
131	clac
132	call restore_msrs
133
134	/*
135	 * 0U=0x0=CPU_CONTEXT_OFFSET_RAX
136	 * 8U=0x8=CPU_CONTEXT_OFFSET_RCX
137	 * 16U=0x10=CPU_CONTEXT_OFFSET_RDX
138	 * 24U=0x18=CPU_CONTEXT_OFFSET_RBX
139	 * 40U=0x28=CPU_CONTEXT_OFFSET_RBP
140	 * 48U=0x30=CPU_CONTEXT_OFFSET_RSI
141	 * 56U=0x38=CPU_CONTEXT_OFFSET_RDI
142	 * 64U=0x40=CPU_CONTEXT_OFFSET_R8
143	 * 72U=0x48=CPU_CONTEXT_OFFSET_R9
144	 * 80U=0x50=CPU_CONTEXT_OFFSET_R10
145	 * 88U=0x58=CPU_CONTEXT_OFFSET_R11
146	 * 96U=0x60=CPU_CONTEXT_OFFSET_R12
147	 * 104U=0x68=CPU_CONTEXT_OFFSET_R13
148	 * 112U=0x70=CPU_CONTEXT_OFFSET_R14
149	 * 120U=0x79=CPU_CONTEXT_OFFSET_R15
150	 */
151	movq 0x0 + cpu_ctx(%rip), %rax
152	movq 0x8 + cpu_ctx(%rip), %rcx
153	movq 0x10 + cpu_ctx(%rip), %rdx
154	movq 0x18 + cpu_ctx(%rip), %rbx
155	movq 0x28 + cpu_ctx(%rip), %rbp
156	movq 0x30 + cpu_ctx(%rip), %rsi
157	movq 0x38 + cpu_ctx(%rip), %rdi
158	movq 0x40 + cpu_ctx(%rip), %r8
159	movq 0x48 + cpu_ctx(%rip), %r9
160	movq 0x50 + cpu_ctx(%rip), %r10
161	movq 0x58 + cpu_ctx(%rip), %r11
162	movq 0x60 + cpu_ctx(%rip), %r12
163	movq 0x68 + cpu_ctx(%rip), %r13
164	movq 0x70 + cpu_ctx(%rip), %r14
165	movq 0x78 + cpu_ctx(%rip), %r15
166
167	retq
168