aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/swsusp_asm64.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/swsusp_asm64.S')
-rw-r--r--arch/powerpc/kernel/swsusp_asm64.S228
1 files changed, 228 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/swsusp_asm64.S b/arch/powerpc/kernel/swsusp_asm64.S
new file mode 100644
index 000000000000..e092c3cbdb9b
--- /dev/null
+++ b/arch/powerpc/kernel/swsusp_asm64.S
@@ -0,0 +1,228 @@
1/*
2 * PowerPC 64-bit swsusp implementation
3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
5 *
6 * GPLv2
7 */
8
9#include <linux/threads.h>
10#include <asm/processor.h>
11#include <asm/page.h>
12#include <asm/cputable.h>
13#include <asm/thread_info.h>
14#include <asm/ppc_asm.h>
15#include <asm/asm-offsets.h>
16
17/*
18 * Structure for storing CPU registers on the save area.
19 */
20#define SL_r1 0x00 /* stack pointer */
21#define SL_PC 0x08
22#define SL_MSR 0x10
23#define SL_SDR1 0x18
24#define SL_XER 0x20
25#define SL_TB 0x40
26#define SL_r2 0x48
27#define SL_CR 0x50
28#define SL_LR 0x58
29#define SL_r12 0x60
30#define SL_r13 0x68
31#define SL_r14 0x70
32#define SL_r15 0x78
33#define SL_r16 0x80
34#define SL_r17 0x88
35#define SL_r18 0x90
36#define SL_r19 0x98
37#define SL_r20 0xa0
38#define SL_r21 0xa8
39#define SL_r22 0xb0
40#define SL_r23 0xb8
41#define SL_r24 0xc0
42#define SL_r25 0xc8
43#define SL_r26 0xd0
44#define SL_r27 0xd8
45#define SL_r28 0xe0
46#define SL_r29 0xe8
47#define SL_r30 0xf0
48#define SL_r31 0xf8
49#define SL_SIZE SL_r31+8
50
51/* these macros rely on the save area being
52 * pointed to by r11 */
53#define SAVE_SPECIAL(special) \
54 mf##special r0 ;\
55 std r0, SL_##special(r11)
56#define RESTORE_SPECIAL(special) \
57 ld r0, SL_##special(r11) ;\
58 mt##special r0
59#define SAVE_REGISTER(reg) \
60 std reg, SL_##reg(r11)
61#define RESTORE_REGISTER(reg) \
62 ld reg, SL_##reg(r11)
63
64/* space for storing cpu state */
65 .section .data
66 .align 5
67swsusp_save_area:
68 .space SL_SIZE
69
70 .section ".toc","aw"
71swsusp_save_area_ptr:
72 .tc swsusp_save_area[TC],swsusp_save_area
73restore_pblist_ptr:
74 .tc restore_pblist[TC],restore_pblist
75
76 .section .text
77 .align 5
78_GLOBAL(swsusp_arch_suspend)
79 ld r11,swsusp_save_area_ptr@toc(r2)
80 SAVE_SPECIAL(LR)
81 SAVE_REGISTER(r1)
82 SAVE_SPECIAL(CR)
83 SAVE_SPECIAL(TB)
84 SAVE_REGISTER(r2)
85 SAVE_REGISTER(r12)
86 SAVE_REGISTER(r13)
87 SAVE_REGISTER(r14)
88 SAVE_REGISTER(r15)
89 SAVE_REGISTER(r16)
90 SAVE_REGISTER(r17)
91 SAVE_REGISTER(r18)
92 SAVE_REGISTER(r19)
93 SAVE_REGISTER(r20)
94 SAVE_REGISTER(r21)
95 SAVE_REGISTER(r22)
96 SAVE_REGISTER(r23)
97 SAVE_REGISTER(r24)
98 SAVE_REGISTER(r25)
99 SAVE_REGISTER(r26)
100 SAVE_REGISTER(r27)
101 SAVE_REGISTER(r28)
102 SAVE_REGISTER(r29)
103 SAVE_REGISTER(r30)
104 SAVE_REGISTER(r31)
105 SAVE_SPECIAL(MSR)
106 SAVE_SPECIAL(SDR1)
107 SAVE_SPECIAL(XER)
108
109 /* we push the stack up 128 bytes but don't store the
110 * stack pointer on the stack like a real stackframe */
111 addi r1,r1,-128
112
113 bl _iommu_save
114 bl swsusp_save
115
116 /* restore LR */
117 ld r11,swsusp_save_area_ptr@toc(r2)
118 RESTORE_SPECIAL(LR)
119 addi r1,r1,128
120
121 blr
122
123/* Resume code */
124_GLOBAL(swsusp_arch_resume)
125 /* Stop pending alitvec streams and memory accesses */
126BEGIN_FTR_SECTION
127 DSSALL
128END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
129 sync
130
131 ld r12,restore_pblist_ptr@toc(r2)
132 ld r12,0(r12)
133
134 cmpdi r12,0
135 beq- nothing_to_copy
136 li r15,512
137copyloop:
138 ld r13,pbe_address(r12)
139 ld r14,pbe_orig_address(r12)
140
141 mtctr r15
142 li r10,0
143copy_page_loop:
144 ldx r0,r10,r13
145 stdx r0,r10,r14
146 addi r10,r10,8
147 bdnz copy_page_loop
148
149 ld r12,pbe_next(r12)
150 cmpdi r12,0
151 bne+ copyloop
152nothing_to_copy:
153
154 /* flush caches */
155 lis r3, 0x10
156 mtctr r3
157 li r3, 0
158 ori r3, r3, CONFIG_KERNEL_START>>48
159 li r0, 48
160 sld r3, r3, r0
161 li r0, 0
1621:
163 dcbf r0,r3
164 addi r3,r3,0x20
165 bdnz 1b
166
167 sync
168
169 tlbia
170
171 ld r11,swsusp_save_area_ptr@toc(r2)
172
173 RESTORE_SPECIAL(CR)
174
175 /* restore timebase */
176 /* load saved tb */
177 ld r1, SL_TB(r11)
178 /* get upper 32 bits of it */
179 srdi r2, r1, 32
180 /* clear tb lower to avoid wrap */
181 li r0, 0
182 mttbl r0
183 /* set tb upper */
184 mttbu r2
185 /* set tb lower */
186 mttbl r1
187
188 /* restore registers */
189 RESTORE_REGISTER(r1)
190 RESTORE_REGISTER(r2)
191 RESTORE_REGISTER(r12)
192 RESTORE_REGISTER(r13)
193 RESTORE_REGISTER(r14)
194 RESTORE_REGISTER(r15)
195 RESTORE_REGISTER(r16)
196 RESTORE_REGISTER(r17)
197 RESTORE_REGISTER(r18)
198 RESTORE_REGISTER(r19)
199 RESTORE_REGISTER(r20)
200 RESTORE_REGISTER(r21)
201 RESTORE_REGISTER(r22)
202 RESTORE_REGISTER(r23)
203 RESTORE_REGISTER(r24)
204 RESTORE_REGISTER(r25)
205 RESTORE_REGISTER(r26)
206 RESTORE_REGISTER(r27)
207 RESTORE_REGISTER(r28)
208 RESTORE_REGISTER(r29)
209 RESTORE_REGISTER(r30)
210 RESTORE_REGISTER(r31)
211 /* can't use RESTORE_SPECIAL(MSR) */
212 ld r0, SL_MSR(r11)
213 mtmsrd r0, 0
214 RESTORE_SPECIAL(SDR1)
215 RESTORE_SPECIAL(XER)
216
217 sync
218
219 addi r1,r1,-128
220 bl slb_flush_and_rebolt
221 bl do_after_copyback
222 addi r1,r1,128
223
224 ld r11,swsusp_save_area_ptr@toc(r2)
225 RESTORE_SPECIAL(LR)
226
227 li r3, 0
228 blr