All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v27 0/9] arm64: add kdump support
@ 2016-11-02  4:49 ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:49 UTC (permalink / raw)
  To: linux-arm-kernel

    v27-specific note: In this version, the change made in v26 was reverted
    because I've got a comment that /reserved-memory DT property should
    not be used on UEFI/ACPI systems, even though it is workable under
    the current implementation. I've also confirmed that Rob doesn't argue
    any more against using "linux,usable-memory-range".
    So v27 is essentially the same as v25.

This patch series adds kdump support on arm64.

To load a crash-dump kernel to the systems, a series of patches to
kexec-tools[1] are also needed. Please use the latest one, v4 [2].

To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
  - crash utility (v7.1.6 or later) [3]


[1] https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
[1] http://lists.infradead.org/pipermail/kexec/2016-November/017555.html
[2] https://github.com/crash-utility/crash.git

Changes for v27 (Nov 2, 2016)
  o rebased to Linux-v4.9-rc3
  o revert v26 change, i.e. revive "linux,usable-memory-range" property
    (patch #2/#3, updating patch #9)
  o minor fixes per review comments (patch #3/#4/#6/#8)
  o re-order patches and improve commit messages for readability

Changes for v26 (Sep 7, 2016):
  o Use /reserved-memory instead of "linux,usable-memory-range" property
    (dropping v25's patch#2 and #3, updating ex-patch#9.)

Changes for v25 (Aug 29, 2016):
  o Rebase to Linux-4.8-rc4
  o Use memremap() instead of ioremap_cache() [patch#5]

Changes for v24 (Aug 9, 2016):
  o Rebase to Linux-4.8-rc1
  o Update descriptions about newly added DT proerties

Changes for v23 (July 26, 2016):

  o Move memblock_reserve() to a single place in reserve_crashkernel()
  o Use  cpu_park_loop() in ipi_cpu_crash_stop()
  o Always enforce ARCH_LOW_ADDRESS_LIMIT to the memory range of crash kernel
  o Re-implement fdt_enforce_memory_region() to remove non-reserve regions
    (for ACPI) from usable memory at crash kernel

Changes for v22 (July 12, 2016):

  o Export "crashkernel-base" and "crashkernel-size" via device-tree,
    and add some descriptions about them in chosen.txt
  o Rename "usable-memory" to "usable-memory-range" to avoid inconsistency
    with powerpc's "usable-memory"
  o Make cosmetic changes regarding "ifdef" usage
  o Correct some wordings in kdump.txt

Changes for v21 (July 6, 2016):

  o Remove kexec patches.
  o Rebase to arm64's for-next/core (Linux-4.7-rc4 based).
  o Clarify the description about kvm in kdump.txt.

See the following link [3] for older changes:
[3]  http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438780.html

AKASHI Takahiro (8):
  memblock: add memblock_cap_memory_range()
  arm64: limit memory regions based on DT property, usable-memory-range
  arm64: kdump: reserve memory for crash dump kernel
  arm64: kdump: implement machine_crash_shutdown()
  arm64: kdump: add VMCOREINFO's for user-space tools
  arm64: kdump: provide /proc/vmcore file
  arm64: kdump: enable kdump in defconfig
  Documentation: kdump: describe arm64 port

James Morse (1):
  Documentation: dt: chosen properties for arm64 kdump

 Documentation/devicetree/bindings/chosen.txt |  50 +++++++
 Documentation/kdump/kdump.txt                |  16 ++-
 arch/arm64/Kconfig                           |  11 ++
 arch/arm64/configs/defconfig                 |   1 +
 arch/arm64/include/asm/hardirq.h             |   2 +-
 arch/arm64/include/asm/kexec.h               |  42 +++++-
 arch/arm64/include/asm/smp.h                 |   2 +
 arch/arm64/kernel/Makefile                   |   1 +
 arch/arm64/kernel/crash_dump.c               |  71 ++++++++++
 arch/arm64/kernel/machine_kexec.c            |  67 ++++++++-
 arch/arm64/kernel/setup.c                    |   7 +-
 arch/arm64/kernel/smp.c                      |  63 +++++++++
 arch/arm64/mm/init.c                         | 199 +++++++++++++++++++++++++++
 include/linux/memblock.h                     |   1 +
 mm/memblock.c                                |  28 ++++
 15 files changed, 554 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm64/kernel/crash_dump.c

-- 
2.10.0

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

* [PATCH v27 0/9] arm64: add kdump support
@ 2016-11-02  4:49 ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:49 UTC (permalink / raw)
  To: catalin.marinas, will.deacon
  Cc: mark.rutland, geoff, kexec, AKASHI Takahiro, james.morse,
	bauerman, dyoung, linux-arm-kernel

    v27-specific note: In this version, the change made in v26 was reverted
    because I've got a comment that /reserved-memory DT property should
    not be used on UEFI/ACPI systems, even though it is workable under
    the current implementation. I've also confirmed that Rob doesn't argue
    any more against using "linux,usable-memory-range".
    So v27 is essentially the same as v25.

This patch series adds kdump support on arm64.

To load a crash-dump kernel to the systems, a series of patches to
kexec-tools[1] are also needed. Please use the latest one, v4 [2].

To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
  - crash utility (v7.1.6 or later) [3]


[1] https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
[1] http://lists.infradead.org/pipermail/kexec/2016-November/017555.html
[2] https://github.com/crash-utility/crash.git

Changes for v27 (Nov 2, 2016)
  o rebased to Linux-v4.9-rc3
  o revert v26 change, i.e. revive "linux,usable-memory-range" property
    (patch #2/#3, updating patch #9)
  o minor fixes per review comments (patch #3/#4/#6/#8)
  o re-order patches and improve commit messages for readability

Changes for v26 (Sep 7, 2016):
  o Use /reserved-memory instead of "linux,usable-memory-range" property
    (dropping v25's patch#2 and #3, updating ex-patch#9.)

Changes for v25 (Aug 29, 2016):
  o Rebase to Linux-4.8-rc4
  o Use memremap() instead of ioremap_cache() [patch#5]

Changes for v24 (Aug 9, 2016):
  o Rebase to Linux-4.8-rc1
  o Update descriptions about newly added DT proerties

Changes for v23 (July 26, 2016):

  o Move memblock_reserve() to a single place in reserve_crashkernel()
  o Use  cpu_park_loop() in ipi_cpu_crash_stop()
  o Always enforce ARCH_LOW_ADDRESS_LIMIT to the memory range of crash kernel
  o Re-implement fdt_enforce_memory_region() to remove non-reserve regions
    (for ACPI) from usable memory at crash kernel

Changes for v22 (July 12, 2016):

  o Export "crashkernel-base" and "crashkernel-size" via device-tree,
    and add some descriptions about them in chosen.txt
  o Rename "usable-memory" to "usable-memory-range" to avoid inconsistency
    with powerpc's "usable-memory"
  o Make cosmetic changes regarding "ifdef" usage
  o Correct some wordings in kdump.txt

Changes for v21 (July 6, 2016):

  o Remove kexec patches.
  o Rebase to arm64's for-next/core (Linux-4.7-rc4 based).
  o Clarify the description about kvm in kdump.txt.

See the following link [3] for older changes:
[3]  http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438780.html

AKASHI Takahiro (8):
  memblock: add memblock_cap_memory_range()
  arm64: limit memory regions based on DT property, usable-memory-range
  arm64: kdump: reserve memory for crash dump kernel
  arm64: kdump: implement machine_crash_shutdown()
  arm64: kdump: add VMCOREINFO's for user-space tools
  arm64: kdump: provide /proc/vmcore file
  arm64: kdump: enable kdump in defconfig
  Documentation: kdump: describe arm64 port

James Morse (1):
  Documentation: dt: chosen properties for arm64 kdump

 Documentation/devicetree/bindings/chosen.txt |  50 +++++++
 Documentation/kdump/kdump.txt                |  16 ++-
 arch/arm64/Kconfig                           |  11 ++
 arch/arm64/configs/defconfig                 |   1 +
 arch/arm64/include/asm/hardirq.h             |   2 +-
 arch/arm64/include/asm/kexec.h               |  42 +++++-
 arch/arm64/include/asm/smp.h                 |   2 +
 arch/arm64/kernel/Makefile                   |   1 +
 arch/arm64/kernel/crash_dump.c               |  71 ++++++++++
 arch/arm64/kernel/machine_kexec.c            |  67 ++++++++-
 arch/arm64/kernel/setup.c                    |   7 +-
 arch/arm64/kernel/smp.c                      |  63 +++++++++
 arch/arm64/mm/init.c                         | 199 +++++++++++++++++++++++++++
 include/linux/memblock.h                     |   1 +
 mm/memblock.c                                |  28 ++++
 15 files changed, 554 insertions(+), 7 deletions(-)
 create mode 100644 arch/arm64/kernel/crash_dump.c

-- 
2.10.0


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

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
  2016-11-02  4:49 ` AKASHI Takahiro
  (?)
@ 2016-11-02  4:51   ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:51 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, akpm
  Cc: james.morse, geoff, bauerman, dyoung, mark.rutland, kexec,
	linux-arm-kernel, linux-mm, AKASHI Takahiro

Add memblock_cap_memory_range() which will remove all the memblock regions
except the range specified in the arguments.

This function, like memblock_mem_limit_remove_map(), will not remove
memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
later as "device memory."
See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
address the mem limit issue").

This function is used, in a succeeding patch in the series of arm64 kdump
suuport, to limit the range of usable memory, System RAM, on crash dump
kernel.
(Please note that "mem=" parameter is of little use for this purpose.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Cc: linux-mm@kvack.org
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 include/linux/memblock.h |  1 +
 mm/memblock.c            | 28 ++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 5b759c9..0e770af 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
 phys_addr_t memblock_end_of_DRAM(void);
 void memblock_enforce_memory_limit(phys_addr_t memory_limit);
 void memblock_mem_limit_remove_map(phys_addr_t limit);
+void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
 bool memblock_is_memory(phys_addr_t addr);
 int memblock_is_map_memory(phys_addr_t addr);
 int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
diff --git a/mm/memblock.c b/mm/memblock.c
index 7608bc3..eb53876 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
 			      (phys_addr_t)ULLONG_MAX);
 }
 
+void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
+{
+	int start_rgn, end_rgn;
+	int i, ret;
+
+	if (!size)
+		return;
+
+	ret = memblock_isolate_range(&memblock.memory, base, size,
+						&start_rgn, &end_rgn);
+	if (ret)
+		return;
+
+	/* remove all the MAP regions */
+	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	for (i = start_rgn - 1; i >= 0; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	/* truncate the reserved regions */
+	memblock_remove_range(&memblock.reserved, 0, base);
+	memblock_remove_range(&memblock.reserved,
+			base + size, (phys_addr_t)ULLONG_MAX);
+}
+
 static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
 {
 	unsigned int left = 0, right = type->cnt;
-- 
2.10.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-02  4:51   ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:51 UTC (permalink / raw)
  To: linux-arm-kernel

Add memblock_cap_memory_range() which will remove all the memblock regions
except the range specified in the arguments.

This function, like memblock_mem_limit_remove_map(), will not remove
memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
later as "device memory."
See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
address the mem limit issue").

This function is used, in a succeeding patch in the series of arm64 kdump
suuport, to limit the range of usable memory, System RAM, on crash dump
kernel.
(Please note that "mem=" parameter is of little use for this purpose.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Cc: linux-mm at kvack.org
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 include/linux/memblock.h |  1 +
 mm/memblock.c            | 28 ++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 5b759c9..0e770af 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
 phys_addr_t memblock_end_of_DRAM(void);
 void memblock_enforce_memory_limit(phys_addr_t memory_limit);
 void memblock_mem_limit_remove_map(phys_addr_t limit);
+void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
 bool memblock_is_memory(phys_addr_t addr);
 int memblock_is_map_memory(phys_addr_t addr);
 int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
diff --git a/mm/memblock.c b/mm/memblock.c
index 7608bc3..eb53876 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
 			      (phys_addr_t)ULLONG_MAX);
 }
 
+void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
+{
+	int start_rgn, end_rgn;
+	int i, ret;
+
+	if (!size)
+		return;
+
+	ret = memblock_isolate_range(&memblock.memory, base, size,
+						&start_rgn, &end_rgn);
+	if (ret)
+		return;
+
+	/* remove all the MAP regions */
+	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	for (i = start_rgn - 1; i >= 0; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	/* truncate the reserved regions */
+	memblock_remove_range(&memblock.reserved, 0, base);
+	memblock_remove_range(&memblock.reserved,
+			base + size, (phys_addr_t)ULLONG_MAX);
+}
+
 static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
 {
 	unsigned int left = 0, right = type->cnt;
-- 
2.10.0

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-02  4:51   ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:51 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, akpm
  Cc: mark.rutland, AKASHI Takahiro, geoff, kexec, linux-mm,
	james.morse, bauerman, dyoung, linux-arm-kernel

Add memblock_cap_memory_range() which will remove all the memblock regions
except the range specified in the arguments.

This function, like memblock_mem_limit_remove_map(), will not remove
memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
later as "device memory."
See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
address the mem limit issue").

This function is used, in a succeeding patch in the series of arm64 kdump
suuport, to limit the range of usable memory, System RAM, on crash dump
kernel.
(Please note that "mem=" parameter is of little use for this purpose.)

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Cc: linux-mm@kvack.org
Cc: Andrew Morton <akpm@linux-foundation.org>
---
 include/linux/memblock.h |  1 +
 mm/memblock.c            | 28 ++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 5b759c9..0e770af 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
 phys_addr_t memblock_end_of_DRAM(void);
 void memblock_enforce_memory_limit(phys_addr_t memory_limit);
 void memblock_mem_limit_remove_map(phys_addr_t limit);
+void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
 bool memblock_is_memory(phys_addr_t addr);
 int memblock_is_map_memory(phys_addr_t addr);
 int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
diff --git a/mm/memblock.c b/mm/memblock.c
index 7608bc3..eb53876 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
 			      (phys_addr_t)ULLONG_MAX);
 }
 
+void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
+{
+	int start_rgn, end_rgn;
+	int i, ret;
+
+	if (!size)
+		return;
+
+	ret = memblock_isolate_range(&memblock.memory, base, size,
+						&start_rgn, &end_rgn);
+	if (ret)
+		return;
+
+	/* remove all the MAP regions */
+	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	for (i = start_rgn - 1; i >= 0; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	/* truncate the reserved regions */
+	memblock_remove_range(&memblock.reserved, 0, base);
+	memblock_remove_range(&memblock.reserved,
+			base + size, (phys_addr_t)ULLONG_MAX);
+}
+
 static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
 {
 	unsigned int left = 0, right = type->cnt;
-- 
2.10.0


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

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

* [PATCH v27 2/9] arm64: limit memory regions based on DT property, usable-memory-range
  2016-11-02  4:49 ` AKASHI Takahiro
@ 2016-11-02  4:52   ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: linux-arm-kernel

Crash dump kernel utilizes only a subset of available memory as System RAM.
On arm64 kdump, This memory range is advertized to crash dump kernel via
a device-tree property under /chosen,
   linux,usable-memory-range = <BASE SIZE>

Crash dump kernel reads this property at boot time and calls
memblock_cap_memory_range() to limit usable memory ranges which are
described as entries in UEFI memory map table or "memory" nodes in
a device tree blob.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/mm/init.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 212c4d1..65f1241 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -187,10 +187,45 @@ static int __init early_mem(char *p)
 }
 early_param("mem", early_mem);
 
+static int __init early_init_dt_scan_usablemem(unsigned long node,
+		const char *uname, int depth, void *data)
+{
+	struct memblock_region *usablemem = (struct memblock_region *)data;
+	const __be32 *reg;
+	int len;
+
+	usablemem->size = 0;
+
+	if (depth != 1 || strcmp(uname, "chosen") != 0)
+		return 0;
+
+	reg = of_get_flat_dt_prop(node, "linux,usable-memory-range", &len);
+	if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells)))
+		return 1;
+
+	usablemem->base = dt_mem_next_cell(dt_root_addr_cells, &reg);
+	usablemem->size = dt_mem_next_cell(dt_root_size_cells, &reg);
+
+	return 1;
+}
+
+static void __init fdt_enforce_memory_region(void)
+{
+	struct memblock_region reg;
+
+	of_scan_flat_dt(early_init_dt_scan_usablemem, &reg);
+
+	if (reg.size)
+		memblock_cap_memory_range(reg.base, reg.size);
+}
+
 void __init arm64_memblock_init(void)
 {
 	const s64 linear_region_size = -(s64)PAGE_OFFSET;
 
+	/* Handle linux,usable-memory-range property */
+	fdt_enforce_memory_region();
+
 	/*
 	 * Ensure that the linear region takes up exactly half of the kernel
 	 * virtual address space. This way, we can distinguish a linear address
-- 
2.10.0

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

* [PATCH v27 2/9] arm64: limit memory regions based on DT property, usable-memory-range
@ 2016-11-02  4:52   ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: catalin.marinas, will.deacon
  Cc: mark.rutland, geoff, kexec, AKASHI Takahiro, james.morse,
	bauerman, dyoung, linux-arm-kernel

Crash dump kernel utilizes only a subset of available memory as System RAM.
On arm64 kdump, This memory range is advertized to crash dump kernel via
a device-tree property under /chosen,
   linux,usable-memory-range = <BASE SIZE>

Crash dump kernel reads this property at boot time and calls
memblock_cap_memory_range() to limit usable memory ranges which are
described as entries in UEFI memory map table or "memory" nodes in
a device tree blob.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Geoff Levand <geoff@infradead.org>
---
 arch/arm64/mm/init.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 212c4d1..65f1241 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -187,10 +187,45 @@ static int __init early_mem(char *p)
 }
 early_param("mem", early_mem);
 
+static int __init early_init_dt_scan_usablemem(unsigned long node,
+		const char *uname, int depth, void *data)
+{
+	struct memblock_region *usablemem = (struct memblock_region *)data;
+	const __be32 *reg;
+	int len;
+
+	usablemem->size = 0;
+
+	if (depth != 1 || strcmp(uname, "chosen") != 0)
+		return 0;
+
+	reg = of_get_flat_dt_prop(node, "linux,usable-memory-range", &len);
+	if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells)))
+		return 1;
+
+	usablemem->base = dt_mem_next_cell(dt_root_addr_cells, &reg);
+	usablemem->size = dt_mem_next_cell(dt_root_size_cells, &reg);
+
+	return 1;
+}
+
+static void __init fdt_enforce_memory_region(void)
+{
+	struct memblock_region reg;
+
+	of_scan_flat_dt(early_init_dt_scan_usablemem, &reg);
+
+	if (reg.size)
+		memblock_cap_memory_range(reg.base, reg.size);
+}
+
 void __init arm64_memblock_init(void)
 {
 	const s64 linear_region_size = -(s64)PAGE_OFFSET;
 
+	/* Handle linux,usable-memory-range property */
+	fdt_enforce_memory_region();
+
 	/*
 	 * Ensure that the linear region takes up exactly half of the kernel
 	 * virtual address space. This way, we can distinguish a linear address
-- 
2.10.0


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

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

* [PATCH v27 3/9] arm64: kdump: reserve memory for crash dump kernel
  2016-11-02  4:49 ` AKASHI Takahiro
@ 2016-11-02  4:52   ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: linux-arm-kernel

"crashkernel=" kernel parameter specifies the size (and optionally
the start address) of the system ram used by crash dump kernel.
reserve_crashkernel() will allocate and reserve the memory at the startup
of primary kernel.

This memory range will be exported to userspace via:
	- an entry named "Crash kernel" in /proc/iomem, and
	- "linux,crashkernel-base" and "linux,crashkernel-size" under
	  /sys/firmware/devicetree/base/chosen

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Pratyush Anand <panand@redhat.com>
Reviewed-by: James Morse <james.morse@arm.com>
---
 arch/arm64/kernel/setup.c |   7 ++-
 arch/arm64/mm/init.c      | 110 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index f534f49..f012659 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -31,7 +31,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>
@@ -225,6 +224,12 @@ static void __init request_standard_resources(void)
 		    kernel_data.end <= res->end)
 			request_resource(res, &kernel_data);
 	}
+
+#ifdef CONFIG_KEXEC_CORE
+	/* User space tools will find "Crash kernel" region in /proc/iomem. */
+	if (crashk_res.end)
+		insert_resource(&iomem_resource, &crashk_res);
+#endif
 }
 
 u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 65f1241..1d62bf7 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -30,12 +30,14 @@
 #include <linux/gfp.h>
 #include <linux/memblock.h>
 #include <linux/sort.h>
+#include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
 #include <linux/efi.h>
 #include <linux/swiotlb.h>
 #include <linux/vmalloc.h>
+#include <linux/kexec.h>
 
 #include <asm/boot.h>
 #include <asm/fixmap.h>
@@ -76,6 +78,111 @@ static int __init early_initrd(char *p)
 early_param("initrd", early_initrd);
 #endif
 
+#ifdef CONFIG_KEXEC_CORE
+static unsigned long long crash_size, crash_base;
+static struct property crash_base_prop = {
+	.name = "linux,crashkernel-base",
+	.length = sizeof(u64),
+	.value = &crash_base
+};
+static struct property crash_size_prop = {
+	.name = "linux,crashkernel-size",
+	.length = sizeof(u64),
+	.value = &crash_size,
+};
+
+static int __init export_crashkernel(void)
+{
+	struct device_node *node;
+	int ret;
+
+	if (!crash_size)
+		return 0;
+
+	/* Add /chosen/linux,crashkernel-* properties */
+	node = of_find_node_by_path("/chosen");
+	if (!node)
+		return -ENOENT;
+
+	/*
+	 * There might be existing crash kernel properties, but we can't
+	 * be sure what's in them, so remove them.
+	 */
+	of_remove_property(node, of_find_property(node,
+				"linux,crashkernel-base", NULL));
+	of_remove_property(node, of_find_property(node,
+				"linux,crashkernel-size", NULL));
+
+	ret = of_add_property(node, &crash_base_prop);
+	if (ret)
+		goto ret_err;
+
+	ret = of_add_property(node, &crash_size_prop);
+	if (ret)
+		goto ret_err;
+
+	return 0;
+
+ret_err:
+	pr_warn("Exporting crashkernel region to device tree failed\n");
+	return ret;
+}
+late_initcall(export_crashkernel);
+
+/*
+ * 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)
+{
+	int ret;
+
+	ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
+				&crash_size, &crash_base);
+	/* no crashkernel= or invalid value specified */
+	if (ret || !crash_size)
+		return;
+
+	if (crash_base == 0) {
+		/* Current arm64 boot protocol requires 2MB alignment */
+		crash_base = memblock_find_in_range(0, ARCH_LOW_ADDRESS_LIMIT,
+				crash_size, SZ_2M);
+		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 (!IS_ALIGNED(crash_base, SZ_2M)) {
+			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;
+}
+#else
+static void __init reserve_crashkernel(void)
+{
+	;
+}
+#endif /* CONFIG_KEXEC_CORE */
+
 /*
  * 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
@@ -331,6 +438,9 @@ void __init arm64_memblock_init(void)
 		arm64_dma_phys_limit = max_zone_dma_phys();
 	else
 		arm64_dma_phys_limit = PHYS_MASK + 1;
+
+	reserve_crashkernel();
+
 	dma_contiguous_reserve(arm64_dma_phys_limit);
 
 	memblock_allow_resize();
-- 
2.10.0

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

* [PATCH v27 3/9] arm64: kdump: reserve memory for crash dump kernel
@ 2016-11-02  4:52   ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: catalin.marinas, will.deacon
  Cc: mark.rutland, Pratyush Anand, geoff, kexec, AKASHI Takahiro,
	james.morse, Mark Salter, bauerman, dyoung, linux-arm-kernel

"crashkernel=" kernel parameter specifies the size (and optionally
the start address) of the system ram used by crash dump kernel.
reserve_crashkernel() will allocate and reserve the memory at the startup
of primary kernel.

This memory range will be exported to userspace via:
	- an entry named "Crash kernel" in /proc/iomem, and
	- "linux,crashkernel-base" and "linux,crashkernel-size" under
	  /sys/firmware/devicetree/base/chosen

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Pratyush Anand <panand@redhat.com>
Reviewed-by: James Morse <james.morse@arm.com>
---
 arch/arm64/kernel/setup.c |   7 ++-
 arch/arm64/mm/init.c      | 110 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index f534f49..f012659 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -31,7 +31,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>
@@ -225,6 +224,12 @@ static void __init request_standard_resources(void)
 		    kernel_data.end <= res->end)
 			request_resource(res, &kernel_data);
 	}
+
+#ifdef CONFIG_KEXEC_CORE
+	/* User space tools will find "Crash kernel" region in /proc/iomem. */
+	if (crashk_res.end)
+		insert_resource(&iomem_resource, &crashk_res);
+#endif
 }
 
 u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 65f1241..1d62bf7 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -30,12 +30,14 @@
 #include <linux/gfp.h>
 #include <linux/memblock.h>
 #include <linux/sort.h>
+#include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-contiguous.h>
 #include <linux/efi.h>
 #include <linux/swiotlb.h>
 #include <linux/vmalloc.h>
+#include <linux/kexec.h>
 
 #include <asm/boot.h>
 #include <asm/fixmap.h>
@@ -76,6 +78,111 @@ static int __init early_initrd(char *p)
 early_param("initrd", early_initrd);
 #endif
 
+#ifdef CONFIG_KEXEC_CORE
+static unsigned long long crash_size, crash_base;
+static struct property crash_base_prop = {
+	.name = "linux,crashkernel-base",
+	.length = sizeof(u64),
+	.value = &crash_base
+};
+static struct property crash_size_prop = {
+	.name = "linux,crashkernel-size",
+	.length = sizeof(u64),
+	.value = &crash_size,
+};
+
+static int __init export_crashkernel(void)
+{
+	struct device_node *node;
+	int ret;
+
+	if (!crash_size)
+		return 0;
+
+	/* Add /chosen/linux,crashkernel-* properties */
+	node = of_find_node_by_path("/chosen");
+	if (!node)
+		return -ENOENT;
+
+	/*
+	 * There might be existing crash kernel properties, but we can't
+	 * be sure what's in them, so remove them.
+	 */
+	of_remove_property(node, of_find_property(node,
+				"linux,crashkernel-base", NULL));
+	of_remove_property(node, of_find_property(node,
+				"linux,crashkernel-size", NULL));
+
+	ret = of_add_property(node, &crash_base_prop);
+	if (ret)
+		goto ret_err;
+
+	ret = of_add_property(node, &crash_size_prop);
+	if (ret)
+		goto ret_err;
+
+	return 0;
+
+ret_err:
+	pr_warn("Exporting crashkernel region to device tree failed\n");
+	return ret;
+}
+late_initcall(export_crashkernel);
+
+/*
+ * 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)
+{
+	int ret;
+
+	ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
+				&crash_size, &crash_base);
+	/* no crashkernel= or invalid value specified */
+	if (ret || !crash_size)
+		return;
+
+	if (crash_base == 0) {
+		/* Current arm64 boot protocol requires 2MB alignment */
+		crash_base = memblock_find_in_range(0, ARCH_LOW_ADDRESS_LIMIT,
+				crash_size, SZ_2M);
+		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 (!IS_ALIGNED(crash_base, SZ_2M)) {
+			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;
+}
+#else
+static void __init reserve_crashkernel(void)
+{
+	;
+}
+#endif /* CONFIG_KEXEC_CORE */
+
 /*
  * 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
@@ -331,6 +438,9 @@ void __init arm64_memblock_init(void)
 		arm64_dma_phys_limit = max_zone_dma_phys();
 	else
 		arm64_dma_phys_limit = PHYS_MASK + 1;
+
+	reserve_crashkernel();
+
 	dma_contiguous_reserve(arm64_dma_phys_limit);
 
 	memblock_allow_resize();
-- 
2.10.0


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

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

* [PATCH v27 4/9] arm64: kdump: implement machine_crash_shutdown()
  2016-11-02  4:49 ` AKASHI Takahiro
@ 2016-11-02  4:52   ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: linux-arm-kernel

Primary kernel calls machine_crash_shutdown() to shut down non-boot cpus
and save registers' status in per-cpu ELF notes before starting crash
dump kernel. See kernel_kexec().
Even if not all secondary cpus have shut down, we do kdump anyway.

As we don't have to make non-boot(crashed) cpus offline (to preserve
correct status of cpus at crash dump) before shutting down, this patch
also adds a variant of smp_send_stop().

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: James Morse <james.morse@arm.com>
---
 arch/arm64/include/asm/hardirq.h  |  2 +-
 arch/arm64/include/asm/kexec.h    | 42 +++++++++++++++++++++++++-
 arch/arm64/include/asm/smp.h      |  2 ++
 arch/arm64/kernel/machine_kexec.c | 56 ++++++++++++++++++++++++++++++++--
 arch/arm64/kernel/smp.c           | 63 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 160 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h
index 8740297..1473fc2 100644
--- a/arch/arm64/include/asm/hardirq.h
+++ b/arch/arm64/include/asm/hardirq.h
@@ -20,7 +20,7 @@
 #include <linux/threads.h>
 #include <asm/irq.h>
 
-#define NR_IPI	6
+#define NR_IPI	7
 
 typedef struct {
 	unsigned int __softirq_pending;
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 04744dc..b5168e8 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -40,7 +40,47 @@
 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 {
+		u64 tmp1, tmp2;
+
+		__asm__ __volatile__ (
+			"stp	 x0,   x1, [%2, #16 *  0]\n"
+			"stp	 x2,   x3, [%2, #16 *  1]\n"
+			"stp	 x4,   x5, [%2, #16 *  2]\n"
+			"stp	 x6,   x7, [%2, #16 *  3]\n"
+			"stp	 x8,   x9, [%2, #16 *  4]\n"
+			"stp	x10,  x11, [%2, #16 *  5]\n"
+			"stp	x12,  x13, [%2, #16 *  6]\n"
+			"stp	x14,  x15, [%2, #16 *  7]\n"
+			"stp	x16,  x17, [%2, #16 *  8]\n"
+			"stp	x18,  x19, [%2, #16 *  9]\n"
+			"stp	x20,  x21, [%2, #16 * 10]\n"
+			"stp	x22,  x23, [%2, #16 * 11]\n"
+			"stp	x24,  x25, [%2, #16 * 12]\n"
+			"stp	x26,  x27, [%2, #16 * 13]\n"
+			"stp	x28,  x29, [%2, #16 * 14]\n"
+			"mov	 %0,  sp\n"
+			"stp	x30,  %0,  [%2, #16 * 15]\n"
+
+			"/* faked current PSTATE */\n"
+			"mrs	 %0, CurrentEL\n"
+			"mrs	 %1, SPSEL\n"
+			"orr	 %0, %0, %1\n"
+			"mrs	 %1, DAIF\n"
+			"orr	 %0, %0, %1\n"
+			"mrs	 %1, NZCV\n"
+			"orr	 %0, %0, %1\n"
+			/* pc */
+			"adr	 %1, 1f\n"
+		"1:\n"
+			"stp	 %1, %0,   [%2, #16 * 16]\n"
+			: "+r" (tmp1), "+r" (tmp2)
+			: "r" (newregs)
+			: "memory"
+		);
+	}
 }
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 0226447..6b0f2c7 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -136,6 +136,8 @@ static inline void cpu_panic_kernel(void)
  */
 bool cpus_are_stuck_in_kernel(void);
 
+extern void smp_send_crash_stop(void);
+
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* ifndef __ASM_SMP_H */
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index bc96c8a..c60346d 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -9,6 +9,9 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
 #include <linux/kexec.h>
 #include <linux/smp.h>
 
@@ -22,6 +25,7 @@
 extern const unsigned char arm64_relocate_new_kernel[];
 extern const unsigned long arm64_relocate_new_kernel_size;
 
+static bool in_crash_kexec;
 static unsigned long kimage_start;
 
 /**
@@ -148,7 +152,8 @@ void machine_kexec(struct kimage *kimage)
 	/*
 	 * New cpus may have become stuck_in_kernel after we loaded the image.
 	 */
-	BUG_ON(cpus_are_stuck_in_kernel() || (num_online_cpus() > 1));
+	BUG_ON((cpus_are_stuck_in_kernel() || (num_online_cpus() > 1)) &&
+			!WARN_ON(in_crash_kexec));
 
 	reboot_code_buffer_phys = page_to_phys(kimage->control_code_page);
 	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
@@ -200,13 +205,58 @@ void machine_kexec(struct kimage *kimage)
 	 * relocation is complete.
 	 */
 
-	cpu_soft_restart(1, reboot_code_buffer_phys, kimage->head,
+	cpu_soft_restart(!in_crash_kexec, reboot_code_buffer_phys, kimage->head,
 		kimage_start, 0);
 
 	BUG(); /* Should never get here. */
 }
 
+static void machine_kexec_mask_interrupts(void)
+{
+	unsigned int i;
+	struct irq_desc *desc;
+
+	for_each_irq_desc(i, desc) {
+		struct irq_chip *chip;
+		int ret;
+
+		chip = irq_desc_get_chip(desc);
+		if (!chip)
+			continue;
+
+		/*
+		 * First try to remove the active state. If this
+		 * fails, try to EOI the interrupt.
+		 */
+		ret = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false);
+
+		if (ret && irqd_irq_inprogress(&desc->irq_data) &&
+		    chip->irq_eoi)
+			chip->irq_eoi(&desc->irq_data);
+
+		if (chip->irq_mask)
+			chip->irq_mask(&desc->irq_data);
+
+		if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data))
+			chip->irq_disable(&desc->irq_data);
+	}
+}
+
+/**
+ * machine_crash_shutdown - shutdown non-crashing cpus and save registers
+ */
 void machine_crash_shutdown(struct pt_regs *regs)
 {
-	/* Empty routine needed to avoid build errors. */
+	local_irq_disable();
+
+	in_crash_kexec = true;
+
+	/* shutdown non-crashing cpus */
+	smp_send_crash_stop();
+
+	/* for crashing cpu */
+	crash_save_cpu(regs, smp_processor_id());
+	machine_kexec_mask_interrupts();
+
+	pr_info("Starting crashdump kernel...\n");
 }
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 8507703..8f8fd3ad 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>
@@ -71,6 +72,7 @@ enum ipi_msg_type {
 	IPI_RESCHEDULE,
 	IPI_CALL_FUNC,
 	IPI_CPU_STOP,
+	IPI_CPU_CRASH_STOP,
 	IPI_TIMER,
 	IPI_IRQ_WORK,
 	IPI_WAKEUP
@@ -745,6 +747,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
 	S(IPI_RESCHEDULE, "Rescheduling interrupts"),
 	S(IPI_CALL_FUNC, "Function call interrupts"),
 	S(IPI_CPU_STOP, "CPU stop interrupts"),
+	S(IPI_CPU_CRASH_STOP, "CPU stop (for crash dump) interrupts"),
 	S(IPI_TIMER, "Timer broadcast interrupts"),
 	S(IPI_IRQ_WORK, "IRQ work interrupts"),
 	S(IPI_WAKEUP, "CPU wake-up interrupts"),
@@ -819,6 +822,29 @@ static void ipi_cpu_stop(unsigned int cpu)
 		cpu_relax();
 }
 
