From cf4fc1790387bc04cbd4d7f5a4611372fcc7821c Mon Sep 17 00:00:00 2001 From: Duncan Laurie Date: Mon, 10 Jun 2013 10:34:20 -0700 Subject: [PATCH] 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. BUG=chrome-os-partner:19980 BRANCH=none TEST=manual: 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 Reviewed-on: https://gerrit.chromium.org/gerrit/58105 --- src/arch/x86/lib/cpu.c | 3 +++ src/console/post.c | 16 ++++++++++++++++ src/device/device.c | 17 +++++++++++++++-- src/include/console/console.h | 5 +++++ src/include/pc80/mc146818rtc.h | 2 ++ 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/arch/x86/lib/cpu.c b/src/arch/x86/lib/cpu.c index be8e38da13..44b32d5b15 100644 --- a/src/arch/x86/lib/cpu.c +++ b/src/arch/x86/lib/cpu.c @@ -254,6 +254,8 @@ void cpu_initialize(unsigned int index) die("CPU: missing cpu device structure"); } + post_log_path(cpu); + /* Find what type of cpu we are dealing with */ identify_cpu(cpu); printk(BIOS_DEBUG, "CPU: vendor %s device %x\n", @@ -283,6 +285,7 @@ void cpu_initialize(unsigned int index) cpu->initialized = 1; cpu->ops->init(cpu); } + post_log_clear(); printk(BIOS_INFO, "CPU #%d initialized\n", index); diff --git a/src/console/post.c b/src/console/post.c index 74886834ce..35cc0e85e1 100644 --- a/src/console/post.c +++ b/src/console/post.c @@ -114,6 +114,22 @@ void post_log_extra(u32 value) 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 /* !__PRE_RAM__ */ diff --git a/src/device/device.c b/src/device/device.c index a971270eba..b04cab6032 100644 --- a/src/device/device.c +++ b/src/device/device.c @@ -66,10 +66,12 @@ void dev_initialize_chips(void) /* Initialize chip if we haven't yet. */ if (dev->chip_ops && dev->chip_ops->init && !dev->chip_ops->initialized) { + post_log_path(dev); dev->chip_ops->init(dev->chip_info); dev->chip_ops->initialized = 1; } } + post_log_clear(); } DECLARE_SPIN_LOCK(dev_lock) @@ -821,8 +823,10 @@ void assign_resources(struct bus *bus) dev_path(curdev)); continue; } + post_log_path(curdev); curdev->ops->set_resources(curdev); } + post_log_clear(); printk(BIOS_SPEW, "%s assign_resources, bus %d link: %d\n", dev_path(bus->dev), bus->secondary, bus->link_num); } @@ -845,14 +849,17 @@ static void enable_resources(struct bus *link) struct bus *c_link; 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); + } } for (dev = link->children; dev; dev = dev->sibling) { for (c_link = dev->link_list; c_link; c_link = c_link->next) enable_resources(c_link); } + post_log_clear(); } /** @@ -892,6 +899,8 @@ unsigned int scan_bus(struct device *busdev, unsigned int max) return max; } + post_log_path(busdev); + do_scan_bus = 1; while (do_scan_bus) { struct bus *link; @@ -951,6 +960,7 @@ void dev_enumerate(void) return; } scan_bus(root, 0); + post_log_clear(); printk(BIOS_INFO, "done\n"); } @@ -1131,8 +1141,10 @@ static void init_link(struct bus *link) struct device *dev; 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); + } for (dev = link->children; dev; dev = dev->sibling) { for (c_link = dev->link_list; c_link; c_link = c_link->next) @@ -1163,6 +1175,7 @@ void dev_initialize(void) /* Now initialize everything. */ for (link = dev_root.link_list; link; link = link->next) init_link(link); + post_log_clear(); printk(BIOS_INFO, "Devices initialized\n"); show_all_devs(BIOS_SPEW, "After init."); diff --git a/src/include/console/console.h b/src/include/console/console.h index 68d9db6723..04ad139e08 100644 --- a/src/include/console/console.h +++ b/src/include/console/console.h @@ -71,8 +71,13 @@ void console_tx_flush(void); void post_code(u8 value); #if CONFIG_CMOS_POST_EXTRA void post_log_extra(u32 value); +struct device; +void post_log_path(struct device *dev); +void post_log_clear(void); #else #define post_log_extra(x) do {} while (0) +#define post_log_path(x) do {} while (0) +#define post_log_clear() do {} while (0) #endif /* this function is weak and can be overridden by a mainboard function. */ void mainboard_post(u8 value); diff --git a/src/include/pc80/mc146818rtc.h b/src/include/pc80/mc146818rtc.h index c3c5c4c3b4..e4e7b0f660 100644 --- a/src/include/pc80/mc146818rtc.h +++ b/src/include/pc80/mc146818rtc.h @@ -212,6 +212,8 @@ static inline int get_option(void *dest __attribute__((unused)), #define CMOS_POST_BANK_1_OFFSET (CMOS_POST_OFFSET + 2) #define CMOS_POST_BANK_1_EXTRA (CMOS_POST_OFFSET + 7) +#define CMOS_POST_EXTRA_DEV_PATH 0x01 + void cmos_post_log(void); #endif /* CONFIG_CMOS_POST */