1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * PowerPC 64-bit swsusp implementation 4 * 5 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> 6 */ 7 8#include <linux/threads.h> 9#include <asm/processor.h> 10#include <asm/page.h> 11#include <asm/cputable.h> 12#include <asm/thread_info.h> 13#include <asm/ppc_asm.h> 14#include <asm/asm-offsets.h> 15#include <asm/feature-fixups.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_SPRG1 0x100 50#define SL_TCR 0x108 51#define SL_SIZE SL_TCR+8 52 53/* these macros rely on the save area being 54 * pointed to by r11 */ 55 56#define SAVE_SPR(register) \ 57 mfspr r0, SPRN_##register ;\ 58 std r0, SL_##register(r11) 59#define RESTORE_SPR(register) \ 60 ld r0, SL_##register(r11) ;\ 61 mtspr SPRN_##register, r0 62#define SAVE_SPECIAL(special) \ 63 mf##special r0 ;\ 64 std r0, SL_##special(r11) 65#define RESTORE_SPECIAL(special) \ 66 ld r0, SL_##special(r11) ;\ 67 mt##special r0 68#define SAVE_REGISTER(reg) \ 69 std reg, SL_##reg(r11) 70#define RESTORE_REGISTER(reg) \ 71 ld reg, SL_##reg(r11) 72 73/* space for storing cpu state */ 74 .section .data 75 .align 5 76swsusp_save_area: 77 .space SL_SIZE 78 79 .section ".toc","aw" 80swsusp_save_area_ptr: 81 .tc swsusp_save_area[TC],swsusp_save_area 82restore_pblist_ptr: 83 .tc restore_pblist[TC],restore_pblist 84 85 .section .text 86 .align 5 87_GLOBAL(swsusp_arch_suspend) 88 ld r11,swsusp_save_area_ptr@toc(r2) 89 SAVE_SPECIAL(LR) 90 SAVE_REGISTER(r1) 91 SAVE_SPECIAL(CR) 92 SAVE_SPECIAL(TB) 93 SAVE_REGISTER(r2) 94 SAVE_REGISTER(r12) 95 SAVE_REGISTER(r13) 96 SAVE_REGISTER(r14) 97 SAVE_REGISTER(r15) 98 SAVE_REGISTER(r16) 99 SAVE_REGISTER(r17) 100 SAVE_REGISTER(r18) 101 SAVE_REGISTER(r19) 102 SAVE_REGISTER(r20) 103 SAVE_REGISTER(r21) 104 SAVE_REGISTER(r22) 105 SAVE_REGISTER(r23) 106 SAVE_REGISTER(r24) 107 SAVE_REGISTER(r25) 108 SAVE_REGISTER(r26) 109 SAVE_REGISTER(r27) 110 SAVE_REGISTER(r28) 111 SAVE_REGISTER(r29) 112 SAVE_REGISTER(r30) 113 SAVE_REGISTER(r31) 114 SAVE_SPECIAL(MSR) 115 SAVE_SPECIAL(XER) 116#ifdef CONFIG_PPC_BOOK3S_64 117BEGIN_FW_FTR_SECTION 118 SAVE_SPECIAL(SDR1) 119END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR) 120#else 121 SAVE_SPR(TCR) 122 123 /* Save SPRG1, SPRG1 be used save paca */ 124 SAVE_SPR(SPRG1) 125#endif 126 127 /* we push the stack up 128 bytes but don't store the 128 * stack pointer on the stack like a real stackframe */ 129 addi r1,r1,-128 130 131 bl swsusp_save 132 133 /* restore LR */ 134 ld r11,swsusp_save_area_ptr@toc(r2) 135 RESTORE_SPECIAL(LR) 136 addi r1,r1,128 137 138 blr 139 140/* Resume code */ 141_GLOBAL(swsusp_arch_resume) 142 /* Stop pending alitvec streams and memory accesses */ 143BEGIN_FTR_SECTION 144 PPC_DSSALL 145END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) 146 sync 147 148 ld r12,restore_pblist_ptr@toc(r2) 149 ld r12,0(r12) 150 151 cmpdi r12,0 152 beq- nothing_to_copy 153 li r15,PAGE_SIZE>>3 154copyloop: 155 ld r13,pbe_address(r12) 156 ld r14,pbe_orig_address(r12) 157 158 mtctr r15 159 li r10,0 160copy_page_loop: 161 ldx r0,r10,r13 162 stdx r0,r10,r14 163 addi r10,r10,8 164 bdnz copy_page_loop 165 166 ld r12,pbe_next(r12) 167 cmpdi r12,0 168 bne+ copyloop 169nothing_to_copy: 170 171#ifdef CONFIG_PPC_BOOK3S_64 172 /* flush caches */ 173 lis r3, 0x10 174 mtctr r3 175 li r3, 0 176 ori r3, r3, CONFIG_KERNEL_START>>48 177 li r0, 48 178 sld r3, r3, r0 179 li r0, 0 1801: 181 dcbf 0,r3 182 addi r3,r3,0x20 183 bdnz 1b 184 185 sync 186 187 tlbia 188#endif 189 190 ld r11,swsusp_save_area_ptr@toc(r2) 191 192 RESTORE_SPECIAL(CR) 193 194 /* restore timebase */ 195 /* load saved tb */ 196 ld r1, SL_TB(r11) 197 /* get upper 32 bits of it */ 198 srdi r2, r1, 32 199 /* clear tb lower to avoid wrap */ 200 li r0, 0 201 mttbl r0 202 /* set tb upper */ 203 mttbu r2 204 /* set tb lower */ 205 mttbl r1 206 207 /* restore registers */ 208 RESTORE_REGISTER(r1) 209 RESTORE_REGISTER(r2) 210 RESTORE_REGISTER(r12) 211 RESTORE_REGISTER(r13) 212 RESTORE_REGISTER(r14) 213 RESTORE_REGISTER(r15) 214 RESTORE_REGISTER(r16) 215 RESTORE_REGISTER(r17) 216 RESTORE_REGISTER(r18) 217 RESTORE_REGISTER(r19) 218 RESTORE_REGISTER(r20) 219 RESTORE_REGISTER(r21) 220 RESTORE_REGISTER(r22) 221 RESTORE_REGISTER(r23) 222 RESTORE_REGISTER(r24) 223 RESTORE_REGISTER(r25) 224 RESTORE_REGISTER(r26) 225 RESTORE_REGISTER(r27) 226 RESTORE_REGISTER(r28) 227 RESTORE_REGISTER(r29) 228 RESTORE_REGISTER(r30) 229 RESTORE_REGISTER(r31) 230 231#ifdef CONFIG_PPC_BOOK3S_64 232 /* can't use RESTORE_SPECIAL(MSR) */ 233 ld r0, SL_MSR(r11) 234 mtmsrd r0, 0 235BEGIN_FW_FTR_SECTION 236 RESTORE_SPECIAL(SDR1) 237END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR) 238#else 239 /* Restore SPRG1, be used to save paca */ 240 ld r0, SL_SPRG1(r11) 241 mtsprg 1, r0 242 243 RESTORE_SPECIAL(MSR) 244 245 /* Restore TCR and clear any pending bits in TSR. */ 246 RESTORE_SPR(TCR) 247 lis r0, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h 248 mtspr SPRN_TSR, r0 249 250 /* Kick decrementer */ 251 li r0, 1 252 mtdec r0 253 254 /* Invalidate all tlbs */ 255 bl _tlbil_all 256#endif 257 RESTORE_SPECIAL(XER) 258 259 sync 260 261 addi r1,r1,-128 262#ifdef CONFIG_PPC_BOOK3S_64 263 bl slb_flush_and_restore_bolted 264#endif 265 bl do_after_copyback 266 addi r1,r1,128 267 268 ld r11,swsusp_save_area_ptr@toc(r2) 269 RESTORE_SPECIAL(LR) 270 271 li r3, 0 272 blr 273