All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 06/16] arm64: Add EL2 switch to cpu_reset
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Also, update the comments of cpu_reset() and cpu_soft_restart() to reflect
this change.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/kernel/cpu-reset.S | 22 +++++++++++++++++++---
 arch/arm64/kernel/cpu-reset.h |  4 +++-
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S
index 64d9d7c..ffc9e385e 100644
--- a/arch/arm64/kernel/cpu-reset.S
+++ b/arch/arm64/kernel/cpu-reset.S
@@ -16,6 +16,7 @@
 #include <asm/assembler.h>
 #include <asm/cpufeature.h>
 #include <asm/alternative.h>
+#include <asm/virt.h>
 
 .text
 .pushsection    .idmap.text, "ax"
@@ -23,9 +24,14 @@
 .align 5
 
 /*
- * cpu_reset(addr) - Helper for cpu_soft_restart.
+ * cpu_reset(addr, el2_switch) - Helper for cpu_soft_restart.
  *
  * @addr: Location to jump to for soft reset.
+ * @el2_switch: Flag to indicate a swich to EL2 is needed.
+ *
+ * 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)
@@ -33,19 +39,28 @@ ENTRY(cpu_reset)
 	bic	x2, x2, #1
 	msr	sctlr_el1, x2			// disable the MMU
 	isb
-	ret	x0
+
+	cbz	x1, 1f				// el2_switch?
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	hvc	#HVC_CALL_FUNC			// no return
+
+1:	ret	x0
 ENDPROC(cpu_reset)
 
 /*
- * cpu_soft_restart(cpu_reset, addr) - Perform a cpu soft reset.
+ * cpu_soft_restart(cpu_reset, addr, el2_switch) - Perform a cpu soft reset.
  *
  * @cpu_reset: Physical address of the cpu_reset routine.
  * @addr: Location to jump to for soft reset, passed to cpu_reset.
+ * @el2_switch: Flag to indicate a swich to EL2 is needed, passed to cpu_reset.
  */
 
 ENTRY(cpu_soft_restart)
 	mov	x19, x0				// cpu_reset
 	mov	x20, x1				// addr
+	mov	x21, x2				// el2_switch
 
 	/* Turn D-cache off */
 	mrs	x0, sctlr_el1
@@ -54,6 +69,7 @@ ENTRY(cpu_soft_restart)
 	isb
 
 	mov	x0, x20
+	mov	x1, x21
 	ret	x19
 ENDPROC(cpu_soft_restart)
 
diff --git a/arch/arm64/kernel/cpu-reset.h b/arch/arm64/kernel/cpu-reset.h
index 4e16dfe..ef3bba2 100644
--- a/arch/arm64/kernel/cpu-reset.h
+++ b/arch/arm64/kernel/cpu-reset.h
@@ -11,8 +11,10 @@
 #if !defined(_ARM64_CPU_RESET_H)
 #define _ARM64_CPU_RESET_H
 
+#include <asm/virt.h>
+
 void __attribute__((noreturn)) cpu_reset(unsigned long addr);
 void __attribute__((noreturn)) cpu_soft_restart(phys_addr_t cpu_reset,
-	unsigned long addr);
+	unsigned long addr, unsigned long el2_switch);
 
 #endif
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 03/16] arm64: Add new hcall HVC_CALL_FUNC
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/include/asm/virt.h | 13 +++++++++++++
 arch/arm64/kernel/hyp-stub.S  | 13 ++++++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index eb10368..3070096 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -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)
 
diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index 017ab519..e8febe9 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -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)
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 05/16] arm64: Add back cpu_reset routines
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

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 those two routines back with some minor
simplifications in the new files cpu_reset.S, and cpu_reset.h.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/kernel/cpu-reset.S | 60 +++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/cpu-reset.h | 18 +++++++++++++
 2 files changed, 78 insertions(+)
 create mode 100644 arch/arm64/kernel/cpu-reset.S
 create mode 100644 arch/arm64/kernel/cpu-reset.h

diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S
new file mode 100644
index 0000000..64d9d7c
--- /dev/null
+++ b/arch/arm64/kernel/cpu-reset.S
@@ -0,0 +1,60 @@
+/*
+ * 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/errno.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/cpufeature.h>
+#include <asm/alternative.h>
+
+.text
+.pushsection    .idmap.text, "ax"
+
+.align 5
+
+/*
+ * cpu_reset(addr) - Helper for cpu_soft_restart.
+ *
+ * @addr: Location to jump to for soft reset.
+ */
+
+ENTRY(cpu_reset)
+	mrs	x2, sctlr_el1
+	bic	x2, x2, #1
+	msr	sctlr_el1, x2			// disable the MMU
+	isb
+	ret	x0
+ENDPROC(cpu_reset)
+
+/*
+ * cpu_soft_restart(cpu_reset, addr) - Perform a cpu soft reset.
+ *
+ * @cpu_reset: Physical address of the cpu_reset routine.
+ * @addr: Location to jump to for soft reset, passed to cpu_reset.
+ */
+
+ENTRY(cpu_soft_restart)
+	mov	x19, x0				// cpu_reset
+	mov	x20, x1				// addr
+
+	/* Turn D-cache off */
+	mrs	x0, sctlr_el1
+	bic	x0, x0, #1 << 2			// clear SCTLR.C
+	msr	sctlr_el1, x0
+	isb
+
+	mov	x0, x20
+	ret	x19
+ENDPROC(cpu_soft_restart)
+
+.popsection
diff --git a/arch/arm64/kernel/cpu-reset.h b/arch/arm64/kernel/cpu-reset.h
new file mode 100644
index 0000000..4e16dfe
--- /dev/null
+++ b/arch/arm64/kernel/cpu-reset.h
@@ -0,0 +1,18 @@
+/*
+ * 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
+
+void __attribute__((noreturn)) cpu_reset(unsigned long addr);
+void __attribute__((noreturn)) cpu_soft_restart(phys_addr_t cpu_reset,
+	unsigned long addr);
+
+#endif
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 02/16] arm64: Convert hcalls to use HVC immediate value
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 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(-)

diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index 7a5df52..eb10368 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -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)
 
diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index a272f33..017ab519 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -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)
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index e583613..073b8bf 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -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.
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 00/16] arm64 kexec kernel patches v10
@ 2015-10-19 23:38 ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

Hi All,

This series adds the core support for kexec re-boot and kdump on ARM64.  This
v10 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-7 add back the ARM64 CPU reset support that was recently removed from
the kernel.

Patches 8-10 add the actual kexec support.

Patches 11-16 add kdump support.

Please consider all patches for inclusion.

[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 7379047d5585187d1288486d4627873170d0005a:

  Linux 4.3-rc6 (2015-10-18 16:08:42 -0700)

are available in the git repository at:

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

for you to fetch changes up to 4cf0c03d6cd1cb4826bb5df679fbcdaf80be0b1c:

  arm64: kdump: relax BUG_ON() if more than one cpus are still active (2015-10-19 15:51:52 -0700)

----------------------------------------------------------------
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 (9):
      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
      arm64: Add EL2 switch to cpu_reset
      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       |  29 ++++-
 arch/arm/include/asm/kvm_host.h     |  10 +-
 arch/arm/include/asm/kvm_mmu.h      |   1 +
 arch/arm/kvm/arm.c                  |  58 +++------
 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       |  76 ++++++++++++
 arch/arm64/kernel/cpu-reset.h       |  20 +++
 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   | 237 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/relocate_kernel.S | 163 +++++++++++++++++++++++++
 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, 1063 insertions(+), 138 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

-- 
2.5.0

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 07/16] Revert "arm64: remove dead code"
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

This reverts commit b08d4640a3dca68670fc5af2fe9205b395a02388.

Add back the setup_mm_for_reboot() needed for kexec.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/include/asm/mmu.h |  1 +
 arch/arm64/mm/mmu.c          | 11 +++++++++++
 2 files changed, 12 insertions(+)

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 0302087..79fcfb0 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -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,
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 9211b85..8cffad9 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -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)
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 04/16] arm64: kvm: allows kvm cpu hotplug
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm/include/asm/kvm_host.h   | 10 ++++++-
 arch/arm/include/asm/kvm_mmu.h    |  1 +
 arch/arm/kvm/arm.c                | 58 ++++++++++++---------------------------
 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, 119 insertions(+), 46 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index c4072d9..4c6a38c 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -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) {}
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 405aa18..dc6fadf 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -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);
 
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index dc017ad..0871809 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -16,7 +16,6 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -85,11 +84,6 @@ struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void)
 	return &kvm_arm_running_vcpu;
 }
 
-int kvm_arch_hardware_enable(void)
-{
-	return 0;
-}
-
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 {
 	return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
@@ -915,7 +909,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
 	}
 }
 
-static void cpu_init_hyp_mode(void *dummy)
+int kvm_arch_hardware_enable(void)
 {
 	phys_addr_t boot_pgd_ptr;
 	phys_addr_t pgd_ptr;
@@ -923,6 +917,9 @@ static void cpu_init_hyp_mode(void *dummy)
 	unsigned long stack_page;
 	unsigned long vector_ptr;
 
+	if (__hyp_get_vectors() != hyp_default_vectors)
+		return 0;
+
 	/* Switch from the HYP stub to our own HYP init vector */
 	__hyp_set_vectors(kvm_get_idmap_vector());
 
@@ -935,34 +932,31 @@ static void cpu_init_hyp_mode(void *dummy)
 	__cpu_init_hyp_mode(boot_pgd_ptr, pgd_ptr, hyp_stack_ptr, vector_ptr);
 
 	kvm_arm_init_debug();
+
+	return 0;
 }
 
-static int hyp_init_cpu_notify(struct notifier_block *self,
-			       unsigned long action, void *cpu)
+void kvm_arch_hardware_disable(void)
 {
-	switch (action) {
-	case CPU_STARTING:
-	case CPU_STARTING_FROZEN:
-		if (__hyp_get_vectors() == hyp_default_vectors)
-			cpu_init_hyp_mode(NULL);
-		break;
-	}
+	phys_addr_t boot_pgd_ptr;
+	phys_addr_t phys_idmap_start;
 
-	return NOTIFY_OK;
-}
+	if (__hyp_get_vectors() == hyp_default_vectors)
+		return;
 
-static struct notifier_block hyp_init_cpu_nb = {
-	.notifier_call = hyp_init_cpu_notify,
-};
+	boot_pgd_ptr = kvm_mmu_get_boot_httbr();
+	phys_idmap_start = kvm_get_idmap_start();
+
+	__cpu_reset_hyp_mode(boot_pgd_ptr, phys_idmap_start);
+}
 
 #ifdef CONFIG_CPU_PM
 static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
 				    unsigned long cmd,
 				    void *v)
 {
-	if (cmd == CPU_PM_EXIT &&
-	    __hyp_get_vectors() == hyp_default_vectors) {
-		cpu_init_hyp_mode(NULL);
+	if (cmd == CPU_PM_EXIT && kvm_arm_get_running_vcpu()) {
+		kvm_arch_hardware_enable();
 		return NOTIFY_OK;
 	}
 
@@ -1064,11 +1058,6 @@ static int init_hyp_mode(void)
 	}
 
 	/*
-	 * Execute the init code on each CPU.
-	 */
-	on_each_cpu(cpu_init_hyp_mode, NULL, 1);
-
-	/*
 	 * Init HYP view of VGIC
 	 */
 	err = kvm_vgic_hyp_init();
@@ -1142,26 +1131,15 @@ int kvm_arch_init(void *opaque)
 		}
 	}
 
-	cpu_notifier_register_begin();
-
 	err = init_hyp_mode();
 	if (err)
 		goto out_err;
 
-	err = __register_cpu_notifier(&hyp_init_cpu_nb);
-	if (err) {
-		kvm_err("Cannot register HYP init CPU notifier (%d)\n", err);
-		goto out_err;
-	}
-
-	cpu_notifier_register_done();
-
 	hyp_cpu_pm_init();
 
 	kvm_coproc_table_init();
 	return 0;
 out_err:
-	cpu_notifier_register_done();
 	return err;
 }
 
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 6984342..69b4a33 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -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;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index ed03968..e86421a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -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) {}
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 6150567..ff5a087 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -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);
 
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index 3070096..bca79f9 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -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__
 
 /*
diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
index 2e67a48..1925163 100644
--- a/arch/arm64/kvm/hyp-init.S
+++ b/arch/arm64/kvm/hyp-init.S
@@ -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
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index 073b8bf..c9804ac 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -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:
 	/*
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 01/16] arm64: Fold proc-macros.S into assembler.h
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 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

diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index b51f2cc..3b46501 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -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 */
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 90d09ed..9ad8b1f 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -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>
diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
index 178ba22..2e67a48 100644
--- a/arch/arm64/kvm/hyp-init.S
+++ b/arch/arm64/kvm/hyp-init.S
@@ -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"
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index eb48d5d..9e13cb5 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -24,8 +24,6 @@
 #include <asm/cpufeature.h>
 #include <asm/alternative.h>
 
-#include "proc-macros.S"
-
 /*
  *	flush_icache_range(start,end)
  *
diff --git a/arch/arm64/mm/proc-macros.S b/arch/arm64/mm/proc-macros.S
deleted file mode 100644
index 4c4d93c..0000000
--- a/arch/arm64/mm/proc-macros.S
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Based on arch/arm/mm/proc-macros.S
- *
- * Copyright (C) 2012 ARM Ltd.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-
-/*
- * 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
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index e4ee7bd..456c1c5 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -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
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 08/16] arm64/kexec: Add core kexec support
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/Kconfig                  |  10 +++
 arch/arm64/include/asm/kexec.h      |  48 +++++++++++
 arch/arm64/kernel/Makefile          |   2 +
 arch/arm64/kernel/cpu-reset.S       |   2 +-
 arch/arm64/kernel/machine_kexec.c   | 141 +++++++++++++++++++++++++++++++
 arch/arm64/kernel/relocate_kernel.S | 163 ++++++++++++++++++++++++++++++++++++
 include/uapi/linux/kexec.h          |   1 +
 7 files changed, 366 insertions(+), 1 deletion(-)
 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

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 07d1811..73e8e31 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -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 (!SMP || 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
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
new file mode 100644
index 0000000..46d63cd
--- /dev/null
+++ b/arch/arm64/include/asm/kexec.h
@@ -0,0 +1,48 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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_KEXEC_H)
+#define _ARM64_KEXEC_H
+
+/* Maximum physical address we can use pages from */
+
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can reach in physical address mode */
+
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can use for the control code buffer */
+
+#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
+
+#define KEXEC_CONTROL_PAGE_SIZE	4096
+
+#define KEXEC_ARCH KEXEC_ARCH_ARM64
+
+#if !defined(__ASSEMBLY__)
+
+/**
+ * crash_setup_regs() - save registers for the panic kernel
+ *
+ * @newregs: registers are saved here
+ * @oldregs: registers to be saved (may be %NULL)
+ */
+
+static inline void crash_setup_regs(struct pt_regs *newregs,
+				    struct pt_regs *oldregs)
+{
+	/* Empty routine needed to avoid build errors. */
+}
+
+#endif /* !defined(__ASSEMBLY__) */
+
+#endif
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 22dc9bc..989ccd7 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -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)
diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S
index ffc9e385e..7cc7f56 100644
--- a/arch/arm64/kernel/cpu-reset.S
+++ b/arch/arm64/kernel/cpu-reset.S
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2001 Deep Blue Solutions Ltd.
  * Copyright (C) 2012 ARM Ltd.
- * Copyright (C) 2015 Huawei Futurewei Technologies.
+ * Copyright (C) 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
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
new file mode 100644
index 0000000..1fae6ae
--- /dev/null
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -0,0 +1,141 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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/kexec.h>
+#include <linux/of_fdt.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/system_misc.h>
+
+#include "cpu-reset.h"
+
+/* Global variables for the relocate_kernel routine. */
+extern const unsigned char arm64_relocate_new_kernel[];
+extern const unsigned long arm64_relocate_new_kernel_size;
+extern unsigned long arm64_kexec_kimage_head_offset;
+extern unsigned long arm64_kexec_kimage_start_offset;
+
+static unsigned long kimage_head;
+static unsigned long kimage_start;
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+	/* Empty routine needed to avoid build errors. */
+}
+
+/**
+ * machine_kexec_prepare - Prepare for a kexec reboot.
+ *
+ * Called from the core kexec code when a kernel image is loaded.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+	kimage_start = image->start;
+	return 0;
+}
+
+/**
+ * kexec_list_flush - Helper to flush the kimage list to PoC.
+ */
+static void kexec_list_flush(unsigned long kimage_head)
+{
+	unsigned long *entry;
+
+	for (entry = &kimage_head; ; entry++) {
+		unsigned int flag = *entry & IND_FLAGS;
+		void *addr = phys_to_virt(*entry & PAGE_MASK);
+
+		switch (flag) {
+		case IND_INDIRECTION:
+			entry = (unsigned long *)addr - 1;
+			__flush_dcache_area(addr, PAGE_SIZE);
+			break;
+		case IND_DESTINATION:
+			break;
+		case IND_SOURCE:
+			__flush_dcache_area(addr, PAGE_SIZE);
+			break;
+		case IND_DONE:
+			return;
+		default:
+			BUG();
+		}
+	}
+}
+
+static void soft_restart(unsigned long addr)
+{
+	setup_mm_for_reboot();
+	cpu_soft_restart(virt_to_phys(cpu_reset), addr,
+		is_hyp_mode_available());
+
+	BUG(); /* Should never get here. */
+}
+
+/**
+ * machine_kexec - Do the kexec reboot.
+ *
+ * Called from the core kexec code for a sys_reboot with LINUX_REBOOT_CMD_KEXEC.
+ */
+void machine_kexec(struct kimage *image)
+{
+	phys_addr_t reboot_code_buffer_phys;
+	void *reboot_code_buffer;
+
+	BUG_ON(num_online_cpus() > 1);
+
+	kimage_head = image->head;
+
+	reboot_code_buffer_phys = page_to_phys(image->control_code_page);
+	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
+
+	/*
+	 * Copy arm64_relocate_new_kernel to the reboot_code_buffer for use
+	 * after the kernel is shut down.
+	 */
+	memcpy(reboot_code_buffer, arm64_relocate_new_kernel,
+		arm64_relocate_new_kernel_size);
+
+	/* Set the variables in reboot_code_buffer. */
+
+	memcpy(reboot_code_buffer + arm64_kexec_kimage_start_offset,
+	       &kimage_start, sizeof(kimage_start));
+	memcpy(reboot_code_buffer + arm64_kexec_kimage_head_offset,
+	       &kimage_head, sizeof(kimage_head));
+
+	/* Flush the reboot_code_buffer in preparation for its execution. */
+	__flush_dcache_area(reboot_code_buffer, arm64_relocate_new_kernel_size);
+
+	/* Flush the kimage list. */
+	kexec_list_flush(image->head);
+
+	pr_info("Bye!\n");
+
+	/* Disable all DAIF exceptions. */
+	asm volatile ("msr daifset, #0xf" : : : "memory");
+
+	/*
+	 * soft_restart() will shutdown the MMU, disable data caches, then
+	 * transfer control to the reboot_code_buffer which contains a copy of
+	 * the arm64_relocate_new_kernel routine.  arm64_relocate_new_kernel
+	 * will use physical addressing to relocate the new kernel to its final
+	 * position and then will transfer control to the entry point of the new
+	 * kernel.
+	 */
+	soft_restart(reboot_code_buffer_phys);
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+	/* Empty routine needed to avoid build errors. */
+}
diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S
new file mode 100644
index 0000000..7b07a16
--- /dev/null
+++ b/arch/arm64/kernel/relocate_kernel.S
@@ -0,0 +1,163 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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/kexec.h>
+
+#include <asm/assembler.h>
+#include <asm/kexec.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+
+
+/*
+ * arm64_relocate_new_kernel - Put a 2nd stage kernel image in place and boot it.
+ *
+ * The memory that the old kernel occupies may be overwritten when coping the
+ * new image to its final location.  To assure that the
+ * arm64_relocate_new_kernel routine which does that copy is not overwritten,
+ * all code and data needed by arm64_relocate_new_kernel must be between the
+ * symbols arm64_relocate_new_kernel and arm64_relocate_new_kernel_end.  The
+ * machine_kexec() routine will copy arm64_relocate_new_kernel to the kexec
+ * control_code_page, a special page which has been set up to be preserved
+ * during the copy operation.
+ */
+.globl arm64_relocate_new_kernel
+arm64_relocate_new_kernel:
+
+	/* Setup the list loop variables. */
+	ldr	x18, .Lkimage_head		/* x18 = list entry */
+	dcache_line_size x17, x0		/* x17 = dcache line size */
+	mov	x16, xzr			/* x16 = segment start */
+	mov	x15, xzr			/* x15 = entry ptr */
+	mov	x14, xzr			/* x14 = copy dest */
+
+	/* Check if the new image needs relocation. */
+	cbz	x18, .Ldone
+	tbnz	x18, IND_DONE_BIT, .Ldone
+
+.Lloop:
+	and	x13, x18, PAGE_MASK		/* x13 = addr */
+
+	/* Test the entry flags. */
+.Ltest_source:
+	tbz	x18, IND_SOURCE_BIT, .Ltest_indirection
+
+	mov x20, x14				/*  x20 = copy dest */
+	mov x21, x13				/*  x21 = copy src */
+
+	/* Invalidate dest page to PoC. */
+	mov	x0, x20
+	add	x19, x0, #PAGE_SIZE
+	sub	x1, x17, #1
+	bic	x0, x0, x1
+1:	dc	ivac, x0
+	add	x0, x0, x17
+	cmp	x0, x19
+	b.lo	1b
+	dsb	sy
+
+	/* Copy page. */
+1:	ldp	x22, x23, [x21]
+	ldp	x24, x25, [x21, #16]
+	ldp	x26, x27, [x21, #32]
+	ldp	x28, x29, [x21, #48]
+	add	x21, x21, #64
+	stnp	x22, x23, [x20]
+	stnp	x24, x25, [x20, #16]
+	stnp	x26, x27, [x20, #32]
+	stnp	x28, x29, [x20, #48]
+	add	x20, x20, #64
+	tst	x21, #(PAGE_SIZE - 1)
+	b.ne	1b
+
+	/* dest += PAGE_SIZE */
+	add	x14, x14, PAGE_SIZE
+	b	.Lnext
+
+.Ltest_indirection:
+	tbz	x18, IND_INDIRECTION_BIT, .Ltest_destination
+
+	/* ptr = addr */
+	mov	x15, x13
+	b	.Lnext
+
+.Ltest_destination:
+	tbz	x18, IND_DESTINATION_BIT, .Lnext
+
+	mov	x16, x13
+
+	/* dest = addr */
+	mov	x14, x13
+
+.Lnext:
+	/* entry = *ptr++ */
+	ldr	x18, [x15], #8
+
+	/* while (!(entry & DONE)) */
+	tbz	x18, IND_DONE_BIT, .Lloop
+
+.Ldone:
+	dsb	sy
+	isb
+	ic	ialluis
+	dsb	sy
+	isb
+
+	/* Start new image. */
+	ldr	x4, .Lkimage_start
+	mov	x0, xzr
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	br	x4
+
+.align 3	/* To keep the 64-bit values below naturally aligned. */
+
+/* The machine_kexec routine sets these variables via offsets from
+ * arm64_relocate_new_kernel.
+ */
+
+/*
+ * .Lkimage_start - Copy of image->start, the entry point of the new
+ * image.
+ */
+.Lkimage_start:
+	.quad	0x0
+
+/*
+ * .Lkimage_head - Copy of image->head, the list of kimage entries.
+ */
+.Lkimage_head:
+	.quad	0x0
+
+.Lcopy_end:
+.org	KEXEC_CONTROL_PAGE_SIZE
+
+/*
+ * arm64_relocate_new_kernel_size - Number of bytes to copy to the control_code_page.
+ */
+.globl arm64_relocate_new_kernel_size
+arm64_relocate_new_kernel_size:
+	.quad	.Lcopy_end - arm64_relocate_new_kernel
+
+/*
+ * arm64_kexec_kimage_start_offset - Offset for writing .Lkimage_start.
+ */
+.globl arm64_kexec_kimage_start_offset
+arm64_kexec_kimage_start_offset:
+	.quad	.Lkimage_start - arm64_relocate_new_kernel
+
+/*
+ * arm64_kexec_kimage_head_offset - Offset for writing .Lkimage_head.
+ */
+.globl arm64_kexec_kimage_head_offset
+arm64_kexec_kimage_head_offset:
+	.quad	.Lkimage_head - arm64_relocate_new_kernel
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h
index 99048e5..ccec467 100644
--- a/include/uapi/linux/kexec.h
+++ b/include/uapi/linux/kexec.h
@@ -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
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 06/16] arm64: Add EL2 switch to cpu_reset
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

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.

Also, update the comments of cpu_reset() and cpu_soft_restart() to reflect
this change.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/kernel/cpu-reset.S | 22 +++++++++++++++++++---
 arch/arm64/kernel/cpu-reset.h |  4 +++-
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S
index 64d9d7c..ffc9e385e 100644
--- a/arch/arm64/kernel/cpu-reset.S
+++ b/arch/arm64/kernel/cpu-reset.S
@@ -16,6 +16,7 @@
 #include <asm/assembler.h>
 #include <asm/cpufeature.h>
 #include <asm/alternative.h>
+#include <asm/virt.h>
 
 .text
 .pushsection    .idmap.text, "ax"
@@ -23,9 +24,14 @@
 .align 5
 
 /*
- * cpu_reset(addr) - Helper for cpu_soft_restart.
+ * cpu_reset(addr, el2_switch) - Helper for cpu_soft_restart.
  *
  * @addr: Location to jump to for soft reset.
+ * @el2_switch: Flag to indicate a swich to EL2 is needed.
+ *
+ * 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)
@@ -33,19 +39,28 @@ ENTRY(cpu_reset)
 	bic	x2, x2, #1
 	msr	sctlr_el1, x2			// disable the MMU
 	isb
-	ret	x0
+
+	cbz	x1, 1f				// el2_switch?
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	hvc	#HVC_CALL_FUNC			// no return
+
+1:	ret	x0
 ENDPROC(cpu_reset)
 
 /*
- * cpu_soft_restart(cpu_reset, addr) - Perform a cpu soft reset.
+ * cpu_soft_restart(cpu_reset, addr, el2_switch) - Perform a cpu soft reset.
  *
  * @cpu_reset: Physical address of the cpu_reset routine.
  * @addr: Location to jump to for soft reset, passed to cpu_reset.
+ * @el2_switch: Flag to indicate a swich to EL2 is needed, passed to cpu_reset.
  */
 
 ENTRY(cpu_soft_restart)
 	mov	x19, x0				// cpu_reset
 	mov	x20, x1				// addr
+	mov	x21, x2				// el2_switch
 
 	/* Turn D-cache off */
 	mrs	x0, sctlr_el1
@@ -54,6 +69,7 @@ ENTRY(cpu_soft_restart)
 	isb
 
 	mov	x0, x20
+	mov	x1, x21
 	ret	x19
 ENDPROC(cpu_soft_restart)
 
diff --git a/arch/arm64/kernel/cpu-reset.h b/arch/arm64/kernel/cpu-reset.h
index 4e16dfe..ef3bba2 100644
--- a/arch/arm64/kernel/cpu-reset.h
+++ b/arch/arm64/kernel/cpu-reset.h
@@ -11,8 +11,10 @@
 #if !defined(_ARM64_CPU_RESET_H)
 #define _ARM64_CPU_RESET_H
 
+#include <asm/virt.h>
+
 void __attribute__((noreturn)) cpu_reset(unsigned long addr);
 void __attribute__((noreturn)) cpu_soft_restart(phys_addr_t cpu_reset,
-	unsigned long addr);
+	unsigned long addr, unsigned long el2_switch);
 
 #endif
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 05/16] arm64: Add back cpu_reset routines
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

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 those two routines back with some minor
simplifications in the new files cpu_reset.S, and cpu_reset.h.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/kernel/cpu-reset.S | 60 +++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/cpu-reset.h | 18 +++++++++++++
 2 files changed, 78 insertions(+)
 create mode 100644 arch/arm64/kernel/cpu-reset.S
 create mode 100644 arch/arm64/kernel/cpu-reset.h

diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S
new file mode 100644
index 0000000..64d9d7c
--- /dev/null
+++ b/arch/arm64/kernel/cpu-reset.S
@@ -0,0 +1,60 @@
+/*
+ * 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/errno.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/cpufeature.h>
+#include <asm/alternative.h>
+
+.text
+.pushsection    .idmap.text, "ax"
+
+.align 5
+
+/*
+ * cpu_reset(addr) - Helper for cpu_soft_restart.
+ *
+ * @addr: Location to jump to for soft reset.
+ */
+
+ENTRY(cpu_reset)
+	mrs	x2, sctlr_el1
+	bic	x2, x2, #1
+	msr	sctlr_el1, x2			// disable the MMU
+	isb
+	ret	x0
+ENDPROC(cpu_reset)
+
+/*
+ * cpu_soft_restart(cpu_reset, addr) - Perform a cpu soft reset.
+ *
+ * @cpu_reset: Physical address of the cpu_reset routine.
+ * @addr: Location to jump to for soft reset, passed to cpu_reset.
+ */
+
+ENTRY(cpu_soft_restart)
+	mov	x19, x0				// cpu_reset
+	mov	x20, x1				// addr
+
+	/* Turn D-cache off */
+	mrs	x0, sctlr_el1
+	bic	x0, x0, #1 << 2			// clear SCTLR.C
+	msr	sctlr_el1, x0
+	isb
+
+	mov	x0, x20
+	ret	x19
+ENDPROC(cpu_soft_restart)
+
+.popsection
diff --git a/arch/arm64/kernel/cpu-reset.h b/arch/arm64/kernel/cpu-reset.h
new file mode 100644
index 0000000..4e16dfe
--- /dev/null
+++ b/arch/arm64/kernel/cpu-reset.h
@@ -0,0 +1,18 @@
+/*
+ * 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
+
+void __attribute__((noreturn)) cpu_reset(unsigned long addr);
+void __attribute__((noreturn)) cpu_soft_restart(phys_addr_t cpu_reset,
+	unsigned long addr);
+
+#endif
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 03/16] arm64: Add new hcall HVC_CALL_FUNC
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/include/asm/virt.h | 13 +++++++++++++
 arch/arm64/kernel/hyp-stub.S  | 13 ++++++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index eb10368..3070096 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -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)
 
diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index 017ab519..e8febe9 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -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)
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 04/16] arm64: kvm: allows kvm cpu hotplug
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm/include/asm/kvm_host.h   | 10 ++++++-
 arch/arm/include/asm/kvm_mmu.h    |  1 +
 arch/arm/kvm/arm.c                | 58 ++++++++++++---------------------------
 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, 119 insertions(+), 46 deletions(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index c4072d9..4c6a38c 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -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) {}
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 405aa18..dc6fadf 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -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);
 
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index dc017ad..0871809 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -16,7 +16,6 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -85,11 +84,6 @@ struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void)
 	return &kvm_arm_running_vcpu;
 }
 
-int kvm_arch_hardware_enable(void)
-{
-	return 0;
-}
-
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 {
 	return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
@@ -915,7 +909,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
 	}
 }
 
-static void cpu_init_hyp_mode(void *dummy)
+int kvm_arch_hardware_enable(void)
 {
 	phys_addr_t boot_pgd_ptr;
 	phys_addr_t pgd_ptr;
@@ -923,6 +917,9 @@ static void cpu_init_hyp_mode(void *dummy)
 	unsigned long stack_page;
 	unsigned long vector_ptr;
 
+	if (__hyp_get_vectors() != hyp_default_vectors)
+		return 0;
+
 	/* Switch from the HYP stub to our own HYP init vector */
 	__hyp_set_vectors(kvm_get_idmap_vector());
 
@@ -935,34 +932,31 @@ static void cpu_init_hyp_mode(void *dummy)
 	__cpu_init_hyp_mode(boot_pgd_ptr, pgd_ptr, hyp_stack_ptr, vector_ptr);
 
 	kvm_arm_init_debug();
+
+	return 0;
 }
 
-static int hyp_init_cpu_notify(struct notifier_block *self,
-			       unsigned long action, void *cpu)
+void kvm_arch_hardware_disable(void)
 {
-	switch (action) {
-	case CPU_STARTING:
-	case CPU_STARTING_FROZEN:
-		if (__hyp_get_vectors() == hyp_default_vectors)
-			cpu_init_hyp_mode(NULL);
-		break;
-	}
+	phys_addr_t boot_pgd_ptr;
+	phys_addr_t phys_idmap_start;
 
-	return NOTIFY_OK;
-}
+	if (__hyp_get_vectors() == hyp_default_vectors)
+		return;
 
-static struct notifier_block hyp_init_cpu_nb = {
-	.notifier_call = hyp_init_cpu_notify,
-};
+	boot_pgd_ptr = kvm_mmu_get_boot_httbr();
+	phys_idmap_start = kvm_get_idmap_start();
+
+	__cpu_reset_hyp_mode(boot_pgd_ptr, phys_idmap_start);
+}
 
 #ifdef CONFIG_CPU_PM
 static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
 				    unsigned long cmd,
 				    void *v)
 {
-	if (cmd == CPU_PM_EXIT &&
-	    __hyp_get_vectors() == hyp_default_vectors) {
-		cpu_init_hyp_mode(NULL);
+	if (cmd == CPU_PM_EXIT && kvm_arm_get_running_vcpu()) {
+		kvm_arch_hardware_enable();
 		return NOTIFY_OK;
 	}
 
@@ -1064,11 +1058,6 @@ static int init_hyp_mode(void)
 	}
 
 	/*
-	 * Execute the init code on each CPU.
-	 */
-	on_each_cpu(cpu_init_hyp_mode, NULL, 1);
-
-	/*
 	 * Init HYP view of VGIC
 	 */
 	err = kvm_vgic_hyp_init();
@@ -1142,26 +1131,15 @@ int kvm_arch_init(void *opaque)
 		}
 	}
 