+#ifdef CONFIG_KEXEC_CORE
+static atomic_t waiting_for_crash_ipi;
+#endif
+
+static void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
+{
+#ifdef CONFIG_KEXEC_CORE
+	crash_save_cpu(regs, cpu);
+
+	atomic_dec(&waiting_for_crash_ipi);
+
+	local_irq_disable();
+
+#ifdef CONFIG_HOTPLUG_CPU
+	if (cpu_ops[cpu]->cpu_die)
+		cpu_ops[cpu]->cpu_die(cpu);
+#endif
+
+	/* just in case */
+	cpu_park_loop();
+#endif
+}
+
 /*
  * Main handler for inter-processor interrupts
  */
@@ -849,6 +875,15 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
 		irq_exit();
 		break;
 
+	case IPI_CPU_CRASH_STOP:
+		if (IS_ENABLED(CONFIG_KEXEC_CORE)) {
+			irq_enter();
+			ipi_cpu_crash_stop(cpu, regs);
+
+			unreachable();
+		}
+		break;
+
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 	case IPI_TIMER:
 		irq_enter();
@@ -921,6 +956,34 @@ void smp_send_stop(void)
 			   cpumask_pr_args(cpu_online_mask));
 }
 
+#ifdef CONFIG_KEXEC_CORE
+void smp_send_crash_stop(void)
+{
+	cpumask_t mask;
+	unsigned long timeout;
+
+	if (num_online_cpus() == 1)
+		return;
+
+	cpumask_copy(&mask, cpu_online_mask);
+	cpumask_clear_cpu(smp_processor_id(), &mask);
+
+	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+
+	pr_crit("SMP: stopping secondary CPUs\n");
+	smp_cross_call(&mask, IPI_CPU_CRASH_STOP);
+
+	/* Wait up to one second for other CPUs to stop */
+	timeout = USEC_PER_SEC;
+	while ((atomic_read(&waiting_for_crash_ipi) > 0) && timeout--)
+		udelay(1);
+
+	if (atomic_read(&waiting_for_crash_ipi) > 0)
+		pr_warning("SMP: failed to stop secondary CPUs %*pbl\n",
+			   cpumask_pr_args(cpu_online_mask));
+}
+#endif
+
 /*
  * not supported here
  */
-- 
2.10.0

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

* [PATCH v27 4/9] arm64: kdump: implement machine_crash_shutdown()
@ 2016-11-02  4:52   ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: catalin.marinas, will.deacon
  Cc: mark.rutland, geoff, kexec, AKASHI Takahiro, james.morse,
	bauerman, dyoung, linux-arm-kernel

Primary kernel calls machine_crash_shutdown() to shut down non-boot cpus
and save registers' status in per-cpu ELF notes before starting crash
dump kernel. See kernel_kexec().
Even if not all secondary cpus have shut down, we do kdump anyway.

As we don't have to make non-boot(crashed) cpus offline (to preserve
correct status of cpus at crash dump) before shutting down, this patch
also adds a variant of smp_send_stop().

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: James Morse <james.morse@arm.com>
---
 arch/arm64/include/asm/hardirq.h  |  2 +-
 arch/arm64/include/asm/kexec.h    | 42 +++++++++++++++++++++++++-
 arch/arm64/include/asm/smp.h      |  2 ++
 arch/arm64/kernel/machine_kexec.c | 56 ++++++++++++++++++++++++++++++++--
 arch/arm64/kernel/smp.c           | 63 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 160 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h
index 8740297..1473fc2 100644
--- a/arch/arm64/include/asm/hardirq.h
+++ b/arch/arm64/include/asm/hardirq.h
@@ -20,7 +20,7 @@
 #include <linux/threads.h>
 #include <asm/irq.h>
 
-#define NR_IPI	6
+#define NR_IPI	7
 
 typedef struct {
 	unsigned int __softirq_pending;
diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
index 04744dc..b5168e8 100644
--- a/arch/arm64/include/asm/kexec.h
+++ b/arch/arm64/include/asm/kexec.h
@@ -40,7 +40,47 @@
 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 {
+		u64 tmp1, tmp2;
+
+		__asm__ __volatile__ (
+			"stp	 x0,   x1, [%2, #16 *  0]\n"
+			"stp	 x2,   x3, [%2, #16 *  1]\n"
+			"stp	 x4,   x5, [%2, #16 *  2]\n"
+			"stp	 x6,   x7, [%2, #16 *  3]\n"
+			"stp	 x8,   x9, [%2, #16 *  4]\n"
+			"stp	x10,  x11, [%2, #16 *  5]\n"
+			"stp	x12,  x13, [%2, #16 *  6]\n"
+			"stp	x14,  x15, [%2, #16 *  7]\n"
+			"stp	x16,  x17, [%2, #16 *  8]\n"
+			"stp	x18,  x19, [%2, #16 *  9]\n"
+			"stp	x20,  x21, [%2, #16 * 10]\n"
+			"stp	x22,  x23, [%2, #16 * 11]\n"
+			"stp	x24,  x25, [%2, #16 * 12]\n"
+			"stp	x26,  x27, [%2, #16 * 13]\n"
+			"stp	x28,  x29, [%2, #16 * 14]\n"
+			"mov	 %0,  sp\n"
+			"stp	x30,  %0,  [%2, #16 * 15]\n"
+
+			"/* faked current PSTATE */\n"
+			"mrs	 %0, CurrentEL\n"
+			"mrs	 %1, SPSEL\n"
+			"orr	 %0, %0, %1\n"
+			"mrs	 %1, DAIF\n"
+			"orr	 %0, %0, %1\n"
+			"mrs	 %1, NZCV\n"
+			"orr	 %0, %0, %1\n"
+			/* pc */
+			"adr	 %1, 1f\n"
+		"1:\n"
+			"stp	 %1, %0,   [%2, #16 * 16]\n"
+			: "+r" (tmp1), "+r" (tmp2)
+			: "r" (newregs)
+			: "memory"
+		);
+	}
 }
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 0226447..6b0f2c7 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -136,6 +136,8 @@ static inline void cpu_panic_kernel(void)
  */
 bool cpus_are_stuck_in_kernel(void);
 
+extern void smp_send_crash_stop(void);
+
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* ifndef __ASM_SMP_H */
diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index bc96c8a..c60346d 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -9,6 +9,9 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
 #include <linux/kexec.h>
 #include <linux/smp.h>
 
@@ -22,6 +25,7 @@
 extern const unsigned char arm64_relocate_new_kernel[];
 extern const unsigned long arm64_relocate_new_kernel_size;
 
+static bool in_crash_kexec;
 static unsigned long kimage_start;
 
 /**
@@ -148,7 +152,8 @@ void machine_kexec(struct kimage *kimage)
 	/*
 	 * New cpus may have become stuck_in_kernel after we loaded the image.
 	 */
-	BUG_ON(cpus_are_stuck_in_kernel() || (num_online_cpus() > 1));
+	BUG_ON((cpus_are_stuck_in_kernel() || (num_online_cpus() > 1)) &&
+			!WARN_ON(in_crash_kexec));
 
 	reboot_code_buffer_phys = page_to_phys(kimage->control_code_page);
 	reboot_code_buffer = phys_to_virt(reboot_code_buffer_phys);
@@ -200,13 +205,58 @@ void machine_kexec(struct kimage *kimage)
 	 * relocation is complete.
 	 */
 
-	cpu_soft_restart(1, reboot_code_buffer_phys, kimage->head,
+	cpu_soft_restart(!in_crash_kexec, reboot_code_buffer_phys, kimage->head,
 		kimage_start, 0);
 
 	BUG(); /* Should never get here. */
 }
 
+static void machine_kexec_mask_interrupts(void)
+{
+	unsigned int i;
+	struct irq_desc *desc;
+
+	for_each_irq_desc(i, desc) {
+		struct irq_chip *chip;
+		int ret;
+
+		chip = irq_desc_get_chip(desc);
+		if (!chip)
+			continue;
+
+		/*
+		 * First try to remove the active state. If this
+		 * fails, try to EOI the interrupt.
+		 */
+		ret = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false);
+
+		if (ret && irqd_irq_inprogress(&desc->irq_data) &&
+		    chip->irq_eoi)
+			chip->irq_eoi(&desc->irq_data);
+
+		if (chip->irq_mask)
+			chip->irq_mask(&desc->irq_data);
+
+		if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data))
+			chip->irq_disable(&desc->irq_data);
+	}
+}
+
+/**
+ * machine_crash_shutdown - shutdown non-crashing cpus and save registers
+ */
 void machine_crash_shutdown(struct pt_regs *regs)
 {
-	/* Empty routine needed to avoid build errors. */
+	local_irq_disable();
+
+	in_crash_kexec = true;
+
+	/* shutdown non-crashing cpus */
+	smp_send_crash_stop();
+
+	/* for crashing cpu */
+	crash_save_cpu(regs, smp_processor_id());
+	machine_kexec_mask_interrupts();
+
+	pr_info("Starting crashdump kernel...\n");
 }
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 8507703..8f8fd3ad 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>
@@ -71,6 +72,7 @@ enum ipi_msg_type {
 	IPI_RESCHEDULE,
 	IPI_CALL_FUNC,
 	IPI_CPU_STOP,
+	IPI_CPU_CRASH_STOP,
 	IPI_TIMER,
 	IPI_IRQ_WORK,
 	IPI_WAKEUP
@@ -745,6 +747,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
 	S(IPI_RESCHEDULE, "Rescheduling interrupts"),
 	S(IPI_CALL_FUNC, "Function call interrupts"),
 	S(IPI_CPU_STOP, "CPU stop interrupts"),
+	S(IPI_CPU_CRASH_STOP, "CPU stop (for crash dump) interrupts"),
 	S(IPI_TIMER, "Timer broadcast interrupts"),
 	S(IPI_IRQ_WORK, "IRQ work interrupts"),
 	S(IPI_WAKEUP, "CPU wake-up interrupts"),
@@ -819,6 +822,29 @@ static void ipi_cpu_stop(unsigned int cpu)
 		cpu_relax();
 }
 
+#ifdef CONFIG_KEXEC_CORE
+static atomic_t waiting_for_crash_ipi;
+#endif
+
+static void ipi_cpu_crash_stop(unsigned int cpu, struct pt_regs *regs)
+{
+#ifdef CONFIG_KEXEC_CORE
+	crash_save_cpu(regs, cpu);
+
+	atomic_dec(&waiting_for_crash_ipi);
+
+	local_irq_disable();
+
+#ifdef CONFIG_HOTPLUG_CPU
+	if (cpu_ops[cpu]->cpu_die)
+		cpu_ops[cpu]->cpu_die(cpu);
+#endif
+
+	/* just in case */
+	cpu_park_loop();
+#endif
+}
+
 /*
  * Main handler for inter-processor interrupts
  */
@@ -849,6 +875,15 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
 		irq_exit();
 		break;
 
+	case IPI_CPU_CRASH_STOP:
+		if (IS_ENABLED(CONFIG_KEXEC_CORE)) {
+			irq_enter();
+			ipi_cpu_crash_stop(cpu, regs);
+
+			unreachable();
+		}
+		break;
+
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 	case IPI_TIMER:
 		irq_enter();
@@ -921,6 +956,34 @@ void smp_send_stop(void)
 			   cpumask_pr_args(cpu_online_mask));
 }
 
+#ifdef CONFIG_KEXEC_CORE
+void smp_send_crash_stop(void)
+{
+	cpumask_t mask;
+	unsigned long timeout;
+
+	if (num_online_cpus() == 1)
+		return;
+
+	cpumask_copy(&mask, cpu_online_mask);
+	cpumask_clear_cpu(smp_processor_id(), &mask);
+
+	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+
+	pr_crit("SMP: stopping secondary CPUs\n");
+	smp_cross_call(&mask, IPI_CPU_CRASH_STOP);
+
+	/* Wait up to one second for other CPUs to stop */
+	timeout = USEC_PER_SEC;
+	while ((atomic_read(&waiting_for_crash_ipi) > 0) && timeout--)
+		udelay(1);
+
+	if (atomic_read(&waiting_for_crash_ipi) > 0)
+		pr_warning("SMP: failed to stop secondary CPUs %*pbl\n",
+			   cpumask_pr_args(cpu_online_mask));
+}
+#endif
+
 /*
  * not supported here
  */
-- 
2.10.0


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

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

