RFC: ARM: Disintegrating mach/uncompress.h: low-level debug
cover RFC: ARM: Disintegrating mach/uncompress.h: low-level debug
Hi,
Earlycon is a thin I/O layer used in the early stage of the
kernel loading, before the kernel is decompressed. It provides basic functionality to output characters one by one and flush a queue/buffer.
Such abstraction allows the management of multiple drivers and the runtime selection of the one to be used (ex. "earlyprintk=amba-pl011,0xc1000" on the cmdline). If no suitable driver is found, fallback ops are used.
Mainline implementation of low-level debugging functionality is currently left to the machine specific uncompress.h header file, which greatly limits the usage of the kernel on multiple machines. Hence the need to remove any driver implementation detail from the said headers.
The idea is to collect/refactor the various implementations into separate drivers which can coexist in the same kernel image. In the case of debug UARTs, the natural place for such drivers is the respective kernel serial driver. Some linker magics is used later to inject them into the decompressor.
Here is a minimal (and very commmon) driver example:
static void __earlyconinit minimal_earlycon_putc(struct earlycon_drv *drv, int ch)
{
while (STATUS_REG(drv->base) & BUSY_MASK)
barrier();
DATA_REG(drv->base) = ch;
}EARLYCON_START("minimal-uart")
.putc = minimal_earlycon_putc,EARLYCON_END
The EARLYCON_START's argument ("minimal-uart") is the name used to select this driver during the early boot process. The __earlyconinit and EARLYCON_START specifiers are defined to put all the related driver stuff into the sections designated to be injected. Besides some restrictions, the Earlycon driver is quite straightforward to code.
Some effort has been spent also to lay down an easy migration path for the various platforms, each one independently from the others. The backward compatibility is granted by the fallback logics, which is controller by two pre-processor knobs: CONFIG_DEBUG_LL_EARLYCON and EARLYCON_STATIC_SETUP.
The fallback logics is used when no suitable Earlycon driver is found or none is searched. In case neither CONFIG_DEBUG_LL_EARLYCON nor EARLYCON_STATIC_SETUP are defined, the fallback ops actually invoke the legacy putc/flush otherwise they don't do anything.
CONFIG_DEBUG_LL_EARLYCON is a configuration option that says "whatever legacy putc/flush stuff is coming from uncompress.h, don't use it, use only the available Earlycom drivers". It's a global setting, it should help to simulate a world without uncompress.h. Actually it really removes the dependency on uncompress.h at the cost of breaking stuff depending on arch_decomp_setup().
EARLYCON_STATIC_SETUP instead is local, it's defined in the uncompress.h header itself. It is used by the driver writer to quickly go back and forth the "world without uncompress.h" and find his/her way out of the blank console. It also helps to identify the uncompress.h headers substantially ready to be removed.
I'm surely missing something but I hope you'll spot it reading/testing the code, which is based on mainline commit f2fde3a.
Thank you for reading so far.
cheers,
Domenico
RFC 1/6 From: Domenico Andreoli <[email protected]> ARM: Inject the Earlycon drivers into the decompressor
An embedded and charset-unspecified text was scrubbed...
Name: earlycon-linker-magic.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120531/706bc051/attachment.ksh>
RFC 1/6 From: Domenico Andreoli <[email protected]> ARM: Inject the Earlycon drivers into the decompressor
Quoted 3 lines · Domenico Andreoli
This linker voodoo clones the Earlycon drivers from the kernel into the decompressor, selecting everything in the designated ELF sections (.text.earlycon.info and .init.earlycon.info).
No, the debug stuff in the main kernel and the decompressor stuff can (and is in some cases) different. There's a reason we have the two implementations separate.
Moreover, these two things operate in two different address spaces; the debug stuff in the kernel has to cope with the MMU being either on or off, and use the kernel v:p mappings when the MMU is on. The decompressor on the other hand has a 1:1 v:p mapping when the MMU is on - so it would not be able to tell the difference if you just cloned the exact same code.
One example of this would be RiscPC, where the decompressor writes to the framebuffer, but the debug stuff writes to the serial port.
The preference is for the decompressor to write to the normal user visible interface when possible, and the debug stuff to a serial port.
RFC 1/6 From: Domenico Andreoli <[email protected]> ARM: Inject the Earlycon drivers into the decompressor
Quoted 8 lines · Russell King - ARM Linux
Quoted 3 lines · Domenico Andreoli
This linker voodoo clones the Earlycon drivers from the kernel into the decompressor, selecting everything in the designated ELF sections (.text.earlycon.info and .init.earlycon.info).
No, the debug stuff in the main kernel and the decompressor stuff can (and is in some cases) different. There's a reason we have the two implementations separate.
Not to mention the discomfort to discover another debug i/o in head.S used for a totally different purpose which, incidentally, includes the same debug-macro.S of the main kernel early console.
I realized that something was wrong as soon as the code to parse earlyprintk started to work, effectively enabling also the main kernel early console, something I didn't truly want.
So yes, I got the point, they have different use cases and effectively cannot use right the same bianry code. This is not the intent of the patch though.
The usage of the section cloning is not to keep and later reuse the Earlycon built in the main kernel image. It's only to let that (source) code live in a single place and not being replicated in those many haders.
Probably a similar result could be achieved shipping Earlycon as ordinary library to the decompressor but it would loose the initial idea of fiddling with the sections, which is where everything started from ;)
Plus some more Makefile paperwork to build the library for the decompressor, which would pick all and only the wanted drivers (platform specific, common, etc...) sticking the usual list somewhere/somehow in an old fashioned way (yes, boring).
Quoted 6 lines
Moreover, these two things operate in two different address spaces; the debug stuff in the kernel has to cope with the MMU being either on or off, and use the kernel v:p mappings when the MMU is on. The decompressor on the other hand has a 1:1 v:p mapping when the MMU is on - so it would not be able to tell the difference if you just cloned the exact same code.
I think all this is not applicable to Earlycon because it is to be used only by the the decompressor in whichever configuration the MMU is in that instant.
It must be clear to the earlycon driver that nothing fancy should be done there. So if something is going to be broken because wrongs assumptions are done on the MMU status, yes... sorry, you should be fiddling with a couple of registers or a buffer and live with the base address you received and stop there.
Quoted 2 lines
One example of this would be RiscPC, where the decompressor writes to the framebuffer, but the debug stuff writes to the serial port.
Yes, clear. I never wanted to make this impossible.
Quoted 2 lines
The preference is for the decompressor to write to the normal user visible interface when possible, and the debug stuff to a serial port.
So earlyprintk= is the wrong one, actually the decompressor/Earlycon should use the same console= used by the kernel. How to map a console=ttyAMA0 to to an amba-pl011 on board A and amba-pl010 on board B?
Now, putting aside this code (which I would be very happy could somehow end in the kernel) which I made for fun, is this "Decompressing Linux..." so worthy?
BTW there is a similar (possibly critical) problem with arch_decomp_setup(), often used to initialize the watchdog. We need to build many of them and select the right one using the machid (or DT, how?) at boot. Would you consider a patch approaching the problem in in the same fashion?
thanks,
Domenico
RFC 2/6 From: Domenico Andreoli <[email protected]> ARM: Add Earlycon support to the decompressor
In reply to Domenico AndreoliAn embedded and charset-unspecified text was scrubbed...
Name: earlycon-decompressor.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120531/12ef202a/attachment.ksh>
RFC 3/6 From: Domenico Andreoli <[email protected]> ARM: Earlycon support for AMBA PL010 UARTs
In reply to Domenico AndreoliAn embedded and charset-unspecified text was scrubbed...
Name: earlycon-uart-amba-pl010.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120531/341356b0/attachment.ksh>
RFC 4/6 From: Domenico Andreoli <[email protected]> ARM: Earlycon support for AMBA PL011 UARTs
In reply to Domenico AndreoliAn embedded and charset-unspecified text was scrubbed...
Name: earlycon-uart-amba-pl011.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120531/a77d5ea6/attachment.ksh>
RFC 5/6 From: Domenico Andreoli <[email protected]> ARM: Earlycon support for Samsung UARTs
In reply to Domenico AndreoliAn embedded and charset-unspecified text was scrubbed...
Name: earlycon-uart-samsung.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120531/ae0767ed/attachment.ksh>
RFC 6/6 From: Domenico Andreoli <[email protected]> ARM: Earlycon support for OMAP UARTs
In reply to Domenico AndreoliAn embedded and charset-unspecified text was scrubbed...
Name: earlycon-uart-omap.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20120531/ae26bc89/attachment.ksh>