Skip to contentSkip to conversation

arm64 kexec kernel patches v11

PATCH In review Geoff Levand 3 participants 18 messages Nov 6, 2015 – Nov 10, 2015

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

cover arm64 kexec kernel patches v11

Hi All,

This series adds the core support for kexec re-boot and kdump on ARM64. This version of the series combines Takahiro's kdump patches with my kexec patches.

To load a second stage kernel and execute a kexec re-boot or to work with kdump on ARM64 systems a series of patches to kexec-tools [2], which have not yet been merged upstream, are needed.

I have tested kexec with the ARM Foundation model, and Takahiro has reported that kdump is working on the 96boards HiKey developer board. Kexec on EFI systems works correctly. More ACPI + kexec testing is needed.

Patch 1 here moves the macros from proc-macros.S to asm/assembler.h so that the dcache_line_size macro it defines can be uesd by kexec's relocate kernel routine.

Patches 2 & 3 rework the ARM64 hcall mechanism to give the CPU reset routines the ability to switch exception levels from EL1 to EL2 for kernels that were entered in EL2.

Patch 4 allows KVM to handle a CPU reset.

Patches 5 & 6 add back the ARM64 CPU reset support that was recently removed from the kernel.

Patches 7 - 9 add kexec support.

Patches 10-15 add kdump support.

Please consider all patches for inclusion.

Changes since v10:

o Move the flush of the new image from arm64_relocate_new_kernel to machine_kexec.
o Pass values to arm64_relocate_new_kernel in registers, not in global variables.
o Fixups to setting the sctlr_el1 and sctlr_el2 flags.

[1] https://git.kernel.org/cgit/linux/kernel/git/geoff/linux-kexec.git
[2] https://git.kernel.org/cgit/linux/kernel/git/geoff/kexec-tools.git

-Geoff

The following changes since commit 6a13feb9c82803e2b815eca72fa7a9f5561d7861:

Linux 4.3 (2015-11-01 16:05:25 -0800)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/geoff/linux-kexec.git kexec-v11

for you to fetch changes up to 2b09b58c7586a4ca929400327d394fec3135fdd0:

arm64: kdump: relax BUG_ON() if more than one cpus are still active (2015-11-06 10:38:13 -0800)

----------------------------------------------------------------
AKASHI Takahiro (7):
arm64: kvm: allows kvm cpu hotplug
arm64: kdump: reserve memory for crash dump kernel
arm64: kdump: implement machine_crash_shutdown()
arm64: kdump: add kdump support
arm64: kdump: update a kernel doc
arm64: kdump: enable kdump in the arm64 defconfig
arm64: kdump: relax BUG_ON() if more than one cpus are still active

Geoff Levand (8):
arm64: Fold proc-macros.S into assembler.h
arm64: Convert hcalls to use HVC immediate value
arm64: Add new hcall HVC_CALL_FUNC
arm64: Add back cpu_reset routines Revert "arm64: remove dead code" arm64/kexec: Add core kexec support arm64/kexec: Add pr_devel output arm64/kexec: Enable kexec in the arm64 defconfig

 Documentation/kdump/kdump.txt       |  32 ++++-
 arch/arm/include/asm/kvm_host.h     |  10 +-
 arch/arm/include/asm/kvm_mmu.h      |   1 +
 arch/arm/kvm/arm.c                  |  79 ++++++------
 arch/arm/kvm/mmu.c                  |   5 +
 arch/arm64/Kconfig                  |  22 ++++
 arch/arm64/configs/defconfig        |   2 +
 arch/arm64/include/asm/assembler.h  |  48 ++++++-
 arch/arm64/include/asm/kexec.h      |  80 ++++++++++++
 arch/arm64/include/asm/kvm_host.h   |  16 ++-
 arch/arm64/include/asm/kvm_mmu.h    |   1 +
 arch/arm64/include/asm/mmu.h        |   1 +
 arch/arm64/include/asm/virt.h       |  49 +++++++
 arch/arm64/kernel/Makefile          |   3 +
 arch/arm64/kernel/cpu-reset.S       |  84 ++++++++++++
 arch/arm64/kernel/cpu-reset.h       |  22 ++++
 arch/arm64/kernel/crash_dump.c      |  71 +++++++++++
 arch/arm64/kernel/head.S            |   1 -
 arch/arm64/kernel/hyp-stub.S        |  43 +++++--
 arch/arm64/kernel/machine_kexec.c   | 248 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/relocate_kernel.S | 131 +++++++++++++++++++
 arch/arm64/kernel/setup.c           |   7 +-
 arch/arm64/kernel/smp.c             |  16 ++-
 arch/arm64/kvm/hyp-init.S           |  34 ++++-
 arch/arm64/kvm/hyp.S                |  44 +++++--
 arch/arm64/mm/cache.S               |   2 -
 arch/arm64/mm/init.c                |  83 ++++++++++++
 arch/arm64/mm/mmu.c                 |  11 ++
 arch/arm64/mm/proc-macros.S         |  64 ----------
 arch/arm64/mm/proc.S                |   3 -
 include/uapi/linux/kexec.h          |   1 +
 31 files changed, 1074 insertions(+), 140 deletions(-)
 create mode 100644 arch/arm64/include/asm/kexec.h
 create mode 100644 arch/arm64/kernel/cpu-reset.S
 create mode 100644 arch/arm64/kernel/cpu-reset.h
 create mode 100644 arch/arm64/kernel/crash_dump.c
 create mode 100644 arch/arm64/kernel/machine_kexec.c
 create mode 100644 arch/arm64/kernel/relocate_kernel.S
 delete mode 100644 arch/arm64/mm/proc-macros.S
Signature · 7 lines
2.5.0


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#1 lore raw

PATCH 1/15 arm64: Fold proc-macros.S into assembler.h

To allow the assembler macros defined in arch/arm64/mm/proc-macros.S to be used outside the mm code move the contents of proc-macros.S to asm/assembler.h. Also, delete proc-macros.S, and fix up all references to proc-macros.S.

---
 arch/arm64/include/asm/assembler.h | 48 +++++++++++++++++++++++++++-
 arch/arm64/kernel/head.S           |  1 -
 arch/arm64/kvm/hyp-init.S          |  1 -
 arch/arm64/mm/cache.S              |  2 --
 arch/arm64/mm/proc-macros.S        | 64 --------------------------------------
 arch/arm64/mm/proc.S               |  3 --
 6 files changed, 47 insertions(+), 72 deletions(-)
 delete mode 100644 arch/arm64/mm/proc-macros.S
