Initial implementation of kdump for ARM
Subsystems (4)
v2 cover Initial implementation of kdump for ARM
Hello,
This is re-send of the series. I didn't receive any comments on this but we found few minor things during in-house review which are incorporated.
Changes to v1:
- corrected kernel-doc for crash_setup_regs()
- check return value of ioremap() in copy_oldmem_page()
Changes to RFC version:
- crash_setup_regs() uses Russell's suggestion for saving registers
- copy_oldmem_page() code is changed to use ioremap()
- there is no need for special 'mem=' parameters
I've tested this on N900 and beagleboard.
Thanks,
Mw
Mika Westerberg (8):
arm: kdump: reserve memory for crashkernel
arm: kdump: implement crash_setup_regs()
arm: kdump: implement machine_crash_shutdown()
arm: kdump: skip indirection page when crashing
arm: kdump: implement copy_oldmem_page()
arm: allow passing an ELF64 header to elf_check_arch()
arm: kdump: add support for elfcorehdr= parameter
arm: kdump: add CONFIG_CRASH_DUMP Kconfig option
arch/arm/Kconfig | 12 ++++++ arch/arm/include/asm/elf.h | 4 +- arch/arm/include/asm/kexec.h | 22 +++++++++- arch/arm/kernel/Makefile | 1 + arch/arm/kernel/crash_dump.c | 60 +++++++++++++++++++++++++++++ arch/arm/kernel/elf.c | 6 ++- arch/arm/kernel/machine_kexec.c | 4 ++ arch/arm/kernel/relocate_kernel.S | 6 +++ arch/arm/kernel/setup.c | 76 +++++++++++++++++++++++++++++++++++++ 9 files changed, 184 insertions(+), 7 deletions(-) create mode 100644 arch/arm/kernel/crash_dump.c
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
PATCH v2 1/8 arm: kdump: reserve memory for crashkernel
Implemented ARM support for command line option "crashkernel=size@start" which allows user to reserve some memory for a dump capture kernel.
--- arch/arm/kernel/setup.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 51 insertions(+), 0 deletions(-)
arch/arm/kernel/setup.c +51 -0
@@ -19,6 +19,7 @@#include <linux/seq_file.h> #include <linux/screen_info.h> #include <linux/init.h> +#include <linux/kexec.h> #include <linux/root_dev.h> #include <linux/cpu.h> #include <linux/interrupt.h>
@@ -661,6 +662,55 @@ static int __init customize_machine(void) }arch_initcall (customize_machine); +#ifdef CONFIG_KEXEC +static inline unsigned long long get_total_mem (void ) +{ +unsigned long total; + + total = max_low_pfn - min_low_pfn; +return total <<PAGE_SHIFT ; +} + +/** +* reserve_crashkernel() - reserves memory are for crash kernel +* +* This function reserves memory area given in "crashkernel=" kernel command +* line parameter. The memory reserved is used by a dump capture kernel when +* primary kernel is crashing. +*/ +static void __init reserve_crashkernel (void ) +{ +unsigned long long crash_size, crash_base; +unsigned long long total_mem; +int ret; + + total_mem =get_total_mem (); + ret =parse_crashkernel (boot_command_line, total_mem, + &crash_size, &crash_base); +if (ret) +return ; + + ret =reserve_bootmem (crash_base, crash_size,BOOTMEM_EXCLUSIVE ); +if (ret <0 ) { +printk (KERN_WARNING "crashkernel reservation failed - " +"memory is in use (0x%lx)\n" , (unsigned long )crash_base); +return ; + } + +printk (KERN_INFO "Reserving %ldMB of memory at %ldMB " +"for crashkernel (System RAM: %ldMB)\n" , + (unsigned long )(crash_size >>20 ), + (unsigned long )(crash_base >>20 ), + (unsigned long )(total_mem >>20 )); + + crashk_res.start = crash_base; + crashk_res.end = crash_base + crash_size -1 ; +insert_resource (&iomem_resource, &crashk_res); +} +#else +static inline void reserve_crashkernel (void ) {} +#endif /* CONFIG_KEXEC */ +void __init setup_arch (char **cmdline_p) {struct tag *tags = (struct tag *)&init_tags;
@@ -720,6 +770,7 @@ void __init setup_arch(char **cmdline_p)#ifdef CONFIG_SMP smp_init_cpus ();#endif +reserve_crashkernel ();cpu_init ();tcm_init ();
Signature · 7 lines
1.5.6.5 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH v2 2/8 arm: kdump: implement crash_setup_regs()
In reply to Mika WesterbergImplement machine specific function crash_setup_regs() which is responsible for storing machine state when crash occured.
--- arch/arm/include/asm/kexec.h | 22 +++++++++++++++++++--- 1 files changed, 19 insertions(+), 3 deletions(-)
arch/arm/include/asm/kexec.h +19 -3
@@ -19,10 +19,26 @@#ifndef __ASSEMBLY__ -struct kimage ; -/* Provide a dummy definition to avoid build failures. */ +/** +* crash_setup_regs() - save registers for the panic kernel +* @newregs: registers are saved here +* @oldregs: registers to be saved (may be %NULL) +* +* Function copies machine registers from @oldregs to @newregs. If @oldregs is +* %NULL then current registers are stored there. +*/ static inline void crash_setup_regs (struct pt_regs *newregs, -struct pt_regs *oldregs) { } +struct pt_regs *oldregs) +{ +if (oldregs) { +memcpy (newregs, oldregs,sizeof (*newregs)); + }else { + __asm__ __volatile__ ("stmia %0, {r0 - r15}" + : :"r" (&newregs->ARM_r0)); + __asm__ __volatile__ ("mrs %0, cpsr" + :"=r" (newregs->ARM_cpsr)); + } +}#endif /* __ASSEMBLY__ */
Signature · 7 lines
1.5.6.5 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH v2 3/8 arm: kdump: implement machine_crash_shutdown()
In reply to Mika WesterbergImplement function machine_crash_shutdown() which disables IRQs and saves machine state to ELF notes structure.
--- arch/arm/kernel/machine_kexec.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/kernel/machine_kexec.c +4 -0
@@ -43,6 +43,10 @@ void machine_shutdown(void)void machine_crash_shutdown (struct pt_regs *regs) { +local_irq_disable (); +crash_save_cpu (regs,smp_processor_id ()); + +printk (KERN_INFO "Loading crashdump kernel...\n" ); }void machine_kexec (struct kimage *image)
Signature · 7 lines
1.5.6.5 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH v2 4/8 arm: kdump: skip indirection page when crashing
In reply to Mika WesterbergWhen we are crashing there is no indirection page in place. Only control page is present.
--- arch/arm/kernel/relocate_kernel.S | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
arch/arm/kernel/relocate_kernel.S +6 -0
@@ -10,6 +10,12 @@ relocate_new_kernel: ldr r0,kexec_indirection_page ldr r1,kexec_start_address + /* + * If there is no indirection page (we are doing crashdumps) + * skip any relocation. + */ + cmp r0, #0 + beq 2f 0: /* top, read another word for the indirection page */ ldr r3, [r0],#4
Signature · 7 lines
1.5.6.5 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH v2 5/8 arm: kdump: implement copy_oldmem_page()
In reply to Mika WesterbergThis function is used by vmcore code to read a page from the old kernel memory.
--- arch/arm/kernel/Makefile | 1 + arch/arm/kernel/crash_dump.c | 60 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 0 deletions(-) create mode 100644 arch/arm/kernel/crash_dump.c
arch/arm/kernel/Makefile +1 -0
@@ -39,6 +39,7 @@ obj-$(CONFIG_ARM_THUMBEE) += thumbee.o obj-$(CONFIG_KGDB) += kgdb.o obj-$(CONFIG_ARM_UNWIND) += unwind.o obj-$(CONFIG_HAVE_TCM) += tcm.o +obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
arch/arm/kernel/crash_dump.c new file +60 -0
60 lines not on this page · raw message
Signature · 7 lines
1.5.6.5 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH v2 6/8 arm: allow passing an ELF64 header to elf_check_arch()
In reply to Mika WesterbergThis is needed to shut following compiler warning when CONFIG_PROC_VMCORE is enabled:
fs/proc/vmcore.c: In function 'parse_crash_elf64_headers':fs/proc/vmcore.c:500: warning: passing argument 1 of 'elf_check_arch' from incompatible pointer type
ELF32 and ELF64 headers have common fields of same size (namely e_ident and e_machine) which are checked in arm_elf_check_arch().
--- arch/arm/include/asm/elf.h | 4 ++-- arch/arm/kernel/elf.c | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-)
arch/arm/include/asm/elf.h +2 -2
@@ -92,8 +92,8 @@ struct elf32_hdr;/* * This is used to ensure we don't load something for the wrong architecture. */ -extern int elf_check_arch (const struct elf32_hdr *); -#define elf_check_arch elf_check_arch +extern int arm_elf_check_arch (const struct elf32_hdr *); +#define elf_check_arch (x) arm_elf_check_arch((const struct elf32_hdr *)(x))extern int arm_elf_read_implies_exec (const struct elf32_hdr *,int );#define elf_read_implies_exec (ex,stk) arm_elf_read_implies_exec(&(ex), stk)
arch/arm/kernel/elf.c +4 -2
@@ -4,11 +4,13 @@#include <linux/binfmts.h> #include <linux/elf.h> -int elf_check_arch (const struct elf32_hdr *x) +int arm_elf_check_arch (const struct elf32_hdr *x) {unsigned int eflags;/* Make sure it's an ARM executable */ +if (x->e_ident[EI_CLASS ] !=ELF_CLASS ) +return 0 ;if (x->e_machine !=EM_ARM )return 0 ;
@@ -35,7 +37,7 @@ int elf_check_arch(const struct elf32_hdr *x) }return 1 ; } -EXPORT_SYMBOL (elf_check_arch); +EXPORT_SYMBOL (arm_elf_check_arch);void elf_set_personality (const struct elf32_hdr *x) {
Signature · 7 lines
1.5.6.5 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH v2 6/8] arm: allow passing an ELF64 header to elf_check_arch()
Quoted 9 lines · Mika Westerberg
This is needed to shut following compiler warning when
CONFIG_PROC_VMCOREis enabled:
fs/proc/vmcore.c: In function 'parse_crash_elf64_headers':fs/proc/vmcore.c:500: warning: passing argument 1 of 'elf_check_arch' from incompatible pointer typeELF32 and ELF64 headers have common fields of same size (namely
e_identande_machine) which are checked inarm_elf_check_arch().
This patch is bogus - and shows the dangers of throwing casts into C code to shut up warnings without first analysing the code.
Our elf_check_arch() uses:
e_machine
e_entry
e_flags
thusly:
if (x->e_machine != EM_ARM)
if (x->e_entry & 1) {
} else if (x->e_entry & 3)
eflags = x->e_flags;Now, the Elf32 header looks like this:
typedef struct elf32_hdr{
unsigned char e_ident[EI_NIDENT]; /* 0x00 - 0x0F */
Elf32_Half e_type; /* 0x10 - 0x11 */ Elf32_Half e_machine; /* 0x12 - 0x13 */ Elf32_Word e_version; /* 0x14 - 0x17 */ Elf32_Addr e_entry; /* 0x18 - 0x1b */ Elf32_Off e_phoff; /* 0x1c - 0x1f */ Elf32_Off e_shoff; /* 0x20 - 0x23 */ Elf32_Word e_flags; /* 0x24 - 0x27 */
and Elf64 header:
typedef struct elf64_hdr {
unsigned char e_ident[EI_NIDENT]; /* 0x00 - 0x0F */
Elf64_Half e_type; /* 0x10 - 0x11 */
Elf64_Half e_machine; /* 0x12 - 0x13 */
Elf64_Word e_version; /* 0x14 - 0x17 */
Elf64_Addr e_entry; /* 0x18 - 0x1f */
Elf64_Off e_phoff; /* 0x20 - 0x27 */
Elf64_Off e_shoff; /* 0x28 - 0x2f */
Elf64_Word e_flags; /* 0x30 - 0x33 */
Notice that e_entry and e_flags are different sizes and/or different offsets, so ARMs elf_check_arch can not work with elf64 headers. So with an ELF64 header, accessing e_flags will result in actually accessing the top half of the 64-bit e_phoff, and accessing 32-bit e_entry will get us the lower half of the 64-bit e_entry.
Now, here's the question: why does this crashkernel stuff want to parse a 64-bit ELF header on a 32-bit only platform where the crashing kernel will never generate a 64-bit ELF core file?
Re: [PATCH v2 6/8] arm: allow passing an ELF64 header to elf_check_arch()
Quoted 48 lines · ext Russell King - ARM Linux
Quoted 9 lines · Mika Westerberg
This is needed to shut following compiler warning when
CONFIG_PROC_VMCOREis enabled:
fs/proc/vmcore.c: In function 'parse_crash_elf64_headers':fs/proc/vmcore.c:500: warning: passing argument 1 of 'elf_check_arch' from incompatible pointer typeELF32 and ELF64 headers have common fields of same size (namely
e_identande_machine) which are checked inarm_elf_check_arch().This patch is bogus - and shows the dangers of throwing casts into C code to shut up warnings without first analysing the code.
Our
elf_check_arch()uses:
e_machine
e_entry
e_flags
thusly:if (x->e_machine != EM_ARM) if (x->e_entry & 1) { } else if (x->e_entry & 3) eflags = x->e_flags;Now, the Elf32 header looks like this:
typedef struct elf32_hdr{
unsigned char e_ident[EI_NIDENT]; /*0x00-0x0F*/Elf32_Half e_type; /* 0x10 - 0x11 */ Elf32_Half e_machine; /* 0x12 - 0x13 */ Elf32_Word e_version; /* 0x14 - 0x17 */ Elf32_Addr e_entry; /* 0x18 - 0x1b */ Elf32_Off e_phoff; /* 0x1c - 0x1f */ Elf32_Off e_shoff; /* 0x20 - 0x23 */ Elf32_Word e_flags; /* 0x24 - 0x27 */and Elf64 header:
typedef struct
elf64_hdr{
unsigned char e_ident[EI_NIDENT]; /*0x00-0x0F*/
Elf64_Halfe_type; /*0x10-0x11*/
Elf64_Halfe_machine; /*0x12-0x13*/
Elf64_Worde_version; /*0x14-0x17*/
Elf64_Addre_entry; /*0x18-0x1f*/
Elf64_Offe_phoff; /*0x20-0x27*/
Elf64_Offe_shoff; /*0x28-0x2f*/
Elf64_Worde_flags; /*0x30-0x33*/
Quoted 5 lines
Notice that
e_entryande_flagsare different sizes and/or different offsets, so ARMself_check_archcan not work with elf64 headers. So with an ELF64 header, accessinge_flagswill result in actually accessing the top half of the 64-bite_phoff, and accessing 32-bite_entrywill get us the lower half of the 64-bite_entry.
Thanks for comments.
I believe that when passing ELF64 header, it fails in following checks:
/* Make sure it's an ARM executable */ if (x->e_ident[EI_CLASS] != ELF_CLASS) return 0; if (x->e_machine != EM_ARM) return 0;
ELF_CLASS is defined in arch/arm/include/asm/elf.h:
#define ELF_CLASS ELFCLASS32
So if class is different than ELFCLASS32 it returns 0 and never even try to access other fields, right?
Quoted 3 lines
Now, here's the question: why does this crashkernel stuff want to parse a 64-bit ELF header on a 32-bit only platform where the crashing kernel will never generate a 64-bit ELF core file?
I really don't know but fs/proc/vmcore.c is coded in such way that it supports both types of ELF headers. It however, passes the header to elf_check_arch() which in our case should fail if it is something else than ELF32 header.
Thanks,
MW
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH v2 6/8] arm: allow passing an ELF64 header to elf_check_arch()
Quoted 8 lines · Mika Westerberg
I believe that when passing ELF64 header, it fails in following checks:
/* Make sure it's an ARM executable */ if (x->e_ident[EI_CLASS] != ELF_CLASS) return 0; if (x->e_machine != EM_ARM) return 0;
Quoted 6 lines
ELF_CLASSis defined inarch/arm/include/asm/elf.h:#define
ELF_CLASSELFCLASS32So if class is different than ELFCLASS32 it returns 0 and never even try to access other fields, right?
Yes.
Quoted 7 lines
Quoted 3 lines
Now, here's the question: why does this crashkernel stuff want to parse a 64-bit ELF header on a 32-bit only platform where the crashing kernel will never generate a 64-bit ELF core file?
I really don't know but
fs/proc/vmcore.cis coded in such way that it supports both types of ELF headers. It however, passes the header toelf_check_arch()which in our case should fail if it is something else than ELF32 header.
There's other arches which want elf_check_arch to be a function call, so I think my question needs to be looked at more closely - and possibly the code changed such that we don't end up with this situation.
Maybe a cleaner solution would be for vmcore.c to split its calls to elf_check_arch() - to be elf32_check_arch() and elf64_check_arch() ? Platforms where it's just a macro can define both to be elf_check_arch() but those where only one flavour is supported should define the unsupported flavour to zero - which incidentally would allow the compiler to optimize away the unnecessary parts of parse_crash_elf*_headers().
Re: [PATCH v2 6/8] arm: allow passing an ELF64 header to elf_check_arch()
Quoted 5 lines · ext Russell King - ARM Linux
Quoted 5 lines
Quoted 4 lines
Now, here's the question: why does this crashkernel stuff want to parse a 64-bit ELF header on a 32-bit only platform where the crashing kernel will never generate a 64-bit ELF core file?
Quoted 7 lines
Quoted 3 lines
I really don't know but
fs/proc/vmcore.cis coded in such way that it supports both types of ELF headers. It however, passes the header toelf_check_arch()which in our case should fail if it is something else than ELF32 header.There's other arches which want
elf_check_archto be a function call, so I think my question needs to be looked at more closely - and possibly the code changed such that we don't end up with this situation.
I quickly checked and it seems that only one arch in addition to ARM wants this to be a function:
arch/frv/include/asm/elf.h:
...
extern int elf_check_arch(const struct elf32_hdr *hdr);
and they don't (yet) support kdump.
Quoted 2 lines
Maybe a cleaner solution would be for
vmcore.cto split its calls toelf_check_arch()- to beelf32_check_arch()andelf64_check_arch()?
True. However, there already is another macro in vmcore.c:vmcore_elf_check_arch() which is used by 64-bit code. So adding 32- and 64-bit versions of elf_check_arch() might be overkill.
Also elf_check_arch() is used outside vmcore.c as well.
Quoted 4 lines
Platforms where it's just a macro can define both to be
elf_check_arch()but those where only one flavour is supported should define the unsupported flavour to zero - which incidentally would allow the compiler to optimize away the unnecessary parts of parse_crash_elf*_headers().
I agree but changing these needs to be performed on every arch and it might cause regressions (at least because it is hard to test on archs that I don't have). So I'm not sure if it is worth a risk.
It's up to you, I can implement it this way also if you don't accept the current version of the patch.
Thanks again,
MW
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH v2 6/8] arm: allow passing an ELF64 header to elf_check_arch()
In reply to Russell King - ARM LinuxQuoted 1 line · ext Russell King - ARM Linux
On Mon, May 10, 2010 at 03:09:20PM +0300, Mika Westerberg wrote:
[...]
Quoted 8 lines
Quoted 3 lines
I really don't know but
fs/proc/vmcore.cis coded in such way that it supports both types of ELF headers. It however, passes the header toelf_check_arch()which in our case should fail if it is something else than ELF32 header.There's other arches which want
elf_check_archto be a function call, so I think my question needs to be looked at more closely - and possibly the code changed such that we don't end up with this situation.
Quoted 6 lines
Maybe a cleaner solution would be for
vmcore.cto split its calls toelf_check_arch()- to beelf32_check_arch()andelf64_check_arch()? Platforms where it's just a macro can define both to beelf_check_arch()but those where only one flavour is supported should define the unsupported flavour to zero - which incidentally would allow the compiler to optimize away the unnecessary parts of parse_crash_elf*_headers().
Russell,
I noticed that you applied all the kdump patches except this and the CONFIG_CRASH_DUMP patch. Thanks.
Should I update this patch as you describe above? So that we don't need to perform any casting but just have elf_check_arch() separated into 32- and 64-bit versions. Or is there something else preventing these 2 patches to be merged?
Thanks,
MW
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH v2 6/8] arm: allow passing an ELF64 header to elf_check_arch()
Hi Mika,
I have tried your patch, and it works perfect.
But there is something inconvenient that I have to modify the PHYS_OFFSET and mach/Makefile.boot
manually if I want to get a kdump capable kernel.
How about add additional configuration like CONFIG_RELOCATABLE CONFIG_PHYSICAL_STARTas x86?
This would do great help for formal usage.
Thanks,
Lei
Quoted 27 lines · Mika Westerberg
Quoted 1 line · ext Russell King - ARM Linux
On Mon, May 10, 2010 at 03:09:20PM +0300, Mika Westerberg wrote:
[...]
Quoted 8 lines
Quoted 3 lines
I really don't know but
fs/proc/vmcore.cis coded in such way that it supports both types of ELF headers. It however, passes the header toelf_check_arch()which in our case should fail if it is something else than ELF32 header.There's other arches which want
elf_check_archto be a function call, so I think my question needs to be looked at more closely - and possibly the code changed such that we don't end up with this situation.Quoted 6 lines
Maybe a cleaner solution would be for
vmcore.cto split its calls toelf_check_arch()- to beelf32_check_arch()andelf64_check_arch()? Platforms where it's just a macro can define both to beelf_check_arch()but those where only one flavour is supported should define the unsupported flavour to zero - which incidentally would allow the compiler to optimize away the unnecessary parts of parse_crash_elf*_headers().Russell,
I noticed that you applied all the kdump patches except this and the
CONFIG_CRASH_DUMPpatch. Thanks.Should I update this patch as you describe above? So that we don't need to perform any casting but just have
elf_check_arch()separated into 32- and 64-bit versions. Or is there something else preventing these 2 patches to be merged?
Quoted 8 lines
Thanks,
MW_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH v2 6/8] arm: allow passing an ELF64 header to elf_check_arch()
Hi,
Quoted 5 lines · ext Lei Wen
I have tried your patch, and it works perfect.
But there is something inconvenient that I have to modify thePHYS_OFFSETand mach/Makefile.boot
manually if I want to get a kdump capable kernel.
Yeah, it's a bit annoying. I remember that I had some plans to make it configurable but never implemented it.
Quoted 3 lines
How about add additional configuration like
CONFIG_RELOCATABLECONFIG_PHYSICAL_STARTasx86?
This would do great help for formal usage.
You are right, something like that is eventually needed. I'll try to find some time to look into that and cook up some solution.
Thanks,
MW
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
PATCH v2 7/8 arm: kdump: add support for elfcorehdr= parameter
In reply to Mika WesterbergThis parameter is used by primary kernel to pass address of vmcore header to the dump capture kernel.
--- arch/arm/kernel/setup.c | 25 +++++++++++++++++++++++++ 1 files changed, 25 insertions(+), 0 deletions(-)
arch/arm/kernel/setup.c +25 -0
@@ -20,6 +20,7 @@#include <linux/screen_info.h> #include <linux/init.h> #include <linux/kexec.h> +#include <linux/crash_dump.h> #include <linux/root_dev.h> #include <linux/cpu.h> #include <linux/interrupt.h>
@@ -711,6 +712,30 @@ static void __init reserve_crashkernel(void)static inline void reserve_crashkernel (void ) {}#endif /* CONFIG_KEXEC */ +/* +* Note: elfcorehdr_addr is not just limited to vmcore. It is also used by +* is_kdump_kernel() to determine if we are booting after a panic. Hence +* ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE. +*/ + +#ifdef CONFIG_CRASH_DUMP +/* +* elfcorehdr= specifies the location of elf core header stored by the crashed +* kernel. This option will be passed by kexec loader to the capture kernel. +*/ +static int __init setup_elfcorehdr (char *arg) +{ +char *end; + +if (!arg) +return -EINVAL ; + + elfcorehdr_addr =memparse (arg, &end); +return end > arg ?0 : -EINVAL ; +} +early_param ("elfcorehdr" , setup_elfcorehdr); +#endif /* CONFIG_CRASH_DUMP */ +void __init setup_arch (char **cmdline_p) {struct tag *tags = (struct tag *)&init_tags;
Signature · 7 lines
1.5.6.5 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH v2 8/8 arm: kdump: add CONFIG_CRASH_DUMP Kconfig option
In reply to Mika WesterbergAdd CONFIG_CRASH_DUMP configuration option which is used by dump capture kernels. Dump capture kernel must be loaded into different physical address than the primary kernel. This means that PHYS_OFFSET must be different and it also should match the 'crashkernel=size@start' value passed to primary kernel command line.
--- arch/arm/Kconfig | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-)
arch/arm/Kconfig +12 -0
@@ -1467,6 +1467,18 @@ config ATAGS_PROC Should the atags used to boot the kernel be exported in an "atags" file in procfs. Useful with kexec. +config CRASH_DUMP + bool "Build kdump crash kernel (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + Build a kernel suitable for use as kdump capture kernel. This should + be set only on dump capture kernels. Note that dump capture kernel + must be loaded into different physical address than the primary kernel + (e.g set PHYS_OFFSET and related mach/Makefile.boot parameters + to match value given in 'crashkernel=size@start'). + + For more details see Documentation/kdump/kdump.txt + endmenu menu "CPU Power Management"
Signature · 7 lines
1.5.6.5 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Quoted 8 lines · On Wed, May 05, 2010 at 08:54:12AM +0200, Westerberg Mika.1…
This is re-send of the series. I didn't receive any comments on this but we found few minor things during in-house review which are incorporated.
Changes to v1:
- corrected kernel-doc forcrash_setup_regs()
- check return value ofioremap()incopy_oldmem_page()
Quoted 6 lines
Changes to RFC version:
-crash_setup_regs()uses Russell's suggestion for saving registers
-copy_oldmem_page()code is changed to useioremap()
- there is no need for special 'mem=' parametersI've tested this on N900 and beagleboard.
Hi Russell,
Sorry to bother you with this but I wasn't sure what is going to happen with these patches. Are you planning to take them or do you want me to change something?
I already submitted these to your patch system as I didn't receive much comments (not sure was this the right thing to do, however).
In addition, I tested these on ep93xx based Sim.One board and they seem to work there as well.
Thanks,
MW
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
v2 cover Initial implementation of kdump for ARM
Quoted 22 lines · Mika Westerberg
Quoted 8 lines · On Wed, May 05, 2010 at 08:54:12AM +0200, Westerberg Mika.1…
This is re-send of the series. I didn't receive any comments on this but we found few minor things during in-house review which are incorporated.
Changes to v1:
- corrected kernel-doc forcrash_setup_regs()
- check return value ofioremap()incopy_oldmem_page()Quoted 6 lines
Changes to RFC version:
-crash_setup_regs()uses Russell's suggestion for saving registers
-copy_oldmem_page()code is changed to useioremap()
- there is no need for special 'mem=' parametersI've tested this on N900 and beagleboard.
Hi Russell,
Sorry to bother you with this but I wasn't sure what is going to happen with these patches. Are you planning to take them or do you want me to change something?
Quoted 5 lines
I already submitted these to your patch system as I didn't receive much comments (not sure was this the right thing to do, however).
In addition, I tested these on ep93xx based Sim.One board and they seem to work there as well.
Ping..
Do you have any plans for these patches? The reason I'm asking is that there are also userspace tools (namely makedumpfile and crash) which are needed for post-mortem analysis, and they depend on kernel support. Without support in mainline it makes little sense to port these to ARM.
As ARM is going to use LMB I know that patch 6116/1 "kdump: reserve memory for crashkernel" needs to be changed to use LMB instead of bootmem but that change should be quite simple.
So do you think I should rework these patches or may they be included in .36? It would be nice to know if any changes are needed.
Thanks again,
MW
v2 cover Initial implementation of kdump for ARM
Hi,
I have a question regarding these patches. It seems to me that the kexec will be done with the MMU left on for the ARMv7 case. Looking at the code in the cpu_arm926_reset() routine in arch/arm/mm/proc-arm926.S this is not the case there. Instead, the MMU is turned off and the last instruction that is fetched using the virtual address mapping is a jump to a physical address.
Shouldn't this be handled as consistently as possible for the different ARM sub-archs?
Regards,
Per Fransson
v2 cover Initial implementation of kdump for ARM
Hi,
Quoted 7 lines · Per Fransson
I have a question regarding these patches. It seems to me that the kexec will be done with the MMU left on for the ARMv7 case. Looking at the code in the
cpu_arm926_reset()routine inarch/arm/mm/proc-arm926.Sthis is not the case there. Instead, the MMU is turned off and the last instruction that is fetched using the virtual address mapping is a jump to a physical address.
This seems to be the case for both ARMv6 and ARMv7. I don't know why the MMU is not switched off there. Anyway, I've been testing this on ARMv7 and at least for panic kernel it works even when MMU is left on (didn't check but maybe the decompressor disables that before jumping to the kernel).
Quoted 2 lines
Shouldn't this be handled as consistently as possible for the different ARM sub-archs?
Yes, I guess. I'm still wondering why this hasn't been fixed already?
Regards,
MW
v2 cover Initial implementation of kdump for ARM
Quoted 8 lines · Mika Westerberg
Quoted 7 lines
I have a question regarding these patches. It seems to me that the kexec will be done with the MMU left on for the ARMv7 case. Looking at the code in the
cpu_arm926_reset()routine inarch/arm/mm/proc-arm926.Sthis is not the case there. Instead, the MMU is turned off and the last instruction that is fetched using the virtual address mapping is a jump to a physical address.
Quoted 6 lines
This seems to be the case for both ARMv6 and ARMv7. I don't know why the MMU is not switched off there. Anyway, I've been testing this on ARMv7 and at least for panic kernel it works even when MMU is left on (didn't check but maybe the decompressor disables that before jumping to the kernel).
In machine_kexec an identity mapping is set up for the user space part of the virtual address space, through a call to setup_mm_for_reboot(). I believe this mapping is only necessary because the MMU is kept on and if the kexec is done to facilitate the collection of a dump it would be nice if a large part of the page table for the crashing context has not been corrupted. Don't you agree?
Quoted 4 lines
Quoted 2 lines
Shouldn't this be handled as consistently as possible for the different ARM sub-archs?
Yes, I guess. I'm still wondering why this hasn't been fixed already?
Can't help you there, I'm afraid.
Regards,
Per
v2 cover Initial implementation of kdump for ARM
Quoted 6 lines · Per Fransson
In
machine_kexecan identity mapping is set up for the user space part of the virtual address space, through a call tosetup_mm_for_reboot(). I believe this mapping is only necessary because the MMU is kept on and if the kexec is done to facilitate the collection of a dump it would be nice if a large part of the page table for the crashing context has not been corrupted. Don't you agree?
No. The identity mapping is there so that we can safely disable the MMU and jump to the intended address.
There is an implementation defined delay between writing the control register and the point in the instruction stream that the effect of that write is seen.
The missing MMU disable for AMRv6 and ARMv7 is an oversight which needs to be resolved.
v2 cover Initial implementation of kdump for ARM
Quoted 8 lines · Russell King - ARM Linux
Quoted 6 lines · Per Fransson
In
machine_kexecan identity mapping is set up for the user space part of the virtual address space, through a call tosetup_mm_for_reboot(). I believe this mapping is only necessary because the MMU is kept on and if the kexec is done to facilitate the collection of a dump it would be nice if a large part of the page table for the crashing context has not been corrupted. Don't you agree?
Quoted 7 lines
No. The identity mapping is there so that we can safely disable the MMU and jump to the intended address.
There is an implementation defined delay between writing the control register and the point in the instruction stream that the effect of that write is seen.
But the identity mapping is only set up for user space part. It needs to be set up around the code which turns off the MMU for the case when there is no delay at all. And it would still be nice to not corrupt the page table of the crashing context.
Quoted 3 lines
The missing MMU disable for AMRv6 and ARMv7 is an oversight which needs to be resolved.
v2 cover Initial implementation of kdump for ARM
Quoted 4 lines · Per Fransson
But the identity mapping is only set up for user space part. It needs to be set up around the code which turns off the MMU for the case when there is no delay at all. And it would still be nice to not corrupt the page table of the crashing context.
Yeah, with the current version, user-space mappings of the crashing process are gone.
If they are really needed, then maybe we could do similar than x86 and set up temporary page tables and do the identity mapping there? This way the crashing process' page tables would remain untouched.
Regards,
MW
v2 cover Initial implementation of kdump for ARM
Quoted 6 lines · Mika Westerberg
Quoted 4 lines · Per Fransson
But the identity mapping is only set up for user space part. It needs to be set up around the code which turns off the MMU for the case when there is no delay at all. And it would still be nice to not corrupt the page table of the crashing context.
Quoted 7 lines
Yeah, with the current version, user-space mappings of the crashing process are gone.
If they are really needed, then maybe we could do similar than x86 and set up temporary page tables and do the identity mapping there? This way the crashing process' page tables would remain untouched.
We could move the MMU disabling to the relocate_new_kernel() routine. Before jumping there the two (if we are unlucky) page table entries (for 1 MB sections) that this routine occupies could be put into registers and an identity mapping be set up for just those entries. Once we reach relocate_new_kernel():
1) the MMU is turned off
2) relocate_new_kernel does it's stuff (not much if a crashkernel area is used)
3) the entries are restored, once we are sure the disabling has taken effect
Regards,
Per
v2 cover Initial implementation of kdump for ARM
In reply to Per FranssonQuoted 12 lines · Per Fransson
Quoted 11 lines · Russell King - ARM Linux
Quoted 6 lines · Per Fransson
In
machine_kexecan identity mapping is set up for the user space part of the virtual address space, through a call tosetup_mm_for_reboot(). I believe this mapping is only necessary because the MMU is kept on and if the kexec is done to facilitate the collection of a dump it would be nice if a large part of the page table for the crashing context has not been corrupted. Don't you agree?No. The identity mapping is there so that we can safely disable the MMU and jump to the intended address.
Quoted 6 lines
Quoted 4 lines
There is an implementation defined delay between writing the control register and the point in the instruction stream that the effect of that write is seen.
But the identity mapping is only set up for user space part.
That's because we're normally calling back into the boot loader.
Quoted 3 lines
It needs to
be set up around the code which turns off the MMU for the case when there is no delay at all.
There is always a delay as the ARM architecture is pipelined. By the time the instruction which writes to the control register has got to the writeback stage, the following instruction has long since been fetched from memory, and has probably been decoded and partially executed.
Quoted 2 lines
And it would still be nice to not corrupt the page table of the crashing context.
What you're then asking for is the crashing kernel to allocate 16K of memory to setup some page tables, and then context switch to that table so that the MMU can be turned off.
That's never going to be anywhere near reliable.
v2 cover Initial implementation of kdump for ARM
Quoted 13 lines · Russell King - ARM Linux
Quoted 12 lines · Per Fransson
Quoted 11 lines · Russell King - ARM Linux
Quoted 6 lines · Per Fransson
In
machine_kexecan identity mapping is set up for the user space part of the virtual address space, through a call tosetup_mm_for_reboot(). I believe this mapping is only necessary because the MMU is kept on and if the kexec is done to facilitate the collection of a dump it would be nice if a large part of the page table for the crashing context has not been corrupted. Don't you agree?No. The identity mapping is there so that we can safely disable the MMU and jump to the intended address.
Quoted 9 lines
Quoted 6 lines
Quoted 4 lines
There is an implementation defined delay between writing the control register and the point in the instruction stream that the effect of that write is seen.
But the identity mapping is only set up for user space part.
That's because we're normally calling back into the boot loader.
True
Quoted 10 lines
Quoted 3 lines
It needs to
be set up around the code which turns off the MMU for the case when there is no delay at all.There is always a delay as the ARM architecture is pipelined. By the time the instruction which writes to the control register has got to the writeback stage, the following instruction has long since been fetched from memory, and has probably been decoded and partially executed.
I'm sure you are right. Although I've actually come across kexec not working for this very reason, when running under Qemu. By that I'm not saying the kernel should necessarily provide work-arounds for emulator inaccuracies.
Quoted 9 lines
Quoted 2 lines
And it would still be nice to not corrupt the page table of the crashing context.
What you're then asking for is the crashing kernel to allocate 16K of memory to setup some page tables, and then context switch to that table so that the MMU can be turned off.
That's never going to be anywhere near reliable.
Well, I had another suggestion in my last mail.
Regards,
Per
v2 cover Initial implementation of kdump for ARM
Quoted 1 line · Per Fransson
Well, I had another suggestion in my last mail.
Which is going to need per-CPU type support in order to achieve. Do we really want to implement relocate_new_kernel for each of the 24 CPU types which we currently support?
v2 cover Initial implementation of kdump for ARM
Quoted 7 lines · Russell King - ARM Linux
Quoted 1 line · Per Fransson
Well, I had another suggestion in my last mail.
Which is going to need per-CPU type support in order to achieve. Do we really want to implement
relocate_new_kernelfor each of the 24 CPU types which we currently support?
Perhaps not. Couldn't the variable delay be macrofied then, i.e. a macro like
MMU_DISABLED_DELAY_AND_EXEC(<asm instr>)
which would do nothing for an appropriate amount of time and put the instruction in the last MMU mapped slot?
Regards,
Per
v2 cover Initial implementation of kdump for ARM
Quoted 9 lines · Per Fransson
Quoted 7 lines · Russell King - ARM Linux
Quoted 1 line · Per Fransson
Well, I had another suggestion in my last mail.
Which is going to need per-CPU type support in order to achieve. Do we really want to implement
relocate_new_kernelfor each of the 24 CPU types which we currently support?
Quoted 7 lines
Perhaps not. Couldn't the variable delay be macrofied then, i.e. a macro like
MMU_DISABLED_DELAY_AND_EXEC(<asm instr>)which would do nothing for an appropriate amount of time and put the instruction in the last MMU mapped slot?
This delay is not the same across various ARM implementations, and I don't think it is even reliably predictable and stable on some implementations.
Nicolas
v2 cover Initial implementation of kdump for ARM
In reply to Per FranssonQuoted 9 lines · Per Fransson
Quoted 7 lines · Russell King - ARM Linux
Quoted 1 line · Per Fransson
Well, I had another suggestion in my last mail.
Which is going to need per-CPU type support in order to achieve. Do we really want to implement
relocate_new_kernelfor each of the 24 CPU types which we currently support?
Quoted 7 lines
Perhaps not. Couldn't the variable delay be macrofied then, i.e. a macro like
MMU_DISABLED_DELAY_AND_EXEC(<asm instr>)which would do nothing for an appropriate amount of time and put the instruction in the last MMU mapped slot?
There is no "appropriate amount of time" - some CPUs depend on many effects that a "3 nops and you'll be fine" approach doesn't work.
Also, what about kernels that support multiple different CPU types.
v2 cover Initial implementation of kdump for ARM
Quoted 15 lines · Russell King - ARM Linux
Quoted 14 lines · Per Fransson
Quoted 7 lines · Russell King - ARM Linux
Quoted 1 line · Per Fransson
Well, I had another suggestion in my last mail.
Which is going to need per-CPU type support in order to achieve. Do we really want to implement
relocate_new_kernelfor each of the 24 CPU types which we currently support?Perhaps not. Couldn't the variable delay be macrofied then, i.e. a macro like
MMU_DISABLED_DELAY_AND_EXEC(<asm instr>)
Quoted 8 lines
Quoted 2 lines
which would do nothing for an appropriate amount of time and put the instruction in the last MMU mapped slot?
There is no "appropriate amount of time" - some CPUs depend on many effects that a "3 nops and you'll be fine" approach doesn't work.
Also, what about kernels that support multiple different CPU types.
Ok, I see what you're both saying about there not always being an "appropriate amount of time". But surely there must be a minimum number of instructions after which we can be sure the MMU will be off? Can't we set up the identity mapping for only the entry containing relocate_new_kernel() and then add enough NOPs at the start of that routine to cover all implementations? That way only one entry in the L1 table is over-written while keeping the MMU handling code in the different arch/arm/mm/proc-<cpu_or_arch>.S?
Also, couldn't the L1 page table entry in question be saved for posterity in a variable inside the kernel before the table is modified, together with another variable to hold information on the index in the table the entry came from.
Regards,
Per
v2 cover Initial implementation of kdump for ARM
Quoted 6 lines · ext Per Fransson
Can't we set up the identity mapping for only the entry containing
relocate_new_kernel()and then add enough NOPs at the start of that routine to cover all implementations? That way only one entry in the L1 table is over-written while keeping the MMU handling code in the different arch/arm/mm/proc-<cpu_or_arch>.S?
Did you mean something like the patch at the end of this mail? It doesn't turn off the MMU but sets up the identity mapping for the control page only. I quickly tested it on our platform and it seems to work:
crash> bt
PID: 1505 TASK: ddc51d40 CPU: 0 COMMAND: "sh"
#0 [<c00890b0>] (crash_kexec) from [<c037ecd0>] #1 [<c037ecd0>] (panic) from [<c0030544>]
#2 [<c0030544>] (die) from [<c0032630>]
#3 [<c0032630>] (__do_kernel_fault) from [<c0032804>] #4 [<c0032804>] (do_page_fault) from [<c002c2b4>] #5 [<c002c2b4>] (do_DataAbort) from [<c002ca6c>]
pc : [<c0252d74>] lr : [<c0252f54>] psr: 600000d3
sp : ddca1f18 ip : 00005d75 fp : bede761c
r10: 00000000 r9 : ddca0000 r8 : 00000007
r7 : 00000063 r6 : 00000000 r5 : 60000053 r4 : c04e0a10
r3 : 00000001 r2 : 00000000 r1 : 00000000 r0 : 00000063
Flags: nZCv IRQs off FIQs off Mode SVC_32 ISA ARM
#6 [<c002ca6c>] (__dabt_svc) from [<c0252f54>]
#7 [<c0252d74>] (sysrq_handle_crash) from [<c0252f54>]
#8 [<c0252f54>] (__handle_sysrq) from [<c0253050>]
#9 [<c0253050>] (write_sysrq_trigger) from [<c010e9bc>]#10 [<c010e9bc>] (proc_reg_write) from [<c00ca0a0>] #11 [<c00ca0a0>] (vfs_write) from [<c00ca1f4>] #12 [<c00ca1f4>] (sys_write) from [<c002cf40>]
crash> ps -a 1505
PID: 1505 TASK: ddc51d40 CPU: 0 COMMAND: "sh"
ARG: -sh
ENV: TERM=linux
PATH=/sbin:/usr/sbin:/bin:/usr/bin
USER=root
LOGNAME=root
HOME=/root
SHELL=/bin/shSo we can at least access the user stack.
However, I'm not sure what is happening with these kdump patches. If they are going in at some point maybe we can do this stuff later on as separate patches or should post a new version of the patches?
Quoted 4 lines
Also, couldn't the L1 page table entry in question be saved for posterity in a variable inside the kernel before the table is modified, together with another variable to hold information on the index in the table the entry came from.
Yeah, I think that we want to have full user-space mappings for post-mortem analysis.
Regards,
MW
Quoted 1 line
From: Mika Westerberg <[email protected]>
Subject: [PATCH] ARM: kexec: make identity mapping for control page only
With current implementation we setup 1:1 mapping for all user-space pages in order to softboot to a new kernel. This has a drawback that we cannot access those pages later on during post-mortem analysis.
This patch changes kexec to setup identity mapping for only the control page (this takes 2 PMD entries) and leaves rest of the mappings intact.
--- arch/arm/kernel/machine_kexec.c | 42 ++++++++++++++++++++++++++++++++++++-- 1 files changed, 39 insertions(+), 3 deletions(-)
arch/arm/kernel/machine_kexec.c +39 -3
@@ -7,6 +7,7 @@#include <linux/delay.h> #include <linux/reboot.h> #include <linux/io.h> +#include <asm/cputype.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> #include <asm/mmu_context.h>
@@ -16,8 +17,6 @@extern const unsigned char relocate_new_kernel[];extern const unsigned int relocate_new_kernel_size; -extern void setup_mm_for_reboot (char mode); -extern unsigned long kexec_start_address;extern unsigned long kexec_indirection_page;extern unsigned long kexec_mach_type;
@@ -49,6 +48,43 @@ void machine_crash_shutdown(struct pt_regs *regs)printk (KERN_INFO "Loading crashdump kernel...\n" ); } +/** +* setup_identity_mapping() - sets up 1:1 identity mapping for a control page +* @phys: physical address of the control page +* +* Sets up necessary 1:1 identity mapping for user-space pages covering kexec +* control page. Other user-space mappings are kept intact. +* +* TODO: We could save these 2 PMD entries and restore them in +* relocate_new_kernel() when we are sure that the MMU is off. +* This would allow us to have complete user-space mappings +* for post-mortem analysis. +*/ +static void setup_identity_mapping (unsigned long phys) +{ +unsigned long pmdval = phys &PMD_MASK ; +pgd_t *pgd; +pmd_t *pmd; + +/* +* We need to access to user-mode page tables here. For kernel threads +* we don't have any user-mode mappings so we use the context that we +* "borrowed". +*/ + pgd =pgd_offset (current->active_mm, phys); + pmd =pmd_offset (pgd, phys); + + pmdval |=PMD_SECT_AP_WRITE |PMD_SECT_AP_READ |PMD_TYPE_SECT ; +if (cpu_architecture () <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale ()) + pmdval |=PMD_BIT4 ; + + pmd[0 ] =__pmd (pmdval); + pmd[1 ] =__pmd (pmdval + (1 << (PGDIR_SHIFT -1 ))); + +flush_pmd_entry (pmd); +local_flush_tlb_all (); +} +void machine_kexec (struct kimage *image) {unsigned long page_list;
@@ -79,6 +115,6 @@ void machine_kexec(struct kimage *image)printk (KERN_INFO "Bye!\n" );cpu_proc_fin (); -setup_mm_for_reboot (0 );/* mode is not used, so just pass 0*/ +setup_identity_mapping (reboot_code_buffer_phys);cpu_reset (reboot_code_buffer_phys); }
Signature · 1 line
1.5.6.5
v2 cover Initial implementation of kdump for ARM
Quoted 13 lines · Mika Westerberg
Quoted 6 lines · ext Per Fransson
Can't we set up the identity mapping for only the entry containing
relocate_new_kernel()and then add enough NOPs at the start of that routine to cover all implementations? That way only one entry in the L1 table is over-written while keeping the MMU handling code in the different arch/arm/mm/proc-<cpu_or_arch>.S?Did you mean something like the patch at the end of this mail? It doesn't turn off the MMU but sets up the identity mapping for the control page only. I quickly tested it on our platform and it seems to work:
crash> bt
...
Quoted 2 lines
So we can at least access the user stack.
Yes, that's what I had in mind. A delay will have to be introduced at the start of relocate_new_kernel as well. And we have to make sure that it's not possible for this code to straddle two L1 page table entries, which might be the case already, I don't know. Finally, the overwritten entry needs to be stored somewhere before cleaning the caches.
Quoted 4 lines
However, I'm not sure what is happening with these kdump patches. If they are going in at some point maybe we can do this stuff later on as separate patches or should post a new version of the patches?
I'm also interested in knowing whether there's a chance of these patches going in soon.
Is the solution for saving the user-space MMU mapping we've sketched here good enough? If yes, we might as well try to do it all in one go, as far as I'm concerned. Maybe a new version of the patches is needed anyway to fix the inconsistencies between CPUs with regards to the MMU? On the other hand, if there's a chance of getting these patches in quicker as they stand, it would be nice to seize the opportunity for kdump/ARM to get a footing in mainline.
Quoted 21 lines
Quoted 4 lines
Also, couldn't the L1 page table entry in question be saved for posterity in a variable inside the kernel before the table is modified, together with another variable to hold information on the index in the table the entry came from.
Yeah, I think that we want to have full user-space mappings for post-mortem analysis.
Regards,
MWQuoted 1 line
From: Mika Westerberg<[email protected]>
Subject: [PATCH] ARM: kexec: make identity mapping for control page only
With current implementation we setup 1:1 mapping for all user-space pages in order to softboot to a new kernel. This has a drawback that we cannot access those pages later on during post-mortem analysis.
This patch changes kexec to setup identity mapping for only the control page (this takes 2 PMD entries) and leaves rest of the mappings intact.
v2 cover Initial implementation of kdump for ARM
Quoted 6 lines · ext Per Fransson
Yes, that's what I had in mind. A delay will have to be introduced at the start of
relocate_new_kernelas well. And we have to make sure that it's not possible for this code to straddle two L1 page table entries, which might be the case already, I don't know. Finally, the overwritten entry needs to be stored somewhere before cleaning the caches.
Hi,
Now that I (hopefully) understand this little bit better, I made a small change to kexec code according what you proposed. It, however creates identity mapping for the cpu_reset() function instead of relocate_new_kernel(). At least if I understand ARMv7 specs correctly, it is recommended to run the code which disables/enables the MMU with VA == PA. I also tried to just disable the MMU but if I'm not running with VA == PA, it hangs.
I'm not sure whether the MMU disabling code is correct, should we do something else before switching the MMU off? In OMAP3 it seems to work as is.
Regards,
MW
Subject: ARM: kexec: create identity mapping for cpu_reset
With current implementation we setup 1:1 mapping for all user-space pages in order to softboot to a new kernel. This has a drawback that we cannot access those pages later on during post-mortem analysis. We also leave MMU on when calling the secondary kernel.
This patch makes identity mapping for the cpu_reset() function only. This way we can be sure that we are running with VA == PA when the MMU is disabled.
relocate_new_kernel() restores the trashed 2 PMD entries which can be then used for post-mortem analysis.
--- arch/arm/kernel/machine_kexec.c | 62 ++++++++++++++++++++++++++++++++++--- arch/arm/kernel/relocate_kernel.S | 26 +++++++++++++++ arch/arm/mm/proc-v7.S | 18 +++++++++++ 3 files changed, 101 insertions(+), 5 deletions(-)
arch/arm/kernel/machine_kexec.c +57 -5
@@ -7,6 +7,7 @@#include <linux/delay.h> #include <linux/reboot.h> #include <linux/io.h> +#include <asm/cputype.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> #include <asm/mmu_context.h>
@@ -16,12 +17,13 @@extern const unsigned char relocate_new_kernel[];extern const unsigned int relocate_new_kernel_size; -extern void setup_mm_for_reboot (char mode); -extern unsigned long kexec_start_address;extern unsigned long kexec_indirection_page;extern unsigned long kexec_mach_type;extern unsigned long kexec_boot_atags; +extern unsigned long kexec_pmd_addr; +extern unsigned long kexec_pmd_val0; +extern unsigned long kexec_pmd_val1;/* * Provide a dummy crash_notes definition while crash dump arrives to arm.
@@ -49,12 +51,59 @@ void machine_crash_shutdown(struct pt_regs *regs)printk (KERN_INFO "Loading crashdump kernel...\n" ); } +/** +* setup_identity_mapping() - set up identity mapping for given address +* @paddr: physical address which is mapped +* +* This function sets up indentity mapping for the given CPU reset function. We +* do the worst case and allocate 2 PMD entries. This is due the fact that +* cpu_reset() might be split into subsequent sections. Original PMD entries are +* placed in @kexec_pmd_val0 and @kexec_pmd_val1, and address of the first PMD +* is placed in @kexec_pmd_addr. +*/ +static void setup_identity_mapping (unsigned long paddr) +{ +unsigned long pmdval = paddr &SECTION_MASK ; +pgd_t *pgd; +pmd_t *pmd; + +/* +* We need to access to user-mode page tables here. For kernel threads +* we don't have any user-mode mappings so we use the context that we +* "borrowed". +*/ + pgd =pgd_offset (current->active_mm, paddr); + pmd =pmd_offset (pgd, paddr); + +/* +* Store the both original PMD entries. These are restored later on by +* relocate_new_kernel(). +*/ + kexec_pmd_addr =__pa (pmd); + kexec_pmd_val0 = pmd[0 ]; + kexec_pmd_val1 = pmd[1 ]; + + pmdval |=PMD_SECT_AP_WRITE |PMD_SECT_AP_READ |PMD_TYPE_SECT ; +if (cpu_architecture () <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale ()) + pmdval |=PMD_BIT4 ; + +/* +* Place identity mapping for the 2 sections. +*/ + pmd[0 ] =__pmd (pmdval); + pmd[1 ] =__pmd (pmdval + (1 << (PGDIR_SHIFT -1 ))); + +flush_pmd_entry (pmd); +} +void machine_kexec (struct kimage *image) {unsigned long page_list;unsigned long reboot_code_buffer_phys;void *reboot_code_buffer; +void (*reset_fn)(unsigned long ); + reset_fn = (void (*)(unsigned long ))__pa (cpu_reset); page_list = image->head &PAGE_MASK ;
@@ -69,16 +118,19 @@ void machine_kexec(struct kimage *image) kexec_mach_type = machine_arch_type; kexec_boot_atags = image->start -KEXEC_ARM_ZIMAGE_OFFSET +KEXEC_ARM_ATAGS_OFFSET ; +setup_identity_mapping (__pa (cpu_reset)); +local_flush_tlb_all (); +/* copy our kernel relocation code to the control code page */ memcpy (reboot_code_buffer, relocate_new_kernel, relocate_new_kernel_size); -flush_icache_range ((unsigned long ) reboot_code_buffer, (unsigned long ) reboot_code_buffer +KEXEC_CONTROL_PAGE_SIZE );printk (KERN_INFO "Bye!\n" );cpu_proc_fin (); -setup_mm_for_reboot (0 );/* mode is not used, so just pass 0*/ -cpu_reset (reboot_code_buffer_phys); + +/* call the CPU reset function through the identity mapping */ + (*reset_fn)(reboot_code_buffer_phys); }
arch/arm/kernel/relocate_kernel.S +26 -0
@@ -11,6 +11,17 @@ relocate_new_kernel: ldr r1,kexec_start_address /* + * First restore the 2 PMD entries that were thrashed when identity + * mapping was created for CPU reset function. These are needed for + * possible post-mortem analysis. + */ + ldr r2, kexec_pmd_addr + ldr r3, kexec_pmd_val0 + ldr r4, kexec_pmd_val1 + str r3, [r2], #4 + str r4, [r2] + + /* * If there is no indirection page (we are doing crashdumps) * skip any relocation. */
@@ -76,6 +87,21 @@ kexec_mach_type: kexec_boot_atags: .long 0x0 +/* + * machine_kexec() changes user-space mappings for cpu_reset() function. The 2 + * original values are stored here, and will be restored when + * relocate_new_kernel is called (with MMU off). + */ + .globl kexec_pmd_addr + .globl kexec_pmd_val0 + .globl kexec_pmd_val1 +kexec_pmd_addr: + .long 0x0 +kexec_pmd_val0: + .long 0x0 +kexec_pmd_val1: + .long 0x0 + relocate_new_kernel_end: .globl relocate_new_kernel_size
arch/arm/mm/proc-v7.S +18 -0
@@ -62,10 +62,28 @@ ENDPROC(cpu_v7_proc_fin) * same state as it would be if it had been reset, and branch * to what would be the reset vector. * + * This function should be called only when VA == PA (e.g make indentity + * mapping for the function and jump into __pa(cpu_v7_reset)). + * * - loc - location to jump to for soft reset */ .align 5 ENTRY(cpu_v7_reset) +#ifdef CONFIG_MMU + mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs +#endif + mrc p15, 0, ip, c1, c0 + bic ip, ip, #0x0001 + mcr p15, 0, ip, c1, c0 @ turn MMU off + + /* + * Now provide a small delay which should guarantee that MMU is really + * switched off. + */ + nop; nop; nop + nop; nop; nop + + /* and jump to the reset address */ mov pc, r0 ENDPROC(cpu_v7_reset)
Signature · 1 line
1.5.6.5
v2 cover Initial implementation of kdump for ARM
In reply to Russell King - ARM LinuxQuoted 32 lines · Russell King - ARM Linux
Quoted 12 lines · Per Fransson
Quoted 11 lines · Russell King - ARM Linux
Quoted 6 lines · Per Fransson
In
machine_kexecan identity mapping is set up for the user space part of the virtual address space, through a call tosetup_mm_for_reboot(). I believe this mapping is only necessary because the MMU is kept on and if the kexec is done to facilitate the collection of a dump it would be nice if a large part of the page table for the crashing context has not been corrupted. Don't you agree?No. The identity mapping is there so that we can safely disable the MMU and jump to the intended address.
Quoted 6 lines
Quoted 4 lines
There is an implementation defined delay between writing the control register and the point in the instruction stream that the effect of that write is seen.
But the identity mapping is only set up for user space part.
That's because we're normally calling back into the boot loader.
Quoted 3 lines
It needs to
be set up around the code which turns off the MMU for the case when there is no delay at all.There is always a delay as the ARM architecture is pipelined. By the time the instruction which writes to the control register has got to the writeback stage, the following instruction has long since been fetched from memory, and has probably been decoded and partially executed.
Quoted 8 lines
Quoted 2 lines
And it would still be nice to not corrupt the page table of the crashing context.
What you're then asking for is the crashing kernel to allocate 16K of memory to setup some page tables, and then context switch to that table so that the MMU can be turned off.
That's never going to be anywhere near reliable.
Can this be addresses by allocating the memory at the time that kdump is loaded rather than when it is executed (because of a crash)?
IIRC, x86 uses a double page table approach and it is done reliably.
v2 cover Initial implementation of kdump for ARM
Quoted 7 lines · Simon Horman
Quoted 7 lines
Quoted 2 lines
And it would still be nice to not corrupt the page table of the crashing context.
What you're then asking for is the crashing kernel to allocate 16K of memory to setup some page tables, and then context switch to that table so that the MMU can be turned off.
Quoted 8 lines
Quoted 1 line
That's never going to be anywhere near reliable.
Can this be addresses by allocating the memory at the time that kdump is loaded rather than when it is executed (because of a crash)?
IIRC, x86 uses a double page table approach and it is done reliably.
We could do that.
Admittedly, this is getting very "hacky", but if we want to set up a new L1 page table in which we really only need one entry (for the code running until we're sure the MMU is off), we could set up this one entry all by itself placed at just the right offset within a page and then set the PGD to point at the start of that page (since we're talking about mappings for 0x00000000-0x40000000). The rest of the page could still be used for other stuff - and even if this turns out to be more trouble than it's worth, the other 12KB do not need to be allocated.
However, I still think we could work within the old L1 table and:
1) only modify one entry
2) save that entry before overwriting it
Regards,
Per