Log device path into CMOS during probe stages

One of the most common hangs during coreboot execution
is during ramstage device init steps.  Currently there
are a set of (somewhat misleading) post codes during this
phase which give some indication as to where execution
stopped, but it provides no information on what device
was actually being initialized at that point.

This uses the new CMOS "extra" log banks to store the
encoded device path of the device that is about to be
touched by coreboot.  This way if the system hangs when
talking to the device there will be some indication where
to investigate next.

interrupted boot with reset button and
gathered the eventlog after several test runs:

26 | 2013-06-10 10:32:48 | System boot | 120
27 | 2013-06-10 10:32:48 | Last post code in previous boot | 0x75 | Device Initialize
28 | 2013-06-10 10:32:48 | Extra info from previous boot | PCI | 00:16.0
29 | 2013-06-10 10:32:48 | Reset Button
30 | 2013-06-10 10:32:48 | System Reset

Change-Id: I6045bd4c384358b8a4e464eb03ccad639283939c
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/58105
Reviewed-on: http://review.coreboot.org/4230
Tested-by: build bot (Jenkins)
Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
This commit is contained in:
Duncan Laurie 2013-06-10 10:34:20 -07:00 committed by Stefan Reinauer
parent d5686fe23b
commit 8adf7a2c50
5 changed files with 41 additions and 2 deletions

View File

@ -256,6 +256,8 @@ void cpu_initialize(unsigned int index)
die("CPU: missing cpu device structure"); die("CPU: missing cpu device structure");
} }
post_log_path(cpu);
/* Find what type of cpu we are dealing with */ /* Find what type of cpu we are dealing with */
identify_cpu(cpu); identify_cpu(cpu);
printk(BIOS_DEBUG, "CPU: vendor %s device %x\n", printk(BIOS_DEBUG, "CPU: vendor %s device %x\n",
@ -285,6 +287,7 @@ void cpu_initialize(unsigned int index)
cpu->initialized = 1; cpu->initialized = 1;
cpu->ops->init(cpu); cpu->ops->init(cpu);
} }
post_log_clear();
printk(BIOS_INFO, "CPU #%d initialized\n", index); printk(BIOS_INFO, "CPU #%d initialized\n", index);

View File

@ -114,6 +114,22 @@ void post_log_extra(u32 value)
spin_unlock(&cmos_post_lock); spin_unlock(&cmos_post_lock);
} }
void post_log_path(struct device *dev)
{
if (dev) {
/* Encode path into lower 3 bytes */
u32 path = dev_path_encode(dev);
/* Upper byte contains the log type */
path |= CMOS_POST_EXTRA_DEV_PATH << 24;
post_log_extra(path);
}
}
void post_log_clear(void)
{
post_log_extra(0);
}
#endif /* CONFIG_CMOS_POST_EXTRA */ #endif /* CONFIG_CMOS_POST_EXTRA */
#endif /* !__PRE_RAM__ */ #endif /* !__PRE_RAM__ */

View File