* [PATCH v27 5/9] arm64: kdump: add VMCOREINFO's for user-space tools
  2016-11-02  4:49 ` AKASHI Takahiro
@ 2016-11-02  4:52   ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: linux-arm-kernel

In addition to common VMCOREINFO's defined in
crash_save_vmcoreinfo_init(), we need to know, for crash utility,
  - kimage_voffset
  - PHYS_OFFSET
to examine the contents of a dump file (/proc/vmcore) correctly
due to the introduction of KASLR (CONFIG_RANDOMIZE_BASE) in v4.6.

  - VA_BITS
is also required for makedumpfile command.

arch_crash_save_vmcoreinfo() appends them to the dump file.
More VMCOREINFO's may be added later.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: James Morse <james.morse@arm.com>
---
 arch/arm64/kernel/machine_kexec.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index c60346d..994fe0b 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -17,6 +17,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/cpu_ops.h>
+#include <asm/memory.h>
 #include <asm/mmu_context.h>
 
 #include "cpu-reset.h"
@@ -260,3 +261,13 @@ void machine_crash_shutdown(struct pt_regs *regs)
 
 	pr_info("Starting crashdump kernel...\n");
 }
+
+void arch_crash_save_vmcoreinfo(void)
+{
+	VMCOREINFO_NUMBER(VA_BITS);
+	/* Please note VMCOREINFO_NUMBER() uses "%d", not "%x" */
+	vmcoreinfo_append_str("NUMBER(kimage_voffset)=0x%llx\n",
+						kimage_voffset);
+	vmcoreinfo_append_str("NUMBER(PHYS_OFFSET)=0x%llx\n",
+						PHYS_OFFSET);
+}
-- 
2.10.0

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

* [PATCH v27 5/9] arm64: kdump: add VMCOREINFO's for user-space tools
@ 2016-11-02  4:52   ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: catalin.marinas, will.deacon
  Cc: mark.rutland, geoff, kexec, AKASHI Takahiro, james.morse,
	bauerman, dyoung, linux-arm-kernel

In addition to common VMCOREINFO's defined in
crash_save_vmcoreinfo_init(), we need to know, for crash utility,
  - kimage_voffset
  - PHYS_OFFSET
to examine the contents of a dump file (/proc/vmcore) correctly
due to the introduction of KASLR (CONFIG_RANDOMIZE_BASE) in v4.6.

  - VA_BITS
is also required for makedumpfile command.

arch_crash_save_vmcoreinfo() appends them to the dump file.
More VMCOREINFO's may be added later.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: James Morse <james.morse@arm.com>
---
 arch/arm64/kernel/machine_kexec.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c
index c60346d..994fe0b 100644
--- a/arch/arm64/kernel/machine_kexec.c
+++ b/arch/arm64/kernel/machine_kexec.c
@@ -17,6 +17,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/cpu_ops.h>
+#include <asm/memory.h>
 #include <asm/mmu_context.h>
 
 #include "cpu-reset.h"
@@ -260,3 +261,13 @@ void machine_crash_shutdown(struct pt_regs *regs)
 
 	pr_info("Starting crashdump kernel...\n");
 }
+
+void arch_crash_save_vmcoreinfo(void)
+{
+	VMCOREINFO_NUMBER(VA_BITS);
+	/* Please note VMCOREINFO_NUMBER() uses "%d", not "%x" */
+	vmcoreinfo_append_str("NUMBER(kimage_voffset)=0x%llx\n",
+						kimage_voffset);
+	vmcoreinfo_append_str("NUMBER(PHYS_OFFSET)=0x%llx\n",
+						PHYS_OFFSET);
+}
-- 
2.10.0


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

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

* [PATCH v27 6/9] arm64: kdump: provide /proc/vmcore file
  2016-11-02  4:49 ` AKASHI Takahiro
@ 2016-11-02  4:52   ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: linux-arm-kernel

Add arch-specific functions to provide a dump file, /proc/vmcore.

This file is in ELF format and its ELF header needs to be prepared by
userspace tools, like kexec-tools, in adance. The primary kernel is
responsible to allocate the region with reserve_elfcorehdr() at boot time
and advertize its location to crash dump kernel via a new device-tree
property, "linux,elfcorehdr".

Then crash dump kernel will access the primary kernel's memory with
copy_oldmem_page(), which feeds the data page-by-page by ioremap'ing it
since it does not reside in linear mapping on crash dump kernel.

We also need our own elfcorehdr_read() here since the header is placed
within crash dump kernel's usable memory.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: James Morse <james.morse@arm.com>
---
 arch/arm64/Kconfig             | 11 +++++++
 arch/arm64/kernel/Makefile     |  1 +
 arch/arm64/kernel/crash_dump.c | 71 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/init.c           | 54 ++++++++++++++++++++++++++++++++
 4 files changed, 137 insertions(+)
 create mode 100644 arch/arm64/kernel/crash_dump.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 969ef88..399f84a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -688,6 +688,17 @@ 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.
+
+	  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 7d66bba..6a7384e 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -50,6 +50,7 @@ arm64-obj-$(CONFIG_RANDOMIZE_BASE)	+= kaslr.o
 arm64-obj-$(CONFIG_HIBERNATION)		+= hibernate.o hibernate-asm.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/ probes/
 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..c3d5a21
--- /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 = memremap(__pfn_to_phys(pfn), PAGE_SIZE, MEMREMAP_WB);
+	if (!vaddr)
+		return -ENOMEM;
+
+	if (userbuf) {
+		if (copy_to_user((char __user *)buf, vaddr + offset, csize)) {
+			memunmap(vaddr);
+			return -EFAULT;
+		}
+	} else {
+		memcpy(buf, vaddr + offset, csize);
+	}
+
+	memunmap(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 1d62bf7..ef8adfd 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -38,6 +38,7 @@
 #include <linux/swiotlb.h>
 #include <linux/vmalloc.h>
 #include <linux/kexec.h>
+#include <linux/crash_dump.h>
 
 #include <asm/boot.h>
 #include <asm/fixmap.h>
@@ -183,6 +184,57 @@ static void __init reserve_crashkernel(void)
 }
 #endif /* CONFIG_KEXEC_CORE */
 
+#ifdef CONFIG_CRASH_DUMP
+static int __init early_init_dt_scan_elfcorehdr(unsigned long node,
+		const char *uname, int depth, void *data)
+{
+	const __be32 *reg;
+	int len;
+
+	if (depth != 1 || strcmp(uname, "chosen") != 0)
+		return 0;
+
+	reg = of_get_flat_dt_prop(node, "linux,elfcorehdr", &len);
+	if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells)))
+		return 1;
+
+	elfcorehdr_addr = dt_mem_next_cell(dt_root_addr_cells, &reg);
+	elfcorehdr_size = dt_mem_next_cell(dt_root_size_cells, &reg);
+
+	return 1;
+}
+
+/*
+ * 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)
+{
+	of_scan_flat_dt(early_init_dt_scan_elfcorehdr, NULL);
+
+	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@0x%llx for elfcorehdr\n",
+		elfcorehdr_size >> 10, elfcorehdr_addr);
+}
+#else
+static void __init reserve_elfcorehdr(void)
+{
+	;
+}
+#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
@@ -441,6 +493,8 @@ void __init arm64_memblock_init(void)
 
 	reserve_crashkernel();
 
+	reserve_elfcorehdr();
+
 	dma_contiguous_reserve(arm64_dma_phys_limit);
 
 	memblock_allow_resize();
-- 
2.10.0

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

* [PATCH v27 6/9] arm64: kdump: provide /proc/vmcore file
@ 2016-11-02  4:52   ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: catalin.marinas, will.deacon
  Cc: mark.rutland, geoff, kexec, AKASHI Takahiro, james.morse,
	bauerman, dyoung, linux-arm-kernel

Add arch-specific functions to provide a dump file, /proc/vmcore.

This file is in ELF format and its ELF header needs to be prepared by
userspace tools, like kexec-tools, in adance. The primary kernel is
responsible to allocate the region with reserve_elfcorehdr() at boot time
and advertize its location to crash dump kernel via a new device-tree
property, "linux,elfcorehdr".

Then crash dump kernel will access the primary kernel's memory with
copy_oldmem_page(), which feeds the data page-by-page by ioremap'ing it
since it does not reside in linear mapping on crash dump kernel.

We also need our own elfcorehdr_read() here since the header is placed
within crash dump kernel's usable memory.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: James Morse <james.morse@arm.com>
---
 arch/arm64/Kconfig             | 11 +++++++
 arch/arm64/kernel/Makefile     |  1 +
 arch/arm64/kernel/crash_dump.c | 71 ++++++++++++++++++++++++++++++++++++++++++
 arch/arm64/mm/init.c           | 54 ++++++++++++++++++++++++++++++++
 4 files changed, 137 insertions(+)
 create mode 100644 arch/arm64/kernel/crash_dump.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 969ef88..399f84a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -688,6 +688,17 @@ 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.
+
+	  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 7d66bba..6a7384e 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -50,6 +50,7 @@ arm64-obj-$(CONFIG_RANDOMIZE_BASE)	+= kaslr.o
 arm64-obj-$(CONFIG_HIBERNATION)		+= hibernate.o hibernate-asm.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/ probes/
 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..c3d5a21
--- /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 = memremap(__pfn_to_phys(pfn), PAGE_SIZE, MEMREMAP_WB);
+	if (!vaddr)
+		return -ENOMEM;
+
+	if (userbuf) {
+		if (copy_to_user((char __user *)buf, vaddr + offset, csize)) {
+			memunmap(vaddr);
+			return -EFAULT;
+		}
+	} else {
+		memcpy(buf, vaddr + offset, csize);
+	}
+
+	memunmap(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 1d62bf7..ef8adfd 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -38,6 +38,7 @@
 #include <linux/swiotlb.h>
 #include <linux/vmalloc.h>
 #include <linux/kexec.h>
+#include <linux/crash_dump.h>
 
 #include <asm/boot.h>
 #include <asm/fixmap.h>
@@ -183,6 +184,57 @@ static void __init reserve_crashkernel(void)
 }
 #endif /* CONFIG_KEXEC_CORE */
 
+#ifdef CONFIG_CRASH_DUMP
+static int __init early_init_dt_scan_elfcorehdr(unsigned long node,
+		const char *uname, int depth, void *data)
+{
+	const __be32 *reg;
+	int len;
+
+	if (depth != 1 || strcmp(uname, "chosen") != 0)
+		return 0;
+
+	reg = of_get_flat_dt_prop(node, "linux,elfcorehdr", &len);
+	if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells)))
+		return 1;
+
+	elfcorehdr_addr = dt_mem_next_cell(dt_root_addr_cells, &reg);
+	elfcorehdr_size = dt_mem_next_cell(dt_root_size_cells, &reg);
+
+	return 1;
+}
+
+/*
+ * 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)
+{
+	of_scan_flat_dt(early_init_dt_scan_elfcorehdr, NULL);
+
+	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 0x%llx for elfcorehdr\n",
+		elfcorehdr_size >> 10, elfcorehdr_addr);
+}
+#else
+static void __init reserve_elfcorehdr(void)
+{
+	;
+}
+#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
@@ -441,6 +493,8 @@ void __init arm64_memblock_init(void)
 
 	reserve_crashkernel();
 
+	reserve_elfcorehdr();
+
 	dma_contiguous_reserve(arm64_dma_phys_limit);
 
 	memblock_allow_resize();
-- 
2.10.0


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

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

* [PATCH v27 7/9] arm64: kdump: enable kdump in defconfig
  2016-11-02  4:49 ` AKASHI Takahiro
@ 2016-11-02  4:52   ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: linux-arm-kernel

Kdump is enabled by default as kexec is.

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 dab2cb0..24922c9 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -79,6 +79,7 @@ CONFIG_CMA=y
 CONFIG_SECCOMP=y
 CONFIG_XEN=y
 CONFIG_KEXEC=y
+CONFIG_CRASH_DUMP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
 CONFIG_CPU_IDLE=y
-- 
2.10.0

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

* [PATCH v27 7/9] arm64: kdump: enable kdump in defconfig
@ 2016-11-02  4:52   ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: catalin.marinas, will.deacon
  Cc: mark.rutland, geoff, kexec, AKASHI Takahiro, james.morse,
	bauerman, dyoung, linux-arm-kernel

Kdump is enabled by default as kexec is.

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 dab2cb0..24922c9 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -79,6 +79,7 @@ CONFIG_CMA=y
 CONFIG_SECCOMP=y
 CONFIG_XEN=y
 CONFIG_KEXEC=y
+CONFIG_CRASH_DUMP=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
 CONFIG_CPU_IDLE=y
-- 
2.10.0


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

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

* [PATCH v27 8/9] Documentation: kdump: describe arm64 port
  2016-11-02  4:49 ` AKASHI Takahiro
@ 2016-11-02  4:52   ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: linux-arm-kernel

Add arch specific descriptions about kdump usage on arm64 to kdump.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Baoquan He <bhe@redhat.com>
Acked-by: Dave Young <dyoung@redhat.com>
---
 Documentation/kdump/kdump.txt | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index b0eb27b..615434d 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,13 @@ Dump-capture kernel config options (Arch Dependent, arm)
 
     AUTO_ZRELADDR=y
 
+Dump-capture kernel config options (Arch Dependent, arm64)
+----------------------------------------------------------
+
+- Please note that kvm of the dump-capture kernel will not be enabled
+  on non-VHE systems even if it is configured. This is because the CPU
+  will not be reset to EL2 on panic.
+
 Extended crashkernel syntax
 ===========================
 
@@ -305,6 +312,8 @@ Boot into System Kernel
    kernel will automatically locate the crash kernel image within the
    first 512MB of RAM if X is not given.
 
+   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
 ============================
@@ -327,6 +336,8 @@ For s390x:
 	- Use image or bzImage
 For arm:
 	- Use zImage
+For arm64:
+	- Use vmlinux or Image
 
 If you are using a uncompressed vmlinux image then use following command
 to load dump-capture kernel.
@@ -370,6 +381,9 @@ For s390x:
 For arm:
 	"1 maxcpus=1 reset_devices"
 
+For arm64:
+	"1 maxcpus=1 reset_devices"
+
 Notes on loading the dump-capture kernel:
 
 * By default, the ELF headers are stored in ELF64 format to support
-- 
2.10.0

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

* [PATCH v27 8/9] Documentation: kdump: describe arm64 port
@ 2016-11-02  4:52   ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:52 UTC (permalink / raw)
  To: catalin.marinas, will.deacon
  Cc: mark.rutland, geoff, kexec, AKASHI Takahiro, james.morse,
	bauerman, dyoung, linux-arm-kernel

Add arch specific descriptions about kdump usage on arm64 to kdump.txt.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Reviewed-by: Baoquan He <bhe@redhat.com>
Acked-by: Dave Young <dyoung@redhat.com>
---
 Documentation/kdump/kdump.txt | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index b0eb27b..615434d 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,13 @@ Dump-capture kernel config options (Arch Dependent, arm)
 
     AUTO_ZRELADDR=y
 
+Dump-capture kernel config options (Arch Dependent, arm64)
+----------------------------------------------------------
+
+- Please note that kvm of the dump-capture kernel will not be enabled
+  on non-VHE systems even if it is configured. This is because the CPU
+  will not be reset to EL2 on panic.
+
 Extended crashkernel syntax
 ===========================
 
@@ -305,6 +312,8 @@ Boot into System Kernel
    kernel will automatically locate the crash kernel image within the
    first 512MB of RAM if X is not given.
 
+   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
 ============================
@@ -327,6 +336,8 @@ For s390x:
 	- Use image or bzImage
 For arm:
 	- Use zImage
+For arm64:
+	- Use vmlinux or Image
 
 If you are using a uncompressed vmlinux image then use following command
 to load dump-capture kernel.
@@ -370,6 +381,9 @@ For s390x:
 For arm:
 	"1 maxcpus=1 reset_devices"
 
+For arm64:
+	"1 maxcpus=1 reset_devices"
+
 Notes on loading the dump-capture kernel:
 
 * By default, the ELF headers are stored in ELF64 format to support
-- 
2.10.0


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

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

* [PATCH v27 9/9] Documentation: dt: chosen properties for arm64 kdump
  2016-11-02  4:49 ` AKASHI Takahiro
  (?)
@ 2016-11-02  4:54     ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:54 UTC (permalink / raw)
  To: catalin.marinas-5wv7dgnIgG8, will.deacon-5wv7dgnIgG8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8
  Cc: james.morse-5wv7dgnIgG8, geoff-wEGCiKHe2LqWVfeAwA7xHQ,
	bauerman-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8,
	dyoung-H+wXaHxf7aLQT0dZR+AlfA,
	kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA, AKASHI Takahiro

From: James Morse <james.morse-5wv7dgnIgG8@public.gmane.org>

Add documentation for
	linux,crashkernel-base and crashkernel-size,
	linux,usable-memory-range
	linux,elfcorehdr
used by arm64 kdump to decribe the kdump reserved area, and
the elfcorehdr's location within it.

Signed-off-by: James Morse <james.morse-5wv7dgnIgG8@public.gmane.org>
[takahiro.akashi-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org: added "linux,crashkernel-base" and "-size" ]
Signed-off-by: AKASHI Takahiro <takahiro.akashi-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
---
 Documentation/devicetree/bindings/chosen.txt | 50 ++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/Documentation/devicetree/bindings/chosen.txt b/Documentation/devicetree/bindings/chosen.txt
index 6ae9d82..7b11516 100644
--- a/Documentation/devicetree/bindings/chosen.txt
+++ b/Documentation/devicetree/bindings/chosen.txt
@@ -52,3 +52,53 @@ This property is set (currently only on PowerPC, and only needed on
 book3e) by some versions of kexec-tools to tell the new kernel that it
 is being booted by kexec, as the booting environment may differ (e.g.
 a different secondary CPU release mechanism)
+
+linux,crashkernel-base
+linux,crashkernel-size
+----------------------
+
+These properties (currently used on PowerPC and arm64) indicates
+the base address and the size, respectively, of the reserved memory
+range for crash dump kernel.
+e.g.
+
+/ {
+	chosen {
+		linux,crashkernel-base = <0x9 0xf0000000>;
+		linux,crashkernel-size = <0x0 0x10000000>;
+	};
+};
+
+linux,usable-memory-range
+-------------------------
+
+This property (currently used only on arm64) holds the memory range,
+the base address and the size, which can be used as system ram on
+the *current* kernel. Note that, if this property is present, any memory
+regions under "memory" nodes in DT blob or ones marked as "conventional
+memory" in EFI memory map should be ignored.
+e.g.
+
+/ {
+	chosen {
+		linux,usable-memory-range = <0x9 0xf0000000 0x0 0x10000000>;
+	};
+};
+
+The main usage is for crash dump kernel to identify its own usable
+memory and exclude, at its boot time, any other memory areas that are
+part of the panicked kernel's memory.
+
+linux,elfcorehdr
+----------------
+
+This property (currently used only on arm64) holds the memory range,
+the address and the size, of the elf core header which mainly describes
+the panicked kernel's memory layout as PT_LOAD segments of elf format.
+e.g.
+
+/ {
+	chosen {
+		linux,elfcorehdr = <0x9 0xfffff000 0x0 0x800>;
+	};
+};
-- 
2.10.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v27 9/9] Documentation: dt: chosen properties for arm64 kdump
@ 2016-11-02  4:54     ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:54 UTC (permalink / raw)
  To: linux-arm-kernel

From: James Morse <james.morse@arm.com>

Add documentation for
	linux,crashkernel-base and crashkernel-size,
	linux,usable-memory-range
	linux,elfcorehdr
used by arm64 kdump to decribe the kdump reserved area, and
the elfcorehdr's location within it.

Signed-off-by: James Morse <james.morse@arm.com>
[takahiro.akashi at linaro.org: added "linux,crashkernel-base" and "-size" ]
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Cc: devicetree at vger.kernel.org
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
---
 Documentation/devicetree/bindings/chosen.txt | 50 ++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/Documentation/devicetree/bindings/chosen.txt b/Documentation/devicetree/bindings/chosen.txt
index 6ae9d82..7b11516 100644
--- a/Documentation/devicetree/bindings/chosen.txt
+++ b/Documentation/devicetree/bindings/chosen.txt
@@ -52,3 +52,53 @@ This property is set (currently only on PowerPC, and only needed on
 book3e) by some versions of kexec-tools to tell the new kernel that it
 is being booted by kexec, as the booting environment may differ (e.g.
 a different secondary CPU release mechanism)
+
+linux,crashkernel-base
+linux,crashkernel-size
+----------------------
+
+These properties (currently used on PowerPC and arm64) indicates
+the base address and the size, respectively, of the reserved memory
+range for crash dump kernel.
+e.g.
+
+/ {
+	chosen {
+		linux,crashkernel-base = <0x9 0xf0000000>;
+		linux,crashkernel-size = <0x0 0x10000000>;
+	};
+};
+
+linux,usable-memory-range
+-------------------------
+
+This property (currently used only on arm64) holds the memory range,
+the base address and the size, which can be used as system ram on
+the *current* kernel. Note that, if this property is present, any memory
+regions under "memory" nodes in DT blob or ones marked as "conventional
+memory" in EFI memory map should be ignored.
+e.g.
+
+/ {
+	chosen {
+		linux,usable-memory-range = <0x9 0xf0000000 0x0 0x10000000>;
+	};
+};
+
+The main usage is for crash dump kernel to identify its own usable
+memory and exclude, at its boot time, any other memory areas that are
+part of the panicked kernel's memory.
+
+linux,elfcorehdr
+----------------
+
+This property (currently used only on arm64) holds the memory range,
+the address and the size, of the elf core header which mainly describes
+the panicked kernel's memory layout as PT_LOAD segments of elf format.
+e.g.
+
+/ {
+	chosen {
+		linux,elfcorehdr = <0x9 0xfffff000 0x0 0x800>;
+	};
+};
-- 
2.10.0

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

* [PATCH v27 9/9] Documentation: dt: chosen properties for arm64 kdump
@ 2016-11-02  4:54     ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-02  4:54 UTC (permalink / raw)
  To: catalin.marinas, will.deacon, robh+dt, mark.rutland
  Cc: devicetree, geoff, kexec, AKASHI Takahiro, james.morse, bauerman,
	dyoung, linux-arm-kernel

From: James Morse <james.morse@arm.com>

Add documentation for
	linux,crashkernel-base and crashkernel-size,
	linux,usable-memory-range
	linux,elfcorehdr
used by arm64 kdump to decribe the kdump reserved area, and
the elfcorehdr's location within it.

Signed-off-by: James Morse <james.morse@arm.com>
[takahiro.akashi@linaro.org: added "linux,crashkernel-base" and "-size" ]
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Cc: devicetree@vger.kernel.org
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
---
 Documentation/devicetree/bindings/chosen.txt | 50 ++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/Documentation/devicetree/bindings/chosen.txt b/Documentation/devicetree/bindings/chosen.txt
index 6ae9d82..7b11516 100644
--- a/Documentation/devicetree/bindings/chosen.txt
+++ b/Documentation/devicetree/bindings/chosen.txt
@@ -52,3 +52,53 @@ This property is set (currently only on PowerPC, and only needed on
 book3e) by some versions of kexec-tools to tell the new kernel that it
 is being booted by kexec, as the booting environment may differ (e.g.
 a different secondary CPU release mechanism)
+
+linux,crashkernel-base
+linux,crashkernel-size
+----------------------
+
+These properties (currently used on PowerPC and arm64) indicates
+the base address and the size, respectively, of the reserved memory
+range for crash dump kernel.
+e.g.
+
+/ {
+	chosen {
+		linux,crashkernel-base = <0x9 0xf0000000>;
+		linux,crashkernel-size = <0x0 0x10000000>;
+	};
+};
+
+linux,usable-memory-range
+-------------------------
+
+This property (currently used only on arm64) holds the memory range,
+the base address and the size, which can be used as system ram on
+the *current* kernel. Note that, if this property is present, any memory
+regions under "memory" nodes in DT blob or ones marked as "conventional
+memory" in EFI memory map should be ignored.
+e.g.
+
+/ {
+	chosen {
+		linux,usable-memory-range = <0x9 0xf0000000 0x0 0x10000000>;
+	};
+};
+
+The main usage is for crash dump kernel to identify its own usable
+memory and exclude, at its boot time, any other memory areas that are
+part of the panicked kernel's memory.
+
+linux,elfcorehdr
+----------------
+
+This property (currently used only on arm64) holds the memory range,
+the address and the size, of the elf core header which mainly describes
+the panicked kernel's memory layout as PT_LOAD segments of elf format.
+e.g.
+
+/ {
+	chosen {
+		linux,elfcorehdr = <0x9 0xfffff000 0x0 0x800>;
+	};
+};
-- 
2.10.0


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

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

* [PATCH v27 0/9] arm64: add kdump support
  2016-11-02  4:49 ` AKASHI Takahiro
@ 2016-11-02  9:39   ` Pratyush Anand
  -1 siblings, 0 replies; 58+ messages in thread
From: Pratyush Anand @ 2016-11-02  9:39 UTC (permalink / raw)
  To: linux-arm-kernel



On Wednesday 02 November 2016 10:19 AM, AKASHI Takahiro wrote:
>     v27-specific note: In this version, the change made in v26 was reverted
>     because I've got a comment that /reserved-memory DT property should
>     not be used on UEFI/ACPI systems, even though it is workable under
>     the current implementation. I've also confirmed that Rob doesn't argue
>     any more against using "linux,usable-memory-range".
>     So v27 is essentially the same as v25.
>
> This patch series adds kdump support on arm64.
>
> To load a crash-dump kernel to the systems, a series of patches to
> kexec-tools[1] are also needed. Please use the latest one, v4 [2].
>
> To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
>   - crash utility (v7.1.6 or later) [3]

Tested with mustang and seattle.
Tested-by: Pratyush Anand <panand@redhat.com>

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

* Re: [PATCH v27 0/9] arm64: add kdump support
@ 2016-11-02  9:39   ` Pratyush Anand
  0 siblings, 0 replies; 58+ messages in thread
From: Pratyush Anand @ 2016-11-02  9:39 UTC (permalink / raw)
  To: AKASHI Takahiro, catalin.marinas, will.deacon
  Cc: mark.rutland, geoff, kexec, james.morse, bauerman, dyoung,
	linux-arm-kernel



On Wednesday 02 November 2016 10:19 AM, AKASHI Takahiro wrote:
>     v27-specific note: In this version, the change made in v26 was reverted
>     because I've got a comment that /reserved-memory DT property should
>     not be used on UEFI/ACPI systems, even though it is workable under
>     the current implementation. I've also confirmed that Rob doesn't argue
>     any more against using "linux,usable-memory-range".
>     So v27 is essentially the same as v25.
>
> This patch series adds kdump support on arm64.
>
> To load a crash-dump kernel to the systems, a series of patches to
> kexec-tools[1] are also needed. Please use the latest one, v4 [2].
>
> To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
>   - crash utility (v7.1.6 or later) [3]

Tested with mustang and seattle.
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] 58+ messages in thread

* [PATCH v27 0/9] arm64: add kdump support
  2016-11-02  4:49 ` AKASHI Takahiro
@ 2016-11-04  3:00   ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-04  3:00 UTC (permalink / raw)
  To: linux-arm-kernel

For easier testing, I pushed my patches to:
https://git.linaro.org/people/takahiro.akashi/linux-aarch64.git arm64/kdump
https://git.linaro.org/people/takahiro.akashi/kexec-tools.git arm64/kdump

If anybody tries my patches, please let me know the result.
(Pratyush, thank you for your test.)

Thanks,
-Takahiro AKASHI

On Wed, Nov 02, 2016 at 01:49:59PM +0900, AKASHI Takahiro wrote:
>     v27-specific note: In this version, the change made in v26 was reverted
>     because I've got a comment that /reserved-memory DT property should
>     not be used on UEFI/ACPI systems, even though it is workable under
>     the current implementation. I've also confirmed that Rob doesn't argue
>     any more against using "linux,usable-memory-range".
>     So v27 is essentially the same as v25.
> 
> This patch series adds kdump support on arm64.
> 
> To load a crash-dump kernel to the systems, a series of patches to
> kexec-tools[1] are also needed. Please use the latest one, v4 [2].
> 
> To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
>   - crash utility (v7.1.6 or later) [3]
> 
> 
> [1] https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
> [1] http://lists.infradead.org/pipermail/kexec/2016-November/017555.html
> [2] https://github.com/crash-utility/crash.git
> 
> Changes for v27 (Nov 2, 2016)
>   o rebased to Linux-v4.9-rc3
>   o revert v26 change, i.e. revive "linux,usable-memory-range" property
>     (patch #2/#3, updating patch #9)
>   o minor fixes per review comments (patch #3/#4/#6/#8)
>   o re-order patches and improve commit messages for readability
> 
> Changes for v26 (Sep 7, 2016):
>   o Use /reserved-memory instead of "linux,usable-memory-range" property
>     (dropping v25's patch#2 and #3, updating ex-patch#9.)
> 
> Changes for v25 (Aug 29, 2016):
>   o Rebase to Linux-4.8-rc4
>   o Use memremap() instead of ioremap_cache() [patch#5]
> 
> Changes for v24 (Aug 9, 2016):
>   o Rebase to Linux-4.8-rc1
>   o Update descriptions about newly added DT proerties
> 
> Changes for v23 (July 26, 2016):
> 
>   o Move memblock_reserve() to a single place in reserve_crashkernel()
>   o Use  cpu_park_loop() in ipi_cpu_crash_stop()
>   o Always enforce ARCH_LOW_ADDRESS_LIMIT to the memory range of crash kernel
>   o Re-implement fdt_enforce_memory_region() to remove non-reserve regions
>     (for ACPI) from usable memory at crash kernel
> 
> Changes for v22 (July 12, 2016):
> 
>   o Export "crashkernel-base" and "crashkernel-size" via device-tree,
>     and add some descriptions about them in chosen.txt
>   o Rename "usable-memory" to "usable-memory-range" to avoid inconsistency
>     with powerpc's "usable-memory"
>   o Make cosmetic changes regarding "ifdef" usage
>   o Correct some wordings in kdump.txt
> 
> Changes for v21 (July 6, 2016):
> 
>   o Remove kexec patches.
>   o Rebase to arm64's for-next/core (Linux-4.7-rc4 based).
>   o Clarify the description about kvm in kdump.txt.
> 
> See the following link [3] for older changes:
> [3]  http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438780.html
> 
> AKASHI Takahiro (8):
>   memblock: add memblock_cap_memory_range()
>   arm64: limit memory regions based on DT property, usable-memory-range
>   arm64: kdump: reserve memory for crash dump kernel
>   arm64: kdump: implement machine_crash_shutdown()
>   arm64: kdump: add VMCOREINFO's for user-space tools
>   arm64: kdump: provide /proc/vmcore file
>   arm64: kdump: enable kdump in defconfig
>   Documentation: kdump: describe arm64 port
> 
> James Morse (1):
>   Documentation: dt: chosen properties for arm64 kdump
> 
>  Documentation/devicetree/bindings/chosen.txt |  50 +++++++
>  Documentation/kdump/kdump.txt                |  16 ++-
>  arch/arm64/Kconfig                           |  11 ++
>  arch/arm64/configs/defconfig                 |   1 +
>  arch/arm64/include/asm/hardirq.h             |   2 +-
>  arch/arm64/include/asm/kexec.h               |  42 +++++-
>  arch/arm64/include/asm/smp.h                 |   2 +
>  arch/arm64/kernel/Makefile                   |   1 +
>  arch/arm64/kernel/crash_dump.c               |  71 ++++++++++
>  arch/arm64/kernel/machine_kexec.c            |  67 ++++++++-
>  arch/arm64/kernel/setup.c                    |   7 +-
>  arch/arm64/kernel/smp.c                      |  63 +++++++++
>  arch/arm64/mm/init.c                         | 199 +++++++++++++++++++++++++++
>  include/linux/memblock.h                     |   1 +
>  mm/memblock.c                                |  28 ++++
>  15 files changed, 554 insertions(+), 7 deletions(-)
>  create mode 100644 arch/arm64/kernel/crash_dump.c
> 
> -- 
> 2.10.0
> 

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

* Re: [PATCH v27 0/9] arm64: add kdump support
@ 2016-11-04  3:00   ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-04  3:00 UTC (permalink / raw)
  To: catalin.marinas, will.deacon
  Cc: mark.rutland, geoff, Ruslan Bilovol, kexec, james.morse,
	bauerman, dyoung, linux-arm-kernel

For easier testing, I pushed my patches to:
https://git.linaro.org/people/takahiro.akashi/linux-aarch64.git arm64/kdump
https://git.linaro.org/people/takahiro.akashi/kexec-tools.git arm64/kdump

If anybody tries my patches, please let me know the result.
(Pratyush, thank you for your test.)

Thanks,
-Takahiro AKASHI

On Wed, Nov 02, 2016 at 01:49:59PM +0900, AKASHI Takahiro wrote:
>     v27-specific note: In this version, the change made in v26 was reverted
>     because I've got a comment that /reserved-memory DT property should
>     not be used on UEFI/ACPI systems, even though it is workable under
>     the current implementation. I've also confirmed that Rob doesn't argue
>     any more against using "linux,usable-memory-range".
>     So v27 is essentially the same as v25.
> 
> This patch series adds kdump support on arm64.
> 
> To load a crash-dump kernel to the systems, a series of patches to
> kexec-tools[1] are also needed. Please use the latest one, v4 [2].
> 
> To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
>   - crash utility (v7.1.6 or later) [3]
> 
> 
> [1] https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git
> [1] http://lists.infradead.org/pipermail/kexec/2016-November/017555.html
> [2] https://github.com/crash-utility/crash.git
> 
> Changes for v27 (Nov 2, 2016)
>   o rebased to Linux-v4.9-rc3
>   o revert v26 change, i.e. revive "linux,usable-memory-range" property
>     (patch #2/#3, updating patch #9)
>   o minor fixes per review comments (patch #3/#4/#6/#8)
>   o re-order patches and improve commit messages for readability
> 
> Changes for v26 (Sep 7, 2016):
>   o Use /reserved-memory instead of "linux,usable-memory-range" property
>     (dropping v25's patch#2 and #3, updating ex-patch#9.)
> 
> Changes for v25 (Aug 29, 2016):
>   o Rebase to Linux-4.8-rc4
>   o Use memremap() instead of ioremap_cache() [patch#5]
> 
> Changes for v24 (Aug 9, 2016):
>   o Rebase to Linux-4.8-rc1
>   o Update descriptions about newly added DT proerties
> 
> Changes for v23 (July 26, 2016):
> 
>   o Move memblock_reserve() to a single place in reserve_crashkernel()
>   o Use  cpu_park_loop() in ipi_cpu_crash_stop()
>   o Always enforce ARCH_LOW_ADDRESS_LIMIT to the memory range of crash kernel
>   o Re-implement fdt_enforce_memory_region() to remove non-reserve regions
>     (for ACPI) from usable memory at crash kernel
> 
> Changes for v22 (July 12, 2016):
> 
>   o Export "crashkernel-base" and "crashkernel-size" via device-tree,
>     and add some descriptions about them in chosen.txt
>   o Rename "usable-memory" to "usable-memory-range" to avoid inconsistency
>     with powerpc's "usable-memory"
>   o Make cosmetic changes regarding "ifdef" usage
>   o Correct some wordings in kdump.txt
> 
> Changes for v21 (July 6, 2016):
> 
>   o Remove kexec patches.
>   o Rebase to arm64's for-next/core (Linux-4.7-rc4 based).
>   o Clarify the description about kvm in kdump.txt.
> 
> See the following link [3] for older changes:
> [3]  http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438780.html
> 
> AKASHI Takahiro (8):
>   memblock: add memblock_cap_memory_range()
>   arm64: limit memory regions based on DT property, usable-memory-range
>   arm64: kdump: reserve memory for crash dump kernel
>   arm64: kdump: implement machine_crash_shutdown()
>   arm64: kdump: add VMCOREINFO's for user-space tools
>   arm64: kdump: provide /proc/vmcore file
>   arm64: kdump: enable kdump in defconfig
>   Documentation: kdump: describe arm64 port
> 
> James Morse (1):
>   Documentation: dt: chosen properties for arm64 kdump
> 
>  Documentation/devicetree/bindings/chosen.txt |  50 +++++++
>  Documentation/kdump/kdump.txt                |  16 ++-
>  arch/arm64/Kconfig                           |  11 ++
>  arch/arm64/configs/defconfig                 |   1 +
>  arch/arm64/include/asm/hardirq.h             |   2 +-
>  arch/arm64/include/asm/kexec.h               |  42 +++++-
>  arch/arm64/include/asm/smp.h                 |   2 +
>  arch/arm64/kernel/Makefile                   |   1 +
>  arch/arm64/kernel/crash_dump.c               |  71 ++++++++++
>  arch/arm64/kernel/machine_kexec.c            |  67 ++++++++-
>  arch/arm64/kernel/setup.c                    |   7 +-
>  arch/arm64/kernel/smp.c                      |  63 +++++++++
>  arch/arm64/mm/init.c                         | 199 +++++++++++++++++++++++++++
>  include/linux/memblock.h                     |   1 +
>  mm/memblock.c                                |  28 ++++
>  15 files changed, 554 insertions(+), 7 deletions(-)
>  create mode 100644 arch/arm64/kernel/crash_dump.c
> 
> -- 
> 2.10.0
> 

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

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

* [PATCH v27 0/9] arm64: add kdump support
  2016-11-04  3:00   ` AKASHI Takahiro
@ 2016-11-10 16:06     ` James Morse
  -1 siblings, 0 replies; 58+ messages in thread
From: James Morse @ 2016-11-10 16:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Akashi,

On 04/11/16 03:00, AKASHI Takahiro wrote:
> For easier testing, I pushed my patches to:
> https://git.linaro.org/people/takahiro.akashi/linux-aarch64.git arm64/kdump
> https://git.linaro.org/people/takahiro.akashi/kexec-tools.git arm64/kdump

Aha, thanks. That saved hopping around the mail archives to find the right set
of kdump patches.

> If anybody tries my patches, please let me know the result.

I gave this a spin on Juno with all the page-size va-bits combinations it
supports and used 'crash' to fish around in the resulting image. I also tested
the 4K/39 combination on Seattle that caused us problems in the past.

If its useful:
Tested-by: James Morse <james.morse@arm.com>

So the last thing is review/acks on patch 1
"memblock: add memblock_cap_memory_range()"?



Thanks,

James

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

* Re: [PATCH v27 0/9] arm64: add kdump support
@ 2016-11-10 16:06     ` James Morse
  0 siblings, 0 replies; 58+ messages in thread
From: James Morse @ 2016-11-10 16:06 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: mark.rutland, geoff, catalin.marinas, Ruslan Bilovol,
	will.deacon, bauerman, dyoung, kexec, linux-arm-kernel

Hi Akashi,

On 04/11/16 03:00, AKASHI Takahiro wrote:
> For easier testing, I pushed my patches to:
> https://git.linaro.org/people/takahiro.akashi/linux-aarch64.git arm64/kdump
> https://git.linaro.org/people/takahiro.akashi/kexec-tools.git arm64/kdump

Aha, thanks. That saved hopping around the mail archives to find the right set
of kdump patches.

> If anybody tries my patches, please let me know the result.

I gave this a spin on Juno with all the page-size va-bits combinations it
supports and used 'crash' to fish around in the resulting image. I also tested
the 4K/39 combination on Seattle that caused us problems in the past.

If its useful:
Tested-by: James Morse <james.morse@arm.com>

So the last thing is review/acks on patch 1
"memblock: add memblock_cap_memory_range()"?



Thanks,

James

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

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
  2016-11-02  4:51   ` AKASHI Takahiro
  (?)
@ 2016-11-10 17:27     ` Will Deacon
  -1 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-10 17:27 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: catalin.marinas, akpm, james.morse, geoff, bauerman, dyoung,
	mark.rutland, kexec, linux-arm-kernel, linux-mm

On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> Add memblock_cap_memory_range() which will remove all the memblock regions
> except the range specified in the arguments.
> 
> This function, like memblock_mem_limit_remove_map(), will not remove
> memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> later as "device memory."
> See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> address the mem limit issue").
> 
> This function is used, in a succeeding patch in the series of arm64 kdump
> suuport, to limit the range of usable memory, System RAM, on crash dump
> kernel.
> (Please note that "mem=" parameter is of little use for this purpose.)
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Cc: linux-mm@kvack.org
> Cc: Andrew Morton <akpm@linux-foundation.org>
> ---
>  include/linux/memblock.h |  1 +
>  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
>  2 files changed, 29 insertions(+)
> 
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 5b759c9..0e770af 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
>  phys_addr_t memblock_end_of_DRAM(void);
>  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
>  void memblock_mem_limit_remove_map(phys_addr_t limit);
> +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
>  bool memblock_is_memory(phys_addr_t addr);
>  int memblock_is_map_memory(phys_addr_t addr);
>  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> diff --git a/mm/memblock.c b/mm/memblock.c
> index 7608bc3..eb53876 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
>  			      (phys_addr_t)ULLONG_MAX);
>  }
>  
> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> +{
> +	int start_rgn, end_rgn;
> +	int i, ret;
> +
> +	if (!size)
> +		return;
> +
> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> +						&start_rgn, &end_rgn);
> +	if (ret)
> +		return;
> +
> +	/* remove all the MAP regions */
> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> +			memblock_remove_region(&memblock.memory, i);
> +
> +	for (i = start_rgn - 1; i >= 0; i--)
> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> +			memblock_remove_region(&memblock.memory, i);
> +
> +	/* truncate the reserved regions */
> +	memblock_remove_range(&memblock.reserved, 0, base);
> +	memblock_remove_range(&memblock.reserved,
> +			base + size, (phys_addr_t)ULLONG_MAX);
> +}

