ram_console和last_kmsg是Android加入到kernel中的一个Debug功能。
实现:
android要求平台提供一块固定的内存,作为ram_console的存储空间。然后通过“代码:register_console(&ram_console);”,将ram_console注册到printk输出的console_list中去,所以printk会时时向ram_console中输出kernel log。在ram_console头部有一个“代码:RAM_CONSOLE_SIG”的签名,每次android设备启动的时候,会check头部的签名是否正确。如果正确,那就会将ram_console中的内容保起来,生成一个/proc/last_kmsg的节点,用来查看上次最后的kernel log。如果不正确,就不会生成last_kmsg。
作用:
ram_console和last_kmsg的作用是用来分析重启的原因。
1. 如果是kernel panic造成的重启,则可以在last_kmsg中panic的现场。
2. 如果人为的重启,则有机会在last_kmsg中找到一定线索。
3. 如果没有last_kmsg,说明系统一定掉过电。可以作为分析重启原因的一个重要线索。
探索:
那么问题来了,平台是如何为ram_console提供一块固定内存的呢?
我们先来看MTK平台:
MTK平台直接给了一个虚拟地址:CONFIG_MTK_RAM_CONSOLE_ADDR=0xF900DC00
然后我们找到了:(说明MTK平台将SOC的SRAM中的64K映射到了kernel虚拟地址中的0xF9000000-0xF9010000)
#define INTER_SRAM 0xF9000000
static struct map_desc mt_io_desc[] __initdata =
{
......
{
/* virtual 0xF9000000, physical 0x00100000 */
.virtual = INTER_SRAM,
.pfn = __phys_to_pfn(0x00100000),
.length = SZ_64K,
.type = MT_MEMORY_NONCACHED
},
......
void __init mt_map_io(void)
{
iotable_init(mt_io_desc, ARRAY_SIZE(mt_io_desc));
}
......
MACHINE_START(MT6582, "MT6582")
.atag_offset = 0x00000100,
.map_io = mt_map_io,
.init_irq = mt_init_irq,
.timer = &mt6582_timer,
.init_machine = mt_init,
.fixup = mt_fixup,
.restart = arm_machine_restart,
.reserve = mt_reserve,
MACHINE_END
最后我们来看一下这部分内存在内核虚拟内存layout中的哪个部分:
我们来看一下kernel/Documentation/arm/memory.txt
VMALLOC_START VMALLOC_END-1 vmalloc() / ioremap() space.
Memory returned by vmalloc/ioremap will
be dynamically placed in this region.
Machine specific static mappings are also
located here through iotable_init().
VMALLOC_START is based upon the value
of the high_memory variable, and VMALLOC_END
is equal to 0xff000000.
比较明显是被映射到了vmalloc区域。
那我们再看一个FSL平台的实现:
ram_console.c
static int ram_console_driver_probe(struct platform_device *pdev)
{
......
struct resource *res = pdev->resource;
......
buffer = ioremap(res->start, buffer_size);
arch/arm/mach-mx6/board-mx6q_sabrelite.c
static void __init mx6q_sabrelite_reserve(void)
{
......
#ifdef CONFIG_ANDROID_RAM_CONSOLE
phys = memblock_alloc_base(SZ_128K, SZ_4K, SZ_1G);
memblock_remove(phys, SZ_128K);
memblock_free(phys, SZ_128K);
ram_console_resource.start = phys;
ram_console_resource.end = phys + SZ_128K - 1;
#endif
......
MACHINE_START(MX6Q_SABRELITE, "Freescale i.MX 6Quad Sabre-Lite Board")
/* Maintainer: Freescale Semiconductor, Inc. */
.boot_params = MX6_PHYS_OFFSET + 0x100,
.fixup = fixup_mxc_board,
.map_io = mx6_map_io,
.init_irq = mx6_init_irq,
.init_machine = mx6_sabrelite_board_init,
.timer = &mx6_sabrelite_timer,
.reserve = mx6q_sabrelite_reserve,
MACHINE_END
那么FSL平台是的地址是被reserve起来了。