Poison RAM and continuously report on status if stack checking is enabled.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: corebootv3-poison/include/arch/x86/cpu.h =================================================================== --- corebootv3-poison/include/arch/x86/cpu.h (Revision 1046) +++ corebootv3-poison/include/arch/x86/cpu.h (Arbeitskopie) @@ -329,5 +329,12 @@ void setup_resource_map(const struct rmap *rm, u32 max); EXPORT_SYMBOL(setup_resource_map);
+#ifdef CONFIG_CHECK_STACK_USAGE +/* POISON_BYTE could be a special value like 0x6b. Just make sure the stage0 + * code fills the complete CAR area with it. And the stack switching needs to + * overwrite the unused parts of the stack with POISON_BYTE as well. + */ +#define POISON_BYTE 0x6b +#endif
#endif /* ARCH_X86_CPU_H */ Index: corebootv3-poison/lib/stage2.c =================================================================== --- corebootv3-poison/lib/stage2.c (Revision 1046) +++ corebootv3-poison/lib/stage2.c (Arbeitskopie) @@ -28,6 +28,9 @@ #include <device/device.h> #include <tables.h>
+/* FIXME: Figure out the proper include file for this function. */ +void find_lowest_unpoisoned_memory(int msg_level); + /** * Main function of the DRAM part of coreboot. * @@ -46,6 +49,9 @@ void *mbi;
post_code(POST_STAGE2_BEGIN); +#ifdef CONFIG_CHECK_STACK_USAGE + find_lowest_unpoisoned_memory(BIOS_DEBUG); +#endif dev_init();
/* Phase 1 was console init and making printk work. Both functions are @@ -54,6 +60,9 @@ post_code(POST_STAGE2_PHASE1_START); dev_phase1(); show_all_devs(BIOS_DEBUG, "After phase 1."); +#ifdef CONFIG_CHECK_STACK_USAGE + find_lowest_unpoisoned_memory(BIOS_DEBUG); +#endif
/* Here is where weird stuff like init_timer handling should be * done. This is for ANYTHING that might have to happen before @@ -62,6 +71,9 @@ post_code(POST_STAGE2_PHASE2_START); dev_phase2(); show_all_devs(BIOS_DEBUG, "After phase 2."); +#ifdef CONFIG_CHECK_STACK_USAGE + find_lowest_unpoisoned_memory(BIOS_DEBUG); +#endif
/* Walk physical devices and add any dynamic devices to the * device tree. @@ -69,26 +81,41 @@ post_code(POST_STAGE2_PHASE3_START); dev_root_phase3(); show_all_devs_tree(BIOS_DEBUG, "After phase 3."); +#ifdef CONFIG_CHECK_STACK_USAGE + find_lowest_unpoisoned_memory(BIOS_DEBUG); +#endif
/* Compute and assign the bus resources. */ post_code(POST_STAGE2_PHASE4_START); dev_phase4(); show_all_devs(BIOS_DEBUG, "After phase 4."); +#ifdef CONFIG_CHECK_STACK_USAGE + find_lowest_unpoisoned_memory(BIOS_DEBUG); +#endif
/* Now actually enable devices on the bus. */ post_code(POST_STAGE2_PHASE5_START); dev_root_phase5(); show_all_devs(BIOS_DEBUG, "After phase 5."); +#ifdef CONFIG_CHECK_STACK_USAGE + find_lowest_unpoisoned_memory(BIOS_DEBUG); +#endif
/* Initialize devices on the bus. */ post_code(POST_STAGE2_PHASE6_START); dev_phase6(); show_all_devs(BIOS_DEBUG, "After phase 6."); +#ifdef CONFIG_CHECK_STACK_USAGE + find_lowest_unpoisoned_memory(BIOS_DEBUG); +#endif
/* Write tables to pass information to the payloads. */ post_code(POST_STAGE2_WRITE_TABLES); mbi = write_tables(); show_all_devs(BIOS_DEBUG, "After writing tables."); +#ifdef CONFIG_CHECK_STACK_USAGE + find_lowest_unpoisoned_memory(BIOS_DEBUG); +#endif
return mbi; } Index: corebootv3-poison/arch/x86/Kconfig =================================================================== --- corebootv3-poison/arch/x86/Kconfig (Revision 1046) +++ corebootv3-poison/arch/x86/Kconfig (Arbeitskopie) @@ -246,5 +246,6 @@ The monitoring code is invoked from printk because printk is a leaf function and consumes quite a bit of stack for itself. This slows down booting a LOT. + This does not work in CAR stage until the asm is changed.
endmenu Index: corebootv3-poison/arch/x86/stage1.c =================================================================== --- corebootv3-poison/arch/x86/stage1.c (Revision 1046) +++ corebootv3-poison/arch/x86/stage1.c (Arbeitskopie) @@ -106,11 +106,6 @@ }
#ifdef CONFIG_CHECK_STACK_USAGE -/* STACKFILL_BYTE could be a special value like 0x6b. Just make sure the stage0 - * code fills the complete CAR area with it. And the stack switching needs to - * overwrite the unused parts of the stack with STACKFILL_BYTE as well. - */ -#define STACKFILL_BYTE 0x0 void check_stack() { unsigned long stacksize, i; @@ -121,7 +116,7 @@ stacksize = CAR_STACK_SIZE; lowestaddr = bottom_of_stack() - stacksize; for (i = 0; i < stacksize; i++) - if (lowestaddr[i] != STACKFILL_BYTE) + if (lowestaddr[i] != POISON_BYTE) break; global_vars()->loweststack = lowestaddr + i; } @@ -139,6 +134,22 @@ return; }
+#ifdef CONFIG_CHECK_STACK_USAGE +void find_lowest_unpoisoned_memory(int msg_level) +{ + char *addr; + for (addr = NULL; (unsigned long)addr < 1024*1024; addr++) { + if (*addr != POISON_BYTE) { + printk(msg_level, "lowest unpoisoned mem is at %p\n", + addr); + dump_mem_range(msg_level, (unsigned char *)((unsigned long)addr & (~0xf)), 64); + break; + } + } + return; +} +#endif + /** cycles * provide 64-bit high precision counter * @returns Time in 64 bits @@ -290,6 +301,18 @@ */ void stage1_phase2(void) { +#ifdef CONFIG_CHECK_STACK_USAGE +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + /* We poison the area between 0x00000 and 1 MB, but we exclude + * the CAR area. If devices are mapped there, we lose. + */ + memset(NULL, POISON_BYTE, min(CONFIG_CARBASE, 1024 * 1024)); + if (CONFIG_CARBASE + CONFIG_CARSIZE < 1024 * 1024) + memset((void *)CONFIG_CARBASE + CONFIG_CARSIZE, POISON_BYTE, + 1024 * 1024 - (CONFIG_CARBASE + CONFIG_CARSIZE)); + find_lowest_unpoisoned_memory(BIOS_DEBUG); +#endif #ifdef CONFIG_CONSOLE_BUFFER /* Move the printk buffer to PRINTK_BUF_ADDR_RAM */ printk_buffer_move((void *)PRINTK_BUF_ADDR_RAM, PRINTK_BUF_SIZE_RAM); @@ -332,6 +355,10 @@ /* Provide an easy way to check whether RAM is available. */ global_vars()->ram_available = 1;
+#ifdef CONFIG_CHECK_STACK_USAGE + find_lowest_unpoisoned_memory(BIOS_DEBUG); +#endif + // location and size of image. init_archive(&archive);
@@ -354,6 +381,7 @@ #ifdef CONFIG_CHECK_STACK_USAGE printk(BIOS_DEBUG, "Before handoff to payload, lowest stack is %p\n", global_vars()->loweststack); + find_lowest_unpoisoned_memory(BIOS_DEBUG); #endif if (entry != (void*)-1) { /* Final coreboot call before handing off to the payload. */