-	cpu_notifier_register_begin();
-
 	err = init_hyp_mode();
 	if (err)
 		goto out_err;
 
-	err = __register_cpu_notifier(&hyp_init_cpu_nb);
-	if (err) {
-		kvm_err("Cannot register HYP init CPU notifier (%d)\n", err);
-		goto out_err;
-	}
-
-	cpu_notifier_register_done();
-
 	hyp_cpu_pm_init();
 
 	kvm_coproc_table_init();
 	return 0;
 out_err:
-	cpu_notifier_register_done();
 	return err;
 }
 
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 6984342..69b4a33 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -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;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index ed03968..e86421a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -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) {}
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 6150567..ff5a087 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -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);
 
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index 3070096..bca79f9 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -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__
 
 /*
diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
index 2e67a48..1925163 100644
--- a/arch/arm64/kvm/hyp-init.S
+++ b/arch/arm64/kvm/hyp-init.S
@@ -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
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index 073b8bf..c9804ac 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -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:
 	/*
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 01/16] arm64: Fold proc-macros.S into assembler.h
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 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

diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index b51f2cc..3b46501 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -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 */
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 90d09ed..9ad8b1f 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -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>
diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
index 178ba22..2e67a48 100644
--- a/arch/arm64/kvm/hyp-init.S
+++ b/arch/arm64/kvm/hyp-init.S
@@ -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"
diff --git a/arch/arm64/mm/cache.S b/arch/arm64/mm/cache.S
index eb48d5d..9e13cb5 100644
--- a/arch/arm64/mm/cache.S
+++ b/arch/arm64/mm/cache.S
@@ -24,8 +24,6 @@
 #include <asm/cpufeature.h>
 #include <asm/alternative.h>
 
-#include "proc-macros.S"
-
 /*
  *	flush_icache_range(start,end)
  *
diff --git a/arch/arm64/mm/proc-macros.S b/arch/arm64/mm/proc-macros.S
deleted file mode 100644
index 4c4d93c..0000000
--- a/arch/arm64/mm/proc-macros.S
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Based on arch/arm/mm/proc-macros.S
- *
- * Copyright (C) 2012 ARM Ltd.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <asm/asm-offsets.h>
-#include <asm/thread_info.h>
-
-/*
- * 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
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index e4ee7bd..456c1c5 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -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
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 02/16] arm64: Convert hcalls to use HVC immediate value
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 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(-)

diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index 7a5df52..eb10368 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -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)
 
diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index a272f33..017ab519 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -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)
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index e583613..073b8bf 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -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.
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 00/16] arm64 kexec kernel patches v10
@ 2015-10-19 23:38 ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

Hi All,

This series adds the core support for kexec re-boot and kdump on ARM64.  This
v10 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-7 add back the ARM64 CPU reset support that was recently removed from
the kernel.

Patches 8-10 add the actual kexec support.

Patches 11-16 add kdump support.

Please consider all patches for inclusion.

[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 7379047d5585187d1288486d4627873170d0005a:

  Linux 4.3-rc6 (2015-10-18 16:08:42 -0700)

are available in the git repository at:

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

for you to fetch changes up to 4cf0c03d6cd1cb4826bb5df679fbcdaf80be0b1c:

  arm64: kdump: relax BUG_ON() if more than one cpus are still active (2015-10-19 15:51:52 -0700)

----------------------------------------------------------------
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 (9):
      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
      arm64: Add EL2 switch to cpu_reset
      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       |  29 ++++-
 arch/arm/include/asm/kvm_host.h     |  10 +-
 arch/arm/include/asm/kvm_mmu.h      |   1 +
 arch/arm/kvm/arm.c                  |  58 +++------
 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       |  76 ++++++++++++
 arch/arm64/kernel/cpu-reset.h       |  20 +++
 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   | 237 ++++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/relocate_kernel.S | 163 +++++++++++++++++++++++++
 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, 1063 insertions(+), 138 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

-- 
2.5.0


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 07/16] Revert "arm64: remove dead code"
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

This reverts commit b08d4640a3dca68670fc5af2fe9205b395a02388.

Add back the setup_mm_for_reboot() needed for kexec.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/include/asm/mmu.h |  1 +
 arch/arm64/mm/mmu.c          | 11 +++++++++++
 2 files changed, 12 insertions(+)

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 0302087..79fcfb0 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -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,
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 9211b85..8cffad9 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -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)
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 08/16] arm64/kexec: Add core kexec support
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/Kconfig                  |  10 +++
 arch/arm64/include/asm/kexec.h      |  48 +++++++++++
 arch/arm64/kernel/Makefile          |   2 +
 arch/arm64/kernel/cpu-reset.S       |   2 +-
 arch/arm64/kernel/machine_kexec.c   | 141 +++++++++++++++++++++++++++++++
 arch/arm64/kernel/relocate_kernel.S | 163 ++++++++++++++++++++++++++++++++++++
 include/uapi/linux/kexec.h          |   1 +
 7 files changed, 366 insertions(+), 1 deletion(-)
 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

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 07d1811..73e8e31 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -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 (!SMP || 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
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
new file mode 100644
index 0000000..46d63cd
--- /dev/null
+++ b/arch/arm64/include/asm/kexec.h
@@ -0,0 +1,48 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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_KEXEC_H)
+#define _ARM64_KEXEC_H
+
+/* Maximum physical address we can use pages from */
+
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can reach in physical address mode */
+
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can use for the control code buffer */
+
+#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
+
+#define KEXEC_CONTROL_PAGE_SIZE	4096
+
+#define KEXEC_ARCH KEXEC_ARCH_ARM64
+
+#if !defined(__ASSEMBLY__)
+
+/**
+ * crash_setup_regs() - save registers for the panic kernel
+ *
+ * @newregs: registers are saved here
+ * @oldregs: registers to be saved (may be %NULL)
+ */
+
+static inline void crash_setup_regs(struct pt_regs *newregs,
+				    struct pt_regs *oldregs)
+{
+	/* Empty routine needed to avoid build errors. */
+}
+
+#endif /* !defined(__ASSEMBLY__) */
+
+#endif
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 22dc9bc..989ccd7 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -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)
diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S
index ffc9e385e..7cc7f56 100644
--- a/arch/arm64/kernel/cpu-reset.S
+++ b/arch/arm64/kernel/cpu-reset.S
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2001 Deep Blue Solutions Ltd.
  * Copyright (C) 2012 ARM Ltd.
- * Copyright (C) 2015 Huawei Futurewei Technologies.
+ * Copyright (C) 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
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
new file mode 100644
index 0000000..1fae6ae
--- /dev/null
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -0,0 +1,141 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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/kexec.h>
+#include <linux/of_fdt.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/system_misc.h>
+
+#include "cpu-reset.h"
+
+/* Global variables for the relocate_kernel routine. */
+extern const unsigned char arm64_relocate_new_kernel[];
+extern const unsigned long arm64_relocate_new_kernel_size;
+extern unsigned long arm64_kexec_kimage_head_offset;
+extern unsigned long arm64_kexec_kimage_start_offset;
+
+static unsigned long kimage_head;
+static unsigned long kimage_start;
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+	/* Empty routine needed to avoid build errors. */
+}
+
+/**
+ * machine_kexec_prepare - Prepare for a kexec reboot.
+ *
+ * Called from the core kexec code when a kernel image is loaded.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+	kimage_start = image->start;
+	return 0;
+}
+
+/**
+ * kexec_list_flush - Helper to flush the kimage list to PoC.
+ */
+static void kexec_list_flush(unsigned long kimage_head)
+{
+	unsigned long *entry;
+
+	for (entry = &kimage_head; ; entry++) {
+		unsigned int flag = *entry & IND_FLAGS;
+		void *addr = phys_to_virt(*entry & PAGE_MASK);
+
+		switch (flag) {
+		case IND_INDIRECTION:
+			entry = (unsigned long *)addr - 1;
+			__flush_dcache_area(addr, PAGE_SIZE);
+			break;
+		case IND_DESTINATION:
+			break;
+		case IND_SOURCE:
+			__flush_dcache_area(addr, PAGE_SIZE);
+			break;
+		case IND_DONE:
+			return;
+		default:
+			BUG();
+		}
+	}
+}
+
+static void soft_restart(unsigned long addr)
+{
+	setup_mm_for_reboot();
+	cpu_soft_restart(virt_to_phys(cpu_reset), addr,
+		is_hyp_mode_available());
+
+	BUG(); /* Should never get here. */
+}
+
+/**
+ * machine_kexec - Do the kexec reboot.
+ *
+ * Called from the core kexec code for a sys_reboot with LINUX_REBOOT_CMD_KEXEC.
+ */
+void machine_kexec(struct kimage *image)
+{
+	phys_addr_t reboot_code_buffer_phys;
+	void *reboot_code_buffer;
+
+	BUG_ON(num_online_cpus() > 1);
+
+	kimage_head = image->head;
+
+	reboot_code_buffer_phys = page_to_phys(image->control_code_page);
+	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
+
+	/*
+	 * Copy arm64_relocate_new_kernel to the reboot_code_buffer for use
+	 * after the kernel is shut down.
+	 */
+	memcpy(reboot_code_buffer, arm64_relocate_new_kernel,
+		arm64_relocate_new_kernel_size);
+
+	/* Set the variables in reboot_code_buffer. */
+
+	memcpy(reboot_code_buffer + arm64_kexec_kimage_start_offset,
+	       &kimage_start, sizeof(kimage_start));
+	memcpy(reboot_code_buffer + arm64_kexec_kimage_head_offset,
+	       &kimage_head, sizeof(kimage_head));
+
+	/* Flush the reboot_code_buffer in preparation for its execution. */
+	__flush_dcache_area(reboot_code_buffer, arm64_relocate_new_kernel_size);
+
+	/* Flush the kimage list. */
+	kexec_list_flush(image->head);
+
+	pr_info("Bye!\n");
+
+	/* Disable all DAIF exceptions. */
+	asm volatile ("msr daifset, #0xf" : : : "memory");
+
+	/*
+	 * soft_restart() will shutdown the MMU, disable data caches, then
+	 * transfer control to the reboot_code_buffer which contains a copy of
+	 * the arm64_relocate_new_kernel routine.  arm64_relocate_new_kernel
+	 * will use physical addressing to relocate the new kernel to its final
+	 * position and then will transfer control to the entry point of the new
+	 * kernel.
+	 */
+	soft_restart(reboot_code_buffer_phys);
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+	/* Empty routine needed to avoid build errors. */
+}
diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S
new file mode 100644
index 0000000..7b07a16
--- /dev/null
+++ b/arch/arm64/kernel/relocate_kernel.S
@@ -0,0 +1,163 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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/kexec.h>
+
+#include <asm/assembler.h>
+#include <asm/kexec.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+
+
+/*
+ * arm64_relocate_new_kernel - Put a 2nd stage kernel image in place and boot it.
+ *
+ * The memory that the old kernel occupies may be overwritten when coping the
+ * new image to its final location.  To assure that the
+ * arm64_relocate_new_kernel routine which does that copy is not overwritten,
+ * all code and data needed by arm64_relocate_new_kernel must be between the
+ * symbols arm64_relocate_new_kernel and arm64_relocate_new_kernel_end.  The
+ * machine_kexec() routine will copy arm64_relocate_new_kernel to the kexec
+ * control_code_page, a special page which has been set up to be preserved
+ * during the copy operation.
+ */
+.globl arm64_relocate_new_kernel
+arm64_relocate_new_kernel:
+
+	/* Setup the list loop variables. */
+	ldr	x18, .Lkimage_head		/* x18 = list entry */
+	dcache_line_size x17, x0		/* x17 = dcache line size */
+	mov	x16, xzr			/* x16 = segment start */
+	mov	x15, xzr			/* x15 = entry ptr */
+	mov	x14, xzr			/* x14 = copy dest */
+
+	/* Check if the new image needs relocation. */
+	cbz	x18, .Ldone
+	tbnz	x18, IND_DONE_BIT, .Ldone
+
+.Lloop:
+	and	x13, x18, PAGE_MASK		/* x13 = addr */
+
+	/* Test the entry flags. */
+.Ltest_source:
+	tbz	x18, IND_SOURCE_BIT, .Ltest_indirection
+
+	mov x20, x14				/*  x20 = copy dest */
+	mov x21, x13				/*  x21 = copy src */
+
+	/* Invalidate dest page to PoC. */
+	mov	x0, x20
+	add	x19, x0, #PAGE_SIZE
+	sub	x1, x17, #1
+	bic	x0, x0, x1
+1:	dc	ivac, x0
+	add	x0, x0, x17
+	cmp	x0, x19
+	b.lo	1b
+	dsb	sy
+
+	/* Copy page. */
+1:	ldp	x22, x23, [x21]
+	ldp	x24, x25, [x21, #16]
+	ldp	x26, x27, [x21, #32]
+	ldp	x28, x29, [x21, #48]
+	add	x21, x21, #64
+	stnp	x22, x23, [x20]
+	stnp	x24, x25, [x20, #16]
+	stnp	x26, x27, [x20, #32]
+	stnp	x28, x29, [x20, #48]
+	add	x20, x20, #64
+	tst	x21, #(PAGE_SIZE - 1)
+	b.ne	1b
+
+	/* dest += PAGE_SIZE */
+	add	x14, x14, PAGE_SIZE
+	b	.Lnext
+
+.Ltest_indirection:
+	tbz	x18, IND_INDIRECTION_BIT, .Ltest_destination
+
+	/* ptr = addr */
+	mov	x15, x13
+	b	.Lnext
+
+.Ltest_destination:
+	tbz	x18, IND_DESTINATION_BIT, .Lnext
+
+	mov	x16, x13
+
+	/* dest = addr */
+	mov	x14, x13
+
+.Lnext:
+	/* entry = *ptr++ */
+	ldr	x18, [x15], #8
+
+	/* while (!(entry & DONE)) */
+	tbz	x18, IND_DONE_BIT, .Lloop
+
+.Ldone:
+	dsb	sy
+	isb
+	ic	ialluis
+	dsb	sy
+	isb
+
+	/* Start new image. */
+	ldr	x4, .Lkimage_start
+	mov	x0, xzr
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	br	x4
+
+.align 3	/* To keep the 64-bit values below naturally aligned. */
+
+/* The machine_kexec routine sets these variables via offsets from
+ * arm64_relocate_new_kernel.
+ */
+
+/*
+ * .Lkimage_start - Copy of image->start, the entry point of the new
+ * image.
+ */
+.Lkimage_start:
+	.quad	0x0
+
+/*
+ * .Lkimage_head - Copy of image->head, the list of kimage entries.
+ */
+.Lkimage_head:
+	.quad	0x0
+
+.Lcopy_end:
+.org	KEXEC_CONTROL_PAGE_SIZE
+
+/*
+ * arm64_relocate_new_kernel_size - Number of bytes to copy to the control_code_page.
+ */
+.globl arm64_relocate_new_kernel_size
+arm64_relocate_new_kernel_size:
+	.quad	.Lcopy_end - arm64_relocate_new_kernel
+
+/*
+ * arm64_kexec_kimage_start_offset - Offset for writing .Lkimage_start.
+ */
+.globl arm64_kexec_kimage_start_offset
+arm64_kexec_kimage_start_offset:
+	.quad	.Lkimage_start - arm64_relocate_new_kernel
+
+/*
+ * arm64_kexec_kimage_head_offset - Offset for writing .Lkimage_head.
+ */
+.globl arm64_kexec_kimage_head_offset
+arm64_kexec_kimage_head_offset:
+	.quad	.Lkimage_head - arm64_relocate_new_kernel
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h
index 99048e5..ccec467 100644
--- a/include/uapi/linux/kexec.h
+++ b/include/uapi/linux/kexec.h
@@ -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
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 16/16] arm64: kdump: relax BUG_ON() if more than one cpus are still active
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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 | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index f315ee4..157c29b 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -139,7 +139,12 @@ void machine_kexec(struct kimage *image)
 	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("*\n* kdump might fail because %d cpus are still online\n*\n", num_online_cpus());
+		else
+			BUG();
+	}
 
 	kimage_head = image->head;
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 15/16] arm64: kdump: enable kdump in the arm64 defconfig
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index c80d8a4..94ec44e 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -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
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 09/16] arm64/kexec: Add pr_devel output
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/kernel/machine_kexec.c | 63 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index 1fae6ae..362f719 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -28,6 +28,48 @@ extern unsigned long arm64_kexec_kimage_start_offset;
 static unsigned long kimage_head;
 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 *image)
+{
+	unsigned long i;
+
+#if !defined(DEBUG)
+	return;
+#endif
+	pr_devel("%s:%d:\n", func, line);
+	pr_devel("  kexec image info:\n");
+	pr_devel("    type:        %d\n", image->type);
+	pr_devel("    start:       %lx\n", image->start);
+	pr_devel("    head:        %lx\n", image->head);
+	pr_devel("    nr_segments: %lu\n", image->nr_segments);
+
+	for (i = 0; i < image->nr_segments; i++) {
+		pr_devel("      segment[%lu]: %016lx - %016lx, %lx bytes, %lu pages%s\n",
+			i,
+			image->segment[i].mem,
+			image->segment[i].mem + image->segment[i].memsz,
+			image->segment[i].memsz,
+			image->segment[i].memsz /  PAGE_SIZE,
+			(kexec_is_dtb(image->segment[i].buf) ?
+				", dtb segment" : ""));
+	}
+}
+
 void machine_kexec_cleanup(struct kimage *image)
 {
 	/* Empty routine needed to avoid build errors. */
@@ -41,6 +83,8 @@ void machine_kexec_cleanup(struct kimage *image)
 int machine_kexec_prepare(struct kimage *image)
 {
 	kimage_start = image->start;
+	kexec_image_info(image);
+
 	return 0;
 }
 
@@ -99,6 +143,25 @@ void machine_kexec(struct kimage *image)
 	reboot_code_buffer_phys = page_to_phys(image->control_code_page);
 	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
 
+	kexec_image_info(image);
+
+	pr_devel("%s:%d: control_code_page:        %p\n", __func__, __LINE__,
+		image->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.
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 11/16] arm64: kdump: reserve memory for crash dump kernel
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/setup.c |  7 +++++-
 arch/arm64/mm/init.c      | 54 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 2322479..9d085ac 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -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
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f5c0680..f33f201 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -34,6 +34,7 @@
 #include <linux/dma-contiguous.h>
 #include <linux/efi.h>
 #include <linux/swiotlb.h>
+#include <linux/kexec.h>
 
 #include <asm/fixmap.h>
 #include <asm/memory.h>
@@ -66,6 +67,55 @@ static int __init early_initrd(char *p)
 early_param("initrd", early_initrd);
 #endif
 
+#ifdef CONFIG_KEXEC
+/*
+ * reserve_crashkernel() - reserves memory for crash kernel
+ *
+ * This function reserves memory area given in "crashkernel=" kernel command
+ * line parameter. The memory reserved is used by dump capture kernel when
+ * primary kernel is crashing.
+ */
+static void __init reserve_crashkernel(void)
+{
+	unsigned long long crash_size = 0, crash_base = 0;
+	int ret;
+
+	ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
+				&crash_size, &crash_base);
+	if (ret)
+		return;
+
+	if (crash_base == 0) {
+		crash_base = memblock_alloc(crash_size, 1 << 21);
+		if (crash_base == 0) {
+			pr_warn("Unable to allocate crashkernel (size:%llx)\n",
+				crash_size);
+			return;
+		}
+	} else {
+		/* User specifies base address explicitly. */
+		if (!memblock_is_region_memory(crash_base, crash_size) ||
+			memblock_is_region_reserved(crash_base, crash_size)) {
+			pr_warn("crashkernel has wrong address or size\n");
+			return;
+		}
+
+		if (crash_base & ((1 << 21) - 1)) {
+			pr_warn("crashkernel base address is not 2MB aligned\n");
+			return;
+		}
+
+		memblock_reserve(crash_base, crash_size);
+	}
+
+	pr_info("Reserving %lldMB of memory@%lldMB for crashkernel\n",
+		crash_size >> 20, crash_base >> 20);
+
+	crashk_res.start = crash_base;
+	crashk_res.end = crash_base + crash_size - 1;
+}
+#endif /* CONFIG_KEXEC */
+
 /*
  * 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
@@ -170,6 +220,10 @@ void __init arm64_memblock_init(void)
 		memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start);
 #endif
 
+#ifdef CONFIG_KEXEC
+	reserve_crashkernel();
+#endif
+
 	early_init_fdt_scan_reserved_mem();
 
 	/* 4GB maximum for 32-bit only capable devices */
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 12/16] arm64: kdump: implement machine_crash_shutdown()
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/kexec.h    | 34 +++++++++++++++++++++++++++++++++-
 arch/arm64/kernel/machine_kexec.c | 30 +++++++++++++++++++++++++++++-
 arch/arm64/kernel/smp.c           | 16 ++++++++++++++--
 3 files changed, 76 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 46d63cd..555a955 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -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__) */
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index 362f719..f315ee4 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -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>
@@ -28,6 +29,8 @@ extern unsigned long arm64_kexec_kimage_start_offset;
 static unsigned long kimage_head;
 static unsigned long kimage_start;
 
