2011-02-01 09:30:00

by Cong Wang

[permalink] [raw]
Subject: Re: [RFC][PATCH] kmsg_dumper for NVRAM

On Mon, Jan 31, 2011 at 11:21:17AM -0500, Seiji Aguchi wrote:
>Hi,
>
>This prototype patch introduces kmsg_dumper for NVRAM(Non-Volatile RAM).
>

Hi,

This looks like what Tony wanted, pstore.

...

>[Patch Description]
>This patch adds following boot paremeters.
>
> - nvram_kmsg_dump_enable
> Enable kmsg_dumper for NVRAM with UEFI.
>
> - nvram_kmsg_dump_len
> Size of kernel messages dumped to NVRAM.
> default size is 1KB.(because I would like to use efivars for reading them from userspace.)
> Maximum size is 32KB.
>
>On the next boot, sysfs files are created as follows and through these files we can see
>the kernel messages stored in NVRAM.
>
> /sys/firmware/efi/vars/LinuxKmsgDump001-8be4df61-93ca-11d2-aa0d-00e098032b8c/data
> /sys/firmware/efi/vars/LinuxKmsgDump002-8be4df61-93ca-11d2-aa0d-00e098032b8c/data
> .
> .
> /sys/firmware/efi/vars/LinuxKmsgDump032-8be4df61-93ca-11d2-aa0d-00e098032b8c/data
>
>  - Size of each entry is 1KB. 32 entries are created at a maximum.
>  - "8be4df61-93ca-11d2-aa0d-00e098032b8c" is EFI_GLOBAL_VARIABLE which is defined in
> UEFI specification.
>

So, 'cat /sys/firmware/efi/vars/LinuxKmsgDump*/data' will show
the whole kernel messages? And in the right order?

Also ,will these data be flushed after the next next boot? If not, how
can they be flushed/deleted?


>
>---
> Documentation/kernel-parameters.txt | 9 +++
> arch/ia64/kernel/efi.c | 4 +
> arch/x86/platform/efi/efi.c | 135 +++++++++++++++++++++++++++++++++++
> include/linux/efi.h | 4 +
> init/main.c | 5 +-
> 5 files changed, 156 insertions(+), 1 deletions(-)


Some comments below.


