Message ID | 20231101233011.83098-3-julien@xen.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | xen/arm32: Improve logging during early boot | expand |
Hi Julien, On 02/11/2023 00:30, Julien Grall wrote: > > > From: Julien Grall <jgrall@amazon.com> > > 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 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> > --- > xen/arch/arm/arm32/head.S | 68 ++++++++++++++++++++----- > xen/arch/arm/include/asm/asm_defns.h | 6 ++- > xen/arch/arm/include/asm/early_printk.h | 3 ++ > xen/arch/arm/include/asm/mmu/layout.h | 4 ++ > xen/arch/arm/mm.c | 5 ++ > xen/arch/arm/xen.lds.S | 1 + > 6 files changed, 71 insertions(+), 16 deletions(-) > > diff --git a/xen/arch/arm/arm32/head.S b/xen/arch/arm/arm32/head.S > index fec2433e568f..bd61521a9dea 100644 > --- a/xen/arch/arm/arm32/head.S > +++ b/xen/arch/arm/arm32/head.S > @@ -46,9 +46,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 > > /* > @@ -104,16 +108,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 puts ;\ > - mov lr, r3 ;\ > - RODATA_STR(98, _s) > +#define PRINT_SECT(section, string) \ > + mov r3, lr ;\ > + adr_l r0, 98f ;\ > + bl 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 > @@ -129,6 +143,7 @@ > > #else /* CONFIG_EARLY_PRINTK */ > #define PRINT(s) > +#define PRINT_ID(s) > > .macro print_reg rb > .endm > @@ -183,11 +198,6 @@ past_zImage: > bl check_cpu_mode > bl cpu_init > bl create_page_tables > - /* Add the UART mapping if requested */ > -#ifdef CONFIG_EARLY_PRINTK > - mov_w r0, EARLY_UART_VIRTUAL_ADDRESS > - create_mapping_entry xen_fixmap, r0, r11, type=PT_DEV_L3 > -#endif I think that patch no.1 should move the mapping into init_uart right away. This way the issue I mentioned in that patch will be fixed and there will be no need to remove the code introduced just before. > > /* Address in the runtime mapping to jump to after the MMU is enabled */ > mov_w lr, primary_switched > @@ -593,6 +603,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 Shouldn't the clobber list be updated? > + 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. > @@ -643,12 +668,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 > @@ -659,6 +686,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 > @@ -671,7 +700,10 @@ switch_to_runtime_mapping: > */ > isb > > + PRINT("- Runtime mapping mapped -\r\n") > ready_to_switch: > + PRINT("- Jumping to runtime address -\r\n") This is causing a boot hang in a configuration where there is no need for temporary mapping. In that case, we are still in 1:1 map and should use PRINT_ID > + > mov pc, lr > ENDPROC(switch_to_runtime_mapping) > > @@ -795,6 +827,14 @@ init_uart: > early_uart_init r11, r1, r2 > #endif > PRINT("- UART enabled -\r\n") > + > + /* > + * Add the UART mapping to the fixmap so the UART can be used > + * as the MMU is on. > + */ > + mov_w r0, EARLY_UART_VIRTUAL_ADDRESS > + create_mapping_entry xen_fixmap, r0, r11, type=PT_DEV_L3 Shouldn't the clobber list be updated to include r4? > + > mov pc, lr > ENDPROC(init_uart) > > diff --git a/xen/arch/arm/include/asm/asm_defns.h b/xen/arch/arm/include/asm/asm_defns.h > index 29a9dbb002fa..ec803c0a370c 100644 > --- a/xen/arch/arm/include/asm/asm_defns.h > +++ b/xen/arch/arm/include/asm/asm_defns.h > @@ -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); \ > diff --git a/xen/arch/arm/include/asm/early_printk.h b/xen/arch/arm/include/asm/early_printk.h > index c5149b2976da..c1e84f8b0009 100644 > --- a/xen/arch/arm/include/asm/early_printk.h > +++ b/xen/arch/arm/include/asm/early_printk.h > @@ -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 > diff --git a/xen/arch/arm/include/asm/mmu/layout.h b/xen/arch/arm/include/asm/mmu/layout.h > index da6be276ac5f..68855c4f3184 100644 > --- a/xen/arch/arm/include/asm/mmu/layout.h > +++ b/xen/arch/arm/include/asm/mmu/layout.h > @@ -113,6 +113,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 */ > > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c > index c34cc94c907a..6ffa45c53be6 100644 > --- a/xen/arch/arm/mm.c > +++ b/xen/arch/arm/mm.c > @@ -193,7 +193,12 @@ 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(first, TEMPORARY_XEN_VIRT_START, > + TEMPORARY_FIXMAP_VIRT_START); duplicated entry? ~Michal
On 02/11/2023 10:23, Michal Orzel wrote: > Hi Julien, Hi Michal, > On 02/11/2023 00:30, Julien Grall wrote: >> >> >> From: Julien Grall <jgrall@amazon.com> >> >> 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 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> >> --- >> xen/arch/arm/arm32/head.S | 68 ++++++++++++++++++++----- >> xen/arch/arm/include/asm/asm_defns.h | 6 ++- >> xen/arch/arm/include/asm/early_printk.h | 3 ++ >> xen/arch/arm/include/asm/mmu/layout.h | 4 ++ >> xen/arch/arm/mm.c | 5 ++ >> xen/arch/arm/xen.lds.S | 1 + >> 6 files changed, 71 insertions(+), 16 deletions(-) >> >> diff --git a/xen/arch/arm/arm32/head.S b/xen/arch/arm/arm32/head.S >> index fec2433e568f..bd61521a9dea 100644 >> --- a/xen/arch/arm/arm32/head.S >> +++ b/xen/arch/arm/arm32/head.S >> @@ -46,9 +46,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 >> >> /* >> @@ -104,16 +108,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 puts ;\ >> - mov lr, r3 ;\ >> - RODATA_STR(98, _s) >> +#define PRINT_SECT(section, string) \ >> + mov r3, lr ;\ >> + adr_l r0, 98f ;\ >> + bl 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 >> @@ -129,6 +143,7 @@ >> >> #else /* CONFIG_EARLY_PRINTK */ >> #define PRINT(s) >> +#define PRINT_ID(s) >> >> .macro print_reg rb >> .endm >> @@ -183,11 +198,6 @@ past_zImage: >> bl check_cpu_mode >> bl cpu_init >> bl create_page_tables >> - /* Add the UART mapping if requested */ >> -#ifdef CONFIG_EARLY_PRINTK >> - mov_w r0, EARLY_UART_VIRTUAL_ADDRESS >> - create_mapping_entry xen_fixmap, r0, r11, type=PT_DEV_L3 >> -#endif > I think that patch no.1 should move the mapping into init_uart right away. This way > the issue I mentioned in that patch will be fixed and there will be no need to remove the code > introduced just before. Correct. I folded the fix in the wrong patch. > >> >> /* Address in the runtime mapping to jump to after the MMU is enabled */ >> mov_w lr, primary_switched >> @@ -593,6 +603,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 > Shouldn't the clobber list be updated? > >> + 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. >> @@ -643,12 +668,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 >> @@ -659,6 +686,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 >> @@ -671,7 +700,10 @@ switch_to_runtime_mapping: >> */ >> isb >> >> + PRINT("- Runtime mapping mapped -\r\n") >> ready_to_switch: >> + PRINT("- Jumping to runtime address -\r\n") > This is causing a boot hang in a configuration where there is no need for temporary mapping. > In that case, we are still in 1:1 map and should use PRINT_ID Good point. I will switch. > >> + >> mov pc, lr >> ENDPROC(switch_to_runtime_mapping) >> >> @@ -795,6 +827,14 @@ init_uart: >> early_uart_init r11, r1, r2 >> #endif >> PRINT("- UART enabled -\r\n") >> + >> + /* >> + * Add the UART mapping to the fixmap so the UART can be used >> + * as the MMU is on. >> + */ >> + mov_w r0, EARLY_UART_VIRTUAL_ADDRESS >> + create_mapping_entry xen_fixmap, r0, r11, type=PT_DEV_L3 > Shouldn't the clobber list be updated to include r4? It should. > >> + >> mov pc, lr >> ENDPROC(init_uart) >> >> diff --git a/xen/arch/arm/include/asm/asm_defns.h b/xen/arch/arm/include/asm/asm_defns.h >> index 29a9dbb002fa..ec803c0a370c 100644 >> --- a/xen/arch/arm/include/asm/asm_defns.h >> +++ b/xen/arch/arm/include/asm/asm_defns.h >> @@ -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); \ >> diff --git a/xen/arch/arm/include/asm/early_printk.h b/xen/arch/arm/include/asm/early_printk.h >> index c5149b2976da..c1e84f8b0009 100644 >> --- a/xen/arch/arm/include/asm/early_printk.h >> +++ b/xen/arch/arm/include/asm/early_printk.h >> @@ -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 >> diff --git a/xen/arch/arm/include/asm/mmu/layout.h b/xen/arch/arm/include/asm/mmu/layout.h >> index da6be276ac5f..68855c4f3184 100644 >> --- a/xen/arch/arm/include/asm/mmu/layout.h >> +++ b/xen/arch/arm/include/asm/mmu/layout.h >> @@ -113,6 +113,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 */ >> >> diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c >> index c34cc94c907a..6ffa45c53be6 100644 >> --- a/xen/arch/arm/mm.c >> +++ b/xen/arch/arm/mm.c >> @@ -193,7 +193,12 @@ 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(first, TEMPORARY_XEN_VIRT_START, >> + TEMPORARY_FIXMAP_VIRT_START); > duplicated entry? Yes it is duplicated. Cheers,
On 02/11/2023 10:23, Michal Orzel wrote: >> /* Address in the runtime mapping to jump to after the MMU is enabled */ >> mov_w lr, primary_switched >> @@ -593,6 +603,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 > Shouldn't the clobber list be updated? I missed this comment. I understand it will get clobbered today, but thinking a bit more, I would actually prefer if r11 is updated to EARLY_UART_ADDRESS just right after calling switch_to_runtime_mapping. So we can add more prints in remove_identity_mapping() and remove_temporary_mapping(). I will have a look to update this patch. Cheers,
diff --git a/xen/arch/arm/arm32/head.S b/xen/arch/arm/arm32/head.S index fec2433e568f..bd61521a9dea 100644 --- a/xen/arch/arm/arm32/head.S +++ b/xen/arch/arm/arm32/head.S @@ -46,9 +46,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 /* @@ -104,16 +108,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 puts ;\ - mov lr, r3 ;\ - RODATA_STR(98, _s) +#define PRINT_SECT(section, string) \ + mov r3, lr ;\ + adr_l r0, 98f ;\ + bl 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 @@ -129,6 +143,7 @@ #else /* CONFIG_EARLY_PRINTK */ #define PRINT(s) +#define PRINT_ID(s) .macro print_reg rb .endm @@ -183,11 +198,6 @@ past_zImage: bl check_cpu_mode bl cpu_init bl create_page_tables - /* Add the UART mapping if requested */ -#ifdef CONFIG_EARLY_PRINTK - mov_w r0, EARLY_UART_VIRTUAL_ADDRESS - create_mapping_entry xen_fixmap, r0, r11, type=PT_DEV_L3 -#endif /* Address in the runtime mapping to jump to after the MMU is enabled */ mov_w lr, primary_switched @@ -593,6 +603,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. @@ -643,12 +668,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 @@ -659,6 +686,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 @@ -671,7 +700,10 @@ switch_to_runtime_mapping: */ isb + PRINT("- Runtime mapping mapped -\r\n") ready_to_switch: + PRINT("- Jumping to runtime address -\r\n") + mov pc, lr ENDPROC(switch_to_runtime_mapping) @@ -795,6 +827,14 @@ init_uart: early_uart_init r11, r1, r2 #endif PRINT("- UART enabled -\r\n") + + /* + * Add the UART mapping to the fixmap so the UART can be used + * as the MMU is on. + */ + mov_w r0, EARLY_UART_VIRTUAL_ADDRESS + create_mapping_entry xen_fixmap, r0, r11, type=PT_DEV_L3 + mov pc, lr ENDPROC(init_uart) diff --git a/xen/arch/arm/include/asm/asm_defns.h b/xen/arch/arm/include/asm/asm_defns.h index 29a9dbb002fa..ec803c0a370c 100644 --- a/xen/arch/arm/include/asm/asm_defns.h +++ b/xen/arch/arm/include/asm/asm_defns.h @@ -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); \ diff --git a/xen/arch/arm/include/asm/early_printk.h b/xen/arch/arm/include/asm/early_printk.h index c5149b2976da..c1e84f8b0009 100644 --- a/xen/arch/arm/include/asm/early_printk.h +++ b/xen/arch/arm/include/asm/early_printk.h @@ -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 diff --git a/xen/arch/arm/include/asm/mmu/layout.h b/xen/arch/arm/include/asm/mmu/layout.h index da6be276ac5f..68855c4f3184 100644 --- a/xen/arch/arm/include/asm/mmu/layout.h +++ b/xen/arch/arm/include/asm/mmu/layout.h @@ -113,6 +113,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 */ diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index c34cc94c907a..6ffa45c53be6 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -193,7 +193,12 @@ 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(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 diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S index 59b80d122fd0..20598c6963ce 100644 --- a/xen/arch/arm/xen.lds.S +++ b/xen/arch/arm/xen.lds.S @@ -35,6 +35,7 @@ SECTIONS _idmap_start = .; *(.text.header) *(.text.idmap) + *(.rodata.idmap) _idmap_end = .; *(.text.cold)