Corey Minyard wrote: > This is fine. Can you write a program to reconstruct the log from the SEL?
Sure, will do. BTW, I'm not sure, which package will contain this program? In the kernel doc? ipmiutil? Thanks, Hiroshi > > -corey > > Hiroshi Shimamoto wrote: >> From: Hiroshi Shimamoto <[email protected]> >> >> Console messages on oops or panic are very important to investigate problem. >> Logging oops or panic messages to SEL is useful because SEL is a non >> volatile memory. >> >> Implement a console driver to log messages to SEL when oops_in_progress is >> not zero. The first message just after oops, panic or every 10 seconds from >> last timestamp are logged as OEM event with timestamp, others are logged as >> OEM event without timestamp. >> >> Enable config IPMI_OOPS_CONSOLE and add console=ttyIPMI to kernel command >> line to log panic or oops messages to IPMI SEL. >> >> The number of entries for this output is limited by msg_limit paramter, >> and the default value is 100. >> >> Signed-off-by: Hiroshi Shimamoto <[email protected]> >> --- >> v2 -> v3: Use timestamp in first recode and every 10 seconds. >> v1 -> v2: Add msg_limit to limit output size. >> >> drivers/char/ipmi/Kconfig | 7 + >> drivers/char/ipmi/Makefile | 1 + >> drivers/char/ipmi/ipmi_oops_console.c | 256 >> +++++++++++++++++++++++++++++++++ >> 3 files changed, 264 insertions(+), 0 deletions(-) >> create mode 100644 drivers/char/ipmi/ipmi_oops_console.c >> >> diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig >> index 0baa8fa..4bca2b3 100644 >> --- a/drivers/char/ipmi/Kconfig >> +++ b/drivers/char/ipmi/Kconfig >> @@ -61,4 +61,11 @@ config IPMI_POWEROFF >> This enables a function to power off the system with IPMI if >> the IPMI management controller is capable of this. >> >> +config IPMI_OOPS_CONSOLE >> + tristate 'IPMI oops console' >> + help >> + This enables the IPMI oops console. IPMI oops console logs oops or >> + panic console messsages to SEL. The number of entries for this usage >> + is limited by msg_limit, default is 100 entries. >> + >> endif # IPMI_HANDLER >> diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile >> index eb8a1a8..cbbac18 100644 >> --- a/drivers/char/ipmi/Makefile >> +++ b/drivers/char/ipmi/Makefile >> @@ -9,3 +9,4 @@ obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o >> obj-$(CONFIG_IPMI_SI) += ipmi_si.o >> obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o >> obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o >> +obj-$(CONFIG_IPMI_OOPS_CONSOLE) += ipmi_oops_console.o >> diff --git a/drivers/char/ipmi/ipmi_oops_console.c >> b/drivers/char/ipmi/ipmi_oops_console.c >> new file mode 100644 >> index 0000000..437955f >> --- /dev/null >> +++ b/drivers/char/ipmi/ipmi_oops_console.c >> @@ -0,0 +1,256 @@ >> +/* >> + * ipmi_oops_console.c >> + * >> + * IPMI Oops Console >> + * Logging console message to SEL on oops >> + * >> + * Author: Hiroshi Shimamoto <[email protected]> >> + * >> + * Copyright (C) 2008 NEC Corporation >> + * >> + * This program is free software; you can redistribute it and/or modify it >> + * under the terms of the GNU General Public License as published by the >> + * Free Software Foundation; either version 2 of the License, or (at your >> + * option) any later version. >> + * >> + * >> + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED >> + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF >> + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. >> + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, >> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, >> + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS >> + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND >> + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR >> + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE >> + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >> + * >> + * You should have received a copy of the GNU General Public License along >> + * with this program; if not, write to the Free Software Foundation, Inc., >> + * 675 Mass Ave, Cambridge, MA 02139, USA. >> + */ >> + >> +#include <linux/module.h> >> +#include <linux/moduleparam.h> >> +#include <linux/ipmi.h> >> +#include <linux/ipmi_smi.h> >> +#include <linux/console.h> >> +#include <linux/jiffies.h> >> +#include <asm/atomic.h> >> + >> +#define PFX "IPMI oops_console: " >> + >> +static ipmi_user_t oops_user; >> +static int oops_intf = -1; >> + >> +static atomic_t oops_counter; >> + >> +#define SEL_MSGSIZE_TIMESTAMP (6U) >> +#define SEL_MSGSIZE (13U) >> +#define DEF_LIMIT (100) >> +#define TIMESTAMP_INTERVAL (10 * HZ) >> + >> +static char oops_msg[SEL_MSGSIZE_TIMESTAMP + SEL_MSGSIZE]; >> +static char *msg_ptr = oops_msg; >> +static unsigned int msg_len; >> +static unsigned long msg_jiffies; >> +static int msg_count, msg_limit = DEF_LIMIT; >> + >> +module_param(msg_limit, int, 0644); >> +MODULE_PARM_DESC(msg_limit, "Message limit. Default: 100 entries."); >> + >> +static void oops_smi_msg_done(struct ipmi_smi_msg *msg) >> +{ >> + atomic_dec(&oops_counter); >> +} >> +static struct ipmi_smi_msg oops_smi_msg = { >> + .done = oops_smi_msg_done >> +}; >> + >> +static void oops_recv_msg_done(struct ipmi_recv_msg *msg) >> +{ >> + atomic_dec(&oops_counter); >> +} >> +static struct ipmi_recv_msg oops_recv_msg = { >> + .done = oops_recv_msg_done >> +}; >> + >> +static void ipmi_oops_console_log_to_sel(int timestamp) >> +{ >> + struct ipmi_system_interface_addr si; >> + struct kernel_ipmi_msg msg; >> + unsigned int len; >> + unsigned char data[16]; >> + unsigned char my_addr; >> + >> + if (!oops_user || !msg_len || msg_count >= msg_limit) >> + return; >> + >> + len = min((timestamp ? SEL_MSGSIZE_TIMESTAMP : SEL_MSGSIZE), msg_len); >> + >> + si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; >> + si.channel = IPMI_BMC_CHANNEL; >> + si.lun = 0; >> + >> + msg.netfn = IPMI_NETFN_STORAGE_REQUEST; >> + msg.cmd = IPMI_ADD_SEL_ENTRY_CMD; >> + msg.data = data; >> + msg.data_len = 16; >> + >> + memset(data, 0, sizeof(data)); >> + if (timestamp) { >> + len = min(SEL_MSGSIZE_TIMESTAMP, msg_len); >> + data[2] = 0xd1; /* OEM event with timestamp */ >> + memcpy(data + 10, msg_ptr, len); >> + msg_jiffies = jiffies; /* save jiffies at timestamp */ >> + } else { >> + len = min(SEL_MSGSIZE, msg_len); >> + data[2] = 0xf1; /* OEM event without timestamp */ >> + memcpy(data + 3, msg_ptr, len); >> + } >> + >> + preempt_disable(); >> + >> + if (ipmi_get_my_address(oops_user, 0, &my_addr)) >> + goto out; >> + >> + atomic_set(&oops_counter, 2); >> + if (ipmi_request_supply_msgs(oops_user, (struct ipmi_addr *)&si, >> + 0, &msg, NULL, &oops_smi_msg, >> + &oops_recv_msg, 1) < 0) >> + goto out; >> + while (atomic_read(&oops_counter) > 0) { >> + ipmi_poll_interface(oops_user); >> + cpu_relax(); >> + } >> + >> + ++msg_count; >> + msg_len -= len; >> + msg_ptr = msg_len ? &oops_msg[len] : oops_msg; >> +out: >> + preempt_enable(); >> +} >> + >> +static void ipmi_oops_console_sync(void) >> +{ >> + if (!oops_user || !msg_len || msg_count >= msg_limit) >> + return; >> + >> + if (jiffies > (msg_jiffies + TIMESTAMP_INTERVAL)) { >> + if (msg_ptr != oops_msg) >> + ipmi_oops_console_log_to_sel(0); >> + if (msg_len >= SEL_MSGSIZE_TIMESTAMP) >> + ipmi_oops_console_log_to_sel(1); >> + return; >> + } >> + if (msg_len >= SEL_MSGSIZE) >> + ipmi_oops_console_log_to_sel(0); >> +} >> + >> +static void >> +ipmi_oops_console_write(struct console *con, const char *s, unsigned int >> count) >> +{ >> + unsigned int size; >> + >> + if (likely(!oops_in_progress)) { >> + ipmi_oops_console_log_to_sel(0); >> + return; >> + } >> + >> + if (unlikely(!oops_user)) >> + return; >> + >> + while (msg_count < msg_limit && count > 0) { >> + size = min(SEL_MSGSIZE - msg_len, count); >> + memcpy(msg_ptr + msg_len, s, size); >> + msg_len += size; >> + s += size; >> + count -= size; >> + ipmi_oops_console_sync(); >> + } >> +} >> + >> +static struct console oops_console = { >> + .name = "ttyIPMI", >> + .write = ipmi_oops_console_write, >> + .unblank = ipmi_oops_console_sync, >> + .index = -1, >> +}; >> + >> +static void ipmi_oops_recv(struct ipmi_recv_msg *msg, void *data) >> +{ >> + ipmi_free_recv_msg(msg); >> +} >> + >> +static struct ipmi_user_hndl ipmi_handler = { >> + .ipmi_recv_hndl = ipmi_oops_recv, >> +}; >> + >> +static void ipmi_register_oops_console(int intf) >> +{ >> + int ret; >> + >> + ret = ipmi_create_user(intf, &ipmi_handler, NULL, &oops_user); >> + if (ret < 0) { >> + printk(KERN_ERR PFX "unable to create user\n"); >> + return; >> + } >> + >> + oops_intf = intf; >> + >> + register_console(&oops_console); >> + >> + printk(KERN_INFO PFX "ready\n"); >> +} >> + >> +static void ipmi_unregister_oops_console(int intf) >> +{ >> + unregister_console(&oops_console); >> + >> + ipmi_destroy_user(oops_user); >> + oops_user = NULL; >> + oops_intf = -1; >> +} >> + >> +static void ipmi_new_smi(int if_num, struct device *dev) >> +{ >> + ipmi_register_oops_console(if_num); >> +} >> + >> +static void ipmi_smi_gone(int if_num) >> +{ >> + ipmi_unregister_oops_console(if_num); >> +} >> + >> +static struct ipmi_smi_watcher smi_watcher = { >> + .owner = THIS_MODULE, >> + .new_smi = ipmi_new_smi, >> + .smi_gone = ipmi_smi_gone, >> +}; >> + >> +static int __init ipmi_oops_console_init(void) >> +{ >> + int ret; >> + >> + ret = ipmi_smi_watcher_register(&smi_watcher); >> + if (ret) { >> + printk(KERN_ERR PFX "unable to register smi watcher\n"); >> + return ret; >> + } >> + >> + printk(KERN_INFO PFX "driver initialized\n"); >> + >> + return ret; >> +} >> +module_init(ipmi_oops_console_init); >> + >> +static void __exit ipmi_oops_console_exit(void) >> +{ >> + if (oops_intf >= 0) >> + ipmi_unregister_oops_console(oops_intf); >> +} >> +module_exit(ipmi_oops_console_exit); >> + >> +MODULE_LICENSE("GPL"); >> +MODULE_AUTHOR("Hiroshi Shimamoto <[email protected]>"); >> +MODULE_DESCRIPTION("oops console handler based upon the IPMI interface."); >> > > ------------------------------------------------------------------------------ _______________________________________________ Openipmi-developer mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openipmi-developer