+bool in_crash_kexec;
+
 /**
  * kexec_is_dtb - Helper routine to check the device tree header signature.
  */
@@ -198,7 +201,32 @@ void machine_kexec(struct kimage *image)
 	soft_restart(reboot_code_buffer_phys);
 }
 
+/**
+ * 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("Loading crashdump kernel...\n");
 }
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index dbdaacd..88aec66 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -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;
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 13/16] arm64: kdump: add kdump support
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 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

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 73e8e31..262bd49 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -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
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 989ccd7..7ef9fa4 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -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)
diff --git a/arch/arm64/kernel/crash_dump.c b/arch/arm64/kernel/crash_dump.c
new file mode 100644
index 0000000..3d86c0a
--- /dev/null
+++ b/arch/arm64/kernel/crash_dump.c
@@ -0,0 +1,71 @@
+/*
+ * Routines for doing kexec-based kdump
+ *
+ * Copyright (C) 2014 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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/crash_dump.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/memblock.h>
+#include <linux/uaccess.h>
+#include <asm/memory.h>
+
+/**
+ * copy_oldmem_page() - copy one page from old kernel memory
+ * @pfn: page frame number to be copied
+ * @buf: buffer where the copied page is placed
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page
+ * @userbuf: if set, @buf is in a user address space
+ *
+ * This function copies one page from old kernel memory into buffer pointed by
+ * @buf. If @buf is in userspace, set @userbuf to %1. Returns number of bytes
+ * copied or negative error in case of failure.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+			 size_t csize, unsigned long offset,
+			 int userbuf)
+{
+	void *vaddr;
+
+	if (!csize)
+		return 0;
+
+	vaddr = ioremap_cache(pfn << PAGE_SHIFT, PAGE_SIZE);
+	if (!vaddr)
+		return -ENOMEM;
+
+	if (userbuf) {
+		if (copy_to_user(buf, vaddr + offset, csize)) {
+			iounmap(vaddr);
+			return -EFAULT;
+		}
+	} else {
+		memcpy(buf, vaddr + offset, csize);
+	}
+
+	iounmap(vaddr);
+
+	return csize;
+}
+
+/**
+ * elfcorehdr_read - read from ELF core header
+ * @buf: buffer where the data is placed
+ * @csize: number of bytes to read
+ * @ppos: address in the memory
+ *
+ * This function reads @count bytes from elf core header which exists
+ * on crash dump kernel's memory.
+ */
+ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos)
+{
+	memcpy(buf, phys_to_virt((phys_addr_t)*ppos), count);
+	return count;
+}
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f33f201..ff8eeb4 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -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();
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 10/16] arm64/kexec: Enable kexec in the arm64 defconfig
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 34d71dd..c80d8a4 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -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
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 14/16] arm64: kdump: update a kernel doc
  2015-10-19 23:38 ` Geoff Levand
@ 2015-10-19 23:38   ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 Documentation/kdump/kdump.txt | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index bc4bd5a..35f4fa7 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -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,26 @@ 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.
+
 Extended crashkernel syntax
 ===========================
 
@@ -312,6 +332,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 +356,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 +401,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
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 16/16] arm64: kdump: relax BUG_ON() if more than one cpus are still active
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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 | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index f315ee4..157c29b 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -139,7 +139,12 @@ void machine_kexec(struct kimage *image)
 	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("*\n* kdump might fail because %d cpus are still online\n*\n", num_online_cpus());
+		else
+			BUG();
+	}
 
 	kimage_head = image->head;
 
-- 
2.5.0


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 09/16] arm64/kexec: Add pr_devel output
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/kernel/machine_kexec.c | 63 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index 1fae6ae..362f719 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -28,6 +28,48 @@ extern unsigned long arm64_kexec_kimage_start_offset;
 static unsigned long kimage_head;
 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 *image)
+{
+	unsigned long i;
+
+#if !defined(DEBUG)
+	return;
+#endif
+	pr_devel("%s:%d:\n", func, line);
+	pr_devel("  kexec image info:\n");
+	pr_devel("    type:        %d\n", image->type);
+	pr_devel("    start:       %lx\n", image->start);
+	pr_devel("    head:        %lx\n", image->head);
+	pr_devel("    nr_segments: %lu\n", image->nr_segments);
+
+	for (i = 0; i < image->nr_segments; i++) {
+		pr_devel("      segment[%lu]: %016lx - %016lx, %lx bytes, %lu pages%s\n",
+			i,
+			image->segment[i].mem,
+			image->segment[i].mem + image->segment[i].memsz,
+			image->segment[i].memsz,
+			image->segment[i].memsz /  PAGE_SIZE,
+			(kexec_is_dtb(image->segment[i].buf) ?
+				", dtb segment" : ""));
+	}
+}
+
 void machine_kexec_cleanup(struct kimage *image)
 {
 	/* Empty routine needed to avoid build errors. */
@@ -41,6 +83,8 @@ void machine_kexec_cleanup(struct kimage *image)
 int machine_kexec_prepare(struct kimage *image)
 {
 	kimage_start = image->start;
+	kexec_image_info(image);
+
 	return 0;
 }
 
@@ -99,6 +143,25 @@ void machine_kexec(struct kimage *image)
 	reboot_code_buffer_phys = page_to_phys(image->control_code_page);
 	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
 
+	kexec_image_info(image);
+
+	pr_devel("%s:%d: control_code_page:        %p\n", __func__, __LINE__,
+		image->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.
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 15/16] arm64: kdump: enable kdump in the arm64 defconfig
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index c80d8a4..94ec44e 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -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
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 11/16] arm64: kdump: reserve memory for crash dump kernel
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/kernel/setup.c |  7 +++++-
 arch/arm64/mm/init.c      | 54 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 2322479..9d085ac 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -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
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f5c0680..f33f201 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -34,6 +34,7 @@
 #include <linux/dma-contiguous.h>
 #include <linux/efi.h>
 #include <linux/swiotlb.h>
+#include <linux/kexec.h>
 
 #include <asm/fixmap.h>
 #include <asm/memory.h>
@@ -66,6 +67,55 @@ static int __init early_initrd(char *p)
 early_param("initrd", early_initrd);
 #endif
 
+#ifdef CONFIG_KEXEC
+/*
+ * reserve_crashkernel() - reserves memory for crash kernel
+ *
+ * This function reserves memory area given in "crashkernel=" kernel command
+ * line parameter. The memory reserved is used by dump capture kernel when
+ * primary kernel is crashing.
+ */
+static void __init reserve_crashkernel(void)
+{
+	unsigned long long crash_size = 0, crash_base = 0;
+	int ret;
+
+	ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
+				&crash_size, &crash_base);
+	if (ret)
+		return;
+
+	if (crash_base == 0) {
+		crash_base = memblock_alloc(crash_size, 1 << 21);
+		if (crash_base == 0) {
+			pr_warn("Unable to allocate crashkernel (size:%llx)\n",
+				crash_size);
+			return;
+		}
+	} else {
+		/* User specifies base address explicitly. */
+		if (!memblock_is_region_memory(crash_base, crash_size) ||
+			memblock_is_region_reserved(crash_base, crash_size)) {
+			pr_warn("crashkernel has wrong address or size\n");
+			return;
+		}
+
+		if (crash_base & ((1 << 21) - 1)) {
+			pr_warn("crashkernel base address is not 2MB aligned\n");
+			return;
+		}
+
+		memblock_reserve(crash_base, crash_size);
+	}
+
+	pr_info("Reserving %lldMB of memory at %lldMB for crashkernel\n",
+		crash_size >> 20, crash_base >> 20);
+
+	crashk_res.start = crash_base;
+	crashk_res.end = crash_base + crash_size - 1;
+}
+#endif /* CONFIG_KEXEC */
+
 /*
  * 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
@@ -170,6 +220,10 @@ void __init arm64_memblock_init(void)
 		memblock_reserve(__virt_to_phys(initrd_start), initrd_end - initrd_start);
 #endif
 
+#ifdef CONFIG_KEXEC
+	reserve_crashkernel();
+#endif
+
 	early_init_fdt_scan_reserved_mem();
 
 	/* 4GB maximum for 32-bit only capable devices */
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 12/16] arm64: kdump: implement machine_crash_shutdown()
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 arch/arm64/include/asm/kexec.h    | 34 +++++++++++++++++++++++++++++++++-
 arch/arm64/kernel/machine_kexec.c | 30 +++++++++++++++++++++++++++++-
 arch/arm64/kernel/smp.c           | 16 ++++++++++++++--
 3 files changed, 76 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 46d63cd..555a955 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -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__) */
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index 362f719..f315ee4 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -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>
@@ -28,6 +29,8 @@ extern unsigned long arm64_kexec_kimage_start_offset;
 static unsigned long kimage_head;
 static unsigned long kimage_start;
 
+bool in_crash_kexec;
+
 /**
  * kexec_is_dtb - Helper routine to check the device tree header signature.
  */
@@ -198,7 +201,32 @@ void machine_kexec(struct kimage *image)
 	soft_restart(reboot_code_buffer_phys);
 }
 
+/**
+ * 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("Loading crashdump kernel...\n");
 }
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index dbdaacd..88aec66 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -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;
 
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 10/16] arm64/kexec: Enable kexec in the arm64 defconfig
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 34d71dd..c80d8a4 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -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
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 13/16] arm64: kdump: add kdump support
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 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

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 73e8e31..262bd49 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -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
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 989ccd7..7ef9fa4 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -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)
diff --git a/arch/arm64/kernel/crash_dump.c b/arch/arm64/kernel/crash_dump.c
new file mode 100644
index 0000000..3d86c0a
--- /dev/null
+++ b/arch/arm64/kernel/crash_dump.c
@@ -0,0 +1,71 @@
+/*
+ * Routines for doing kexec-based kdump
+ *
+ * Copyright (C) 2014 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * 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/crash_dump.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/memblock.h>
+#include <linux/uaccess.h>
+#include <asm/memory.h>
+
+/**
+ * copy_oldmem_page() - copy one page from old kernel memory
+ * @pfn: page frame number to be copied
+ * @buf: buffer where the copied page is placed
+ * @csize: number of bytes to copy
+ * @offset: offset in bytes into the page
+ * @userbuf: if set, @buf is in a user address space
+ *
+ * This function copies one page from old kernel memory into buffer pointed by
+ * @buf. If @buf is in userspace, set @userbuf to %1. Returns number of bytes
+ * copied or negative error in case of failure.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+			 size_t csize, unsigned long offset,
+			 int userbuf)
+{
+	void *vaddr;
+
+	if (!csize)
+		return 0;
+
+	vaddr = ioremap_cache(pfn << PAGE_SHIFT, PAGE_SIZE);
+	if (!vaddr)
+		return -ENOMEM;
+
+	if (userbuf) {
+		if (copy_to_user(buf, vaddr + offset, csize)) {
+			iounmap(vaddr);
+			return -EFAULT;
+		}
+	} else {
+		memcpy(buf, vaddr + offset, csize);
+	}
+
+	iounmap(vaddr);
+
+	return csize;
+}
+
+/**
+ * elfcorehdr_read - read from ELF core header
+ * @buf: buffer where the data is placed
+ * @csize: number of bytes to read
+ * @ppos: address in the memory
+ *
+ * This function reads @count bytes from elf core header which exists
+ * on crash dump kernel's memory.
+ */
+ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos)
+{
+	memcpy(buf, phys_to_virt((phys_addr_t)*ppos), count);
+	return count;
+}
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f33f201..ff8eeb4 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -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();
 
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 14/16] arm64: kdump: update a kernel doc
@ 2015-10-19 23:38   ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-19 23:38 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 Documentation/kdump/kdump.txt | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index bc4bd5a..35f4fa7 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -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,26 @@ 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.
+
 Extended crashkernel syntax
 ===========================
 
@@ -312,6 +332,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 +356,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 +401,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
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 08/16] arm64/kexec: Add core kexec support
  2015-10-19 23:38   ` Geoff Levand
@ 2015-10-20  8:56     ` Pratyush Anand
  -1 siblings, 0 replies; 72+ messages in thread
From: Pratyush Anand @ 2015-10-20  8:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Geoff,

Thanks for the patches.

On 19/10/2015:11:38:53 PM, Geoff Levand wrote:
> +static void soft_restart(unsigned long addr)
> +{
> +	setup_mm_for_reboot();
> +	cpu_soft_restart(virt_to_phys(cpu_reset), addr,
> +		is_hyp_mode_available());

So now we do not flush cache for any memory region. Shouldn't we still flush
at least kernel and purgatory segments. 

kexec-tools loads a new kernel and purgatory executable. Some of those bits
might still be only in D-cache and we disable D-cache before control is passed
to the purgatory binary. Purgatory and some initial part of kernel code is
executed with D-cache disabled. So, We might land into a situation where correct
code is not executed while D-cache is disabled, no?

~Pratyush

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 08/16] arm64/kexec: Add core kexec support
@ 2015-10-20  8:56     ` Pratyush Anand
  0 siblings, 0 replies; 72+ messages in thread
From: Pratyush Anand @ 2015-10-20  8:56 UTC (permalink / raw)
  To: Geoff Levand
  Cc: Mark Rutland, AKASHI, marc.zyngier, Catalin Marinas, Will Deacon,
	Takahiro, christoffer.dall, kexec, linux-arm-kernel

Hi Geoff,

Thanks for the patches.

On 19/10/2015:11:38:53 PM, Geoff Levand wrote:
> +static void soft_restart(unsigned long addr)
> +{
> +	setup_mm_for_reboot();
> +	cpu_soft_restart(virt_to_phys(cpu_reset), addr,
> +		is_hyp_mode_available());

So now we do not flush cache for any memory region. Shouldn't we still flush
at least kernel and purgatory segments. 

kexec-tools loads a new kernel and purgatory executable. Some of those bits
might still be only in D-cache and we disable D-cache before control is passed
to the purgatory binary. Purgatory and some initial part of kernel code is
executed with D-cache disabled. So, We might land into a situation where correct
code is not executed while D-cache is disabled, no?

~Pratyush

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 08/16] arm64/kexec: Add core kexec support
  2015-10-20  8:56     ` Pratyush Anand
@ 2015-10-20 17:19       ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-20 17:19 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Tue, 2015-10-20 at 14:26 +0530, Pratyush Anand wrote:
> On 19/10/2015:11:38:53 PM, Geoff Levand wrote:
> > +static void soft_restart(unsigned long addr)
> > +{
> > +> > 	> > setup_mm_for_reboot();
> > +> > 	> > cpu_soft_restart(virt_to_phys(cpu_reset), addr,
> > +> > 	> > 	> > is_hyp_mode_available());
> 
> So now we do not flush cache for any memory region. Shouldn't we still flush
> at least kernel and purgatory segments. 

Relevant pages of the kexec list are flushed in the code following the comment
'Invalidate dest page to PoC' of the arm64_relocate_new_kernel routine:

 The dcache is turned off
 The page is invalidated to PoC
 The new page is written

-Geoff

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 08/16] arm64/kexec: Add core kexec support
@ 2015-10-20 17:19       ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-20 17:19 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: Mark Rutland, AKASHI, marc.zyngier, Catalin Marinas, Will Deacon,
	Takahiro, linux-arm-kernel, kexec, christoffer.dall

Hi,

On Tue, 2015-10-20 at 14:26 +0530, Pratyush Anand wrote:
> On 19/10/2015:11:38:53 PM, Geoff Levand wrote:
> > +static void soft_restart(unsigned long addr)
> > +{
> > +> > 	> > setup_mm_for_reboot();
> > +> > 	> > cpu_soft_restart(virt_to_phys(cpu_reset), addr,
> > +> > 	> > 	> > is_hyp_mode_available());
> 
> So now we do not flush cache for any memory region. Shouldn't we still flush
> at least kernel and purgatory segments. 

Relevant pages of the kexec list are flushed in the code following the comment
'Invalidate dest page to PoC' of the arm64_relocate_new_kernel routine:

 The dcache is turned off
 The page is invalidated to PoC
 The new page is written

-Geoff


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v10.1 12/16] arm64: kdump: implement machine_crash_shutdown()
  2015-10-19 23:38   ` Geoff Levand
@ 2015-10-20 18:54     ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-20 18:54 UTC (permalink / raw)
  To: linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
v10.1: Fixed: crash dump kernel won't be able to boot if a kvm
guest is running at crash. This is because we don't have any chance
to reset EL2 mode at crash and so "switch to EL2" in cpu_reset fails.


 arch/arm64/include/asm/kexec.h    | 34 +++++++++++++++++++++++++++++++++-
 arch/arm64/kernel/machine_kexec.c | 32 ++++++++++++++++++++++++++++++--
 arch/arm64/kernel/smp.c           | 16 ++++++++++++++--
 3 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 46d63cd..555a955 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -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__) */
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index 362f719..8595d43 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -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>
@@ -28,6 +29,8 @@ extern unsigned long arm64_kexec_kimage_start_offset;
 static unsigned long kimage_head;
 static unsigned long kimage_start;
 
+bool in_crash_kexec;
+
 /**
  * kexec_is_dtb - Helper routine to check the device tree header signature.
  */
@@ -121,7 +124,7 @@ static void soft_restart(unsigned long addr)
 {
 	setup_mm_for_reboot();
 	cpu_soft_restart(virt_to_phys(cpu_reset), addr,
-		is_hyp_mode_available());
+		(in_crash_kexec ? 0 : is_hyp_mode_available()));
 
 	BUG(); /* Should never get here. */
 }
@@ -198,7 +201,32 @@ void machine_kexec(struct kimage *image)
 	soft_restart(reboot_code_buffer_phys);
 }
 
+/**
+ * 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("Loading crashdump kernel...\n");
 }
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index dbdaacd..88aec66 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -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;
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v10.1 12/16] arm64: kdump: implement machine_crash_shutdown()
@ 2015-10-20 18:54     ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-20 18:54 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	christoffer.dall, linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
v10.1: Fixed: crash dump kernel won't be able to boot if a kvm
guest is running at crash. This is because we don't have any chance
to reset EL2 mode at crash and so "switch to EL2" in cpu_reset fails.


 arch/arm64/include/asm/kexec.h    | 34 +++++++++++++++++++++++++++++++++-
 arch/arm64/kernel/machine_kexec.c | 32 ++++++++++++++++++++++++++++++--
 arch/arm64/kernel/smp.c           | 16 ++++++++++++++--
 3 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 46d63cd..555a955 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -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__) */
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index 362f719..8595d43 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -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>
@@ -28,6 +29,8 @@ extern unsigned long arm64_kexec_kimage_start_offset;
 static unsigned long kimage_head;
 static unsigned long kimage_start;
 
+bool in_crash_kexec;
+
 /**
  * kexec_is_dtb - Helper routine to check the device tree header signature.
  */
@@ -121,7 +124,7 @@ static void soft_restart(unsigned long addr)
 {
 	setup_mm_for_reboot();
 	cpu_soft_restart(virt_to_phys(cpu_reset), addr,
-		is_hyp_mode_available());
+		(in_crash_kexec ? 0 : is_hyp_mode_available()));
 
 	BUG(); /* Should never get here. */
 }
@@ -198,7 +201,32 @@ void machine_kexec(struct kimage *image)
 	soft_restart(reboot_code_buffer_phys);
 }
 
+/**
+ * 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("Loading crashdump kernel...\n");
 }
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index dbdaacd..88aec66 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -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;
 
-- 
2.5.0


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v10.1 04/16] arm64: kvm: allows kvm cpu hotplug
  2015-10-19 23:38   ` Geoff Levand
@ 2015-10-20 18:57     ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-20 18:57 UTC (permalink / raw)
  To: linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
V10.1: Fixed: kvm cannot start a guest when cpuidle is enabled
if the hardware does not retain cpu state (EL2) in idle state.

This patch re-initailizes EL2 state at CPU_PM_EXIT by calling
kvm_arch_hardware_enable() if and only if kvm has been initialized
before CPU_PM_ENTER, that is, if any vcpus have been created.


 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(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index c4072d9..4c6a38c 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -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) {}
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 405aa18..dc6fadf 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -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);
 
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index dc017ad..fbff638 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -16,7 +16,6 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -61,6 +60,8 @@ static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
 static u8 kvm_next_vmid;
 static DEFINE_SPINLOCK(kvm_vmid_lock);
 
+static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled);
+
 static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu)
 {
 	BUG_ON(preemptible());
@@ -85,11 +86,6 @@ struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void)
 	return &kvm_arm_running_vcpu;
 }
 
-int kvm_arch_hardware_enable(void)
-{
-	return 0;
-}
-
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 {
 	return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
@@ -915,7 +911,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
 	}
 }
 
-static void cpu_init_hyp_mode(void *dummy)
+int kvm_arch_hardware_enable(void)
 {
 	phys_addr_t boot_pgd_ptr;
 	phys_addr_t pgd_ptr;
@@ -923,6 +919,9 @@ static void cpu_init_hyp_mode(void *dummy)
 	unsigned long stack_page;
 	unsigned long vector_ptr;
 
+	if (__hyp_get_vectors() != hyp_default_vectors)
+		return 0;
+
 	/* Switch from the HYP stub to our own HYP init vector */
 	__hyp_set_vectors(kvm_get_idmap_vector());
 
@@ -935,38 +934,50 @@ static void cpu_init_hyp_mode(void *dummy)
 	__cpu_init_hyp_mode(boot_pgd_ptr, pgd_ptr, hyp_stack_ptr, vector_ptr);
 
 	kvm_arm_init_debug();
+
+	return 0;
 }
 
