]> xenbits.xensource.com Git - people/andrewcoop/xen.git/commitdiff
xen/arm32: head: Improve logging in head.S
authorJulien Grall <jgrall@amazon.com>
Fri, 12 Jan 2024 11:54:31 +0000 (11:54 +0000)
committerJulien Grall <jgrall@amazon.com>
Fri, 12 Jan 2024 11:54:49 +0000 (11:54 +0000)
The sequence to enable the MMU on arm32 is quite complex as we may need
to jump to a temporary mapping to map Xen.

Recently, we had one bug in the logic (see f5a49eb7f8b3 ("xen/arm32:
head: Add mising isb in switch_to_runtime_mapping()") and it was
a pain to debug because there are no logging.

In order to improve the logging in the MMU switch we need to add
support for early printk while running on the identity mapping
and also on the temporary mapping.

For the identity mapping, we have only the first page of Xen mapped.
So all the strings should reside in the first page. For that purpose
a new macro PRINT_ID is introduced.

For the temporary mapping, the fixmap is already linked in the temporary
area (and so does the UART). So we just need to update the register
storing the UART address (i.e. r11) to point to the UART temporary
mapping.

Take the opportunity to introduce mov_w_on_cond in order to
conditionally execute mov_w and avoid branches.

Signed-off-by: Julien Grall <jgrall@amazon.com>
Reviewed-by: Michal Orzel <michal.orzel@amd.com>
xen/arch/arm/arm32/head.S
xen/arch/arm/arm32/mmu/head.S
xen/arch/arm/include/asm/arm32/macros.h
xen/arch/arm/include/asm/asm_defns.h
xen/arch/arm/include/asm/early_printk.h
xen/arch/arm/include/asm/mmu/layout.h
xen/arch/arm/mmu/setup.c
xen/arch/arm/xen.lds.S

index 34ab14a9e228d53455793da33a7dd62c2143bc94..99d7d4aa63d1521fdeef150f5c1cb8e3d0136c4b 100644 (file)
@@ -98,10 +98,6 @@ past_zImage:
         b     enable_boot_cpu_mm
 
 primary_switched:
-#ifdef CONFIG_EARLY_PRINTK
-        /* Use a virtual address to access the UART. */
-        mov_w r11, EARLY_UART_VIRTUAL_ADDRESS
-#endif
         bl    zero_bss
         PRINT("- Ready -\r\n")
         /* Setup the arguments for start_xen and jump to C world */
@@ -142,12 +138,7 @@ GLOBAL(init_secondary)
 
         mov_w lr, secondary_switched
         b     enable_secondary_cpu_mm
-
 secondary_switched:
-#ifdef CONFIG_EARLY_PRINTK
-        /* Use a virtual address to access the UART. */
-        mov_w r11, EARLY_UART_VIRTUAL_ADDRESS
-#endif
         PRINT("- Ready -\r\n")
         /* Jump to C world */
         mov_w r2, start_secondary
index bb3980843ad0cdd1cb7a97d164e77ac849485bb0..1e2bbf0c82e9b3602f5b44e59e00b274c7f683bb 100644 (file)
@@ -298,6 +298,21 @@ enable_mmu:
         mcr   CP32(r0, HSCTLR)       /* now paging is enabled */
         isb                          /* Now, flush the icache */
 
+        /*
+         * At this stage, the UART address will depend on whether the
+         * temporary mapping was created or not.
+         *
+         * If it was, then the UART will be mapped in the temporary
+         * area. Otherwise, it will be mapped at runtime virtual
+         * mapping.
+         */
+#ifdef CONFIG_EARLY_PRINTK
+        teq   r12, #1               /* Was the temporary mapping created? */
+        mov_w_on_cond eq, r11, TEMPORARY_EARLY_UART_VIRTUAL_ADDRESS
+        mov_w_on_cond ne, r11, EARLY_UART_VIRTUAL_ADDRESS
+#endif
+        PRINT_ID("- Paging turned on -\r\n")
+
         /*
          * The MMU is turned on and we are in the 1:1 mapping. Switch
          * to the runtime mapping.
@@ -307,6 +322,17 @@ enable_mmu:
         b     switch_to_runtime_mapping
 1:
         mov   lr, r5                /* Restore LR */
+
+        /*
+         * Now we are running at the runtime address. The UART can
+         * be accessed using its runtime virtual address.
+         */
+#ifdef CONFIG_EARLY_PRINTK
+        mov_w r11, EARLY_UART_VIRTUAL_ADDRESS
+#endif
+
+        PRINT("- Switched to the runtime mapping -\r\n")
+
         /*
          * At this point, either the 1:1 map or the temporary mapping
          * will be present. The former may clash with other parts of the
@@ -348,12 +374,14 @@ switch_to_runtime_mapping:
         teq   r12, #0
         beq   ready_to_switch
 
+        PRINT_ID("- Switching to the temporary mapping -\r\n")
         /* We are still in the 1:1 mapping. Jump to the temporary Virtual address. */
         mov_w r0, 1f
         add   r0, r0, #XEN_TEMPORARY_OFFSET /* r0 := address in temporary mapping */
         mov   pc, r0
 
 1:
+        PRINT("- Running on the temporary mapping  -\r\n")
         /* Remove boot_second_id */
         mov   r2, #0
         mov   r3, #0
@@ -364,6 +392,8 @@ switch_to_runtime_mapping:
 
         flush_xen_tlb_local r0
 
+        PRINT("- 1:1 mapping removed -\r\n")
+
         /* Map boot_second into boot_pgtable */
         mov_w r0, XEN_VIRT_START
         create_table_entry boot_pgtable, boot_second, r0, 1
@@ -376,7 +406,10 @@ switch_to_runtime_mapping:
          */
         isb
 
+        PRINT("- Runtime mapping mapped -\r\n")
 ready_to_switch:
+        PRINT_ID("- Jumping to runtime address -\r\n")
+
         mov   pc, lr
 ENDPROC(switch_to_runtime_mapping)
 
@@ -404,6 +437,8 @@ ENTRY(enable_secondary_cpu_mm)
         mov_w lr, 1f
         b     enable_mmu
 1:
+        PRINT("- Switching to the runtime page-tables -\r\n")
+
         /*
          * Non-boot CPUs need to move on to the proper pagetables, which were
          * setup in prepare_secondary_mm.
@@ -469,6 +504,8 @@ ENDPROC(enable_boot_cpu_mm)
  * Clobbers r0 - r3
  */
 remove_identity_mapping:
+        PRINT("- Removing the identity mapping -\r\n")
+
         /* r2:r3 := invalid page-table entry */
         mov   r2, #0x0
         mov   r3, #0x0
@@ -489,6 +526,8 @@ ENDPROC(remove_identity_mapping)
  * Clobbers r0 - r3
  */
 remove_temporary_mapping:
+        PRINT("- Removing the temporary mapping -\r\n")
+
         /* r2:r3 := invalid page-table entry */
         mov   r2, #0
         mov   r3, #0
index b84666c764d4f7b7fd7136b44ed1ab164207fd79..db681a7c7eaaacffb77f250aeb695739dae23b5a 100644 (file)
@@ -9,9 +9,13 @@
  * Move an immediate constant into a 32-bit register using movw/movt
  * instructions.
  */
+.macro mov_w_on_cond cond, reg, word
+        movw\cond  \reg, #:lower16:\word
+        movt\cond  \reg, #:upper16:\word
+.endm
+
 .macro mov_w reg, word
-        movw  \reg, #:lower16:\word
-        movt  \reg, #:upper16:\word
+        mov_w_on_cond al, \reg, \word
 .endm
 
 /*
 
 #ifdef CONFIG_EARLY_PRINTK
 /*
- * Macro to print a string to the UART, if there is one.
+ * Macros to print a string to the UART, if there is one.
+ *
+ * There are multiple flavors:
+ *  - PRINT_SECT(section, string): The @string will be located in @section
+ *  - PRINT(): The string will be located in .rodata.str.
+ *  - PRINT_ID(): When Xen is running on the Identity Mapping, it is
+ *    only possible to have a limited amount of Xen. This will create
+ *    the string in .rodata.idmap which will always be mapped.
  *
  * Clobbers r0 - r3
  */
-#define PRINT(_s)           \
-        mov   r3, lr       ;\
-        adr_l r0, 98f      ;\
-        bl    asm_puts     ;\
-        mov   lr, r3       ;\
-        RODATA_STR(98, _s)
+#define PRINT_SECT(section, string)         \
+        mov   r3, lr                       ;\
+        adr_l r0, 98f                      ;\
+        bl    asm_puts                     ;\
+        mov   lr, r3                       ;\
+        RODATA_SECT(section, 98, string)
+
+#define PRINT(string) PRINT_SECT(.rodata.str, string)
+#define PRINT_ID(string) PRINT_SECT(.rodata.idmap, string)
 
 /*
  * Macro to print the value of register \rb
@@ -54,6 +68,7 @@
 
 #else /* CONFIG_EARLY_PRINTK */
 #define PRINT(s)
+#define PRINT_ID(s)
 
 .macro print_reg rb
 .endm
index 29a9dbb002fafb0b215f59a2088531891d582c2f..ec803c0a370c3dfe741de37f9218c944e12bfe0d 100644 (file)
 # error "unknown ARM variant"
 #endif
 
-#define RODATA_STR(label, msg)                  \
-.pushsection .rodata.str, "aMS", %progbits, 1 ; \
+#define RODATA_SECT(section, label, msg)         \
+.pushsection section, "aMS", %progbits, 1 ;     \
 label:  .asciz msg;                             \
 .popsection
 
+#define RODATA_STR(label, msg) RODATA_SECT(.rodata.str, label, msg)
+
 #define ASM_INT(label, val)                 \
     .p2align 2;                             \
 label: .long (val);                         \
index c5149b2976dae75febfde38f650038059539b98a..c1e84f8b00097891d57244e9580af7989329723f 100644 (file)
@@ -19,6 +19,9 @@
 #define EARLY_UART_VIRTUAL_ADDRESS \
     (FIXMAP_ADDR(FIXMAP_CONSOLE) + (CONFIG_EARLY_UART_BASE_ADDRESS & ~PAGE_MASK))
 
+#define TEMPORARY_EARLY_UART_VIRTUAL_ADDRESS \
+    (TEMPORARY_FIXMAP_ADDR(FIXMAP_CONSOLE) + (CONFIG_EARLY_UART_BASE_ADDRESS & ~PAGE_MASK))
+
 #endif /* !CONFIG_EARLY_PRINTK */
 
 #endif
index eac7eef885d60a1ab49d62dc50d7d7790bc101dc..a3b546465b5ab3ed72760763e930c33d1117d1d7 100644 (file)
       (TEMPORARY_AREA_FIRST_SLOT << XEN_PT_LEVEL_SHIFT(1)))
 
 #define TEMPORARY_XEN_VIRT_START    TEMPORARY_AREA_ADDR(XEN_VIRT_START)
+#define TEMPORARY_FIXMAP_VIRT_START TEMPORARY_AREA_ADDR(FIXMAP_VIRT_START)
+
+#define TEMPORARY_FIXMAP_ADDR(n)                    \
+     (TEMPORARY_FIXMAP_VIRT_START + (n) * PAGE_SIZE)
 
 #else /* ARM_64 */
 
index d5264e51bc443e7eadbb3516d2fa7426dad681dc..72725840b6b75cfe3f3cc8a65d029ccb792480aa 100644 (file)
@@ -120,7 +120,10 @@ static void __init __maybe_unused build_assertions(void)
 #ifdef CONFIG_ARM_32
     CHECK_SAME_SLOT(first, TEMPORARY_XEN_VIRT_START, DOMHEAP_VIRT_START);
     CHECK_DIFFERENT_SLOT(first, XEN_VIRT_START, TEMPORARY_XEN_VIRT_START);
+    CHECK_SAME_SLOT(first, TEMPORARY_XEN_VIRT_START,
+                    TEMPORARY_FIXMAP_VIRT_START);
     CHECK_SAME_SLOT(second, XEN_VIRT_START, TEMPORARY_XEN_VIRT_START);
+    CHECK_SAME_SLOT(second, FIXMAP_VIRT_START, TEMPORARY_FIXMAP_VIRT_START);
 #endif
 
 #undef CHECK_SAME_SLOT
index 59b80d122fd085d06704325ee50ad451c858d69f..20598c6963cee7b312865256ef2b43685a4f8500 100644 (file)
@@ -35,6 +35,7 @@ SECTIONS
        _idmap_start = .;
        *(.text.header)
        *(.text.idmap)
+       *(.rodata.idmap)
        _idmap_end = .;
 
        *(.text.cold)