[PATCH 3/3] RFC: ARM: head: Debug prints for section mappings
Nicolas Pitre
nico at fluxnic.net
Fri Sep 4 11:51:42 EDT 2020
On Fri, 4 Sep 2020, Linus Walleij wrote:
> This creates a facility to print the early 1MB section mappings
> of the kernel. By selecting the symbol CONFIG_DEBUG_EARLY_MAPPINGS
> we can get a printout of some of the early mappings as they
> are written into the swapper_pg_dir page table during very early
> boot.
>
> Currently I introduced hooks for printing the MMU enable 1:1
> mappings, the kernel RAM mappings and the "r2" (ATAGs or DTB)
> mappings.
>
> The debug prints will show the physical address base and the
> virtual address base map, something like this for example:
>
> Uncompressing Linux... done, booting the kernel.
> MMU enable: 0x40300000->0x40300000
> Kernel RAM: 0x40000000->0xc0000000
> Kernel RAM: 0x40100000->0xc0100000
> Kernel RAM: 0x40200000->0xc0200000
> (...)
> Kernel RAM: 0x42500000->0xc2500000
> Kernel RAM: 0x42600000->0xc2600000
> ATAG/DTB : 0x43000000->0xc3000000
> ATAG/DTB : 0x43100000->0xc3100000
>
> This code does not try to be clever and shuffle registers
> around like some puzzle, instead we just store out r1 thru r6
> into memory while printing and read them back afterwards.
> It is debug code anyway, so optimizations are not any concern
> here.
>
> Signed-off-by: Linus Walleij <linus.walleij at linaro.org>
> ---
> arch/arm/Kconfig.debug | 13 ++++-
> arch/arm/kernel/head.S | 109 ++++++++++++++++++++++++++++++++++++++++-
> 2 files changed, 120 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
> index 87912e5c2256..a1620f2d0963 100644
> --- a/arch/arm/Kconfig.debug
> +++ b/arch/arm/Kconfig.debug
> @@ -1919,7 +1919,18 @@ config DEBUG_UNCOMPRESS
> When this option is set, the selected DEBUG_LL output method
> will be re-used for normal decompressor output on multiplatform
> kernels.
> -
> +
> +config DEBUG_EARLY_MAPPINGS
> + bool "Enable early section mapping debugging via DEBUG_LL output"
> + depends on DEBUG_LL
> + help
> + This option enables the kernel to print a list of all the 1 MB
> + section mappings used to map physical to virtual mempory
> + during the early boot. These mappings are used until the
> + kernel sets up the proper page table.
> +
> + The selected DEBUG_LL output method will be used for these debug
> + messages.
>
> config UNCOMPRESS_INCLUDE
> string
> diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
> index 8b089c4c0d17..5758a99f6f0f 100644
> --- a/arch/arm/kernel/head.S
> +++ b/arch/arm/kernel/head.S
> @@ -163,6 +163,109 @@ ENDPROC(stext)
> .long PAGE_OFFSET
> #endif
>
> +#ifdef CONFIG_DEBUG_EARLY_MAPPINGS
> +__debug_tmp:
> + .align
> + .long 0, 0, 0, 0, 0, 0 /* r1 thru r6 */
You shouldn't write to the .text segment. This won't work for XIP as
you'll read 0 back, or worse you'll trigger a flash memory controller
operation. You should allocate your temporary buffer in the .bss section
instead. Look at the printhex code for example.
> +__en_mmu_debug_txt:
> + .asciz "MMU enable: "
> + .align
> +__ram_debug_txt:
> + .asciz "Kernel RAM: "
> + .align
> +__r2_debug_txt:
> + .asciz "ATAG/DTB : "
> + .align
No need to align string starts. This is necessary only after the last
one.
> + /*
> + * This macro prints one physical to virtual section map using
> + * a section descriptor and a section table address
> + */
> + .macro dbg_pr, secd, vindex
> + /* Only the physical address in secd please */
> + bic \secd, \secd, #0x000ff000
> + bic \secd, \secd, #0x00000ff0
> + bic \secd, \secd, #0x0000000f
> + /* Convert the section index to a virtual address */
> + bic \vindex, \vindex, #0xff000000
> + bic \vindex, \vindex, #0x00ff0000
> + bic \vindex, \vindex, #0x0000c000
> + lsr \vindex, \vindex, #PMD_ORDER /* Convert to index */
> + lsl \vindex, \vindex, #SECTION_SHIFT /* Convert to virtual address */
> + mov r0, #'0'
> + bl printch
> + mov r0, #'x'
> + bl printch
> + mov r0, \secd
> + bl printhex8
> + mov r0, #'-'
> + bl printch
> + mov r0, #'>'
> + bl printch
> + mov r0, #'0'
> + bl printch
> + mov r0, #'x'
> + bl printch
Here I'd suggest you add the string "->0x", or even " -> 0x" for
some breathing room, e.g.:
__num_prefix_debug_txt:
.asciz " -> 0x"
Then, with the first number you use:
adr r0, __num_prefix_debug_txt + 4
bl printascii
and no string offset for the second number.
> + mov r0, \vindex
> + bl printhex8
> + mov r0, #'\n'
> + bl printch
> + .endm
> +
> + /*
> + * r3 = current section descriptor, bits 31-20 is the physical address
> + * r5 = section table index
> + */
> + .macro dbg_pr_mmu
> + adr r0, __debug_tmp
> + stmia r0, {r1-r6}
> + mov r6, r3 /* Save r3 to r6 (print corrupts r3) */
> + adr r0, __en_mmu_debug_txt
> + bl printascii
> + /* Print helper wants physical offset index */
> + lsl r5, r5, #PMD_ORDER
> + dbg_pr r6, r5
> + adr r0, __debug_tmp
> + ldmia r0, {r1-r6}
> + .endm
> +
> + /*
> + * r0 = section table index absolute address in physical memory
> + * r3 = current section descriptor, bits 31-20 is the physical address
> + */
> + .macro dbg_pr_ram
> + mov r5, r0 /* Save r0 in r5 */
> + adr r0, __debug_tmp
> + stmia r0, {r1-r6}
> + mov r6, r3 /* Save r3 to r6 (print corrupts r3) */
A long long time ago I had a patch that shuffled registers around so
that the long lived values would be kept in r4 and above so to free
r0-r3 for short lived values and parameter passing to make things easier
when doing this sort of thing. I don't remember if I pushed it to the
patch system, and if I did probably it got outdated and I didn't refresh
it.
> + adr r0, __ram_debug_txt
> + bl printascii
> + dbg_pr r6, r5
> + adr r0, __debug_tmp
> + ldmia r0, {r1-r6}
> + mov r0, r5 /* Restore r0 from r5 */
> + .endm
> +
> + /* Debug text for "what is in r2" either ATAGs or a DTB */
> + .macro dbg_pr_r2
> + adr r0, __debug_tmp
> + stmia r0, {r1-r6}
> + mov r5, r3 /* Save r3 to r5 (print corrupts r3) */
> + adr r0, __r2_debug_txt
> + bl printascii
> + dbg_pr r6, r5
> + adr r0, __debug_tmp
> + ldmia r0, {r1-r6}
> + .endm
> +#else
> + /* Dummy stubs when not debugging */
> + .macro dbg_pr_mmu
> + .endm
> + .macro dbg_pr_ram
> + .endm
> + .macro dbg_pr_r2
> + .endm
> +#endif /* CONFIG_DEBUG_EARLY_MAPPINGS */
> +
> /*
> * Setup the initial page tables. We only setup the barest
> * amount which are required to get the kernel running, which
> @@ -234,6 +337,7 @@ __create_page_tables:
> mov r6, r6, lsr #SECTION_SHIFT
>
> 1: orr r3, r7, r5, lsl #SECTION_SHIFT @ flags + kernel base
> + dbg_pr_mmu
> str r3, [r4, r5, lsl #PMD_ORDER] @ identity mapping
> cmp r5, r6
> addlo r5, r5, #1 @ next section
> @@ -246,7 +350,8 @@ __create_page_tables:
> ldr r6, =(_end - 1)
> orr r3, r8, r7
> add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)
> -1: str r3, [r0], #1 << PMD_ORDER
> +1: dbg_pr_ram
> + str r3, [r0], #1 << PMD_ORDER
> add r3, r3, #1 << SECTION_SHIFT
> cmp r0, r6
> bls 1b
> @@ -281,8 +386,10 @@ __create_page_tables:
> add r3, r3, #PAGE_OFFSET
> add r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
> orr r6, r7, r0
> + dbg_pr_r2
> str r6, [r3], #1 << PMD_ORDER
> add r6, r6, #1 << SECTION_SHIFT
> + dbg_pr_r2
> str r6, [r3]
> 1:
>
> --
> 2.26.2
>
>
More information about the linux-arm-kernel
mailing list