-static int hyp_init_cpu_notify(struct notifier_block *self,
-			       unsigned long action, void *cpu)
+void kvm_arch_hardware_disable(void)
 {
-	switch (action) {
-	case CPU_STARTING:
-	case CPU_STARTING_FROZEN:
-		if (__hyp_get_vectors() == hyp_default_vectors)
-			cpu_init_hyp_mode(NULL);
-		break;
-	}
+	phys_addr_t boot_pgd_ptr;
+	phys_addr_t phys_idmap_start;
 
-	return NOTIFY_OK;
-}
+	if (__hyp_get_vectors() == hyp_default_vectors)
+		return;
 
-static struct notifier_block hyp_init_cpu_nb = {
-	.notifier_call = hyp_init_cpu_notify,
-};
+	boot_pgd_ptr = kvm_mmu_get_boot_httbr();
+	phys_idmap_start = kvm_get_idmap_start();
+
+	__cpu_reset_hyp_mode(boot_pgd_ptr, phys_idmap_start);
+}
 
 #ifdef CONFIG_CPU_PM
 static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
 				    unsigned long cmd,
 				    void *v)
 {
-	if (cmd == CPU_PM_EXIT &&
-	    __hyp_get_vectors() == hyp_default_vectors) {
-		cpu_init_hyp_mode(NULL);
+	switch (cmd) {
+	case CPU_PM_ENTER:
+		if (__hyp_get_vectors() != hyp_default_vectors)
+			__this_cpu_write(kvm_arm_hardware_enabled, 1);
+		else
+			__this_cpu_write(kvm_arm_hardware_enabled, 0);
+		/*
+		 * don't call kvm_arch_hardware_disable() in case of
+		 * CPU_PM_ENTER because it does't actually save any state.
+		 */
+
+		return NOTIFY_OK;
+	case CPU_PM_EXIT:
+		if (__this_cpu_read(kvm_arm_hardware_enabled))
+			kvm_arch_hardware_enable();
+
 		return NOTIFY_OK;
-	}
 
-	return NOTIFY_DONE;
+	default:
+		return NOTIFY_DONE;
+	}
 }
 
 static struct notifier_block hyp_init_cpu_pm_nb = {
@@ -1064,11 +1075,6 @@ static int init_hyp_mode(void)
 	}
 
 	/*
-	 * Execute the init code on each CPU.
-	 */
-	on_each_cpu(cpu_init_hyp_mode, NULL, 1);
-
-	/*
 	 * Init HYP view of VGIC
 	 */
 	err = kvm_vgic_hyp_init();
@@ -1142,26 +1148,15 @@ int kvm_arch_init(void *opaque)
 		}
 	}
 
-	cpu_notifier_register_begin();
-
 	err = init_hyp_mode();
 	if (err)
 		goto out_err;
 
-	err = __register_cpu_notifier(&hyp_init_cpu_nb);
-	if (err) {
-		kvm_err("Cannot register HYP init CPU notifier (%d)\n", err);
-		goto out_err;
-	}
-
-	cpu_notifier_register_done();
-
 	hyp_cpu_pm_init();
 
 	kvm_coproc_table_init();
 	return 0;
 out_err:
-	cpu_notifier_register_done();
 	return err;
 }
 
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 6984342..69b4a33 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -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;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index ed03968..e86421a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -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) {}
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 6150567..ff5a087 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -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);
 
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index 3070096..bca79f9 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -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__
 
 /*
diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
index 2e67a48..1925163 100644
--- a/arch/arm64/kvm/hyp-init.S
+++ b/arch/arm64/kvm/hyp-init.S
@@ -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
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index 073b8bf..c9804ac 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -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:
 	/*
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v10.1 04/16] arm64: kvm: allows kvm cpu hotplug
@ 2015-10-20 18:57     ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-20 18:57 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

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.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
V10.1: Fixed: kvm cannot start a guest when cpuidle is enabled
if the hardware does not retain cpu state (EL2) in idle state.

This patch re-initailizes EL2 state at CPU_PM_EXIT by calling
kvm_arch_hardware_enable() if and only if kvm has been initialized
before CPU_PM_ENTER, that is, if any vcpus have been created.


 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(-)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index c4072d9..4c6a38c 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -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) {}
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 405aa18..dc6fadf 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -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);
 
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index dc017ad..fbff638 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -16,7 +16,6 @@
  * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-#include <linux/cpu.h>
 #include <linux/cpu_pm.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -61,6 +60,8 @@ static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
 static u8 kvm_next_vmid;
 static DEFINE_SPINLOCK(kvm_vmid_lock);
 
+static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled);
+
 static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu)
 {
 	BUG_ON(preemptible());
@@ -85,11 +86,6 @@ struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void)
 	return &kvm_arm_running_vcpu;
 }
 
-int kvm_arch_hardware_enable(void)
-{
-	return 0;
-}
-
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 {
 	return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
@@ -915,7 +911,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
 	}
 }
 
-static void cpu_init_hyp_mode(void *dummy)
+int kvm_arch_hardware_enable(void)
 {
 	phys_addr_t boot_pgd_ptr;
 	phys_addr_t pgd_ptr;
@@ -923,6 +919,9 @@ static void cpu_init_hyp_mode(void *dummy)
 	unsigned long stack_page;
 	unsigned long vector_ptr;
 
+	if (__hyp_get_vectors() != hyp_default_vectors)
+		return 0;
+
 	/* Switch from the HYP stub to our own HYP init vector */
 	__hyp_set_vectors(kvm_get_idmap_vector());
 
@@ -935,38 +934,50 @@ static void cpu_init_hyp_mode(void *dummy)
 	__cpu_init_hyp_mode(boot_pgd_ptr, pgd_ptr, hyp_stack_ptr, vector_ptr);
 
 	kvm_arm_init_debug();
+
+	return 0;
 }
 
-static int hyp_init_cpu_notify(struct notifier_block *self,
-			       unsigned long action, void *cpu)
+void kvm_arch_hardware_disable(void)
 {
-	switch (action) {
-	case CPU_STARTING:
-	case CPU_STARTING_FROZEN:
-		if (__hyp_get_vectors() == hyp_default_vectors)
-			cpu_init_hyp_mode(NULL);
-		break;
-	}
+	phys_addr_t boot_pgd_ptr;
+	phys_addr_t phys_idmap_start;
 
-	return NOTIFY_OK;
-}
+	if (__hyp_get_vectors() == hyp_default_vectors)
+		return;
 
-static struct notifier_block hyp_init_cpu_nb = {
-	.notifier_call = hyp_init_cpu_notify,
-};
+	boot_pgd_ptr = kvm_mmu_get_boot_httbr();
+	phys_idmap_start = kvm_get_idmap_start();
+
+	__cpu_reset_hyp_mode(boot_pgd_ptr, phys_idmap_start);
+}
 
 #ifdef CONFIG_CPU_PM
 static int hyp_init_cpu_pm_notifier(struct notifier_block *self,
 				    unsigned long cmd,
 				    void *v)
 {
-	if (cmd == CPU_PM_EXIT &&
-	    __hyp_get_vectors() == hyp_default_vectors) {
-		cpu_init_hyp_mode(NULL);
+	switch (cmd) {
+	case CPU_PM_ENTER:
+		if (__hyp_get_vectors() != hyp_default_vectors)
+			__this_cpu_write(kvm_arm_hardware_enabled, 1);
+		else
+			__this_cpu_write(kvm_arm_hardware_enabled, 0);
+		/*
+		 * don't call kvm_arch_hardware_disable() in case of
+		 * CPU_PM_ENTER because it does't actually save any state.
+		 */
+
+		return NOTIFY_OK;
+	case CPU_PM_EXIT:
+		if (__this_cpu_read(kvm_arm_hardware_enabled))
+			kvm_arch_hardware_enable();
+
 		return NOTIFY_OK;
-	}
 
-	return NOTIFY_DONE;
+	default:
+		return NOTIFY_DONE;
+	}
 }
 
 static struct notifier_block hyp_init_cpu_pm_nb = {
@@ -1064,11 +1075,6 @@ static int init_hyp_mode(void)
 	}
 
 	/*
-	 * Execute the init code on each CPU.
-	 */
-	on_each_cpu(cpu_init_hyp_mode, NULL, 1);
-
-	/*
 	 * Init HYP view of VGIC
 	 */
 	err = kvm_vgic_hyp_init();
@@ -1142,26 +1148,15 @@ int kvm_arch_init(void *opaque)
 		}
 	}
 
-	cpu_notifier_register_begin();
-
 	err = init_hyp_mode();
 	if (err)
 		goto out_err;
 
-	err = __register_cpu_notifier(&hyp_init_cpu_nb);
-	if (err) {
-		kvm_err("Cannot register HYP init CPU notifier (%d)\n", err);
-		goto out_err;
-	}
-
-	cpu_notifier_register_done();
-
 	hyp_cpu_pm_init();
 
 	kvm_coproc_table_init();
 	return 0;
 out_err:
-	cpu_notifier_register_done();
 	return err;
 }
 
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 6984342..69b4a33 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -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;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index ed03968..e86421a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -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) {}
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 6150567..ff5a087 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -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);
 
