Skip to content

Commit

Permalink
xen/arm32: head: Improve logging in head.S
Browse files Browse the repository at this point in the history
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 f5a49eb ("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 <[email protected]>
Reviewed-by: Michal Orzel <[email protected]>
  • Loading branch information
Julien Grall committed Jan 12, 2024
1 parent 4108371 commit 1ec3fe1
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 20 deletions.
9 changes: 0 additions & 9 deletions xen/arch/arm/arm32/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down
39 changes: 39 additions & 0 deletions xen/arch/arm/arm32/mmu/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
33 changes: 24 additions & 9 deletions xen/arch/arm/include/asm/arm32/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

/*
Expand All @@ -29,16 +33,26 @@

#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
Expand All @@ -54,6 +68,7 @@

#else /* CONFIG_EARLY_PRINTK */
#define PRINT(s)
#define PRINT_ID(s)

.macro print_reg rb
.endm
Expand Down
6 changes: 4 additions & 2 deletions xen/arch/arm/include/asm/asm_defns.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@
# 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); \
Expand Down
3 changes: 3 additions & 0 deletions xen/arch/arm/include/asm/early_printk.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions xen/arch/arm/include/asm/mmu/layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@
(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 */

Expand Down
3 changes: 3 additions & 0 deletions xen/arch/arm/mmu/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions xen/arch/arm/xen.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ SECTIONS
_idmap_start = .;
*(.text.header)
*(.text.idmap)
*(.rodata.idmap)
_idmap_end = .;

*(.text.cold)
Expand Down

0 comments on commit 1ec3fe1

Please sign in to comment.