[ARM] 4224/2: allow XIP kernel to boot again

Since commit 2552fc27ff79b10b9678d92bcaef21df38bb7bb6 XIP kernels failed
to boot because (_end - PAGE_OFFSET - 1) is much smaller than the size
of the kernel text and data in the XIP case, causing the kernel not to
be entirely mapped.

Even in the non-XIP case, the use of (_end - PAGE_OFFSET - 1) is wrong
because it produces a too large value if TEXT_OFFSET is larger than 1MB.

Finally the original code was performing one loop too many.

Let's break the loop when the section pointer has passed the last byte
of the kernel instead.

Signed-off-by: Nicolas Pitre <nico@cam.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index cf495a30..c5f0c52 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -48,9 +48,11 @@
 	.endm
 
 #ifdef CONFIG_XIP_KERNEL
-#define TEXTADDR  XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
+#define KERNEL_START	XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR)
+#define KERNEL_END	_edata_loc
 #else
-#define TEXTADDR  KERNEL_RAM_VADDR
+#define KERNEL_START	KERNEL_RAM_VADDR
+#define KERNEL_END	_end
 #endif
 
 /*
@@ -240,16 +242,15 @@
 	 * Now setup the pagetables for our kernel direct
 	 * mapped region.
 	 */
-	add	r0, r4,  #(TEXTADDR & 0xff000000) >> 18	@ start of kernel
-	str	r3, [r0, #(TEXTADDR & 0x00f00000) >> 18]!
-
-	ldr	r6, =(_end - PAGE_OFFSET - 1)	@ r6 = number of sections
-	mov	r6, r6, lsr #20			@ needed for kernel minus 1
-
-1:	add	r3, r3, #1 << 20
-	str	r3, [r0, #4]!
-	subs	r6, r6, #1
-	bgt	1b
+	add	r0, r4,  #(KERNEL_START & 0xff000000) >> 18
+	str	r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
+	ldr	r6, =(KERNEL_END - 1)
+	add	r0, r0, #4
+	add	r6, r4, r6, lsr #18
+1:	cmp	r0, r6
+	add	r3, r3, #1 << 20
+	strls	r3, [r0], #4
+	bls	1b
 
 	/*
 	 * Then map first 1MB of ram in case it contains our boot params.
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index b929a60..ddbdad4 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -156,6 +156,7 @@
 
 		_edata = .;
 	}
+	_edata_loc = __data_loc + SIZEOF(.data);
 
 	.bss : {
 		__bss_start = .;	/* BSS				*/