diff --git a/arch/arm64/include/asm/virt.h b/arch/arm64/include/asm/virt.h
index 3070096..bca79f9 100644
--- a/arch/arm64/include/asm/virt.h
+++ b/arch/arm64/include/asm/virt.h
@@ -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__
 
 /*
diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
index 2e67a48..1925163 100644
--- a/arch/arm64/kvm/hyp-init.S
+++ b/arch/arm64/kvm/hyp-init.S
@@ -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
diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index 073b8bf..c9804ac 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -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:
 	/*
-- 
2.5.0


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v10.2 08/16] arm64/kexec: Add core kexec support
  2015-10-19 23:38   ` Geoff Levand
@ 2015-10-21 18:30     ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-21 18:30 UTC (permalink / raw)
  To: linux-arm-kernel

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
V10.2: Minor comment fixups.

 arch/arm64/Kconfig                  |  10 +++
 arch/arm64/include/asm/kexec.h      |  48 +++++++++++
 arch/arm64/kernel/Makefile          |   2 +
 arch/arm64/kernel/machine_kexec.c   | 140 +++++++++++++++++++++++++++++++
 arch/arm64/kernel/relocate_kernel.S | 163 ++++++++++++++++++++++++++++++++++++
 include/uapi/linux/kexec.h          |   1 +
 6 files changed, 364 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

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 07d1811..73e8e31 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -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 (!SMP || 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
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
new file mode 100644
index 0000000..46d63cd
--- /dev/null
+++ b/arch/arm64/include/asm/kexec.h
@@ -0,0 +1,48 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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_KEXEC_H)
+#define _ARM64_KEXEC_H
+
+/* Maximum physical address we can use pages from */
+
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can reach in physical address mode */
+
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can use for the control code buffer */
+
+#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
+
+#define KEXEC_CONTROL_PAGE_SIZE	4096
+
+#define KEXEC_ARCH KEXEC_ARCH_ARM64
+
+#if !defined(__ASSEMBLY__)
+
+/**
+ * crash_setup_regs() - save registers for the panic kernel
+ *
+ * @newregs: registers are saved here
+ * @oldregs: registers to be saved (may be %NULL)
+ */
+
+static inline void crash_setup_regs(struct pt_regs *newregs,
+				    struct pt_regs *oldregs)
+{
+	/* Empty routine needed to avoid build errors. */
+}
+
+#endif /* !defined(__ASSEMBLY__) */
+
+#endif
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 22dc9bc..989ccd7 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -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)
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
new file mode 100644
index 0000000..7e3436d
--- /dev/null
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -0,0 +1,140 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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/kexec.h>
+#include <linux/of_fdt.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/system_misc.h>
+
+#include "cpu-reset.h"
+
+/* Global variables for the arm64_relocate_new_kernel routine. */
+extern const unsigned char arm64_relocate_new_kernel[];
+extern const unsigned long arm64_relocate_new_kernel_size;
+extern unsigned long arm64_kexec_kimage_head_offset;
+extern unsigned long arm64_kexec_kimage_start_offset;
+
+static unsigned long kimage_head;
+static unsigned long kimage_start;
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+	/* Empty routine needed to avoid build errors. */
+}
+
+/**
+ * machine_kexec_prepare - Prepare for a kexec reboot.
+ *
+ * Called from the core kexec code when a kernel image is loaded.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+	kimage_start = image->start;
+	return 0;
+}
+
+/**
+ * kexec_list_flush - Helper to flush the kimage list to PoC.
+ */
+static void kexec_list_flush(unsigned long kimage_head)
+{
+	unsigned long *entry;
+
+	for (entry = &kimage_head; ; entry++) {
+		unsigned int flag = *entry & IND_FLAGS;
+		void *addr = phys_to_virt(*entry & PAGE_MASK);
+
+		switch (flag) {
+		case IND_INDIRECTION:
+			entry = (unsigned long *)addr - 1;
+			__flush_dcache_area(addr, PAGE_SIZE);
+			break;
+		case IND_DESTINATION:
+			break;
+		case IND_SOURCE:
+			__flush_dcache_area(addr, PAGE_SIZE);
+			break;
+		case IND_DONE:
+			return;
+		default:
+			BUG();
+		}
+	}
+}
+
+static void soft_restart(unsigned long addr)
+{
+	setup_mm_for_reboot();
+	cpu_soft_restart(virt_to_phys(cpu_reset), addr,
+		is_hyp_mode_available());
+
+	BUG(); /* Should never get here. */
+}
+
+/**
+ * machine_kexec - Do the kexec reboot.
+ *
+ * Called from the core kexec code for a sys_reboot with LINUX_REBOOT_CMD_KEXEC.
+ */
+void machine_kexec(struct kimage *image)
+{
+	phys_addr_t reboot_code_buffer_phys;
+	void *reboot_code_buffer;
+
+	BUG_ON(num_online_cpus() > 1);
+
+	kimage_head = image->head;
+
+	reboot_code_buffer_phys = page_to_phys(image->control_code_page);
+	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
+
+	/*
+	 * Copy arm64_relocate_new_kernel to the reboot_code_buffer for use
+	 * after the kernel is shut down.
+	 */
+	memcpy(reboot_code_buffer, arm64_relocate_new_kernel,
+		arm64_relocate_new_kernel_size);
+
+	/* Set the variables in reboot_code_buffer. */
+	memcpy(reboot_code_buffer + arm64_kexec_kimage_start_offset,
+	       &kimage_start, sizeof(kimage_start));
+	memcpy(reboot_code_buffer + arm64_kexec_kimage_head_offset,
+	       &kimage_head, sizeof(kimage_head));
+
+	/* Flush the reboot_code_buffer in preparation for its execution. */
+	__flush_dcache_area(reboot_code_buffer, arm64_relocate_new_kernel_size);
+
+	/* Flush the kimage list. */
+	kexec_list_flush(image->head);
+
+	pr_info("Bye!\n");
+
+	/* Disable all DAIF exceptions. */
+	asm volatile ("msr daifset, #0xf" : : : "memory");
+
+	/*
+	 * soft_restart() will shutdown the MMU, disable data caches, then
+	 * transfer control to the reboot_code_buffer which contains a copy of
+	 * the arm64_relocate_new_kernel routine.  arm64_relocate_new_kernel
+	 * uses physical addressing to relocate the new image to its final
+	 * position and transfers control to the image entry point when the
+	 * relocation is complete.
+	 */
+	soft_restart(reboot_code_buffer_phys);
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+	/* Empty routine needed to avoid build errors. */
+}
diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S
new file mode 100644
index 0000000..2d709c6
--- /dev/null
+++ b/arch/arm64/kernel/relocate_kernel.S
@@ -0,0 +1,163 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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/kexec.h>
+
+#include <asm/assembler.h>
+#include <asm/kexec.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+
+
+/*
+ * arm64_relocate_new_kernel - Put a 2nd stage image in place and boot it.
+ *
+ * The memory that the old kernel occupies may be overwritten when coping the
+ * new image to its final location.  To assure that the
+ * arm64_relocate_new_kernel routine which does that copy is not overwritten,
+ * all code and data needed by arm64_relocate_new_kernel must be between the
+ * symbols arm64_relocate_new_kernel and arm64_relocate_new_kernel_end.  The
+ * machine_kexec() routine will copy arm64_relocate_new_kernel to the kexec
+ * control_code_page, a special page which has been set up to be preserved
+ * during the copy operation.
+ */
+.globl arm64_relocate_new_kernel
+arm64_relocate_new_kernel:
+
+	/* Setup the list loop variables. */
+	ldr	x18, .Lkimage_head		/* x18 = list entry */
+	dcache_line_size x17, x0		/* x17 = dcache line size */
+	mov	x16, xzr			/* x16 = segment start */
+	mov	x15, xzr			/* x15 = entry ptr */
+	mov	x14, xzr			/* x14 = copy dest */
+
+	/* Check if the new image needs relocation. */
+	cbz	x18, .Ldone
+	tbnz	x18, IND_DONE_BIT, .Ldone
+
+.Lloop:
+	and	x13, x18, PAGE_MASK		/* x13 = addr */
+
+	/* Test the entry flags. */
+.Ltest_source:
+	tbz	x18, IND_SOURCE_BIT, .Ltest_indirection
+
+	mov x20, x14				/*  x20 = copy dest */
+	mov x21, x13				/*  x21 = copy src */
+
+	/* Invalidate dest page to PoC. */
+	mov	x0, x20
+	add	x19, x0, #PAGE_SIZE
+	sub	x1, x17, #1
+	bic	x0, x0, x1
+1:	dc	ivac, x0
+	add	x0, x0, x17
+	cmp	x0, x19
+	b.lo	1b
+	dsb	sy
+
+	/* Copy page. */
+1:	ldp	x22, x23, [x21]
+	ldp	x24, x25, [x21, #16]
+	ldp	x26, x27, [x21, #32]
+	ldp	x28, x29, [x21, #48]
+	add	x21, x21, #64
+	stnp	x22, x23, [x20]
+	stnp	x24, x25, [x20, #16]
+	stnp	x26, x27, [x20, #32]
+	stnp	x28, x29, [x20, #48]
+	add	x20, x20, #64
+	tst	x21, #(PAGE_SIZE - 1)
+	b.ne	1b
+
+	/* dest += PAGE_SIZE */
+	add	x14, x14, PAGE_SIZE
+	b	.Lnext
+
+.Ltest_indirection:
+	tbz	x18, IND_INDIRECTION_BIT, .Ltest_destination
+
+	/* ptr = addr */
+	mov	x15, x13
+	b	.Lnext
+
+.Ltest_destination:
+	tbz	x18, IND_DESTINATION_BIT, .Lnext
+
+	mov	x16, x13
+
+	/* dest = addr */
+	mov	x14, x13
+
+.Lnext:
+	/* entry = *ptr++ */
+	ldr	x18, [x15], #8
+
+	/* while (!(entry & DONE)) */
+	tbz	x18, IND_DONE_BIT, .Lloop
+
+.Ldone:
+	dsb	sy
+	isb
+	ic	ialluis
+	dsb	sy
+	isb
+
+	/* Start new image. */
+	ldr	x4, .Lkimage_start
+	mov	x0, xzr
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	br	x4
+
+.align 3	/* To keep the 64-bit values below naturally aligned. */
+
+/* The machine_kexec routine sets these variables via offsets from
+ * arm64_relocate_new_kernel.
+ */
+
+/*
+ * .Lkimage_start - Copy of image->start, the entry point of the new
+ * image.
+ */
+.Lkimage_start:
+	.quad	0x0
+
+/*
+ * .Lkimage_head - Copy of image->head, the list of kimage entries.
+ */
+.Lkimage_head:
+	.quad	0x0
+
+.Lcopy_end:
+.org	KEXEC_CONTROL_PAGE_SIZE
+
+/*
+ * arm64_relocate_new_kernel_size - Number of bytes to copy to the control_code_page.
+ */
+.globl arm64_relocate_new_kernel_size
+arm64_relocate_new_kernel_size:
+	.quad	.Lcopy_end - arm64_relocate_new_kernel
+
+/*
+ * arm64_kexec_kimage_start_offset - Offset for writing .Lkimage_start.
+ */
+.globl arm64_kexec_kimage_start_offset
+arm64_kexec_kimage_start_offset:
+	.quad	.Lkimage_start - arm64_relocate_new_kernel
+
+/*
+ * arm64_kexec_kimage_head_offset - Offset for writing .Lkimage_head.
+ */
+.globl arm64_kexec_kimage_head_offset
+arm64_kexec_kimage_head_offset:
+	.quad	.Lkimage_head - arm64_relocate_new_kernel
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h
index 99048e5..ccec467 100644
--- a/include/uapi/linux/kexec.h
+++ b/include/uapi/linux/kexec.h
@@ -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
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v10.2 08/16] arm64/kexec: Add core kexec support
@ 2015-10-21 18:30     ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-10-21 18:30 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Mark Rutland, AKASHI, marc.zyngier, kexec, Takahiro,
	linux-arm-kernel, christoffer.dall

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.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
V10.2: Minor comment fixups.

 arch/arm64/Kconfig                  |  10 +++
 arch/arm64/include/asm/kexec.h      |  48 +++++++++++
 arch/arm64/kernel/Makefile          |   2 +
 arch/arm64/kernel/machine_kexec.c   | 140 +++++++++++++++++++++++++++++++
 arch/arm64/kernel/relocate_kernel.S | 163 ++++++++++++++++++++++++++++++++++++
 include/uapi/linux/kexec.h          |   1 +
 6 files changed, 364 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

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 07d1811..73e8e31 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -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 (!SMP || 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
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
new file mode 100644
index 0000000..46d63cd
--- /dev/null
+++ b/arch/arm64/include/asm/kexec.h
@@ -0,0 +1,48 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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_KEXEC_H)
+#define _ARM64_KEXEC_H
+
+/* Maximum physical address we can use pages from */
+
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can reach in physical address mode */
+
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can use for the control code buffer */
+
+#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
+
+#define KEXEC_CONTROL_PAGE_SIZE	4096
+
+#define KEXEC_ARCH KEXEC_ARCH_ARM64
+
+#if !defined(__ASSEMBLY__)
+
+/**
+ * crash_setup_regs() - save registers for the panic kernel
+ *
+ * @newregs: registers are saved here
+ * @oldregs: registers to be saved (may be %NULL)
+ */
+
+static inline void crash_setup_regs(struct pt_regs *newregs,
+				    struct pt_regs *oldregs)
+{
+	/* Empty routine needed to avoid build errors. */
+}
+
+#endif /* !defined(__ASSEMBLY__) */
+
+#endif
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 22dc9bc..989ccd7 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -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)
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
new file mode 100644
index 0000000..7e3436d
--- /dev/null
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -0,0 +1,140 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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/kexec.h>
+#include <linux/of_fdt.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <asm/cacheflush.h>
+#include <asm/system_misc.h>
+
+#include "cpu-reset.h"
+
+/* Global variables for the arm64_relocate_new_kernel routine. */
+extern const unsigned char arm64_relocate_new_kernel[];
+extern const unsigned long arm64_relocate_new_kernel_size;
+extern unsigned long arm64_kexec_kimage_head_offset;
+extern unsigned long arm64_kexec_kimage_start_offset;
+
+static unsigned long kimage_head;
+static unsigned long kimage_start;
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+	/* Empty routine needed to avoid build errors. */
+}
+
+/**
+ * machine_kexec_prepare - Prepare for a kexec reboot.
+ *
+ * Called from the core kexec code when a kernel image is loaded.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+	kimage_start = image->start;
+	return 0;
+}
+
+/**
+ * kexec_list_flush - Helper to flush the kimage list to PoC.
+ */
+static void kexec_list_flush(unsigned long kimage_head)
+{
+	unsigned long *entry;
+
+	for (entry = &kimage_head; ; entry++) {
+		unsigned int flag = *entry & IND_FLAGS;
+		void *addr = phys_to_virt(*entry & PAGE_MASK);
+
+		switch (flag) {
+		case IND_INDIRECTION:
+			entry = (unsigned long *)addr - 1;
+			__flush_dcache_area(addr, PAGE_SIZE);
+			break;
+		case IND_DESTINATION:
+			break;
+		case IND_SOURCE:
+			__flush_dcache_area(addr, PAGE_SIZE);
+			break;
+		case IND_DONE:
+			return;
+		default:
+			BUG();
+		}
+	}
+}
+
+static void soft_restart(unsigned long addr)
+{
+	setup_mm_for_reboot();
+	cpu_soft_restart(virt_to_phys(cpu_reset), addr,
+		is_hyp_mode_available());
+
+	BUG(); /* Should never get here. */
+}
+
+/**
+ * machine_kexec - Do the kexec reboot.
+ *
+ * Called from the core kexec code for a sys_reboot with LINUX_REBOOT_CMD_KEXEC.
+ */
+void machine_kexec(struct kimage *image)
+{
+	phys_addr_t reboot_code_buffer_phys;
+	void *reboot_code_buffer;
+
+	BUG_ON(num_online_cpus() > 1);
+
+	kimage_head = image->head;
+
+	reboot_code_buffer_phys = page_to_phys(image->control_code_page);
+	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
+
+	/*
+	 * Copy arm64_relocate_new_kernel to the reboot_code_buffer for use
+	 * after the kernel is shut down.
+	 */
+	memcpy(reboot_code_buffer, arm64_relocate_new_kernel,
+		arm64_relocate_new_kernel_size);
+
+	/* Set the variables in reboot_code_buffer. */
+	memcpy(reboot_code_buffer + arm64_kexec_kimage_start_offset,
+	       &kimage_start, sizeof(kimage_start));
+	memcpy(reboot_code_buffer + arm64_kexec_kimage_head_offset,
+	       &kimage_head, sizeof(kimage_head));
+
+	/* Flush the reboot_code_buffer in preparation for its execution. */
+	__flush_dcache_area(reboot_code_buffer, arm64_relocate_new_kernel_size);
+
+	/* Flush the kimage list. */
+	kexec_list_flush(image->head);
+
+	pr_info("Bye!\n");
+
+	/* Disable all DAIF exceptions. */
+	asm volatile ("msr daifset, #0xf" : : : "memory");
+
+	/*
+	 * soft_restart() will shutdown the MMU, disable data caches, then
+	 * transfer control to the reboot_code_buffer which contains a copy of
+	 * the arm64_relocate_new_kernel routine.  arm64_relocate_new_kernel
+	 * uses physical addressing to relocate the new image to its final
+	 * position and transfers control to the image entry point when the
+	 * relocation is complete.
+	 */
+	soft_restart(reboot_code_buffer_phys);
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+	/* Empty routine needed to avoid build errors. */
+}
diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S
new file mode 100644
index 0000000..2d709c6
--- /dev/null
+++ b/arch/arm64/kernel/relocate_kernel.S
@@ -0,0 +1,163 @@
+/*
+ * kexec for arm64
+ *
+ * Copyright (C) Linaro.
+ * Copyright (C) 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/kexec.h>
+
+#include <asm/assembler.h>
+#include <asm/kexec.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+
+
+/*
+ * arm64_relocate_new_kernel - Put a 2nd stage image in place and boot it.
+ *
+ * The memory that the old kernel occupies may be overwritten when coping the
+ * new image to its final location.  To assure that the
+ * arm64_relocate_new_kernel routine which does that copy is not overwritten,
+ * all code and data needed by arm64_relocate_new_kernel must be between the
+ * symbols arm64_relocate_new_kernel and arm64_relocate_new_kernel_end.  The
+ * machine_kexec() routine will copy arm64_relocate_new_kernel to the kexec
+ * control_code_page, a special page which has been set up to be preserved
+ * during the copy operation.
+ */
+.globl arm64_relocate_new_kernel
+arm64_relocate_new_kernel:
+
+	/* Setup the list loop variables. */
+	ldr	x18, .Lkimage_head		/* x18 = list entry */
+	dcache_line_size x17, x0		/* x17 = dcache line size */
+	mov	x16, xzr			/* x16 = segment start */
+	mov	x15, xzr			/* x15 = entry ptr */
+	mov	x14, xzr			/* x14 = copy dest */
+
+	/* Check if the new image needs relocation. */
+	cbz	x18, .Ldone
+	tbnz	x18, IND_DONE_BIT, .Ldone
+
+.Lloop:
+	and	x13, x18, PAGE_MASK		/* x13 = addr */
+
+	/* Test the entry flags. */
+.Ltest_source:
+	tbz	x18, IND_SOURCE_BIT, .Ltest_indirection
+
+	mov x20, x14				/*  x20 = copy dest */
+	mov x21, x13				/*  x21 = copy src */
+
+	/* Invalidate dest page to PoC. */
+	mov	x0, x20
+	add	x19, x0, #PAGE_SIZE
+	sub	x1, x17, #1
+	bic	x0, x0, x1
+1:	dc	ivac, x0
+	add	x0, x0, x17
+	cmp	x0, x19
+	b.lo	1b
+	dsb	sy
+
+	/* Copy page. */
+1:	ldp	x22, x23, [x21]
+	ldp	x24, x25, [x21, #16]
+	ldp	x26, x27, [x21, #32]
+	ldp	x28, x29, [x21, #48]
+	add	x21, x21, #64
+	stnp	x22, x23, [x20]
+	stnp	x24, x25, [x20, #16]
+	stnp	x26, x27, [x20, #32]
+	stnp	x28, x29, [x20, #48]
+	add	x20, x20, #64
+	tst	x21, #(PAGE_SIZE - 1)
+	b.ne	1b
+
+	/* dest += PAGE_SIZE */
+	add	x14, x14, PAGE_SIZE
+	b	.Lnext
+
+.Ltest_indirection:
+	tbz	x18, IND_INDIRECTION_BIT, .Ltest_destination
+
+	/* ptr = addr */
+	mov	x15, x13
+	b	.Lnext
+
+.Ltest_destination:
+	tbz	x18, IND_DESTINATION_BIT, .Lnext
+
+	mov	x16, x13
+
+	/* dest = addr */
+	mov	x14, x13
+
+.Lnext:
+	/* entry = *ptr++ */
+	ldr	x18, [x15], #8
+
+	/* while (!(entry & DONE)) */
+	tbz	x18, IND_DONE_BIT, .Lloop
+
+.Ldone:
+	dsb	sy
+	isb
+	ic	ialluis
+	dsb	sy
+	isb
+
+	/* Start new image. */
+	ldr	x4, .Lkimage_start
+	mov	x0, xzr
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	br	x4
+
+.align 3	/* To keep the 64-bit values below naturally aligned. */
+
+/* The machine_kexec routine sets these variables via offsets from
+ * arm64_relocate_new_kernel.
+ */
+
+/*
+ * .Lkimage_start - Copy of image->start, the entry point of the new
+ * image.
+ */
+.Lkimage_start:
+	.quad	0x0
+
+/*
+ * .Lkimage_head - Copy of image->head, the list of kimage entries.
+ */
+.Lkimage_head:
+	.quad	0x0
+
+.Lcopy_end:
+.org	KEXEC_CONTROL_PAGE_SIZE
+
+/*
+ * arm64_relocate_new_kernel_size - Number of bytes to copy to the control_code_page.
+ */
+.globl arm64_relocate_new_kernel_size
+arm64_relocate_new_kernel_size:
+	.quad	.Lcopy_end - arm64_relocate_new_kernel
+
+/*
+ * arm64_kexec_kimage_start_offset - Offset for writing .Lkimage_start.
+ */
+.globl arm64_kexec_kimage_start_offset
+arm64_kexec_kimage_start_offset:
+	.quad	.Lkimage_start - arm64_relocate_new_kernel
+
+/*
+ * arm64_kexec_kimage_head_offset - Offset for writing .Lkimage_head.
+ */
+.globl arm64_kexec_kimage_head_offset
+arm64_kexec_kimage_head_offset:
+	.quad	.Lkimage_head - arm64_relocate_new_kernel
diff --git a/include/uapi/linux/kexec.h b/include/uapi/linux/kexec.h
index 99048e5..ccec467 100644
--- a/include/uapi/linux/kexec.h
+++ b/include/uapi/linux/kexec.h
@@ -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
-- 
2.5.0


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH 13/16] arm64: kdump: add kdump support
  2015-10-19 23:38   ` Geoff Levand
@ 2015-10-22  3:25     ` Dave Young
  -1 siblings, 0 replies; 72+ messages in thread
From: Dave Young @ 2015-10-22  3:25 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, AKASHI,

On 10/19/15 at 11:38pm, Geoff Levand wrote:
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> 
> 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.

How does kexec-tools pass usable memory ranges to kernel? using dtb?
Passing an extra mem=X sounds odd in the design. Kdump kernel should get
usable ranges and hanle the limit better than depending on an extern kernel
param. 

Thanks
Dave

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 13/16] arm64: kdump: add kdump support
@ 2015-10-22  3:25     ` Dave Young
  0 siblings, 0 replies; 72+ messages in thread
From: Dave Young @ 2015-10-22  3:25 UTC (permalink / raw)
  To: Geoff Levand
  Cc: Mark Rutland, AKASHI, marc.zyngier, Catalin Marinas, Will Deacon,
	Takahiro, christoffer.dall, kexec, linux-arm-kernel

Hi, AKASHI,

On 10/19/15 at 11:38pm, Geoff Levand wrote:
> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> 
> 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.

How does kexec-tools pass usable memory ranges to kernel? using dtb?
Passing an extra mem=X sounds odd in the design. Kdump kernel should get
usable ranges and hanle the limit better than depending on an extern kernel
param. 

Thanks
Dave

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 13/16] arm64: kdump: add kdump support
  2015-10-22  3:25     ` Dave Young
@ 2015-10-22  4:29       ` AKASHI Takahiro
  -1 siblings, 0 replies; 72+ messages in thread
From: AKASHI Takahiro @ 2015-10-22  4:29 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Dave,

Thank you for your comment.

On 10/22/2015 12:25 PM, Dave Young wrote:
> Hi, AKASHI,
>
> On 10/19/15 at 11:38pm, Geoff Levand wrote:
>> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
>>
>> 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.
>
> How does kexec-tools pass usable memory ranges to kernel? using dtb?
> Passing an extra mem=X sounds odd in the design. Kdump kernel should get
> usable ranges and hanle the limit better than depending on an extern kernel
> param.

Well, regarding "depending on an external kernel param,"
- this limitation ("mem=") is compatible with arm(32) implementation although
   it is not clearly described in kernel's Documentation/kdump/kdump.txt.
- "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
   The parameter is explicitly generated and added by kexec-tools.

Do I miss your point?

Thanks,
-Takahiro AKASHI

> Thanks
> Dave
>

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 13/16] arm64: kdump: add kdump support
@ 2015-10-22  4:29       ` AKASHI Takahiro
  0 siblings, 0 replies; 72+ messages in thread
From: AKASHI Takahiro @ 2015-10-22  4:29 UTC (permalink / raw)
  To: Dave Young, Geoff Levand
  Cc: Mark Rutland, AKASHI, marc.zyngier, Catalin Marinas, Will Deacon,
	christoffer.dall, kexec, linux-arm-kernel

Hi Dave,

Thank you for your comment.

On 10/22/2015 12:25 PM, Dave Young wrote:
> Hi, AKASHI,
>
> On 10/19/15 at 11:38pm, Geoff Levand wrote:
>> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
>>
>> 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.
>
> How does kexec-tools pass usable memory ranges to kernel? using dtb?
> Passing an extra mem=X sounds odd in the design. Kdump kernel should get
> usable ranges and hanle the limit better than depending on an extern kernel
> param.

Well, regarding "depending on an external kernel param,"
- this limitation ("mem=") is compatible with arm(32) implementation although
   it is not clearly described in kernel's Documentation/kdump/kdump.txt.
- "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
   The parameter is explicitly generated and added by kexec-tools.

Do I miss your point?

Thanks,
-Takahiro AKASHI

> Thanks
> Dave
>

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 13/16] arm64: kdump: add kdump support
  2015-10-22  4:29       ` AKASHI Takahiro
@ 2015-10-22  5:15         ` Dave Young
  -1 siblings, 0 replies; 72+ messages in thread
From: Dave Young @ 2015-10-22  5:15 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
> Hi Dave,
> 
> Thank you for your comment.
> 
> On 10/22/2015 12:25 PM, Dave Young wrote:
> >Hi, AKASHI,
> >
> >On 10/19/15 at 11:38pm, Geoff Levand wrote:
> >>From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> >>
> >>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.
> >
> >How does kexec-tools pass usable memory ranges to kernel? using dtb?
> >Passing an extra mem=X sounds odd in the design. Kdump kernel should get
> >usable ranges and hanle the limit better than depending on an extern kernel
> >param.
> 
> Well, regarding "depending on an external kernel param,"
> - this limitation ("mem=") is compatible with arm(32) implementation although
>   it is not clearly described in kernel's Documentation/kdump/kdump.txt.
> - "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
>   The parameter is explicitly generated and added by kexec-tools.
> 
> Do I miss your point?

Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
says: The boot loader must pass at a minimum the size and location of the
system memory

In arm64 booting.txt, it does mentions about dtb but without above sentence.

So if you are using dtb to pass memory I think the extra mem= should be not
necessary unless there's other limitations dtb can not been used.

One thing I'm confused is mem= only pass the memory size, where does you pass
the start addresses? What if there's multiple sections such as some reserved
ranges 2nd kernel also need?

Thanks
Dave

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 13/16] arm64: kdump: add kdump support
@ 2015-10-22  5:15         ` Dave Young
  0 siblings, 0 replies; 72+ messages in thread
From: Dave Young @ 2015-10-22  5:15 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Mark Rutland, AKASHI, Geoff Levand, Catalin Marinas, Will Deacon,
	marc.zyngier, linux-arm-kernel, kexec, christoffer.dall

On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
> Hi Dave,
> 
> Thank you for your comment.
> 
> On 10/22/2015 12:25 PM, Dave Young wrote:
> >Hi, AKASHI,
> >
> >On 10/19/15 at 11:38pm, Geoff Levand wrote:
> >>From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> >>
> >>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.
> >
> >How does kexec-tools pass usable memory ranges to kernel? using dtb?
> >Passing an extra mem=X sounds odd in the design. Kdump kernel should get
> >usable ranges and hanle the limit better than depending on an extern kernel
> >param.
> 
> Well, regarding "depending on an external kernel param,"
> - this limitation ("mem=") is compatible with arm(32) implementation although
>   it is not clearly described in kernel's Documentation/kdump/kdump.txt.
> - "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
>   The parameter is explicitly generated and added by kexec-tools.
> 
> Do I miss your point?

Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
says: The boot loader must pass at a minimum the size and location of the
system memory

In arm64 booting.txt, it does mentions about dtb but without above sentence.

So if you are using dtb to pass memory I think the extra mem= should be not
necessary unless there's other limitations dtb can not been used.

One thing I'm confused is mem= only pass the memory size, where does you pass
the start addresses? What if there's multiple sections such as some reserved
ranges 2nd kernel also need?

Thanks
Dave

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 13/16] arm64: kdump: add kdump support
  2015-10-22  5:15         ` Dave Young
@ 2015-10-22  9:57           ` AKASHI Takahiro
  -1 siblings, 0 replies; 72+ messages in thread
From: AKASHI Takahiro @ 2015-10-22  9:57 UTC (permalink / raw)
  To: linux-arm-kernel

(added Ard to Cc.)

On 10/22/2015 02:15 PM, Dave Young wrote:
> On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
>> Hi Dave,
>>
>> Thank you for your comment.
>>
>> On 10/22/2015 12:25 PM, Dave Young wrote:
>>> Hi, AKASHI,
>>>
>>> On 10/19/15 at 11:38pm, Geoff Levand wrote:
>>>> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
>>>>
>>>> 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.
>>>
>>> How does kexec-tools pass usable memory ranges to kernel? using dtb?
>>> Passing an extra mem=X sounds odd in the design. Kdump kernel should get
>>> usable ranges and hanle the limit better than depending on an extern kernel
>>> param.
>>
>> Well, regarding "depending on an external kernel param,"
>> - this limitation ("mem=") is compatible with arm(32) implementation although
>>    it is not clearly described in kernel's Documentation/kdump/kdump.txt.
>> - "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
>>    The parameter is explicitly generated and added by kexec-tools.
>>
>> Do I miss your point?
>
> Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
> says: The boot loader must pass at a minimum the size and location of the
> system memory
>
> In arm64 booting.txt, it does mentions about dtb but without above sentence.
>
> So if you are using dtb to pass memory I think the extra mem= should be not
> necessary unless there's other limitations dtb can not been used.

I would expect comments from arm64 maintainers here.

In my old implementation, I added "usablemem" attributes, along with "reg," to
"memory" nodes in dtb to specify the usable memory region on crash dump kernel.

But I removed this feature partly because, on uefi system, uefi might pass
no memory information in dtb.

> One thing I'm confused is mem= only pass the memory size, where does you pass
> the start addresses?

In the current arm64 implementation, any regions below the start address will
be ignored as system ram.

> What if there's multiple sections such as some reserved
> ranges 2nd kernel also need?

My patch utilizes only a single contiguous region of memory as system ram.
One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.

Please let me know if there is any other case that should be supported.

Thanks,
-Takahiro AKASHI

> Thanks
> Dave
>

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 13/16] arm64: kdump: add kdump support
@ 2015-10-22  9:57           ` AKASHI Takahiro
  0 siblings, 0 replies; 72+ messages in thread
From: AKASHI Takahiro @ 2015-10-22  9:57 UTC (permalink / raw)
  To: Dave Young
  Cc: Mark Rutland, AKASHI, ard.biesheuvel, Geoff Levand,
	Catalin Marinas, Will Deacon, marc.zyngier, linux-arm-kernel,
	kexec, christoffer.dall

(added Ard to Cc.)

On 10/22/2015 02:15 PM, Dave Young wrote:
> On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
>> Hi Dave,
>>
>> Thank you for your comment.
>>
>> On 10/22/2015 12:25 PM, Dave Young wrote:
>>> Hi, AKASHI,
>>>
>>> On 10/19/15 at 11:38pm, Geoff Levand wrote:
>>>> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
>>>>
>>>> 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.
>>>
>>> How does kexec-tools pass usable memory ranges to kernel? using dtb?
>>> Passing an extra mem=X sounds odd in the design. Kdump kernel should get
>>> usable ranges and hanle the limit better than depending on an extern kernel
>>> param.
>>
>> Well, regarding "depending on an external kernel param,"
>> - this limitation ("mem=") is compatible with arm(32) implementation although
>>    it is not clearly described in kernel's Documentation/kdump/kdump.txt.
>> - "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
>>    The parameter is explicitly generated and added by kexec-tools.
>>
>> Do I miss your point?
>
> Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
> says: The boot loader must pass at a minimum the size and location of the
> system memory
>
> In arm64 booting.txt, it does mentions about dtb but without above sentence.
>
> So if you are using dtb to pass memory I think the extra mem= should be not
> necessary unless there's other limitations dtb can not been used.

I would expect comments from arm64 maintainers here.

In my old implementation, I added "usablemem" attributes, along with "reg," to
"memory" nodes in dtb to specify the usable memory region on crash dump kernel.

But I removed this feature partly because, on uefi system, uefi might pass
no memory information in dtb.

> One thing I'm confused is mem= only pass the memory size, where does you pass
> the start addresses?

In the current arm64 implementation, any regions below the start address will
be ignored as system ram.

> What if there's multiple sections such as some reserved
> ranges 2nd kernel also need?

My patch utilizes only a single contiguous region of memory as system ram.
One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.

Please let me know if there is any other case that should be supported.

Thanks,
-Takahiro AKASHI

> Thanks
> Dave
>

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 08/16] arm64/kexec: Add core kexec support
  2015-10-20 17:19       ` Geoff Levand
@ 2015-10-23  7:29         ` Pratyush Anand
  -1 siblings, 0 replies; 72+ messages in thread
From: Pratyush Anand @ 2015-10-23  7:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 20/10/2015:10:19:25 AM, Geoff Levand wrote:
> Hi,
> 
> On Tue, 2015-10-20 at 14:26 +0530, Pratyush Anand wrote:
> > On 19/10/2015:11:38:53 PM, Geoff Levand wrote:
> > > +static void soft_restart(unsigned long addr)
> > > +{
> > > +> > 	> > setup_mm_for_reboot();
> > > +> > 	> > cpu_soft_restart(virt_to_phys(cpu_reset), addr,
> > > +> > 	> > 	> > is_hyp_mode_available());
> > 
> > So now we do not flush cache for any memory region. Shouldn't we still flush
> > at least kernel and purgatory segments. 
> 
> Relevant pages of the kexec list are flushed in the code following the comment
> 'Invalidate dest page to PoC' of the arm64_relocate_new_kernel routine:
> 
>  The dcache is turned off
>  The page is invalidated to PoC
>  The new page is written

Thanks for clarifying it.

I tested your kexec-v10.2 with mustang.

Tested-by: Pratyush Anand <panand@redhat.com>

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 08/16] arm64/kexec: Add core kexec support
@ 2015-10-23  7:29         ` Pratyush Anand
  0 siblings, 0 replies; 72+ messages in thread
From: Pratyush Anand @ 2015-10-23  7:29 UTC (permalink / raw)
  To: Geoff Levand
  Cc: Mark Rutland, AKASHI, marc.zyngier, Catalin Marinas, Will Deacon,
	Takahiro, linux-arm-kernel, kexec, christoffer.dall

On 20/10/2015:10:19:25 AM, Geoff Levand wrote:
> Hi,
> 
> On Tue, 2015-10-20 at 14:26 +0530, Pratyush Anand wrote:
> > On 19/10/2015:11:38:53 PM, Geoff Levand wrote:
> > > +static void soft_restart(unsigned long addr)
> > > +{
> > > +> > 	> > setup_mm_for_reboot();
> > > +> > 	> > cpu_soft_restart(virt_to_phys(cpu_reset), addr,
> > > +> > 	> > 	> > is_hyp_mode_available());
> > 
> > So now we do not flush cache for any memory region. Shouldn't we still flush
> > at least kernel and purgatory segments. 
> 
> Relevant pages of the kexec list are flushed in the code following the comment
> 'Invalidate dest page to PoC' of the arm64_relocate_new_kernel routine:
> 
>  The dcache is turned off
>  The page is invalidated to PoC
>  The new page is written

Thanks for clarifying it.

I tested your kexec-v10.2 with mustang.

Tested-by: Pratyush Anand <panand@redhat.com>

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 13/16] arm64: kdump: add kdump support
  2015-10-22  9:57           ` AKASHI Takahiro
@ 2015-10-23  9:50             ` Dave Young
  -1 siblings, 0 replies; 72+ messages in thread
From: Dave Young @ 2015-10-23  9:50 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/22/15 at 06:57pm, AKASHI Takahiro wrote:
> (added Ard to Cc.)
> 
> On 10/22/2015 02:15 PM, Dave Young wrote:
> >On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
> >>Hi Dave,
> >>
> >>Thank you for your comment.
> >>
> >>On 10/22/2015 12:25 PM, Dave Young wrote:
> >>>Hi, AKASHI,
> >>>
> >>>On 10/19/15 at 11:38pm, Geoff Levand wrote:
> >>>>From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> >>>>
> >>>>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.
> >>>
> >>>How does kexec-tools pass usable memory ranges to kernel? using dtb?
> >>>Passing an extra mem=X sounds odd in the design. Kdump kernel should get
> >>>usable ranges and hanle the limit better than depending on an extern kernel
> >>>param.
> >>
> >>Well, regarding "depending on an external kernel param,"
> >>- this limitation ("mem=") is compatible with arm(32) implementation although
> >>   it is not clearly described in kernel's Documentation/kdump/kdump.txt.
> >>- "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
> >>   The parameter is explicitly generated and added by kexec-tools.
> >>
> >>Do I miss your point?
> >
> >Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
> >says: The boot loader must pass at a minimum the size and location of the
> >system memory
> >
> >In arm64 booting.txt, it does mentions about dtb but without above sentence.
> >
> >So if you are using dtb to pass memory I think the extra mem= should be not
> >necessary unless there's other limitations dtb can not been used.
> 
> I would expect comments from arm64 maintainers here.
> 
> In my old implementation, I added "usablemem" attributes, along with "reg," to
> "memory" nodes in dtb to specify the usable memory region on crash dump kernel.
> 
> But I removed this feature partly because, on uefi system, uefi might pass
> no memory information in dtb.

If this is the case there must be somewhere else one can pass memory infomation
to kernel, the booting.txt should be updated?

kexec as a boot loader need use same method as the 1st kernel boot loader.

> 
> >One thing I'm confused is mem= only pass the memory size, where does you pass
> >the start addresses?
> 
> In the current arm64 implementation, any regions below the start address will
> be ignored as system ram.
> 
> >What if there's multiple sections such as some reserved
> >ranges 2nd kernel also need?
> 
> My patch utilizes only a single contiguous region of memory as system ram.
> One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.
> 
> Please let me know if there is any other case that should be supported.

For example the elf headers range, you reserved them in kdump kernel code,
but kexec-tools can do that early if it can provides all memory info to 2nd
kernel. Ditto for mark all the memory ranges 1st kernel used as reserved.

Thanks
Dave

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 13/16] arm64: kdump: add kdump support
@ 2015-10-23  9:50             ` Dave Young
  0 siblings, 0 replies; 72+ messages in thread
From: Dave Young @ 2015-10-23  9:50 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Mark Rutland, AKASHI, ard.biesheuvel, Geoff Levand,
	Catalin Marinas, Will Deacon, marc.zyngier, linux-arm-kernel,
	kexec, christoffer.dall

On 10/22/15 at 06:57pm, AKASHI Takahiro wrote:
> (added Ard to Cc.)
> 
> On 10/22/2015 02:15 PM, Dave Young wrote:
> >On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
> >>Hi Dave,
> >>
> >>Thank you for your comment.
> >>
> >>On 10/22/2015 12:25 PM, Dave Young wrote:
> >>>Hi, AKASHI,
> >>>
> >>>On 10/19/15 at 11:38pm, Geoff Levand wrote:
> >>>>From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> >>>>
> >>>>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.
> >>>
> >>>How does kexec-tools pass usable memory ranges to kernel? using dtb?
> >>>Passing an extra mem=X sounds odd in the design. Kdump kernel should get
> >>>usable ranges and hanle the limit better than depending on an extern kernel
> >>>param.
> >>
> >>Well, regarding "depending on an external kernel param,"
> >>- this limitation ("mem=") is compatible with arm(32) implementation although
> >>   it is not clearly described in kernel's Documentation/kdump/kdump.txt.
> >>- "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
> >>   The parameter is explicitly generated and added by kexec-tools.
> >>
> >>Do I miss your point?
> >
> >Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
> >says: The boot loader must pass at a minimum the size and location of the
> >system memory
> >
> >In arm64 booting.txt, it does mentions about dtb but without above sentence.
> >
> >So if you are using dtb to pass memory I think the extra mem= should be not
> >necessary unless there's other limitations dtb can not been used.
> 
> I would expect comments from arm64 maintainers here.
> 
> In my old implementation, I added "usablemem" attributes, along with "reg," to
> "memory" nodes in dtb to specify the usable memory region on crash dump kernel.
> 
> But I removed this feature partly because, on uefi system, uefi might pass
> no memory information in dtb.

If this is the case there must be somewhere else one can pass memory infomation
to kernel, the booting.txt should be updated?

kexec as a boot loader need use same method as the 1st kernel boot loader.

> 
> >One thing I'm confused is mem= only pass the memory size, where does you pass
> >the start addresses?
> 
> In the current arm64 implementation, any regions below the start address will
> be ignored as system ram.
> 
> >What if there's multiple sections such as some reserved
> >ranges 2nd kernel also need?
> 
> My patch utilizes only a single contiguous region of memory as system ram.
> One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.
> 
> Please let me know if there is any other case that should be supported.

For example the elf headers range, you reserved them in kdump kernel code,
but kexec-tools can do that early if it can provides all memory info to 2nd
kernel. Ditto for mark all the memory ranges 1st kernel used as reserved.

Thanks
Dave

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 13/16] arm64: kdump: add kdump support
  2015-10-23  9:50             ` Dave Young
@ 2015-10-29  5:55               ` AKASHI Takahiro
  -1 siblings, 0 replies; 72+ messages in thread
From: AKASHI Takahiro @ 2015-10-29  5:55 UTC (permalink / raw)
  To: linux-arm-kernel

Dave,

On 10/23/2015 06:50 PM, Dave Young wrote:
> On 10/22/15 at 06:57pm, AKASHI Takahiro wrote:
>> (added Ard to Cc.)
>>
>> On 10/22/2015 02:15 PM, Dave Young wrote:
>>> On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
>>>> Hi Dave,
>>>>
>>>> Thank you for your comment.
>>>>
>>>> On 10/22/2015 12:25 PM, Dave Young wrote:
>>>>> Hi, AKASHI,
>>>>>
>>>>> On 10/19/15 at 11:38pm, Geoff Levand wrote:
>>>>>> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
>>>>>>
>>>>>> 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.
>>>>>
>>>>> How does kexec-tools pass usable memory ranges to kernel? using dtb?
>>>>> Passing an extra mem=X sounds odd in the design. Kdump kernel should get
>>>>> usable ranges and hanle the limit better than depending on an extern kernel
>>>>> param.
>>>>
>>>> Well, regarding "depending on an external kernel param,"
>>>> - this limitation ("mem=") is compatible with arm(32) implementation although
>>>>    it is not clearly described in kernel's Documentation/kdump/kdump.txt.
>>>> - "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
>>>>    The parameter is explicitly generated and added by kexec-tools.
>>>>
>>>> Do I miss your point?
>>>
>>> Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
>>> says: The boot loader must pass at a minimum the size and location of the
>>> system memory
>>>
>>> In arm64 booting.txt, it does mentions about dtb but without above sentence.
>>>
>>> So if you are using dtb to pass memory I think the extra mem= should be not
>>> necessary unless there's other limitations dtb can not been used.
>>
>> I would expect comments from arm64 maintainers here.
>>
>> In my old implementation, I added "usablemem" attributes, along with "reg," to
>> "memory" nodes in dtb to specify the usable memory region on crash dump kernel.
>>
>> But I removed this feature partly because, on uefi system, uefi might pass
>> no memory information in dtb.
>
> If this is the case there must be somewhere else one can pass memory infomation
> to kernel, the booting.txt should be updated?
>
> kexec as a boot loader need use same method as the 1st kernel boot loader.
>
>>
>>> One thing I'm confused is mem= only pass the memory size, where does you pass
>>> the start addresses?
>>
>> In the current arm64 implementation, any regions below the start address will
>> be ignored as system ram.
>>
>>> What if there's multiple sections such as some reserved
>>> ranges 2nd kernel also need?
>>
>> My patch utilizes only a single contiguous region of memory as system ram.
>> One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.
>>
>> Please let me know if there is any other case that should be supported.
>
> For example the elf headers range, you reserved them in kdump kernel code,
> but kexec-tools can do that early if it can provides all memory info to 2nd
> kernel. Ditto for mark all the memory ranges 1st kernel used as reserved.

It seems to me that the issue you mentioned here is totally independent
from "mem=" issue, isn't it?
(and "elfcorehdr=" is a common way for crash dump kernel to know the region.)

-Takahiro AKASHI

> Thanks
> Dave
>

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 13/16] arm64: kdump: add kdump support
@ 2015-10-29  5:55               ` AKASHI Takahiro
  0 siblings, 0 replies; 72+ messages in thread
From: AKASHI Takahiro @ 2015-10-29  5:55 UTC (permalink / raw)
  To: Dave Young
  Cc: Mark Rutland, AKASHI, ard.biesheuvel, Geoff Levand,
	Catalin Marinas, Will Deacon, marc.zyngier, linux-arm-kernel,
	kexec, christoffer.dall

Dave,

On 10/23/2015 06:50 PM, Dave Young wrote:
> On 10/22/15 at 06:57pm, AKASHI Takahiro wrote:
>> (added Ard to Cc.)
>>
>> On 10/22/2015 02:15 PM, Dave Young wrote:
>>> On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
>>>> Hi Dave,
>>>>
>>>> Thank you for your comment.
>>>>
>>>> On 10/22/2015 12:25 PM, Dave Young wrote:
>>>>> Hi, AKASHI,
>>>>>
>>>>> On 10/19/15 at 11:38pm, Geoff Levand wrote:
>>>>>> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
>>>>>>
>>>>>> 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.
>>>>>
>>>>> How does kexec-tools pass usable memory ranges to kernel? using dtb?
>>>>> Passing an extra mem=X sounds odd in the design. Kdump kernel should get
>>>>> usable ranges and hanle the limit better than depending on an extern kernel
>>>>> param.
>>>>
>>>> Well, regarding "depending on an external kernel param,"
>>>> - this limitation ("mem=") is compatible with arm(32) implementation although
>>>>    it is not clearly described in kernel's Documentation/kdump/kdump.txt.
>>>> - "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
>>>>    The parameter is explicitly generated and added by kexec-tools.
>>>>
>>>> Do I miss your point?
>>>
>>> Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
>>> says: The boot loader must pass at a minimum the size and location of the
>>> system memory
>>>
>>> In arm64 booting.txt, it does mentions about dtb but without above sentence.
>>>
>>> So if you are using dtb to pass memory I think the extra mem= should be not
>>> necessary unless there's other limitations dtb can not been used.
>>
>> I would expect comments from arm64 maintainers here.
>>
>> In my old implementation, I added "usablemem" attributes, along with "reg," to
>> "memory" nodes in dtb to specify the usable memory region on crash dump kernel.
>>
>> But I removed this feature partly because, on uefi system, uefi might pass
>> no memory information in dtb.
>
> If this is the case there must be somewhere else one can pass memory infomation
> to kernel, the booting.txt should be updated?
>
> kexec as a boot loader need use same method as the 1st kernel boot loader.
>
>>
>>> One thing I'm confused is mem= only pass the memory size, where does you pass
>>> the start addresses?
>>
>> In the current arm64 implementation, any regions below the start address will
>> be ignored as system ram.
>>
>>> What if there's multiple sections such as some reserved
>>> ranges 2nd kernel also need?
>>
>> My patch utilizes only a single contiguous region of memory as system ram.
>> One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.
>>
>> Please let me know if there is any other case that should be supported.
>
> For example the elf headers range, you reserved them in kdump kernel code,
> but kexec-tools can do that early if it can provides all memory info to 2nd
> kernel. Ditto for mark all the memory ranges 1st kernel used as reserved.

It seems to me that the issue you mentioned here is totally independent
from "mem=" issue, isn't it?
(and "elfcorehdr=" is a common way for crash dump kernel to know the region.)

-Takahiro AKASHI

> Thanks
> Dave
>

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 13/16] arm64: kdump: add kdump support
  2015-10-29  5:55               ` AKASHI Takahiro
@ 2015-10-29  6:40                 ` Dave Young
  -1 siblings, 0 replies; 72+ messages in thread
From: Dave Young @ 2015-10-29  6:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, AKASHI

On 10/29/15 at 02:55pm, AKASHI Takahiro wrote:
> Dave,
> 
> On 10/23/2015 06:50 PM, Dave Young wrote:
> >On 10/22/15 at 06:57pm, AKASHI Takahiro wrote:
> >>(added Ard to Cc.)
> >>
> >>On 10/22/2015 02:15 PM, Dave Young wrote:
> >>>On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
> >>>>Hi Dave,
> >>>>
> >>>>Thank you for your comment.
> >>>>
> >>>>On 10/22/2015 12:25 PM, Dave Young wrote:
> >>>>>Hi, AKASHI,
> >>>>>
> >>>>>On 10/19/15 at 11:38pm, Geoff Levand wrote:
> >>>>>>From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> >>>>>>
> >>>>>>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.
> >>>>>
> >>>>>How does kexec-tools pass usable memory ranges to kernel? using dtb?
> >>>>>Passing an extra mem=X sounds odd in the design. Kdump kernel should get
> >>>>>usable ranges and hanle the limit better than depending on an extern kernel
> >>>>>param.
> >>>>
> >>>>Well, regarding "depending on an external kernel param,"
> >>>>- this limitation ("mem=") is compatible with arm(32) implementation although
> >>>>   it is not clearly described in kernel's Documentation/kdump/kdump.txt.
> >>>>- "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
> >>>>   The parameter is explicitly generated and added by kexec-tools.
> >>>>
> >>>>Do I miss your point?
> >>>
> >>>Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
> >>>says: The boot loader must pass at a minimum the size and location of the
> >>>system memory
> >>>
> >>>In arm64 booting.txt, it does mentions about dtb but without above sentence.
> >>>
> >>>So if you are using dtb to pass memory I think the extra mem= should be not
> >>>necessary unless there's other limitations dtb can not been used.
> >>
> >>I would expect comments from arm64 maintainers here.
> >>
> >>In my old implementation, I added "usablemem" attributes, along with "reg," to
> >>"memory" nodes in dtb to specify the usable memory region on crash dump kernel.
> >>
> >>But I removed this feature partly because, on uefi system, uefi might pass
> >>no memory information in dtb.
> >
> >If this is the case there must be somewhere else one can pass memory infomation
> >to kernel, the booting.txt should be updated?
> >
> >kexec as a boot loader need use same method as the 1st kernel boot loader.
> >
> >>
> >>>One thing I'm confused is mem= only pass the memory size, where does you pass
> >>>the start addresses?
> >>
> >>In the current arm64 implementation, any regions below the start address will
> >>be ignored as system ram.
> >>
> >>>What if there's multiple sections such as some reserved
> >>>ranges 2nd kernel also need?
> >>
> >>My patch utilizes only a single contiguous region of memory as system ram.
> >>One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.
> >>
> >>Please let me know if there is any other case that should be supported.
> >
> >For example the elf headers range, you reserved them in kdump kernel code,
> >but kexec-tools can do that early if it can provides all memory info to 2nd
> >kernel. Ditto for mark all the memory ranges 1st kernel used as reserved.
> 
> It seems to me that the issue you mentioned here is totally independent
> from "mem=" issue, isn't it?
> (and "elfcorehdr=" is a common way for crash dump kernel to know the region.)

Hmm, I did not talked about the eflcorehdr=, I means the code to reserve the
memory ranges elfcorehdr is using.

Thanks
Dave

> 
> -Takahiro AKASHI
> 
> >Thanks
> >Dave
> >

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 13/16] arm64: kdump: add kdump support
@ 2015-10-29  6:40                 ` Dave Young
  0 siblings, 0 replies; 72+ messages in thread
From: Dave Young @ 2015-10-29  6:40 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Mark Rutland, AKASHI, ard.biesheuvel, Geoff Levand,
	Catalin Marinas, Will Deacon, marc.zyngier, linux-arm-kernel,
	kexec, christoffer.dall

Hi, AKASHI

On 10/29/15 at 02:55pm, AKASHI Takahiro wrote:
> Dave,
> 
> On 10/23/2015 06:50 PM, Dave Young wrote:
> >On 10/22/15 at 06:57pm, AKASHI Takahiro wrote:
> >>(added Ard to Cc.)
> >>
> >>On 10/22/2015 02:15 PM, Dave Young wrote:
> >>>On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
> >>>>Hi Dave,
> >>>>
> >>>>Thank you for your comment.
> >>>>
> >>>>On 10/22/2015 12:25 PM, Dave Young wrote:
> >>>>>Hi, AKASHI,
> >>>>>
> >>>>>On 10/19/15 at 11:38pm, Geoff Levand wrote:
> >>>>>>From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> >>>>>>
> >>>>>>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.
> >>>>>
> >>>>>How does kexec-tools pass usable memory ranges to kernel? using dtb?
> >>>>>Passing an extra mem=X sounds odd in the design. Kdump kernel should get
> >>>>>usable ranges and hanle the limit better than depending on an extern kernel
> >>>>>param.
> >>>>
> >>>>Well, regarding "depending on an external kernel param,"
> >>>>- this limitation ("mem=") is compatible with arm(32) implementation although
> >>>>   it is not clearly described in kernel's Documentation/kdump/kdump.txt.
> >>>>- "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
> >>>>   The parameter is explicitly generated and added by kexec-tools.
> >>>>
> >>>>Do I miss your point?
> >>>
> >>>Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
> >>>says: The boot loader must pass at a minimum the size and location of the
> >>>system memory
> >>>
> >>>In arm64 booting.txt, it does mentions about dtb but without above sentence.
> >>>
> >>>So if you are using dtb to pass memory I think the extra mem= should be not
> >>>necessary unless there's other limitations dtb can not been used.
> >>
> >>I would expect comments from arm64 maintainers here.
> >>
> >>In my old implementation, I added "usablemem" attributes, along with "reg," to
> >>"memory" nodes in dtb to specify the usable memory region on crash dump kernel.
> >>
> >>But I removed this feature partly because, on uefi system, uefi might pass
> >>no memory information in dtb.
> >
> >If this is the case there must be somewhere else one can pass memory infomation
> >to kernel, the booting.txt should be updated?
> >
> >kexec as a boot loader need use same method as the 1st kernel boot loader.
> >
> >>
> >>>One thing I'm confused is mem= only pass the memory size, where does you pass
> >>>the start addresses?
> >>
> >>In the current arm64 implementation, any regions below the start address will
> >>be ignored as system ram.
> >>
> >>>What if there's multiple sections such as some reserved
> >>>ranges 2nd kernel also need?
> >>
> >>My patch utilizes only a single contiguous region of memory as system ram.
> >>One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.
> >>
> >>Please let me know if there is any other case that should be supported.
> >
> >For example the elf headers range, you reserved them in kdump kernel code,
> >but kexec-tools can do that early if it can provides all memory info to 2nd
> >kernel. Ditto for mark all the memory ranges 1st kernel used as reserved.
> 
> It seems to me that the issue you mentioned here is totally independent
> from "mem=" issue, isn't it?
> (and "elfcorehdr=" is a common way for crash dump kernel to know the region.)

Hmm, I did not talked about the eflcorehdr=, I means the code to reserve the
memory ranges elfcorehdr is using.

Thanks
Dave

> 
> -Takahiro AKASHI
> 
> >Thanks
> >Dave
> >

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 13/16] arm64: kdump: add kdump support
  2015-10-29  6:40                 ` Dave Young
@ 2015-10-29  6:53                   ` AKASHI Takahiro
  -1 siblings, 0 replies; 72+ messages in thread
From: AKASHI Takahiro @ 2015-10-29  6:53 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/29/2015 03:40 PM, Dave Young wrote:
> Hi, AKASHI
>
> On 10/29/15 at 02:55pm, AKASHI Takahiro wrote:
>> Dave,
>>
>> On 10/23/2015 06:50 PM, Dave Young wrote:
>>> On 10/22/15 at 06:57pm, AKASHI Takahiro wrote:
>>>> (added Ard to Cc.)
>>>>
>>>> On 10/22/2015 02:15 PM, Dave Young wrote:
>>>>> On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
>>>>>> Hi Dave,
>>>>>>
>>>>>> Thank you for your comment.
>>>>>>
>>>>>> On 10/22/2015 12:25 PM, Dave Young wrote:
>>>>>>> Hi, AKASHI,
>>>>>>>
>>>>>>> On 10/19/15 at 11:38pm, Geoff Levand wrote:
>>>>>>>> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
>>>>>>>>
>>>>>>>> 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.
>>>>>>>
>>>>>>> How does kexec-tools pass usable memory ranges to kernel? using dtb?
>>>>>>> Passing an extra mem=X sounds odd in the design. Kdump kernel should get
>>>>>>> usable ranges and hanle the limit better than depending on an extern kernel
>>>>>>> param.
>>>>>>
>>>>>> Well, regarding "depending on an external kernel param,"
>>>>>> - this limitation ("mem=") is compatible with arm(32) implementation although
>>>>>>    it is not clearly described in kernel's Documentation/kdump/kdump.txt.
>>>>>> - "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
>>>>>>    The parameter is explicitly generated and added by kexec-tools.
>>>>>>
>>>>>> Do I miss your point?
>>>>>
>>>>> Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
>>>>> says: The boot loader must pass at a minimum the size and location of the
>>>>> system memory
>>>>>
>>>>> In arm64 booting.txt, it does mentions about dtb but without above sentence.
>>>>>
>>>>> So if you are using dtb to pass memory I think the extra mem= should be not
>>>>> necessary unless there's other limitations dtb can not been used.
>>>>
>>>> I would expect comments from arm64 maintainers here.
>>>>
>>>> In my old implementation, I added "usablemem" attributes, along with "reg," to
>>>> "memory" nodes in dtb to specify the usable memory region on crash dump kernel.
>>>>
>>>> But I removed this feature partly because, on uefi system, uefi might pass
>>>> no memory information in dtb.
>>>
>>> If this is the case there must be somewhere else one can pass memory infomation
>>> to kernel, the booting.txt should be updated?
>>>
>>> kexec as a boot loader need use same method as the 1st kernel boot loader.
>>>
>>>>
>>>>> One thing I'm confused is mem= only pass the memory size, where does you pass
>>>>> the start addresses?
>>>>
>>>> In the current arm64 implementation, any regions below the start address will
>>>> be ignored as system ram.
>>>>
>>>>> What if there's multiple sections such as some reserved
>>>>> ranges 2nd kernel also need?
>>>>
>>>> My patch utilizes only a single contiguous region of memory as system ram.
>>>> One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.
>>>>
>>>> Please let me know if there is any other case that should be supported.
>>>
>>> For example the elf headers range, you reserved them in kdump kernel code,
>>> but kexec-tools can do that early if it can provides all memory info to 2nd
>>> kernel. Ditto for mark all the memory ranges 1st kernel used as reserved.
>>
>> It seems to me that the issue you mentioned here is totally independent
>> from "mem=" issue, isn't it?
>> (and "elfcorehdr=" is a common way for crash dump kernel to know the region.)
>
> Hmm, I did not talked about the eflcorehdr=, I means the code to reserve the
> memory ranges elfcorehdr is using.

So how does it relate to "mem=" issue?

-Takahiro AKASHI

> Thanks
> Dave
>
>>
>> -Takahiro AKASHI
>>
>>> Thanks
>>> Dave
>>>

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 13/16] arm64: kdump: add kdump support
@ 2015-10-29  6:53                   ` AKASHI Takahiro
  0 siblings, 0 replies; 72+ messages in thread
From: AKASHI Takahiro @ 2015-10-29  6:53 UTC (permalink / raw)
  To: Dave Young
  Cc: Mark Rutland, AKASHI, ard.biesheuvel, Geoff Levand,
	Catalin Marinas, Will Deacon, marc.zyngier, linux-arm-kernel,
	kexec, christoffer.dall

On 10/29/2015 03:40 PM, Dave Young wrote:
> Hi, AKASHI
>
> On 10/29/15 at 02:55pm, AKASHI Takahiro wrote:
>> Dave,
>>
>> On 10/23/2015 06:50 PM, Dave Young wrote:
>>> On 10/22/15 at 06:57pm, AKASHI Takahiro wrote:
>>>> (added Ard to Cc.)
>>>>
>>>> On 10/22/2015 02:15 PM, Dave Young wrote:
>>>>> On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
>>>>>> Hi Dave,
>>>>>>
>>>>>> Thank you for your comment.
>>>>>>
>>>>>> On 10/22/2015 12:25 PM, Dave Young wrote:
>>>>>>> Hi, AKASHI,
>>>>>>>
>>>>>>> On 10/19/15 at 11:38pm, Geoff Levand wrote:
>>>>>>>> From: AKASHI Takahiro <takahiro.akashi@linaro.org>
>>>>>>>>
>>>>>>>> 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.
>>>>>>>
>>>>>>> How does kexec-tools pass usable memory ranges to kernel? using dtb?
>>>>>>> Passing an extra mem=X sounds odd in the design. Kdump kernel should get
>>>>>>> usable ranges and hanle the limit better than depending on an extern kernel
>>>>>>> param.
>>>>>>
>>>>>> Well, regarding "depending on an external kernel param,"
>>>>>> - this limitation ("mem=") is compatible with arm(32) implementation although
>>>>>>    it is not clearly described in kernel's Documentation/kdump/kdump.txt.
>>>>>> - "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
>>>>>>    The parameter is explicitly generated and added by kexec-tools.
>>>>>>
>>>>>> Do I miss your point?
>>>>>
>>>>> Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
>>>>> says: The boot loader must pass at a minimum the size and location of the
>>>>> system memory
>>>>>
>>>>> In arm64 booting.txt, it does mentions about dtb but without above sentence.
>>>>>
>>>>> So if you are using dtb to pass memory I think the extra mem= should be not
>>>>> necessary unless there's other limitations dtb can not been used.
>>>>
>>>> I would expect comments from arm64 maintainers here.
>>>>
>>>> In my old implementation, I added "usablemem" attributes, along with "reg," to
>>>> "memory" nodes in dtb to specify the usable memory region on crash dump kernel.
>>>>
>>>> But I removed this feature partly because, on uefi system, uefi might pass
>>>> no memory information in dtb.
>>>
>>> If this is the case there must be somewhere else one can pass memory infomation
>>> to kernel, the booting.txt should be updated?
>>>
>>> kexec as a boot loader need use same method as the 1st kernel boot loader.
>>>
>>>>
>>>>> One thing I'm confused is mem= only pass the memory size, where does you pass
>>>>> the start addresses?
>>>>
>>>> In the current arm64 implementation, any regions below the start address will
>>>> be ignored as system ram.
>>>>
>>>>> What if there's multiple sections such as some reserved
>>>>> ranges 2nd kernel also need?
>>>>
>>>> My patch utilizes only a single contiguous region of memory as system ram.
>>>> One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.
>>>>
>>>> Please let me know if there is any other case that should be supported.
>>>
>>> For example the elf headers range, you reserved them in kdump kernel code,
>>> but kexec-tools can do that early if it can provides all memory info to 2nd
>>> kernel. Ditto for mark all the memory ranges 1st kernel used as reserved.
>>
>> It seems to me that the issue you mentioned here is totally independent
>> from "mem=" issue, isn't it?
>> (and "elfcorehdr=" is a common way for crash dump kernel to know the region.)
>
> Hmm, I did not talked about the eflcorehdr=, I means the code to reserve the
> memory ranges elfcorehdr is using.

So how does it relate to "mem=" issue?

-Takahiro AKASHI

> Thanks
> Dave
>
>>
>> -Takahiro AKASHI
>>
>>> Thanks
>>> Dave
>>>

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 13/16] arm64: kdump: add kdump support
  2015-10-29  6:53                   ` AKASHI Takahiro