arch/arm64/include/asm/assembler.h +47 -1
index b51f2cc..3b46501 100644
@@ -1,5 +1,5 @@
 /*
- * Based on arch/arm/include/asm/assembler.h
+ * Based on arch/arm/include/asm/assembler.h, arch/arm/mm/proc-macros.S
  *
  * Copyright (C) 1996-2000 Russell King
  * Copyright (C) 2012 ARM Ltd.
@@ -23,6 +23,8 @@
 #ifndef __ASM_ASSEMBLER_H
 #define __ASM_ASSEMBLER_H
 
+#include <asm/asm-offsets.h>
+#include <asm/pgtable-hwdef.h>
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
 
@@ -193,4 +195,48 @@ lr	.req	x30		// link register
 	str	\src, [\tmp, :lo12:\sym]
 	.endm
 
+/*
+ * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
+ */
+	.macro	vma_vm_mm, rd, rn
+	ldr	\rd, [\rn, #VMA_VM_MM]
+	.endm
+
+/*
+ * mmid - get context id from mm pointer (mm->context.id)
+ */
+	.macro	mmid, rd, rn
+	ldr	\rd, [\rn, #MM_CONTEXT_ID]
+	.endm
+
+/*
+ * dcache_line_size - get the minimum D-cache line size from the CTR register.
+ */
+	.macro	dcache_line_size, reg, tmp
+	mrs	\tmp, ctr_el0			// read CTR
+	ubfm	\tmp, \tmp, #16, #19		// cache line size encoding
+	mov	\reg, #4			// bytes per word
+	lsl	\reg, \reg, \tmp		// actual cache line size
+	.endm
+
+/*
+ * icache_line_size - get the minimum I-cache line size from the CTR register.
+ */
+	.macro	icache_line_size, reg, tmp
+	mrs	\tmp, ctr_el0			// read CTR
+	and	\tmp, \tmp, #0xf		// cache line size encoding
+	mov	\reg, #4			// bytes per word
+	lsl	\reg, \reg, \tmp		// actual cache line size
+	.endm
+
+/*
+ * tcr_set_idmap_t0sz - update TCR.T0SZ so that we can load the ID map
+ */
+	.macro	tcr_set_idmap_t0sz, valreg, tmpreg
+#ifndef CONFIG_ARM64_VA_BITS_48
+	ldr_l	\tmpreg, idmap_t0sz
+	bfi	\valreg, \tmpreg, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH
+#endif
+	.endm
+
 #endif	/* __ASM_ASSEMBLER_H */
arch/arm64/kernel/head.S +0 -1
index 90d09ed..9ad8b1f 100644
@@ -31,7 +31,6 @@
 #include <asm/cputype.h>
 #include <asm/memory.h>
 #include <asm/thread_info.h>
-#include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/virt.h>
arch/arm64/kvm/hyp-init.S +0 -1
index 178ba22..2e67a48 100644
@@ -20,7 +20,6 @@
 #include <asm/assembler.h>
 #include <asm/kvm_arm.h>
 #include <asm/kvm_mmu.h>
-#include <asm/pgtable-hwdef.h>
 
 	.text
 	.pushsection	.hyp.idmap.text, "ax"
arch/arm64/mm/cache.S +0 -2
index eb48d5d..9e13cb5 100644
@@ -24,8 +24,6 @@
 #include <asm/cpufeature.h>
 #include <asm/alternative.h>
 
-#include "proc-macros.S"
-
 /*
  *	flush_icache_range(start,end)
  *
arch/arm64/mm/proc-macros.S deleted +0 -64

64 lines not on this page · raw message

arch/arm64/mm/proc.S +0 -3
index e4ee7bd..456c1c5 100644
@@ -23,11 +23,8 @@
 #include <asm/assembler.h>
 #include <asm/asm-offsets.h>
 #include <asm/hwcap.h>
-#include <asm/pgtable-hwdef.h>
 #include <asm/pgtable.h>
 
-#include "proc-macros.S"
-
 #ifdef CONFIG_ARM64_64K_PAGES
 #define TCR_TG_FLAGS	TCR_TG0_64K | TCR_TG1_64K
 #else
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#2 lore raw

PATCH 2/15 arm64: Convert hcalls to use HVC immediate value

In reply to Geoff Levand

The existing arm64 hcall implementations are limited in that they only allow for two distinct hcalls; with the x0 register either zero or not zero. Also, the API of the hyp-stub exception vector routines and the KVM exception vector routines differ; hyp-stub uses a non-zero value in x0 to implement __hyp_set_vectors, whereas KVM uses it to implement kvm_call_hyp.

To allow for additional hcalls to be defined and to make the arm64 hcall API more consistent across exception vector routines, change the hcall implementations to use the 16 bit immediate value of the HVC instruction to specify the hcall type.

Define three new preprocessor macros HVC_CALL_HYP, HVC_GET_VECTORS, and HVC_SET_VECTORS to be used as hcall type specifiers and convert the existing __hyp_get_vectors(), __hyp_set_vectors() and kvm_call_hyp() routines to use these new macros when executing an HVC call. Also, change the corresponding hyp-stub and KVM el1_sync exception vector routines to use these new macros.

---
 arch/arm64/include/asm/virt.h | 27 +++++++++++++++++++++++++++
 arch/arm64/kernel/hyp-stub.S  | 32 +++++++++++++++++++++-----------
 arch/arm64/kvm/hyp.S          | 16 +++++++++-------
 3 files changed, 57 insertions(+), 18 deletions(-)
arch/arm64/include/asm/virt.h +27 -0
index 7a5df52..eb10368 100644
@@ -18,6 +18,33 @@
 #ifndef __ASM__VIRT_H
 #define __ASM__VIRT_H
 
+/*
+ * The arm64 hcall implementation uses the ISS field of the ESR_EL2 register to
+ * specify the hcall type.  The exception handlers are allowed to use registers
+ * x17 and x18 in their implementation.  Any routine issuing an hcall must not
+ * expect these registers to be preserved.
+ */
+
+/*
+ * HVC_CALL_HYP - Execute a hyp routine.
+ */
+
+#define HVC_CALL_HYP 0
+
+/*
+ * HVC_GET_VECTORS - Return the value of the vbar_el2 register.
+ */
+
+#define HVC_GET_VECTORS 1
+
+/*
+ * HVC_SET_VECTORS - Set the value of the vbar_el2 register.
+ *
+ * @x0: Physical address of the new vector table.
+ */
+
+#define HVC_SET_VECTORS 2
+
 #define BOOT_CPU_MODE_EL1	(0xe11)
 #define BOOT_CPU_MODE_EL2	(0xe12)
 
arch/arm64/kernel/hyp-stub.S +21 -11
index a272f33..017ab519 100644
@@ -22,6 +22,7 @@
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include <asm/assembler.h>
+#include <asm/kvm_arm.h>
 #include <asm/ptrace.h>
 #include <asm/virt.h>
 
@@ -53,14 +54,22 @@ ENDPROC(__hyp_stub_vectors)
 	.align 11
 
 el1_sync:
-	mrs	x1, esr_el2
-	lsr	x1, x1, #26
-	cmp	x1, #0x16
+	mrs	x18, esr_el2
+	lsr	x17, x18, #ESR_ELx_EC_SHIFT
+	and	x18, x18, #ESR_ELx_ISS_MASK
+
+	cmp	x17, #ESR_ELx_EC_HVC64
 	b.ne	2f				// Not an HVC trap
-	cbz	x0, 1f
-	msr	vbar_el2, x0			// Set vbar_el2
+
+	cmp	x18, #HVC_GET_VECTORS
+	b.ne	1f
+	mrs	x0, vbar_el2
 	b	2f
-1:	mrs	x0, vbar_el2			// Return vbar_el2
+
+1:	cmp	x18, #HVC_SET_VECTORS
+	b.ne	2f
+	msr	vbar_el2, x0
+
 2:	eret
 ENDPROC(el1_sync)
 
@@ -100,11 +109,12 @@ ENDPROC(\label)
  * initialisation entry point.
  */
 
-ENTRY(__hyp_get_vectors)
-	mov	x0, xzr
-	// fall through
 ENTRY(__hyp_set_vectors)
-	hvc	#0
+	hvc	#HVC_SET_VECTORS
 	ret
-ENDPROC(__hyp_get_vectors)
 ENDPROC(__hyp_set_vectors)
+
+ENTRY(__hyp_get_vectors)
+	hvc	#HVC_GET_VECTORS
+	ret
+ENDPROC(__hyp_get_vectors)
arch/arm64/kvm/hyp.S +9 -7
index e583613..073b8bf 100644
@@ -29,6 +29,7 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmu.h>
 #include <asm/memory.h>
+#include <asm/virt.h>
 
 #define CPU_GP_REG_OFFSET(x)	(CPU_GP_REGS + x)
 #define CPU_XREG_OFFSET(x)	CPU_GP_REG_OFFSET(CPU_USER_PT_REGS + 8*x)
@@ -924,12 +925,9 @@ __hyp_panic_str:
  * in Hyp mode (see init_hyp_mode in arch/arm/kvm/arm.c).  Return values are
  * passed in r0 and r1.
  *
- * A function pointer with a value of 0 has a special meaning, and is
- * used to implement __hyp_get_vectors in the same way as in
- * arch/arm64/kernel/hyp_stub.S.
  */
 ENTRY(kvm_call_hyp)
-	hvc	#0
+	hvc	#HVC_CALL_HYP
 	ret
 ENDPROC(kvm_call_hyp)
 
@@ -960,6 +958,7 @@ el1_sync:					// Guest trapped into EL2
 
 	mrs	x1, esr_el2
 	lsr	x2, x1, #ESR_ELx_EC_SHIFT
+	and	x0, x1, #ESR_ELx_ISS_MASK
 
 	cmp	x2, #ESR_ELx_EC_HVC64
 	b.ne	el1_trap
@@ -968,15 +967,18 @@ el1_sync:					// Guest trapped into EL2
 	cbnz	x3, el1_trap			// called HVC
 
 	/* Here, we're pretty sure the host called HVC. */
+	mov	x18, x0
 	pop	x2, x3
 	pop	x0, x1
 
-	/* Check for __hyp_get_vectors */
-	cbnz	x0, 1f
+	cmp	x18, #HVC_GET_VECTORS
+	b.ne	1f
 	mrs	x0, vbar_el2
 	b	2f
 
-1:	push	lr, xzr
+1:	/* Default to HVC_CALL_HYP. */
+
+	push	lr, xzr
 
 	/*
 	 * Compute the function address in EL2, and shuffle the parameters.
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#3 lore raw

PATCH 3/15 arm64: Add new hcall HVC_CALL_FUNC

In reply to Geoff Levand

Add the new hcall HVC_CALL_FUNC that allows execution of a function at EL2. During CPU reset the CPU must be brought to the exception level it had on entry to the kernel. The HVC_CALL_FUNC hcall will provide the mechanism needed for this exception level switch.

To allow the HVC_CALL_FUNC exception vector to work without a stack, which is needed to support an hcall at CPU reset, this implementation uses register x18 to store the link register across the caller provided function. This dictates that the caller provided function must preserve the contents of register x18.

---
 arch/arm64/include/asm/virt.h | 13 +++++++++++++
 arch/arm64/kernel/hyp-stub.S  | 13 ++++++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)
arch/arm64/include/asm/virt.h +13 -0
index eb10368..3070096 100644
@@ -45,6 +45,19 @@
 
 #define HVC_SET_VECTORS 2
 
+/*
+ * HVC_CALL_FUNC - Execute a function at EL2.
+ *
+ * @x0: Physical address of the function to be executed.
+ * @x1: Passed as the first argument to the function.
+ * @x2: Passed as the second argument to the function.
+ * @x3: Passed as the third argument to the function.
+ *
+ * The called function must preserve the contents of register x18.
+ */
+
+#define HVC_CALL_FUNC 3
+
 #define BOOT_CPU_MODE_EL1	(0xe11)
 #define BOOT_CPU_MODE_EL2	(0xe12)
 
arch/arm64/kernel/hyp-stub.S +12 -1
index 017ab519..e8febe9 100644
@@ -67,8 +67,19 @@ el1_sync:
 	b	2f
 
 1:	cmp	x18, #HVC_SET_VECTORS
-	b.ne	2f
+	b.ne	1f
 	msr	vbar_el2, x0
+	b	2f
+
+1:	cmp	x18, #HVC_CALL_FUNC
+	b.ne	2f
+	mov	x18, lr
+	mov	lr, x0
+	mov	x0, x1
+	mov	x1, x2
+	mov	x2, x3
+	blr	lr
+	mov	lr, x18
 
 2:	eret
 ENDPROC(el1_sync)
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#4 lore raw

PATCH 4/15 arm64: kvm: allows kvm cpu hotplug

In reply to Geoff Levand

From: AKASHI Takahiro <[email protected]>

The current kvm implementation on arm64 does cpu-specific initialization at system boot, and has no way to gracefully shutdown a core in terms of kvm. This prevents, especially, kexec from rebooting the system on a boot core in EL2.

This patch adds a cpu tear-down function and also puts an existing cpu-init code into a separate function, kvm_arch_hardware_disable() and kvm_arch_hardware_enable() respectively.
We don't need arm64-specific cpu hotplug hook any more.

Since this patch modifies common part of code between arm and arm64, one stub definition, __cpu_reset_hyp_mode(), is added on arm side to avoid compiling errors.

---
 arch/arm/include/asm/kvm_host.h   | 10 ++++-
 arch/arm/include/asm/kvm_mmu.h    |  1 +
 arch/arm/kvm/arm.c                | 79 ++++++++++++++++++---------------------
 arch/arm/kvm/mmu.c                |  5 +++
 arch/arm64/include/asm/kvm_host.h | 16 +++++++-
 arch/arm64/include/asm/kvm_mmu.h  |  1 +
 arch/arm64/include/asm/virt.h     |  9 +++++
 arch/arm64/kvm/hyp-init.S         | 33 ++++++++++++++++
 arch/arm64/kvm/hyp.S              | 32 ++++++++++++++--
 9 files changed, 138 insertions(+), 48 deletions(-)
arch/arm/include/asm/kvm_host.h +9 -1
index c4072d9..4c6a38c 100644
@@ -211,6 +211,15 @@ static inline void __cpu_init_hyp_mode(phys_addr_t boot_pgd_ptr,
 	kvm_call_hyp((void*)hyp_stack_ptr, vector_ptr, pgd_ptr);
 }
 
+static inline void __cpu_reset_hyp_mode(phys_addr_t boot_pgd_ptr,
+					phys_addr_t phys_idmap_start)
+{
+	/*
+	 * TODO
+	 * kvm_call_reset(boot_pgd_ptr, phys_idmap_start);
+	 */
+}
+
 static inline int kvm_arch_dev_ioctl_check_extension(long ext)
 {
 	return 0;
@@ -223,7 +232,6 @@ void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
 
 struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
 
-static inline void kvm_arch_hardware_disable(void) {}
 static inline void kvm_arch_hardware_unsetup(void) {}
 static inline void kvm_arch_sync_events(struct kvm *kvm) {}
 static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
arch/arm/include/asm/kvm_mmu.h +1 -0
index 405aa18..dc6fadf 100644
@@ -66,6 +66,7 @@ void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu);
 phys_addr_t kvm_mmu_get_httbr(void);
 phys_addr_t kvm_mmu_get_boot_httbr(void);
 phys_addr_t kvm_get_idmap_vector(void);
+phys_addr_t kvm_get_idmap_start(void);
 int kvm_mmu_init(void);
 void kvm_clear_hyp_idmap(void);
 
arch/arm/kvm/arm.c +37 -42

149 lines not on this page · raw message

arch/arm/kvm/mmu.c +5 -0
index 6984342..69b4a33 100644
@@ -1644,6 +1644,11 @@ phys_addr_t kvm_get_idmap_vector(void)
 	return hyp_idmap_vector;
 }
 
+phys_addr_t kvm_get_idmap_start(void)
+{
+	return hyp_idmap_start;
+}
+
 int kvm_mmu_init(void)
 {
 	int err;
arch/arm64/include/asm/kvm_host.h +15 -1
index ed03968..e86421a 100644
@@ -220,6 +220,7 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
 
 u64 kvm_call_hyp(void *hypfn, ...);
+void kvm_call_reset(phys_addr_t boot_pgd_ptr, phys_addr_t phys_idmap_start);
 void force_vm_exit(const cpumask_t *mask);
 void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
 
@@ -244,7 +245,20 @@ static inline void __cpu_init_hyp_mode(phys_addr_t boot_pgd_ptr,
 		     hyp_stack_ptr, vector_ptr);
 }
 
-static inline void kvm_arch_hardware_disable(void) {}
+static inline void __cpu_reset_hyp_mode(phys_addr_t boot_pgd_ptr,
+					phys_addr_t phys_idmap_start)
+{
+	/*
+	 * Call reset code, and switch back to stub hyp vectors.
+	 */
+	kvm_call_reset(boot_pgd_ptr, phys_idmap_start);
+}
+
+struct vgic_sr_vectors {
+	void	*save_vgic;
+	void	*restore_vgic;
+};
+
 static inline void kvm_arch_hardware_unsetup(void) {}
 static inline void kvm_arch_sync_events(struct kvm *kvm) {}
 static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
arch/arm64/include/asm/kvm_mmu.h +1 -0
index 6150567..ff5a087 100644
@@ -98,6 +98,7 @@ void kvm_mmu_free_memory_caches(struct kvm_vcpu *vcpu);
 phys_addr_t kvm_mmu_get_httbr(void);
 phys_addr_t kvm_mmu_get_boot_httbr(void);
 phys_addr_t kvm_get_idmap_vector(void);
+phys_addr_t kvm_get_idmap_start(void);
 int kvm_mmu_init(void);
 void kvm_clear_hyp_idmap(void);
 
arch/arm64/include/asm/virt.h +9 -0
index 3070096..bca79f9 100644
@@ -58,9 +58,18 @@
 
 #define HVC_CALL_FUNC 3
 
+/*
+ * HVC_RESET_CPU - Reset cpu in EL2 to initial state.
+ *
+ * @x0: entry address in trampoline code in va
+ * @x1: identical mapping page table in pa
+ */
+
 #define BOOT_CPU_MODE_EL1	(0xe11)
 #define BOOT_CPU_MODE_EL2	(0xe12)
 
+#define HVC_RESET_CPU 4
+
 #ifndef __ASSEMBLY__
 
 /*
arch/arm64/kvm/hyp-init.S +33 -0
index 2e67a48..1925163 100644
@@ -139,6 +139,39 @@ merged:
 	eret
 ENDPROC(__kvm_hyp_init)
 
+	/*
+	 * x0: HYP boot pgd
+	 * x1: HYP phys_idmap_start
+	 */
+ENTRY(__kvm_hyp_reset)
+	/* We're in trampoline code in VA, switch back to boot page tables */
+	msr	ttbr0_el2, x0
+	isb
+
+	/* Invalidate the old TLBs */
+	tlbi	alle2
+	dsb	sy
+
+	/* Branch into PA space */
+	adr	x0, 1f
+	bfi	x1, x0, #0, #PAGE_SHIFT
+	br	x1
+
+	/* We're now in idmap, disable MMU */
+1:	mrs	x0, sctlr_el2
+	ldr	x1, =SCTLR_EL2_FLAGS
+	bic	x0, x0, x1		// Clear SCTL_M and etc
+	msr	sctlr_el2, x0
+	isb
+
+	/* Install stub vectors */
+	adrp	x0, __hyp_stub_vectors
+	add	x0, x0, #:lo12:__hyp_stub_vectors
+	msr	vbar_el2, x0
+
+	eret
+ENDPROC(__kvm_hyp_reset)
+
 	.ltorg
 
 	.popsection
arch/arm64/kvm/hyp.S +28 -4
index 073b8bf..c9804ac 100644
@@ -931,6 +931,11 @@ ENTRY(kvm_call_hyp)
 	ret
 ENDPROC(kvm_call_hyp)
 
+ENTRY(kvm_call_reset)
+	hvc	#HVC_RESET_CPU
+	ret
+ENDPROC(kvm_call_reset)
+
 .macro invalid_vector	label, target
 	.align	2
 \label:
@@ -974,10 +979,27 @@ el1_sync:					// Guest trapped into EL2
 	cmp	x18, #HVC_GET_VECTORS
 	b.ne	1f
 	mrs	x0, vbar_el2
-	b	2f
-
-1:	/* Default to HVC_CALL_HYP. */
+	b	do_eret
 
+	/* jump into trampoline code */
+1:	cmp	x18, #HVC_RESET_CPU
+	b.ne	2f
+	/*
+	 * Entry point is:
+	 *	TRAMPOLINE_VA
+	 *	+ (__kvm_hyp_reset - (__hyp_idmap_text_start & PAGE_MASK))
+	 */
+	adrp	x2, __kvm_hyp_reset
+	add	x2, x2, #:lo12:__kvm_hyp_reset
+	adrp	x3, __hyp_idmap_text_start
+	add	x3, x3, #:lo12:__hyp_idmap_text_start
+	and	x3, x3, PAGE_MASK
+	sub	x2, x2, x3
+	ldr	x3, =TRAMPOLINE_VA
+	add	x2, x2, x3
+	br	x2				// no return
+
+2:	/* Default to HVC_CALL_HYP. */
 	push	lr, xzr
 
 	/*
@@ -991,7 +1013,9 @@ el1_sync:					// Guest trapped into EL2
 	blr	lr
 
 	pop	lr, xzr
-2:	eret
+
+do_eret:
+	eret
 
 el1_trap:
 	/*
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#5 lore raw

PATCH 5/15 arm64: Add back cpu_reset routines

In reply to Geoff Levand

Commit 68234df4ea7939f98431aa81113fbdce10c4a84b (arm64: kill flush_cache_all()) removed the global arm64 routines cpu_reset() and cpu_soft_restart() needed by the arm64 kexec and kdump support. Add simplified versions of those two routines back with some changes needed for kexec in the new files cpu_reset.S, and cpu_reset.h.

When a CPU is reset it needs to be put into the exception level it had when it entered the kernel. Update cpu_reset() to accept an argument which signals if the reset address needs to be entered at EL1 or EL2.

---
 arch/arm64/kernel/cpu-reset.S | 84 +++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/cpu-reset.h | 22 ++++++++++++
 2 files changed, 106 insertions(+)
 create mode 100644 arch/arm64/kernel/cpu-reset.S
 create mode 100644 arch/arm64/kernel/cpu-reset.h
arch/arm64/kernel/cpu-reset.S new file +84 -0
new file mode 100644
index 0000000..0423f27
@@ -0,0 +1,84 @@
+/*
+ * cpu reset routines
+ *
+ * Copyright (C) 2001 Deep Blue Solutions Ltd.
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2015 Huawei Futurewei Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/virt.h>
+
+#define SCTLR_ELx_I	(1 << 12)
+#define SCTLR_ELx_SA	(1 << 3)
+#define SCTLR_ELx_C	(1 << 2)
+#define SCTLR_ELx_A	(1 << 1)
+#define SCTLR_ELx_M	1
+#define SCTLR_ELx_FLAGS	(SCTLR_ELx_M | SCTLR_ELx_A | SCTLR_ELx_C |	\
+			 SCTLR_ELx_SA | SCTLR_ELx_I)
+
+.text
+.pushsection    .idmap.text, "ax"
+
+.align 5
+
+/*
+ * cpu_soft_restart(cpu_reset, el2_switch, entry, arg0, arg1) - Perform a cpu
+ * soft reset.
+ *
+ * @cpu_reset: Physical address of the cpu_reset routine.
+ * @el2_switch: Flag to indicate a swich to EL2 is needed, passed to cpu_reset.
+ * @entry: Location to jump to for soft reset, passed to cpu_reset.
+ * arg0: First argument passed to @entry.
+ * arg1: Second argument passed to @entry.
+ */
+
+ENTRY(cpu_soft_restart)
+	mov	x18, x0				// cpu_reset
+	mov	x0, x1				// el2_switch
+	mov	x1, x2				// entry
+	mov	x2, x3				// arg0
+	mov	x3, x4				// arg1
+	ret	x18
+ENDPROC(cpu_soft_restart)
+
+/*
+ * cpu_reset(el2_switch, entry, arg0, arg1) - Helper for cpu_soft_restart.
+ *
+ * @el2_switch: Flag to indicate a swich to EL2 is needed.
+ * @entry: Location to jump to for soft reset.
+ * arg0: First argument passed to @entry.
+ * arg1: Second argument passed to @entry.
+ *
+ * Put the CPU into the same state as it would be if it had been reset, and
+ * branch to what would be the reset vector. It must be executed with the
+ * flat identity mapping.
+ */
+
+ENTRY(cpu_reset)
+	/* Clear sctlr_el1 flags. */
+	mrs	x12, sctlr_el1
+	ldr	x13, =SCTLR_ELx_FLAGS
+	bic	x12, x12, x13
+	msr	sctlr_el1, x12
+	isb
+
+	cbz	x0, 1f				// el2_switch?
+
+	mov	x0, x1				// entry
+	mov	x1, x2				// arg0
+	mov	x2, x3				// arg1
+	hvc	#HVC_CALL_FUNC			// no return
+
+1:	mov	x18, x1				// entry
+	mov	x0, x2				// arg0
+	mov	x1, x3				// arg1
+	ret	x18
+ENDPROC(cpu_reset)
+
+.popsection
arch/arm64/kernel/cpu-reset.h new file +22 -0
new file mode 100644
index 0000000..79816b6
@@ -0,0 +1,22 @@
+/*
+ * cpu reset routines
+ *
+ * Copyright (C) 2015 Huawei Futurewei Technologies.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#if !defined(_ARM64_CPU_RESET_H)
+#define _ARM64_CPU_RESET_H
+
+#include <asm/virt.h>
+
+void __attribute__((noreturn)) cpu_reset(unsigned long el2_switch,
+	unsigned long entry, unsigned long arg0, unsigned long arg1);
+void __attribute__((noreturn)) cpu_soft_restart(phys_addr_t cpu_reset,
+	unsigned long el2_switch, unsigned long entry, unsigned long arg0,
+	unsigned long arg1);
+
+#endif
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#6 lore raw

PATCH 6/15 Revert "arm64: remove dead code"

In reply to Geoff Levand

This reverts commit b08d4640a3dca68670fc5af2fe9205b395a02388.

Add back the setup_mm_for_reboot() needed for kexec.

---
 arch/arm64/include/asm/mmu.h |  1 +
 arch/arm64/mm/mmu.c          | 11 +++++++++++
 2 files changed, 12 insertions(+)
arch/arm64/include/asm/mmu.h +1 -0
index 0302087..79fcfb0 100644
@@ -28,6 +28,7 @@ typedef struct {
 #define ASID(mm)	((mm)->context.id & 0xffff)
 
 extern void paging_init(void);
+extern void setup_mm_for_reboot(void);
 extern void __iomem *early_io_map(phys_addr_t phys, unsigned long virt);
 extern void init_mem_pgprot(void);
 extern void create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
arch/arm64/mm/mmu.c +11 -0
index 9211b85..8cffad9 100644
@@ -461,6 +461,17 @@ void __init paging_init(void)
 }
 
 /*
+ * Enable the identity mapping to allow the MMU disabling.
+ */
+void setup_mm_for_reboot(void)
+{
+	cpu_set_reserved_ttbr0();
+	flush_tlb_all();
+	cpu_set_idmap_tcr_t0sz();
+	cpu_switch_mm(idmap_pg_dir, &init_mm);
+}
+
+/*
  * Check whether a kernel address is valid (derived from arch/x86/).
  */
 int kern_addr_valid(unsigned long addr)
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#7 lore raw

PATCH 7/15 arm64/kexec: Add core kexec support

In reply to Geoff Levand

Add three new files, kexec.h, machine_kexec.c and relocate_kernel.S to the arm64 architecture that add support for the kexec re-boot mechanism (CONFIG_KEXEC) on arm64 platforms.

---
 arch/arm64/Kconfig                  |  10 +++
 arch/arm64/include/asm/kexec.h      |  48 ++++++++++++
 arch/arm64/kernel/Makefile          |   2 +
 arch/arm64/kernel/machine_kexec.c   | 152 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/relocate_kernel.S | 131 +++++++++++++++++++++++++++++++
 include/uapi/linux/kexec.h          |   1 +
 6 files changed, 344 insertions(+)
 create mode 100644 arch/arm64/include/asm/kexec.h
 create mode 100644 arch/arm64/kernel/machine_kexec.c
 create mode 100644 arch/arm64/kernel/relocate_kernel.S
arch/arm64/Kconfig +10 -0
index 07d1811..d9631ac 100644
@@ -491,6 +491,16 @@ config SECCOMP
 	  and the task is only allowed to execute a few safe syscalls
 	  defined by each seccomp mode.
 
+config KEXEC
+	depends on PM_SLEEP_SMP
+	select KEXEC_CORE
+	bool "kexec system call"
+	---help---
+	  kexec is a system call that implements the ability to shutdown your
+	  current kernel, and to start another kernel.  It is like a reboot
+	  but it is independent of the system firmware.   And like a reboot
+	  you can start any kernel with it, not just Linux.
+
 config XEN_DOM0
 	def_bool y
 	depends on XEN
arch/arm64/include/asm/kexec.h new file +48 -0

48 lines not on this page · raw message

arch/arm64/kernel/Makefile +2 -0
index 22dc9bc..989ccd7 100644
@@ -36,6 +36,8 @@ arm64-obj-$(CONFIG_EFI)			+= efi.o efi-stub.o efi-entry.o
 arm64-obj-$(CONFIG_PCI)			+= pci.o
 arm64-obj-$(CONFIG_ARMV8_DEPRECATED)	+= armv8_deprecated.o
 arm64-obj-$(CONFIG_ACPI)		+= acpi.o
+arm64-obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o	\
+					   cpu-reset.o
 
 obj-y					+= $(arm64-obj-y) vdso/
 obj-m					+= $(arm64-obj-m)
arch/arm64/kernel/machine_kexec.c new file +152 -0

152 lines not on this page · raw message

arch/arm64/kernel/relocate_kernel.S new file +131 -0

131 lines not on this page · raw message

include/uapi/linux/kexec.h +1 -0
index 99048e5..ccec467 100644
@@ -39,6 +39,7 @@
 #define KEXEC_ARCH_SH      (42 << 16)
 #define KEXEC_ARCH_MIPS_LE (10 << 16)
 #define KEXEC_ARCH_MIPS    ( 8 << 16)
+#define KEXEC_ARCH_ARM64   (183 << 16)
 
 /* The artificial cap on the number of segments passed to kexec_load. */
 #define KEXEC_SEGMENT_MAX 16
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#8 lore raw

PATCH 8/15 arm64/kexec: Add pr_devel output

In reply to Geoff Levand

To aid in debugging kexec problems or when adding new functionality to kexec add a new routine kexec_image_info() and several inline pr_devel statements.

---
 arch/arm64/kernel/machine_kexec.c | 63 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)