This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
you not implement that in terms of your new, more general, function? e.g.
by passing base == 0, and size == limit?

Will

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-10 17:27     ` Will Deacon
  0 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-10 17:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> Add memblock_cap_memory_range() which will remove all the memblock regions
> except the range specified in the arguments.
> 
> This function, like memblock_mem_limit_remove_map(), will not remove
> memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> later as "device memory."
> See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> address the mem limit issue").
> 
> This function is used, in a succeeding patch in the series of arm64 kdump
> suuport, to limit the range of usable memory, System RAM, on crash dump
> kernel.
> (Please note that "mem=" parameter is of little use for this purpose.)
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Cc: linux-mm at kvack.org
> Cc: Andrew Morton <akpm@linux-foundation.org>
> ---
>  include/linux/memblock.h |  1 +
>  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
>  2 files changed, 29 insertions(+)
> 
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 5b759c9..0e770af 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
>  phys_addr_t memblock_end_of_DRAM(void);
>  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
>  void memblock_mem_limit_remove_map(phys_addr_t limit);
> +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
>  bool memblock_is_memory(phys_addr_t addr);
>  int memblock_is_map_memory(phys_addr_t addr);
>  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> diff --git a/mm/memblock.c b/mm/memblock.c
> index 7608bc3..eb53876 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
>  			      (phys_addr_t)ULLONG_MAX);
>  }
>  
> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> +{
> +	int start_rgn, end_rgn;
> +	int i, ret;
> +
> +	if (!size)
> +		return;
> +
> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> +						&start_rgn, &end_rgn);
> +	if (ret)
> +		return;
> +
> +	/* remove all the MAP regions */
> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> +			memblock_remove_region(&memblock.memory, i);
> +
> +	for (i = start_rgn - 1; i >= 0; i--)
> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> +			memblock_remove_region(&memblock.memory, i);
> +
> +	/* truncate the reserved regions */
> +	memblock_remove_range(&memblock.reserved, 0, base);
> +	memblock_remove_range(&memblock.reserved,
> +			base + size, (phys_addr_t)ULLONG_MAX);
> +}

This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
you not implement that in terms of your new, more general, function? e.g.
by passing base == 0, and size == limit?

Will

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-10 17:27     ` Will Deacon
  0 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-10 17:27 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: mark.rutland, geoff, catalin.marinas, kexec, linux-mm,
	james.morse, bauerman, akpm, dyoung, linux-arm-kernel

On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> Add memblock_cap_memory_range() which will remove all the memblock regions
> except the range specified in the arguments.
> 
> This function, like memblock_mem_limit_remove_map(), will not remove
> memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> later as "device memory."
> See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> address the mem limit issue").
> 
> This function is used, in a succeeding patch in the series of arm64 kdump
> suuport, to limit the range of usable memory, System RAM, on crash dump
> kernel.
> (Please note that "mem=" parameter is of little use for this purpose.)
> 
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> Cc: linux-mm@kvack.org
> Cc: Andrew Morton <akpm@linux-foundation.org>
> ---
>  include/linux/memblock.h |  1 +
>  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
>  2 files changed, 29 insertions(+)
> 
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 5b759c9..0e770af 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
>  phys_addr_t memblock_end_of_DRAM(void);
>  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
>  void memblock_mem_limit_remove_map(phys_addr_t limit);
> +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
>  bool memblock_is_memory(phys_addr_t addr);
>  int memblock_is_map_memory(phys_addr_t addr);
>  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> diff --git a/mm/memblock.c b/mm/memblock.c
> index 7608bc3..eb53876 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
>  			      (phys_addr_t)ULLONG_MAX);
>  }
>  
> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> +{
> +	int start_rgn, end_rgn;
> +	int i, ret;
> +
> +	if (!size)
> +		return;
> +
> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> +						&start_rgn, &end_rgn);
> +	if (ret)
> +		return;
> +
> +	/* remove all the MAP regions */
> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> +			memblock_remove_region(&memblock.memory, i);
> +
> +	for (i = start_rgn - 1; i >= 0; i--)
> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> +			memblock_remove_region(&memblock.memory, i);
> +
> +	/* truncate the reserved regions */
> +	memblock_remove_range(&memblock.reserved, 0, base);
> +	memblock_remove_range(&memblock.reserved,
> +			base + size, (phys_addr_t)ULLONG_MAX);
> +}

This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
you not implement that in terms of your new, more general, function? e.g.
by passing base == 0, and size == limit?

Will

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

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
  2016-11-10 17:27     ` Will Deacon
  (?)
@ 2016-11-11  2:50       ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-11  2:50 UTC (permalink / raw)
  To: Will Deacon
  Cc: catalin.marinas, akpm, james.morse, geoff, bauerman, dyoung,
	mark.rutland, kexec, linux-arm-kernel, linux-mm, dennis.chen

Will,
(+ Cc: Dennis)

On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > Add memblock_cap_memory_range() which will remove all the memblock regions
> > except the range specified in the arguments.
> > 
> > This function, like memblock_mem_limit_remove_map(), will not remove
> > memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> > later as "device memory."
> > See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> > address the mem limit issue").
> > 
> > This function is used, in a succeeding patch in the series of arm64 kdump
> > suuport, to limit the range of usable memory, System RAM, on crash dump
> > kernel.
> > (Please note that "mem=" parameter is of little use for this purpose.)
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > Cc: linux-mm@kvack.org
> > Cc: Andrew Morton <akpm@linux-foundation.org>
> > ---
> >  include/linux/memblock.h |  1 +
> >  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
> >  2 files changed, 29 insertions(+)
> > 
> > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > index 5b759c9..0e770af 100644
> > --- a/include/linux/memblock.h
> > +++ b/include/linux/memblock.h
> > @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
> >  phys_addr_t memblock_end_of_DRAM(void);
> >  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
> >  void memblock_mem_limit_remove_map(phys_addr_t limit);
> > +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
> >  bool memblock_is_memory(phys_addr_t addr);
> >  int memblock_is_map_memory(phys_addr_t addr);
> >  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> > diff --git a/mm/memblock.c b/mm/memblock.c
> > index 7608bc3..eb53876 100644
> > --- a/mm/memblock.c
> > +++ b/mm/memblock.c
> > @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
> >  			      (phys_addr_t)ULLONG_MAX);
> >  }
> >  
> > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > +{
> > +	int start_rgn, end_rgn;
> > +	int i, ret;
> > +
> > +	if (!size)
> > +		return;
> > +
> > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > +						&start_rgn, &end_rgn);
> > +	if (ret)
> > +		return;
> > +
> > +	/* remove all the MAP regions */
> > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > +			memblock_remove_region(&memblock.memory, i);
> > +
> > +	for (i = start_rgn - 1; i >= 0; i--)
> > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > +			memblock_remove_region(&memblock.memory, i);
> > +
> > +	/* truncate the reserved regions */
> > +	memblock_remove_range(&memblock.reserved, 0, base);
> > +	memblock_remove_range(&memblock.reserved,
> > +			base + size, (phys_addr_t)ULLONG_MAX);
> > +}
> 
> This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> you not implement that in terms of your new, more general, function? e.g.
> by passing base == 0, and size == limit?

Obviously it's possible.
I actually talked to Dennis before about merging them,
but he was against my idea.

Thanks,
-Takahiro AKASHI

> Will

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-11  2:50       ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-11  2:50 UTC (permalink / raw)
  To: linux-arm-kernel

Will,
(+ Cc: Dennis)

On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > Add memblock_cap_memory_range() which will remove all the memblock regions
> > except the range specified in the arguments.
> > 
> > This function, like memblock_mem_limit_remove_map(), will not remove
> > memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> > later as "device memory."
> > See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> > address the mem limit issue").
> > 
> > This function is used, in a succeeding patch in the series of arm64 kdump
> > suuport, to limit the range of usable memory, System RAM, on crash dump
> > kernel.
> > (Please note that "mem=" parameter is of little use for this purpose.)
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > Cc: linux-mm at kvack.org
> > Cc: Andrew Morton <akpm@linux-foundation.org>
> > ---
> >  include/linux/memblock.h |  1 +
> >  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
> >  2 files changed, 29 insertions(+)
> > 
> > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > index 5b759c9..0e770af 100644
> > --- a/include/linux/memblock.h
> > +++ b/include/linux/memblock.h
> > @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
> >  phys_addr_t memblock_end_of_DRAM(void);
> >  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
> >  void memblock_mem_limit_remove_map(phys_addr_t limit);
> > +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
> >  bool memblock_is_memory(phys_addr_t addr);
> >  int memblock_is_map_memory(phys_addr_t addr);
> >  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> > diff --git a/mm/memblock.c b/mm/memblock.c
> > index 7608bc3..eb53876 100644
> > --- a/mm/memblock.c
> > +++ b/mm/memblock.c
> > @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
> >  			      (phys_addr_t)ULLONG_MAX);
> >  }
> >  
> > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > +{
> > +	int start_rgn, end_rgn;
> > +	int i, ret;
> > +
> > +	if (!size)
> > +		return;
> > +
> > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > +						&start_rgn, &end_rgn);
> > +	if (ret)
> > +		return;
> > +
> > +	/* remove all the MAP regions */
> > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > +			memblock_remove_region(&memblock.memory, i);
> > +
> > +	for (i = start_rgn - 1; i >= 0; i--)
> > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > +			memblock_remove_region(&memblock.memory, i);
> > +
> > +	/* truncate the reserved regions */
> > +	memblock_remove_range(&memblock.reserved, 0, base);
> > +	memblock_remove_range(&memblock.reserved,
> > +			base + size, (phys_addr_t)ULLONG_MAX);
> > +}
> 
> This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> you not implement that in terms of your new, more general, function? e.g.
> by passing base == 0, and size == limit?

Obviously it's possible.
I actually talked to Dennis before about merging them,
but he was against my idea.

Thanks,
-Takahiro AKASHI

> Will

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-11  2:50       ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-11  2:50 UTC (permalink / raw)
  To: Will Deacon
  Cc: mark.rutland, geoff, catalin.marinas, kexec, linux-mm,
	james.morse, bauerman, dennis.chen, akpm, dyoung,
	linux-arm-kernel

Will,
(+ Cc: Dennis)

On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > Add memblock_cap_memory_range() which will remove all the memblock regions
> > except the range specified in the arguments.
> > 
> > This function, like memblock_mem_limit_remove_map(), will not remove
> > memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> > later as "device memory."
> > See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> > address the mem limit issue").
> > 
> > This function is used, in a succeeding patch in the series of arm64 kdump
> > suuport, to limit the range of usable memory, System RAM, on crash dump
> > kernel.
> > (Please note that "mem=" parameter is of little use for this purpose.)
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > Cc: linux-mm@kvack.org
> > Cc: Andrew Morton <akpm@linux-foundation.org>
> > ---
> >  include/linux/memblock.h |  1 +
> >  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
> >  2 files changed, 29 insertions(+)
> > 
> > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > index 5b759c9..0e770af 100644
> > --- a/include/linux/memblock.h
> > +++ b/include/linux/memblock.h
> > @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
> >  phys_addr_t memblock_end_of_DRAM(void);
> >  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
> >  void memblock_mem_limit_remove_map(phys_addr_t limit);
> > +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
> >  bool memblock_is_memory(phys_addr_t addr);
> >  int memblock_is_map_memory(phys_addr_t addr);
> >  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> > diff --git a/mm/memblock.c b/mm/memblock.c
> > index 7608bc3..eb53876 100644
> > --- a/mm/memblock.c
> > +++ b/mm/memblock.c
> > @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
> >  			      (phys_addr_t)ULLONG_MAX);
> >  }
> >  
> > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > +{
> > +	int start_rgn, end_rgn;
> > +	int i, ret;
> > +
> > +	if (!size)
> > +		return;
> > +
> > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > +						&start_rgn, &end_rgn);
> > +	if (ret)
> > +		return;
> > +
> > +	/* remove all the MAP regions */
> > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > +			memblock_remove_region(&memblock.memory, i);
> > +
> > +	for (i = start_rgn - 1; i >= 0; i--)
> > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > +			memblock_remove_region(&memblock.memory, i);
> > +
> > +	/* truncate the reserved regions */
> > +	memblock_remove_range(&memblock.reserved, 0, base);
> > +	memblock_remove_range(&memblock.reserved,
> > +			base + size, (phys_addr_t)ULLONG_MAX);
> > +}
> 
> This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> you not implement that in terms of your new, more general, function? e.g.
> by passing base == 0, and size == limit?

Obviously it's possible.
I actually talked to Dennis before about merging them,
but he was against my idea.

Thanks,
-Takahiro AKASHI

> Will

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

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
  2016-11-11  2:50       ` AKASHI Takahiro
  (?)