@ 2015-10-29  7:01                     ` Dave Young
  -1 siblings, 0 replies; 72+ messages in thread
From: Dave Young @ 2015-10-29  7:01 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/29/15 at 03:53pm, AKASHI Takahiro wrote:
> On 10/29/2015 03:40 PM, Dave Young wrote:
> >Hi, AKASHI
> >
> >On 10/29/15 at 02:55pm, AKASHI Takahiro wrote:
> >>Dave,
> >>
> >>On 10/23/2015 06:50 PM, Dave Young wrote:
> >>>On 10/22/15 at 06:57pm, AKASHI Takahiro wrote:
> >>>>(added Ard to Cc.)
> >>>>
> >>>>On 10/22/2015 02:15 PM, Dave Young wrote:
> >>>>>On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
> >>>>>>Hi Dave,
> >>>>>>
> >>>>>>Thank you for your comment.
> >>>>>>
> >>>>>>On 10/22/2015 12:25 PM, Dave Young wrote:
> >>>>>>>Hi, AKASHI,
> >>>>>>>
> >>>>>>>On 10/19/15 at 11:38pm, Geoff Levand wrote:
> >>>>>>>>From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> >>>>>>>>
> >>>>>>>>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.
> >>>>>>>
> >>>>>>>How does kexec-tools pass usable memory ranges to kernel? using dtb?
> >>>>>>>Passing an extra mem=X sounds odd in the design. Kdump kernel should get
> >>>>>>>usable ranges and hanle the limit better than depending on an extern kernel
> >>>>>>>param.
> >>>>>>
> >>>>>>Well, regarding "depending on an external kernel param,"
> >>>>>>- this limitation ("mem=") is compatible with arm(32) implementation although
> >>>>>>   it is not clearly described in kernel's Documentation/kdump/kdump.txt.
> >>>>>>- "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
> >>>>>>   The parameter is explicitly generated and added by kexec-tools.
> >>>>>>
> >>>>>>Do I miss your point?
> >>>>>
> >>>>>Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
> >>>>>says: The boot loader must pass at a minimum the size and location of the
> >>>>>system memory
> >>>>>
> >>>>>In arm64 booting.txt, it does mentions about dtb but without above sentence.
> >>>>>
> >>>>>So if you are using dtb to pass memory I think the extra mem= should be not
> >>>>>necessary unless there's other limitations dtb can not been used.
> >>>>
> >>>>I would expect comments from arm64 maintainers here.
> >>>>
> >>>>In my old implementation, I added "usablemem" attributes, along with "reg," to
> >>>>"memory" nodes in dtb to specify the usable memory region on crash dump kernel.
> >>>>
> >>>>But I removed this feature partly because, on uefi system, uefi might pass
> >>>>no memory information in dtb.
> >>>
> >>>If this is the case there must be somewhere else one can pass memory infomation
> >>>to kernel, the booting.txt should be updated?
> >>>
> >>>kexec as a boot loader need use same method as the 1st kernel boot loader.
> >>>
> >>>>
> >>>>>One thing I'm confused is mem= only pass the memory size, where does you pass
> >>>>>the start addresses?
> >>>>
> >>>>In the current arm64 implementation, any regions below the start address will
> >>>>be ignored as system ram.
> >>>>
> >>>>>What if there's multiple sections such as some reserved
> >>>>>ranges 2nd kernel also need?
> >>>>
> >>>>My patch utilizes only a single contiguous region of memory as system ram.
> >>>>One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.
> >>>>
> >>>>Please let me know if there is any other case that should be supported.
> >>>
> >>>For example the elf headers range, you reserved them in kdump kernel code,
> >>>but kexec-tools can do that early if it can provides all memory info to 2nd
> >>>kernel. Ditto for mark all the memory ranges 1st kernel used as reserved.
> >>
> >>It seems to me that the issue you mentioned here is totally independent
> >>from "mem=" issue, isn't it?
> >>(and "elfcorehdr=" is a common way for crash dump kernel to know the region.)
> >
> >Hmm, I did not talked about the eflcorehdr=, I means the code to reserve the
> >memory ranges elfcorehdr is using.
> 
> So how does it relate to "mem=" issue?

It is just an example that kexec can pass it along with the usable mem range to
kernel via some interface like dtb blob or some other interfaces. 

> 
> -Takahiro AKASHI
> 
> >Thanks
> >Dave
> >
> >>
> >>-Takahiro AKASHI
> >>
> >>>Thanks
> >>>Dave
> >>>

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 13/16] arm64: kdump: add kdump support
@ 2015-10-29  7:01                     ` Dave Young
  0 siblings, 0 replies; 72+ messages in thread