arch/arm64/kernel/machine_kexec.c +63 -0
index 8b990b8..da28a26 100644
@@ -25,6 +25,48 @@ extern const unsigned long arm64_relocate_new_kernel_size;
 
 static unsigned long kimage_start;
 
+/**
+ * kexec_is_dtb - Helper routine to check the device tree header signature.
+ */
+static bool kexec_is_dtb(const void *dtb)
+{
+	__be32 magic;
+
+	return get_user(magic, (__be32 *)dtb) ? false :
+		(be32_to_cpu(magic) == OF_DT_HEADER);
+}
+
+/**
+ * kexec_image_info - For debugging output.
+ */
+#define kexec_image_info(_i) _kexec_image_info(__func__, __LINE__, _i)
+static void _kexec_image_info(const char *func, int line,
+	const struct kimage *kimage)
+{
+	unsigned long i;
+
+#if !defined(DEBUG)
+	return;
+#endif
+	pr_devel("%s:%d:\n", func, line);
+	pr_devel("  kexec kimage info:\n");
+	pr_devel("    type:        %d\n", kimage->type);
+	pr_devel("    start:       %lx\n", kimage->start);
+	pr_devel("    head:        %lx\n", kimage->head);
+	pr_devel("    nr_segments: %lu\n", kimage->nr_segments);
+
+	for (i = 0; i < kimage->nr_segments; i++) {
+		pr_devel("      segment[%lu]: %016lx - %016lx, %lx bytes, %lu pages%s\n",
+			i,
+			kimage->segment[i].mem,
+			kimage->segment[i].mem + kimage->segment[i].memsz,
+			kimage->segment[i].memsz,
+			kimage->segment[i].memsz /  PAGE_SIZE,
+			(kexec_is_dtb(kimage->segment[i].buf) ?
+				", dtb segment" : ""));
+	}
+}
+
 void machine_kexec_cleanup(struct kimage *kimage)
 {
 	/* Empty routine needed to avoid build errors. */
@@ -38,6 +80,8 @@ void machine_kexec_cleanup(struct kimage *kimage)
 int machine_kexec_prepare(struct kimage *kimage)
 {
 	kimage_start = kimage->start;
+	kexec_image_info(kimage);
+
 	return 0;
 }
 
@@ -107,6 +151,25 @@ void machine_kexec(struct kimage *kimage)
 	reboot_code_buffer_phys = page_to_phys(kimage->control_code_page);
 	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
 
+	kexec_image_info(kimage);
+
+	pr_devel("%s:%d: control_code_page:        %p\n", __func__, __LINE__,
+		kimage->control_code_page);
+	pr_devel("%s:%d: reboot_code_buffer_phys:  %pa\n", __func__, __LINE__,
+		&reboot_code_buffer_phys);
+	pr_devel("%s:%d: reboot_code_buffer:       %p\n", __func__, __LINE__,
+		reboot_code_buffer);
+	pr_devel("%s:%d: relocate_new_kernel:      %p\n", __func__, __LINE__,
+		arm64_relocate_new_kernel);
+	pr_devel("%s:%d: relocate_new_kernel_size: 0x%lx(%lu) bytes\n",
+		__func__, __LINE__, arm64_relocate_new_kernel_size,
+		arm64_relocate_new_kernel_size);
+
+	pr_devel("%s:%d: kimage_head:              %lx\n", __func__, __LINE__,
+		kimage->head);
+	pr_devel("%s:%d: kimage_start:             %lx\n", __func__, __LINE__,
+		kimage_start);
+
 	/*
 	 * Copy arm64_relocate_new_kernel to the reboot_code_buffer for use
 	 * after the kernel is shut down.
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#9 lore raw

PATCH 9/15 arm64/kexec: Enable kexec in the arm64 defconfig

In reply to Geoff Levand
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)
arch/arm64/configs/defconfig +1 -0
index 34d71dd..c80d8a4 100644
@@ -55,6 +55,7 @@ CONFIG_PREEMPT=y
 CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CMA=y
+CONFIG_KEXEC=y
 CONFIG_CMDLINE="console=ttyAMA0"
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#10 lore raw

PATCH 10/15 arm64: kdump: reserve memory for crash dump kernel

In reply to Geoff Levand

From: AKASHI Takahiro <[email protected]>

On primary kernel, the memory region used by crash dump kernel must be specified by "crashkernel=" boot parameter. reserve_crashkernel() will allocate and reserve the region for later use.

User space tools will be able to find the region marked as "Crash kernel" in /proc/iomem.

---
 arch/arm64/kernel/setup.c |  7 +++++-
 arch/arm64/mm/init.c      | 54 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 1 deletion(-)
arch/arm64/kernel/setup.c +6 -1
index 2322479..9d085ac 100644
@@ -32,7 +32,6 @@
 #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>
@@ -337,6 +336,12 @@ static void __init request_standard_resources(void)
 		    kernel_data.end <= res->end)
 			request_resource(res, &kernel_data);
 	}
+
+#ifdef CONFIG_KEXEC
+	/* User space tools will find "Crash kernel" region in /proc/iomem. */
+	if (crashk_res.end)
+		insert_resource(&iomem_resource, &crashk_res);
+#endif
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
arch/arm64/mm/init.c +54 -0

72 lines not on this page · raw message

Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#11 lore raw

PATCH 11/15 arm64: kdump: implement machine_crash_shutdown()

In reply to Geoff Levand

From: AKASHI Takahiro <[email protected]>

kdump calls machine_crash_shutdown() to shut down non-boot cpus and save registers' status in per-cpu ELF notes before starting the crash dump kernel. See kernel_kexec().

ipi_cpu_stop() is a bit modified and used to support this behavior.

---
 arch/arm64/include/asm/kexec.h    | 34 +++++++++++++++++++++++++++++++++-
 arch/arm64/kernel/machine_kexec.c | 31 +++++++++++++++++++++++++++++--
 arch/arm64/kernel/smp.c           | 16 ++++++++++++++--
 3 files changed, 76 insertions(+), 5 deletions(-)
arch/arm64/include/asm/kexec.h +33 -1
index 46d63cd..555a955 100644
@@ -30,6 +30,8 @@
 
 #if !defined(__ASSEMBLY__)
 
+extern bool in_crash_kexec;
+
 /**
  * crash_setup_regs() - save registers for the panic kernel
  *
@@ -40,7 +42,37 @@
 static inline void crash_setup_regs(struct pt_regs *newregs,
 				    struct pt_regs *oldregs)
 {
-	/* Empty routine needed to avoid build errors. */
+	if (oldregs) {
+		memcpy(newregs, oldregs, sizeof(*newregs));
+	} else {
+		__asm__ __volatile__ (
+			"stp	 x0,   x1, [%3, #16 *  0]\n"
+			"stp	 x2,   x3, [%3, #16 *  1]\n"
+			"stp	 x4,   x5, [%3, #16 *  2]\n"
+			"stp	 x6,   x7, [%3, #16 *  3]\n"
+			"stp	 x8,   x9, [%3, #16 *  4]\n"
+			"stp	x10,  x11, [%3, #16 *  5]\n"
+			"stp	x12,  x13, [%3, #16 *  6]\n"
+			"stp	x14,  x15, [%3, #16 *  7]\n"
+			"stp	x16,  x17, [%3, #16 *  8]\n"
+			"stp	x18,  x19, [%3, #16 *  9]\n"
+			"stp	x20,  x21, [%3, #16 * 10]\n"
+			"stp	x22,  x23, [%3, #16 * 11]\n"
+			"stp	x24,  x25, [%3, #16 * 12]\n"
+			"stp	x26,  x27, [%3, #16 * 13]\n"
+			"stp	x28,  x29, [%3, #16 * 14]\n"
+			"str	x30,	   [%3, #16 * 15]\n"
+			"mov	%0, sp\n"
+			"adr	%1, 1f\n"
+			"mrs	%2, spsr_el1\n"
+		"1:"
+			: "=r" (newregs->sp),
+			  "=r" (newregs->pc),
+			  "=r" (newregs->pstate)
+			: "r"  (&newregs->regs)
+			: "memory"
+		);
+	}
 }
 
 #endif /* !defined(__ASSEMBLY__) */