@ 2016-11-11  3:19         ` Dennis Chen
  -1 siblings, 0 replies; 58+ messages in thread
From: Dennis Chen @ 2016-11-11  3:19 UTC (permalink / raw)
  To: AKASHI Takahiro, Will Deacon, catalin.marinas, akpm, james.morse,
	geoff, bauerman, dyoung, mark.rutland, kexec, linux-arm-kernel,
	linux-mm

On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> Will,
> (+ Cc: Dennis)
> 
> On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > Add memblock_cap_memory_range() which will remove all the memblock regions
> > > except the range specified in the arguments.
> > > 
> > > This function, like memblock_mem_limit_remove_map(), will not remove
> > > memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> > > later as "device memory."
> > > See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> > > address the mem limit issue").
> > > 
> > > This function is used, in a succeeding patch in the series of arm64 kdump
> > > suuport, to limit the range of usable memory, System RAM, on crash dump
> > > kernel.
> > > (Please note that "mem=" parameter is of little use for this purpose.)
> > > 
> > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > Cc: linux-mm@kvack.org
> > > Cc: Andrew Morton <akpm@linux-foundation.org>
> > > ---
> > >  include/linux/memblock.h |  1 +
> > >  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
> > >  2 files changed, 29 insertions(+)
> > > 
> > > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > > index 5b759c9..0e770af 100644
> > > --- a/include/linux/memblock.h
> > > +++ b/include/linux/memblock.h
> > > @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
> > >  phys_addr_t memblock_end_of_DRAM(void);
> > >  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
> > >  void memblock_mem_limit_remove_map(phys_addr_t limit);
> > > +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
> > >  bool memblock_is_memory(phys_addr_t addr);
> > >  int memblock_is_map_memory(phys_addr_t addr);
> > >  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> > > diff --git a/mm/memblock.c b/mm/memblock.c
> > > index 7608bc3..eb53876 100644
> > > --- a/mm/memblock.c
> > > +++ b/mm/memblock.c
> > > @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
> > >  			      (phys_addr_t)ULLONG_MAX);
> > >  }
> > >  
> > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > +{
> > > +	int start_rgn, end_rgn;
> > > +	int i, ret;
> > > +
> > > +	if (!size)
> > > +		return;
> > > +
> > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > +						&start_rgn, &end_rgn);
> > > +	if (ret)
> > > +		return;
> > > +
> > > +	/* remove all the MAP regions */
> > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > +			memblock_remove_region(&memblock.memory, i);
> > > +
> > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > +			memblock_remove_region(&memblock.memory, i);
> > > +
> > > +	/* truncate the reserved regions */
> > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > +	memblock_remove_range(&memblock.reserved,
> > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > +}
> > 
> > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > you not implement that in terms of your new, more general, function? e.g.
> > by passing base == 0, and size == limit?
> 
> Obviously it's possible.
> I actually talked to Dennis before about merging them,
> but he was against my idea.
>
Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
So feel free to do that as Will'll do
> 
> Thanks,
> -Takahiro AKASHI
> 
> > Will

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-11  3:19         ` Dennis Chen
  0 siblings, 0 replies; 58+ messages in thread
From: Dennis Chen @ 2016-11-11  3:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> Will,
> (+ Cc: Dennis)
> 
> On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > Add memblock_cap_memory_range() which will remove all the memblock regions
> > > except the range specified in the arguments.
> > > 
> > > This function, like memblock_mem_limit_remove_map(), will not remove
> > > memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> > > later as "device memory."
> > > See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> > > address the mem limit issue").
> > > 
> > > This function is used, in a succeeding patch in the series of arm64 kdump
> > > suuport, to limit the range of usable memory, System RAM, on crash dump
> > > kernel.
> > > (Please note that "mem=" parameter is of little use for this purpose.)
> > > 
> > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > Cc: linux-mm at kvack.org
> > > Cc: Andrew Morton <akpm@linux-foundation.org>
> > > ---
> > >  include/linux/memblock.h |  1 +
> > >  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
> > >  2 files changed, 29 insertions(+)
> > > 
> > > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > > index 5b759c9..0e770af 100644
> > > --- a/include/linux/memblock.h
> > > +++ b/include/linux/memblock.h
> > > @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
> > >  phys_addr_t memblock_end_of_DRAM(void);
> > >  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
> > >  void memblock_mem_limit_remove_map(phys_addr_t limit);
> > > +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
> > >  bool memblock_is_memory(phys_addr_t addr);
> > >  int memblock_is_map_memory(phys_addr_t addr);
> > >  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> > > diff --git a/mm/memblock.c b/mm/memblock.c
> > > index 7608bc3..eb53876 100644
> > > --- a/mm/memblock.c
> > > +++ b/mm/memblock.c
> > > @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
> > >  			      (phys_addr_t)ULLONG_MAX);
> > >  }
> > >  
> > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > +{
> > > +	int start_rgn, end_rgn;
> > > +	int i, ret;
> > > +
> > > +	if (!size)
> > > +		return;
> > > +
> > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > +						&start_rgn, &end_rgn);
> > > +	if (ret)
> > > +		return;
> > > +
> > > +	/* remove all the MAP regions */
> > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > +			memblock_remove_region(&memblock.memory, i);
> > > +
> > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > +			memblock_remove_region(&memblock.memory, i);
> > > +
> > > +	/* truncate the reserved regions */
> > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > +	memblock_remove_range(&memblock.reserved,
> > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > +}
> > 
> > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > you not implement that in terms of your new, more general, function? e.g.
> > by passing base == 0, and size == limit?
> 
> Obviously it's possible.
> I actually talked to Dennis before about merging them,
> but he was against my idea.
>
Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
So feel free to do that as Will'll do
> 
> Thanks,
> -Takahiro AKASHI
> 
> > Will

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-11  3:19         ` Dennis Chen
  0 siblings, 0 replies; 58+ messages in thread
From: Dennis Chen @ 2016-11-11  3:19 UTC (permalink / raw)
  To: AKASHI Takahiro, Will Deacon, catalin.marinas, akpm, james.morse,
	geoff, bauerman, dyoung, mark.rutland, kexec, linux-arm-kernel,
	linux-mm
  Cc: nd

On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> Will,
> (+ Cc: Dennis)
> 
> On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > Add memblock_cap_memory_range() which will remove all the memblock regions
> > > except the range specified in the arguments.
> > > 
> > > This function, like memblock_mem_limit_remove_map(), will not remove
> > > memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> > > later as "device memory."
> > > See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> > > address the mem limit issue").
> > > 
> > > This function is used, in a succeeding patch in the series of arm64 kdump
> > > suuport, to limit the range of usable memory, System RAM, on crash dump
> > > kernel.
> > > (Please note that "mem=" parameter is of little use for this purpose.)
> > > 
> > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > Cc: linux-mm@kvack.org
> > > Cc: Andrew Morton <akpm@linux-foundation.org>
> > > ---
> > >  include/linux/memblock.h |  1 +
> > >  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
> > >  2 files changed, 29 insertions(+)
> > > 
> > > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > > index 5b759c9..0e770af 100644
> > > --- a/include/linux/memblock.h
> > > +++ b/include/linux/memblock.h
> > > @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
> > >  phys_addr_t memblock_end_of_DRAM(void);
> > >  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
> > >  void memblock_mem_limit_remove_map(phys_addr_t limit);
> > > +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
> > >  bool memblock_is_memory(phys_addr_t addr);
> > >  int memblock_is_map_memory(phys_addr_t addr);
> > >  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> > > diff --git a/mm/memblock.c b/mm/memblock.c
> > > index 7608bc3..eb53876 100644
> > > --- a/mm/memblock.c
> > > +++ b/mm/memblock.c
> > > @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
> > >  			      (phys_addr_t)ULLONG_MAX);
> > >  }
> > >  
> > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > +{
> > > +	int start_rgn, end_rgn;
> > > +	int i, ret;
> > > +
> > > +	if (!size)
> > > +		return;
> > > +
> > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > +						&start_rgn, &end_rgn);
> > > +	if (ret)
> > > +		return;
> > > +
> > > +	/* remove all the MAP regions */
> > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > +			memblock_remove_region(&memblock.memory, i);
> > > +
> > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > +			memblock_remove_region(&memblock.memory, i);
> > > +
> > > +	/* truncate the reserved regions */
> > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > +	memblock_remove_range(&memblock.reserved,
> > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > +}
> > 
> > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > you not implement that in terms of your new, more general, function? e.g.
> > by passing base == 0, and size == limit?
> 
> Obviously it's possible.
> I actually talked to Dennis before about merging them,
> but he was against my idea.
>
Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
So feel free to do that as Will'll do
> 
> Thanks,
> -Takahiro AKASHI
> 
> > Will

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

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
  2016-11-11  3:19         ` Dennis Chen
  (?)
@ 2016-11-14  5:55           ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-14  5:55 UTC (permalink / raw)
  To: Dennis Chen, Will Deacon
  Cc: catalin.marinas, akpm, james.morse, geoff, bauerman, dyoung,
	mark.rutland, kexec, linux-arm-kernel, linux-mm

On Fri, Nov 11, 2016 at 11:19:04AM +0800, Dennis Chen wrote:
> On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> > Will,
> > (+ Cc: Dennis)
> > 
> > On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > > Add memblock_cap_memory_range() which will remove all the memblock regions
> > > > except the range specified in the arguments.
> > > > 
> > > > This function, like memblock_mem_limit_remove_map(), will not remove
> > > > memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> > > > later as "device memory."
> > > > See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> > > > address the mem limit issue").
> > > > 
> > > > This function is used, in a succeeding patch in the series of arm64 kdump
> > > > suuport, to limit the range of usable memory, System RAM, on crash dump
> > > > kernel.
> > > > (Please note that "mem=" parameter is of little use for this purpose.)
> > > > 
> > > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > > Cc: linux-mm@kvack.org
> > > > Cc: Andrew Morton <akpm@linux-foundation.org>
> > > > ---
> > > >  include/linux/memblock.h |  1 +
> > > >  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
> > > >  2 files changed, 29 insertions(+)
> > > > 
> > > > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > > > index 5b759c9..0e770af 100644
> > > > --- a/include/linux/memblock.h
> > > > +++ b/include/linux/memblock.h
> > > > @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
> > > >  phys_addr_t memblock_end_of_DRAM(void);
> > > >  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
> > > >  void memblock_mem_limit_remove_map(phys_addr_t limit);
> > > > +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
> > > >  bool memblock_is_memory(phys_addr_t addr);
> > > >  int memblock_is_map_memory(phys_addr_t addr);
> > > >  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> > > > diff --git a/mm/memblock.c b/mm/memblock.c
> > > > index 7608bc3..eb53876 100644
> > > > --- a/mm/memblock.c
> > > > +++ b/mm/memblock.c
> > > > @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
> > > >  			      (phys_addr_t)ULLONG_MAX);
> > > >  }
> > > >  
> > > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > > +{
> > > > +	int start_rgn, end_rgn;
> > > > +	int i, ret;
> > > > +
> > > > +	if (!size)
> > > > +		return;
> > > > +
> > > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > > +						&start_rgn, &end_rgn);
> > > > +	if (ret)
> > > > +		return;
> > > > +
> > > > +	/* remove all the MAP regions */
> > > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > +			memblock_remove_region(&memblock.memory, i);
> > > > +
> > > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > +			memblock_remove_region(&memblock.memory, i);
> > > > +
> > > > +	/* truncate the reserved regions */
> > > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > > +	memblock_remove_range(&memblock.reserved,
> > > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > > +}
> > > 
> > > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > > you not implement that in terms of your new, more general, function? e.g.
> > > by passing base == 0, and size == limit?
> > 
> > Obviously it's possible.
> > I actually talked to Dennis before about merging them,
> > but he was against my idea.
> >
> Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
> So feel free to do that as Will'll do

OK, but I found that the two functions have a bit different semantics
in clipping memory range, in particular, when the range [base,base+size)
goes across several regions with a gap.
(This does not happen in my arm64 kdump, though.)
That is, 'limit' in memblock_mem_limit_remove_map() means total size of
available memory, while 'size' in memblock_cap_memory_range() indicates
the size of _continuous_ memory range.

So I added an extra argument, exact, to a common function to specify
distinct behaviors. Confusing? Please see the patch below.

If nobody objects to this merge, I will submit a whole patchset of kdump
again.

Thanks,
-Takahiro AKASHI
===8<===
 include/linux/memblock.h |  1 +
 mm/memblock.c            | 91 +++++++++++++++++++++++++++++++++++-------------
 2 files changed, 68 insertions(+), 24 deletions(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 5b759c9..0e770af 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
 phys_addr_t memblock_end_of_DRAM(void);
 void memblock_enforce_memory_limit(phys_addr_t memory_limit);
 void memblock_mem_limit_remove_map(phys_addr_t limit);
+void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
 bool memblock_is_memory(phys_addr_t addr);
 int memblock_is_map_memory(phys_addr_t addr);
 int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
diff --git a/mm/memblock.c b/mm/memblock.c
index 7608bc3..5f849a9 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1473,9 +1473,10 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)
 	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
 }
 
-static phys_addr_t __init_memblock __find_max_addr(phys_addr_t limit)
+static phys_addr_t __init_memblock __find_max_addr(phys_addr_t min,
+							phys_addr_t limit)
 {
-	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
+	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX, base, size;
 	struct memblock_region *r;
 
 	/*
@@ -1484,11 +1485,22 @@ static phys_addr_t __init_memblock __find_max_addr(phys_addr_t limit)
 	 * of those regions, max_addr will keep original value ULLONG_MAX
 	 */
 	for_each_memblock(memory, r) {
-		if (limit <= r->size) {
-			max_addr = r->base + limit;
+		if (min >= r->base + r->size)
+			continue;
+
+		if (r->base <= min) {
+			base = min;
+			size = r->base + r->size - min;
+		} else {
+			base = r->base;
+			size = r->size;
+		}
+
+		if (limit <= size) {
+			max_addr = base + limit;
 			break;
 		}
-		limit -= r->size;
+		limit -= size;
 	}
 
 	return max_addr;
@@ -1501,7 +1513,7 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 	if (!limit)
 		return;
 
-	max_addr = __find_max_addr(limit);
+	max_addr = __find_max_addr(0, limit);
 
 	/* @limit exceeds the total size of the memory, do nothing */
 	if (max_addr == (phys_addr_t)ULLONG_MAX)
@@ -1514,34 +1526,65 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 			      (phys_addr_t)ULLONG_MAX);
 }
 
-void __init memblock_mem_limit_remove_map(phys_addr_t limit)
+/*
+ * __memblock_cap_memory_range - cap memblock regions
+ * @base: lowest address to clip
+ * @size: size of memory range
+ * @exact: true or false
+ *
+ * If @exact is true, the exact range [@base, @base+@size) of memory with
+ * kernel direct mapping is clipped from memblock.memory. Otherwise, total
+ * of @size of memory is clipped starting from @base.
+ */
+static void __init __memblock_cap_memory_range(phys_addr_t base,
+					phys_addr_t size, bool exact)
 {
-	struct memblock_type *type = &memblock.memory;
-	phys_addr_t max_addr;
-	int i, ret, start_rgn, end_rgn;
+	int start_rgn, end_rgn;
+	int i, ret;
 
-	if (!limit)
+	if (!size)
 		return;
 
-	max_addr = __find_max_addr(limit);
+	if (!exact) {
+		phys_addr_t max_addr;
 
-	/* @limit exceeds the total size of the memory, do nothing */
-	if (max_addr == (phys_addr_t)ULLONG_MAX)
-		return;
+		max_addr = __find_max_addr(base, size);
+		/* @size exceeds the total size of the memory, do nothing */
+		if (max_addr == (phys_addr_t)ULLONG_MAX)
+			return;
+
+		/* recalc the size to clip the exact range [@base, max_addr) */
+		size = max_addr  - base;
+	}
 
-	ret = memblock_isolate_range(type, max_addr, (phys_addr_t)ULLONG_MAX,
-				&start_rgn, &end_rgn);
+	ret = memblock_isolate_range(&memblock.memory, base, size,
+						&start_rgn, &end_rgn);
 	if (ret)
 		return;
 
-	/* remove all the MAP regions above the limit */
-	for (i = end_rgn - 1; i >= start_rgn; i--) {
-		if (!memblock_is_nomap(&type->regions[i]))
-			memblock_remove_region(type, i);
-	}
+	/* remove all the other MAP regions */
+	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	for (i = start_rgn - 1; i >= 0; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
 	/* truncate the reserved regions */
-	memblock_remove_range(&memblock.reserved, max_addr,
-			      (phys_addr_t)ULLONG_MAX);
+	memblock_remove_range(&memblock.reserved, 0, base);
+	memblock_remove_range(&memblock.reserved,
+			base + size, (phys_addr_t)ULLONG_MAX);
+}
+
+void __init memblock_mem_limit_remove_map(phys_addr_t limit)
+{
+	__memblock_cap_memory_range(0, limit, false);
+}
+
+void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
+{
+	__memblock_cap_memory_range(base, size, true);
 }
 
 static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
-- 
2.10.0

===>8===

> > 
> > Thanks,
> > -Takahiro AKASHI
> > 
> > > Will

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-14  5:55           ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-14  5:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Nov 11, 2016 at 11:19:04AM +0800, Dennis Chen wrote:
> On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> > Will,
> > (+ Cc: Dennis)
> > 
> > On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > > Add memblock_cap_memory_range() which will remove all the memblock regions
> > > > except the range specified in the arguments.
> > > > 
> > > > This function, like memblock_mem_limit_remove_map(), will not remove
> > > > memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> > > > later as "device memory."
> > > > See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> > > > address the mem limit issue").
> > > > 
> > > > This function is used, in a succeeding patch in the series of arm64 kdump
> > > > suuport, to limit the range of usable memory, System RAM, on crash dump
> > > > kernel.
> > > > (Please note that "mem=" parameter is of little use for this purpose.)
> > > > 
> > > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > > Cc: linux-mm at kvack.org
> > > > Cc: Andrew Morton <akpm@linux-foundation.org>
> > > > ---
> > > >  include/linux/memblock.h |  1 +
> > > >  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
> > > >  2 files changed, 29 insertions(+)
> > > > 
> > > > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > > > index 5b759c9..0e770af 100644
> > > > --- a/include/linux/memblock.h
> > > > +++ b/include/linux/memblock.h
> > > > @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
> > > >  phys_addr_t memblock_end_of_DRAM(void);
> > > >  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
> > > >  void memblock_mem_limit_remove_map(phys_addr_t limit);
> > > > +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
> > > >  bool memblock_is_memory(phys_addr_t addr);
> > > >  int memblock_is_map_memory(phys_addr_t addr);
> > > >  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> > > > diff --git a/mm/memblock.c b/mm/memblock.c
> > > > index 7608bc3..eb53876 100644
> > > > --- a/mm/memblock.c
> > > > +++ b/mm/memblock.c
> > > > @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
> > > >  			      (phys_addr_t)ULLONG_MAX);
> > > >  }
> > > >  
> > > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > > +{
> > > > +	int start_rgn, end_rgn;
> > > > +	int i, ret;
> > > > +
> > > > +	if (!size)
> > > > +		return;
> > > > +
> > > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > > +						&start_rgn, &end_rgn);
> > > > +	if (ret)
> > > > +		return;
> > > > +
> > > > +	/* remove all the MAP regions */
> > > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > +			memblock_remove_region(&memblock.memory, i);
> > > > +
> > > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > +			memblock_remove_region(&memblock.memory, i);
> > > > +
> > > > +	/* truncate the reserved regions */
> > > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > > +	memblock_remove_range(&memblock.reserved,
> > > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > > +}
> > > 
> > > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > > you not implement that in terms of your new, more general, function? e.g.
> > > by passing base == 0, and size == limit?
> > 
> > Obviously it's possible.
> > I actually talked to Dennis before about merging them,
> > but he was against my idea.
> >
> Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
> So feel free to do that as Will'll do

OK, but I found that the two functions have a bit different semantics
in clipping memory range, in particular, when the range [base,base+size)
goes across several regions with a gap.
(This does not happen in my arm64 kdump, though.)
That is, 'limit' in memblock_mem_limit_remove_map() means total size of
available memory, while 'size' in memblock_cap_memory_range() indicates
the size of _continuous_ memory range.

So I added an extra argument, exact, to a common function to specify
distinct behaviors. Confusing? Please see the patch below.

If nobody objects to this merge, I will submit a whole patchset of kdump
again.

Thanks,
-Takahiro AKASHI
===8<===
 include/linux/memblock.h |  1 +
 mm/memblock.c            | 91 +++++++++++++++++++++++++++++++++++-------------
 2 files changed, 68 insertions(+), 24 deletions(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 5b759c9..0e770af 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
 phys_addr_t memblock_end_of_DRAM(void);
 void memblock_enforce_memory_limit(phys_addr_t memory_limit);
 void memblock_mem_limit_remove_map(phys_addr_t limit);
+void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
 bool memblock_is_memory(phys_addr_t addr);
 int memblock_is_map_memory(phys_addr_t addr);
 int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
diff --git a/mm/memblock.c b/mm/memblock.c
index 7608bc3..5f849a9 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1473,9 +1473,10 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)
 	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
 }
 
