All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue
@ 2016-06-23 11:30 ` Dennis Chen
  0 siblings, 0 replies; 19+ messages in thread
From: Dennis Chen @ 2016-06-23 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: nd, Dennis Chen, Catalin Marinas, Steve Capper, Ard Biesheuvel,
	Will Deacon, Mark Rutland, Rafael J . Wysocki, Matt Fleming,
	linux-mm, linux-acpi, linux-efi

Two major changes in this patch:
[1] Add memblock_mem_limit_mark_nomap(phys_addr_t limit) function to
mark memblock regions above the @limit as NOMAP region, which will
be used to address the observed 'mem=x' kernel parameter issue.

[2] Add 'size' and 'flag' debug output in the memblock debugfs.
The '/sys/kernel/debug/memblock/memory' output looks like before:
   0: 0x0000008000000000..0x0000008001e7ffff
   1: 0x0000008001e80000..0x00000083ff184fff
   2: 0x00000083ff185000..0x00000083ff1c2fff
   3: 0x00000083ff1c3000..0x00000083ff222fff
   4: 0x00000083ff223000..0x00000083ffe42fff
   5: 0x00000083ffe43000..0x00000083ffffffff

With this patch applied:
   0: 0x0000008000000000..0x0000008001e7ffff  0x0000000001e80000  0x4
   1: 0x0000008001e80000..0x00000083ff184fff  0x00000003fd305000  0x0
   2: 0x00000083ff185000..0x00000083ff1c2fff  0x000000000003e000  0x4
   3: 0x00000083ff1c3000..0x00000083ff222fff  0x0000000000060000  0x0
   4: 0x00000083ff223000..0x00000083ffe42fff  0x0000000000c20000  0x4
   5: 0x00000083ffe43000..0x00000083ffffffff  0x00000000001bd000  0x0

Signed-off-by: Dennis Chen <dennis.chen@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Steve Capper <steve.capper@arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: linux-mm@kvack.org
Cc: linux-acpi@vger.kernel.org
Cc: linux-efi@vger.kernel.org
---
 include/linux/memblock.h |  2 ++
 mm/memblock.c            | 50 ++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 6c14b61..5e069c8 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -92,6 +92,7 @@ int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
 int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
+int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
 ulong choose_memblock_flags(void);
 
 /* Low level functions */
@@ -332,6 +333,7 @@ phys_addr_t memblock_mem_size(unsigned long limit_pfn);
 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_mark_nomap(phys_addr_t limit);
 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 ca09915..60930ac 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -814,6 +814,18 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
 }
 
 /**
+ * memblock_clear_nomap - Clear flag MEMBLOCK_NOMAP for a specified region.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Return 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size)
+{
+	return memblock_setclr_flag(base, size, 0, MEMBLOCK_NOMAP);
+}
+
+/**
  * __next_reserved_mem_region - next function for for_each_reserved_region()
  * @idx: pointer to u64 loop variable
  * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL
@@ -1465,14 +1477,11 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)
 	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
 }
 
-void __init memblock_enforce_memory_limit(phys_addr_t limit)
+static phys_addr_t __find_max_addr(phys_addr_t limit)
 {
 	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
 	struct memblock_region *r;
 
-	if (!limit)
-		return;
-
 	/* find out max address */
 	for_each_memblock(memory, r) {
 		if (limit <= r->size) {
@@ -1482,6 +1491,18 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 		limit -= r->size;
 	}
 
+	return max_addr;
+}
+
+void __init memblock_enforce_memory_limit(phys_addr_t limit)
+{
+	phys_addr_t max_addr;
+
+	if (!limit)
+		return;
+
+	max_addr = __find_max_addr(limit);
+
 	/* truncate both memory and reserved regions */
 	memblock_remove_range(&memblock.memory, max_addr,
 			      (phys_addr_t)ULLONG_MAX);
@@ -1489,6 +1510,17 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 			      (phys_addr_t)ULLONG_MAX);
 }
 
+void __init memblock_mem_limit_mark_nomap(phys_addr_t limit)
+{
+	phys_addr_t max_addr;
+
+	if (!limit)
+		return;
+
+	max_addr = __find_max_addr(limit);
+	memblock_mark_nomap(max_addr, (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;
@@ -1677,13 +1709,15 @@ static int memblock_debug_show(struct seq_file *m, void *private)
 		reg = &type->regions[i];
 		seq_printf(m, "%4d: ", i);
 		if (sizeof(phys_addr_t) == 4)
-			seq_printf(m, "0x%08lx..0x%08lx\n",
+			seq_printf(m, "0x%08lx..0x%08lx  0x%08lx  0x%lx\n",
 				   (unsigned long)reg->base,
-				   (unsigned long)(reg->base + reg->size - 1));
+				   (unsigned long)(reg->base + reg->size - 1),
+				   (unsigned long)reg->size, reg->flags);
 		else
-			seq_printf(m, "0x%016llx..0x%016llx\n",
+			seq_printf(m, "0x%016llx..0x%016llx  0x%016llx  0x%lx\n",
 				   (unsigned long long)reg->base,
-				   (unsigned long long)(reg->base + reg->size - 1));
+				   (unsigned long long)(reg->base + reg->size - 1),
+				   (unsigned long long)reg->size, reg->flags);
 
 	}
 	return 0;
-- 
1.8.3.1

--
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] 19+ messages in thread

* [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue
@ 2016-06-23 11:30 ` Dennis Chen
  0 siblings, 0 replies; 19+ messages in thread
From: Dennis Chen @ 2016-06-23 11:30 UTC (permalink / raw)
  To: linux-arm-kernel

Two major changes in this patch:
[1] Add memblock_mem_limit_mark_nomap(phys_addr_t limit) function to
mark memblock regions above the @limit as NOMAP region, which will
be used to address the observed 'mem=x' kernel parameter issue.

[2] Add 'size' and 'flag' debug output in the memblock debugfs.
The '/sys/kernel/debug/memblock/memory' output looks like before:
   0: 0x0000008000000000..0x0000008001e7ffff
   1: 0x0000008001e80000..0x00000083ff184fff
   2: 0x00000083ff185000..0x00000083ff1c2fff
   3: 0x00000083ff1c3000..0x00000083ff222fff
   4: 0x00000083ff223000..0x00000083ffe42fff
   5: 0x00000083ffe43000..0x00000083ffffffff

With this patch applied:
   0: 0x0000008000000000..0x0000008001e7ffff  0x0000000001e80000  0x4
   1: 0x0000008001e80000..0x00000083ff184fff  0x00000003fd305000  0x0
   2: 0x00000083ff185000..0x00000083ff1c2fff  0x000000000003e000  0x4
   3: 0x00000083ff1c3000..0x00000083ff222fff  0x0000000000060000  0x0
   4: 0x00000083ff223000..0x00000083ffe42fff  0x0000000000c20000  0x4
   5: 0x00000083ffe43000..0x00000083ffffffff  0x00000000001bd000  0x0

Signed-off-by: Dennis Chen <dennis.chen@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Steve Capper <steve.capper@arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: linux-mm at kvack.org
Cc: linux-acpi at vger.kernel.org
Cc: linux-efi at vger.kernel.org
---
 include/linux/memblock.h |  2 ++
 mm/memblock.c            | 50 ++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 44 insertions(+), 8 deletions(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 6c14b61..5e069c8 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -92,6 +92,7 @@ int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
 int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
 int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
+int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
 ulong choose_memblock_flags(void);
 
 /* Low level functions */
@@ -332,6 +333,7 @@ phys_addr_t memblock_mem_size(unsigned long limit_pfn);
 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_mark_nomap(phys_addr_t limit);
 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 ca09915..60930ac 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -814,6 +814,18 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
 }
 
 /**
+ * memblock_clear_nomap - Clear flag MEMBLOCK_NOMAP for a specified region.
+ * @base: the base phys addr of the region
+ * @size: the size of the region
+ *
+ * Return 0 on success, -errno on failure.
+ */
+int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size)
+{
+	return memblock_setclr_flag(base, size, 0, MEMBLOCK_NOMAP);
+}
+
+/**
  * __next_reserved_mem_region - next function for for_each_reserved_region()
  * @idx: pointer to u64 loop variable
  * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL
@@ -1465,14 +1477,11 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)
 	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
 }
 
-void __init memblock_enforce_memory_limit(phys_addr_t limit)
+static phys_addr_t __find_max_addr(phys_addr_t limit)
 {
 	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
 	struct memblock_region *r;
 
-	if (!limit)
-		return;
-
 	/* find out max address */
 	for_each_memblock(memory, r) {
 		if (limit <= r->size) {
@@ -1482,6 +1491,18 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 		limit -= r->size;
 	}
 
+	return max_addr;
+}
+
+void __init memblock_enforce_memory_limit(phys_addr_t limit)
+{
+	phys_addr_t max_addr;
+
+	if (!limit)
+		return;
+
+	max_addr = __find_max_addr(limit);
+
 	/* truncate both memory and reserved regions */
 	memblock_remove_range(&memblock.memory, max_addr,
 			      (phys_addr_t)ULLONG_MAX);
@@ -1489,6 +1510,17 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
 			      (phys_addr_t)ULLONG_MAX);
 }
 