arch/arm64/kernel/machine_kexec.c +29 -2
index da28a26..d2d7e90 100644
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/kernel.h>
 #include <linux/kexec.h>
 #include <linux/of_fdt.h>
 #include <linux/slab.h>
@@ -23,6 +24,7 @@
 extern const unsigned char arm64_relocate_new_kernel[];
 extern const unsigned long arm64_relocate_new_kernel_size;
 
+bool in_crash_kexec;
 static unsigned long kimage_start;
 
 /**
@@ -203,13 +205,38 @@ void machine_kexec(struct kimage *kimage)
 	 */
 
 	cpu_soft_restart(virt_to_phys(cpu_reset),
-		is_hyp_mode_available(),
+		in_crash_kexec ? 0 : is_hyp_mode_available(),
 		reboot_code_buffer_phys, kimage->head, kimage_start);
 
 	BUG(); /* Should never get here. */
 }
 
+/**
+ * machine_crash_shutdown - shutdown non-boot cpus and save registers
+ */
 void machine_crash_shutdown(struct pt_regs *regs)
 {
-	/* Empty routine needed to avoid build errors. */
+	struct pt_regs dummy_regs;
+	int cpu;
+
+	local_irq_disable();
+
+	in_crash_kexec = true;
+
+	/*
+	 * clear and initialize the per-cpu info. This is necessary
+	 * because, otherwise, slots for offline cpus would never be
+	 * filled up. See smp_send_stop().
+	 */
+	memset(&dummy_regs, 0, sizeof(dummy_regs));
+	for_each_possible_cpu(cpu)
+		crash_save_cpu(&dummy_regs, cpu);
+
+	/* shutdown non-boot cpus */
+	smp_send_stop();
+
+	/* for boot cpu */
+	crash_save_cpu(regs, smp_processor_id());
+
+	pr_info("Starting crashdump kernel...\n");
 }
