[coreboot] New patch to review for coreboot: 6f6fe9f Support better tracking of AP stack usage.

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Tue Nov 13 00:19:40 CET 2012


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1818

-gerrit

commit 6f6fe9ff6a910e81aa6526a11a3090bc12aef317
Author: Ronald G. Minnich <rminnich at chromium.org>
Date:   Wed Jun 6 13:00:24 2012 -0700

    Support better tracking of AP stack usage.
    
    This change allows us to figure out how much of the AP stacks we are
    using, as well as to catch any case of an AP overrunning its stack.
    Also, the stack is poisoned, which is a good way to catch programming
    errors -- code should never count on auto variables being zerod.
    
    The stack bases are recorded in a new array, stacks. At the end,
    when all APs are initialized, the stacks are walked and the
    lowest level of the stack that is reached is printed.
    
    Build and boot and look for output like this:
    
    CPU1: stack allocated from 00148000 to 00148ff4:\
    	lowest stack address was 00148c4c
    CPU2: stack allocated from 00147000 to 00147ff4:\
    	lowest stack address was 00147c4c
    CPU3: stack allocated from 00146000 to 00146ff4:\
    	lowest stack address was 00146c4c
    
    Note that we used only about 1K of stack, even though in this
    case we allocated 4K (and in the main branch, we allocate 32K!)
    
    Change-Id: I99b7b9086848496feb3ecd207f64203fa69fadf5
    Signed-off-by: Ronald G. Minnich <rminnich at chromium.org>
---
 src/cpu/x86/lapic/lapic_cpu_init.c | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/src/cpu/x86/lapic/lapic_cpu_init.c b/src/cpu/x86/lapic/lapic_cpu_init.c
index b721e8f..256066f 100644
--- a/src/cpu/x86/lapic/lapic_cpu_init.c
+++ b/src/cpu/x86/lapic/lapic_cpu_init.c
@@ -16,7 +16,7 @@
 #include <cpu/cpu.h>
 #include <cpu/intel/speedstep.h>
 
-#if CONFIG_SMP
+#if CONFIG_SMP && CONFIG_MAX_CPUS > 1
 /* This is a lot more paranoid now, since Linux can NOT handle
  * being told there is a CPU when none exists. So any errors
  * will return 0, meaning no CPU.
@@ -216,15 +216,19 @@ static atomic_t active_cpus = ATOMIC_INIT(1);
 static spinlock_t start_cpu_lock = SPIN_LOCK_UNLOCKED;
 static unsigned last_cpu_index = 0;
 volatile unsigned long secondary_stack;
+void *stacks[CONFIG_MAX_CPUS];
 
 int start_cpu(device_t cpu)
 {
 	extern unsigned char _estack[];
 	struct cpu_info *info;
 	unsigned long stack_end;
+	unsigned long stack_base;
+	unsigned long *stack;
 	unsigned long apicid;
 	unsigned long index;
 	unsigned long count;
+	int i;
 	int result;
 
 	spin_lock(&start_cpu_lock);
@@ -238,6 +242,13 @@ int start_cpu(device_t cpu)
 	/* Find end of the new processors stack */
 	stack_end = ((unsigned long)_estack) - (CONFIG_STACK_SIZE*index) - sizeof(struct cpu_info);
 
+	stack_base = ((unsigned long)_estack) - (CONFIG_STACK_SIZE*(index+1));
+	printk(BIOS_SPEW, "CPU%ld: stack_base %p, stack_end %p\n", index,
+		(void *)stack_base, (void *)stack_end);
+	/* poison the stack */
+	for(stack = (void *)stack_base, i = 0; i < CONFIG_STACK_SIZE; i++)
+		stack[i/sizeof(*stack)] = 0xDEADBEEF;
+	stacks[index] = stack;
 	/* Record the index and which cpu structure we are using */
 	info = (struct cpu_info *)stack_end;
 	info->index = index;
@@ -440,6 +451,7 @@ static void wait_other_cpus_stop(struct bus *cpu_bus)
 	device_t cpu;
 	int old_active_count, active_count;
 	long loopcount = 0;
+	int i;
 
 	/* Now loop until the other cpus have finished initializing */
 	old_active_count = 1;
@@ -466,6 +478,21 @@ static void wait_other_cpus_stop(struct bus *cpu_bus)
 		}
 	}
 	printk(BIOS_DEBUG, "All AP CPUs stopped (%ld loops)\n", loopcount);
+	for(i = 1; i <= last_cpu_index; i++){
+		unsigned long *stack = stacks[i];
+		int lowest;
+		int maxstack = (CONFIG_STACK_SIZE - sizeof(struct cpu_info))
+					/sizeof(*stack) - 1;
+		if (stack[0] != 0xDEADBEEF)
+			printk(BIOS_ERR, "CPU%d overran its stack\n", i);
+		for(lowest = 0; lowest < maxstack; lowest++)
+			if (stack[lowest] != 0xDEADBEEF)
+				break;
+		printk(BIOS_SPEW, "CPU%d: stack allocated from %p to %p:", i,
+			stack, &stack[maxstack]);
+		printk(BIOS_SPEW, "lowest stack address was %p\n", &stack[lowest]);
+
+	}
 }
 
 #endif /* CONFIG_SMP */
@@ -494,7 +521,7 @@ void initialize_cpus(struct bus *cpu_bus)
 	/* Find the device structure for the boot cpu */
 	info->cpu = alloc_find_dev(cpu_bus, &cpu_path);
 
-#if CONFIG_SMP
+#if CONFIG_SMP && CONFIG_MAX_CPUS > 1
 	copy_secondary_start_to_1m_below(); // why here? In case some day we can start core1 in amd_sibling_init
 #endif
 
@@ -502,7 +529,7 @@ void initialize_cpus(struct bus *cpu_bus)
 	smm_init();
 #endif
 
-#if CONFIG_SMP
+#if CONFIG_SMP && CONFIG_MAX_CPUS > 1
 	#if !CONFIG_SERIAL_CPU_INIT
 	/* start all aps at first, so we can init ECC all together */
 	start_other_cpus(cpu_bus, info->cpu);
@@ -512,7 +539,7 @@ void initialize_cpus(struct bus *cpu_bus)
 	/* Initialize the bootstrap processor */
 	cpu_initialize();
 
-#if CONFIG_SMP
+#if CONFIG_SMP && CONFIG_MAX_CPUS > 1
 	#if CONFIG_SERIAL_CPU_INIT
 	start_other_cpus(cpu_bus, info->cpu);
 	#endif




More information about the coreboot mailing list