diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 87a822e5c..724bcfd31 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -86,6 +86,21 @@ SYM_CODE_START(primary_entry) bl record_mmu_state bl preserve_boot_args + /* + * ALARM boot marker, stage 1: primary_entry reached. + * + * Writes a word to 0xB0000000, the region hekate reserves and preserves + * across boots as its pstore carveout (bdk/memory_map.h: PSTORE_ADDR). + * The MMU is still off here, so this is a plain physical write. U-Boot + * dumps that region to the SD on the next boot, which is the only way to + * observe how far the kernel gets when it dies before its first printk. + * + * x0-x3 are preserved by preserve_boot_args above; x9/x10 are free. + */ + movz x9, #0xB000, lsl #16 // 0xB0000000 + mov w10, #0xA1 + str w10, [x9] + adrp x1, early_init_stack mov sp, x1 mov x29, xzr @@ -127,6 +142,12 @@ SYM_CODE_START(primary_entry) * the TCR will have been set. */ bl __cpu_setup // initialise processor + + /* ALARM boot marker, stage 2: page tables built, CPU setup done, MMU off. */ + movz x9, #0xB000, lsl #16 // 0xB0000000 + mov w10, #0xA2 + str w10, [x9, #4] + b __primary_switch SYM_CODE_END(primary_entry) diff --git a/init/main.c b/init/main.c index e363232b4..3a5644a71 100644 --- a/init/main.c +++ b/init/main.c @@ -40,6 +40,8 @@ #include #include #include +/* ALARM: __va() for the boot markers written into hekate's pstore region. */ +#include #include #include #include @@ -991,7 +993,23 @@ void start_kernel(void) boot_cpu_init(); page_address_init(); pr_notice("%s", linux_banner); + + /* + * ALARM boot marker: 0xB0000000 is the region hekate reserves and preserves + * across boots as its pstore carveout (bdk/memory_map.h: PSTORE_ADDR). + * U-Boot dumps it to the SD on the next boot, which is the only way to see + * how far the kernel gets -- the display is tiled and unreadable, there is + * no UART, and the kernel dies before its first printk. + * + * Stages 1 and 2 are written from head.S before the MMU is on (plain + * physical writes). From here the linear mapping exists, hence __va(). + */ +#define ALARM_MARK(n) \ + (*(volatile u32 *)__va(0xB0000000UL + (n) * 4) = 0xA0A00000u | (n)) + setup_arch(&command_line); + ALARM_MARK(3); /* device tree parsed, memory and paging set up */ + mm_core_init_early(); /* Static keys and static calls are needed by LSMs */ jump_label_init(); @@ -1086,6 +1104,7 @@ void start_kernel(void) vdso_setup_data_pages(); timekeeping_init(); time_init(); + ALARM_MARK(4); /* arch timer initialised */ /* This must be after timekeeping is initialized */ random_init();