arch/arm64/kernel/smp.c +14 -2
index dbdaacd..88aec66 100644
@@ -37,6 +37,7 @@
 #include <linux/completion.h>
 #include <linux/of.h>
 #include <linux/irq_work.h>
+#include <linux/kexec.h>
 
 #include <asm/alternative.h>
 #include <asm/atomic.h>
@@ -54,6 +55,8 @@
 #include <asm/ptrace.h>
 #include <asm/virt.h>
 
+#include "cpu-reset.h"
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/ipi.h>
 
@@ -679,8 +682,12 @@ static DEFINE_RAW_SPINLOCK(stop_lock);
 /*
  * ipi_cpu_stop - handle IPI from smp_send_stop()
  */
-static void ipi_cpu_stop(unsigned int cpu)
+static void ipi_cpu_stop(unsigned int cpu, struct pt_regs *regs)
 {
+#ifdef CONFIG_KEXEC
+	/* printing messages may slow down the shutdown. */
+	if (!in_crash_kexec)
+#endif
 	if (system_state == SYSTEM_BOOTING ||
 	    system_state == SYSTEM_RUNNING) {
 		raw_spin_lock(&stop_lock);
@@ -693,6 +700,11 @@ static void ipi_cpu_stop(unsigned int cpu)
 
 	local_irq_disable();
 
+#ifdef CONFIG_KEXEC
+	if (in_crash_kexec)
+		crash_save_cpu(regs, cpu);
+#endif /* CONFIG_KEXEC */
+
 	while (1)
 		cpu_relax();
 }
@@ -723,7 +735,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
 
 	case IPI_CPU_STOP:
 		irq_enter();
-		ipi_cpu_stop(cpu);
+		ipi_cpu_stop(cpu, regs);
 		irq_exit();
 		break;
 
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#12 lore raw

Re: [PATCH 11/15] arm64: kdump: implement machine_crash_shutdown()

Quoted 7 lines · Geoff Levand

From: AKASHI Takahiro <[email protected]>

kdump calls machine_crash_shutdown() to shut down non-boot cpus and save registers' status in per-cpu ELF notes before starting the crash dump kernel. See kernel_kexec().

ipi_cpu_stop() is a bit modified and used to support this behavior.

I've got some concerns of using ipi_cpu_stop().

Quoted 157 lines
---
  arch/arm64/include/asm/kexec.h    | 34 +++++++++++++++++++++++++++++++++-
  arch/arm64/kernel/machine_kexec.c | 31 +++++++++++++++++++++++++++++--
  arch/arm64/kernel/smp.c           | 16 ++++++++++++++--
  3 files changed, 76 insertions(+), 5 deletions(-)
arch/arm64/include/asm/kexec.h +33 -1
index 46d63cd..555a955 100644
@@ -30,6 +30,8 @@
 
  #if !defined(__ASSEMBLY__)
 
+extern bool in_crash_kexec;
+
  /**
   * crash_setup_regs() - save registers for the panic kernel
   *
@@ -40,7 +42,37 @@
  static inline void crash_setup_regs(struct pt_regs *newregs,
  				    struct pt_regs *oldregs)
  {
-	/* Empty routine needed to avoid build errors. */
+	if (oldregs) {
+		memcpy(newregs, oldregs, sizeof(*newregs));
+	} else {
+		__asm__ __volatile__ (
+			"stp	 x0,   x1, [%3, #16 *  0]\n"
+			"stp	 x2,   x3, [%3, #16 *  1]\n"
+			"stp	 x4,   x5, [%3, #16 *  2]\n"
+			"stp	 x6,   x7, [%3, #16 *  3]\n"
+			"stp	 x8,   x9, [%3, #16 *  4]\n"
+			"stp	x10,  x11, [%3, #16 *  5]\n"
+			"stp	x12,  x13, [%3, #16 *  6]\n"
+			"stp	x14,  x15, [%3, #16 *  7]\n"
+			"stp	x16,  x17, [%3, #16 *  8]\n"
+			"stp	x18,  x19, [%3, #16 *  9]\n"
+			"stp	x20,  x21, [%3, #16 * 10]\n"
+			"stp	x22,  x23, [%3, #16 * 11]\n"
+			"stp	x24,  x25, [%3, #16 * 12]\n"
+			"stp	x26,  x27, [%3, #16 * 13]\n"
+			"stp	x28,  x29, [%3, #16 * 14]\n"
+			"str	x30,	   [%3, #16 * 15]\n"
+			"mov	%0, sp\n"
+			"adr	%1, 1f\n"
+			"mrs	%2, spsr_el1\n"
+		"1:"
+			: "=r" (newregs->sp),
+			  "=r" (newregs->pc),
+			  "=r" (newregs->pstate)
+			: "r"  (&newregs->regs)
+			: "memory"
+		);
+	}
  }
 
  #endif /* !defined(__ASSEMBLY__) */
