diff mbox series

[v2,1/2] x86: respect memory size limiting via mem= parameter

Message ID 20190130082233.23840-2-jgross@suse.com (mailing list archive)
State New, archived
Headers show
Series x86: respect memory size limits | expand

Commit Message

Jürgen Groß Jan. 30, 2019, 8:22 a.m. UTC
When limiting memory size via kernel parameter "mem=" this should be
respected even in case of memory made accessible via a PCI card.

Today this kind of memory won't be made usable in initial memory
setup as the memory won't be visible in E820 map, but it might be
added when adding PCI devices due to corresponding ACPI table entries.

Not respecting "mem=" can be corrected by adding a global max_mem_size
variable set by parse_memopt() which will result in rejecting adding
memory areas resulting in a memory size above the allowed limit.

Signed-off-by: Juergen Gross <jgross@suse.com>
---
 arch/x86/kernel/e820.c         | 5 +++++
 include/linux/memory_hotplug.h | 2 ++
 mm/memory_hotplug.c            | 6 ++++++
 3 files changed, 13 insertions(+)

Comments

Ingo Molnar Feb. 11, 2019, 12:06 p.m. UTC | #1
* Juergen Gross <jgross@suse.com> wrote:

> When limiting memory size via kernel parameter "mem=" this should be
> respected even in case of memory made accessible via a PCI card.
> 
> Today this kind of memory won't be made usable in initial memory
> setup as the memory won't be visible in E820 map, but it might be
> added when adding PCI devices due to corresponding ACPI table entries.
> 
> Not respecting "mem=" can be corrected by adding a global max_mem_size
> variable set by parse_memopt() which will result in rejecting adding
> memory areas resulting in a memory size above the allowed limit.

So historically 'mem=xxxM' was a way to quickly limit RAM.

If PCI devices had physical mmio memory areas above this range, we'd 
still expect them to work - the option was really only meant to limit 
RAM.

So I'm wondering what the new logic is here - why should an iomem 
resource from a PCI device be ignored? It's a completely separate area 
that might or might not be enumerated in the e820 table - the only 
requirement we have here I think is that it not overlap RAM areas or each 
other (obviously).

So if I understood this new restriction you want mem= to imply, devices 
would start failing to initialize on bare metal when mem= is used?

Thanks,

	Ingo
Jürgen Groß Feb. 11, 2019, 12:14 p.m. UTC | #2
On 11/02/2019 13:06, Ingo Molnar wrote:
> 
> * Juergen Gross <jgross@suse.com> wrote:
> 
>> When limiting memory size via kernel parameter "mem=" this should be
>> respected even in case of memory made accessible via a PCI card.
>>
>> Today this kind of memory won't be made usable in initial memory
>> setup as the memory won't be visible in E820 map, but it might be
>> added when adding PCI devices due to corresponding ACPI table entries.
>>
>> Not respecting "mem=" can be corrected by adding a global max_mem_size
>> variable set by parse_memopt() which will result in rejecting adding
>> memory areas resulting in a memory size above the allowed limit.
> 
> So historically 'mem=xxxM' was a way to quickly limit RAM.

Right.

> If PCI devices had physical mmio memory areas above this range, we'd 
> still expect them to work - the option was really only meant to limit 
> RAM.

No, in this case it seems to be real RAM added via PCI. The RAM is
initially present in the E820 map, but the "mem=" will remove it from
there again. During ACPI scan it is found (again) and will be added
via hotplug mechanism, so "mem=" has no effect for that memory.


Juergen
Ingo Molnar Feb. 11, 2019, 12:23 p.m. UTC | #3
* Juergen Gross <jgross@suse.com> wrote:

> > If PCI devices had physical mmio memory areas above this range, we'd 
> > still expect them to work - the option was really only meant to limit 
> > RAM.
> 
> No, in this case it seems to be real RAM added via PCI. The RAM is 
> initially present in the E820 map, but the "mem=" will remove it from 
> there again. During ACPI scan it is found (again) and will be added via 
> hotplug mechanism, so "mem=" has no effect for that memory.

OK. With that background:

Acked-by: Ingo Molnar <mingo@kernel.org>

I suppose you want this to go upstream via the Xen tree, which is the 
main testcase for the bug to begin with?

Thanks,

	ngo
Jürgen Groß Feb. 11, 2019, 12:35 p.m. UTC | #4
On 11/02/2019 13:23, Ingo Molnar wrote:
> 
> * Juergen Gross <jgross@suse.com> wrote:
> 
>>> If PCI devices had physical mmio memory areas above this range, we'd 
>>> still expect them to work - the option was really only meant to limit 
>>> RAM.
>>
>> No, in this case it seems to be real RAM added via PCI. The RAM is 
>> initially present in the E820 map, but the "mem=" will remove it from 
>> there again. During ACPI scan it is found (again) and will be added via 
>> hotplug mechanism, so "mem=" has no effect for that memory.
> 
> OK. With that background:
> 
> Acked-by: Ingo Molnar <mingo@kernel.org>
> 
> I suppose you want this to go upstream via the Xen tree, which is the 
> main testcase for the bug to begin with?

Yes, I'd prefer that.


Juergen
diff mbox series

Patch

diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 50895c2f937d..e67513e2cbbb 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -14,6 +14,7 @@ 
 #include <linux/acpi.h>
 #include <linux/firmware-map.h>
 #include <linux/sort.h>
+#include <linux/memory_hotplug.h>
 
 #include <asm/e820/api.h>
 #include <asm/setup.h>
@@ -881,6 +882,10 @@  static int __init parse_memopt(char *p)
 
 	e820__range_remove(mem_size, ULLONG_MAX - mem_size, E820_TYPE_RAM, 1);
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+	max_mem_size = mem_size;
+#endif
+
 	return 0;
 }
 early_param("mem", parse_memopt);
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 07da5c6c5ba0..fb6bd0022d41 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -98,6 +98,8 @@  extern void __online_page_free(struct page *page);
 
 extern int try_online_node(int nid);
 
+extern u64 max_mem_size;
+
 extern bool memhp_auto_online;
 /* If movable_node boot option specified */
 extern bool movable_node_enabled;
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index b9a667d36c55..94f81c596151 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -96,10 +96,16 @@  void mem_hotplug_done(void)
 	cpus_read_unlock();
 }
 
+u64 max_mem_size = U64_MAX;
+
 /* add this memory to iomem resource */
 static struct resource *register_memory_resource(u64 start, u64 size)
 {
 	struct resource *res, *conflict;
+
+	if (start + size > max_mem_size)
+		return ERR_PTR(-E2BIG);
+
 	res = kzalloc(sizeof(struct resource), GFP_KERNEL);
 	if (!res)
 		return ERR_PTR(-ENOMEM);