123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- /*
- * PowerPC 64-bit swsusp implementation
- *
- * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
- *
- * GPLv2
- */
- #include <linux/threads.h>
- #include <asm/processor.h>
- #include <asm/page.h>
- #include <asm/cputable.h>
- #include <asm/thread_info.h>
- #include <asm/ppc_asm.h>
- #include <asm/asm-offsets.h>
- /*
- * Structure for storing CPU registers on the save area.
- */
- #define SL_r1 0x00 /* stack pointer */
- #define SL_PC 0x08
- #define SL_MSR 0x10
- #define SL_SDR1 0x18
- #define SL_XER 0x20
- #define SL_TB 0x40
- #define SL_r2 0x48
- #define SL_CR 0x50
- #define SL_LR 0x58
- #define SL_r12 0x60
- #define SL_r13 0x68
- #define SL_r14 0x70
- #define SL_r15 0x78
- #define SL_r16 0x80
- #define SL_r17 0x88
- #define SL_r18 0x90
- #define SL_r19 0x98
- #define SL_r20 0xa0
- #define SL_r21 0xa8
- #define SL_r22 0xb0
- #define SL_r23 0xb8
- #define SL_r24 0xc0
- #define SL_r25 0xc8
- #define SL_r26 0xd0
- #define SL_r27 0xd8
- #define SL_r28 0xe0
- #define SL_r29 0xe8
- #define SL_r30 0xf0
- #define SL_r31 0xf8
- #define SL_SPRG1 0x100
- #define SL_TCR 0x108
- #define SL_SIZE SL_TCR+8
- /* these macros rely on the save area being
- * pointed to by r11 */
- #define SAVE_SPR(register) \
- mfspr r0, SPRN_##register ;\
- std r0, SL_##register(r11)
- #define RESTORE_SPR(register) \
- ld r0, SL_##register(r11) ;\
- mtspr SPRN_##register, r0
- #define SAVE_SPECIAL(special) \
- mf##special r0 ;\
- std r0, SL_##special(r11)
- #define RESTORE_SPECIAL(special) \
- ld r0, SL_##special(r11) ;\
- mt##special r0
- #define SAVE_REGISTER(reg) \
- std reg, SL_##reg(r11)
- #define RESTORE_REGISTER(reg) \
- ld reg, SL_##reg(r11)
- /* space for storing cpu state */
- .section .data
- .align 5
- swsusp_save_area:
- .space SL_SIZE
- .section ".toc","aw"
- swsusp_save_area_ptr:
- .tc swsusp_save_area[TC],swsusp_save_area
- restore_pblist_ptr:
- .tc restore_pblist[TC],restore_pblist
- .section .text
- .align 5
- _GLOBAL(swsusp_arch_suspend)
- ld r11,swsusp_save_area_ptr@toc(r2)
- SAVE_SPECIAL(LR)
- SAVE_REGISTER(r1)
- SAVE_SPECIAL(CR)
- SAVE_SPECIAL(TB)
- SAVE_REGISTER(r2)
- SAVE_REGISTER(r12)
- SAVE_REGISTER(r13)
- SAVE_REGISTER(r14)
- SAVE_REGISTER(r15)
- SAVE_REGISTER(r16)
- SAVE_REGISTER(r17)
- SAVE_REGISTER(r18)
- SAVE_REGISTER(r19)
- SAVE_REGISTER(r20)
- SAVE_REGISTER(r21)
- SAVE_REGISTER(r22)
- SAVE_REGISTER(r23)
- SAVE_REGISTER(r24)
- SAVE_REGISTER(r25)
- SAVE_REGISTER(r26)
- SAVE_REGISTER(r27)
- SAVE_REGISTER(r28)
- SAVE_REGISTER(r29)
- SAVE_REGISTER(r30)
- SAVE_REGISTER(r31)
- SAVE_SPECIAL(MSR)
- SAVE_SPECIAL(XER)
- #ifdef CONFIG_PPC_BOOK3S_64
- BEGIN_FW_FTR_SECTION
- SAVE_SPECIAL(SDR1)
- END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR)
- #else
- SAVE_SPR(TCR)
- /* Save SPRG1, SPRG1 be used save paca */
- SAVE_SPR(SPRG1)
- #endif
- /* we push the stack up 128 bytes but don't store the
- * stack pointer on the stack like a real stackframe */
- addi r1,r1,-128
- bl _iommu_save
- bl swsusp_save
- /* restore LR */
- ld r11,swsusp_save_area_ptr@toc(r2)
- RESTORE_SPECIAL(LR)
- addi r1,r1,128
- blr
- /* Resume code */
- _GLOBAL(swsusp_arch_resume)
- /* Stop pending alitvec streams and memory accesses */
- BEGIN_FTR_SECTION
- DSSALL
- END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
- sync
- ld r12,restore_pblist_ptr@toc(r2)
- ld r12,0(r12)
- cmpdi r12,0
- beq- nothing_to_copy
- li r15,PAGE_SIZE>>3
- copyloop:
- ld r13,pbe_address(r12)
- ld r14,pbe_orig_address(r12)
- mtctr r15
- li r10,0
- copy_page_loop:
- ldx r0,r10,r13
- stdx r0,r10,r14
- addi r10,r10,8
- bdnz copy_page_loop
- ld r12,pbe_next(r12)
- cmpdi r12,0
- bne+ copyloop
- nothing_to_copy:
- #ifdef CONFIG_PPC_BOOK3S_64
- /* flush caches */
- lis r3, 0x10
- mtctr r3
- li r3, 0
- ori r3, r3, CONFIG_KERNEL_START>>48
- li r0, 48
- sld r3, r3, r0
- li r0, 0
- 1:
- dcbf r0,r3
- addi r3,r3,0x20
- bdnz 1b
- sync
- tlbia
- #endif
- ld r11,swsusp_save_area_ptr@toc(r2)
- RESTORE_SPECIAL(CR)
- /* restore timebase */
- /* load saved tb */
- ld r1, SL_TB(r11)
- /* get upper 32 bits of it */
- srdi r2, r1, 32
- /* clear tb lower to avoid wrap */
- li r0, 0
- mttbl r0
- /* set tb upper */
- mttbu r2
- /* set tb lower */
- mttbl r1
- /* restore registers */
- RESTORE_REGISTER(r1)
- RESTORE_REGISTER(r2)
- RESTORE_REGISTER(r12)
- RESTORE_REGISTER(r13)
- RESTORE_REGISTER(r14)
- RESTORE_REGISTER(r15)
- RESTORE_REGISTER(r16)
- RESTORE_REGISTER(r17)
- RESTORE_REGISTER(r18)
- RESTORE_REGISTER(r19)
- RESTORE_REGISTER(r20)
- RESTORE_REGISTER(r21)
- RESTORE_REGISTER(r22)
- RESTORE_REGISTER(r23)
- RESTORE_REGISTER(r24)
- RESTORE_REGISTER(r25)
- RESTORE_REGISTER(r26)
- RESTORE_REGISTER(r27)
- RESTORE_REGISTER(r28)
- RESTORE_REGISTER(r29)
- RESTORE_REGISTER(r30)
- RESTORE_REGISTER(r31)
- #ifdef CONFIG_PPC_BOOK3S_64
- /* can't use RESTORE_SPECIAL(MSR) */
- ld r0, SL_MSR(r11)
- mtmsrd r0, 0
- BEGIN_FW_FTR_SECTION
- RESTORE_SPECIAL(SDR1)
- END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR)
- #else
- /* Restore SPRG1, be used to save paca */
- ld r0, SL_SPRG1(r11)
- mtsprg 1, r0
- RESTORE_SPECIAL(MSR)
- /* Restore TCR and clear any pending bits in TSR. */
- RESTORE_SPR(TCR)
- lis r0, (TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS)@h
- mtspr SPRN_TSR, r0
- /* Kick decrementer */
- li r0, 1
- mtdec r0
- /* Invalidate all tlbs */
- bl _tlbil_all
- #endif
- RESTORE_SPECIAL(XER)
- sync
- addi r1,r1,-128
- #ifdef CONFIG_PPC_BOOK3S_64
- bl slb_flush_and_rebolt
- #endif
- bl do_after_copyback
- addi r1,r1,128
- ld r11,swsusp_save_area_ptr@toc(r2)
- RESTORE_SPECIAL(LR)
- li r3, 0
- blr
|