arch/arm64/kernel/machine_kexec.c +29 -2
index da28a26..d2d7e90 100644
@@ -9,6 +9,7 @@
   * published by the Free Software Foundation.
   */
 
+#include <linux/kernel.h>
  #include <linux/kexec.h>
  #include <linux/of_fdt.h>
  #include <linux/slab.h>
@@ -23,6 +24,7 @@
  extern const unsigned char arm64_relocate_new_kernel[];
  extern const unsigned long arm64_relocate_new_kernel_size;
 
+bool in_crash_kexec;
  static unsigned long kimage_start;
 
  /**
@@ -203,13 +205,38 @@ void machine_kexec(struct kimage *kimage)
  	 */
 
  	cpu_soft_restart(virt_to_phys(cpu_reset),
-		is_hyp_mode_available(),
+		in_crash_kexec ? 0 : is_hyp_mode_available(),
  		reboot_code_buffer_phys, kimage->head, kimage_start);
 
  	BUG(); /* Should never get here. */
  }
 
+/**
+ * machine_crash_shutdown - shutdown non-boot cpus and save registers
+ */
  void machine_crash_shutdown(struct pt_regs *regs)
  {
-	/* Empty routine needed to avoid build errors. */
+	struct pt_regs dummy_regs;
+	int cpu;
+
+	local_irq_disable();
+
+	in_crash_kexec = true;
+
+	/*
+	 * clear and initialize the per-cpu info. This is necessary
+	 * because, otherwise, slots for offline cpus would never be
+	 * filled up. See smp_send_stop().
+	 */
+	memset(&dummy_regs, 0, sizeof(dummy_regs));
+	for_each_possible_cpu(cpu)
+		crash_save_cpu(&dummy_regs, cpu);
+
+	/* shutdown non-boot cpus */
+	smp_send_stop();
+
+	/* for boot cpu */
+	crash_save_cpu(regs, smp_processor_id());
+
+	pr_info("Starting crashdump kernel...\n");
  }