From: Dave Young @ 2015-10-29  7:01 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Mark Rutland, AKASHI, ard.biesheuvel, Geoff Levand,
	Catalin Marinas, Will Deacon, marc.zyngier, linux-arm-kernel,
	kexec, christoffer.dall

On 10/29/15 at 03:53pm, AKASHI Takahiro wrote:
> On 10/29/2015 03:40 PM, Dave Young wrote:
> >Hi, AKASHI
> >
> >On 10/29/15 at 02:55pm, AKASHI Takahiro wrote:
> >>Dave,
> >>
> >>On 10/23/2015 06:50 PM, Dave Young wrote:
> >>>On 10/22/15 at 06:57pm, AKASHI Takahiro wrote:
> >>>>(added Ard to Cc.)
> >>>>
> >>>>On 10/22/2015 02:15 PM, Dave Young wrote:
> >>>>>On 10/22/15 at 01:29pm, AKASHI Takahiro wrote:
> >>>>>>Hi Dave,
> >>>>>>
> >>>>>>Thank you for your comment.
> >>>>>>
> >>>>>>On 10/22/2015 12:25 PM, Dave Young wrote:
> >>>>>>>Hi, AKASHI,
> >>>>>>>
> >>>>>>>On 10/19/15 at 11:38pm, Geoff Levand wrote:
> >>>>>>>>From: AKASHI Takahiro <takahiro.akashi@linaro.org>
> >>>>>>>>
> >>>>>>>>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.
> >>>>>>>
> >>>>>>>How does kexec-tools pass usable memory ranges to kernel? using dtb?
> >>>>>>>Passing an extra mem=X sounds odd in the design. Kdump kernel should get
> >>>>>>>usable ranges and hanle the limit better than depending on an extern kernel
> >>>>>>>param.
> >>>>>>
> >>>>>>Well, regarding "depending on an external kernel param,"
> >>>>>>- this limitation ("mem=") is compatible with arm(32) implementation although
> >>>>>>   it is not clearly described in kernel's Documentation/kdump/kdump.txt.
> >>>>>>- "elfcorehdr" kernel parameter is mandatory on x86 as well as on arm/arm64.
> >>>>>>   The parameter is explicitly generated and added by kexec-tools.
> >>>>>>
> >>>>>>Do I miss your point?
> >>>>>
> >>>>>Arm previously use atag_mem tag for memory kernel uses, with dtb, Booting.txt
> >>>>>says: The boot loader must pass at a minimum the size and location of the
> >>>>>system memory
> >>>>>
> >>>>>In arm64 booting.txt, it does mentions about dtb but without above sentence.
> >>>>>
> >>>>>So if you are using dtb to pass memory I think the extra mem= should be not
> >>>>>necessary unless there's other limitations dtb can not been used.
> >>>>
> >>>>I would expect comments from arm64 maintainers here.
> >>>>
> >>>>In my old implementation, I added "usablemem" attributes, along with "reg," to
> >>>>"memory" nodes in dtb to specify the usable memory region on crash dump kernel.
> >>>>
> >>>>But I removed this feature partly because, on uefi system, uefi might pass
> >>>>no memory information in dtb.
> >>>
> >>>If this is the case there must be somewhere else one can pass memory infomation
> >>>to kernel, the booting.txt should be updated?
> >>>
> >>>kexec as a boot loader need use same method as the 1st kernel boot loader.
> >>>
> >>>>
> >>>>>One thing I'm confused is mem= only pass the memory size, where does you pass
> >>>>>the start addresses?
> >>>>
> >>>>In the current arm64 implementation, any regions below the start address will
> >>>>be ignored as system ram.
> >>>>
> >>>>>What if there's multiple sections such as some reserved
> >>>>>ranges 2nd kernel also need?
> >>>>
> >>>>My patch utilizes only a single contiguous region of memory as system ram.
> >>>>One exception that I notice is uefi's runtime data. They will be ioremap'ed separately.
> >>>>
> >>>>Please let me know if there is any other case that should be supported.
> >>>
> >>>For example the elf headers range, you reserved them in kdump kernel code,
> >>>but kexec-tools can do that early if it can provides all memory info to 2nd
> >>>kernel. Ditto for mark all the memory ranges 1st kernel used as reserved.
> >>
> >>It seems to me that the issue you mentioned here is totally independent
> >>from "mem=" issue, isn't it?
> >>(and "elfcorehdr=" is a common way for crash dump kernel to know the region.)
> >
> >Hmm, I did not talked about the eflcorehdr=, I means the code to reserve the
> >memory ranges elfcorehdr is using.
> 
> So how does it relate to "mem=" issue?

It is just an example that kexec can pass it along with the usable mem range to
kernel via some interface like dtb blob or some other interfaces. 

> 
> -Takahiro AKASHI
> 
> >Thanks
> >Dave
> >
> >>
> >>-Takahiro AKASHI
> >>
> >>>Thanks
> >>>Dave
> >>>

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 08/16] arm64/kexec: Add core kexec support
  2015-10-19 23:38   ` Geoff Levand
@ 2015-10-30 16:29     ` James Morse
  -1 siblings, 0 replies; 72+ messages in thread
From: James Morse @ 2015-10-30 16:29 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Geoff,

On 20/10/15 00:38, Geoff Levand wrote:
> 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.
> 
> Signed-off-by: Geoff Levand <geoff@infradead.org>
> ---
>  arch/arm64/Kconfig                  |  10 +++
>  arch/arm64/include/asm/kexec.h      |  48 +++++++++++
>  arch/arm64/kernel/Makefile          |   2 +
>  arch/arm64/kernel/cpu-reset.S       |   2 +-
>  arch/arm64/kernel/machine_kexec.c   | 141 +++++++++++++++++++++++++++++++
>  arch/arm64/kernel/relocate_kernel.S | 163 ++++++++++++++++++++++++++++++++++++
>  include/uapi/linux/kexec.h          |   1 +
>  7 files changed, 366 insertions(+), 1 deletion(-)
>  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
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 07d1811..73e8e31 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -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 (!SMP || PM_SLEEP_SMP)

Commit 4b3dc9679cf7 got rid of '!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
> diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S
> index ffc9e385e..7cc7f56 100644
> --- a/arch/arm64/kernel/cpu-reset.S
> +++ b/arch/arm64/kernel/cpu-reset.S
> @@ -3,7 +3,7 @@
>   *
>   * Copyright (C) 2001 Deep Blue Solutions Ltd.
>   * Copyright (C) 2012 ARM Ltd.
> - * Copyright (C) 2015 Huawei Futurewei Technologies.
> + * Copyright (C) Huawei Futurewei Technologies.

Move this hunk into the patch that adds the file?


>   *
>   * 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
> diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S
> new file mode 100644
> index 0000000..7b07a16
> --- /dev/null
> +++ b/arch/arm64/kernel/relocate_kernel.S
> @@ -0,0 +1,163 @@
> +/*
> + * kexec for arm64
> + *
> + * Copyright (C) Linaro.
> + * Copyright (C) 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/kexec.h>
> +
> +#include <asm/assembler.h>
> +#include <asm/kexec.h>
> +#include <asm/memory.h>
> +#include <asm/page.h>
> +
> +
> +/*
> + * arm64_relocate_new_kernel - Put a 2nd stage kernel image in place and boot it.
> + *
> + * The memory that the old kernel occupies may be overwritten when coping the
> + * new image to its final location.  To assure that the
> + * arm64_relocate_new_kernel routine which does that copy is not overwritten,
> + * all code and data needed by arm64_relocate_new_kernel must be between the
> + * symbols arm64_relocate_new_kernel and arm64_relocate_new_kernel_end.  The
> + * machine_kexec() routine will copy arm64_relocate_new_kernel to the kexec
> + * control_code_page, a special page which has been set up to be preserved
> + * during the copy operation.
> + */
> +.globl arm64_relocate_new_kernel
> +arm64_relocate_new_kernel:
> +
> +	/* Setup the list loop variables. */
> +	ldr	x18, .Lkimage_head		/* x18 = list entry */
> +	dcache_line_size x17, x0		/* x17 = dcache line size */
> +	mov	x16, xzr			/* x16 = segment start */
> +	mov	x15, xzr			/* x15 = entry ptr */
> +	mov	x14, xzr			/* x14 = copy dest */
> +
> +	/* Check if the new image needs relocation. */
> +	cbz	x18, .Ldone
> +	tbnz	x18, IND_DONE_BIT, .Ldone
> +
> +.Lloop:
> +	and	x13, x18, PAGE_MASK		/* x13 = addr */
> +
> +	/* Test the entry flags. */
> +.Ltest_source:
> +	tbz	x18, IND_SOURCE_BIT, .Ltest_indirection
> +
> +	mov x20, x14				/*  x20 = copy dest */
> +	mov x21, x13				/*  x21 = copy src */
> +
> +	/* Invalidate dest page to PoC. */
> +	mov	x0, x20
> +	add	x19, x0, #PAGE_SIZE
> +	sub	x1, x17, #1
> +	bic	x0, x0, x1
> +1:	dc	ivac, x0
> +	add	x0, x0, x17
> +	cmp	x0, x19
> +	b.lo	1b
> +	dsb	sy

If I've followed all this through properly:

With KVM - mmu+caches are configured, but then disabled by 'kvm: allows kvm
cpu hotplug'. This 'arm64_relocate_new_kernel' function then runs at EL2
with M=0, C=0, I=0.

Without KVM - when there is no user of EL2, the mmu+caches are left in
whatever state the bootloader (or efi stub) left them in. From
Documentation/arm64/booting.txt:
> Instruction cache may be on or off.
and
> System caches which respect the architected cache maintenance by VA
> operations must be configured and may be enabled.

So 'arm64_relocate_new_kernel' function could run at EL2 with M=0, C=?, I=?.

I think this means you can't guarantee anything you are copying below
actually makes it through the caches - booting secondary processors may get
stale values.

The EFI stub disables the M and C bits when booted at EL2 with uefi - but
it leaves the instruction cache enabled. You only clean the
reboot_code_buffer from the data cache, so there may be stale values in the
instruction cache.

I think you need to disable the i-cache at EL1. If you jump to EL2, I think
you need to disable the I/C bits there too - as you can't rely on the code
in 'kvm: allows kvm cpu hotplug' to do this in a non-kvm case.