+void __init memblock_mem_limit_mark_nomap(phys_addr_t limit)
+{
+	phys_addr_t max_addr;
+
+	if (!limit)
+		return;
+
+	max_addr = __find_max_addr(limit);
+	memblock_mark_nomap(max_addr, (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;
@@ -1677,13 +1709,15 @@ static int memblock_debug_show(struct seq_file *m, void *private)
 		reg = &type->regions[i];
 		seq_printf(m, "%4d: ", i);
 		if (sizeof(phys_addr_t) == 4)
-			seq_printf(m, "0x%08lx..0x%08lx\n",
+			seq_printf(m, "0x%08lx..0x%08lx  0x%08lx  0x%lx\n",
 				   (unsigned long)reg->base,
-				   (unsigned long)(reg->base + reg->size - 1));
+				   (unsigned long)(reg->base + reg->size - 1),
+				   (unsigned long)reg->size, reg->flags);
 		else
-			seq_printf(m, "0x%016llx..0x%016llx\n",
+			seq_printf(m, "0x%016llx..0x%016llx  0x%016llx  0x%lx\n",
 				   (unsigned long long)reg->base,
-				   (unsigned long long)(reg->base + reg->size - 1));
+				   (unsigned long long)(reg->base + reg->size - 1),
+				   (unsigned long long)reg->size, reg->flags);
 
 	}
 	return 0;
-- 
1.8.3.1

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

* [PATCH 2/2] arm64:acpi Fix the acpi alignment exeception when 'mem=' specified
  2016-06-23 11:30 ` Dennis Chen
@ 2016-06-23 11:30   ` Dennis Chen
  -1 siblings, 0 replies; 19+ messages in thread
From: Dennis Chen @ 2016-06-23 11:30 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: nd, Dennis Chen, Catalin Marinas, Steve Capper, Ard Biesheuvel,
	Will Deacon, Mark Rutland, Rafael J . Wysocki, Matt Fleming,
	linux-mm, linux-acpi, linux-efi

This is a rework patch based on [1]. According to the proposal from
Mark Rutland, when applying the system memory limit through 'mem=x'
kernel command line, don't remove the rest memory regions above the
limit from the memblock, instead marking them as MEMBLOCK_NOMAP region,
which will preserve the ability to identify regions as normal memory
while not using them for allocation and the linear map.

Without this patch, the ACPI core will map those acpi data regions(if
they are above the limit) as device type memory, which will result in
the alignment exception when ACPI core parses the AML data stream 
since the parsing will produce some non-alignment accesses.

[1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438443.html

Signed-off-by: Dennis Chen <dennis.chen@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Steve Capper <steve.capper@arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: linux-mm@kvack.org
Cc: linux-acpi@vger.kernel.org
Cc: linux-efi@vger.kernel.org
---
 arch/arm64/mm/init.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index d45f862..e509e24 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -222,12 +222,14 @@ void __init arm64_memblock_init(void)
 
 	/*
 	 * Apply the memory limit if it was set. Since the kernel may be loaded
-	 * high up in memory, add back the kernel region that must be accessible
-	 * via the linear mapping.
+	 * in the memory regions above the limit, so we need to clear the
+	 * MEMBLOCK_NOMAP flag of this region to make it can be accessible via
+	 * the linear mapping.
 	 */
 	if (memory_limit != (phys_addr_t)ULLONG_MAX) {
-		memblock_enforce_memory_limit(memory_limit);
-		memblock_add(__pa(_text), (u64)(_end - _text));
+		memblock_mem_limit_mark_nomap(memory_limit);
+		if (!memblock_is_map_memory(__pa(_text)))
+			memblock_clear_nomap(__pa(_text), (u64)(_end - _text));
 	}
 
 	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
-- 
1.8.3.1

--
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] 19+ messages in thread

* [PATCH 2/2] arm64:acpi Fix the acpi alignment exeception when 'mem=' specified
@ 2016-06-23 11:30   ` Dennis Chen
  0 siblings, 0 replies; 19+ messages in thread
From: Dennis Chen @ 2016-06-23 11:30 UTC (permalink / raw)
  To: linux-arm-kernel

This is a rework patch based on [1]. According to the proposal from
Mark Rutland, when applying the system memory limit through 'mem=x'
kernel command line, don't remove the rest memory regions above the
limit from the memblock, instead marking them as MEMBLOCK_NOMAP region,
which will preserve the ability to identify regions as normal memory
while not using them for allocation and the linear map.

Without this patch, the ACPI core will map those acpi data regions(if
they are above the limit) as device type memory, which will result in
the alignment exception when ACPI core parses the AML data stream 
since the parsing will produce some non-alignment accesses.

[1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438443.html

Signed-off-by: Dennis Chen <dennis.chen@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Steve Capper <steve.capper@arm.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>
Cc: linux-mm at kvack.org
Cc: linux-acpi at vger.kernel.org
Cc: linux-efi at vger.kernel.org
---
 arch/arm64/mm/init.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index d45f862..e509e24 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -222,12 +222,14 @@ void __init arm64_memblock_init(void)
 
 	/*
 	 * Apply the memory limit if it was set. Since the kernel may be loaded
-	 * high up in memory, add back the kernel region that must be accessible
-	 * via the linear mapping.
+	 * in the memory regions above the limit, so we need to clear the
+	 * MEMBLOCK_NOMAP flag of this region to make it can be accessible via
+	 * the linear mapping.
 	 */
 	if (memory_limit != (phys_addr_t)ULLONG_MAX) {
-		memblock_enforce_memory_limit(memory_limit);
-		memblock_add(__pa(_text), (u64)(_end - _text));
+		memblock_mem_limit_mark_nomap(memory_limit);
+		if (!memblock_is_map_memory(__pa(_text)))
+			memblock_clear_nomap(__pa(_text), (u64)(_end - _text));
 	}
 
 	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
-- 
1.8.3.1

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

* Re: [PATCH 2/2] arm64:acpi Fix the acpi alignment exeception when 'mem=' specified
  2016-06-23 11:30   ` Dennis Chen
  (?)
@ 2016-06-23 12:42       ` Mark Rutland
  -1 siblings, 0 replies; 19+ messages in thread
From: Mark Rutland @ 2016-06-23 12:42 UTC (permalink / raw)
  To: Dennis Chen
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	nd-5wv7dgnIgG8, Catalin Marinas, Steve Capper, Ard Biesheuvel,
	Will Deacon, Rafael J . Wysocki, Matt Fleming,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA

On Thu, Jun 23, 2016 at 07:30:15PM +0800, Dennis Chen wrote:
> This is a rework patch based on [1]. According to the proposal from
> Mark Rutland, when applying the system memory limit through 'mem=x'
> kernel command line, don't remove the rest memory regions above the
> limit from the memblock, instead marking them as MEMBLOCK_NOMAP region,
> which will preserve the ability to identify regions as normal memory
> while not using them for allocation and the linear map.
> 
> Without this patch, the ACPI core will map those acpi data regions(if
> they are above the limit) as device type memory, which will result in
> the alignment exception when ACPI core parses the AML data stream 
> since the parsing will produce some non-alignment accesses.
>
> [1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438443.html

Please rewrite the message to be standalone (i.e. so peopel can read
this without having to folow the link).

Explain why using mem= makes ACPI think regions should be mapped as
Device memory, the problems this causes for ACPICA, then cover why we
want to nomap the region.

> Signed-off-by: Dennis Chen <dennis.chen-5wv7dgnIgG8@public.gmane.org>
> Cc: Catalin Marinas <catalin.marinas-5wv7dgnIgG8@public.gmane.org>
> Cc: Steve Capper <steve.capper-5wv7dgnIgG8@public.gmane.org>
> Cc: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
> Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
> Cc: Rafael J. Wysocki <rafael.j.wysocki-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
> Cc: linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org
> Cc: linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> ---
>  arch/arm64/mm/init.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> index d45f862..e509e24 100644
> --- a/arch/arm64/mm/init.c
> +++ b/arch/arm64/mm/init.c
> @@ -222,12 +222,14 @@ void __init arm64_memblock_init(void)
>  
>  	/*
>  	 * Apply the memory limit if it was set. Since the kernel may be loaded
> -	 * high up in memory, add back the kernel region that must be accessible
> -	 * via the linear mapping.
> +	 * in the memory regions above the limit, so we need to clear the
> +	 * MEMBLOCK_NOMAP flag of this region to make it can be accessible via
> +	 * the linear mapping.
>  	 */
>  	if (memory_limit != (phys_addr_t)ULLONG_MAX) {
> -		memblock_enforce_memory_limit(memory_limit);
> -		memblock_add(__pa(_text), (u64)(_end - _text));
> +		memblock_mem_limit_mark_nomap(memory_limit);
> +		if (!memblock_is_map_memory(__pa(_text)))
> +			memblock_clear_nomap(__pa(_text), (u64)(_end - _text));

I think that the memblock_is_map_memory() check should go. Just because
a page of the kernel image is mapped doesn't mean that the rest is. That
will make this a 1-1 change.

Other than that, this looks right to me.

Thanks,
Mark.

>  	}
>  
>  	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
> -- 
> 1.8.3.1
> 

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

* Re: [PATCH 2/2] arm64:acpi Fix the acpi alignment exeception when 'mem=' specified
@ 2016-06-23 12:42       ` Mark Rutland
  0 siblings, 0 replies; 19+ messages in thread
From: Mark Rutland @ 2016-06-23 12:42 UTC (permalink / raw)
  To: Dennis Chen
  Cc: linux-arm-kernel, nd, Catalin Marinas, Steve Capper,
	Ard Biesheuvel, Will Deacon, Rafael J . Wysocki, Matt Fleming,
	linux-mm, linux-acpi, linux-efi

On Thu, Jun 23, 2016 at 07:30:15PM +0800, Dennis Chen wrote:
> This is a rework patch based on [1]. According to the proposal from
> Mark Rutland, when applying the system memory limit through 'mem=x'
> kernel command line, don't remove the rest memory regions above the
> limit from the memblock, instead marking them as MEMBLOCK_NOMAP region,
> which will preserve the ability to identify regions as normal memory
> while not using them for allocation and the linear map.
> 
> Without this patch, the ACPI core will map those acpi data regions(if
> they are above the limit) as device type memory, which will result in
> the alignment exception when ACPI core parses the AML data stream 
> since the parsing will produce some non-alignment accesses.
>
> [1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438443.html

Please rewrite the message to be standalone (i.e. so peopel can read
this without having to folow the link).

Explain why using mem= makes ACPI think regions should be mapped as
Device memory, the problems this causes for ACPICA, then cover why we
want to nomap the region.

> Signed-off-by: Dennis Chen <dennis.chen@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Steve Capper <steve.capper@arm.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Cc: Matt Fleming <matt@codeblueprint.co.uk>
> Cc: linux-mm@kvack.org
> Cc: linux-acpi@vger.kernel.org
> Cc: linux-efi@vger.kernel.org
> ---
>  arch/arm64/mm/init.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> index d45f862..e509e24 100644
> --- a/arch/arm64/mm/init.c
> +++ b/arch/arm64/mm/init.c
> @@ -222,12 +222,14 @@ void __init arm64_memblock_init(void)
>  
>  	/*
>  	 * Apply the memory limit if it was set. Since the kernel may be loaded
> -	 * high up in memory, add back the kernel region that must be accessible
> -	 * via the linear mapping.
> +	 * in the memory regions above the limit, so we need to clear the
> +	 * MEMBLOCK_NOMAP flag of this region to make it can be accessible via
> +	 * the linear mapping.
>  	 */
>  	if (memory_limit != (phys_addr_t)ULLONG_MAX) {
> -		memblock_enforce_memory_limit(memory_limit);
> -		memblock_add(__pa(_text), (u64)(_end - _text));
> +		memblock_mem_limit_mark_nomap(memory_limit);
> +		if (!memblock_is_map_memory(__pa(_text)))
> +			memblock_clear_nomap(__pa(_text), (u64)(_end - _text));

I think that the memblock_is_map_memory() check should go. Just because
a page of the kernel image is mapped doesn't mean that the rest is. That
will make this a 1-1 change.

Other than that, this looks right to me.

Thanks,
Mark.

>  	}
>  
>  	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
> -- 
> 1.8.3.1
> 

--
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] 19+ messages in thread

* [PATCH 2/2] arm64:acpi Fix the acpi alignment exeception when 'mem=' specified
@ 2016-06-23 12:42       ` Mark Rutland
  0 siblings, 0 replies; 19+ messages in thread
From: Mark Rutland @ 2016-06-23 12:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 23, 2016 at 07:30:15PM +0800, Dennis Chen wrote:
> This is a rework patch based on [1]. According to the proposal from
> Mark Rutland, when applying the system memory limit through 'mem=x'
> kernel command line, don't remove the rest memory regions above the
> limit from the memblock, instead marking them as MEMBLOCK_NOMAP region,
> which will preserve the ability to identify regions as normal memory
> while not using them for allocation and the linear map.
> 
> Without this patch, the ACPI core will map those acpi data regions(if
> they are above the limit) as device type memory, which will result in
> the alignment exception when ACPI core parses the AML data stream 
> since the parsing will produce some non-alignment accesses.
>
> [1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438443.html

Please rewrite the message to be standalone (i.e. so peopel can read
this without having to folow the link).

Explain why using mem= makes ACPI think regions should be mapped as
Device memory, the problems this causes for ACPICA, then cover why we
want to nomap the region.

> Signed-off-by: Dennis Chen <dennis.chen@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Steve Capper <steve.capper@arm.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Cc: Matt Fleming <matt@codeblueprint.co.uk>
> Cc: linux-mm at kvack.org
> Cc: linux-acpi at vger.kernel.org
> Cc: linux-efi at vger.kernel.org
> ---
>  arch/arm64/mm/init.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> index d45f862..e509e24 100644
> --- a/arch/arm64/mm/init.c
> +++ b/arch/arm64/mm/init.c
> @@ -222,12 +222,14 @@ void __init arm64_memblock_init(void)
>  
>  	/*
>  	 * Apply the memory limit if it was set. Since the kernel may be loaded
> -	 * high up in memory, add back the kernel region that must be accessible
> -	 * via the linear mapping.
> +	 * in the memory regions above the limit, so we need to clear the
> +	 * MEMBLOCK_NOMAP flag of this region to make it can be accessible via
> +	 * the linear mapping.
>  	 */
>  	if (memory_limit != (phys_addr_t)ULLONG_MAX) {
> -		memblock_enforce_memory_limit(memory_limit);
> -		memblock_add(__pa(_text), (u64)(_end - _text));
> +		memblock_mem_limit_mark_nomap(memory_limit);
> +		if (!memblock_is_map_memory(__pa(_text)))
> +			memblock_clear_nomap(__pa(_text), (u64)(_end - _text));

I think that the memblock_is_map_memory() check should go. Just because
a page of the kernel image is mapped doesn't mean that the rest is. That
will make this a 1-1 change.

Other than that, this looks right to me.

Thanks,
Mark.

>  	}
>  
>  	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
> -- 
> 1.8.3.1
> 

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

* Re: [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue
  2016-06-23 11:30 ` Dennis Chen
  (?)
@ 2016-06-23 12:57     ` Mark Rutland
  -1 siblings, 0 replies; 19+ messages in thread
From: Mark Rutland @ 2016-06-23 12:57 UTC (permalink / raw)
  To: Dennis Chen
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	nd-5wv7dgnIgG8, Catalin Marinas, Steve Capper, Ard Biesheuvel,
	Will Deacon, Rafael J . Wysocki, Matt Fleming,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA

On Thu, Jun 23, 2016 at 07:30:14PM +0800, Dennis Chen wrote:
> Two major changes in this patch:
> [1] Add memblock_mem_limit_mark_nomap(phys_addr_t limit) function to
> mark memblock regions above the @limit as NOMAP region, which will
> be used to address the observed 'mem=x' kernel parameter issue.
> 
> [2] Add 'size' and 'flag' debug output in the memblock debugfs.
> The '/sys/kernel/debug/memblock/memory' output looks like before:
>    0: 0x0000008000000000..0x0000008001e7ffff
>    1: 0x0000008001e80000..0x00000083ff184fff
>    2: 0x00000083ff185000..0x00000083ff1c2fff
>    3: 0x00000083ff1c3000..0x00000083ff222fff
>    4: 0x00000083ff223000..0x00000083ffe42fff
>    5: 0x00000083ffe43000..0x00000083ffffffff
> 
> With this patch applied:
>    0: 0x0000008000000000..0x0000008001e7ffff  0x0000000001e80000  0x4
>    1: 0x0000008001e80000..0x00000083ff184fff  0x00000003fd305000  0x0
>    2: 0x00000083ff185000..0x00000083ff1c2fff  0x000000000003e000  0x4
>    3: 0x00000083ff1c3000..0x00000083ff222fff  0x0000000000060000  0x0
>    4: 0x00000083ff223000..0x00000083ffe42fff  0x0000000000c20000  0x4
>    5: 0x00000083ffe43000..0x00000083ffffffff  0x00000000001bd000  0x0

Please explain in the commit message what the problem being solved is,
and how this solves it. e.g.

In some cases, memblock is queried to determine whether a physical
address corresponds to memory present in a system even if unused by the
OS for the linear mapping, highmem, etc. For example, the ACPI core
needs this information to determine which attributes to use when mapping
ACPI regions. Use of incorrect memory types can result in faults, data
corruption, or other issues.

Removing memory with memblock_enforce_memory_limit throws away this
information, and so a kernel booted with mem= may suffer from the issues
described above. To avoid this, we can mark regions as nomap rather than
removing them, which preserves the information we need while preventing
other use of the regions.

This patch adds new insfrastructure to mark all memblock regions in an
address range as nomap, to cater for this. Similarly we add
infrastructure to clear the flag for an address range, which makes
handling some overlap cases simpler.

Other than that, the patch itself looks fine to me.

Thanks,
Mark.

> Signed-off-by: Dennis Chen <dennis.chen-5wv7dgnIgG8@public.gmane.org>
> Cc: Catalin Marinas <catalin.marinas-5wv7dgnIgG8@public.gmane.org>
> Cc: Steve Capper <steve.capper-5wv7dgnIgG8@public.gmane.org>
> Cc: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> Cc: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
> Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
> Cc: Rafael J. Wysocki <rafael.j.wysocki-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
> Cc: linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org
> Cc: linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> ---
>  include/linux/memblock.h |  2 ++
>  mm/memblock.c            | 50 ++++++++++++++++++++++++++++++++++++++++--------
>  2 files changed, 44 insertions(+), 8 deletions(-)
> 
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 6c14b61..5e069c8 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -92,6 +92,7 @@ int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
>  int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
> +int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
>  ulong choose_memblock_flags(void);
>  
>  /* Low level functions */
> @@ -332,6 +333,7 @@ phys_addr_t memblock_mem_size(unsigned long limit_pfn);
>  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_mark_nomap(phys_addr_t limit);
>  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 ca09915..60930ac 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -814,6 +814,18 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
>  }
>  
>  /**
> + * memblock_clear_nomap - Clear flag MEMBLOCK_NOMAP for a specified region.
> + * @base: the base phys addr of the region
> + * @size: the size of the region
> + *
> + * Return 0 on success, -errno on failure.
> + */
> +int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size)
> +{
> +	return memblock_setclr_flag(base, size, 0, MEMBLOCK_NOMAP);
> +}
> +
> +/**
>   * __next_reserved_mem_region - next function for for_each_reserved_region()
>   * @idx: pointer to u64 loop variable
>   * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL
> @@ -1465,14 +1477,11 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)
>  	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
>  }
>  
> -void __init memblock_enforce_memory_limit(phys_addr_t limit)
> +static phys_addr_t __find_max_addr(phys_addr_t limit)
>  {
>  	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
>  	struct memblock_region *r;
>  
> -	if (!limit)
> -		return;
> -
>  	/* find out max address */
>  	for_each_memblock(memory, r) {
>  		if (limit <= r->size) {
> @@ -1482,6 +1491,18 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>  		limit -= r->size;
>  	}
>  
> +	return max_addr;
> +}
> +
> +void __init memblock_enforce_memory_limit(phys_addr_t limit)
> +{
> +	phys_addr_t max_addr;
> +
> +	if (!limit)
> +		return;
> +
> +	max_addr = __find_max_addr(limit);
> +
>  	/* truncate both memory and reserved regions */
>  	memblock_remove_range(&memblock.memory, max_addr,
>  			      (phys_addr_t)ULLONG_MAX);
> @@ -1489,6 +1510,17 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>  			      (phys_addr_t)ULLONG_MAX);
>  }
>  
> +void __init memblock_mem_limit_mark_nomap(phys_addr_t limit)
> +{
> +	phys_addr_t max_addr;
> +
> +	if (!limit)
> +		return;
> +
> +	max_addr = __find_max_addr(limit);
> +	memblock_mark_nomap(max_addr, (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;
> @@ -1677,13 +1709,15 @@ static int memblock_debug_show(struct seq_file *m, void *private)
>  		reg = &type->regions[i];
>  		seq_printf(m, "%4d: ", i);
>  		if (sizeof(phys_addr_t) == 4)
> -			seq_printf(m, "0x%08lx..0x%08lx\n",
> +			seq_printf(m, "0x%08lx..0x%08lx  0x%08lx  0x%lx\n",
>  				   (unsigned long)reg->base,
> -				   (unsigned long)(reg->base + reg->size - 1));
> +				   (unsigned long)(reg->base + reg->size - 1),
> +				   (unsigned long)reg->size, reg->flags);
>  		else
> -			seq_printf(m, "0x%016llx..0x%016llx\n",
> +			seq_printf(m, "0x%016llx..0x%016llx  0x%016llx  0x%lx\n",
>  				   (unsigned long long)reg->base,
> -				   (unsigned long long)(reg->base + reg->size - 1));
> +				   (unsigned long long)(reg->base + reg->size - 1),
> +				   (unsigned long long)reg->size, reg->flags);
>  
>  	}
>  	return 0;
> -- 
> 1.8.3.1
> 

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

* Re: [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue
@ 2016-06-23 12:57     ` Mark Rutland
  0 siblings, 0 replies; 19+ messages in thread
From: Mark Rutland @ 2016-06-23 12:57 UTC (permalink / raw)
  To: Dennis Chen
  Cc: linux-arm-kernel, nd, Catalin Marinas, Steve Capper,
	Ard Biesheuvel, Will Deacon, Rafael J . Wysocki, Matt Fleming,
	linux-mm, linux-acpi, linux-efi

On Thu, Jun 23, 2016 at 07:30:14PM +0800, Dennis Chen wrote:
> Two major changes in this patch:
> [1] Add memblock_mem_limit_mark_nomap(phys_addr_t limit) function to
> mark memblock regions above the @limit as NOMAP region, which will
> be used to address the observed 'mem=x' kernel parameter issue.
> 
> [2] Add 'size' and 'flag' debug output in the memblock debugfs.
> The '/sys/kernel/debug/memblock/memory' output looks like before:
>    0: 0x0000008000000000..0x0000008001e7ffff
>    1: 0x0000008001e80000..0x00000083ff184fff
>    2: 0x00000083ff185000..0x00000083ff1c2fff
>    3: 0x00000083ff1c3000..0x00000083ff222fff
>    4: 0x00000083ff223000..0x00000083ffe42fff
>    5: 0x00000083ffe43000..0x00000083ffffffff
> 
> With this patch applied:
>    0: 0x0000008000000000..0x0000008001e7ffff  0x0000000001e80000  0x4
>    1: 0x0000008001e80000..0x00000083ff184fff  0x00000003fd305000  0x0
>    2: 0x00000083ff185000..0x00000083ff1c2fff  0x000000000003e000  0x4
>    3: 0x00000083ff1c3000..0x00000083ff222fff  0x0000000000060000  0x0
>    4: 0x00000083ff223000..0x00000083ffe42fff  0x0000000000c20000  0x4
>    5: 0x00000083ffe43000..0x00000083ffffffff  0x00000000001bd000  0x0

Please explain in the commit message what the problem being solved is,
and how this solves it. e.g.

In some cases, memblock is queried to determine whether a physical
address corresponds to memory present in a system even if unused by the
OS for the linear mapping, highmem, etc. For example, the ACPI core
needs this information to determine which attributes to use when mapping
ACPI regions. Use of incorrect memory types can result in faults, data
corruption, or other issues.

Removing memory with memblock_enforce_memory_limit throws away this
information, and so a kernel booted with mem= may suffer from the issues
described above. To avoid this, we can mark regions as nomap rather than
removing them, which preserves the information we need while preventing
other use of the regions.

This patch adds new insfrastructure to mark all memblock regions in an
address range as nomap, to cater for this. Similarly we add
infrastructure to clear the flag for an address range, which makes
handling some overlap cases simpler.

Other than that, the patch itself looks fine to me.

Thanks,
Mark.

> Signed-off-by: Dennis Chen <dennis.chen@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Steve Capper <steve.capper@arm.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Cc: Matt Fleming <matt@codeblueprint.co.uk>
> Cc: linux-mm@kvack.org
> Cc: linux-acpi@vger.kernel.org
> Cc: linux-efi@vger.kernel.org
> ---
>  include/linux/memblock.h |  2 ++
>  mm/memblock.c            | 50 ++++++++++++++++++++++++++++++++++++++++--------
>  2 files changed, 44 insertions(+), 8 deletions(-)
> 
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 6c14b61..5e069c8 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -92,6 +92,7 @@ int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
>  int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
> +int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
>  ulong choose_memblock_flags(void);
>  
>  /* Low level functions */
> @@ -332,6 +333,7 @@ phys_addr_t memblock_mem_size(unsigned long limit_pfn);
>  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_mark_nomap(phys_addr_t limit);
>  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 ca09915..60930ac 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -814,6 +814,18 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
>  }
>  
>  /**
> + * memblock_clear_nomap - Clear flag MEMBLOCK_NOMAP for a specified region.
> + * @base: the base phys addr of the region
> + * @size: the size of the region
> + *
> + * Return 0 on success, -errno on failure.
> + */
> +int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size)
> +{
> +	return memblock_setclr_flag(base, size, 0, MEMBLOCK_NOMAP);
> +}
> +
> +/**
>   * __next_reserved_mem_region - next function for for_each_reserved_region()
>   * @idx: pointer to u64 loop variable
>   * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL
> @@ -1465,14 +1477,11 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)
>  	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
>  }
>  
> -void __init memblock_enforce_memory_limit(phys_addr_t limit)
> +static phys_addr_t __find_max_addr(phys_addr_t limit)
>  {
>  	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
>  	struct memblock_region *r;
>  
> -	if (!limit)
> -		return;
> -
>  	/* find out max address */
>  	for_each_memblock(memory, r) {
>  		if (limit <= r->size) {
> @@ -1482,6 +1491,18 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>  		limit -= r->size;
>  	}
>  
> +	return max_addr;
> +}
> +
> +void __init memblock_enforce_memory_limit(phys_addr_t limit)
> +{
> +	phys_addr_t max_addr;
> +
> +	if (!limit)
> +		return;
> +
> +	max_addr = __find_max_addr(limit);
> +
>  	/* truncate both memory and reserved regions */
>  	memblock_remove_range(&memblock.memory, max_addr,
>  			      (phys_addr_t)ULLONG_MAX);
> @@ -1489,6 +1510,17 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>  			      (phys_addr_t)ULLONG_MAX);
>  }
>  
> +void __init memblock_mem_limit_mark_nomap(phys_addr_t limit)
> +{
> +	phys_addr_t max_addr;
> +
> +	if (!limit)
> +		return;
> +
> +	max_addr = __find_max_addr(limit);
> +	memblock_mark_nomap(max_addr, (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;
> @@ -1677,13 +1709,15 @@ static int memblock_debug_show(struct seq_file *m, void *private)
>  		reg = &type->regions[i];
>  		seq_printf(m, "%4d: ", i);
>  		if (sizeof(phys_addr_t) == 4)
> -			seq_printf(m, "0x%08lx..0x%08lx\n",
> +			seq_printf(m, "0x%08lx..0x%08lx  0x%08lx  0x%lx\n",
>  				   (unsigned long)reg->base,
> -				   (unsigned long)(reg->base + reg->size - 1));
> +				   (unsigned long)(reg->base + reg->size - 1),
> +				   (unsigned long)reg->size, reg->flags);
>  		else
> -			seq_printf(m, "0x%016llx..0x%016llx\n",
> +			seq_printf(m, "0x%016llx..0x%016llx  0x%016llx  0x%lx\n",
>  				   (unsigned long long)reg->base,
> -				   (unsigned long long)(reg->base + reg->size - 1));
> +				   (unsigned long long)(reg->base + reg->size - 1),
> +				   (unsigned long long)reg->size, reg->flags);
>  
>  	}
>  	return 0;
> -- 
> 1.8.3.1
> 

--
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] 19+ messages in thread

* [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue
@ 2016-06-23 12:57     ` Mark Rutland
  0 siblings, 0 replies; 19+ messages in thread
From: Mark Rutland @ 2016-06-23 12:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 23, 2016 at 07:30:14PM +0800, Dennis Chen wrote:
> Two major changes in this patch:
> [1] Add memblock_mem_limit_mark_nomap(phys_addr_t limit) function to
> mark memblock regions above the @limit as NOMAP region, which will
> be used to address the observed 'mem=x' kernel parameter issue.
> 
> [2] Add 'size' and 'flag' debug output in the memblock debugfs.
> The '/sys/kernel/debug/memblock/memory' output looks like before:
>    0: 0x0000008000000000..0x0000008001e7ffff
>    1: 0x0000008001e80000..0x00000083ff184fff
>    2: 0x00000083ff185000..0x00000083ff1c2fff
>    3: 0x00000083ff1c3000..0x00000083ff222fff
>    4: 0x00000083ff223000..0x00000083ffe42fff
>    5: 0x00000083ffe43000..0x00000083ffffffff
> 
> With this patch applied:
>    0: 0x0000008000000000..0x0000008001e7ffff  0x0000000001e80000  0x4
>    1: 0x0000008001e80000..0x00000083ff184fff  0x00000003fd305000  0x0
>    2: 0x00000083ff185000..0x00000083ff1c2fff  0x000000000003e000  0x4
>    3: 0x00000083ff1c3000..0x00000083ff222fff  0x0000000000060000  0x0
>    4: 0x00000083ff223000..0x00000083ffe42fff  0x0000000000c20000  0x4
>    5: 0x00000083ffe43000..0x00000083ffffffff  0x00000000001bd000  0x0

Please explain in the commit message what the problem being solved is,
and how this solves it. e.g.

In some cases, memblock is queried to determine whether a physical
address corresponds to memory present in a system even if unused by the
OS for the linear mapping, highmem, etc. For example, the ACPI core
needs this information to determine which attributes to use when mapping
ACPI regions. Use of incorrect memory types can result in faults, data
corruption, or other issues.

Removing memory with memblock_enforce_memory_limit throws away this
information, and so a kernel booted with mem= may suffer from the issues
described above. To avoid this, we can mark regions as nomap rather than
removing them, which preserves the information we need while preventing
other use of the regions.

This patch adds new insfrastructure to mark all memblock regions in an
address range as nomap, to cater for this. Similarly we add
infrastructure to clear the flag for an address range, which makes
handling some overlap cases simpler.

Other than that, the patch itself looks fine to me.

Thanks,
Mark.

> Signed-off-by: Dennis Chen <dennis.chen@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Steve Capper <steve.capper@arm.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Cc: Matt Fleming <matt@codeblueprint.co.uk>
> Cc: linux-mm at kvack.org
> Cc: linux-acpi at vger.kernel.org
> Cc: linux-efi at vger.kernel.org
> ---
>  include/linux/memblock.h |  2 ++
>  mm/memblock.c            | 50 ++++++++++++++++++++++++++++++++++++++++--------
>  2 files changed, 44 insertions(+), 8 deletions(-)
> 
> diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> index 6c14b61..5e069c8 100644
> --- a/include/linux/memblock.h
> +++ b/include/linux/memblock.h
> @@ -92,6 +92,7 @@ int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
>  int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
>  int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
> +int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
>  ulong choose_memblock_flags(void);
>  
>  /* Low level functions */
> @@ -332,6 +333,7 @@ phys_addr_t memblock_mem_size(unsigned long limit_pfn);
>  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_mark_nomap(phys_addr_t limit);
>  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 ca09915..60930ac 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -814,6 +814,18 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
>  }
>  
>  /**
> + * memblock_clear_nomap - Clear flag MEMBLOCK_NOMAP for a specified region.
> + * @base: the base phys addr of the region
> + * @size: the size of the region
> + *
> + * Return 0 on success, -errno on failure.
> + */
> +int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size)
> +{
> +	return memblock_setclr_flag(base, size, 0, MEMBLOCK_NOMAP);
> +}
> +
> +/**
>   * __next_reserved_mem_region - next function for for_each_reserved_region()
>   * @idx: pointer to u64 loop variable
>   * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL
> @@ -1465,14 +1477,11 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)
>  	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
>  }
>  
> -void __init memblock_enforce_memory_limit(phys_addr_t limit)
> +static phys_addr_t __find_max_addr(phys_addr_t limit)
>  {
>  	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
>  	struct memblock_region *r;
>  
> -	if (!limit)
> -		return;
> -
>  	/* find out max address */
>  	for_each_memblock(memory, r) {
>  		if (limit <= r->size) {
> @@ -1482,6 +1491,18 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>  		limit -= r->size;
>  	}
>  
> +	return max_addr;
> +}
> +
> +void __init memblock_enforce_memory_limit(phys_addr_t limit)
> +{
> +	phys_addr_t max_addr;
> +
> +	if (!limit)
> +		return;
> +
> +	max_addr = __find_max_addr(limit);
> +
>  	/* truncate both memory and reserved regions */
>  	memblock_remove_range(&memblock.memory, max_addr,
>  			      (phys_addr_t)ULLONG_MAX);
> @@ -1489,6 +1510,17 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
>  			      (phys_addr_t)ULLONG_MAX);
>  }
>  
> +void __init memblock_mem_limit_mark_nomap(phys_addr_t limit)
> +{
> +	phys_addr_t max_addr;
> +
> +	if (!limit)
> +		return;
> +
> +	max_addr = __find_max_addr(limit);
> +	memblock_mark_nomap(max_addr, (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;
> @@ -1677,13 +1709,15 @@ static int memblock_debug_show(struct seq_file *m, void *private)
>  		reg = &type->regions[i];
>  		seq_printf(m, "%4d: ", i);
>  		if (sizeof(phys_addr_t) == 4)
> -			seq_printf(m, "0x%08lx..0x%08lx\n",
> +			seq_printf(m, "0x%08lx..0x%08lx  0x%08lx  0x%lx\n",
>  				   (unsigned long)reg->base,
> -				   (unsigned long)(reg->base + reg->size - 1));
> +				   (unsigned long)(reg->base + reg->size - 1),
> +				   (unsigned long)reg->size, reg->flags);
>  		else
> -			seq_printf(m, "0x%016llx..0x%016llx\n",
> +			seq_printf(m, "0x%016llx..0x%016llx  0x%016llx  0x%lx\n",
>  				   (unsigned long long)reg->base,
> -				   (unsigned long long)(reg->base + reg->size - 1));
> +				   (unsigned long long)(reg->base + reg->size - 1),
> +				   (unsigned long long)reg->size, reg->flags);
>  
>  	}
>  	return 0;
> -- 
> 1.8.3.1
> 

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

* Re: [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue
  2016-06-23 11:30 ` Dennis Chen
  (?)
@ 2016-06-23 15:26   ` kbuild test robot
  -1 siblings, 0 replies; 19+ messages in thread
From: kbuild test robot @ 2016-06-23 15:26 UTC (permalink / raw)
  Cc: kbuild-all, linux-arm-kernel, nd, Dennis Chen, Catalin Marinas,
	Steve Capper, Ard Biesheuvel, Will Deacon, Mark Rutland,
	Rafael J . Wysocki, Matt Fleming, linux-mm, linux-acpi,
	linux-efi

[-- Attachment #1: Type: text/plain, Size: 1188 bytes --]

Hi,

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on v4.7-rc4 next-20160623]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Dennis-Chen/mm-memblock-Add-some-new-functions-to-address-the-mem-limit-issue/20160623-193344
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux for-next/core
config: x86_64-randconfig-s0-06232144 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

>> WARNING: vmlinux.o(.text.unlikely+0x330c): Section mismatch in reference from the function __find_max_addr() to the variable .meminit.data:memblock
   The function __find_max_addr() references
   the variable __meminitdata memblock.
   This is often because __find_max_addr lacks a __meminitdata
   annotation or the annotation of memblock is wrong.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 21054 bytes --]

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

* Re: [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue
@ 2016-06-23 15:26   ` kbuild test robot
  0 siblings, 0 replies; 19+ messages in thread
From: kbuild test robot @ 2016-06-23 15:26 UTC (permalink / raw)
  To: Dennis Chen
  Cc: kbuild-all, linux-arm-kernel, nd, Catalin Marinas, Steve Capper,
	Ard Biesheuvel, Will Deacon, Mark Rutland, Rafael J . Wysocki,
	Matt Fleming, linux-mm, linux-acpi, linux-efi

[-- Attachment #1: Type: text/plain, Size: 1188 bytes --]

Hi,

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on v4.7-rc4 next-20160623]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Dennis-Chen/mm-memblock-Add-some-new-functions-to-address-the-mem-limit-issue/20160623-193344
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux for-next/core
config: x86_64-randconfig-s0-06232144 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

>> WARNING: vmlinux.o(.text.unlikely+0x330c): Section mismatch in reference from the function __find_max_addr() to the variable .meminit.data:memblock
   The function __find_max_addr() references
   the variable __meminitdata memblock.
   This is often because __find_max_addr lacks a __meminitdata
   annotation or the annotation of memblock is wrong.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 21054 bytes --]

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

* [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue
@ 2016-06-23 15:26   ` kbuild test robot
  0 siblings, 0 replies; 19+ messages in thread
From: kbuild test robot @ 2016-06-23 15:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

[auto build test WARNING on arm64/for-next/core]
[also build test WARNING on v4.7-rc4 next-20160623]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Dennis-Chen/mm-memblock-Add-some-new-functions-to-address-the-mem-limit-issue/20160623-193344
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux for-next/core
config: x86_64-randconfig-s0-06232144 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

>> WARNING: vmlinux.o(.text.unlikely+0x330c): Section mismatch in reference from the function __find_max_addr() to the variable .meminit.data:memblock
   The function __find_max_addr() references
   the variable __meminitdata memblock.
   This is often because __find_max_addr lacks a __meminitdata
   annotation or the annotation of memblock is wrong.

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/octet-stream
Size: 21054 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160623/f10dbdcd/attachment-0001.obj>

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

* Re: [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue
  2016-06-23 12:57     ` Mark Rutland
  (?)
@ 2016-06-24  2:28       ` Dennis Chen
  -1 siblings, 0 replies; 19+ messages in thread
From: Dennis Chen @ 2016-06-24  2:28 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	nd-5wv7dgnIgG8, Catalin Marinas, Steve Capper, Ard Biesheuvel,
	Will Deacon, Rafael J . Wysocki, Matt Fleming,
	linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	linux-efi-u79uwXL29TY76Z2rM5mHXA

On Thu, Jun 23, 2016 at 01:57:48PM +0100, Mark Rutland wrote:
> On Thu, Jun 23, 2016 at 07:30:14PM +0800, Dennis Chen wrote:
> > Two major changes in this patch:
> > [1] Add memblock_mem_limit_mark_nomap(phys_addr_t limit) function to
> > mark memblock regions above the @limit as NOMAP region, which will
> > be used to address the observed 'mem=x' kernel parameter issue.
> > 
> > [2] Add 'size' and 'flag' debug output in the memblock debugfs.
> > The '/sys/kernel/debug/memblock/memory' output looks like before:
> >    0: 0x0000008000000000..0x0000008001e7ffff
> >    1: 0x0000008001e80000..0x00000083ff184fff
> >    2: 0x00000083ff185000..0x00000083ff1c2fff
> >    3: 0x00000083ff1c3000..0x00000083ff222fff
> >    4: 0x00000083ff223000..0x00000083ffe42fff
> >    5: 0x00000083ffe43000..0x00000083ffffffff
> > 
> > With this patch applied:
> >    0: 0x0000008000000000..0x0000008001e7ffff  0x0000000001e80000  0x4
> >    1: 0x0000008001e80000..0x00000083ff184fff  0x00000003fd305000  0x0
> >    2: 0x00000083ff185000..0x00000083ff1c2fff  0x000000000003e000  0x4
> >    3: 0x00000083ff1c3000..0x00000083ff222fff  0x0000000000060000  0x0
> >    4: 0x00000083ff223000..0x00000083ffe42fff  0x0000000000c20000  0x4
> >    5: 0x00000083ffe43000..0x00000083ffffffff  0x00000000001bd000  0x0
> 
> Please explain in the commit message what the problem being solved is,
> and how this solves it. e.g.
> 
> In some cases, memblock is queried to determine whether a physical
> address corresponds to memory present in a system even if unused by the
> OS for the linear mapping, highmem, etc. For example, the ACPI core
> needs this information to determine which attributes to use when mapping
> ACPI regions. Use of incorrect memory types can result in faults, data
> corruption, or other issues.
> 
> Removing memory with memblock_enforce_memory_limit throws away this
> information, and so a kernel booted with mem= may suffer from the issues
> described above. To avoid this, we can mark regions as nomap rather than
> removing them, which preserves the information we need while preventing
> other use of the regions.
> 
> This patch adds new insfrastructure to mark all memblock regions in an
> address range as nomap, to cater for this. Similarly we add
> infrastructure to clear the flag for an address range, which makes
> handling some overlap cases simpler.
> 
> Other than that, the patch itself looks fine to me.
>
The above commit message is very clear to describe why we need to add
those new infrastructures in this patch. Thanks Mark, you're saving 
my time :) I will apply it in the next version.

Thanks,
Dennis
> 
> Thanks,
> Mark.
> 
> > Signed-off-by: Dennis Chen <dennis.chen-5wv7dgnIgG8@public.gmane.org>
> > Cc: Catalin Marinas <catalin.marinas-5wv7dgnIgG8@public.gmane.org>
> > Cc: Steve Capper <steve.capper-5wv7dgnIgG8@public.gmane.org>
> > Cc: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> > Cc: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
> > Cc: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
> > Cc: Rafael J. Wysocki <rafael.j.wysocki-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> > Cc: Matt Fleming <matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org>
> > Cc: linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org
> > Cc: linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > ---
> >  include/linux/memblock.h |  2 ++
> >  mm/memblock.c            | 50 ++++++++++++++++++++++++++++++++++++++++--------
> >  2 files changed, 44 insertions(+), 8 deletions(-)
> > 
> > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > index 6c14b61..5e069c8 100644
> > --- a/include/linux/memblock.h
> > +++ b/include/linux/memblock.h
> > @@ -92,6 +92,7 @@ int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
> >  int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
> >  int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
> >  int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
> > +int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
> >  ulong choose_memblock_flags(void);
> >  
> >  /* Low level functions */
> > @@ -332,6 +333,7 @@ phys_addr_t memblock_mem_size(unsigned long limit_pfn);
> >  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_mark_nomap(phys_addr_t limit);
> >  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 ca09915..60930ac 100644
> > --- a/mm/memblock.c
> > +++ b/mm/memblock.c
> > @@ -814,6 +814,18 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
> >  }
> >  
> >  /**
> > + * memblock_clear_nomap - Clear flag MEMBLOCK_NOMAP for a specified region.
> > + * @base: the base phys addr of the region
> > + * @size: the size of the region
> > + *
> > + * Return 0 on success, -errno on failure.
> > + */
> > +int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size)
> > +{
> > +	return memblock_setclr_flag(base, size, 0, MEMBLOCK_NOMAP);
> > +}
> > +
> > +/**
> >   * __next_reserved_mem_region - next function for for_each_reserved_region()
> >   * @idx: pointer to u64 loop variable
> >   * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL
> > @@ -1465,14 +1477,11 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)
> >  	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
> >  }
> >  
> > -void __init memblock_enforce_memory_limit(phys_addr_t limit)
> > +static phys_addr_t __find_max_addr(phys_addr_t limit)
> >  {
> >  	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
> >  	struct memblock_region *r;
> >  
> > -	if (!limit)
> > -		return;
> > -
> >  	/* find out max address */
> >  	for_each_memblock(memory, r) {
> >  		if (limit <= r->size) {
> > @@ -1482,6 +1491,18 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >  		limit -= r->size;
> >  	}
> >  
> > +	return max_addr;
> > +}
> > +
> > +void __init memblock_enforce_memory_limit(phys_addr_t limit)
> > +{
> > +	phys_addr_t max_addr;
> > +
> > +	if (!limit)
> > +		return;
> > +
> > +	max_addr = __find_max_addr(limit);
> > +
> >  	/* truncate both memory and reserved regions */
> >  	memblock_remove_range(&memblock.memory, max_addr,
> >  			      (phys_addr_t)ULLONG_MAX);
> > @@ -1489,6 +1510,17 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >  			      (phys_addr_t)ULLONG_MAX);
> >  }
> >  
> > +void __init memblock_mem_limit_mark_nomap(phys_addr_t limit)
> > +{
> > +	phys_addr_t max_addr;
> > +
> > +	if (!limit)
> > +		return;
> > +
> > +	max_addr = __find_max_addr(limit);
> > +	memblock_mark_nomap(max_addr, (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;
> > @@ -1677,13 +1709,15 @@ static int memblock_debug_show(struct seq_file *m, void *private)
> >  		reg = &type->regions[i];
> >  		seq_printf(m, "%4d: ", i);
> >  		if (sizeof(phys_addr_t) == 4)
> > -			seq_printf(m, "0x%08lx..0x%08lx\n",
> > +			seq_printf(m, "0x%08lx..0x%08lx  0x%08lx  0x%lx\n",
> >  				   (unsigned long)reg->base,
> > -				   (unsigned long)(reg->base + reg->size - 1));
> > +				   (unsigned long)(reg->base + reg->size - 1),
> > +				   (unsigned long)reg->size, reg->flags);
> >  		else
> > -			seq_printf(m, "0x%016llx..0x%016llx\n",
> > +			seq_printf(m, "0x%016llx..0x%016llx  0x%016llx  0x%lx\n",
> >  				   (unsigned long long)reg->base,
> > -				   (unsigned long long)(reg->base + reg->size - 1));
> > +				   (unsigned long long)(reg->base + reg->size - 1),
> > +				   (unsigned long long)reg->size, reg->flags);
> >  
> >  	}
> >  	return 0;
> > -- 
> > 1.8.3.1
> > 
> 

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

* Re: [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue
@ 2016-06-24  2:28       ` Dennis Chen
  0 siblings, 0 replies; 19+ messages in thread
From: Dennis Chen @ 2016-06-24  2:28 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, Catalin Marinas, Steve Capper, Ard Biesheuvel,
	Will Deacon, Rafael J . Wysocki, Matt Fleming, linux-mm,
	linux-acpi, linux-efi

On Thu, Jun 23, 2016 at 01:57:48PM +0100, Mark Rutland wrote:
> On Thu, Jun 23, 2016 at 07:30:14PM +0800, Dennis Chen wrote:
> > Two major changes in this patch:
> > [1] Add memblock_mem_limit_mark_nomap(phys_addr_t limit) function to
> > mark memblock regions above the @limit as NOMAP region, which will
> > be used to address the observed 'mem=x' kernel parameter issue.
> > 
> > [2] Add 'size' and 'flag' debug output in the memblock debugfs.
> > The '/sys/kernel/debug/memblock/memory' output looks like before:
> >    0: 0x0000008000000000..0x0000008001e7ffff
> >    1: 0x0000008001e80000..0x00000083ff184fff
> >    2: 0x00000083ff185000..0x00000083ff1c2fff
> >    3: 0x00000083ff1c3000..0x00000083ff222fff
> >    4: 0x00000083ff223000..0x00000083ffe42fff
> >    5: 0x00000083ffe43000..0x00000083ffffffff
> > 
> > With this patch applied:
> >    0: 0x0000008000000000..0x0000008001e7ffff  0x0000000001e80000  0x4
> >    1: 0x0000008001e80000..0x00000083ff184fff  0x00000003fd305000  0x0
> >    2: 0x00000083ff185000..0x00000083ff1c2fff  0x000000000003e000  0x4
> >    3: 0x00000083ff1c3000..0x00000083ff222fff  0x0000000000060000  0x0
> >    4: 0x00000083ff223000..0x00000083ffe42fff  0x0000000000c20000  0x4
> >    5: 0x00000083ffe43000..0x00000083ffffffff  0x00000000001bd000  0x0
> 
> Please explain in the commit message what the problem being solved is,
> and how this solves it. e.g.
> 
> In some cases, memblock is queried to determine whether a physical
> address corresponds to memory present in a system even if unused by the
> OS for the linear mapping, highmem, etc. For example, the ACPI core
> needs this information to determine which attributes to use when mapping
> ACPI regions. Use of incorrect memory types can result in faults, data
> corruption, or other issues.
> 
> Removing memory with memblock_enforce_memory_limit throws away this
> information, and so a kernel booted with mem= may suffer from the issues
> described above. To avoid this, we can mark regions as nomap rather than
> removing them, which preserves the information we need while preventing
> other use of the regions.
> 
> This patch adds new insfrastructure to mark all memblock regions in an
> address range as nomap, to cater for this. Similarly we add
> infrastructure to clear the flag for an address range, which makes
> handling some overlap cases simpler.
> 
> Other than that, the patch itself looks fine to me.
>
The above commit message is very clear to describe why we need to add
those new infrastructures in this patch. Thanks Mark, you're saving 
my time :) I will apply it in the next version.

Thanks,
Dennis
> 
> Thanks,
> Mark.
> 
> > Signed-off-by: Dennis Chen <dennis.chen@arm.com>
> > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > Cc: Steve Capper <steve.capper@arm.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Will Deacon <will.deacon@arm.com>
> > Cc: Mark Rutland <mark.rutland@arm.com>
> > Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > Cc: Matt Fleming <matt@codeblueprint.co.uk>
> > Cc: linux-mm@kvack.org
> > Cc: linux-acpi@vger.kernel.org
> > Cc: linux-efi@vger.kernel.org
> > ---
> >  include/linux/memblock.h |  2 ++
> >  mm/memblock.c            | 50 ++++++++++++++++++++++++++++++++++++++++--------
> >  2 files changed, 44 insertions(+), 8 deletions(-)
> > 
> > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > index 6c14b61..5e069c8 100644
> > --- a/include/linux/memblock.h
> > +++ b/include/linux/memblock.h
> > @@ -92,6 +92,7 @@ int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
> >  int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
> >  int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
> >  int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
> > +int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
> >  ulong choose_memblock_flags(void);
> >  
> >  /* Low level functions */
> > @@ -332,6 +333,7 @@ phys_addr_t memblock_mem_size(unsigned long limit_pfn);
> >  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_mark_nomap(phys_addr_t limit);
> >  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 ca09915..60930ac 100644
> > --- a/mm/memblock.c
> > +++ b/mm/memblock.c
> > @@ -814,6 +814,18 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
> >  }
> >  
> >  /**
> > + * memblock_clear_nomap - Clear flag MEMBLOCK_NOMAP for a specified region.
> > + * @base: the base phys addr of the region
> > + * @size: the size of the region
> > + *
> > + * Return 0 on success, -errno on failure.
> > + */
> > +int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size)
> > +{
> > +	return memblock_setclr_flag(base, size, 0, MEMBLOCK_NOMAP);
> > +}
> > +
> > +/**
> >   * __next_reserved_mem_region - next function for for_each_reserved_region()
> >   * @idx: pointer to u64 loop variable
> >   * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL
> > @@ -1465,14 +1477,11 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)
> >  	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
> >  }
> >  
> > -void __init memblock_enforce_memory_limit(phys_addr_t limit)
> > +static phys_addr_t __find_max_addr(phys_addr_t limit)
> >  {
> >  	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
> >  	struct memblock_region *r;
> >  
> > -	if (!limit)
> > -		return;
> > -
> >  	/* find out max address */
> >  	for_each_memblock(memory, r) {
> >  		if (limit <= r->size) {
> > @@ -1482,6 +1491,18 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >  		limit -= r->size;
> >  	}
> >  
> > +	return max_addr;
> > +}
> > +
> > +void __init memblock_enforce_memory_limit(phys_addr_t limit)
> > +{
> > +	phys_addr_t max_addr;
> > +
> > +	if (!limit)
> > +		return;
> > +
> > +	max_addr = __find_max_addr(limit);
> > +
> >  	/* truncate both memory and reserved regions */
> >  	memblock_remove_range(&memblock.memory, max_addr,
> >  			      (phys_addr_t)ULLONG_MAX);
> > @@ -1489,6 +1510,17 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >  			      (phys_addr_t)ULLONG_MAX);
> >  }
> >  
> > +void __init memblock_mem_limit_mark_nomap(phys_addr_t limit)
> > +{
> > +	phys_addr_t max_addr;
> > +
> > +	if (!limit)
> > +		return;
> > +
> > +	max_addr = __find_max_addr(limit);
> > +	memblock_mark_nomap(max_addr, (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;
> > @@ -1677,13 +1709,15 @@ static int memblock_debug_show(struct seq_file *m, void *private)
> >  		reg = &type->regions[i];
> >  		seq_printf(m, "%4d: ", i);
> >  		if (sizeof(phys_addr_t) == 4)
> > -			seq_printf(m, "0x%08lx..0x%08lx\n",
> > +			seq_printf(m, "0x%08lx..0x%08lx  0x%08lx  0x%lx\n",
> >  				   (unsigned long)reg->base,
> > -				   (unsigned long)(reg->base + reg->size - 1));
> > +				   (unsigned long)(reg->base + reg->size - 1),
> > +				   (unsigned long)reg->size, reg->flags);
> >  		else
> > -			seq_printf(m, "0x%016llx..0x%016llx\n",
> > +			seq_printf(m, "0x%016llx..0x%016llx  0x%016llx  0x%lx\n",
> >  				   (unsigned long long)reg->base,
> > -				   (unsigned long long)(reg->base + reg->size - 1));
> > +				   (unsigned long long)(reg->base + reg->size - 1),
> > +				   (unsigned long long)reg->size, reg->flags);
> >  
> >  	}
> >  	return 0;
> > -- 
> > 1.8.3.1
> > 
> 

--
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] 19+ messages in thread

* [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue
@ 2016-06-24  2:28       ` Dennis Chen
  0 siblings, 0 replies; 19+ messages in thread
From: Dennis Chen @ 2016-06-24  2:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 23, 2016 at 01:57:48PM +0100, Mark Rutland wrote:
> On Thu, Jun 23, 2016 at 07:30:14PM +0800, Dennis Chen wrote:
> > Two major changes in this patch:
> > [1] Add memblock_mem_limit_mark_nomap(phys_addr_t limit) function to
> > mark memblock regions above the @limit as NOMAP region, which will
> > be used to address the observed 'mem=x' kernel parameter issue.
> > 
> > [2] Add 'size' and 'flag' debug output in the memblock debugfs.
> > The '/sys/kernel/debug/memblock/memory' output looks like before:
> >    0: 0x0000008000000000..0x0000008001e7ffff
> >    1: 0x0000008001e80000..0x00000083ff184fff
> >    2: 0x00000083ff185000..0x00000083ff1c2fff
> >    3: 0x00000083ff1c3000..0x00000083ff222fff
> >    4: 0x00000083ff223000..0x00000083ffe42fff
> >    5: 0x00000083ffe43000..0x00000083ffffffff
> > 
> > With this patch applied:
> >    0: 0x0000008000000000..0x0000008001e7ffff  0x0000000001e80000  0x4
> >    1: 0x0000008001e80000..0x00000083ff184fff  0x00000003fd305000  0x0
> >    2: 0x00000083ff185000..0x00000083ff1c2fff  0x000000000003e000  0x4
> >    3: 0x00000083ff1c3000..0x00000083ff222fff  0x0000000000060000  0x0
> >    4: 0x00000083ff223000..0x00000083ffe42fff  0x0000000000c20000  0x4
> >    5: 0x00000083ffe43000..0x00000083ffffffff  0x00000000001bd000  0x0
> 
> Please explain in the commit message what the problem being solved is,
> and how this solves it. e.g.
> 
> In some cases, memblock is queried to determine whether a physical
> address corresponds to memory present in a system even if unused by the
> OS for the linear mapping, highmem, etc. For example, the ACPI core
> needs this information to determine which attributes to use when mapping
> ACPI regions. Use of incorrect memory types can result in faults, data
> corruption, or other issues.
> 
> Removing memory with memblock_enforce_memory_limit throws away this
> information, and so a kernel booted with mem= may suffer from the issues
> described above. To avoid this, we can mark regions as nomap rather than
> removing them, which preserves the information we need while preventing
> other use of the regions.
> 
> This patch adds new insfrastructure to mark all memblock regions in an
> address range as nomap, to cater for this. Similarly we add
> infrastructure to clear the flag for an address range, which makes
> handling some overlap cases simpler.
> 
> Other than that, the patch itself looks fine to me.
>
The above commit message is very clear to describe why we need to add
those new infrastructures in this patch. Thanks Mark, you're saving 
my time :) I will apply it in the next version.

Thanks,
Dennis
> 
> Thanks,
> Mark.
> 
> > Signed-off-by: Dennis Chen <dennis.chen@arm.com>
> > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > Cc: Steve Capper <steve.capper@arm.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Will Deacon <will.deacon@arm.com>
> > Cc: Mark Rutland <mark.rutland@arm.com>
> > Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > Cc: Matt Fleming <matt@codeblueprint.co.uk>
> > Cc: linux-mm at kvack.org
> > Cc: linux-acpi at vger.kernel.org
> > Cc: linux-efi at vger.kernel.org
> > ---
> >  include/linux/memblock.h |  2 ++
> >  mm/memblock.c            | 50 ++++++++++++++++++++++++++++++++++++++++--------
> >  2 files changed, 44 insertions(+), 8 deletions(-)
> > 
> > diff --git a/include/linux/memblock.h b/include/linux/memblock.h
> > index 6c14b61..5e069c8 100644
> > --- a/include/linux/memblock.h
> > +++ b/include/linux/memblock.h
> > @@ -92,6 +92,7 @@ int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
> >  int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
> >  int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
> >  int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
> > +int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
> >  ulong choose_memblock_flags(void);
> >  
> >  /* Low level functions */
> > @@ -332,6 +333,7 @@ phys_addr_t memblock_mem_size(unsigned long limit_pfn);
> >  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_mark_nomap(phys_addr_t limit);
> >  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 ca09915..60930ac 100644
> > --- a/mm/memblock.c
> > +++ b/mm/memblock.c
> > @@ -814,6 +814,18 @@ int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
> >  }
> >  
> >  /**
> > + * memblock_clear_nomap - Clear flag MEMBLOCK_NOMAP for a specified region.
> > + * @base: the base phys addr of the region
> > + * @size: the size of the region
> > + *
> > + * Return 0 on success, -errno on failure.
> > + */
> > +int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size)
> > +{
> > +	return memblock_setclr_flag(base, size, 0, MEMBLOCK_NOMAP);
> > +}
> > +
> > +/**
> >   * __next_reserved_mem_region - next function for for_each_reserved_region()
> >   * @idx: pointer to u64 loop variable
> >   * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL
> > @@ -1465,14 +1477,11 @@ phys_addr_t __init_memblock memblock_end_of_DRAM(void)
> >  	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
> >  }
> >  
> > -void __init memblock_enforce_memory_limit(phys_addr_t limit)
> > +static phys_addr_t __find_max_addr(phys_addr_t limit)
> >  {
> >  	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
> >  	struct memblock_region *r;
> >  
> > -	if (!limit)
> > -		return;
> > -
> >  	/* find out max address */
> >  	for_each_memblock(memory, r) {
> >  		if (limit <= r->size) {
> > @@ -1482,6 +1491,18 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >  		limit -= r->size;
> >  	}
> >  
> > +	return max_addr;
> > +}
> > +
> > +void __init memblock_enforce_memory_limit(phys_addr_t limit)
> > +{
> > +	phys_addr_t max_addr;
> > +
> > +	if (!limit)
> > +		return;
> > +
> > +	max_addr = __find_max_addr(limit);
> > +
> >  	/* truncate both memory and reserved regions */
> >  	memblock_remove_range(&memblock.memory, max_addr,
> >  			      (phys_addr_t)ULLONG_MAX);
> > @@ -1489,6 +1510,17 @@ void __init memblock_enforce_memory_limit(phys_addr_t limit)
> >  			      (phys_addr_t)ULLONG_MAX);
> >  }
> >  
> > +void __init memblock_mem_limit_mark_nomap(phys_addr_t limit)
> > +{
> > +	phys_addr_t max_addr;
> > +
> > +	if (!limit)
> > +		return;
> > +
> > +	max_addr = __find_max_addr(limit);
> > +	memblock_mark_nomap(max_addr, (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;
> > @@ -1677,13 +1709,15 @@ static int memblock_debug_show(struct seq_file *m, void *private)
> >  		reg = &type->regions[i];
> >  		seq_printf(m, "%4d: ", i);
> >  		if (sizeof(phys_addr_t) == 4)
> > -			seq_printf(m, "0x%08lx..0x%08lx\n",
> > +			seq_printf(m, "0x%08lx..0x%08lx  0x%08lx  0x%lx\n",
> >  				   (unsigned long)reg->base,
> > -				   (unsigned long)(reg->base + reg->size - 1));
> > +				   (unsigned long)(reg->base + reg->size - 1),
> > +				   (unsigned long)reg->size, reg->flags);
> >  		else
> > -			seq_printf(m, "0x%016llx..0x%016llx\n",
> > +			seq_printf(m, "0x%016llx..0x%016llx  0x%016llx  0x%lx\n",
> >  				   (unsigned long long)reg->base,
> > -				   (unsigned long long)(reg->base + reg->size - 1));
> > +				   (unsigned long long)(reg->base + reg->size - 1),
> > +				   (unsigned long long)reg->size, reg->flags);
> >  
> >  	}
> >  	return 0;
> > -- 
> > 1.8.3.1
> > 
> 

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

* Re: [PATCH 2/2] arm64:acpi Fix the acpi alignment exeception when 'mem=' specified
  2016-06-23 12:42       ` Mark Rutland
  (?)
@ 2016-06-24  2:31         ` Dennis Chen
  -1 siblings, 0 replies; 19+ messages in thread
From: Dennis Chen @ 2016-06-24  2:31 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, nd, Catalin Marinas, Steve Capper,
	Ard Biesheuvel, Will Deacon, Rafael J . Wysocki, Matt Fleming,
	linux-mm, linux-acpi, linux-efi

On Thu, Jun 23, 2016 at 01:42:30PM +0100, Mark Rutland wrote:
> On Thu, Jun 23, 2016 at 07:30:15PM +0800, Dennis Chen wrote:
> > This is a rework patch based on [1]. According to the proposal from
> > Mark Rutland, when applying the system memory limit through 'mem=x'
> > kernel command line, don't remove the rest memory regions above the
> > limit from the memblock, instead marking them as MEMBLOCK_NOMAP region,
> > which will preserve the ability to identify regions as normal memory
> > while not using them for allocation and the linear map.
> > 
> > Without this patch, the ACPI core will map those acpi data regions(if
> > they are above the limit) as device type memory, which will result in
> > the alignment exception when ACPI core parses the AML data stream 
> > since the parsing will produce some non-alignment accesses.
> >
> > [1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438443.html
> 
> Please rewrite the message to be standalone (i.e. so peopel can read
> this without having to folow the link).
> 
> Explain why using mem= makes ACPI think regions should be mapped as
> Device memory, the problems this causes for ACPICA, then cover why we
> want to nomap the region.
> 
> > Signed-off-by: Dennis Chen <dennis.chen@arm.com>
> > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > Cc: Steve Capper <steve.capper@arm.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Will Deacon <will.deacon@arm.com>
> > Cc: Mark Rutland <mark.rutland@arm.com>
> > Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > Cc: Matt Fleming <matt@codeblueprint.co.uk>
> > Cc: linux-mm@kvack.org
> > Cc: linux-acpi@vger.kernel.org
> > Cc: linux-efi@vger.kernel.org
> > ---
> >  arch/arm64/mm/init.c | 10 ++++++----
> >  1 file changed, 6 insertions(+), 4 deletions(-)
> > 
> > diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> > index d45f862..e509e24 100644
> > --- a/arch/arm64/mm/init.c
> > +++ b/arch/arm64/mm/init.c
> > @@ -222,12 +222,14 @@ void __init arm64_memblock_init(void)
> >  
> >  	/*
> >  	 * Apply the memory limit if it was set. Since the kernel may be loaded
> > -	 * high up in memory, add back the kernel region that must be accessible
> > -	 * via the linear mapping.
> > +	 * in the memory regions above the limit, so we need to clear the
> > +	 * MEMBLOCK_NOMAP flag of this region to make it can be accessible via
> > +	 * the linear mapping.
> >  	 */
> >  	if (memory_limit != (phys_addr_t)ULLONG_MAX) {
> > -		memblock_enforce_memory_limit(memory_limit);
> > -		memblock_add(__pa(_text), (u64)(_end - _text));
> > +		memblock_mem_limit_mark_nomap(memory_limit);
> > +		if (!memblock_is_map_memory(__pa(_text)))
> > +			memblock_clear_nomap(__pa(_text), (u64)(_end - _text));
> 
> I think that the memblock_is_map_memory() check should go. Just because
> a page of the kernel image is mapped doesn't mean that the rest is. That
> will make this a 1-1 change.
>
Good catch! Will be applied, thanks!
> 
> Other than that, this looks right to me.
> 
> Thanks,
> Mark.
> 
> >  	}
> >  
> >  	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
> > -- 
> > 1.8.3.1
> > 
> 

--
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] 19+ messages in thread

* Re: [PATCH 2/2] arm64:acpi Fix the acpi alignment exeception when 'mem=' specified
@ 2016-06-24  2:31         ` Dennis Chen
  0 siblings, 0 replies; 19+ messages in thread
From: Dennis Chen @ 2016-06-24  2:31 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, Catalin Marinas, Steve Capper, Ard Biesheuvel,
	Will Deacon, Rafael J . Wysocki, Matt Fleming, linux-mm,
	linux-acpi, linux-efi

On Thu, Jun 23, 2016 at 01:42:30PM +0100, Mark Rutland wrote:
> On Thu, Jun 23, 2016 at 07:30:15PM +0800, Dennis Chen wrote:
> > This is a rework patch based on [1]. According to the proposal from
> > Mark Rutland, when applying the system memory limit through 'mem=x'
> > kernel command line, don't remove the rest memory regions above the
> > limit from the memblock, instead marking them as MEMBLOCK_NOMAP region,
> > which will preserve the ability to identify regions as normal memory
> > while not using them for allocation and the linear map.
> > 
> > Without this patch, the ACPI core will map those acpi data regions(if
> > they are above the limit) as device type memory, which will result in
> > the alignment exception when ACPI core parses the AML data stream 
> > since the parsing will produce some non-alignment accesses.
> >
> > [1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438443.html
> 
> Please rewrite the message to be standalone (i.e. so peopel can read
> this without having to folow the link).
> 
> Explain why using mem= makes ACPI think regions should be mapped as
> Device memory, the problems this causes for ACPICA, then cover why we
> want to nomap the region.
> 
> > Signed-off-by: Dennis Chen <dennis.chen@arm.com>
> > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > Cc: Steve Capper <steve.capper@arm.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Will Deacon <will.deacon@arm.com>
> > Cc: Mark Rutland <mark.rutland@arm.com>
> > Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > Cc: Matt Fleming <matt@codeblueprint.co.uk>
> > Cc: linux-mm@kvack.org
> > Cc: linux-acpi@vger.kernel.org
> > Cc: linux-efi@vger.kernel.org
> > ---
> >  arch/arm64/mm/init.c | 10 ++++++----
> >  1 file changed, 6 insertions(+), 4 deletions(-)
> > 
> > diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> > index d45f862..e509e24 100644
> > --- a/arch/arm64/mm/init.c
> > +++ b/arch/arm64/mm/init.c
> > @@ -222,12 +222,14 @@ void __init arm64_memblock_init(void)
> >  
> >  	/*
> >  	 * Apply the memory limit if it was set. Since the kernel may be loaded
> > -	 * high up in memory, add back the kernel region that must be accessible
> > -	 * via the linear mapping.
> > +	 * in the memory regions above the limit, so we need to clear the
> > +	 * MEMBLOCK_NOMAP flag of this region to make it can be accessible via
> > +	 * the linear mapping.
> >  	 */
> >  	if (memory_limit != (phys_addr_t)ULLONG_MAX) {
> > -		memblock_enforce_memory_limit(memory_limit);
> > -		memblock_add(__pa(_text), (u64)(_end - _text));
> > +		memblock_mem_limit_mark_nomap(memory_limit);
> > +		if (!memblock_is_map_memory(__pa(_text)))
> > +			memblock_clear_nomap(__pa(_text), (u64)(_end - _text));
> 
> I think that the memblock_is_map_memory() check should go. Just because
> a page of the kernel image is mapped doesn't mean that the rest is. That
> will make this a 1-1 change.
>
Good catch! Will be applied, thanks!
> 
> Other than that, this looks right to me.
> 
> Thanks,
> Mark.
> 
> >  	}
> >  
> >  	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
> > -- 
> > 1.8.3.1
> > 
> 

--
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] 19+ messages in thread

* [PATCH 2/2] arm64:acpi Fix the acpi alignment exeception when 'mem=' specified
@ 2016-06-24  2:31         ` Dennis Chen
  0 siblings, 0 replies; 19+ messages in thread
From: Dennis Chen @ 2016-06-24  2:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jun 23, 2016 at 01:42:30PM +0100, Mark Rutland wrote:
> On Thu, Jun 23, 2016 at 07:30:15PM +0800, Dennis Chen wrote:
> > This is a rework patch based on [1]. According to the proposal from
> > Mark Rutland, when applying the system memory limit through 'mem=x'
> > kernel command line, don't remove the rest memory regions above the
> > limit from the memblock, instead marking them as MEMBLOCK_NOMAP region,
> > which will preserve the ability to identify regions as normal memory
> > while not using them for allocation and the linear map.
> > 
> > Without this patch, the ACPI core will map those acpi data regions(if
> > they are above the limit) as device type memory, which will result in
> > the alignment exception when ACPI core parses the AML data stream 
> > since the parsing will produce some non-alignment accesses.
> >
> > [1]:http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438443.html
> 
> Please rewrite the message to be standalone (i.e. so peopel can read
> this without having to folow the link).
> 
> Explain why using mem= makes ACPI think regions should be mapped as
> Device memory, the problems this causes for ACPICA, then cover why we
> want to nomap the region.
> 
> > Signed-off-by: Dennis Chen <dennis.chen@arm.com>
> > Cc: Catalin Marinas <catalin.marinas@arm.com>
> > Cc: Steve Capper <steve.capper@arm.com>
> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> > Cc: Will Deacon <will.deacon@arm.com>
> > Cc: Mark Rutland <mark.rutland@arm.com>
> > Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > Cc: Matt Fleming <matt@codeblueprint.co.uk>
> > Cc: linux-mm at kvack.org
> > Cc: linux-acpi at vger.kernel.org
> > Cc: linux-efi at vger.kernel.org
> > ---
> >  arch/arm64/mm/init.c | 10 ++++++----
> >  1 file changed, 6 insertions(+), 4 deletions(-)
> > 
> > diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> > index d45f862..e509e24 100644
> > --- a/arch/arm64/mm/init.c
> > +++ b/arch/arm64/mm/init.c
> > @@ -222,12 +222,14 @@ void __init arm64_memblock_init(void)
> >  
> >  	/*
> >  	 * Apply the memory limit if it was set. Since the kernel may be loaded
> > -	 * high up in memory, add back the kernel region that must be accessible
> > -	 * via the linear mapping.
> > +	 * in the memory regions above the limit, so we need to clear the
> > +	 * MEMBLOCK_NOMAP flag of this region to make it can be accessible via
> > +	 * the linear mapping.
> >  	 */
> >  	if (memory_limit != (phys_addr_t)ULLONG_MAX) {
> > -		memblock_enforce_memory_limit(memory_limit);
> > -		memblock_add(__pa(_text), (u64)(_end - _text));
> > +		memblock_mem_limit_mark_nomap(memory_limit);
> > +		if (!memblock_is_map_memory(__pa(_text)))
> > +			memblock_clear_nomap(__pa(_text), (u64)(_end - _text));
> 
> I think that the memblock_is_map_memory() check should go. Just because
> a page of the kernel image is mapped doesn't mean that the rest is. That
> will make this a 1-1 change.
>
Good catch! Will be applied, thanks!
> 
> Other than that, this looks right to me.
> 
> Thanks,
> Mark.
> 
> >  	}
> >  
> >  	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && initrd_start) {
> > -- 
> > 1.8.3.1
> > 
> 

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

end of thread, other threads:[~2016-06-24  2:32 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-23 11:30 [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue Dennis Chen
2016-06-23 11:30 ` Dennis Chen
2016-06-23 11:30 ` [PATCH 2/2] arm64:acpi Fix the acpi alignment exeception when 'mem=' specified Dennis Chen
2016-06-23 11:30   ` Dennis Chen
     [not found]   ` <1466681415-8058-2-git-send-email-dennis.chen-5wv7dgnIgG8@public.gmane.org>
2016-06-23 12:42     ` Mark Rutland
2016-06-23 12:42       ` Mark Rutland
2016-06-23 12:42       ` Mark Rutland
2016-06-24  2:31       ` Dennis Chen
2016-06-24  2:31         ` Dennis Chen
2016-06-24  2:31         ` Dennis Chen
     [not found] ` <1466681415-8058-1-git-send-email-dennis.chen-5wv7dgnIgG8@public.gmane.org>
2016-06-23 12:57   ` [PATCH 1/2] mm: memblock Add some new functions to address the mem limit issue Mark Rutland
2016-06-23 12:57     ` Mark Rutland
2016-06-23 12:57     ` Mark Rutland
2016-06-24  2:28     ` Dennis Chen
2016-06-24  2:28       ` Dennis Chen
2016-06-24  2:28       ` Dennis Chen
2016-06-23 15:26 ` kbuild test robot
2016-06-23 15:26   ` kbuild test robot
2016-06-23 15:26   ` kbuild test robot

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.