-static phys_addr_t __init_memblock __find_max_addr(phys_addr_t limit)
+static phys_addr_t __init_memblock __find_max_addr(phys_addr_t min,
+							phys_addr_t limit)
 {
-	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
+	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX, base, size;
 	struct memblock_region *r;
 
 	/*
@@ -1484,11 +1485,22 @@ static phys_addr_t __init_memblock __find_max_addr(phys_addr_t limit)
 	 * of those regions, max_addr will keep original value ULLONG_MAX
 	 */
 	for_each_memblock(memory, r) {
-		if (limit <= r->size) {
-			max_addr = r->base + limit;
+		if (min >= r->base + r->size)
+			continue;
+
+		if (r->base <= min) {
+			base = min;
+			size = r->base + r->size - min;
+		} else {
+			base = r->base;
+			size = r->size;
+		}
+
+		if (limit <= size) {
+			max_addr = base + limit;
 			break;
 		}
-		limit -= r->size;
+		limit -= size;
 	}
 
 	return max_addr;
@@ -1501,7 +1513,7 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 	if (!limit)
 		return;
 
-	max_addr = __find_max_addr(limit);
+	max_addr = __find_max_addr(0, limit);
 
 	/* @limit exceeds the total size of the memory, do nothing */
 	if (max_addr == (phys_addr_t)ULLONG_MAX)
@@ -1514,34 +1526,65 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 			      (phys_addr_t)ULLONG_MAX);
 }
 
-void __init memblock_mem_limit_remove_map(phys_addr_t limit)
+/*
+ * __memblock_cap_memory_range - cap memblock regions
+ * @base: lowest address to clip
+ * @size: size of memory range
+ * @exact: true or false
+ *
+ * If @exact is true, the exact range [@base, @base+ at size) of memory with
+ * kernel direct mapping is clipped from memblock.memory. Otherwise, total
+ * of @size of memory is clipped starting from @base.
+ */
+static void __init __memblock_cap_memory_range(phys_addr_t base,
+					phys_addr_t size, bool exact)
 {
-	struct memblock_type *type = &memblock.memory;
-	phys_addr_t max_addr;
-	int i, ret, start_rgn, end_rgn;
+	int start_rgn, end_rgn;
+	int i, ret;
 
-	if (!limit)
+	if (!size)
 		return;
 
-	max_addr = __find_max_addr(limit);
+	if (!exact) {
+		phys_addr_t max_addr;
 
-	/* @limit exceeds the total size of the memory, do nothing */
-	if (max_addr == (phys_addr_t)ULLONG_MAX)
-		return;
+		max_addr = __find_max_addr(base, size);
+		/* @size exceeds the total size of the memory, do nothing */
+		if (max_addr == (phys_addr_t)ULLONG_MAX)
+			return;
+
+		/* recalc the size to clip the exact range [@base, max_addr) */
+		size = max_addr  - base;
+	}
 
-	ret = memblock_isolate_range(type, max_addr, (phys_addr_t)ULLONG_MAX,
-				&start_rgn, &end_rgn);
+	ret = memblock_isolate_range(&memblock.memory, base, size,
+						&start_rgn, &end_rgn);
 	if (ret)
 		return;
 
-	/* remove all the MAP regions above the limit */
-	for (i = end_rgn - 1; i >= start_rgn; i--) {
-		if (!memblock_is_nomap(&type->regions[i]))
-			memblock_remove_region(type, i);
-	}
+	/* remove all the other MAP regions */
+	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	for (i = start_rgn - 1; i >= 0; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
 	/* truncate the reserved regions */
-	memblock_remove_range(&memblock.reserved, max_addr,
-			      (phys_addr_t)ULLONG_MAX);
+	memblock_remove_range(&memblock.reserved, 0, base);
+	memblock_remove_range(&memblock.reserved,
+			base + size, (phys_addr_t)ULLONG_MAX);
+}
+
+void __init memblock_mem_limit_remove_map(phys_addr_t limit)
+{
+	__memblock_cap_memory_range(0, limit, false);
+}
+
+void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
+{
+	__memblock_cap_memory_range(base, size, true);
 }
 
 static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
-- 
2.10.0

===>8===

> > 
> > Thanks,
> > -Takahiro AKASHI
> > 
> > > Will

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-14  5:55           ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-14  5:55 UTC (permalink / raw)
  To: Dennis Chen, Will Deacon
  Cc: mark.rutland, geoff, catalin.marinas, kexec, linux-mm,
	james.morse, bauerman, akpm, nd, dyoung, linux-arm-kernel

On Fri, Nov 11, 2016 at 11:19:04AM +0800, Dennis Chen wrote:
> On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> > Will,
> > (+ Cc: Dennis)
> > 
> > On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > > Add memblock_cap_memory_range() which will remove all the memblock regions
> > > > except the range specified in the arguments.
> > > > 
> > > > This function, like memblock_mem_limit_remove_map(), will not remove
> > > > memblocks with MEMMAP_NOMAP attribute as they may be mapped and accessed
> > > > later as "device memory."
> > > > See the commit a571d4eb55d8 ("mm/memblock.c: add new infrastructure to
> > > > address the mem limit issue").
> > > > 
> > > > This function is used, in a succeeding patch in the series of arm64 kdump
> > > > suuport, to limit the range of usable memory, System RAM, on crash dump
> > > > kernel.
> > > > (Please note that "mem=" parameter is of little use for this purpose.)
> > > > 
> > > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > > Cc: linux-mm@kvack.org
> > > > Cc: Andrew Morton <akpm@linux-foundation.org>
> > > > ---
> > > >  include/linux/memblock.h |  1 +
> > > >  mm/memblock.c            | 28 ++++++++++++++++++++++++++++
> > > >  2 files changed, 29 insertions(+)
> > > > 
> > > > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > > > index 5b759c9..0e770af 100644
> > > > --- a/include/linux/memblock.h
> > > > +++ b/include/linux/memblock.h
> > > > @@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
> > > >  phys_addr_t memblock_end_of_DRAM(void);
> > > >  void memblock_enforce_memory_limit(phys_addr_t memory_limit);
> > > >  void memblock_mem_limit_remove_map(phys_addr_t limit);
> > > > +void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
> > > >  bool memblock_is_memory(phys_addr_t addr);
> > > >  int memblock_is_map_memory(phys_addr_t addr);
> > > >  int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
> > > > diff --git a/mm/memblock.c b/mm/memblock.c
> > > > index 7608bc3..eb53876 100644
> > > > --- a/mm/memblock.c
> > > > +++ b/mm/memblock.c
> > > > @@ -1544,6 +1544,34 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
> > > >  			      (phys_addr_t)ULLONG_MAX);
> > > >  }
> > > >  
> > > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > > +{
> > > > +	int start_rgn, end_rgn;
> > > > +	int i, ret;
> > > > +
> > > > +	if (!size)
> > > > +		return;
> > > > +
> > > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > > +						&start_rgn, &end_rgn);
> > > > +	if (ret)
> > > > +		return;
> > > > +
> > > > +	/* remove all the MAP regions */
> > > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > +			memblock_remove_region(&memblock.memory, i);
> > > > +
> > > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > +			memblock_remove_region(&memblock.memory, i);
> > > > +
> > > > +	/* truncate the reserved regions */
> > > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > > +	memblock_remove_range(&memblock.reserved,
> > > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > > +}
> > > 
> > > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > > you not implement that in terms of your new, more general, function? e.g.
> > > by passing base == 0, and size == limit?
> > 
> > Obviously it's possible.
> > I actually talked to Dennis before about merging them,
> > but he was against my idea.
> >
> Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
> So feel free to do that as Will'll do

OK, but I found that the two functions have a bit different semantics
in clipping memory range, in particular, when the range [base,base+size)
goes across several regions with a gap.
(This does not happen in my arm64 kdump, though.)
That is, 'limit' in memblock_mem_limit_remove_map() means total size of
available memory, while 'size' in memblock_cap_memory_range() indicates
the size of _continuous_ memory range.

So I added an extra argument, exact, to a common function to specify
distinct behaviors. Confusing? Please see the patch below.

If nobody objects to this merge, I will submit a whole patchset of kdump
again.

Thanks,
-Takahiro AKASHI
===8<===
 include/linux/memblock.h |  1 +
 mm/memblock.c            | 91 +++++++++++++++++++++++++++++++++++-------------
 2 files changed, 68 insertions(+), 24 deletions(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 5b759c9..0e770af 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -334,6 +334,7 @@ phys_addr_t memblock_start_of_DRAM(void);
 phys_addr_t memblock_end_of_DRAM(void);
 void memblock_enforce_memory_limit(phys_addr_t memory_limit);
 void memblock_mem_limit_remove_map(phys_addr_t limit);
+void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
 bool memblock_is_memory(phys_addr_t addr);
 int memblock_is_map_memory(phys_addr_t addr);
 int memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
diff --git a/mm/memblock.c b/mm/memblock.c
index 7608bc3..5f849a9 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1473,9 +1473,10 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)
 	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
 }
 
-static phys_addr_t __init_memblock __find_max_addr(phys_addr_t limit)
+static phys_addr_t __init_memblock __find_max_addr(phys_addr_t min,
+							phys_addr_t limit)
 {
-	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
+	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX, base, size;
 	struct memblock_region *r;
 
 	/*
@@ -1484,11 +1485,22 @@ static phys_addr_t __init_memblock __find_max_addr(phys_addr_t limit)
 	 * of those regions, max_addr will keep original value ULLONG_MAX
 	 */
 	for_each_memblock(memory, r) {
-		if (limit <= r->size) {
-			max_addr = r->base + limit;
+		if (min >= r->base + r->size)
+			continue;
+
+		if (r->base <= min) {
+			base = min;
+			size = r->base + r->size - min;
+		} else {
+			base = r->base;
+			size = r->size;
+		}
+
+		if (limit <= size) {
+			max_addr = base + limit;
 			break;
 		}
-		limit -= r->size;
+		limit -= size;
 	}
 
 	return max_addr;
@@ -1501,7 +1513,7 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 	if (!limit)
 		return;
 
-	max_addr = __find_max_addr(limit);
+	max_addr = __find_max_addr(0, limit);
 
 	/* @limit exceeds the total size of the memory, do nothing */
 	if (max_addr == (phys_addr_t)ULLONG_MAX)
@@ -1514,34 +1526,65 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 			      (phys_addr_t)ULLONG_MAX);
 }
 
