At the moment, Xen is relocated towards the end of the memory. While
this has the advantage to free space in low memory, the code is not
compliant with the break-before-make because it requires to switch
between two sets of page-table. This is not entirely trivial to fix as
it would require us to go through an identity mapping and disabling MMU.
Furthermore, it looks like that some platform (such as the Hikey960)
may not be able to bring-up secondary CPUs if the entry is too high.
I don't believe the low memory is an issue because Xen is quite tiny
(< 2MB). So the best solution is to stop relocating Xen. This has the
advantage to simplify the code and should speed-up the boot as relocation
is not necessary anymore.
Note that the break-before-make issue is not fixed by this patch.
Signed-off-by: Julien Grall <julien.gr...@arm.com>
Reported-by: Matthew Daley <ma...@bugfuzz.com>
---
xen/arch/arm/arm32/head.S | 54 +++------------------------------------
xen/arch/arm/arm64/head.S | 50 +++++-------------------------------
xen/arch/arm/mm.c | 20 ++++-----------
xen/arch/arm/setup.c | 65 +++--------------------------------------------
xen/include/asm-arm/mm.h | 2 +-
5 files changed, 18 insertions(+), 173 deletions(-)
diff --git a/xen/arch/arm/arm32/head.S b/xen/arch/arm/arm32/head.S
index 93b51e9ef2..390a505e05 100644
--- a/xen/arch/arm/arm32/head.S
+++ b/xen/arch/arm/arm32/head.S
@@ -469,58 +469,12 @@ fail: PRINT("- Boot failed -\r\n")
GLOBAL(_end_boot)
/*
- * Copy Xen to new location and switch TTBR
+ * Switch TTBR
* r1:r0 ttbr
- * r2 source address
- * r3 destination address
- * [sp]=>r4 length
*
- * Source and destination must be word aligned, length is rounded up
- * to a 16 byte boundary.
- *
- * MUST BE VERY CAREFUL when saving things to RAM over the copy
+ * TODO: This code does not comply with break-before-make.
*/
-ENTRY(relocate_xen)
- push {r4,r5,r6,r7,r8,r9,r10,r11}
-
- ldr r4, [sp, #8*4] /* Get 4th argument from stack */
-
- /* Copy 16 bytes at a time using:
- * r5: counter
- * r6: data
- * r7: data
- * r8: data
- * r9: data
- * r10: source
- * r11: destination
- */
- mov r5, r4
- mov r10, r2
- mov r11, r3
-1: ldmia r10!, {r6, r7, r8, r9}
- stmia r11!, {r6, r7, r8, r9}
-
- subs r5, r5, #16
- bgt 1b
-
- /* Flush destination from dcache using:
- * r5: counter
- * r6: step
- * r7: vaddr
- */
- dsb /* So the CPU issues all writes to the range */
-
- mov r5, r4
- ldr r6, =dcache_line_bytes /* r6 := step */
- ldr r6, [r6]
- mov r7, r3
-
-1: mcr CP32(r7, DCCMVAC)
-
- add r7, r7, r6
- subs r5, r5, r6
- bgt 1b
-
+ENTRY(switch_ttbr)
dsb /* Ensure the flushes happen before
* continuing */
isb /* Ensure synchronization with previous
@@ -543,8 +497,6 @@ ENTRY(relocate_xen)
dsb /* Ensure completion of TLB+BP flush */
isb
- pop {r4, r5,r6,r7,r8,r9,r10,r11}
-
mov pc, lr
#ifdef CONFIG_EARLY_PRINTK
diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S
index 9428c3f5a2..4589a37874 100644
--- a/xen/arch/arm/arm64/head.S
+++ b/xen/arch/arm/arm64/head.S
@@ -605,52 +605,14 @@ fail: PRINT("- Boot failed -\r\n")
GLOBAL(_end_boot)
-/* Copy Xen to new location and switch TTBR
- * x0 ttbr
- * x1 source address
- * x2 destination address
- * x3 length
+/*
+ * Switch TTBR
*
- * Source and destination must be word aligned, length is rounded up
- * to a 16 byte boundary.
+ * x0 ttbr
*
- * MUST BE VERY CAREFUL when saving things to RAM over the copy */
-ENTRY(relocate_xen)
- /* Copy 16 bytes at a time using:
- * x9: counter
- * x10: data
- * x11: data
- * x12: source
- * x13: destination
- */
- mov x9, x3
- mov x12, x1
- mov x13, x2
-
-1: ldp x10, x11, [x12], #16
- stp x10, x11, [x13], #16
-
- subs x9, x9, #16
- bgt 1b
-
- /* Flush destination from dcache using:
- * x9: counter
- * x10: step
- * x11: vaddr
- */
- dsb sy /* So the CPU issues all writes to the range */
-
- mov x9, x3
- ldr x10, =dcache_line_bytes /* x10 := step */
- ldr x10, [x10]
- mov x11, x2
-
-1: dc cvac, x11
-
- add x11, x11, x10
- subs x9, x9, x10
- bgt 1b
-
+ * TODO: This code does not comply with break-before-make.
+ */
+ENTRY(switch_ttbr)
dsb sy /* Ensure the flushes happen before
* continuing */
isb /* Ensure synchronization with previous
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 2556e57a99..f6931e007f 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -601,7 +601,7 @@ void __init remove_early_mappings(void)
flush_xen_data_tlb_range_va(BOOT_FDT_VIRT_START, BOOT_FDT_SLOT_SIZE);
}
-extern void relocate_xen(uint64_t ttbr, void *src, void *dst, size_t len);
+extern void switch_ttbr(uint64_t ttbr);
/* Clear a translation table and clean & invalidate the cache */
static void clear_table(void *table)
@@ -612,15 +612,13 @@ static void clear_table(void *table)
/* Boot-time pagetable setup.
* Changes here may need matching changes in head.S */
-void __init setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr)
+void __init setup_pagetables(unsigned long boot_phys_offset)
{
uint64_t ttbr;
- unsigned long dest_va;
lpae_t pte, *p;
int i;
- /* Calculate virt-to-phys offset for the new location */
- phys_offset = xen_paddr - (unsigned long) _start;
+ phys_offset = boot_phys_offset;
#ifdef CONFIG_ARM_64
p = (void *) xen_pgtable;
@@ -652,7 +650,7 @@ void __init setup_pagetables(unsigned long
boot_phys_offset, paddr_t xen_paddr)
/* Break up the Xen mapping into 4k pages and protect them separately. */
for ( i = 0; i < LPAE_ENTRIES; i++ )
{
- mfn_t mfn = mfn_add(maddr_to_mfn(xen_paddr), i);
+ mfn_t mfn = mfn_add(maddr_to_mfn((vaddr_t)_start + phys_offset), i);