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,PAGE_SIZE>>3 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 229