 e2ccba4908
			
		
	
	
	e2ccba4908
	
	
	
		
			
			Copying a function with memcpy() and then trying to execute the result isn't trivially portable to Thumb. This patch modifies the kexec soft restart code to copy its assembler trampoline relocate_new_kernel() using fncpy() instead, so that relocate_new_kernel can be in the same ISA as the rest of the kernel without problems. Signed-off-by: Dave Martin <Dave.Martin@arm.com> Acked-by: Will Deacon <will.deacon@arm.com> Reported-by: Taras Kondratiuk <taras.kondratiuk@linaro.org> Tested-by: Taras Kondratiuk <taras.kondratiuk@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
		
			
				
	
	
		
			92 lines
		
	
	
	
		
			1.4 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			92 lines
		
	
	
	
		
			1.4 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*
 | |
|  * relocate_kernel.S - put the kernel image in place to boot
 | |
|  */
 | |
| 
 | |
| #include <linux/linkage.h>
 | |
| #include <asm/kexec.h>
 | |
| 
 | |
| 	.align	3	/* not needed for this code, but keeps fncpy() happy */
 | |
| 
 | |
| ENTRY(relocate_new_kernel)
 | |
| 
 | |
| 	ldr	r0,kexec_indirection_page
 | |
| 	ldr	r1,kexec_start_address
 | |
| 
 | |
| 	/*
 | |
| 	 * If there is no indirection page (we are doing crashdumps)
 | |
| 	 * skip any relocation.
 | |
| 	 */
 | |
| 	cmp	r0, #0
 | |
| 	beq	2f
 | |
| 
 | |
| 0:	/* top, read another word for the indirection page */
 | |
| 	ldr	r3, [r0],#4
 | |
| 
 | |
| 	/* Is it a destination page. Put destination address to r4 */
 | |
| 	tst	r3,#1,0
 | |
| 	beq	1f
 | |
| 	bic	r4,r3,#1
 | |
| 	b	0b
 | |
| 1:
 | |
| 	/* Is it an indirection page */
 | |
| 	tst	r3,#2,0
 | |
| 	beq	1f
 | |
| 	bic	r0,r3,#2
 | |
| 	b	0b
 | |
| 1:
 | |
| 
 | |
| 	/* are we done ? */
 | |
| 	tst	r3,#4,0
 | |
| 	beq	1f
 | |
| 	b	2f
 | |
| 
 | |
| 1:
 | |
| 	/* is it source ? */
 | |
| 	tst	r3,#8,0
 | |
| 	beq	0b
 | |
| 	bic r3,r3,#8
 | |
| 	mov r6,#1024
 | |
| 9:
 | |
| 	ldr r5,[r3],#4
 | |
| 	str r5,[r4],#4
 | |
| 	subs r6,r6,#1
 | |
| 	bne 9b
 | |
| 	b 0b
 | |
| 
 | |
| 2:
 | |
| 	/* Jump to relocated kernel */
 | |
| 	mov lr,r1
 | |
| 	mov r0,#0
 | |
| 	ldr r1,kexec_mach_type
 | |
| 	ldr r2,kexec_boot_atags
 | |
|  ARM(	mov pc, lr	)
 | |
|  THUMB(	bx lr		)
 | |
| 
 | |
| 	.align
 | |
| 
 | |
| 	.globl kexec_start_address
 | |
| kexec_start_address:
 | |
| 	.long	0x0
 | |
| 
 | |
| 	.globl kexec_indirection_page
 | |
| kexec_indirection_page:
 | |
| 	.long	0x0
 | |
| 
 | |
| 	.globl kexec_mach_type
 | |
| kexec_mach_type:
 | |
| 	.long	0x0
 | |
| 
 | |
| 	/* phy addr of the atags for the new kernel */
 | |
| 	.globl kexec_boot_atags
 | |
| kexec_boot_atags:
 | |
| 	.long	0x0
 | |
| 
 | |
| ENDPROC(relocate_new_kernel)
 | |
| 
 | |
| relocate_new_kernel_end:
 | |
| 
 | |
| 	.globl relocate_new_kernel_size
 | |
| relocate_new_kernel_size:
 | |
| 	.long relocate_new_kernel_end - relocate_new_kernel
 | |
| 
 | |
| 
 |