diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index e5ab51b9cceb..2568d311be21 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -237,7 +237,8 @@ not_relocated:	mov	r0, #0
  */
 		cmp	r4, r2
 		bhs	wont_overwrite
-		add	r0, r4, #4096*1024	@ 4MB largest kernel size
+		sub	r3, sp, r5		@ > compressed kernel size
+		add	r0, r4, r3, lsl #2	@ allow for 4x expansion
 		cmp	r0, r5
 		bls	wont_overwrite
 
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 5365d4e5949e..ebc3e74a7947 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -234,18 +234,18 @@ __create_page_tables:
 
 	/*
 	 * Now setup the pagetables for our kernel direct
-	 * mapped region.  We round TEXTADDR down to the
-	 * nearest megabyte boundary.  It is assumed that
-	 * the kernel fits within 4 contigous 1MB sections.
+	 * mapped region.
 	 */
 	add	r0, r4,  #(TEXTADDR & 0xff000000) >> 18	@ start of kernel
 	str	r3, [r0, #(TEXTADDR & 0x00f00000) >> 18]!
-	add	r3, r3, #1 << 20
-	str	r3, [r0, #4]!			@ KERNEL + 1MB
-	add	r3, r3, #1 << 20
-	str	r3, [r0, #4]!			@ KERNEL + 2MB
-	add	r3, r3, #1 << 20
-	str	r3, [r0, #4]			@ KERNEL + 3MB
+
+	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
 
 	/*
 	 * Then map first 1MB of ram in case it contains our boot params.