>+static int __init setup_nvram_kmsg_dump_enable(char *arg)
>+{
>+ nvram_kmsg_dump_enabled = 1;
>+ return 0;
>+}
>+__setup("nvram_kmsg_dump_enable", setup_nvram_kmsg_dump_enable);
>+
>+static int __init setup_nvram_kmsg_dump_len(char *str)
>+{
>+ unsigned size = memparse(str, &str);

You ignored errors here.

>+
>+ if (!efi_enabled) {
>+ printk(KERN_INFO "setup_nvram_kmsg_dump_len: EFI is disabled\n");
>+ return 1;
>+ }
>+
>+ if (size)
>+ size = roundup_pow_of_two(size);
>+ if (size > nvram_kmsg_dump_len) {
>+ char *new_nvram_kmsg_dump;
>+
>+ new_nvram_kmsg_dump = alloc_bootmem(size);
>+ if (!new_nvram_kmsg_dump) {
>+ printk(KERN_WARNING "nvram_kmsg_dump_len: \
>+allocation failed\n");

We don't split strings like this.

>+ return 1;
>+ }
>+ nvram_kmsg_dump_len = size;
>+ nvram_kmsg_dump_buf = new_nvram_kmsg_dump;
>+ }
>+ printk(KERN_NOTICE "nvram_kmsg_dump_len: %d\n", nvram_kmsg_dump_len);
>+
>+ return 0;
>+
>+}
>+__setup("nvram_kmsg_dump_len=", setup_nvram_kmsg_dump_len);
>+
>+static void nvram_do_kmsg_dump(struct kmsg_dumper *dumper,
>+ enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
>+ const char *s2, unsigned long l2)
>+{
>+ unsigned long s1_start, s2_start, l1_cpy, l2_cpy;
>+ unsigned long attribute = 0xf, total, tmp, cpy_size;
>+ int i;
>+ efi_status_t efi_status;
>+ void *tmp_buf;
>+
>+ l2_cpy = min(l2, (unsigned long)nvram_kmsg_dump_len);
>+ l1_cpy = min(l1, (unsigned long)nvram_kmsg_dump_len - l2_cpy);
>+
>+ s2_start = l2 - l2_cpy;
>+ s1_start = l1 - l1_cpy;
>+
>+ memcpy(nvram_kmsg_dump_buf, s1 + s1_start, l1_cpy);
>+ memcpy(nvram_kmsg_dump_buf + l1_cpy, s2 + s2_start, l2_cpy);
>+
>+ /* initialize */
>+ for (i = 0; i < MAX_ENTRY; i++)
>+ efi.set_variable(kmsg_dump_value_utf16[i],
>+ &EFI_GLOBAL_VARIABLE_GUID,
>+ attribute, 0, NULL);
>+
>+ /* write data */
>+ total = l1_cpy + l2_cpy;
>+ tmp_buf = (void *)nvram_kmsg_dump_buf + total;
>+ cpy_size = 0;
>+ for (i = 0; i < MAX_ENTRY; i++) {
>+ tmp = min(total - cpy_size, (unsigned long)SET_VARIABLE_LEN);
>+ tmp_buf -= tmp;
>+ efi_status = efi.set_variable(kmsg_dump_value_utf16[i],
>+ &EFI_GLOBAL_VARIABLE_GUID,
>+ attribute, tmp, tmp_buf);
>+ if (efi_status) {
>+ printk(KERN_WARNING "nvram_do_kmsg_dump: \
>+set_variable %d failed 0x%lx\n", i, efi_status);

Ditto.

>+ efi.set_variable(kmsg_dump_value_utf16[i],
>+ &EFI_GLOBAL_VARIABLE_GUID,
>+ attribute, 0, NULL);
>+ tmp_buf += tmp;
>+ cpy_size -= tmp;
>+ }
>+ cpy_size += tmp;
>+ if (cpy_size >= total)
>+ break;
>+ }
>+}
>+
>+void nvram_kmsg_dump_init(void)
>+{
>+
>+ int i, outlen, err;
>+
>+ for (i = 0; i < MAX_ENTRY; i++) {
>+ snprintf(kmsg_dump_value, sizeof(kmsg_dump_value),
>+ "%s%04d", LINUX_KMSG_DUMP_PREFIX, i + 1);
>+ outlen = utf8s_to_utf16s((u8 *)kmsg_dump_value,
>+ sizeof(kmsg_dump_value),
>+ (wchar_t *)kmsg_dump_value_utf16[i]);
>+ if (outlen != LINUX_KMSG_DUMP_LEN - 1) {
>+ printk(KERN_ERR
>+ "nvram_kmsg_dump_init: utf8s_to_utf16s %d\n",
>+ outlen);
>+ return;
>+ }
>+ }
>+
>+ memset(&nvram_kmsg_dumper, 0, sizeof(nvram_kmsg_dumper));


You don't need to memset a static gloabl var to 0.


>+ nvram_kmsg_dumper.dump = nvram_do_kmsg_dump;
>+ err = kmsg_dump_register(&nvram_kmsg_dumper);
>+ if (err) {
>+ printk(KERN_ERR "nvram_kmsg_dump_init: kmsg_dump_register %d\n",
>+ err);
>+ return;
>+ }
>+ printk(KERN_NOTICE "nvram_kmsg_dump initialized\n");
>+
>+ return;
>+}
>diff --git a/include/linux/efi.h b/include/linux/efi.h
>index fb737bc..d0d1a3c 100644
>--- a/include/linux/efi.h
>+++ b/include/linux/efi.h
>@@ -300,6 +300,7 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource,
> extern unsigned long efi_get_time(void);
> extern int efi_set_rtc_mmss(unsigned long nowtime);
> extern struct efi_memory_map memmap;
>+extern void nvram_kmsg_dump_init(void);
>
> /**
> * efi_range_is_wc - check the WC bit on an address range
>@@ -333,11 +334,14 @@ extern int __init efi_setup_pcdp_console(char *);
> #ifdef CONFIG_EFI
> # ifdef CONFIG_X86
> extern int efi_enabled;
>+ extern int nvram_kmsg_dump_enabled;
> # else
> # define efi_enabled 1
>+# define nvram_kmsg_dump_enabled 1


There is a global var with the same name, right?


2011-02-01 19:47:13

by Luck, Tony

[permalink] [raw]
Subject: RE: [RFC][PATCH] kmsg_dumper for NVRAM

> This looks like what Tony wanted, pstore.

Yes - this looks like another means to the same end (making console log
Available after a crash).

I wonder whether you could use my pstore file system interface
for this ... you'd need to write a backend that used EFI variable
space to save the pieces of a console log, in much the same way
that I used ERST to stash the pieces.

This might be a bit messy - but I think that it would be
worth doing in order to provide a single user interface
to the kmsg_dump on different architectures, regardless
of the underlying storage method used. I.e. the OS
vendors would just have to write startup scripts to glean
information from /dev/pstore and clear it by removing the
files there. Rather than having one set of scripts that
looks at EFI variables for machines that use that, a different
set for machines that have the sparc64 method of saving in
some special area of ram, and yet another set for a machine
that has some other motherboard magical non volatile storage
that hasn't been designed yet.

-Tony

????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m???? ????????I?

2011-02-03 21:12:17

by Seiji Aguchi

[permalink] [raw]
Subject: RE: [RFC][PATCH] kmsg_dumper for NVRAM

Hi Tony,

>I wonder whether you could use my pstore file system interface
>for this ... you'd need to write a backend that used EFI variable
>space to save the pieces of a console log, in much the same way
>that I used ERST to stash the pieces.
>
>This might be a bit messy - but I think that it would be
>worth doing in order to provide a single user interface
>to the kmsg_dump on different architectures, regardless
>of the underlying storage method used.

I will check whether I could use your pstore file system interface.
Could you please send your latest patch to me?

Seiji

>-----Original Message-----
>From: Luck, Tony [mailto:[email protected]]
>Sent: Tuesday, February 01, 2011 2:47 PM
>To: Américo Wang; Seiji Aguchi
>Cc: [email protected]; Yu, Fenghua; [email protected]; [email protected]; [email protected]; [email protected];
>[email protected]; [email protected]; [email protected]; [email protected]; [email protected];
>[email protected]; [email protected]; [email protected]; [email protected];
>[email protected]; Satoru Moriya
>Subject: RE: [RFC][PATCH] kmsg_dumper for NVRAM
>
>> This looks like what Tony wanted, pstore.
>
>Yes - this looks like another means to the same end (making console log
>Available after a crash).
>
>I wonder whether you could use my pstore file system interface
>for this ... you'd need to write a backend that used EFI variable
>space to save the pieces of a console log, in much the same way
>that I used ERST to stash the pieces.
>
>This might be a bit messy - but I think that it would be
>worth doing in order to provide a single user interface
>to the kmsg_dump on different architectures, regardless
>of the underlying storage method used. I.e. the OS
>vendors would just have to write startup scripts to glean
>information from /dev/pstore and clear it by removing the
>files there. Rather than having one set of scripts that
>looks at EFI variables for machines that use that, a different
>set for machines that have the sparc64 method of saving in
>some special area of ram, and yet another set for a machine
>that has some other motherboard magical non volatile storage
>that hasn't been designed yet.
>
>-Tony

????{.n?+???????+%?????ݶ??w??{.n?+????{??G?????{ay?ʇڙ?,j??f???h?????????z_??(?階?ݢj"???m??????G????????????&???~???iO???z??v?^?m???? ????????I?