 711b5138d5
			
		
	
	
	711b5138d5
	
	
	
		
			
			Currently, when not in hypervisor mode the kernel Oopses during suspend or hibernation when accessing the SDR1 register, because it is only available in hypervisor mode. Access to it needs to be protected in BEGIN/END_FW_FTR_SECTION. Signed-off-by: Dan Streetman <ddstreet@ieee.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Reported-by: Jimmy Pan <jipan@redhat.com> Tested-by: Jimmy Pan <jipan@redhat.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
		
			
				
	
	
		
			273 lines
		
	
	
	
		
			5.1 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			273 lines
		
	
	
	
		
			5.1 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * 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
 |