-void __init memblock_mem_limit_remove_map(phys_addr_t limit)
+/*
+ * __memblock_cap_memory_range - cap memblock regions
+ * @base: lowest address to clip
+ * @size: size of memory range
+ * @exact: true or false
+ *
+ * If @exact is true, the exact range [@base, @base+@size) of memory with
+ * kernel direct mapping is clipped from memblock.memory. Otherwise, total
+ * of @size of memory is clipped starting from @base.
+ */
+static void __init __memblock_cap_memory_range(phys_addr_t base,
+					phys_addr_t size, bool exact)
 {
-	struct memblock_type *type = &memblock.memory;
-	phys_addr_t max_addr;
-	int i, ret, start_rgn, end_rgn;
+	int start_rgn, end_rgn;
+	int i, ret;
 
-	if (!limit)
+	if (!size)
 		return;
 
-	max_addr = __find_max_addr(limit);
+	if (!exact) {
+		phys_addr_t max_addr;
 
-	/* @limit exceeds the total size of the memory, do nothing */
-	if (max_addr == (phys_addr_t)ULLONG_MAX)
-		return;
+		max_addr = __find_max_addr(base, size);
+		/* @size exceeds the total size of the memory, do nothing */
+		if (max_addr == (phys_addr_t)ULLONG_MAX)
+			return;
+
+		/* recalc the size to clip the exact range [@base, max_addr) */
+		size = max_addr  - base;
+	}
 
-	ret = memblock_isolate_range(type, max_addr, (phys_addr_t)ULLONG_MAX,
-				&start_rgn, &end_rgn);
+	ret = memblock_isolate_range(&memblock.memory, base, size,
+						&start_rgn, &end_rgn);
 	if (ret)
 		return;
 
-	/* remove all the MAP regions above the limit */
-	for (i = end_rgn - 1; i >= start_rgn; i--) {
-		if (!memblock_is_nomap(&type->regions[i]))
-			memblock_remove_region(type, i);
-	}
+	/* remove all the other MAP regions */
+	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	for (i = start_rgn - 1; i >= 0; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
 	/* truncate the reserved regions */
-	memblock_remove_range(&memblock.reserved, max_addr,
-			      (phys_addr_t)ULLONG_MAX);
+	memblock_remove_range(&memblock.reserved, 0, base);
+	memblock_remove_range(&memblock.reserved,
+			base + size, (phys_addr_t)ULLONG_MAX);
+}
+
+void __init memblock_mem_limit_remove_map(phys_addr_t limit)
+{
+	__memblock_cap_memory_range(0, limit, false);
+}
+
+void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
+{
+	__memblock_cap_memory_range(base, size, true);
 }
 
 static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
-- 
2.10.0

===>8===

> > 
> > Thanks,
> > -Takahiro AKASHI
> > 
> > > Will

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

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
  2016-11-14  5:55           ` AKASHI Takahiro
  (?)
@ 2016-11-16 16:30             ` Will Deacon
  -1 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-16 16:30 UTC (permalink / raw)
  To: AKASHI Takahiro, Dennis Chen, catalin.marinas, akpm, james.morse,
	geoff, bauerman, dyoung, mark.rutland, kexec, linux-arm-kernel,
	linux-mm

Hi Akashi,

On Mon, Nov 14, 2016 at 02:55:16PM +0900, AKASHI Takahiro wrote:
> On Fri, Nov 11, 2016 at 11:19:04AM +0800, Dennis Chen wrote:
> > On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> > > On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > > > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > > > +{
> > > > > +	int start_rgn, end_rgn;
> > > > > +	int i, ret;
> > > > > +
> > > > > +	if (!size)
> > > > > +		return;
> > > > > +
> > > > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > > > +						&start_rgn, &end_rgn);
> > > > > +	if (ret)
> > > > > +		return;
> > > > > +
> > > > > +	/* remove all the MAP regions */
> > > > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > +
> > > > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > +
> > > > > +	/* truncate the reserved regions */
> > > > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > > > +	memblock_remove_range(&memblock.reserved,
> > > > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > > > +}
> > > > 
> > > > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > > > you not implement that in terms of your new, more general, function? e.g.
> > > > by passing base == 0, and size == limit?
> > > 
> > > Obviously it's possible.
> > > I actually talked to Dennis before about merging them,
> > > but he was against my idea.
> > >
> > Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
> > So feel free to do that as Will'll do
> 
> OK, but I found that the two functions have a bit different semantics
> in clipping memory range, in particular, when the range [base,base+size)
> goes across several regions with a gap.
> (This does not happen in my arm64 kdump, though.)
> That is, 'limit' in memblock_mem_limit_remove_map() means total size of
> available memory, while 'size' in memblock_cap_memory_range() indicates
> the size of _continuous_ memory range.

I thought limit was just a physical address, and then
memblock_mem_limit_remove_map operated on the end of the nearest memblock?
You could leave the __find_max_addr call in memblock_mem_limit_remove_map,
given that I don't think you need/want it for memblock_cap_memory_range.

> So I added an extra argument, exact, to a common function to specify
> distinct behaviors. Confusing? Please see the patch below.

Oh yikes, this certainly wasn't what I had in mind! My observation was
just that memblock_mem_limit_remove_map(limit) does:


  1. memblock_isolate_range(limit - limit+ULLONG_MAX)
  2. memblock_remove_region(all non-nomap regions in the isolated region)
  3. truncate reserved regions to limit

and your memblock_cap_memory_range(base, size) does:

  1. memblock_isolate_range(base - base+size)
  2, memblock_remove_region(all non-nomap regions above and below the
     isolated region)
  3. truncate reserved regions around the isolated region

so, assuming we can invert the isolation in one of the cases, then they
could share the same underlying implementation.

I'm probably just missing something here, because the patch you've ended
up with is far more involved than I anticipated...

Will

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-16 16:30             ` Will Deacon
  0 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-16 16:30 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Akashi,

On Mon, Nov 14, 2016 at 02:55:16PM +0900, AKASHI Takahiro wrote:
> On Fri, Nov 11, 2016 at 11:19:04AM +0800, Dennis Chen wrote:
> > On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> > > On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > > > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > > > +{
> > > > > +	int start_rgn, end_rgn;
> > > > > +	int i, ret;
> > > > > +
> > > > > +	if (!size)
> > > > > +		return;
> > > > > +
> > > > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > > > +						&start_rgn, &end_rgn);
> > > > > +	if (ret)
> > > > > +		return;
> > > > > +
> > > > > +	/* remove all the MAP regions */
> > > > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > +
> > > > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > +
> > > > > +	/* truncate the reserved regions */
> > > > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > > > +	memblock_remove_range(&memblock.reserved,
> > > > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > > > +}
> > > > 
> > > > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > > > you not implement that in terms of your new, more general, function? e.g.
> > > > by passing base == 0, and size == limit?
> > > 
> > > Obviously it's possible.
> > > I actually talked to Dennis before about merging them,
> > > but he was against my idea.
> > >
> > Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
> > So feel free to do that as Will'll do
> 
> OK, but I found that the two functions have a bit different semantics
> in clipping memory range, in particular, when the range [base,base+size)
> goes across several regions with a gap.
> (This does not happen in my arm64 kdump, though.)
> That is, 'limit' in memblock_mem_limit_remove_map() means total size of
> available memory, while 'size' in memblock_cap_memory_range() indicates
> the size of _continuous_ memory range.

I thought limit was just a physical address, and then
memblock_mem_limit_remove_map operated on the end of the nearest memblock?
You could leave the __find_max_addr call in memblock_mem_limit_remove_map,
given that I don't think you need/want it for memblock_cap_memory_range.

> So I added an extra argument, exact, to a common function to specify
> distinct behaviors. Confusing? Please see the patch below.

Oh yikes, this certainly wasn't what I had in mind! My observation was
just that memblock_mem_limit_remove_map(limit) does:


  1. memblock_isolate_range(limit - limit+ULLONG_MAX)
  2. memblock_remove_region(all non-nomap regions in the isolated region)
  3. truncate reserved regions to limit

and your memblock_cap_memory_range(base, size) does:

  1. memblock_isolate_range(base - base+size)
  2, memblock_remove_region(all non-nomap regions above and below the
     isolated region)
  3. truncate reserved regions around the isolated region

so, assuming we can invert the isolation in one of the cases, then they
could share the same underlying implementation.

I'm probably just missing something here, because the patch you've ended
up with is far more involved than I anticipated...

Will

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-16 16:30             ` Will Deacon
  0 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-16 16:30 UTC (permalink / raw)
  To: AKASHI Takahiro, Dennis Chen, catalin.marinas, akpm, james.morse,
	geoff, bauerman, dyoung, mark.rutland, kexec, linux-arm-kernel,
	linux-mm, nd

Hi Akashi,

On Mon, Nov 14, 2016 at 02:55:16PM +0900, AKASHI Takahiro wrote:
> On Fri, Nov 11, 2016 at 11:19:04AM +0800, Dennis Chen wrote:
> > On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> > > On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > > > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > > > +{
> > > > > +	int start_rgn, end_rgn;
> > > > > +	int i, ret;
> > > > > +
> > > > > +	if (!size)
> > > > > +		return;
> > > > > +
> > > > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > > > +						&start_rgn, &end_rgn);
> > > > > +	if (ret)
> > > > > +		return;
> > > > > +
> > > > > +	/* remove all the MAP regions */
> > > > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > +
> > > > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > +
> > > > > +	/* truncate the reserved regions */
> > > > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > > > +	memblock_remove_range(&memblock.reserved,
> > > > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > > > +}
> > > > 
> > > > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > > > you not implement that in terms of your new, more general, function? e.g.
> > > > by passing base == 0, and size == limit?
> > > 
> > > Obviously it's possible.
> > > I actually talked to Dennis before about merging them,
> > > but he was against my idea.
> > >
> > Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
> > So feel free to do that as Will'll do
> 
> OK, but I found that the two functions have a bit different semantics
> in clipping memory range, in particular, when the range [base,base+size)
> goes across several regions with a gap.
> (This does not happen in my arm64 kdump, though.)
> That is, 'limit' in memblock_mem_limit_remove_map() means total size of
> available memory, while 'size' in memblock_cap_memory_range() indicates
> the size of _continuous_ memory range.

I thought limit was just a physical address, and then
memblock_mem_limit_remove_map operated on the end of the nearest memblock?
You could leave the __find_max_addr call in memblock_mem_limit_remove_map,
given that I don't think you need/want it for memblock_cap_memory_range.

> So I added an extra argument, exact, to a common function to specify
> distinct behaviors. Confusing? Please see the patch below.

Oh yikes, this certainly wasn't what I had in mind! My observation was
just that memblock_mem_limit_remove_map(limit) does:


  1. memblock_isolate_range(limit - limit+ULLONG_MAX)
  2. memblock_remove_region(all non-nomap regions in the isolated region)
  3. truncate reserved regions to limit

and your memblock_cap_memory_range(base, size) does:

  1. memblock_isolate_range(base - base+size)
  2, memblock_remove_region(all non-nomap regions above and below the
     isolated region)
  3. truncate reserved regions around the isolated region

so, assuming we can invert the isolation in one of the cases, then they
could share the same underlying implementation.

I'm probably just missing something here, because the patch you've ended
up with is far more involved than I anticipated...

Will

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

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
  2016-11-16 16:30             ` Will Deacon
  (?)
@ 2016-11-17  5:34               ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-17  5:34 UTC (permalink / raw)
  To: Will Deacon
  Cc: Dennis Chen, catalin.marinas, akpm, james.morse, geoff, bauerman,
	dyoung, mark.rutland, kexec, linux-arm-kernel, linux-mm

Will,

On Wed, Nov 16, 2016 at 04:30:15PM +0000, Will Deacon wrote:
> Hi Akashi,
> 
> On Mon, Nov 14, 2016 at 02:55:16PM +0900, AKASHI Takahiro wrote:
> > On Fri, Nov 11, 2016 at 11:19:04AM +0800, Dennis Chen wrote:
> > > On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> > > > On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > > > > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > > > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > > > > +{
> > > > > > +	int start_rgn, end_rgn;
> > > > > > +	int i, ret;
> > > > > > +
> > > > > > +	if (!size)
> > > > > > +		return;
> > > > > > +
> > > > > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > > > > +						&start_rgn, &end_rgn);
> > > > > > +	if (ret)
> > > > > > +		return;
> > > > > > +
> > > > > > +	/* remove all the MAP regions */
> > > > > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > > +
> > > > > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > > +
> > > > > > +	/* truncate the reserved regions */
> > > > > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > > > > +	memblock_remove_range(&memblock.reserved,
> > > > > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > > > > +}
> > > > > 
> > > > > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > > > > you not implement that in terms of your new, more general, function? e.g.
> > > > > by passing base == 0, and size == limit?
> > > > 
> > > > Obviously it's possible.
> > > > I actually talked to Dennis before about merging them,
> > > > but he was against my idea.
> > > >
> > > Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
> > > So feel free to do that as Will'll do
> > 
> > OK, but I found that the two functions have a bit different semantics
> > in clipping memory range, in particular, when the range [base,base+size)
> > goes across several regions with a gap.
> > (This does not happen in my arm64 kdump, though.)
> > That is, 'limit' in memblock_mem_limit_remove_map() means total size of
> > available memory, while 'size' in memblock_cap_memory_range() indicates
> > the size of _continuous_ memory range.
> 
> I thought limit was just a physical address, and then

No, it's not.

> memblock_mem_limit_remove_map operated on the end of the nearest memblock?

No, but "max_addr" returned by __find_max_addr() is a physical address
and the end address of memory of "limit" size in total.

> You could leave the __find_max_addr call in memblock_mem_limit_remove_map,
> given that I don't think you need/want it for memblock_cap_memory_range.
> 
> > So I added an extra argument, exact, to a common function to specify
> > distinct behaviors. Confusing? Please see the patch below.
> 
> Oh yikes, this certainly wasn't what I had in mind! My observation was
> just that memblock_mem_limit_remove_map(limit) does:
> 
> 
>   1. memblock_isolate_range(limit - limit+ULLONG_MAX)
>   2. memblock_remove_region(all non-nomap regions in the isolated region)
>   3. truncate reserved regions to limit
> 
> and your memblock_cap_memory_range(base, size) does:
> 
>   1. memblock_isolate_range(base - base+size)
>   2, memblock_remove_region(all non-nomap regions above and below the
>      isolated region)
>   3. truncate reserved regions around the isolated region
> 
> so, assuming we can invert the isolation in one of the cases, then they
> could share the same underlying implementation.

Please see my simplified patch below which would explain what I meant.
(Note that the size is calculated by 'max_addr - 0'.)

> I'm probably just missing something here, because the patch you've ended
> up with is far more involved than I anticipated...

I hope that it will meet almost your anticipation.

Thanks,
-Takahiro AKASHI

> 
> Will
===8<===
diff --git a/mm/memblock.c b/mm/memblock.c
index 7608bc3..fea1688 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 			      (phys_addr_t)ULLONG_MAX);
 }
 
+void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
+{
+	int start_rgn, end_rgn;
+	int i, ret;
+
+	if (!size)
+		return;
+
+	ret = memblock_isolate_range(&memblock.memory, base, size,
+						&start_rgn, &end_rgn);
+	if (ret)
+		return;
+
+	/* remove all the MAP regions */
+	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	for (i = start_rgn - 1; i >= 0; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	/* truncate the reserved regions */
+	memblock_remove_range(&memblock.reserved, 0, base);
+	memblock_remove_range(&memblock.reserved,
+			base + size, (phys_addr_t)ULLONG_MAX);
+}
+
 void __init memblock_mem_limit_remove_map(phys_addr_t limit)
 {
-	struct memblock_type *type = &memblock.memory;
 	phys_addr_t max_addr;
-	int i, ret, start_rgn, end_rgn;
 
 	if (!limit)
 		return;
@@ -1529,19 +1555,7 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
 	if (max_addr == (phys_addr_t)ULLONG_MAX)
 		return;
 
-	ret = memblock_isolate_range(type, max_addr, (phys_addr_t)ULLONG_MAX,
-				&start_rgn, &end_rgn);
-	if (ret)
-		return;
-
-	/* remove all the MAP regions above the limit */
-	for (i = end_rgn - 1; i >= start_rgn; i--) {
-		if (!memblock_is_nomap(&type->regions[i]))
-			memblock_remove_region(type, i);
-	}
-	/* truncate the reserved regions */
-	memblock_remove_range(&memblock.reserved, max_addr,
-			      (phys_addr_t)ULLONG_MAX);
+	memblock_cap_memory_range(0, max_addr);
 }
 
 static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-17  5:34               ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-17  5:34 UTC (permalink / raw)
  To: linux-arm-kernel

Will,

On Wed, Nov 16, 2016 at 04:30:15PM +0000, Will Deacon wrote:
> Hi Akashi,
> 
> On Mon, Nov 14, 2016 at 02:55:16PM +0900, AKASHI Takahiro wrote:
> > On Fri, Nov 11, 2016 at 11:19:04AM +0800, Dennis Chen wrote:
> > > On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> > > > On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > > > > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > > > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > > > > +{
> > > > > > +	int start_rgn, end_rgn;
> > > > > > +	int i, ret;
> > > > > > +
> > > > > > +	if (!size)
> > > > > > +		return;
> > > > > > +
> > > > > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > > > > +						&start_rgn, &end_rgn);
> > > > > > +	if (ret)
> > > > > > +		return;
> > > > > > +
> > > > > > +	/* remove all the MAP regions */
> > > > > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > > +
> > > > > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > > +
> > > > > > +	/* truncate the reserved regions */
> > > > > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > > > > +	memblock_remove_range(&memblock.reserved,
> > > > > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > > > > +}
> > > > > 
> > > > > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > > > > you not implement that in terms of your new, more general, function? e.g.
> > > > > by passing base == 0, and size == limit?
> > > > 
> > > > Obviously it's possible.
> > > > I actually talked to Dennis before about merging them,
> > > > but he was against my idea.
> > > >
> > > Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
> > > So feel free to do that as Will'll do
> > 
> > OK, but I found that the two functions have a bit different semantics
> > in clipping memory range, in particular, when the range [base,base+size)
> > goes across several regions with a gap.
> > (This does not happen in my arm64 kdump, though.)
> > That is, 'limit' in memblock_mem_limit_remove_map() means total size of
> > available memory, while 'size' in memblock_cap_memory_range() indicates
> > the size of _continuous_ memory range.
> 
> I thought limit was just a physical address, and then

No, it's not.

> memblock_mem_limit_remove_map operated on the end of the nearest memblock?

No, but "max_addr" returned by __find_max_addr() is a physical address
and the end address of memory of "limit" size in total.

> You could leave the __find_max_addr call in memblock_mem_limit_remove_map,
> given that I don't think you need/want it for memblock_cap_memory_range.
> 
> > So I added an extra argument, exact, to a common function to specify
> > distinct behaviors. Confusing? Please see the patch below.
> 
> Oh yikes, this certainly wasn't what I had in mind! My observation was
> just that memblock_mem_limit_remove_map(limit) does:
> 
> 
>   1. memblock_isolate_range(limit - limit+ULLONG_MAX)
>   2. memblock_remove_region(all non-nomap regions in the isolated region)
>   3. truncate reserved regions to limit
> 
> and your memblock_cap_memory_range(base, size) does:
> 
>   1. memblock_isolate_range(base - base+size)
>   2, memblock_remove_region(all non-nomap regions above and below the
>      isolated region)
>   3. truncate reserved regions around the isolated region
> 
> so, assuming we can invert the isolation in one of the cases, then they
> could share the same underlying implementation.

Please see my simplified patch below which would explain what I meant.
(Note that the size is calculated by 'max_addr - 0'.)

> I'm probably just missing something here, because the patch you've ended
> up with is far more involved than I anticipated...

I hope that it will meet almost your anticipation.

Thanks,
-Takahiro AKASHI

> 
> Will
===8<===
diff --git a/mm/memblock.c b/mm/memblock.c
index 7608bc3..fea1688 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 			      (phys_addr_t)ULLONG_MAX);
 }
 
+void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
+{
+	int start_rgn, end_rgn;
+	int i, ret;
+
+	if (!size)
+		return;
+
+	ret = memblock_isolate_range(&memblock.memory, base, size,
+						&start_rgn, &end_rgn);
+	if (ret)
+		return;
+
+	/* remove all the MAP regions */
+	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	for (i = start_rgn - 1; i >= 0; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	/* truncate the reserved regions */
+	memblock_remove_range(&memblock.reserved, 0, base);
+	memblock_remove_range(&memblock.reserved,
+			base + size, (phys_addr_t)ULLONG_MAX);
+}
+
 void __init memblock_mem_limit_remove_map(phys_addr_t limit)
 {
-	struct memblock_type *type = &memblock.memory;
 	phys_addr_t max_addr;
-	int i, ret, start_rgn, end_rgn;
 
 	if (!limit)
 		return;
@@ -1529,19 +1555,7 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
 	if (max_addr == (phys_addr_t)ULLONG_MAX)
 		return;
 
-	ret = memblock_isolate_range(type, max_addr, (phys_addr_t)ULLONG_MAX,
-				&start_rgn, &end_rgn);
-	if (ret)
-		return;
-
-	/* remove all the MAP regions above the limit */
-	for (i = end_rgn - 1; i >= start_rgn; i--) {
-		if (!memblock_is_nomap(&type->regions[i]))
-			memblock_remove_region(type, i);
-	}
-	/* truncate the reserved regions */
-	memblock_remove_range(&memblock.reserved, max_addr,
-			      (phys_addr_t)ULLONG_MAX);
+	memblock_cap_memory_range(0, max_addr);
 }
 
 static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-17  5:34               ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-17  5:34 UTC (permalink / raw)
  To: Will Deacon
  Cc: mark.rutland, geoff, catalin.marinas, kexec, linux-mm,
	james.morse, bauerman, Dennis Chen, akpm, nd, dyoung,
	linux-arm-kernel

Will,

On Wed, Nov 16, 2016 at 04:30:15PM +0000, Will Deacon wrote:
> Hi Akashi,
> 
> On Mon, Nov 14, 2016 at 02:55:16PM +0900, AKASHI Takahiro wrote:
> > On Fri, Nov 11, 2016 at 11:19:04AM +0800, Dennis Chen wrote:
> > > On Fri, Nov 11, 2016 at 11:50:50AM +0900, AKASHI Takahiro wrote:
> > > > On Thu, Nov 10, 2016 at 05:27:20PM +0000, Will Deacon wrote:
> > > > > On Wed, Nov 02, 2016 at 01:51:53PM +0900, AKASHI Takahiro wrote:
> > > > > > +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> > > > > > +{
> > > > > > +	int start_rgn, end_rgn;
> > > > > > +	int i, ret;
> > > > > > +
> > > > > > +	if (!size)
> > > > > > +		return;
> > > > > > +
> > > > > > +	ret = memblock_isolate_range(&memblock.memory, base, size,
> > > > > > +						&start_rgn, &end_rgn);
> > > > > > +	if (ret)
> > > > > > +		return;
> > > > > > +
> > > > > > +	/* remove all the MAP regions */
> > > > > > +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> > > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > > +
> > > > > > +	for (i = start_rgn - 1; i >= 0; i--)
> > > > > > +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> > > > > > +			memblock_remove_region(&memblock.memory, i);
> > > > > > +
> > > > > > +	/* truncate the reserved regions */
> > > > > > +	memblock_remove_range(&memblock.reserved, 0, base);
> > > > > > +	memblock_remove_range(&memblock.reserved,
> > > > > > +			base + size, (phys_addr_t)ULLONG_MAX);
> > > > > > +}
> > > > > 
> > > > > This duplicates a bunch of the logic in memblock_mem_limit_remove_map. Can
> > > > > you not implement that in terms of your new, more general, function? e.g.
> > > > > by passing base == 0, and size == limit?
> > > > 
> > > > Obviously it's possible.
> > > > I actually talked to Dennis before about merging them,
> > > > but he was against my idea.
> > > >
> > > Oops! I thought we have reached agreement in the thread:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/442817.html
> > > So feel free to do that as Will'll do
> > 
> > OK, but I found that the two functions have a bit different semantics
> > in clipping memory range, in particular, when the range [base,base+size)
> > goes across several regions with a gap.
> > (This does not happen in my arm64 kdump, though.)
> > That is, 'limit' in memblock_mem_limit_remove_map() means total size of
> > available memory, while 'size' in memblock_cap_memory_range() indicates
> > the size of _continuous_ memory range.
> 
> I thought limit was just a physical address, and then

No, it's not.

> memblock_mem_limit_remove_map operated on the end of the nearest memblock?

No, but "max_addr" returned by __find_max_addr() is a physical address
and the end address of memory of "limit" size in total.

> You could leave the __find_max_addr call in memblock_mem_limit_remove_map,
> given that I don't think you need/want it for memblock_cap_memory_range.
> 
> > So I added an extra argument, exact, to a common function to specify
> > distinct behaviors. Confusing? Please see the patch below.
> 
> Oh yikes, this certainly wasn't what I had in mind! My observation was
> just that memblock_mem_limit_remove_map(limit) does:
> 
> 
>   1. memblock_isolate_range(limit - limit+ULLONG_MAX)
>   2. memblock_remove_region(all non-nomap regions in the isolated region)
>   3. truncate reserved regions to limit
> 
> and your memblock_cap_memory_range(base, size) does:
> 
>   1. memblock_isolate_range(base - base+size)
>   2, memblock_remove_region(all non-nomap regions above and below the
>      isolated region)
>   3. truncate reserved regions around the isolated region
> 
> so, assuming we can invert the isolation in one of the cases, then they
> could share the same underlying implementation.

Please see my simplified patch below which would explain what I meant.
(Note that the size is calculated by 'max_addr - 0'.)

> I'm probably just missing something here, because the patch you've ended
> up with is far more involved than I anticipated...

I hope that it will meet almost your anticipation.

Thanks,
-Takahiro AKASHI

> 
> Will
===8<===
diff --git a/mm/memblock.c b/mm/memblock.c
index 7608bc3..fea1688 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 			      (phys_addr_t)ULLONG_MAX);
 }
 
+void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
+{
+	int start_rgn, end_rgn;
+	int i, ret;
+
+	if (!size)
+		return;
+
+	ret = memblock_isolate_range(&memblock.memory, base, size,
+						&start_rgn, &end_rgn);
+	if (ret)
+		return;
+
+	/* remove all the MAP regions */
+	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	for (i = start_rgn - 1; i >= 0; i--)
+		if (!memblock_is_nomap(&memblock.memory.regions[i]))
+			memblock_remove_region(&memblock.memory, i);
+
+	/* truncate the reserved regions */
+	memblock_remove_range(&memblock.reserved, 0, base);
+	memblock_remove_range(&memblock.reserved,
+			base + size, (phys_addr_t)ULLONG_MAX);
+}
+
 void __init memblock_mem_limit_remove_map(phys_addr_t limit)
 {
-	struct memblock_type *type = &memblock.memory;
 	phys_addr_t max_addr;
-	int i, ret, start_rgn, end_rgn;
 
 	if (!limit)
 		return;
@@ -1529,19 +1555,7 @@ void __init memblock_mem_limit_remove_map(phys_addr_t limit)
 	if (max_addr == (phys_addr_t)ULLONG_MAX)
 		return;
 
-	ret = memblock_isolate_range(type, max_addr, (phys_addr_t)ULLONG_MAX,
-				&start_rgn, &end_rgn);
-	if (ret)
-		return;
-
-	/* remove all the MAP regions above the limit */
-	for (i = end_rgn - 1; i >= start_rgn; i--) {
-		if (!memblock_is_nomap(&type->regions[i]))
-			memblock_remove_region(type, i);
-	}
-	/* truncate the reserved regions */
-	memblock_remove_range(&memblock.reserved, max_addr,
-			      (phys_addr_t)ULLONG_MAX);
+	memblock_cap_memory_range(0, max_addr);
 }
 
 static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)

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

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
  2016-11-17  5:34               ` AKASHI Takahiro
  (?)
@ 2016-11-17 11:19                 ` Will Deacon
  -1 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-17 11:19 UTC (permalink / raw)
  To: AKASHI Takahiro, Dennis Chen, catalin.marinas, akpm, james.morse,
	geoff, bauerman, dyoung, mark.rutland, kexec, linux-arm-kernel,
	linux-mm

Hi Akashi,

On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
> On Wed, Nov 16, 2016 at 04:30:15PM +0000, Will Deacon wrote:
> > I thought limit was just a physical address, and then
> 
> No, it's not.

Quite right, it's a size. Sorry about that.

> > memblock_mem_limit_remove_map operated on the end of the nearest memblock?
> 
> No, but "max_addr" returned by __find_max_addr() is a physical address
> and the end address of memory of "limit" size in total.
> 
> > You could leave the __find_max_addr call in memblock_mem_limit_remove_map,
> > given that I don't think you need/want it for memblock_cap_memory_range.
> > 
> > > So I added an extra argument, exact, to a common function to specify
> > > distinct behaviors. Confusing? Please see the patch below.
> > 
> > Oh yikes, this certainly wasn't what I had in mind! My observation was
> > just that memblock_mem_limit_remove_map(limit) does:
> > 
> > 
> >   1. memblock_isolate_range(limit - limit+ULLONG_MAX)
> >   2. memblock_remove_region(all non-nomap regions in the isolated region)
> >   3. truncate reserved regions to limit
> > 
> > and your memblock_cap_memory_range(base, size) does:
> > 
> >   1. memblock_isolate_range(base - base+size)
> >   2, memblock_remove_region(all non-nomap regions above and below the
> >      isolated region)
> >   3. truncate reserved regions around the isolated region
> > 
> > so, assuming we can invert the isolation in one of the cases, then they
> > could share the same underlying implementation.
> 
> Please see my simplified patch below which would explain what I meant.
> (Note that the size is calculated by 'max_addr - 0'.)
> 
> > I'm probably just missing something here, because the patch you've ended
> > up with is far more involved than I anticipated...
> 
> I hope that it will meet almost your anticipation.

It looks much better, thanks! Just one question below.

> diff --git a/mm/memblock.c b/mm/memblock.c
> index 7608bc3..fea1688 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>  			      (phys_addr_t)ULLONG_MAX);
>  }
>  
> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> +{
> +	int start_rgn, end_rgn;
> +	int i, ret;
> +
> +	if (!size)
> +		return;
> +
> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> +						&start_rgn, &end_rgn);
> +	if (ret)
> +		return;
> +
> +	/* remove all the MAP regions */
> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> +			memblock_remove_region(&memblock.memory, i);

In the case that we have only one, giant memblock that covers base all
of base + size, can't we end up with start_rgn = end_rgn = 0? In which
case, we'd end up accidentally removing the map regions here.

The existing code:

> -	/* remove all the MAP regions above the limit */
> -	for (i = end_rgn - 1; i >= start_rgn; i--) {
> -		if (!memblock_is_nomap(&type->regions[i]))
> -			memblock_remove_region(type, i);
> -	}

seems to handle this.

Will

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-17 11:19                 ` Will Deacon
  0 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-17 11:19 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Akashi,

On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
> On Wed, Nov 16, 2016 at 04:30:15PM +0000, Will Deacon wrote:
> > I thought limit was just a physical address, and then
> 
> No, it's not.

Quite right, it's a size. Sorry about that.

> > memblock_mem_limit_remove_map operated on the end of the nearest memblock?
> 
> No, but "max_addr" returned by __find_max_addr() is a physical address
> and the end address of memory of "limit" size in total.
> 
> > You could leave the __find_max_addr call in memblock_mem_limit_remove_map,
> > given that I don't think you need/want it for memblock_cap_memory_range.
> > 
> > > So I added an extra argument, exact, to a common function to specify
> > > distinct behaviors. Confusing? Please see the patch below.
> > 
> > Oh yikes, this certainly wasn't what I had in mind! My observation was
> > just that memblock_mem_limit_remove_map(limit) does:
> > 
> > 
> >   1. memblock_isolate_range(limit - limit+ULLONG_MAX)
> >   2. memblock_remove_region(all non-nomap regions in the isolated region)
> >   3. truncate reserved regions to limit
> > 
> > and your memblock_cap_memory_range(base, size) does:
> > 
> >   1. memblock_isolate_range(base - base+size)
> >   2, memblock_remove_region(all non-nomap regions above and below the
> >      isolated region)
> >   3. truncate reserved regions around the isolated region
> > 
> > so, assuming we can invert the isolation in one of the cases, then they
> > could share the same underlying implementation.
> 
> Please see my simplified patch below which would explain what I meant.
> (Note that the size is calculated by 'max_addr - 0'.)
> 
> > I'm probably just missing something here, because the patch you've ended
> > up with is far more involved than I anticipated...
> 
> I hope that it will meet almost your anticipation.

It looks much better, thanks! Just one question below.

> diff --git a/mm/memblock.c b/mm/memblock.c
> index 7608bc3..fea1688 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>  			      (phys_addr_t)ULLONG_MAX);
>  }
>  
> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> +{
> +	int start_rgn, end_rgn;
> +	int i, ret;
> +
> +	if (!size)
> +		return;
> +
> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> +						&start_rgn, &end_rgn);
> +	if (ret)
> +		return;
> +
> +	/* remove all the MAP regions */
> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> +			memblock_remove_region(&memblock.memory, i);

In the case that we have only one, giant memblock that covers base all
of base + size, can't we end up with start_rgn = end_rgn = 0? In which
case, we'd end up accidentally removing the map regions here.

The existing code:

> -	/* remove all the MAP regions above the limit */
> -	for (i = end_rgn - 1; i >= start_rgn; i--) {
> -		if (!memblock_is_nomap(&type->regions[i]))
> -			memblock_remove_region(type, i);
> -	}

seems to handle this.

Will

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-17 11:19                 ` Will Deacon
  0 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-17 11:19 UTC (permalink / raw)
  To: AKASHI Takahiro, Dennis Chen, catalin.marinas, akpm, james.morse,
	geoff, bauerman, dyoung, mark.rutland, kexec, linux-arm-kernel,
	linux-mm, nd

Hi Akashi,

On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
> On Wed, Nov 16, 2016 at 04:30:15PM +0000, Will Deacon wrote:
> > I thought limit was just a physical address, and then
> 
> No, it's not.

Quite right, it's a size. Sorry about that.

> > memblock_mem_limit_remove_map operated on the end of the nearest memblock?
> 
> No, but "max_addr" returned by __find_max_addr() is a physical address
> and the end address of memory of "limit" size in total.
> 
> > You could leave the __find_max_addr call in memblock_mem_limit_remove_map,
> > given that I don't think you need/want it for memblock_cap_memory_range.
> > 
> > > So I added an extra argument, exact, to a common function to specify
> > > distinct behaviors. Confusing? Please see the patch below.
> > 
> > Oh yikes, this certainly wasn't what I had in mind! My observation was
> > just that memblock_mem_limit_remove_map(limit) does:
> > 
> > 
> >   1. memblock_isolate_range(limit - limit+ULLONG_MAX)
> >   2. memblock_remove_region(all non-nomap regions in the isolated region)
> >   3. truncate reserved regions to limit
> > 
> > and your memblock_cap_memory_range(base, size) does:
> > 
> >   1. memblock_isolate_range(base - base+size)
> >   2, memblock_remove_region(all non-nomap regions above and below the
> >      isolated region)
> >   3. truncate reserved regions around the isolated region
> > 
> > so, assuming we can invert the isolation in one of the cases, then they
> > could share the same underlying implementation.
> 
> Please see my simplified patch below which would explain what I meant.
> (Note that the size is calculated by 'max_addr - 0'.)
> 
> > I'm probably just missing something here, because the patch you've ended
> > up with is far more involved than I anticipated...
> 
> I hope that it will meet almost your anticipation.

It looks much better, thanks! Just one question below.

> diff --git a/mm/memblock.c b/mm/memblock.c
> index 7608bc3..fea1688 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>  			      (phys_addr_t)ULLONG_MAX);
>  }
>  
> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> +{
> +	int start_rgn, end_rgn;
> +	int i, ret;
> +
> +	if (!size)
> +		return;
> +
> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> +						&start_rgn, &end_rgn);
> +	if (ret)
> +		return;
> +
> +	/* remove all the MAP regions */
> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> +			memblock_remove_region(&memblock.memory, i);

In the case that we have only one, giant memblock that covers base all
of base + size, can't we end up with start_rgn = end_rgn = 0? In which
case, we'd end up accidentally removing the map regions here.

The existing code:

> -	/* remove all the MAP regions above the limit */
> -	for (i = end_rgn - 1; i >= start_rgn; i--) {
> -		if (!memblock_is_nomap(&type->regions[i]))
> -			memblock_remove_region(type, i);
> -	}

seems to handle this.

Will

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

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
  2016-11-17 11:19                 ` Will Deacon
  (?)
@ 2016-11-17 18:00                   ` James Morse
  -1 siblings, 0 replies; 58+ messages in thread
From: James Morse @ 2016-11-17 18:00 UTC (permalink / raw)
  To: Will Deacon, AKASHI Takahiro
  Cc: Dennis Chen, catalin.marinas, akpm, geoff, bauerman, dyoung,
	mark.rutland, kexec, linux-arm-kernel, linux-mm

Hi Will, Akashi,

On 17/11/16 11:19, Will Deacon wrote:
> It looks much better, thanks! Just one question below.
> 

> On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
>> diff --git a/mm/memblock.c b/mm/memblock.c
>> index 7608bc3..fea1688 100644
>> --- a/mm/memblock.c
>> +++ b/mm/memblock.c
>> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>>  			      (phys_addr_t)ULLONG_MAX);
>>  }
>>  
>> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
>> +{
>> +	int start_rgn, end_rgn;
>> +	int i, ret;
>> +
>> +	if (!size)
>> +		return;
>> +
>> +	ret = memblock_isolate_range(&memblock.memory, base, size,
>> +						&start_rgn, &end_rgn);
>> +	if (ret)
>> +		return;
>> +
>> +	/* remove all the MAP regions */
>> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
>> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
>> +			memblock_remove_region(&memblock.memory, i);
> 
> In the case that we have only one, giant memblock that covers base all
> of base + size, can't we end up with start_rgn = end_rgn = 0? In which

Can this happen? If we only have one memblock that exactly spans
base:(base+size), memblock_isolate_range() will hit the '@rgn is fully
contained, record it' code and set start_rgn=0,end_rgn=1. (rbase==base,
rend==end). We only go round the loop once.

If we only have one memblock that is bigger than base:(base+size) we end up with
three regions, start_rgn=1,end_rgn=2. The trickery here is the '@rgn intersects
from above' code decreases the loop counter so we process the same entry twice,
hitting '@rgn is fully contained, record it' the second time round... so we go
round the loop four times.

I can't see how we hit the:
> 	if (rbase >= end)
> 		break;
> 	if (rend <= base)
> 		continue;

code in either case...



Thanks,

James


> case, we'd end up accidentally removing the map regions here.
> 
> The existing code:
> 
>> -	/* remove all the MAP regions above the limit */
>> -	for (i = end_rgn - 1; i >= start_rgn; i--) {
>> -		if (!memblock_is_nomap(&type->regions[i]))
>> -			memblock_remove_region(type, i);
>> -	}
> 
> seems to handle this.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-17 18:00                   ` James Morse
  0 siblings, 0 replies; 58+ messages in thread