@ -66,10 +66,12 @@ void dev_initialize_chips(void)
/* Initialize chip if we haven't yet. */ /* Initialize chip if we haven't yet. */
if (dev->chip_ops && dev->chip_ops->init && if (dev->chip_ops && dev->chip_ops->init &&
!dev->chip_ops->initialized) { !dev->chip_ops->initialized) {
post_log_path(dev);
dev->chip_ops->init(dev->chip_info); dev->chip_ops->init(dev->chip_info);
dev->chip_ops->initialized = 1; dev->chip_ops->initialized = 1;
} }
} }
post_log_clear();
} }
/** /**
@ -841,8 +843,10 @@ void assign_resources(struct bus *bus)
dev_path(curdev)); dev_path(curdev));
continue; continue;
} }
post_log_path(curdev);
curdev->ops->set_resources(curdev); curdev->ops->set_resources(curdev);
} }
post_log_clear();
printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n", printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n",
dev_path(bus->dev), bus->secondary, bus->link_num); dev_path(bus->dev), bus->secondary, bus->link_num);
} }
@ -865,14 +869,17 @@ static void enable_resources(struct bus *link)
struct bus *c_link; struct bus *c_link;
for (dev = link->children; dev; dev = dev->sibling) { for (dev = link->children; dev; dev = dev->sibling) {
if (dev->enabled && dev->ops && dev->ops->enable_resources) if (dev->enabled && dev->ops && dev->ops->enable_resources) {
post_log_path(dev);
dev->ops->enable_resources(dev); dev->ops->enable_resources(dev);
}
} }
for (dev = link->children; dev; dev = dev->sibling) { for (dev = link->children; dev; dev = dev->sibling) {
for (c_link = dev->link_list; c_link; c_link = c_link->next) for (c_link = dev->link_list; c_link; c_link = c_link->next)
enable_resources(c_link); enable_resources(c_link);
} }
post_log_clear();
} }
/** /**
@ -912,6 +919,8 @@ unsigned int scan_bus(struct device *busdev, unsigned int max)
return max; return max;
} }
post_log_path(busdev);
do_scan_bus = 1; do_scan_bus = 1;
while (do_scan_bus) { while (do_scan_bus) {
struct bus *link; struct bus *link;
@ -971,6 +980,7 @@ void dev_enumerate(void)
return; return;
} }
scan_bus(root, 0); scan_bus(root, 0);
post_log_clear();
printk(BIOS_INFO, "done\n"); printk(BIOS_INFO, "done\n");
} }
@ -1151,8 +1161,10 @@ static void init_link(struct bus *link)
struct device *dev; struct device *dev;
struct bus *c_link; struct bus *c_link;
for (dev = link->children; dev; dev = dev->sibling) for (dev = link->children; dev; dev = dev->sibling) {
post_log_path(dev);
init_dev(dev); init_dev(dev);
}
for (dev = link->children; dev; dev = dev->sibling) { for (dev = link->children; dev; dev = dev->sibling) {
for (c_link = dev->link_list; c_link; c_link = c_link->next) for (c_link = dev->link_list; c_link; c_link = c_link->next)
@ -1183,6 +1195,7 @@ void dev_initialize(void)
/* Now initialize everything. */ /* Now initialize everything. */
for (link = dev_root.link_list; link; link = link->next) for (link = dev_root.link_list; link; link = link->next)
init_link(link); init_link(link);
post_log_clear();
printk(BIOS_INFO, "Devices initialized\n"); printk(BIOS_INFO, "Devices initialized\n");
show_all_devs(BIOS_SPEW, "After init."); show_all_devs(BIOS_SPEW, "After init.");

View File

@ -74,8 +74,13 @@ void console_tx_flush(void);
void post_code(u8 value); void post_code(u8 value);
#if CONFIG_CMOS_POST_EXTRA #if CONFIG_CMOS_POST_EXTRA
void post_log_extra(u32 value); void post_log_extra(u32 value);
struct device;
void post_log_path(struct device *dev);
void post_log_clear(void);
#else #else
#define post_log_extra(x) do {} while (0) #define post_log_extra(x) do {} while (0)
#define post_log_path(x) do {} while (0)
#define post_log_clear() do {} while (0)
#endif #endif
/* this function is weak and can be overridden by a mainboard function. */ /* this function is weak and can be overridden by a mainboard function. */
void mainboard_post(u8 value); void mainboard_post(u8 value);

View File

@ -217,6 +217,8 @@ static inline enum cb_err get_option(void *dest __attribute__((unused)),
#define CMOS_POST_BANK_1_OFFSET (CMOS_POST_OFFSET + 2) #define CMOS_POST_BANK_1_OFFSET (CMOS_POST_OFFSET + 2)
#define CMOS_POST_BANK_1_EXTRA (CMOS_POST_OFFSET + 7) #define CMOS_POST_BANK_1_EXTRA (CMOS_POST_OFFSET + 7)
#define CMOS_POST_EXTRA_DEV_PATH 0x01
void cmos_post_log(void); void cmos_post_log(void);
#endif /* CONFIG_CMOS_POST */ #endif /* CONFIG_CMOS_POST */