This is the file that I am trying to debug by putting printf/printk statements.
The code is assembly.
79 __HEAD
80 ENTRY(stext)
81 ARM_BE8(setend be ) @ ensure we are in BE8 mode
82
83 THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM.
84 THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
85 THUMB( .thumb ) @ switch to Thumb now.
86 THUMB(1: )
87
88 #ifdef CONFIG_ARM_VIRT_EXT
89 bl __hyp_stub_install
90 #endif
91 @ ensure svc mode and all interrupts masked
92 safe_svcmode_maskall r9
93
94 mrc p15, 0, r9, c0, c0 @ get processor id
95 bl __lookup_processor_type @ r5=procinfo r9=cpuid
96 movs r10, r5 @ invalid processor (r5=0)?
97 THUMB( it eq ) @ force fixup-able long branch encoding
98 beq __error_p @ yes, error 'p'
99
100 #ifdef CONFIG_ARM_LPAE
101 mrc p15, 0, r3, c0, c1, 4 @ read ID_MMFR0
102 and r3, r3, #0xf @ extract VMSA support
103 cmp r3, #5 @ long-descriptor translation table format?
104 THUMB( it lo ) @ force fixup-able long branch encoding
105 blo __error_lpae @ only classic page table format
106 #endif
107
108 #ifndef CONFIG_XIP_KERNEL
109 adr r3,
I simply want to put some messages to console from this file. This code is for ARM.
I tried using printk in such code blocks but it fails to compile.
Any suggestions?
The answer is given in ARM booting FAQ. You need to enable the config menu item Kernel Hacking|Kernel low-level debugging functions. For instance, the code __error_p will then display something on your console UART. For instance, elinux.org's Debugging by printing shows an error message when the kernel can not match your machine id. See: ARM booting documentation
DEBUG_LL creates the function extern void printascii(char *); which you can also instrument vprintk_emit() with.
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1483,6 +1483,8 @@ static size_t cont_print_text(char *text, size_t size)
return textlen;
}
+extern void printascii(char*);
+
asmlinkage int vprintk_emit(int facility, int level,
const char *dict, size_t dictlen,
const char *fmt, va_list args)
@@ -1541,6 +1543,7 @@ asmlinkage int vprintk_emit(int facility, int level,
* prefix which might be passed-in as a parameter.
*/
text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
+ printascii(text);
/* mark and strip a trailing newline */
if (text_len && text[text_len-1] == '\n') {
This and the kernel command line initcall_debug will be useful to diagnose boot issue.
If you platform doesn't support the DEBUG_LL, it is fairly easy to implement the polled UART routines needed to support it.
Normally, printk() is buffered during early boot and doesn't actually print out until the console driver is active. So, without patching the vprintk_emit(), you can crash/halt anywhere before the UART driver runs and see nothing with a normal configuration.
For debugging of head.S and the like, you need to do this in assembler. The error_p implementation has some sample code and here is another,
#ifdef CONFIG_DEBUG_LL
/* Save some registers? */
adr r0, prefix
bl printascii
mov r0, r9
bl printhex8
adr r0, tail
bl printascii
b 1f
prefix: .asciz "\nTrace 1 gives "
tail: .asciz "\n"
1: /* Perhaps halt here, due to register clobbers */
#endif
You are limited in the use of registers depending on the context in head.S. Often the only issue with this code is you didn't do something described in the ARM booting documentation.
You may also use the macros directly which are defined in arch/arm/include/debug. The macros are,
addruart - get the addresses of the uarts to parameter 1 (phys), 2 (virt), (3rd is a tmp for macro).senduart - write character param 1 to address (virtual or physical).waituart - parm 1 (tmp), param 2 address (virt or phys). Ready?busyuart - parm 1 (tmp), param 2 address (virt or phys). Empty?You can see the API in use in the implementation of printasii().
ENTRY(printascii)
addruart_current r3, r1, r2 @ phys address to r3
b 2f
1: waituart r2, r3 @ ready (r2 is tmp, r3 is phys address)
senduart r1, r3 @ transmit r1 character
busyuart r2, r3 @ wait for character to finish tx.
teq r1, #'\n'
moveq r1, #'\r' @ insert carriage return if new line.
beq 1b
2: teq r0, #0 @ NULL pointer?
ldrneb r1, [r0], #1 @ next char
teqne r1, #0 @ end of string?
bne 1b @ send another.
mov pc, lr
ENDPROC(printascii)
In the assembler of head.S and others, you can use the macros with various register arguments to avoid clobbers of in-use registers such as r0-r3. They are usually available for use and printascii() can be called directly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With