From: James Morse @ 2016-11-17 18:00 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Will, Akashi,

On 17/11/16 11:19, Will Deacon wrote:
> It looks much better, thanks! Just one question below.
> 

> On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
>> diff --git a/mm/memblock.c b/mm/memblock.c
>> index 7608bc3..fea1688 100644
>> --- a/mm/memblock.c
>> +++ b/mm/memblock.c
>> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>>  			      (phys_addr_t)ULLONG_MAX);
>>  }
>>  
>> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
>> +{
>> +	int start_rgn, end_rgn;
>> +	int i, ret;
>> +
>> +	if (!size)
>> +		return;
>> +
>> +	ret = memblock_isolate_range(&memblock.memory, base, size,
>> +						&start_rgn, &end_rgn);
>> +	if (ret)
>> +		return;
>> +
>> +	/* remove all the MAP regions */
>> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
>> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
>> +			memblock_remove_region(&memblock.memory, i);
> 
> In the case that we have only one, giant memblock that covers base all
> of base + size, can't we end up with start_rgn = end_rgn = 0? In which

Can this happen? If we only have one memblock that exactly spans
base:(base+size), memblock_isolate_range() will hit the '@rgn is fully
contained, record it' code and set start_rgn=0,end_rgn=1. (rbase==base,
rend==end). We only go round the loop once.

If we only have one memblock that is bigger than base:(base+size) we end up with
three regions, start_rgn=1,end_rgn=2. The trickery here is the '@rgn intersects
from above' code decreases the loop counter so we process the same entry twice,
hitting '@rgn is fully contained, record it' the second time round... so we go
round the loop four times.

I can't see how we hit the:
> 	if (rbase >= end)
> 		break;
> 	if (rend <= base)
> 		continue;

code in either case...



Thanks,

James


> case, we'd end up accidentally removing the map regions here.
> 
> The existing code:
> 
>> -	/* remove all the MAP regions above the limit */
>> -	for (i = end_rgn - 1; i >= start_rgn; i--) {
>> -		if (!memblock_is_nomap(&type->regions[i]))
>> -			memblock_remove_region(type, i);
>> -	}
> 
> seems to handle this.

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-17 18:00                   ` James Morse
  0 siblings, 0 replies; 58+ messages in thread
From: James Morse @ 2016-11-17 18:00 UTC (permalink / raw)
  To: Will Deacon, AKASHI Takahiro
  Cc: mark.rutland, geoff, catalin.marinas, kexec, linux-mm, bauerman,
	Dennis Chen, akpm, nd, dyoung, linux-arm-kernel

Hi Will, Akashi,

On 17/11/16 11:19, Will Deacon wrote:
> It looks much better, thanks! Just one question below.
> 

> On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
>> diff --git a/mm/memblock.c b/mm/memblock.c
>> index 7608bc3..fea1688 100644
>> --- a/mm/memblock.c
>> +++ b/mm/memblock.c
>> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>>  			      (phys_addr_t)ULLONG_MAX);
>>  }
>>  
>> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
>> +{
>> +	int start_rgn, end_rgn;
>> +	int i, ret;
>> +
>> +	if (!size)
>> +		return;
>> +
>> +	ret = memblock_isolate_range(&memblock.memory, base, size,
>> +						&start_rgn, &end_rgn);
>> +	if (ret)
>> +		return;
>> +
>> +	/* remove all the MAP regions */
>> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
>> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
>> +			memblock_remove_region(&memblock.memory, i);
> 
> In the case that we have only one, giant memblock that covers base all
> of base + size, can't we end up with start_rgn = end_rgn = 0? In which

Can this happen? If we only have one memblock that exactly spans
base:(base+size), memblock_isolate_range() will hit the '@rgn is fully
contained, record it' code and set start_rgn=0,end_rgn=1. (rbase==base,
rend==end). We only go round the loop once.

If we only have one memblock that is bigger than base:(base+size) we end up with
three regions, start_rgn=1,end_rgn=2. The trickery here is the '@rgn intersects
from above' code decreases the loop counter so we process the same entry twice,
hitting '@rgn is fully contained, record it' the second time round... so we go
round the loop four times.

I can't see how we hit the:
> 	if (rbase >= end)
> 		break;
> 	if (rend <= base)
> 		continue;

code in either case...



Thanks,

James


> case, we'd end up accidentally removing the map regions here.
> 
> The existing code:
> 
>> -	/* remove all the MAP regions above the limit */
>> -	for (i = end_rgn - 1; i >= start_rgn; i--) {
>> -		if (!memblock_is_nomap(&type->regions[i]))
>> -			memblock_remove_region(type, i);
>> -	}
> 
> seems to handle this.

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

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
  2016-11-17 18:00                   ` James Morse
  (?)
@ 2016-11-18  1:03                     ` AKASHI Takahiro
  -1 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-18  1:03 UTC (permalink / raw)
  To: James Morse
  Cc: Will Deacon, Dennis Chen, catalin.marinas, akpm, geoff, bauerman,
	dyoung, mark.rutland, kexec, linux-arm-kernel, linux-mm

James,

On Thu, Nov 17, 2016 at 06:00:58PM +0000, James Morse wrote:
> Hi Will, Akashi,
> 
> On 17/11/16 11:19, Will Deacon wrote:
> > It looks much better, thanks! Just one question below.
> > 
> 
> > On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
> >> diff --git a/mm/memblock.c b/mm/memblock.c
> >> index 7608bc3..fea1688 100644
> >> --- a/mm/memblock.c
> >> +++ b/mm/memblock.c
> >> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >>  			      (phys_addr_t)ULLONG_MAX);
> >>  }
> >>  
> >> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> >> +{
> >> +	int start_rgn, end_rgn;
> >> +	int i, ret;
> >> +
> >> +	if (!size)
> >> +		return;
> >> +
> >> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> >> +						&start_rgn, &end_rgn);
> >> +	if (ret)
> >> +		return;
> >> +
> >> +	/* remove all the MAP regions */
> >> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> >> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> >> +			memblock_remove_region(&memblock.memory, i);
> > 
> > In the case that we have only one, giant memblock that covers base all
> > of base + size, can't we end up with start_rgn = end_rgn = 0? In which
> 
> Can this happen? If we only have one memblock that exactly spans
> base:(base+size), memblock_isolate_range() will hit the '@rgn is fully
> contained, record it' code and set start_rgn=0,end_rgn=1. (rbase==base,
> rend==end). We only go round the loop once.
> 
> If we only have one memblock that is bigger than base:(base+size) we end up with
> three regions, start_rgn=1,end_rgn=2. The trickery here is the '@rgn intersects
> from above' code decreases the loop counter so we process the same entry twice,
> hitting '@rgn is fully contained, record it' the second time round... so we go
> round the loop four times.

Thank you for your observation.

> I can't see how we hit the:
> > 	if (rbase >= end)
> > 		break;
> > 	if (rend <= base)
> > 		continue;
> 
> code in either case...

Right. So 'end_rgn' will never be expected to be 0 as far as some
intersection exists.

-Takahiro AKASHI

> 
> 
> Thanks,
> 
> James
> 
> 
> > case, we'd end up accidentally removing the map regions here.
> > 
> > The existing code:
> > 
> >> -	/* remove all the MAP regions above the limit */
> >> -	for (i = end_rgn - 1; i >= start_rgn; i--) {
> >> -		if (!memblock_is_nomap(&type->regions[i]))
> >> -			memblock_remove_region(type, i);
> >> -	}
> > 
> > seems to handle this.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-18  1:03                     ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-18  1:03 UTC (permalink / raw)
  To: linux-arm-kernel

James,

On Thu, Nov 17, 2016 at 06:00:58PM +0000, James Morse wrote:
> Hi Will, Akashi,
> 
> On 17/11/16 11:19, Will Deacon wrote:
> > It looks much better, thanks! Just one question below.
> > 
> 
> > On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
> >> diff --git a/mm/memblock.c b/mm/memblock.c
> >> index 7608bc3..fea1688 100644
> >> --- a/mm/memblock.c
> >> +++ b/mm/memblock.c
> >> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >>  			      (phys_addr_t)ULLONG_MAX);
> >>  }
> >>  
> >> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> >> +{
> >> +	int start_rgn, end_rgn;
> >> +	int i, ret;
> >> +
> >> +	if (!size)
> >> +		return;
> >> +
> >> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> >> +						&start_rgn, &end_rgn);
> >> +	if (ret)
> >> +		return;
> >> +
> >> +	/* remove all the MAP regions */
> >> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> >> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> >> +			memblock_remove_region(&memblock.memory, i);
> > 
> > In the case that we have only one, giant memblock that covers base all
> > of base + size, can't we end up with start_rgn = end_rgn = 0? In which
> 
> Can this happen? If we only have one memblock that exactly spans
> base:(base+size), memblock_isolate_range() will hit the '@rgn is fully
> contained, record it' code and set start_rgn=0,end_rgn=1. (rbase==base,
> rend==end). We only go round the loop once.
> 
> If we only have one memblock that is bigger than base:(base+size) we end up with
> three regions, start_rgn=1,end_rgn=2. The trickery here is the '@rgn intersects
> from above' code decreases the loop counter so we process the same entry twice,
> hitting '@rgn is fully contained, record it' the second time round... so we go
> round the loop four times.

Thank you for your observation.

> I can't see how we hit the:
> > 	if (rbase >= end)
> > 		break;
> > 	if (rend <= base)
> > 		continue;
> 
> code in either case...

Right. So 'end_rgn' will never be expected to be 0 as far as some
intersection exists.

-Takahiro AKASHI

> 
> 
> Thanks,
> 
> James
> 
> 
> > case, we'd end up accidentally removing the map regions here.
> > 
> > The existing code:
> > 
> >> -	/* remove all the MAP regions above the limit */
> >> -	for (i = end_rgn - 1; i >= start_rgn; i--) {
> >> -		if (!memblock_is_nomap(&type->regions[i]))
> >> -			memblock_remove_region(type, i);
> >> -	}
> > 
> > seems to handle this.

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-18  1:03                     ` AKASHI Takahiro
  0 siblings, 0 replies; 58+ messages in thread
From: AKASHI Takahiro @ 2016-11-18  1:03 UTC (permalink / raw)
  To: James Morse
  Cc: mark.rutland, geoff, catalin.marinas, Will Deacon, linux-mm,
	bauerman, Dennis Chen, akpm, nd, dyoung, kexec, linux-arm-kernel

James,

On Thu, Nov 17, 2016 at 06:00:58PM +0000, James Morse wrote:
> Hi Will, Akashi,
> 
> On 17/11/16 11:19, Will Deacon wrote:
> > It looks much better, thanks! Just one question below.
> > 
> 
> > On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
> >> diff --git a/mm/memblock.c b/mm/memblock.c
> >> index 7608bc3..fea1688 100644
> >> --- a/mm/memblock.c
> >> +++ b/mm/memblock.c
> >> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >>  			      (phys_addr_t)ULLONG_MAX);
> >>  }
> >>  
> >> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> >> +{
> >> +	int start_rgn, end_rgn;
> >> +	int i, ret;
> >> +
> >> +	if (!size)
> >> +		return;
> >> +
> >> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> >> +						&start_rgn, &end_rgn);
> >> +	if (ret)
> >> +		return;
> >> +
> >> +	/* remove all the MAP regions */
> >> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> >> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> >> +			memblock_remove_region(&memblock.memory, i);
> > 
> > In the case that we have only one, giant memblock that covers base all
> > of base + size, can't we end up with start_rgn = end_rgn = 0? In which
> 
> Can this happen? If we only have one memblock that exactly spans
> base:(base+size), memblock_isolate_range() will hit the '@rgn is fully
> contained, record it' code and set start_rgn=0,end_rgn=1. (rbase==base,
> rend==end). We only go round the loop once.
> 
> If we only have one memblock that is bigger than base:(base+size) we end up with
> three regions, start_rgn=1,end_rgn=2. The trickery here is the '@rgn intersects
> from above' code decreases the loop counter so we process the same entry twice,
> hitting '@rgn is fully contained, record it' the second time round... so we go
> round the loop four times.

Thank you for your observation.

> I can't see how we hit the:
> > 	if (rbase >= end)
> > 		break;
> > 	if (rend <= base)
> > 		continue;
> 
> code in either case...

Right. So 'end_rgn' will never be expected to be 0 as far as some
intersection exists.

-Takahiro AKASHI

> 
> 
> Thanks,
> 
> James
> 
> 
> > case, we'd end up accidentally removing the map regions here.
> > 
> > The existing code:
> > 
> >> -	/* remove all the MAP regions above the limit */
> >> -	for (i = end_rgn - 1; i >= start_rgn; i--) {
> >> -		if (!memblock_is_nomap(&type->regions[i]))
> >> -			memblock_remove_region(type, i);
> >> -	}
> > 
> > seems to handle this.

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

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
  2016-11-17 18:00                   ` James Morse
  (?)
@ 2016-11-18 12:10                     ` Will Deacon
  -1 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-18 12:10 UTC (permalink / raw)
  To: James Morse
  Cc: AKASHI Takahiro, Dennis Chen, catalin.marinas, akpm, geoff,
	bauerman, dyoung, mark.rutland, kexec, linux-arm-kernel,
	linux-mm

On Thu, Nov 17, 2016 at 06:00:58PM +0000, James Morse wrote:
> On 17/11/16 11:19, Will Deacon wrote:
> > It looks much better, thanks! Just one question below.
> > 
> 
> > On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
> >> diff --git a/mm/memblock.c b/mm/memblock.c
> >> index 7608bc3..fea1688 100644
> >> --- a/mm/memblock.c
> >> +++ b/mm/memblock.c
> >> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >>  			      (phys_addr_t)ULLONG_MAX);
> >>  }
> >>  
> >> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> >> +{
> >> +	int start_rgn, end_rgn;
> >> +	int i, ret;
> >> +
> >> +	if (!size)
> >> +		return;
> >> +
> >> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> >> +						&start_rgn, &end_rgn);
> >> +	if (ret)
> >> +		return;
> >> +
> >> +	/* remove all the MAP regions */
> >> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> >> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> >> +			memblock_remove_region(&memblock.memory, i);
> > 
> > In the case that we have only one, giant memblock that covers base all
> > of base + size, can't we end up with start_rgn = end_rgn = 0? In which
> 
> Can this happen? If we only have one memblock that exactly spans
> base:(base+size), memblock_isolate_range() will hit the '@rgn is fully
> contained, record it' code and set start_rgn=0,end_rgn=1. (rbase==base,
> rend==end). We only go round the loop once.
> 
> If we only have one memblock that is bigger than base:(base+size) we end up with
> three regions, start_rgn=1,end_rgn=2. The trickery here is the '@rgn intersects
> from above' code decreases the loop counter so we process the same entry twice,
> hitting '@rgn is fully contained, record it' the second time round... so we go
> round the loop four times.
> 
> I can't see how we hit the:
> > 	if (rbase >= end)
> > 		break;
> > 	if (rend <= base)
> > 		continue;
> 
> code in either case...

I consistently misread that as rend >= end and rbase <= base! In which case,
I agree with your analysis:

Reviewed-by: Will Deacon <will.deacon@arm.com>

The patch could probably still use an ack from an mm person.

Will

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

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

* [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-18 12:10                     ` Will Deacon
  0 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-18 12:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Nov 17, 2016 at 06:00:58PM +0000, James Morse wrote:
> On 17/11/16 11:19, Will Deacon wrote:
> > It looks much better, thanks! Just one question below.
> > 
> 
> > On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
> >> diff --git a/mm/memblock.c b/mm/memblock.c
> >> index 7608bc3..fea1688 100644
> >> --- a/mm/memblock.c
> >> +++ b/mm/memblock.c
> >> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >>  			      (phys_addr_t)ULLONG_MAX);
> >>  }
> >>  
> >> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> >> +{
> >> +	int start_rgn, end_rgn;
> >> +	int i, ret;
> >> +
> >> +	if (!size)
> >> +		return;
> >> +
> >> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> >> +						&start_rgn, &end_rgn);
> >> +	if (ret)
> >> +		return;
> >> +
> >> +	/* remove all the MAP regions */
> >> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> >> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> >> +			memblock_remove_region(&memblock.memory, i);
> > 
> > In the case that we have only one, giant memblock that covers base all
> > of base + size, can't we end up with start_rgn = end_rgn = 0? In which
> 
> Can this happen? If we only have one memblock that exactly spans
> base:(base+size), memblock_isolate_range() will hit the '@rgn is fully
> contained, record it' code and set start_rgn=0,end_rgn=1. (rbase==base,
> rend==end). We only go round the loop once.
> 
> If we only have one memblock that is bigger than base:(base+size) we end up with
> three regions, start_rgn=1,end_rgn=2. The trickery here is the '@rgn intersects
> from above' code decreases the loop counter so we process the same entry twice,
> hitting '@rgn is fully contained, record it' the second time round... so we go
> round the loop four times.
> 
> I can't see how we hit the:
> > 	if (rbase >= end)
> > 		break;
> > 	if (rend <= base)
> > 		continue;
> 
> code in either case...

I consistently misread that as rend >= end and rbase <= base! In which case,
I agree with your analysis:

Reviewed-by: Will Deacon <will.deacon@arm.com>

The patch could probably still use an ack from an mm person.

Will

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

* Re: [PATCH v27 1/9] memblock: add memblock_cap_memory_range()
@ 2016-11-18 12:10                     ` Will Deacon
  0 siblings, 0 replies; 58+ messages in thread
From: Will Deacon @ 2016-11-18 12:10 UTC (permalink / raw)
  To: James Morse
  Cc: mark.rutland, linux-mm, geoff, catalin.marinas, kexec,
	AKASHI Takahiro, bauerman, Dennis Chen, akpm, nd, dyoung,
	linux-arm-kernel

On Thu, Nov 17, 2016 at 06:00:58PM +0000, James Morse wrote:
> On 17/11/16 11:19, Will Deacon wrote:
> > It looks much better, thanks! Just one question below.
> > 
> 
> > On Thu, Nov 17, 2016 at 02:34:24PM +0900, AKASHI Takahiro wrote:
> >> diff --git a/mm/memblock.c b/mm/memblock.c
> >> index 7608bc3..fea1688 100644
> >> --- a/mm/memblock.c
> >> +++ b/mm/memblock.c
> >> @@ -1514,11 +1514,37 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >>  			      (phys_addr_t)ULLONG_MAX);
> >>  }
> >>  
> >> +void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
> >> +{
> >> +	int start_rgn, end_rgn;
> >> +	int i, ret;
> >> +
> >> +	if (!size)
> >> +		return;
> >> +
> >> +	ret = memblock_isolate_range(&memblock.memory, base, size,
> >> +						&start_rgn, &end_rgn);
> >> +	if (ret)
> >> +		return;
> >> +
> >> +	/* remove all the MAP regions */
> >> +	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
> >> +		if (!memblock_is_nomap(&memblock.memory.regions[i]))
> >> +			memblock_remove_region(&memblock.memory, i);
> > 
> > In the case that we have only one, giant memblock that covers base all
> > of base + size, can't we end up with start_rgn = end_rgn = 0? In which
> 
> Can this happen? If we only have one memblock that exactly spans
> base:(base+size), memblock_isolate_range() will hit the '@rgn is fully
> contained, record it' code and set start_rgn=0,end_rgn=1. (rbase==base,
> rend==end). We only go round the loop once.
> 
> If we only have one memblock that is bigger than base:(base+size) we end up with
> three regions, start_rgn=1,end_rgn=2. The trickery here is the '@rgn intersects
> from above' code decreases the loop counter so we process the same entry twice,
> hitting '@rgn is fully contained, record it' the second time round... so we go
> round the loop four times.
> 
> I can't see how we hit the:
> > 	if (rbase >= end)
> > 		break;
> > 	if (rend <= base)
> > 		continue;
> 
> code in either case...

I consistently misread that as rend >= end and rbase <= base! In which case,
I agree with your analysis:

Reviewed-by: Will Deacon <will.deacon@arm.com>

The patch could probably still use an ack from an mm person.

Will

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

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

end of thread, other threads:[~2016-11-18 12:10 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-02  4:49 [PATCH v27 0/9] arm64: add kdump support AKASHI Takahiro
2016-11-02  4:49 ` AKASHI Takahiro
2016-11-02  4:51 ` [PATCH v27 1/9] memblock: add memblock_cap_memory_range() AKASHI Takahiro
2016-11-02  4:51   ` AKASHI Takahiro
2016-11-02  4:51   ` AKASHI Takahiro
2016-11-10 17:27   ` Will Deacon
2016-11-10 17:27     ` Will Deacon
2016-11-10 17:27     ` Will Deacon
2016-11-11  2:50     ` AKASHI Takahiro
2016-11-11  2:50       ` AKASHI Takahiro
2016-11-11  2:50       ` AKASHI Takahiro
2016-11-11  3:19       ` Dennis Chen
2016-11-11  3:19         ` Dennis Chen
2016-11-11  3:19         ` Dennis Chen
2016-11-14  5:55         ` AKASHI Takahiro
2016-11-14  5:55           ` AKASHI Takahiro
2016-11-14  5:55           ` AKASHI Takahiro
2016-11-16 16:30           ` Will Deacon
2016-11-16 16:30             ` Will Deacon
2016-11-16 16:30             ` Will Deacon
2016-11-17  5:34             ` AKASHI Takahiro
2016-11-17  5:34               ` AKASHI Takahiro
2016-11-17  5:34               ` AKASHI Takahiro
2016-11-17 11:19               ` Will Deacon
2016-11-17 11:19                 ` Will Deacon
2016-11-17 11:19                 ` Will Deacon
2016-11-17 18:00                 ` James Morse
2016-11-17 18:00                   ` James Morse
2016-11-17 18:00                   ` James Morse
2016-11-18  1:03                   ` AKASHI Takahiro
2016-11-18  1:03                     ` AKASHI Takahiro
2016-11-18  1:03                     ` AKASHI Takahiro
2016-11-18 12:10                   ` Will Deacon
2016-11-18 12:10                     ` Will Deacon
2016-11-18 12:10                     ` Will Deacon
2016-11-02  4:52 ` [PATCH v27 2/9] arm64: limit memory regions based on DT property, usable-memory-range AKASHI Takahiro
2016-11-02  4:52   ` AKASHI Takahiro
2016-11-02  4:52 ` [PATCH v27 3/9] arm64: kdump: reserve memory for crash dump kernel AKASHI Takahiro
2016-11-02  4:52   ` AKASHI Takahiro
2016-11-02  4:52 ` [PATCH v27 4/9] arm64: kdump: implement machine_crash_shutdown() AKASHI Takahiro
2016-11-02  4:52   ` AKASHI Takahiro
2016-11-02  4:52 ` [PATCH v27 5/9] arm64: kdump: add VMCOREINFO's for user-space tools AKASHI Takahiro
2016-11-02  4:52   ` AKASHI Takahiro
2016-11-02  4:52 ` [PATCH v27 6/9] arm64: kdump: provide /proc/vmcore file AKASHI Takahiro
2016-11-02  4:52   ` AKASHI Takahiro
2016-11-02  4:52 ` [PATCH v27 7/9] arm64: kdump: enable kdump in defconfig AKASHI Takahiro
2016-11-02  4:52   ` AKASHI Takahiro
2016-11-02  4:52 ` [PATCH v27 8/9] Documentation: kdump: describe arm64 port AKASHI Takahiro
2016-11-02  4:52   ` AKASHI Takahiro
     [not found] ` <20161102044959.11954-1-takahiro.akashi-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2016-11-02  4:54   ` [PATCH v27 9/9] Documentation: dt: chosen properties for arm64 kdump AKASHI Takahiro
2016-11-02  4:54     ` AKASHI Takahiro
2016-11-02  4:54     ` AKASHI Takahiro
2016-11-02  9:39 ` [PATCH v27 0/9] arm64: add kdump support Pratyush Anand
2016-11-02  9:39   ` Pratyush Anand
2016-11-04  3:00 ` AKASHI Takahiro
2016-11-04  3:00   ` AKASHI Takahiro
2016-11-10 16:06   ` James Morse
2016-11-10 16:06     ` James Morse

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.