arch/arm64/kernel/smp.c +8 -1
index dbdaacd..88aec66 100644
@@ -37,6 +37,7 @@
  #include <linux/completion.h>
  #include <linux/of.h>
  #include <linux/irq_work.h>
+#include <linux/kexec.h>
 
  #include <asm/alternative.h>
  #include <asm/atomic.h>
@@ -54,6 +55,8 @@
  #include <asm/ptrace.h>
  #include <asm/virt.h>
 
+#include "cpu-reset.h"
+
  #define CREATE_TRACE_POINTS
  #include <trace/events/ipi.h>
 
@@ -679,8 +682,12 @@ static DEFINE_RAW_SPINLOCK(stop_lock);
  /*
   * ipi_cpu_stop - handle IPI from smp_send_stop()
   */
-static void ipi_cpu_stop(unsigned int cpu)
+static void ipi_cpu_stop(unsigned int cpu, struct pt_regs *regs)
  {
+#ifdef CONFIG_KEXEC
+	/* printing messages may slow down the shutdown. */
+	if (!in_crash_kexec)
+#endif
  	if (system_state == SYSTEM_BOOTING ||
  	    system_state == SYSTEM_RUNNING) {
  		raw_spin_lock(&stop_lock);
@@ -693,6 +700,11 @@ static void ipi_cpu_stop(unsigned int cpu)
 

arch/arm64/kernel/smp.c static void ipi_cpu_stop(unsigned int cpu) · line 710

Quoted 10 lines
arch/arm64/kernel/smp.c +5 -0
  	local_irq_disable();
 
+#ifdef CONFIG_KEXEC
+	if (in_crash_kexec)
+		crash_save_cpu(regs, cpu);
+#endif /* CONFIG_KEXEC */
+
  	while (1)
  		cpu_relax();
  }

cpu_relax() is defined as asm("yield"), and this puts all but boot cpu into a infinite loop of nop (actually, whether nop or other depends on hw implementation). Thus all the secondary cpus are still running busy loop even after crash dump kernel has started up, and the chip can potentially get overheated.
I ran into this situation when I tested the code on Hikey, and the system was forced to be shut down by thermal driver.

So I'd like to modify the code a bit like:

if (in_crash_kernel {
     crash_save_cpu(regs, cpu);
     while (1)
         asm("wfi"); /* irq is disabled here. */
}

Does this make sense?

-Takahiro AKASHI

Quoted 10 lines
arch/arm64/kernel/smp.c +1 -1
@@ -723,7 +735,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
 
  	case IPI_CPU_STOP:
  		irq_enter();
-		ipi_cpu_stop(cpu);
+		ipi_cpu_stop(cpu, regs);
  		irq_exit();
  		break;
 
#13 lore raw

Re: [PATCH 11/15] arm64: kdump: implement machine_crash_shutdown()

Quoted 17 lines · AKASHI Takahiro
Quoted 7 lines · Geoff Levand

From: AKASHI Takahiro <[email protected]>

kdump calls machine_crash_shutdown() to shut down non-boot cpus and save registers' status in per-cpu ELF notes before starting the crash dump kernel. See kernel_kexec().

ipi_cpu_stop() is a bit modified and used to support this behavior.

I've got some concerns of using ipi_cpu_stop().

Quoted 6 lines
---
 arch/arm64/include/asm/kexec.h    | 34 +++++++++++++++++++++++++++++++++-
 arch/arm64/kernel/machine_kexec.c | 31 +++++++++++++++++++++++++++++--
 arch/arm64/kernel/smp.c           | 16 ++++++++++++++--
 3 files changed, 76 insertions(+), 5 deletions(-)

[...]

Quoted 55 lines
Quoted 37 lines
arch/arm64/kernel/smp.c +8 -1
index dbdaacd..88aec66 100644
@@ -37,6 +37,7 @@
 #include <linux/completion.h>
 #include <linux/of.h>
 #include <linux/irq_work.h>
+#include <linux/kexec.h>
 
 #include <asm/alternative.h>
 #include <asm/atomic.h>
@@ -54,6 +55,8 @@
 #include <asm/ptrace.h>
 #include <asm/virt.h>
 
+#include "cpu-reset.h"
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/ipi.h>
 
@@ -679,8 +682,12 @@ static DEFINE_RAW_SPINLOCK(stop_lock);
 /*
  * ipi_cpu_stop - handle IPI from smp_send_stop()
  */
-static void ipi_cpu_stop(unsigned int cpu)
+static void ipi_cpu_stop(unsigned int cpu, struct pt_regs *regs)
 {
+#ifdef CONFIG_KEXEC
+	/* printing messages may slow down the shutdown. */
+	if (!in_crash_kexec)
+#endif
 	if (system_state == SYSTEM_BOOTING ||
 	    system_state == SYSTEM_RUNNING) {
 		raw_spin_lock(&stop_lock);
@@ -693,6 +700,11 @@ static void ipi_cpu_stop(unsigned int cpu)
 

arch/arm64/kernel/smp.c static void ipi_cpu_stop(unsigned int cpu) · line 710

Quoted 10 lines
arch/arm64/kernel/smp.c +5 -0
 	local_irq_disable();
 
+#ifdef CONFIG_KEXEC
+	if (in_crash_kexec)
+		crash_save_cpu(regs, cpu);
+#endif /* CONFIG_KEXEC */
+
 	while (1)
 		cpu_relax();
 }

cpu_relax() is defined as asm("yield"), and this puts all but boot cpu into a infinite loop of nop (actually, whether nop or other depends on hw implementation). Thus all the secondary cpus are still running busy loop even after crash dump kernel has started up, and the chip can potentially get overheated.
I ran into this situation when I tested the code on Hikey, and the system was forced to be shut down by thermal driver.

Quoted 8 lines

So I'd like to modify the code a bit like:

if (in_crash_kernel {
    crash_save_cpu(regs, cpu);
    while (1)
        asm("wfi"); /* irq is disabled here. */
}

Does this make sense?

It would be even better if we could hotplug them off.

Will

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#14 lore raw

PATCH 12/15 arm64: kdump: add kdump support

In reply to Geoff Levand

From: AKASHI Takahiro <[email protected]>

On crash dump kernel, all the information about primary kernel's core image is available in elf core header specified by "elfcorehdr=" boot parameter. reserve_elfcorehdr() will set aside the region to avoid any corruption by crash dump kernel.

Crash dump kernel will access the system memory of primary kernel via copy_oldmem_page(), which reads one page by ioremap'ing it since it does not reside in linear mapping on crash dump kernel.
Please note that we should add "mem=X[MG]" boot parameter to limit the memory size and avoid the following assertion at ioremap():

	if (WARN_ON(pfn_valid(__phys_to_pfn(phys_addr))))
		return NULL;

when accessing any pages beyond the usable memories of crash dump kernel.

We also need our own elfcorehdr_read() here since the weak definition of elfcorehdr_read() utilizes copy_oldmem_page() and will hit the assertion above on arm64.

---
 arch/arm64/Kconfig             | 12 +++++++
 arch/arm64/kernel/Makefile     |  1 +
 arch/arm64/kernel/crash_dump.c | 71 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/init.c           | 29 +++++++++++++++++
 4 files changed, 113 insertions(+)
 create mode 100644 arch/arm64/kernel/crash_dump.c
arch/arm64/Kconfig +12 -0
index d9631ac..48b787b 100644
@@ -501,6 +501,18 @@ config KEXEC
 	  but it is independent of the system firmware.   And like a reboot
 	  you can start any kernel with it, not just Linux.
 
+config CRASH_DUMP
+	bool "Build kdump crash kernel"
+	help
+	  Generate crash dump after being started by kexec. This should
+	  be normally only set in special crash dump kernels which are
+	  loaded in the main kernel with kexec-tools into a specially
+	  reserved region and then later executed after a crash by
+	  kdump/kexec. The crash dump kernel must be compiled to a
+	  memory address not used by the main kernel.
+
+	  For more details see Documentation/kdump/kdump.txt
+
 config XEN_DOM0
 	def_bool y
 	depends on XEN
arch/arm64/kernel/Makefile +1 -0
index 989ccd7..7ef9fa4 100644
@@ -38,6 +38,7 @@ arm64-obj-$(CONFIG_ARMV8_DEPRECATED)	+= armv8_deprecated.o
 arm64-obj-$(CONFIG_ACPI)		+= acpi.o
 arm64-obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o	\
 					   cpu-reset.o
+arm64-obj-$(CONFIG_CRASH_DUMP)		+= crash_dump.o
 
 obj-y					+= $(arm64-obj-y) vdso/
 obj-m					+= $(arm64-obj-m)
arch/arm64/kernel/crash_dump.c new file +71 -0

71 lines not on this page · raw message

arch/arm64/mm/init.c +29 -0
index f33f201..ff8eeb4 100644
@@ -35,6 +35,7 @@
 #include <linux/efi.h>
 #include <linux/swiotlb.h>
 #include <linux/kexec.h>
+#include <linux/crash_dump.h>
 
 #include <asm/fixmap.h>
 #include <asm/memory.h>
@@ -116,6 +117,31 @@ static void __init reserve_crashkernel(void)
 }
 #endif /* CONFIG_KEXEC */
 
+#ifdef CONFIG_CRASH_DUMP
+/*
+ * reserve_elfcorehdr() - reserves memory for elf core header
+ *
+ * This function reserves elf core header given in "elfcorehdr=" kernel
+ * command line parameter. This region contains all the information about
+ * primary kernel's core image and is used by a dump capture kernel to
+ * access the system memory on primary kernel.
+ */
+static void __init reserve_elfcorehdr(void)
+{
+	if (!elfcorehdr_size)
+		return;
+
+	if (memblock_is_region_reserved(elfcorehdr_addr, elfcorehdr_size)) {
+		pr_warn("elfcorehdr is overlapped\n");
+		return;
+	}
+
+	memblock_reserve(elfcorehdr_addr, elfcorehdr_size);
+
+	pr_info("Reserving %lldKB of memory at %lldMB for elfcorehdr\n",
+		elfcorehdr_size >> 10, elfcorehdr_addr >> 20);
+}
+#endif /* CONFIG_CRASH_DUMP */
 /*
  * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It
  * currently assumes that for memory starting above 4G, 32-bit devices will
@@ -223,6 +249,9 @@ void __init arm64_memblock_init(void)
 #ifdef CONFIG_KEXEC
 	reserve_crashkernel();
 #endif
+#ifdef CONFIG_CRASH_DUMP
+	reserve_elfcorehdr();
+#endif
 
 	early_init_fdt_scan_reserved_mem();
 
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#15 lore raw

PATCH 13/15 arm64: kdump: update a kernel doc

In reply to Geoff Levand

From: AKASHI Takahiro <[email protected]>

This patch adds arch specific descriptions about kdump usage on arm64 to kdump.txt.

---
 Documentation/kdump/kdump.txt | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)
Documentation/kdump/kdump.txt +31 -1
index bc4bd5a..7d3fad0 100644
@@ -18,7 +18,7 @@ memory image to a dump file on the local disk, or across the network to
 a remote system.
 
 Kdump and kexec are currently supported on the x86, x86_64, ppc64, ia64,
-s390x and arm architectures.
+s390x, arm and arm64 architectures.
 
 When the system kernel boots, it reserves a small section of memory for
 the dump-capture kernel. This ensures that ongoing Direct Memory Access
@@ -249,6 +249,29 @@ Dump-capture kernel config options (Arch Dependent, arm)
 
     AUTO_ZRELADDR=y
 
+Dump-capture kernel config options (Arch Dependent, arm64)
+----------------------------------------------------------
+
+1) Disable symmetric multi-processing support under "Processor type and
+   features":
+
+   CONFIG_SMP=n
+
+   (If CONFIG_SMP=y, then specify maxcpus=1 on the kernel command line
+   when loading the dump-capture kernel, see section "Load the Dump-capture
+   Kernel".)
+
+2) The maximum memory size on the dump-capture kernel must be limited by
+   specifying:
+
+   mem=X[MG]
+
+   where X should be less than or equal to the size in "crashkernel="
+   boot parameter. Kexec-tools will automatically add this.
+
+3) Currently, kvm will not be enabled on the dump-capture kernel even
+   if it is configured.
+
 Extended crashkernel syntax
 ===========================
 
@@ -312,6 +335,8 @@ Boot into System Kernel
    any space below the alignment point may be overwritten by the dump-capture kernel,
    which means it is possible that the vmcore is not that precise as expected.
 
+   On arm64, use "crashkernel=Y[@X]".  Note that the start address of
+   the kernel, X if explicitly specified, must be aligned to 2MiB (0x200000).
 
 Load the Dump-capture Kernel
 ============================
@@ -334,6 +359,8 @@ For s390x:
 	- Use image or bzImage
 For arm:
 	- Use zImage
+For arm64:
+	- Use vmlinux
 
 If you are using a uncompressed vmlinux image then use following command
 to load dump-capture kernel.
@@ -377,6 +404,9 @@ For s390x:
 For arm:
 	"1 maxcpus=1 reset_devices"
 
+For arm64:
+	"1 mem=X[MG] maxcpus=1 reset_devices"
+
 Notes on loading the dump-capture kernel:
 
 * By default, the ELF headers are stored in ELF64 format to support
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#16 lore raw

PATCH 14/15 arm64: kdump: enable kdump in the arm64 defconfig

In reply to Geoff Levand

From: AKASHI Takahiro <[email protected]>

---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)
arch/arm64/configs/defconfig +1 -0
index c80d8a4..94ec44e 100644
@@ -56,6 +56,7 @@ CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CMA=y
 CONFIG_KEXEC=y
+CONFIG_CRASH_DUMP=y
 CONFIG_CMDLINE="console=ttyAMA0"
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
Signature · 8 lines
2.5.0



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#17 lore raw

PATCH 15/15 arm64: kdump: relax BUG_ON() if more than one cpus are still active

In reply to Geoff Levand

From: AKASHI Takahiro <[email protected]>

We should try best in case of kdump.
So even if not all secondary cpus have shut down, we do kdump anyway.

---
 arch/arm64/kernel/machine_kexec.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
arch/arm64/kernel/machine_kexec.c +7 -1
index d2d7e90..482aae7 100644
@@ -148,7 +148,13 @@ void machine_kexec(struct kimage *kimage)
 	phys_addr_t reboot_code_buffer_phys;
 	void *reboot_code_buffer;
 
-	BUG_ON(num_online_cpus() > 1);
+	if (num_online_cpus() > 1) {
+		if (in_crash_kexec)
+			pr_warn("kdump might fail because %d cpus are still online\n",
+					num_online_cpus());
+		else
+			BUG();
+	}
 
 	reboot_code_buffer_phys = page_to_phys(kimage->control_code_page);
 	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
Signature · 7 lines
2.5.0


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec