diff --git a/xen/arch/arm/arm32/head.S b/xen/arch/arm/arm32/head.S
index c4ee06ba93..4285f76463 100644
--- a/xen/arch/arm/arm32/head.S
+++ b/xen/arch/arm/arm32/head.S
@@ -148,7 +148,19 @@ past_zImage:
 
         mov   r12, #0                /* r12 := is_secondary_cpu */
 
-        b     common_start
+        bl    check_cpu_mode
+        bl    zero_bss
+        bl    cpu_init
+        bl    create_page_tables
+        bl    enable_mmu
+
+        /* We are still in the 1:1 mapping. Jump to the runtime Virtual Address. */
+        ldr   r0, =primary_switched
+        mov   pc, r0
+primary_switched:
+        bl    setup_fixmap
+        b     launch
+ENDPROC(start)
 
 GLOBAL(init_secondary)
         cpsid aif                    /* Disable all interrupts */
@@ -179,8 +191,22 @@ GLOBAL(init_secondary)
         print_reg r7
         PRINT(" booting -\r\n")
 #endif
-
-common_start:
+        bl    check_cpu_mode
+        bl    zero_bss
+        bl    cpu_init
+        bl    create_page_tables
+        bl    enable_mmu
+
+
+        /* We are still in the 1:1 mapping. Jump to the runtime Virtual Address. */
+        ldr   r0, =secondary_switched
+        mov   pc, r0
+secondary_switched:
+        bl    setup_fixmap
+        b     launch
+ENDPROC(init_secondary)
+
+check_cpu_mode:
         /* Check that this CPU has Hyp mode */
         mrc   CP32(r0, ID_PFR1)
         and   r0, r0, #0xf000        /* Bits 12-15 define virt extensions */
@@ -202,7 +228,10 @@ common_start:
         b     fail
 
 hyp:    PRINT("- Xen starting in Hyp mode -\r\n")
+        mov   pc, lr
+ENDPROC(check_cpu_mode)
 
+zero_bss:
         /* Zero BSS On the boot CPU to avoid nasty surprises */
         teq   r12, #0
         bne   skip_bss
@@ -219,8 +248,14 @@ hyp:    PRINT("- Xen starting in Hyp mode -\r\n")
         blo   1b
 
 skip_bss:
+        mov   pc, lr
+ENDPROC(zero_bss)
+
+cpu_init:
         PRINT("- Setting up control registers -\r\n")
 
+        mov   r5, lr                       /* r5 := return address */
+
         /* Get processor specific proc info into r1 */
         bl    __lookup_processor_type
         teq   r1, #0
@@ -231,7 +266,6 @@ skip_bss:
         PRINT(" -\r\n")
         b     fail
 1:
-
         /* Jump to cpu_init */
         ldr   r1, [r1, #PROCINFO_cpu_init]  /* r1 := vaddr(init func) */
         adr   lr, cpu_init_done             /* Save return address */
@@ -256,6 +290,10 @@ cpu_init_done:
         ldr   r0, =HSCTLR_SET
         mcr   CP32(r0, HSCTLR)
 
+        mov   pc, r5                        /* Return address is in r5 */
+ENDPROC(cpu_init)
+
+create_page_tables:
         /*
          * Rebuild the boot pagetable's first-level entries. The structure
          * is described in mm.c.
@@ -359,15 +397,16 @@ cpu_init_done:
         /* boot pagetable setup complete */
 
         cmp   r6, #1                /* Did we manage to create an identity mapping ? */
-        beq   1f
+        moveq pc, lr
         PRINT("Unable to build boot page tables - Failed to identity map Xen.\r\n")
         b     fail
 virtphys_clash:
         /* Identity map clashes with boot_third, which we cannot handle yet */
         PRINT("- Unable to build boot page tables - virt and phys addresses clash. -\r\n")
         b     fail
+ENDPROC(create_page_tables)
 
-1:
+enable_mmu:
         PRINT("- Turning on paging -\r\n")
 
         /*
@@ -377,16 +416,16 @@ virtphys_clash:
         mcr   CP32(r0, TLBIALLH)     /* Flush hypervisor TLBs */
         dsb   nsh
 
-        ldr   r1, =paging            /* Explicit vaddr, not RIP-relative */
         mrc   CP32(r0, HSCTLR)
         /* Enable MMU and D-cache */
         orr   r0, r0, #(SCTLR_Axx_ELx_M|SCTLR_Axx_ELx_C)
         dsb                          /* Flush PTE writes and finish reads */
         mcr   CP32(r0, HSCTLR)       /* now paging is enabled */
         isb                          /* Now, flush the icache */
-        mov   pc, r1                 /* Get a proper vaddr into PC */
-paging:
+        mov   pc, lr
+ENDPROC(enable_mmu)
 
+setup_fixmap:
         /*
          * Now we can install the fixmap and dtb mappings, since we
          * don't need the 1:1 map any more
@@ -436,12 +475,15 @@ paging:
         mcr   CP32(r0, TLBIALLH)     /* Flush hypervisor TLB */
         dsb                          /* Ensure completion of TLB flush */
         isb
+        mov   pc, lr
+ENDPROC(setup_fixmap)
 
+launch:
         PRINT("- Ready -\r\n")
 
         /* The boot CPU should go straight into C now */
         teq   r12, #0
-        beq   launch
+        beq   1f
 
         /*
          * Non-boot CPUs need to move on to the proper pagetables, which were
@@ -460,7 +502,7 @@ paging:
         dsb                          /* Ensure completion of TLB+BP flush */
         isb
 
-launch:
+1:
         ldr   r0, =init_data
         add   r0, #INITINFO_stack    /* Find the boot-time stack */
         ldr   sp, [r0]
@@ -471,6 +513,7 @@ launch:
         moveq r1, r8                 /*               - DTB address */
         beq   start_xen              /* and disappear into the land of C */
         b     start_secondary        /* (to the appropriate entry point) */
+ENDPROC(launch)
 
 /* Fail-stop */
 fail:   PRINT("- Boot failed -\r\n")
