Skip to contentSkip to conversation

x86: add support for reserved memory defined by DT

PATCH New Grzegorz Jaszczyk 1 participant 3 messages Mar 13 x86

lore
Share & tools
lore
#0 lore raw

v4 cover x86: add support for reserved memory defined by DT

Currently x86 allows to boot with ACPI and DT at the same time and basic DT support is already in place but processing DT reserved memory was missing.

The DT reserved-memory nodes can be present in DT as described in Documentation/devicetree/bindings/reserved-memory/reserved-memory.yaml. Similar to other architecture, which supports DT, there is a need to scan and register reserved memory regions on x86 for such nodes. It is required by drivers (e.g. open-dice driver) to process DT reserved-memory regions.

v3 -> v4:
- Rebased onto latest upstream baseline. Previous series:
https://lore.kernel.org/all/[email protected]/
- Improved commit logs
- Improved e820__reserve_nomap_region to perform e820__update_table_print only once
- Fixed e820__reserve_nomap_region by passing region->base instead of truncated start address and original size, which was wrong

v2 -> v3:
- Patch #1 which extends of/reserved_mem and adds the possibility to register an arch specific hook was dropped. Instead "x86/e820: reserve corresponding to DT reserved-memory nomap region" was introduced.
- "x86/of: add support for reserved memory defined by DT" stop relying on arch specific hook. Also calling x86_flattree_get_config was moved and is now called earlier during memblock setup.
For more info please refer to commit log description and v2 discussion:
https://lore.kernel.org/all/[email protected]/

Grzegorz Jaszczyk (2):
x86/of: add early setup of DT reserved-memory nodes x86/e820: reserve corresponding to DT reserved-memory nomap region

 arch/x86/include/asm/e820/api.h |  1 +
 arch/x86/kernel/devicetree.c    |  1 +
 arch/x86/kernel/e820.c          | 20 ++++++++++++++++++++
 arch/x86/kernel/setup.c         |  6 ++++--
 4 files changed, 26 insertions(+), 2 deletions(-)
Signature · 1 line
2.53.0.851.ga537e3e6e9-goog
#1 lore raw

PATCH v4 1/2 x86/of: add early setup of DT reserved-memory nodes

The x86 allows booting with ACPI and DT simultaneously, and while basic DT support is present, the processing of DT 'reserved-memory' is currently missing.

Some drivers (such as open-dice driver) rely on the standard device-tree bindings (Documentation/devicetree/bindings/reserved-memory/) to communicate securely reserved memory region.

To support this add early_init_fdt_scan_reserved_mem as part of early flattened device tree parsing.

Additionally this patch changes the sequence and calls x86_flattree_get_config earlier in setup_arch(), just after e820 memblock setup, so the DT reserved-memory can be properly reflected in the memblock before that reserved-memory is used for allocation.

---
 arch/x86/kernel/devicetree.c | 1 +
 arch/x86/kernel/setup.c      | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)
arch/x86/kernel/devicetree.c +1 -0
index dd8748c45529..f7db0e8f9c3e 100644
@@ -307,6 +307,7 @@ void __init x86_flattree_get_config(void)
 		}
 
 		early_init_dt_verify(dt, __pa(dt));
+		early_init_fdt_scan_reserved_mem();
 	}
 
 	unflatten_and_copy_device_tree();
arch/x86/kernel/setup.c +2 -2
index eebcc9db1a1b..cf6c93f8be1a 100644
@@ -1076,6 +1076,8 @@ void __init setup_arch(char **cmdline_p)
 
 	e820__memblock_setup();
 
+	x86_flattree_get_config();
+
 	/*
 	 * Needs to run after memblock setup because it needs the physical
 	 * memory size.
@@ -1186,8 +1188,6 @@ void __init setup_arch(char **cmdline_p)
 	early_acpi_boot_init();
 	x86_init.mpparse.early_parse_smp_cfg();
 
-	x86_flattree_get_config();
-
 	initmem_init();
 	dma_contiguous_reserve(max_pfn_mapped << PAGE_SHIFT);
 
Signature · 1 line
2.53.0.851.ga537e3e6e9-goog
#2 lore raw

PATCH v4 2/2 x86/e820: reserve corresponding to DT reserved-memory nomap region

In reply to Grzegorz Jaszczyk

The DT reserved-memory nomap region shouldn't be mapped and registered as an IORESOURCE_SYSTEM_RAM resource. On the x86 platform the resource tree map is built based on e820 entries (via e820__reserve_resources()). Consequently memblock reservation originating from DT are not taken into account by x86 resource management unless they are explicitly injected into e820 table.

Injecting the corresponding no-map into e820 table as 'E820_TYPE_RESERVED', ensures that the x86 architecture builds an accurate resource tree. This aligns x86 with how other architectures (like arm64 in request_standard_resources() during resource tree
creation) protect DT no-map region.

Adding a corresponding e820 entry also allows other parts of x86 early kernel initialization to rely on it. E.g. e820__setup_pci_gap based on the gap in the e820 memory table picks space and passes to the PCI subsystem. Without adding corresponding e820 reserved entry, DT reserved memory nomap region could conflict with such region assigned later to PCI subsystem.

Additionally updating e820_table in this stage of the x86 setup seems safe since it is performed before mentioned e820__reserve_resources and e820__setup_pci_gap and there are also other functions, which updates e820 table on the later stage of early x86 setup such as early_quirks() and efi_arch_mem_reserve() (used by efi_esrt_init).

---
 arch/x86/include/asm/e820/api.h |  1 +
 arch/x86/kernel/e820.c          | 20 ++++++++++++++++++++
 arch/x86/kernel/setup.c         |  2 ++
 3 files changed, 23 insertions(+)
arch/x86/include/asm/e820/api.h +1 -0
index bbe0c8de976c..9568d88e8df8 100644
@@ -27,6 +27,7 @@ extern unsigned long e820__end_of_low_ram_pfn(void);
 
 extern u64  e820__memblock_alloc_reserved(u64 size, u64 align);
 extern void e820__memblock_setup(void);
+extern void e820__reserve_nomap_region(void);
 
 extern void e820__finish_early_params(void);
 extern void e820__reserve_resources(void);
arch/x86/kernel/e820.c +20 -0
index 2a9992758933..6f8a65dba7c7 100644
@@ -1374,3 +1374,23 @@ __init void e820__memblock_setup(void)
 
 	memblock_dump_all();
 }
+
+void __init e820__reserve_nomap_region(void)
+{
+	struct memblock_region *region;
+	bool updated = false;
+
+	for_each_mem_region(region) {
+		if (memblock_is_nomap(region)) {
+			/*
+			 * Add corresponding e820 region and let
+			 * e820__update_table sanitize e820 map
+			 */
+			e820__range_add(region->base, region->size, E820_TYPE_RESERVED);
+			updated = true;
+		}
+	}
+
+	if (updated)
+		e820__update_table_print();
+}
arch/x86/kernel/setup.c +2 -0
index cf6c93f8be1a..cbbc7abdabef 100644
@@ -1078,6 +1078,8 @@ void __init setup_arch(char **cmdline_p)
 
 	x86_flattree_get_config();
 
+	e820__reserve_nomap_region();
+
 	/*
 	 * Needs to run after memblock setup because it needs the physical
 	 * memory size.
Signature · 1 line
2.53.0.851.ga537e3e6e9-goog