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#include <asm/feature-fixups.h> 17 18/* 19 * Structure for storing CPU registers on the save area. 20 */ 21#define SL_r1 0x00 /* stack pointer */ 22#define SL_PC 0x08 23#define SL_MSR 0x10 24#define SL_SDR1 0x18 25#define SL_XER 0x20 26#define SL_TB 0x40 27#define SL_r2 0x48 28#define SL_CR 0x50 29#define SL_LR 0x58 30#define SL_r12 0x60 31#define SL_r13 0x68 32#define SL_r14 0x70 33#define SL_r15 0x78 34#define SL_r16 0x80 35#define SL_r17 0x88 36#define SL_r18 0x90 37#define SL_r19 0x98 38#define SL_r20 0xa0 39#define SL_r21 0xa8 40#define SL_r22 0xb0 41#define SL_r23 0xb8 42#define SL_r24 0xc0 43#define SL_r25 0xc8 44#define SL_r26 0xd0 45#define SL_r27 0xd8 46#define SL_r28 0xe0 47#define SL_r29 0xe8 48#define SL_r30 0xf0 49#define SL_r31 0xf8 50#define SL_SPRG1 0x100 51#define SL_TCR 0x108 52#define SL_SIZE SL_TCR+8 53 54/* these macros rely on the save area being 55 * pointed to by r11 */ 56 57#define SAVE_SPR(register) \ 58 mfspr r0, SPRN_##register ;\ 59 std r0, SL_##register(r11) 60#define RESTORE_SPR(register) \ 61 ld r0, SL_##register(r11) ;\ 62 mtspr SPRN_##register, r0 63#define SAVE_SPECIAL(special) \ 64 mf##special r0 ;\ 65 std r0, SL_##special(r11) 66#define RESTORE_SPECIAL(special) \ 67 ld r0, SL_##special(r11) ;\ 68 mt##special r0 69#define SAVE_REGISTER(reg) \ 70 std reg, SL_##reg(r11) 71#define RESTORE_REGISTER(reg) \ 72 ld reg, SL_##reg(r11) 73 74/* space for storing cpu state */ 75 .section .data 76 .align 5 77swsusp_save_area: 78 .space SL_SIZE 79 80 .section ".toc","aw" 81swsusp_save_area_ptr: 82 .tc swsusp_save_area[TC],swsusp_save_area 83restore_pblist_ptr: 84 .tc restore_pblist[TC],restore_pblist 85 86 .section .text 87 .align 5 88_GLOBAL(swsusp_arch_suspend) 89 ld r11,swsusp_save_area_ptr@toc(r2) 90 SAVE_SPECIAL(LR) 91 SAVE_REGISTER(r1) 92 SAVE_SPECIAL(CR) 93 SAVE_SPECIAL(TB) 94 SAVE_REGISTER(r2) 95 SAVE_REGISTER(r12) 96 SAVE_REGISTER(r13) 97 SAVE_REGISTER(r14) 98 SAVE_REGISTER(r15) 99 SAVE_REGISTER(r16) 100 SAVE_REGISTER(r17) 101 SAVE_REGISTER(r18) 102 SAVE_REGISTER(r19) 103 SAVE_REGISTER(r20) 104 SAVE_REGISTER(r21) 105 SAVE_REGISTER(r22) 106 SAVE_REGISTER(r23) 107 SAVE_REGISTER(r24) 108 SAVE_REGISTER(r25) 109 SAVE_REGISTER(r26) 110 SAVE_REGISTER(r27) 111 SAVE_REGISTER(r28) 112 SAVE_REGISTER(r29) 113 SAVE_REGISTER(r30) 114 SAVE_REGISTER(r31) 115 SAVE_SPECIAL(MSR) 116 SAVE_SPECIAL(XER) 117#ifdef CONFIG_PPC_BOOK3S_64 118BEGIN_FW_FTR_SECTION 119 SAVE_SPECIAL(SDR1) 120END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR) 121#else 122 SAVE_SPR(TCR) 123 124 /* Save SPRG1, SPRG1 be used save paca */ 125 SAVE_SPR(SPRG1) 126#endif 127 128 /* we push the stack up 128 bytes but don't store the 129 * stack pointer on the stack like a real stackframe */ 130 addi r1,r1,-128 131 132 bl _iommu_save 133 bl swsusp_save 134 135 /* restore LR */ 136 ld r11,swsusp_save_area_ptr@toc(r2) 137 RESTORE_SPECIAL(LR) 138 addi r1,r1,128 139 140 blr 141 142/* Resume code */ 143_GLOBAL(swsusp_arch_resume) 144 /* Stop pending alitvec streams and memory accesses */ 145BEGIN_FTR_SECTION 146 DSSALL 147END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) 148 sync 149 150 ld r12,restore_pblist_ptr@toc(r2) 151 ld r12,0(r12) 152 153 cmpdi r12,0 154 beq- nothing_to_copy 155 li r15,PAGE_SIZE>>3 156copyloop: 157 ld r13,pbe_address(r12) 158 ld r14,pbe_orig_address(r12) 159 160 mtctr r15 161 li r10,0 162copy_page_loop: 163 ldx r0,r10,r13 164 stdx r0,r10,r14 165 addi r10,r10,8 166 bdnz copy_page_loop 167 168 ld r12,pbe_next(r12) 169 cmpdi r12,0 170 bne+ copyloop 171nothing_to_copy: 172 173#ifdef CONFIG_PPC_BOOK3S_64 174 /* flush caches */ 175 lis r3, 0x10 176 mtctr r3 177 li r3, 0 178 ori r3, r3, CONFIG_KERNEL_START>>48 179 li r0, 48 180 sld r3, r3, r0 181 li r0, 0 1821: 183 dcbf 0,r3 184 addi r3,r3,0x20 185 bdnz 1b 186 187 sync 188 189 tlbia 190#endif 191 192 ld r11,swsusp_save_area_ptr@toc(r2) 193 194 RESTORE_SPECIAL(CR) 195 196 /* restore timebase */ 197 /* load saved tb */ 198 ld r1, SL_TB(r11) 199 /* get upper 32 bits of it */ 200 srdi r2, r1, 32 201 /* clear tb lower to avoid wrap */ 202 li r0, 0 203 mttbl r0 204 /* set tb upper */ 205 mttbu r2 206 /* set tb lower */ 207 mttbl r1 208 209 /* restore registers */ 210 RESTORE_REGISTER(r1) 211 RESTORE_REGISTER(r2) 212 RESTORE_REGISTER(r12) 213 RESTORE_REGISTER(r13) 214 RESTORE_REGISTER(r14) 215 RESTORE_REGISTER(r15) 216 RESTORE_REGISTER(r16) 217 RESTORE_REGISTER(r17) 218 RESTORE_REGISTER(r18) 219 RESTORE_REGISTER(r19) 220 RESTORE_REGISTER(r20) 221 RESTORE_REGISTER(r21) 222 RESTORE_REGISTER(r22) 223 RESTORE_REGISTER(r23) 224 RESTORE_REGISTER(r24) 225 RESTORE_REGISTER(r25) 226 RESTORE_REGISTER(r26) 227 RESTORE_REGISTER(r27) 228 RESTORE_REGISTER(r28) 229 RESTORE_REGISTER(r29) 230 RESTORE_REGISTER(r30) 231 RESTORE_REGISTER(r31) 232 233#ifdef CONFIG_PPC_BOOK3S_64 234 /* can't use RESTORE_SPECIAL(MSR) */ 235 ld r0, SL_MSR(r11) 236 mtmsrd r0, 0 237BEGIN_FW_FTR_SECTION 238 RESTORE_SPECIAL(SDR1) 239END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR) 240#else 241 /* Restore SPRG1, be used to save paca */ 242 ld r0, SL_SPRG1(r11) 243 mtsprg 1, r0 244 245 RESTORE_SPECIAL(MSR) 246 247 /* Restore TCR and clear any pending bits in TSR. */ 248 RESTORE_SPR(TCR) 249 lis r0, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h 250 mtspr SPRN_TSR, r0 251 252 /* Kick decrementer */ 253 li r0, 1 254 mtdec r0 255 256 /* Invalidate all tlbs */ 257 bl _tlbil_all 258#endif 259 RESTORE_SPECIAL(XER) 260 261 sync 262 263 addi r1,r1,-128 264#ifdef CONFIG_PPC_BOOK3S_64 265 bl slb_flush_and_rebolt 266#endif 267 bl do_after_copyback 268 addi r1,r1,128 269 270 ld r11,swsusp_save_area_ptr@toc(r2) 271 RESTORE_SPECIAL(LR) 272 273 li r3, 0 274 blr 275