> +
> +	/* Copy page. */
> +1:	ldp	x22, x23, [x21]
> +	ldp	x24, x25, [x21, #16]
> +	ldp	x26, x27, [x21, #32]
> +	ldp	x28, x29, [x21, #48]
> +	add	x21, x21, #64
> +	stnp	x22, x23, [x20]
> +	stnp	x24, x25, [x20, #16]
> +	stnp	x26, x27, [x20, #32]
> +	stnp	x28, x29, [x20, #48]
> +	add	x20, x20, #64
> +	tst	x21, #(PAGE_SIZE - 1)
> +	b.ne	1b
> +
> +	/* dest += PAGE_SIZE */
> +	add	x14, x14, PAGE_SIZE
> +	b	.Lnext
> +
> +.Ltest_indirection:
> +	tbz	x18, IND_INDIRECTION_BIT, .Ltest_destination
> +
> +	/* ptr = addr */
> +	mov	x15, x13
> +	b	.Lnext
> +
> +.Ltest_destination:
> +	tbz	x18, IND_DESTINATION_BIT, .Lnext
> +
> +	mov	x16, x13
> +
> +	/* dest = addr */
> +	mov	x14, x13
> +
> +.Lnext:
> +	/* entry = *ptr++ */
> +	ldr	x18, [x15], #8
> +
> +	/* while (!(entry & DONE)) */
> +	tbz	x18, IND_DONE_BIT, .Lloop
> +
> +.Ldone:
> +	dsb	sy
> +	isb
> +	ic	ialluis
> +	dsb	sy

Why the second dsb?


> +	isb
> +
> +	/* Start new image. */
> +	ldr	x4, .Lkimage_start
> +	mov	x0, xzr
> +	mov	x1, xzr
> +	mov	x2, xzr
> +	mov	x3, xzr

Once the kexec'd kernel is booting, I get:
> WARNING: x1-x3 nonzero in violation of boot protocol:
>         x1: 0000000080008000
>         x2: 0000000000000020
>         x3: 0000000000000020
> This indicates a broken bootloader or old kernel

Presumably this 'kimage_start' isn't pointing to the new kernel, but the
purgatory code, (which comes from user-space?). (If so what are these xzr-s
for?)


> +	br	x4
> +
> +.align 3	/* To keep the 64-bit values below naturally aligned. */
> +
> +/* The machine_kexec routine sets these variables via offsets from
> + * arm64_relocate_new_kernel.
> + */
> +
> +/*
> + * .Lkimage_start - Copy of image->start, the entry point of the new
> + * image.
> + */
> +.Lkimage_start:
> +	.quad	0x0
> +
> +/*
> + * .Lkimage_head - Copy of image->head, the list of kimage entries.
> + */
> +.Lkimage_head:
> +	.quad	0x0
> +

I assume these .quad-s are used because you can't pass the values in via
registers - due to the complicated soft_restart(). Given you are the only
user, couldn't you simplify it to do all the disabling in
arm64_relocate_new_kernel?


> +.Lcopy_end:
> +.org	KEXEC_CONTROL_PAGE_SIZE
> +
> +/*
> + * arm64_relocate_new_kernel_size - Number of bytes to copy to the control_code_page.
> + */
> +.globl arm64_relocate_new_kernel_size
> +arm64_relocate_new_kernel_size:
> +	.quad	.Lcopy_end - arm64_relocate_new_kernel
> +
> +/*
> + * arm64_kexec_kimage_start_offset - Offset for writing .Lkimage_start.
> + */
> +.globl arm64_kexec_kimage_start_offset
> +arm64_kexec_kimage_start_offset:
> +	.quad	.Lkimage_start - arm64_relocate_new_kernel
> +
> +/*
> + * arm64_kexec_kimage_head_offset - Offset for writing .Lkimage_head.
> + */
> +.globl arm64_kexec_kimage_head_offset
> +arm64_kexec_kimage_head_offset:
> +	.quad	.Lkimage_head - arm64_relocate_new_kernel


>From 'kexec -e' to the first messages from the new kernel takes ~1 minute
on Juno, Did you see a similar delay? Or should I go looking for what I've
configured wrong!?

(Copying code with the mmu+caches on, then cleaning to PoC was noticeably
faster for hibernate)


I've used this series for kexec-ing between 4K and 64K page_size kernels on
Juno.

Tested-By: James Morse <james.morse@arm.com>



Thanks!

James

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 08/16] arm64/kexec: Add core kexec support
@ 2015-10-30 16:29     ` James Morse
  0 siblings, 0 replies; 72+ messages in thread
From: James Morse @ 2015-10-30 16:29 UTC (permalink / raw)
  To: Geoff Levand
  Cc: Mark Rutland, AKASHI, marc.zyngier, Catalin Marinas, Will Deacon,
	Takahiro, christoffer.dall, kexec, linux-arm-kernel

Hi Geoff,

On 20/10/15 00:38, Geoff Levand wrote:
> 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.
> 
> Signed-off-by: Geoff Levand <geoff@infradead.org>
> ---
>  arch/arm64/Kconfig                  |  10 +++
>  arch/arm64/include/asm/kexec.h      |  48 +++++++++++
>  arch/arm64/kernel/Makefile          |   2 +
>  arch/arm64/kernel/cpu-reset.S       |   2 +-
>  arch/arm64/kernel/machine_kexec.c   | 141 +++++++++++++++++++++++++++++++
>  arch/arm64/kernel/relocate_kernel.S | 163 ++++++++++++++++++++++++++++++++++++
>  include/uapi/linux/kexec.h          |   1 +
>  7 files changed, 366 insertions(+), 1 deletion(-)
>  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
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 07d1811..73e8e31 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -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 (!SMP || PM_SLEEP_SMP)

Commit 4b3dc9679cf7 got rid of '!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
> diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S
> index ffc9e385e..7cc7f56 100644
> --- a/arch/arm64/kernel/cpu-reset.S
> +++ b/arch/arm64/kernel/cpu-reset.S
> @@ -3,7 +3,7 @@
>   *
>   * Copyright (C) 2001 Deep Blue Solutions Ltd.
>   * Copyright (C) 2012 ARM Ltd.
> - * Copyright (C) 2015 Huawei Futurewei Technologies.
> + * Copyright (C) Huawei Futurewei Technologies.

Move this hunk into the patch that adds the file?


>   *
>   * 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
> diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S
> new file mode 100644
> index 0000000..7b07a16
> --- /dev/null
> +++ b/arch/arm64/kernel/relocate_kernel.S
> @@ -0,0 +1,163 @@
> +/*
> + * kexec for arm64
> + *
> + * Copyright (C) Linaro.
> + * Copyright (C) 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/kexec.h>
> +
> +#include <asm/assembler.h>
> +#include <asm/kexec.h>
> +#include <asm/memory.h>
> +#include <asm/page.h>
> +
> +
> +/*
> + * arm64_relocate_new_kernel - Put a 2nd stage kernel image in place and boot it.
> + *
> + * The memory that the old kernel occupies may be overwritten when coping the
> + * new image to its final location.  To assure that the
> + * arm64_relocate_new_kernel routine which does that copy is not overwritten,
> + * all code and data needed by arm64_relocate_new_kernel must be between the
> + * symbols arm64_relocate_new_kernel and arm64_relocate_new_kernel_end.  The
> + * machine_kexec() routine will copy arm64_relocate_new_kernel to the kexec
> + * control_code_page, a special page which has been set up to be preserved
> + * during the copy operation.
> + */
> +.globl arm64_relocate_new_kernel
> +arm64_relocate_new_kernel:
> +
> +	/* Setup the list loop variables. */
> +	ldr	x18, .Lkimage_head		/* x18 = list entry */
> +	dcache_line_size x17, x0		/* x17 = dcache line size */
> +	mov	x16, xzr			/* x16 = segment start */
> +	mov	x15, xzr			/* x15 = entry ptr */
> +	mov	x14, xzr			/* x14 = copy dest */
> +
> +	/* Check if the new image needs relocation. */
> +	cbz	x18, .Ldone
> +	tbnz	x18, IND_DONE_BIT, .Ldone
> +
> +.Lloop:
> +	and	x13, x18, PAGE_MASK		/* x13 = addr */
> +
> +	/* Test the entry flags. */
> +.Ltest_source:
> +	tbz	x18, IND_SOURCE_BIT, .Ltest_indirection
> +
> +	mov x20, x14				/*  x20 = copy dest */
> +	mov x21, x13				/*  x21 = copy src */
> +
> +	/* Invalidate dest page to PoC. */
> +	mov	x0, x20
> +	add	x19, x0, #PAGE_SIZE
> +	sub	x1, x17, #1
> +	bic	x0, x0, x1
> +1:	dc	ivac, x0
> +	add	x0, x0, x17
> +	cmp	x0, x19
> +	b.lo	1b
> +	dsb	sy

If I've followed all this through properly:

With KVM - mmu+caches are configured, but then disabled by 'kvm: allows kvm
cpu hotplug'. This 'arm64_relocate_new_kernel' function then runs at EL2
with M=0, C=0, I=0.

Without KVM - when there is no user of EL2, the mmu+caches are left in
whatever state the bootloader (or efi stub) left them in. From
Documentation/arm64/booting.txt:
> Instruction cache may be on or off.
and
> System caches which respect the architected cache maintenance by VA
> operations must be configured and may be enabled.

So 'arm64_relocate_new_kernel' function could run at EL2 with M=0, C=?, I=?.

I think this means you can't guarantee anything you are copying below
actually makes it through the caches - booting secondary processors may get
stale values.

The EFI stub disables the M and C bits when booted at EL2 with uefi - but
it leaves the instruction cache enabled. You only clean the
reboot_code_buffer from the data cache, so there may be stale values in the
instruction cache.

I think you need to disable the i-cache at EL1. If you jump to EL2, I think
you need to disable the I/C bits there too - as you can't rely on the code
in 'kvm: allows kvm cpu hotplug' to do this in a non-kvm case.


> +
> +	/* Copy page. */
> +1:	ldp	x22, x23, [x21]
> +	ldp	x24, x25, [x21, #16]
> +	ldp	x26, x27, [x21, #32]
> +	ldp	x28, x29, [x21, #48]
> +	add	x21, x21, #64
> +	stnp	x22, x23, [x20]
> +	stnp	x24, x25, [x20, #16]
> +	stnp	x26, x27, [x20, #32]
> +	stnp	x28, x29, [x20, #48]
> +	add	x20, x20, #64
> +	tst	x21, #(PAGE_SIZE - 1)
> +	b.ne	1b
> +
> +	/* dest += PAGE_SIZE */
> +	add	x14, x14, PAGE_SIZE
> +	b	.Lnext
> +
> +.Ltest_indirection:
> +	tbz	x18, IND_INDIRECTION_BIT, .Ltest_destination
> +
> +	/* ptr = addr */
> +	mov	x15, x13
> +	b	.Lnext
> +
> +.Ltest_destination:
> +	tbz	x18, IND_DESTINATION_BIT, .Lnext
> +
> +	mov	x16, x13
> +
> +	/* dest = addr */
> +	mov	x14, x13
> +
> +.Lnext:
> +	/* entry = *ptr++ */
> +	ldr	x18, [x15], #8
> +
> +	/* while (!(entry & DONE)) */
> +	tbz	x18, IND_DONE_BIT, .Lloop
> +
> +.Ldone:
> +	dsb	sy
> +	isb
> +	ic	ialluis
> +	dsb	sy

Why the second dsb?


> +	isb
> +
> +	/* Start new image. */
> +	ldr	x4, .Lkimage_start
> +	mov	x0, xzr
> +	mov	x1, xzr
> +	mov	x2, xzr
> +	mov	x3, xzr

Once the kexec'd kernel is booting, I get:
> WARNING: x1-x3 nonzero in violation of boot protocol:
>         x1: 0000000080008000
>         x2: 0000000000000020
>         x3: 0000000000000020
> This indicates a broken bootloader or old kernel

Presumably this 'kimage_start' isn't pointing to the new kernel, but the
purgatory code, (which comes from user-space?). (If so what are these xzr-s
for?)


> +	br	x4
> +
> +.align 3	/* To keep the 64-bit values below naturally aligned. */
> +
> +/* The machine_kexec routine sets these variables via offsets from
> + * arm64_relocate_new_kernel.
> + */
> +
> +/*
> + * .Lkimage_start - Copy of image->start, the entry point of the new
> + * image.
> + */
> +.Lkimage_start:
> +	.quad	0x0
> +
> +/*
> + * .Lkimage_head - Copy of image->head, the list of kimage entries.
> + */
> +.Lkimage_head:
> +	.quad	0x0
> +

I assume these .quad-s are used because you can't pass the values in via
registers - due to the complicated soft_restart(). Given you are the only
user, couldn't you simplify it to do all the disabling in
arm64_relocate_new_kernel?


> +.Lcopy_end:
> +.org	KEXEC_CONTROL_PAGE_SIZE
> +
> +/*
> + * arm64_relocate_new_kernel_size - Number of bytes to copy to the control_code_page.
> + */
> +.globl arm64_relocate_new_kernel_size
> +arm64_relocate_new_kernel_size:
> +	.quad	.Lcopy_end - arm64_relocate_new_kernel
> +
> +/*
> + * arm64_kexec_kimage_start_offset - Offset for writing .Lkimage_start.
> + */
> +.globl arm64_kexec_kimage_start_offset
> +arm64_kexec_kimage_start_offset:
> +	.quad	.Lkimage_start - arm64_relocate_new_kernel
> +
> +/*
> + * arm64_kexec_kimage_head_offset - Offset for writing .Lkimage_head.
> + */
> +.globl arm64_kexec_kimage_head_offset
> +arm64_kexec_kimage_head_offset:
> +	.quad	.Lkimage_head - arm64_relocate_new_kernel


From 'kexec -e' to the first messages from the new kernel takes ~1 minute
on Juno, Did you see a similar delay? Or should I go looking for what I've
configured wrong!?

(Copying code with the mmu+caches on, then cleaning to PoC was noticeably
faster for hibernate)


I've used this series for kexec-ing between 4K and 64K page_size kernels on
Juno.

Tested-By: James Morse <james.morse@arm.com>



Thanks!

James






_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 08/16] arm64/kexec: Add core kexec support
  2015-10-30 16:29     ` James Morse
@ 2015-10-30 16:54       ` Mark Rutland
  -1 siblings, 0 replies; 72+ messages in thread
From: Mark Rutland @ 2015-10-30 16:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

> If I've followed all this through properly:
> 
> With KVM - mmu+caches are configured, but then disabled by 'kvm: allows kvm
> cpu hotplug'. This 'arm64_relocate_new_kernel' function then runs at EL2
> with M=0, C=0, I=0.
> 
> Without KVM - when there is no user of EL2, the mmu+caches are left in
> whatever state the bootloader (or efi stub) left them in. From
> Documentation/arm64/booting.txt:
> > Instruction cache may be on or off.
> and
> > System caches which respect the architected cache maintenance by VA
> > operations must be configured and may be enabled.
> 
> So 'arm64_relocate_new_kernel' function could run at EL2 with M=0, C=?, I=?.
> 
> I think this means you can't guarantee anything you are copying below
> actually makes it through the caches - booting secondary processors may get
> stale values.
> 
> The EFI stub disables the M and C bits when booted at EL2 with uefi - but
> it leaves the instruction cache enabled. You only clean the
> reboot_code_buffer from the data cache, so there may be stale values in the
> instruction cache.
> 
> I think you need to disable the i-cache at EL1. If you jump to EL2, I think
> you need to disable the I/C bits there too - as you can't rely on the code
> in 'kvm: allows kvm cpu hotplug' to do this in a non-kvm case.

The SCTLR_ELx.I only affects the attributes that the I-cache uses to
fetch with, not whether it is enabled (it cannot be disabled
architecturally).

It's not necessary to clear the I bit so long as the appropriate
maintenance has occurred, though I believe that when the I bit is set
instruction fetches may allocte in unified levels of cache, so
additional consideration is required for that case.

> > +	/* Copy page. */
> > +1:	ldp	x22, x23, [x21]
> > +	ldp	x24, x25, [x21, #16]
> > +	ldp	x26, x27, [x21, #32]
> > +	ldp	x28, x29, [x21, #48]
> > +	add	x21, x21, #64
> > +	stnp	x22, x23, [x20]
> > +	stnp	x24, x25, [x20, #16]
> > +	stnp	x26, x27, [x20, #32]
> > +	stnp	x28, x29, [x20, #48]
> > +	add	x20, x20, #64
> > +	tst	x21, #(PAGE_SIZE - 1)
> > +	b.ne	1b
> > +
> > +	/* dest += PAGE_SIZE */
> > +	add	x14, x14, PAGE_SIZE
> > +	b	.Lnext
> > +
> > +.Ltest_indirection:
> > +	tbz	x18, IND_INDIRECTION_BIT, .Ltest_destination
> > +
> > +	/* ptr = addr */
> > +	mov	x15, x13
> > +	b	.Lnext
> > +
> > +.Ltest_destination:
> > +	tbz	x18, IND_DESTINATION_BIT, .Lnext
> > +
> > +	mov	x16, x13
> > +
> > +	/* dest = addr */
> > +	mov	x14, x13
> > +
> > +.Lnext:
> > +	/* entry = *ptr++ */
> > +	ldr	x18, [x15], #8
> > +
> > +	/* while (!(entry & DONE)) */
> > +	tbz	x18, IND_DONE_BIT, .Lloop
> > +
> > +.Ldone:
> > +	dsb	sy
> > +	isb
> > +	ic	ialluis
> > +	dsb	sy
> 
> Why the second dsb?
> 
> 
> > +	isb

The first DSB ensures that the copied data is observable by the
I-caches.

The first ISB is unnecessary.

The second DSB ensures that the I-cache maintenance is completed.

The second ISB ensures that the I-cache maintenance is complete w.r.t.
the current instruction stream. There could be instructions in the
pipline fetched from the I-cache prior to invalidation which need to be
cleared.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 08/16] arm64/kexec: Add core kexec support
@ 2015-10-30 16:54       ` Mark Rutland
  0 siblings, 0 replies; 72+ messages in thread
From: Mark Rutland @ 2015-10-30 16:54 UTC (permalink / raw)
  To: James Morse
  Cc: AKASHI, Takahiro, Geoff Levand, Catalin Marinas, Will Deacon,
	marc.zyngier, christoffer.dall, kexec, linux-arm-kernel

Hi,

> If I've followed all this through properly:
> 
> With KVM - mmu+caches are configured, but then disabled by 'kvm: allows kvm
> cpu hotplug'. This 'arm64_relocate_new_kernel' function then runs at EL2
> with M=0, C=0, I=0.
> 
> Without KVM - when there is no user of EL2, the mmu+caches are left in
> whatever state the bootloader (or efi stub) left them in. From
> Documentation/arm64/booting.txt:
> > Instruction cache may be on or off.
> and
> > System caches which respect the architected cache maintenance by VA
> > operations must be configured and may be enabled.
> 
> So 'arm64_relocate_new_kernel' function could run at EL2 with M=0, C=?, I=?.
> 
> I think this means you can't guarantee anything you are copying below
> actually makes it through the caches - booting secondary processors may get
> stale values.
> 
> The EFI stub disables the M and C bits when booted at EL2 with uefi - but
> it leaves the instruction cache enabled. You only clean the
> reboot_code_buffer from the data cache, so there may be stale values in the
> instruction cache.
> 
> I think you need to disable the i-cache at EL1. If you jump to EL2, I think
> you need to disable the I/C bits there too - as you can't rely on the code
> in 'kvm: allows kvm cpu hotplug' to do this in a non-kvm case.

The SCTLR_ELx.I only affects the attributes that the I-cache uses to
fetch with, not whether it is enabled (it cannot be disabled
architecturally).

It's not necessary to clear the I bit so long as the appropriate
maintenance has occurred, though I believe that when the I bit is set
instruction fetches may allocte in unified levels of cache, so
additional consideration is required for that case.

> > +	/* Copy page. */
> > +1:	ldp	x22, x23, [x21]
> > +	ldp	x24, x25, [x21, #16]
> > +	ldp	x26, x27, [x21, #32]
> > +	ldp	x28, x29, [x21, #48]
> > +	add	x21, x21, #64
> > +	stnp	x22, x23, [x20]
> > +	stnp	x24, x25, [x20, #16]
> > +	stnp	x26, x27, [x20, #32]
> > +	stnp	x28, x29, [x20, #48]
> > +	add	x20, x20, #64
> > +	tst	x21, #(PAGE_SIZE - 1)
> > +	b.ne	1b
> > +
> > +	/* dest += PAGE_SIZE */
> > +	add	x14, x14, PAGE_SIZE
> > +	b	.Lnext
> > +
> > +.Ltest_indirection:
> > +	tbz	x18, IND_INDIRECTION_BIT, .Ltest_destination
> > +
> > +	/* ptr = addr */
> > +	mov	x15, x13
> > +	b	.Lnext
> > +
> > +.Ltest_destination:
> > +	tbz	x18, IND_DESTINATION_BIT, .Lnext
> > +
> > +	mov	x16, x13
> > +
> > +	/* dest = addr */
> > +	mov	x14, x13
> > +
> > +.Lnext:
> > +	/* entry = *ptr++ */
> > +	ldr	x18, [x15], #8
> > +
> > +	/* while (!(entry & DONE)) */
> > +	tbz	x18, IND_DONE_BIT, .Lloop
> > +
> > +.Ldone:
> > +	dsb	sy
> > +	isb
> > +	ic	ialluis
> > +	dsb	sy
> 
> Why the second dsb?
> 
> 
> > +	isb

The first DSB ensures that the copied data is observable by the
I-caches.

The first ISB is unnecessary.

The second DSB ensures that the I-cache maintenance is completed.

The second ISB ensures that the I-cache maintenance is complete w.r.t.
the current instruction stream. There could be instructions in the
pipline fetched from the I-cache prior to invalidation which need to be
cleared.

Thanks,
Mark.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 08/16] arm64/kexec: Add core kexec support
  2015-10-30 16:29     ` James Morse
@ 2015-11-02  9:26       ` Pratyush Anand
  -1 siblings, 0 replies; 72+ messages in thread
From: Pratyush Anand @ 2015-11-02  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi James,

On 30/10/2015:04:29:01 PM, James Morse wrote:
> 
> >From 'kexec -e' to the first messages from the new kernel takes ~1 minute
> on Juno, Did you see a similar delay? Or should I go looking for what I've
> configured wrong!?

I did had similar issues with mustang, where it was taking more than 2 min.

Can you please try with my kexec-tools repo [1] where I have patches to enable
D-cache for sha verification. Your feedback might help to upstream these patches.

Thanks
~Pratyush

[1] https://github.com/pratyushanand/kexec-tools.git : master

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 08/16] arm64/kexec: Add core kexec support
@ 2015-11-02  9:26       ` Pratyush Anand
  0 siblings, 0 replies; 72+ messages in thread
From: Pratyush Anand @ 2015-11-02  9:26 UTC (permalink / raw)
  To: James Morse
  Cc: Mark Rutland, AKASHI, Takahiro, Geoff Levand, Catalin Marinas,
	Will Deacon, marc.zyngier, linux-arm-kernel, Dave Young, kexec,
	christoffer.dall

Hi James,

On 30/10/2015:04:29:01 PM, James Morse wrote:
> 
> >From 'kexec -e' to the first messages from the new kernel takes ~1 minute
> on Juno, Did you see a similar delay? Or should I go looking for what I've
> configured wrong!?

I did had similar issues with mustang, where it was taking more than 2 min.

Can you please try with my kexec-tools repo [1] where I have patches to enable
D-cache for sha verification. Your feedback might help to upstream these patches.

Thanks
~Pratyush

[1] https://github.com/pratyushanand/kexec-tools.git : master

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH 08/16] arm64/kexec: Add core kexec support
  2015-10-30 16:29     ` James Morse
@ 2015-11-03  0:30       ` Geoff Levand
  -1 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-11-03  0:30 UTC (permalink / raw)
  To: linux-arm-kernel

Hi James,

On Fri, 2015-10-30 at 16:29 +0000, James Morse wrote:
> On 20/10/15 00:38, Geoff Levand wrote:
> > +config KEXEC
> > +> > 	> > depends on (!SMP || PM_SLEEP_SMP)
> 
> Commit 4b3dc9679cf7 got rid of '!SMP'.

Fixed for v11.

> > - * Copyright (C) 2015 Huawei Futurewei Technologies.
> > + * Copyright (C) Huawei Futurewei Technologies.
> 
> Move this hunk into the patch that adds the file?

Was fixed in v10.2.
 

> > +++ b/arch/arm64/kernel/relocate_kernel.S

> If I've followed all this through properly:
> 
> With KVM - mmu+caches are configured, but then disabled by 'kvm: allows kvm
> cpu hotplug'. This 'arm64_relocate_new_kernel' function then runs at EL2
> with M=0, C=0, I=0.
> 
> Without KVM - when there is no user of EL2, the mmu+caches are left in
> whatever state the bootloader (or efi stub) left them in. From
> Documentation/arm64/booting.txt:
> > Instruction cache may be on or off.
> and
> > System caches which respect the architected cache maintenance by VA
> > operations must be configured and may be enabled.
> 
> So 'arm64_relocate_new_kernel' function could run at EL2 with M=0, C=?, I=?.
> 
> I think this means you can't guarantee anything you are copying below
> actually makes it through the caches - booting secondary processors may get
> stale values.
> 
> The EFI stub disables the M and C bits when booted at EL2 with uefi - but
> it leaves the instruction cache enabled. You only clean the
> reboot_code_buffer from the data cache, so there may be stale values in the
> instruction cache.
> 
> I think you need to disable the i-cache at EL1. If you jump to EL2, I think
> you need to disable the I/C bits there too - as you can't rely on the code
> in 'kvm: allows kvm cpu hotplug' to do this in a non-kvm case.

For consistency across all code paths, we could put in something like this:

+       /* Clear SCTLR_ELx_FLAGS. */
+       mrs     x0, CurrentEL
+       cmp     x0, #CurrentEL_EL2
+       b.ne    1f
+       mrs     x0, sctlr_el2
+       ldr     x1, =SCTLR_EL2_FLAGS
+       bic     x0, x0, x1
+       msr     sctlr_el2, x0
+       isb
+       b       2f
+1:     mrs     x0, sctlr_el1
+       ldr     x1, =SCTLR_EL2_FLAGS
+       bic     x0, x0, x1
+       msr     sctlr_el1, x0
+       isb



> > +.Ldone:
> > +> > 	> > dsb> > 	> > sy
> > +> > 	> > isb
> > +> > 	> > ic> > 	> > ialluis
> > +> > 	> > dsb> > 	> > sy
> 
> Why the second dsb?

I removed the first isb as Mark suggested.


> 
> > +> > 	> > isb
> > +
> > +> > 	> > /* Start new image. */
> > +> > 	> > ldr> > 	> > x4, .Lkimage_start
> > +> > 	> > mov> > 	> > x0, xzr
> > +> > 	> > mov> > 	> > x1, xzr
> > +> > 	> > mov> > 	> > x2, xzr
> > +> > 	> > mov> > 	> > x3, xzr
> 
> Once the kexec'd kernel is booting, I get:
> > WARNING: x1-x3 nonzero in violation of boot protocol:
> >         x1: 0000000080008000
> >         x2: 0000000000000020
> >         x3: 0000000000000020
> > This indicates a broken bootloader or old kernel
> 
> Presumably this 'kimage_start' isn't pointing to the new kernel, but the
> purgatory code, (which comes from user-space?). (If so what are these xzr-s
> for?)

The warning was from the arm64 purgatory in kexec-tools, now fixed.

We don't need to zero the registers anymore.   At one time I had
an option where the kernel found the dtb section and jumped
directly to the new image as the 32 bit arm kernel does.

> +/* The machine_kexec routine sets these variables via offsets from
> > + * arm64_relocate_new_kernel.
> > + */
> > +
> > +/*
> > + * .Lkimage_start - Copy of image->start, the entry point of the new
> > + * image.
> > + */
> > +.Lkimage_start:
> > +> > 	> > .quad> > 	> > 0x0
> > +
> > +/*
> > + * .Lkimage_head - Copy of image->head, the list of kimage entries.
> > + */
> > +.Lkimage_head:
> > +> > 	> > .quad> > 	> > 0x0
> > +
> 
> I assume these .quad-s are used because you can't pass the values in via
> registers - due to the complicated soft_restart(). Given you are the only
> user, couldn't you simplify it to do all the disabling in
> arm64_relocate_new_kernel?

I moved some things from cpu_reset to arm64_relocate_new_kernel, but
from what Takahiro has said, to support a modular kvm some of the CPU
shutdown code will be shared.  Maybe we can look into simplifying things
once work on modular kvm is started.


> 
> From 'kexec -e' to the first messages from the new kernel takes ~1 minute
> on Juno, Did you see a similar delay? Or should I go looking for what I've
> configured wrong!?

As Pratyush has mentioned this is most likely due to the dcaches
being disabled.

> (Copying code with the mmu+caches on, then cleaning to PoC was noticeably
> faster for hibernate)
> 
> 
> I've used this series for kexec-ing between 4K and 64K page_size kernels on
> Juno.

Thanks for testing.

-Geoff

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH 08/16] arm64/kexec: Add core kexec support
@ 2015-11-03  0:30       ` Geoff Levand
  0 siblings, 0 replies; 72+ messages in thread
From: Geoff Levand @ 2015-11-03  0:30 UTC (permalink / raw)
  To: James Morse
  Cc: Mark Rutland, AKASHI, marc.zyngier, Catalin Marinas, Will Deacon,
	Takahiro, christoffer.dall, kexec, linux-arm-kernel

Hi James,

On Fri, 2015-10-30 at 16:29 +0000, James Morse wrote:
> On 20/10/15 00:38, Geoff Levand wrote:
> > +config KEXEC
> > +> > 	> > depends on (!SMP || PM_SLEEP_SMP)
> 
> Commit 4b3dc9679cf7 got rid of '!SMP'.

Fixed for v11.

> > - * Copyright (C) 2015 Huawei Futurewei Technologies.
> > + * Copyright (C) Huawei Futurewei Technologies.
> 
> Move this hunk into the patch that adds the file?

Was fixed in v10.2.
 

> > +++ b/arch/arm64/kernel/relocate_kernel.S

> If I've followed all this through properly:
> 
> With KVM - mmu+caches are configured, but then disabled by 'kvm: allows kvm
> cpu hotplug'. This 'arm64_relocate_new_kernel' function then runs at EL2
> with M=0, C=0, I=0.
> 
> Without KVM - when there is no user of EL2, the mmu+caches are left in
> whatever state the bootloader (or efi stub) left them in. From
> Documentation/arm64/booting.txt:
> > Instruction cache may be on or off.
> and
> > System caches which respect the architected cache maintenance by VA
> > operations must be configured and may be enabled.
> 
> So 'arm64_relocate_new_kernel' function could run at EL2 with M=0, C=?, I=?.
> 
> I think this means you can't guarantee anything you are copying below
> actually makes it through the caches - booting secondary processors may get
> stale values.
> 
> The EFI stub disables the M and C bits when booted at EL2 with uefi - but
> it leaves the instruction cache enabled. You only clean the
> reboot_code_buffer from the data cache, so there may be stale values in the
> instruction cache.
> 
> I think you need to disable the i-cache at EL1. If you jump to EL2, I think
> you need to disable the I/C bits there too - as you can't rely on the code
> in 'kvm: allows kvm cpu hotplug' to do this in a non-kvm case.

For consistency across all code paths, we could put in something like this:

+       /* Clear SCTLR_ELx_FLAGS. */
+       mrs     x0, CurrentEL
+       cmp     x0, #CurrentEL_EL2
+       b.ne    1f
+       mrs     x0, sctlr_el2
+       ldr     x1, =SCTLR_EL2_FLAGS
+       bic     x0, x0, x1
+       msr     sctlr_el2, x0
+       isb
+       b       2f
+1:     mrs     x0, sctlr_el1
+       ldr     x1, =SCTLR_EL2_FLAGS
+       bic     x0, x0, x1
+       msr     sctlr_el1, x0
+       isb



> > +.Ldone:
> > +> > 	> > dsb> > 	> > sy
> > +> > 	> > isb
> > +> > 	> > ic> > 	> > ialluis
> > +> > 	> > dsb> > 	> > sy
> 
> Why the second dsb?

I removed the first isb as Mark suggested.


> 
> > +> > 	> > isb
> > +
> > +> > 	> > /* Start new image. */
> > +> > 	> > ldr> > 	> > x4, .Lkimage_start
> > +> > 	> > mov> > 	> > x0, xzr
> > +> > 	> > mov> > 	> > x1, xzr
> > +> > 	> > mov> > 	> > x2, xzr
> > +> > 	> > mov> > 	> > x3, xzr
> 
> Once the kexec'd kernel is booting, I get:
> > WARNING: x1-x3 nonzero in violation of boot protocol:
> >         x1: 0000000080008000
> >         x2: 0000000000000020
> >         x3: 0000000000000020
> > This indicates a broken bootloader or old kernel
> 
> Presumably this 'kimage_start' isn't pointing to the new kernel, but the
> purgatory code, (which comes from user-space?). (If so what are these xzr-s
> for?)

The warning was from the arm64 purgatory in kexec-tools, now fixed.

We don't need to zero the registers anymore.   At one time I had
an option where the kernel found the dtb section and jumped
directly to the new image as the 32 bit arm kernel does.

> +/* The machine_kexec routine sets these variables via offsets from
> > + * arm64_relocate_new_kernel.
> > + */
> > +
> > +/*
> > + * .Lkimage_start - Copy of image->start, the entry point of the new
> > + * image.
> > + */
> > +.Lkimage_start:
> > +> > 	> > .quad> > 	> > 0x0
> > +
> > +/*
> > + * .Lkimage_head - Copy of image->head, the list of kimage entries.
> > + */
> > +.Lkimage_head:
> > +> > 	> > .quad> > 	> > 0x0
> > +
> 
> I assume these .quad-s are used because you can't pass the values in via
> registers - due to the complicated soft_restart(). Given you are the only
> user, couldn't you simplify it to do all the disabling in
> arm64_relocate_new_kernel?

I moved some things from cpu_reset to arm64_relocate_new_kernel, but
from what Takahiro has said, to support a modular kvm some of the CPU
shutdown code will be shared.  Maybe we can look into simplifying things
once work on modular kvm is started.


> 
> From 'kexec -e' to the first messages from the new kernel takes ~1 minute
> on Juno, Did you see a similar delay? Or should I go looking for what I've
> configured wrong!?

As Pratyush has mentioned this is most likely due to the dcaches
being disabled.

> (Copying code with the mmu+caches on, then cleaning to PoC was noticeably
> faster for hibernate)
> 
> 
> I've used this series for kexec-ing between 4K and 64K page_size kernels on
> Juno.

Thanks for testing.

-Geoff


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 72+ messages in thread

end of thread, other threads:[~2015-11-03  0:30 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-19 23:38 [PATCH 00/16] arm64 kexec kernel patches v10 Geoff Levand
2015-10-19 23:38 ` Geoff Levand
2015-10-19 23:38 ` [PATCH 07/16] Revert "arm64: remove dead code" Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 01/16] arm64: Fold proc-macros.S into assembler.h Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 03/16] arm64: Add new hcall HVC_CALL_FUNC Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 02/16] arm64: Convert hcalls to use HVC immediate value Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 08/16] arm64/kexec: Add core kexec support Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-20  8:56   ` Pratyush Anand
2015-10-20  8:56     ` Pratyush Anand
2015-10-20 17:19     ` Geoff Levand
2015-10-20 17:19       ` Geoff Levand
2015-10-23  7:29       ` Pratyush Anand
2015-10-23  7:29         ` Pratyush Anand
2015-10-21 18:30   ` [PATCH v10.2 " Geoff Levand
2015-10-21 18:30     ` Geoff Levand
2015-10-30 16:29   ` [PATCH " James Morse
2015-10-30 16:29     ` James Morse
2015-10-30 16:54     ` Mark Rutland
2015-10-30 16:54       ` Mark Rutland
2015-11-02  9:26     ` Pratyush Anand
2015-11-02  9:26       ` Pratyush Anand
2015-11-03  0:30     ` Geoff Levand
2015-11-03  0:30       ` Geoff Levand
2015-10-19 23:38 ` [PATCH 06/16] arm64: Add EL2 switch to cpu_reset Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 04/16] arm64: kvm: allows kvm cpu hotplug Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-20 18:57   ` [PATCH v10.1 " Geoff Levand
2015-10-20 18:57     ` Geoff Levand
2015-10-19 23:38 ` [PATCH 05/16] arm64: Add back cpu_reset routines Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 15/16] arm64: kdump: enable kdump in the arm64 defconfig Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 11/16] arm64: kdump: reserve memory for crash dump kernel Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 14/16] arm64: kdump: update a kernel doc Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 09/16] arm64/kexec: Add pr_devel output Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 16/16] arm64: kdump: relax BUG_ON() if more than one cpus are still active Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 13/16] arm64: kdump: add kdump support Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-22  3:25   ` Dave Young
2015-10-22  3:25     ` Dave Young
2015-10-22  4:29     ` AKASHI Takahiro
2015-10-22  4:29       ` AKASHI Takahiro
2015-10-22  5:15       ` Dave Young
2015-10-22  5:15         ` Dave Young
2015-10-22  9:57         ` AKASHI Takahiro
2015-10-22  9:57           ` AKASHI Takahiro
2015-10-23  9:50           ` Dave Young
2015-10-23  9:50             ` Dave Young
2015-10-29  5:55             ` AKASHI Takahiro
2015-10-29  5:55               ` AKASHI Takahiro
2015-10-29  6:40               ` Dave Young
2015-10-29  6:40                 ` Dave Young
2015-10-29  6:53                 ` AKASHI Takahiro
2015-10-29  6:53                   ` AKASHI Takahiro
2015-10-29  7:01                   ` Dave Young
2015-10-29  7:01                     ` Dave Young
2015-10-19 23:38 ` [PATCH 10/16] arm64/kexec: Enable kexec in the arm64 defconfig Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-19 23:38 ` [PATCH 12/16] arm64: kdump: implement machine_crash_shutdown() Geoff Levand
2015-10-19 23:38   ` Geoff Levand
2015-10-20 18:54   ` [PATCH v10.1 " Geoff Levand
2015-10-20 18:54     ` Geoff Levand

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.