Skip to contentSkip to conversation

x86, ACPI, numa: Parse numa info early

PATCH Superseded Yinghai Lu 8 participants 55 messages Mar 8, 2013 – Mar 12, 2013

Subsystems (8)

v1 of 5 Superseded Latest is v5 →

lore
Share & tools
lore

Yinghai Lu

author
#0 lore raw

cover x86, ACPI, numa: Parse numa info early

One commit that tried to parse SRAT early get reverted before v3.9-rc1.

| commit e8d1955258091e4c92d5a975ebd7fd8a98f5d30f
| Author: Tang Chen <[email protected]>
| Date:   Fri Feb 22 16:33:44 2013 -0800
|
|    acpi, memory-hotplug: parse SRAT before memblock is ready

It broke several several things, like acpi override and fall back path etc.

This patchset is clean implementation that will parse numa info early.
1. keep the acpi table initrd override working by split finding with copying. finding is done at head_32.S and head64.c stage, that mimics microcode updating. copying is just after memblock is setup.
2. keep fallback path working. numaq and ACPI and amd_nmua and dummy. seperate initmem_init to two stages. early_initmem_init will only extract numa info early into numa_meminfo.
3. keep other old code flow untouched like relocate_initrd and initmem_init.
4. last patch will try to put page table on local node, so that memory hotplug will be happy.

In short, early_initmem_init will parse numa info early and call init_mem_mapping to set page table for every nodes's mem.

could be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-x86-mm

and it is based on today's Linus tree that merges x86_urgent.

Tested on x86 32bit non-numa/numa, 64bit non-numa/numa configurations.

Thanks

Yinghai

Yinghai Lu (14):
x86, ACPI, mm: Kill max_low_pfn_mapped
x86, ACPI: Split find/copy from acpi_initrd_override x86, ACPI: store override acpi tables phys addr
x86, ACPI: make acpi override finding work with 32bit flat mode x86, ACPI: Find acpi tables in initrd early at head_32.S/head64.c x86, mm, numa: Move successful path handling code later x86, mm, numa: call numa_meminfo_cover_memory() early x86, mm, numa: use numa_meminfo to check node_map_pfn alignment x86, mm, numa: set memblock nid later
x86, mm, numa: Move emulation handling down.
x86, acpi, numa: split SLIT handling out
x86, mm, numa: Add early_initmem_init() stub
x86, mm: Parse numa info early
x86, mm: Put pagetable on local node ram

 arch/x86/include/asm/acpi.h            |    3 +-
 arch/x86/include/asm/page_types.h      |    2 +-
 arch/x86/include/asm/pgtable.h         |    2 +-
 arch/x86/include/asm/setup.h           |    2 +
 arch/x86/kernel/head64.c               |    2 +
 arch/x86/kernel/head_32.S              |    4 +
 arch/x86/kernel/setup.c                |   56 +++++---
 arch/x86/mm/init.c                     |   87 ++++++------
 arch/x86/mm/init_32.c                  |   11 ++
 arch/x86/mm/init_64.c                  |   12 ++
 arch/x86/mm/numa.c                     |  236 +++++++++++++++++++++++++-------
 arch/x86/mm/numa_emulation.c           |    2 +-
 arch/x86/mm/numa_internal.h            |    2 +
 arch/x86/mm/srat.c                     |    8 +-
 drivers/acpi/numa.c                    |   22 ++-
 drivers/acpi/osl.c                     |  122 +++++++++++------
 drivers/gpu/drm/i915/i915_gem_stolen.c |    2 +-
 include/linux/acpi.h                   |   18 +--
 include/linux/mm.h                     |    3 -
 mm/page_alloc.c                        |   52 +------
 20 files changed, 425 insertions(+), 223 deletions(-)
Signature · 1 line
1.7.10.4
author
#1 lore raw

PATCH 1/14 x86, ACPI, mm: Kill max_low_pfn_mapped

Now we have arch_pfn_mapped array, and max_low_pfn_mapped should not be used anymore.

Only user is ACPI_OVERRIDE, and it should not use that, as later accessing is using early_remap. Change to try to 4G below and then 4G above.

Other user is in drm/i915, but it is commented out.

Should use arch_pfn_mapped or just 1<<(32-PAGE_SHIFT) instead.

Cc Thomas Renninger <[email protected]>
Cc "Rafael J. Wysocki" <[email protected]>
Cc Daniel Vetter <[email protected]>
Cc David Airlie <[email protected]>
Cc Jacob Shin <[email protected]>
---
 arch/x86/include/asm/page_types.h      |    1 -
 arch/x86/kernel/setup.c                |    4 +---
 arch/x86/mm/init.c                     |    4 ----
 drivers/acpi/osl.c                     |    9 ++++++---
 drivers/gpu/drm/i915/i915_gem_stolen.c |    2 +-
 5 files changed, 8 insertions(+), 12 deletions(-)
arch/x86/include/asm/page_types.h +0 -1
index 54c9787..b012b82 100644
@@ -43,7 +43,6 @@
 
 extern int devmem_is_allowed(unsigned long pagenr);
 
-extern unsigned long max_low_pfn_mapped;
 extern unsigned long max_pfn_mapped;
 
 static inline phys_addr_t get_max_mapped(void)
arch/x86/kernel/setup.c +1 -3
index 90d8cc9..4dcaae7 100644
@@ -113,13 +113,11 @@
 #include <asm/prom.h>
 
 /*
- * max_low_pfn_mapped: highest direct mapped pfn under 4GB
- * max_pfn_mapped:     highest direct mapped pfn over 4GB
+ * max_pfn_mapped:     highest direct mapped pfn
  *
  * The direct mapping only covers E820_RAM regions, so the ranges and gaps are
  * represented by pfn_mapped
  */
-unsigned long max_low_pfn_mapped;
 unsigned long max_pfn_mapped;
 
 #ifdef CONFIG_DMI
arch/x86/mm/init.c +0 -4
index 59b7fc4..abcc241 100644
@@ -313,10 +313,6 @@ static void add_pfn_range_mapped(unsigned long start_pfn, unsigned long end_pfn)
 	nr_pfn_mapped = clean_sort_range(pfn_mapped, E820_X_MAX);
 
 	max_pfn_mapped = max(max_pfn_mapped, end_pfn);
-
-	if (start_pfn < (1UL<<(32-PAGE_SHIFT)))
-		max_low_pfn_mapped = max(max_low_pfn_mapped,
-					 min(end_pfn, 1UL<<(32-PAGE_SHIFT)));
 }
 
 bool pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn)
drivers/acpi/osl.c +6 -3
index 586e7e9..c9e36d7 100644
@@ -624,9 +624,12 @@ void __init acpi_initrd_override(void *data, size_t size)
 	if (table_nr == 0)
 		return;
 
-	acpi_tables_addr =
-		memblock_find_in_range(0, max_low_pfn_mapped << PAGE_SHIFT,
-				       all_tables_size, PAGE_SIZE);
+	/* under 4G at first, then above 4G */
+	acpi_tables_addr = memblock_find_in_range(0, 1ULL<<32,
+					all_tables_size, PAGE_SIZE);
+	if (!acpi_tables_addr)
+		acpi_tables_addr = memblock_find_in_range(1ULL<<32, -1ULL,
+					all_tables_size, PAGE_SIZE);
 	if (!acpi_tables_addr) {
 		WARN_ON(1);
 		return;
drivers/gpu/drm/i915/i915_gem_stolen.c +1 -1
index 69d97cb..7f9380b 100644
@@ -81,7 +81,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
 		base -= dev_priv->mm.gtt->stolen_size;
 	} else {
 		/* Stolen is immediately above Top of Memory */
-		base = max_low_pfn_mapped << PAGE_SHIFT;
+		base = __REMOVED_CRAZY__ << PAGE_SHIFT;
 #endif
 	}
 
Signature · 1 line
1.7.10.4
#2 lore raw

Re: [PATCH 01/14] x86, ACPI, mm: Kill max_low_pfn_mapped

drivers/gpu/drm/i915/i915_gem_stolen.c static unsigned long i915_stolen_to_physical(struct drm_device *dev) · line 84

Quoted 10 lines · Yinghai Lu
drivers/gpu/drm/i915/i915_gem_stolen.c +1 -1
index 69d97cb..7f9380b 100644
@@ -81,7 +81,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
 		base -= dev_priv->mm.gtt->stolen_size;
 	} else {
 		/* Stolen is immediately above Top of Memory */
-		base = max_low_pfn_mapped << PAGE_SHIFT;
+		base = __REMOVED_CRAZY__ << PAGE_SHIFT;

Huh?

Signature · 1 line
tejun
author
#3 lore raw

Re: [PATCH 01/14] x86, ACPI, mm: Kill max_low_pfn_mapped

Quoted 13 lines · Tejun Heo

drivers/gpu/drm/i915/i915_gem_stolen.c static unsigned long i915_stolen_to_physical(struct drm_device *dev) · line 84

Quoted 10 lines · Yinghai Lu
drivers/gpu/drm/i915/i915_gem_stolen.c +1 -1
index 69d97cb..7f9380b 100644
@@ -81,7 +81,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
              base -= dev_priv->mm.gtt->stolen_size;
      } else {
              /* Stolen is immediately above Top of Memory */
-             base = max_low_pfn_mapped << PAGE_SHIFT;
+             base = __REMOVED_CRAZY__ << PAGE_SHIFT;

Huh?

Whole function:

static unsigned long i915_stolen_to_physical(struct drm_device *dev)

{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct pci_dev *pdev = dev_priv->bridge_dev;
	u32 base;

	/* On the machines I have tested the Graphics Base of Stolen Memory
	 * is unreliable, so on those compute the base by subtracting the
	 * stolen memory from the Top of Low Usable DRAM which is where the
	 * BIOS places the graphics stolen memory.
	 *
	 * On gen2, the layout is slightly different with the Graphics Segment
	 * immediately following Top of Memory (or Top of Usable DRAM). Note
	 * it appears that TOUD is only reported by 865g, so we just use the
	 * top of memory as determined by the e820 probe.
	 *
	 * XXX gen2 requires an unavailable symbol and 945gm fails with
	 * its value of TOLUD.
	 */
	base = 0;
	if (INTEL_INFO(dev)->gen >= 6) {
		/* Read Base Data of Stolen Memory Register (BDSM) directly.
		 * Note that there is also a MCHBAR miror at 0x1080c0 or
		 * we could use device 2:0x5c instead.
		*/
		pci_read_config_dword(pdev, 0xB0, &base);
		base &= ~4095; /* lower bits used for locking register */
	} else if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
		/* Read Graphics Base of Stolen Memory directly */
		pci_read_config_dword(pdev, 0xA4, &base);
#if 0
	} else if (IS_GEN3(dev)) {
		u8 val;
		/* Stolen is immediately below Top of Low Usable DRAM */
		pci_read_config_byte(pdev, 0x9c, &val);
		base = val >> 3 << 27;
		base -= dev_priv->mm.gtt->stolen_size;
	} else {
		/* Stolen is immediately above Top of Memory */
		base = __REMOVED_CRAZY__ << PAGE_SHIFT;
#endif
	}

	return base;
}
#4 lore raw

Re: [PATCH 01/14] x86, ACPI, mm: Kill max_low_pfn_mapped

Quoted 15 lines · Yinghai Lu
Quoted 13 lines · Tejun Heo

drivers/gpu/drm/i915/i915_gem_stolen.c static unsigned long i915_stolen_to_physical(struct drm_device *dev) · line 84

Quoted 10 lines · Yinghai Lu
drivers/gpu/drm/i915/i915_gem_stolen.c +1 -1
index 69d97cb..7f9380b 100644
@@ -81,7 +81,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
              base -= dev_priv->mm.gtt->stolen_size;
      } else {
              /* Stolen is immediately above Top of Memory */
-             base = max_low_pfn_mapped << PAGE_SHIFT;
+             base = __REMOVED_CRAZY__ << PAGE_SHIFT;

Huh?

Quoted 1 line

Whole function:

Yeah, but can't we still just do 1LLU << 32 like other places? Or at least explain what was there before? It's gonna confuse the hell out of future readers of the code.

Signature · 1 line
tejun
author
#5 lore raw

Re: [PATCH 01/14] x86, ACPI, mm: Kill max_low_pfn_mapped

Quoted 16 lines · Tejun Heo
Quoted 15 lines · Yinghai Lu
Quoted 13 lines · Tejun Heo

drivers/gpu/drm/i915/i915_gem_stolen.c static unsigned long i915_stolen_to_physical(struct drm_device *dev) · line 84

Quoted 10 lines · Yinghai Lu
drivers/gpu/drm/i915/i915_gem_stolen.c +1 -1
index 69d97cb..7f9380b 100644
@@ -81,7 +81,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
              base -= dev_priv->mm.gtt->stolen_size;
      } else {
              /* Stolen is immediately above Top of Memory */
-             base = max_low_pfn_mapped << PAGE_SHIFT;
+             base = __REMOVED_CRAZY__ << PAGE_SHIFT;

Huh?

Quoted 5 lines
Quoted 1 line

Whole function:

Yeah, but can't we still just do 1LLU << 32 like other places? Or at least explain what was there before? It's gonna confuse the hell out of future readers of the code.

They are not using memblock_find_in_range(), so 1ULL<< will not help.

Really hope i915 drm guys could clean that hacks.

Thanks

Yinghai

#6 lore raw

Re: [PATCH 01/14] x86, ACPI, mm: Kill max_low_pfn_mapped

Quoted 3 lines · Yinghai Lu

They are not using memblock_find_in_range(), so 1ULL<< will not help.

Really hope i915 drm guys could clean that hacks.

The code isn't being used. Just leave it alone. Maybe add a comment.
The change is just making things more confusing.

Signature · 1 line
tejun
#7 lore raw

Re: [PATCH 01/14] x86, ACPI, mm: Kill max_low_pfn_mapped

Quoted 8 lines · Tejun Heo
Quoted 3 lines · Yinghai Lu

They are not using memblock_find_in_range(), so 1ULL<< will not help.

Really hope i915 drm guys could clean that hacks.

The code isn't being used. Just leave it alone. Maybe add a comment.
The change is just making things more confusing.

Indeed, but...

Daniel: can you guys clean this up or can we just remove the #if 0 clause?

-hpa

Signature · 2 lines
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.
#8 lore raw

Re: [PATCH 01/14] x86, ACPI, mm: Kill max_low_pfn_mapped

Quoted 6 lines · H. Peter Anvin
Quoted 5 lines · Tejun Heo
Quoted 3 lines · Yinghai Lu

They are not using memblock_find_in_range(), so 1ULL<< will not help.

Really hope i915 drm guys could clean that hacks.

Quoted 7 lines
Quoted 3 lines

The code isn't being used. Just leave it alone. Maybe add a comment.
The change is just making things more confusing.

Indeed, but...

Daniel: can you guys clean this up or can we just remove the #if 0 clause?

I guess we could just put this into a comment explaining where stolen memory for the gfx devices is at on gen2. But tbh I don't mind if we just keep the #if 0 code around. For all newer platforms we can get at that offset through mch bar registers, so I don't really care. -Daniel

Signature · 3 lines
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
#9 lore raw

Re: [PATCH 01/14] x86, ACPI, mm: Kill max_low_pfn_mapped

Quoted 11 lines · Daniel Vetter
Quoted 10 lines · H. Peter Anvin
Quoted 8 lines · Tejun Heo
Quoted 3 lines · Yinghai Lu

They are not using memblock_find_in_range(), so 1ULL<< will not help.

Really hope i915 drm guys could clean that hacks.

The code isn't being used. Just leave it alone. Maybe add a comment.
The change is just making things more confusing.

Quoted 8 lines
Quoted 3 lines

Indeed, but...

Daniel: can you guys clean this up or can we just remove the #if 0 clause?

I guess we could just put this into a comment explaining where stolen memory for the gfx devices is at on gen2. But tbh I don't mind if we just keep the #if 0 code around. For all newer platforms we can get at that offset through mch bar registers, so I don't really care.

If you want to keep the comment accurate s/max_low_pfn_mapped/max_pfn_mapped/ as the machines in question don't support more than 4GiB anyway. Or you can help address the underlying issue of figuring out how we can derive the location of the stolen memory which is reserved by the BIOS but not communicated to the OS. -Chris

Signature · 1 line
Chris Wilson, Intel Open Source Technology Centre
#10 lore raw

Re: [PATCH 01/14] x86, ACPI, mm: Kill max_low_pfn_mapped

In reply to Daniel Vetter

The problem is that the code will be broken, and so it makes no sense. The #if 0 is really confusing.

Quoted 25 lines · Daniel Vetter
Quoted 2 lines · H. Peter Anvin
Quoted 1 line · Tejun Heo

On Thu, Mar 7, 2013 at 9:27 PM, Yinghai Lu <[email protected]>

Quoted 1 line · wrote:
Quoted 1 line
Quoted 1 line

They are not using memblock_find_in_range(), so 1ULL<< will not

help.

Quoted 4 lines
Quoted 4 lines
Quoted 2 lines

Really hope i915 drm guys could clean that hacks.

The code isn't being used. Just leave it alone. Maybe add a

comment.

Quoted 6 lines
Quoted 2 lines

The change is just making things more confusing.

Indeed, but...

Daniel: can you guys clean this up or can we just remove the #if 0

clause?

I guess we could just put this into a comment explaining where stolen memory for the gfx devices is at on gen2. But tbh I don't mind if we just
keep the #if 0 code around. For all newer platforms we can get at that offset through mch bar registers, so I don't really care. -Daniel

Signature · 1 line
Sent from my mobile phone. Please excuse brevity and lack of formatting.
author
#11 lore raw

PATCH 2/14 x86, ACPI: Split find/copy from acpi_initrd_override

In reply to Yinghai Lu

To parse srat early, we will need to move acpi table probing early. and to keep acpi_initrd_table_override working, we need to move it ahead.

But current that is called after init_mem_mapping and relocate_initrd().

Copying need to be after memblock is ready, because it need to allocate some buffer for acpi tables.

Finding will be moved into head_32.S and head64.c, just like microcode early scanning.

So split them at first.

Also move down functions declaration to avoid #ifdef in setup.c

Cc Thomas Renninger <[email protected]>
Cc Pekka Enberg <[email protected]>
Cc Jacob Shin <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
---
 arch/x86/kernel/setup.c |    6 +++---
 drivers/acpi/osl.c      |   32 +++++++++++++++++++-------------
 include/linux/acpi.h    |   16 ++++++++--------
 3 files changed, 30 insertions(+), 24 deletions(-)
arch/x86/kernel/setup.c +3 -3
index 4dcaae7..e2913e9 100644
@@ -1092,9 +1092,9 @@ void __init setup_arch(char **cmdline_p)
 
 	reserve_initrd();
 
-#if defined(CONFIG_ACPI) && defined(CONFIG_BLK_DEV_INITRD)
-	acpi_initrd_override((void *)initrd_start, initrd_end - initrd_start);
-#endif
+	acpi_initrd_override_find((void *)initrd_start,
+					initrd_end - initrd_start);
+	acpi_initrd_override_copy();
 
 	reserve_crashkernel();
 
drivers/acpi/osl.c +19 -13
index c9e36d7..b9d2ff0 100644
@@ -539,6 +539,7 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
 
 static u64 acpi_tables_addr;
 static int all_tables_size;
+static int table_nr;
 
 /* Copied from acpica/tbutils.c:acpi_tb_checksum() */
 u8 __init acpi_table_checksum(u8 *buffer, u32 length)
@@ -569,18 +570,16 @@ static const char * const table_sigs[] = {
 
 #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
 
-/* Must not increase 10 or needs code modification below */
-#define ACPI_OVERRIDE_TABLES 10
+#define ACPI_OVERRIDE_TABLES 64
+static struct cpio_data __initdata early_initrd_files[ACPI_OVERRIDE_TABLES];
 
-void __init acpi_initrd_override(void *data, size_t size)
+void __init acpi_initrd_override_find(void *data, size_t size)
 {
-	int sig, no, table_nr = 0, total_offset = 0;
+	int sig, no;
 	long offset = 0;
 	struct acpi_table_header *table;
 	char cpio_path[32] = "kernel/firmware/acpi/";
 	struct cpio_data file;
-	struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES];
-	char *p;
 
 	if (data == NULL || size == 0)
 		return;
@@ -621,7 +620,14 @@ void __init acpi_initrd_override(void *data, size_t size)
 		early_initrd_files[table_nr].size = file.size;
 		table_nr++;
 	}
-	if (table_nr == 0)
+}
+
+void __init acpi_initrd_override_copy(void)
+{
+	int no, total_offset = 0;
+	char *p;
+
+	if (!table_nr)
 		return;
 
 	/* under 4G at first, then above 4G */
@@ -647,14 +653,14 @@ void __init acpi_initrd_override(void *data, size_t size)
 	memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size);
 	arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 
-	p = early_ioremap(acpi_tables_addr, all_tables_size);
-
 	for (no = 0; no < table_nr; no++) {
-		memcpy(p + total_offset, early_initrd_files[no].data,
-		       early_initrd_files[no].size);
-		total_offset += early_initrd_files[no].size;
+		size_t size = early_initrd_files[no].size;
+
+		p = early_ioremap(acpi_tables_addr + total_offset, size);
+		memcpy(p, early_initrd_files[no].data, size);
+		early_iounmap(p, size);
+		total_offset += size;
 	}
-	early_iounmap(p, all_tables_size);
 }
 #endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
 
include/linux/acpi.h +8 -8
index bcbdd74..1654a241 100644
@@ -79,14 +79,6 @@ typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table);
 typedef int (*acpi_tbl_entry_handler)(struct acpi_subtable_header *header,
 				      const unsigned long end);
 
-#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
-void acpi_initrd_override(void *data, size_t size);
-#else
-static inline void acpi_initrd_override(void *data, size_t size)
-{
-}
-#endif
-
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 void __acpi_unmap_table(char *map, unsigned long size);
 int early_acpi_boot_init(void);
@@ -485,6 +477,14 @@ static inline bool acpi_driver_match_device(struct device *dev,
 
 #endif	/* !CONFIG_ACPI */
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+void acpi_initrd_override_find(void *data, size_t size);
+void acpi_initrd_override_copy(void);
+#else
+static inline void acpi_initrd_override_find(void *data, size_t size) { }
+static inline void acpi_initrd_override_copy(void) { }
+#endif
+
 #ifdef CONFIG_ACPI
 void acpi_os_set_prepare_sleep(int (*func)(u8 sleep_state,
 			       u32 pm1a_ctrl,  u32 pm1b_ctrl));
Signature · 1 line
1.7.10.4
#12 lore raw

Re: [PATCH 02/14] x86, ACPI: Split find/copy from acpi_initrd_override

Quoted 22 lines · Yinghai Lu

To parse srat early, we will need to move acpi table probing early. and to keep acpi_initrd_table_override working, we need to move it ahead.

But current that is called after init_mem_mapping and relocate_initrd().

Copying need to be after memblock is ready, because it need to allocate some buffer for acpi tables.

Finding will be moved into head_32.S and head64.c, just like microcode early scanning.

So split them at first.

Also move down functions declaration to avoid #ifdef in setup.c

Cc Thomas Renninger <[email protected]>
Cc Pekka Enberg <[email protected]>
Cc Jacob Shin <[email protected]>
Cc Rafael J. Wysocki <[email protected]>

...

drivers/acpi/osl.c acpi_os_predefined_override(const struct acpi_predefined_names *init_val, · line 542

Quoted 9 lines
drivers/acpi/osl.c +1 -0
index c9e36d7..b9d2ff0 100644
@@ -539,6 +539,7 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
 
 static u64 acpi_tables_addr;
 static int all_tables_size;
+static int table_nr;

Not particularly good choice of name for static variable visible to multiple functions. all_tables_size isn't a stellar choice either but no need to continue the tradition. Maybe acpi_nr_initrd_files? Also, why is this one defined here away from the actual table?

drivers/acpi/osl.c static const char * const table_sigs[] = { · line 573

Quoted 3 lines
drivers/acpi/osl.c +1 -2
-/* Must not increase 10 or needs code modification below */
-#define ACPI_OVERRIDE_TABLES 10
+#define ACPI_OVERRIDE_TABLES 64

What's up with the silent bumping of table size?

drivers/acpi/osl.c static const char * const table_sigs[] = { · line 574

Quoted 1 line
drivers/acpi/osl.c +1 -0
+static struct cpio_data __initdata early_initrd_files[ACPI_OVERRIDE_TABLES];

acpi_initrd_files[]? Do we really need the "early" designation together with initrd?

Quoted 8 lines
drivers/acpi/osl.c +0 -3
@@ -647,14 +653,14 @@ void __init acpi_initrd_override(void *data, size_t size)
 	memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size);
 	arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 
-	p = early_ioremap(acpi_tables_addr, all_tables_size);
-
 	for (no = 0; no < table_nr; no++) {
-		memcpy(p + total_offset, early_initrd_files[no].data,

drivers/acpi/osl.c void __init acpi_initrd_override(void *data, size_t size) · line 657

Quoted 10 lines
drivers/acpi/osl.c +6 -3
-		       early_initrd_files[no].size);
-		total_offset += early_initrd_files[no].size;
+		size_t size = early_initrd_files[no].size;
+
+		p = early_ioremap(acpi_tables_addr + total_offset, size);
+		memcpy(p, early_initrd_files[no].data, size);
+		early_iounmap(p, size);
+		total_offset += size;
 	}
-	early_iounmap(p, all_tables_size);

Why is this necessary? Why no explanation in the description?

Quoted 18 lines
include/linux/acpi.h +0 -8
@@ -79,14 +79,6 @@ typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table);
 typedef int (*acpi_tbl_entry_handler)(struct acpi_subtable_header *header,
 				      const unsigned long end);
 
-#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
-void acpi_initrd_override(void *data, size_t size);
-#else
-static inline void acpi_initrd_override(void *data, size_t size)
-{
-}
-#endif
-
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 void __acpi_unmap_table(char *map, unsigned long size);
 int early_acpi_boot_init(void);

include/linux/acpi.h static inline bool acpi_driver_match_device(struct device *dev, · line 486

Quoted 10 lines
include/linux/acpi.h +7 -0
@@ -485,6 +477,14 @@ static inline bool acpi_driver_match_device(struct device *dev,
 
 #endif	/* !CONFIG_ACPI */
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+void acpi_initrd_override_find(void *data, size_t size);
+void acpi_initrd_override_copy(void);
+#else
+static inline void acpi_initrd_override_find(void *data, size_t size) { }
+static inline void acpi_initrd_override_copy(void) { }
+#endif

I don't get this part either. Why is it necessary to move the prototypes to avoid #ifdefs in setup.c? Ah, okay, you're brining it outside CONFIG_ACPI so that they're defined regardless of that config option. Can you please add why you're moving the prototype in the descriptoin? Having "what" is nice but "why" is much nicer. :)

Thanks.

Signature · 1 line
tejun
author
#13 lore raw

Re: [PATCH 02/14] x86, ACPI: Split find/copy from acpi_initrd_override

Quoted 7 lines · Tejun Heo
Quoted 6 lines · Yinghai Lu
drivers/acpi/osl.c +0 -0
index c9e36d7..b9d2ff0 100644
@@ -539,6 +539,7 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
 
Quoted 8 lines

drivers/acpi/osl.c acpi_os_predefined_override(const struct acpi_predefined_names *init_val, · line 542

Quoted 3 lines
drivers/acpi/osl.c +1 -0
 static u64 acpi_tables_addr;
 static int all_tables_size;
+static int table_nr;

Not particularly good choice of name for static variable visible to multiple functions. all_tables_size isn't a stellar choice either but no need to continue the tradition. Maybe acpi_nr_initrd_files? Also, why is this one defined here away from the actual table?

ok, acpi_nr_initrd_files.

will check if it could be killed.

Quoted 5 lines

drivers/acpi/osl.c static const char * const table_sigs[] = { · line 573

Quoted 3 lines
drivers/acpi/osl.c +1 -2
-/* Must not increase 10 or needs code modification below */
-#define ACPI_OVERRIDE_TABLES 10
+#define ACPI_OVERRIDE_TABLES 64

What's up with the silent bumping of table size?

will mention that in change log.

Quoted 5 lines

drivers/acpi/osl.c static const char * const table_sigs[] = { · line 574

Quoted 2 lines
drivers/acpi/osl.c +1 -0
+static struct cpio_data __initdata early_initrd_files[ACPI_OVERRIDE_TABLES];

acpi_initrd_files[]? Do we really need the "early" designation together with initrd?

just move it out from acpi_initrd_override.

Quoted 5 lines
Quoted 5 lines
drivers/acpi/osl.c +0 -0
@@ -647,14 +653,14 @@ void __init acpi_initrd_override(void *data, size_t size)
      memblock_reserve(acpi_tables_addr, acpi_tables_addr + all_tables_size);
      arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 
Quoted 16 lines
Quoted 4 lines
drivers/acpi/osl.c +0 -3
-     p = early_ioremap(acpi_tables_addr, all_tables_size);
-
      for (no = 0; no < table_nr; no++) {
-             memcpy(p + total_offset, early_initrd_files[no].data,

drivers/acpi/osl.c void __init acpi_initrd_override(void *data, size_t size) · line 657

Quoted 10 lines
drivers/acpi/osl.c +6 -3
-                    early_initrd_files[no].size);
-             total_offset += early_initrd_files[no].size;
+             size_t size = early_initrd_files[no].size;
+
+             p = early_ioremap(acpi_tables_addr + total_offset, size);
+             memcpy(p, early_initrd_files[no].data, size);
+             early_iounmap(p, size);
+             total_offset += size;
      }
-     early_iounmap(p, all_tables_size);

Why is this necessary? Why no explanation in the description?

actually it is the reason for bump table_nr to 64.

early_ioremap only can map 256k one time, so there will have limit for overall size.

If map one by one, then we could increase the number of limit.

Quoted 22 lines
Quoted 22 lines
include/linux/acpi.h +0 -8
@@ -79,14 +79,6 @@ typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table);
 typedef int (*acpi_tbl_entry_handler)(struct acpi_subtable_header *header,
                                    const unsigned long end);
 
-#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
-void acpi_initrd_override(void *data, size_t size);
-#else
-static inline void acpi_initrd_override(void *data, size_t size)
-{
-}
-#endif
-
 char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
 void __acpi_unmap_table(char *map, unsigned long size);
 int early_acpi_boot_init(void);
@@ -485,6 +477,14 @@ static inline bool acpi_driver_match_device(struct device *dev,
 
 #endif       /* !CONFIG_ACPI */
 
Quoted 13 lines

include/linux/acpi.h static inline bool acpi_driver_match_device(struct device *dev, · line 486

Quoted 7 lines
include/linux/acpi.h +7 -0
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+void acpi_initrd_override_find(void *data, size_t size);
+void acpi_initrd_override_copy(void);
+#else
+static inline void acpi_initrd_override_find(void *data, size_t size) { }
+static inline void acpi_initrd_override_copy(void) { }
+#endif

I don't get this part either. Why is it necessary to move the prototypes to avoid #ifdefs in setup.c? Ah, okay, you're brining it outside CONFIG_ACPI so that they're defined regardless of that config option. Can you please add why you're moving the prototype in the descriptoin? Having "what" is nice but "why" is much nicer. :)

I think i have that in the log.

more detail is : ACPI_INITRD_TABLE_OVERRIDE depends one ACPI and BLK_DEV_INITRD.

So could move it out safely.

Thanks

Yinghai

author
#14 lore raw

PATCH 3/14 x86, ACPI: store override acpi tables phys addr

In reply to Yinghai Lu

As later 32bit only find table with phys address during 32bit flat mode in head_32.S.

To keep 32bit and 64 bit consistent, use phys_addr for all.

Use early_ioremap to access during copying.

Cc Thomas Renninger <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
---
 drivers/acpi/osl.c |   11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/acpi/osl.c +7 -4
index b9d2ff0..60317ea 100644
@@ -616,7 +616,7 @@ void __init acpi_initrd_override_find(void *data, size_t size)
 			table->signature, cpio_path, file.name, table->length);
 
 		all_tables_size += table->length;
-		early_initrd_files[table_nr].data = file.data;
+		early_initrd_files[table_nr].data = (void *)__pa(file.data);
 		early_initrd_files[table_nr].size = file.size;
 		table_nr++;
 	}
@@ -625,7 +625,7 @@ void __init acpi_initrd_override_find(void *data, size_t size)
 void __init acpi_initrd_override_copy(void)
 {
 	int no, total_offset = 0;
-	char *p;
+	char *p, *q;
 
 	if (!table_nr)
 		return;
@@ -654,10 +654,13 @@ void __init acpi_initrd_override_copy(void)
 	arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 
 	for (no = 0; no < table_nr; no++) {
-		size_t size = early_initrd_files[no].size;
+		unsigned long size = early_initrd_files[no].size;
 
 		p = early_ioremap(acpi_tables_addr + total_offset, size);
-		memcpy(p, early_initrd_files[no].data, size);
+		q = early_ioremap((unsigned long)early_initrd_files[no].data,
+					 size);
+		memcpy(p, q, size);
+		early_iounmap(q, size);
 		early_iounmap(p, size);
 		total_offset += size;
 	}
Signature · 1 line
1.7.10.4
#15 lore raw

Re: [PATCH 03/14] x86, ACPI: store override acpi tables phys addr

Quoted 15 lines · Yinghai Lu

As later 32bit only find table with phys address during 32bit flat mode in head_32.S.

To keep 32bit and 64 bit consistent, use phys_addr for all.

Use early_ioremap to access during copying.

Cc Thomas Renninger <[email protected]>
Cc Rafael J. Wysocki <[email protected]>

---

drivers/acpi/osl.c +0 -0
@@ -654,10 +654,13 @@ void __init acpi_initrd_override_copy(void)
 	arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 

drivers/acpi/osl.c void __init acpi_initrd_override_copy(void) · line 663

Quoted 10 lines
drivers/acpi/osl.c +5 -2
 	for (no = 0; no < table_nr; no++) {
-		size_t size = early_initrd_files[no].size;
+		unsigned long size = early_initrd_files[no].size;
 
 		p = early_ioremap(acpi_tables_addr + total_offset, size);
-		memcpy(p, early_initrd_files[no].data, size);
+		q = early_ioremap((unsigned long)early_initrd_files[no].data,
+					 size);
+		memcpy(p, q, size);
+		early_iounmap(q, size);

Ah, okay, so the loop change in the previous patch was for this, I suppose? That chunk probably should either be a separate patch or rolled into this one.

Thanks.

Signature · 1 line
tejun
author
#16 lore raw

Re: [PATCH 03/14] x86, ACPI: store override acpi tables phys addr

Quoted 20 lines · Tejun Heo
Quoted 19 lines · Yinghai Lu

As later 32bit only find table with phys address during 32bit flat mode in head_32.S.

To keep 32bit and 64 bit consistent, use phys_addr for all.

Use early_ioremap to access during copying.

Cc Thomas Renninger <[email protected]>
Cc Rafael J. Wysocki <[email protected]>

---

drivers/acpi/osl.c +1 -1
@@ -654,10 +654,13 @@ void __init acpi_initrd_override_copy(void)
      arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 
      for (no = 0; no < table_nr; no++) {
-             size_t size = early_initrd_files[no].size;
+             unsigned long size = early_initrd_files[no].size;
 
Quoted 10 lines

drivers/acpi/osl.c void __init acpi_initrd_override_copy(void) · line 663

Quoted 6 lines
drivers/acpi/osl.c +4 -1
              p = early_ioremap(acpi_tables_addr + total_offset, size);
-             memcpy(p, early_initrd_files[no].data, size);
+             q = early_ioremap((unsigned long)early_initrd_files[no].data,
+                                      size);
+             memcpy(p, q, size);
+             early_iounmap(q, size);

Ah, okay, so the loop change in the previous patch was for this, I suppose? That chunk probably should either be a separate patch or rolled into this one.

merge two patches?

#17 lore raw

Re: [PATCH 03/14] x86, ACPI: store override acpi tables phys addr

Quoted 18 lines · Yinghai Lu
Quoted 7 lines
Quoted 7 lines
drivers/acpi/osl.c +1 -1
@@ -654,10 +654,13 @@ void __init acpi_initrd_override_copy(void)
      arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 
      for (no = 0; no < table_nr; no++) {
-             size_t size = early_initrd_files[no].size;
+             unsigned long size = early_initrd_files[no].size;
 
Quoted 10 lines

drivers/acpi/osl.c void __init acpi_initrd_override_copy(void) · line 663

Quoted 6 lines
drivers/acpi/osl.c +4 -1
              p = early_ioremap(acpi_tables_addr + total_offset, size);
-             memcpy(p, early_initrd_files[no].data, size);
+             q = early_ioremap((unsigned long)early_initrd_files[no].data,
+                                      size);
+             memcpy(p, q, size);
+             early_iounmap(q, size);

Ah, okay, so the loop change in the previous patch was for this, I suppose? That chunk probably should either be a separate patch or rolled into this one.

Quoted 1 line

merge two patches?

Hmm... probably better to just move the related chunks from the previous patch to this one with better explanation on what's going on.

Thanks.

Signature · 1 line
tejun
author
#18 lore raw

PATCH 4/14 x86, ACPI: make acpi override finding work with 32bit flat mode

In reply to Yinghai Lu

We will find acpi tables in initrd during head_32.S in 32bit flat mode.

So need acpi_initrd_override_find could take phys directly.

Cc Thomas Renninger <[email protected]>
Cc Pekka Enberg <[email protected]>
Cc Jacob Shin <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
---
 arch/x86/kernel/setup.c |    2 +-
 drivers/acpi/osl.c      |   84 +++++++++++++++++++++++++++++++----------------
 include/linux/acpi.h    |    4 +--
 3 files changed, 58 insertions(+), 32 deletions(-)
arch/x86/kernel/setup.c +1 -1
index e2913e9..668e658 100644
@@ -1093,7 +1093,7 @@ void __init setup_arch(char **cmdline_p)
 	reserve_initrd();
 
 	acpi_initrd_override_find((void *)initrd_start,
-					initrd_end - initrd_start);
+					initrd_end - initrd_start, false);
 	acpi_initrd_override_copy();
 
 	reserve_crashkernel();
drivers/acpi/osl.c +55 -29

136 lines not on this page · raw message

include/linux/acpi.h +2 -2
index 1654a241..46a8a89 100644
@@ -478,10 +478,10 @@ static inline bool acpi_driver_match_device(struct device *dev,
 #endif	/* !CONFIG_ACPI */
 
 #ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
-void acpi_initrd_override_find(void *data, size_t size);
+void acpi_initrd_override_find(void *data, size_t size, bool is_phys);
 void acpi_initrd_override_copy(void);
 #else
-static inline void acpi_initrd_override_find(void *data, size_t size) { }
+static inline void acpi_initrd_override_find(void *data, size_t size, bool is_phys) { }
 static inline void acpi_initrd_override_copy(void) { }
 #endif
 
Signature · 1 line
1.7.10.4
#19 lore raw

Re: [PATCH 04/14] x86, ACPI: make acpi override finding work with 32bit flat mode

Quoted 3 lines · Yinghai Lu

We will find acpi tables in initrd during head_32.S in 32bit flat mode.

So need acpi_initrd_override_find could take phys directly.

The patch description doesn't explain even half of what's going on.

Quoted 5 lines
drivers/acpi/osl.c +0 -1
@@ -552,38 +552,47 @@ u8 __init acpi_table_checksum(u8 *buffer, u32 length)
 	return sum;
 }
 
-/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */

drivers/acpi/osl.c u8 __init acpi_table_checksum(u8 *buffer, u32 length) · line 565

Quoted 10 lines
drivers/acpi/osl.c +0 -10
-static const char * const table_sigs[] = {
-	ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
-	ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
-	ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
-	ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
-	ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
-	ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
-	ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
-	ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
-	ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };

Why is this table made a stack variable? What's the benefit of doing that?

drivers/acpi/osl.c u8 __init acpi_table_checksum(u8 *buffer, u32 length) · line 557

Quoted 4 lines
drivers/acpi/osl.c +1 -1
 /* Non-fatal errors: Affected tables/files are ignored */
 #define INVALID_TABLE(x, path, name)					\
-	{ pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; }
+	do { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); } while (0)

Might as well rename the macro to something which indicates it's just printing error message. Urgh... who thought embedding control flow directive like continue inside a macro was a good idea? :(

drivers/acpi/osl.c u8 __init acpi_table_checksum(u8 *buffer, u32 length) · line 564

Quoted 2 lines
drivers/acpi/osl.c +1 -1
-void __init acpi_initrd_override_find(void *data, size_t size)
+void __init acpi_initrd_override_find(void *data, size_t size, bool is_phys)

Is it really necessary to make the function take both virtual and physical addresses? Can't we just make the function take phys_addr_t and update everyone to call with physaddr? Also @is_phys isn't simple address switch. It also changes error reporting. If you're gonna keep @is_phys, let's at least write up a function comment explaining what's going on and why we need it. But, really, if at all possible, let's change the function to take single type of argument and predicate error message printing on something else (e.g. early printk initialized or whatever).

drivers/acpi/osl.c void __init acpi_initrd_override_copy(void) · line 680

Quoted 5 lines
drivers/acpi/osl.c +1 -0
@@ -654,11 +677,14 @@ void __init acpi_initrd_override_copy(void)
 	arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 
 	for (no = 0; no < table_nr; no++) {
+		unsigned long phys_addr = (unsigned long)early_initrd_files[no].data;

Can we please use phys_addr_t for physical addresses?

drivers/acpi/osl.c void __init acpi_initrd_override_copy(void) · line 686

Quoted 6 lines
drivers/acpi/osl.c +4 -0
 		unsigned long size = early_initrd_files[no].size;
 
+		q = early_ioremap(phys_addr, size);
+		pr_info("%4.4s ACPI table found in initrd [%#010lx-%#010lx]\n",
+				((struct acpi_table_header *)q)->signature,
+				phys_addr, phys_addr + size - 1);

Maybe putting pr_info after ioremapping both p and q would be easier on the eyes?

drivers/acpi/osl.c void __init acpi_initrd_override_copy(void) · line 690

Quoted 6 lines
drivers/acpi/osl.c +0 -2
 		p = early_ioremap(acpi_tables_addr + total_offset, size);
-		q = early_ioremap((unsigned long)early_initrd_files[no].data,
-					 size);
 		memcpy(p, q, size);
 		early_iounmap(q, size);
 		early_iounmap(p, size);

Thanks.

Signature · 1 line
tejun
author
#20 lore raw

Re: [PATCH 04/14] x86, ACPI: make acpi override finding work with 32bit flat mode

Quoted 6 lines · Tejun Heo
Quoted 3 lines · Yinghai Lu

We will find acpi tables in initrd during head_32.S in 32bit flat mode.

So need acpi_initrd_override_find could take phys directly.

The patch description doesn't explain even half of what's going on.

hope HPA could understand.

Access initrd before relocate_initrd and init_memory mapping.

Quoted 5 lines
Quoted 5 lines
drivers/acpi/osl.c +0 -0
@@ -552,38 +552,47 @@ u8 __init acpi_table_checksum(u8 *buffer, u32 length)
      return sum;
 }
 
Quoted 14 lines

drivers/acpi/osl.c u8 __init acpi_table_checksum(u8 *buffer, u32 length) · line 565

Quoted 11 lines
drivers/acpi/osl.c +0 -11
-/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
-static const char * const table_sigs[] = {
-     ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
-     ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
-     ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
-     ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
-     ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
-     ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
-     ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
-     ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
-     ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };

Why is this table made a stack variable? What's the benefit of doing that?

so I do need to switch global variables to phys and access it.

Quoted 9 lines

drivers/acpi/osl.c u8 __init acpi_table_checksum(u8 *buffer, u32 length) · line 557

Quoted 5 lines
drivers/acpi/osl.c +1 -1
 /* Non-fatal errors: Affected tables/files are ignored */
 #define INVALID_TABLE(x, path, name)                                 \
-     { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); continue; }
+     do { pr_err("ACPI OVERRIDE: " x " [%s%s]\n", path, name); } while (0)

Might as well rename the macro to something which indicates it's just printing error message. Urgh... who thought embedding control flow directive like continue inside a macro was a good idea? :(

so I removed it.

Quoted 13 lines

drivers/acpi/osl.c u8 __init acpi_table_checksum(u8 *buffer, u32 length) · line 564

Quoted 3 lines
drivers/acpi/osl.c +1 -1
-void __init acpi_initrd_override_find(void *data, size_t size)
+void __init acpi_initrd_override_find(void *data, size_t size, bool is_phys)

Is it really necessary to make the function take both virtual and physical addresses? Can't we just make the function take phys_addr_t and update everyone to call with physaddr? Also @is_phys isn't simple address switch. It also changes error reporting. If you're gonna keep @is_phys, let's at least write up a function comment explaining what's going on and why we need it. But, really, if at all possible, let's change the function to take single type of argument and predicate error message printing on something else (e.g. early printk initialized or whatever).

yes, one for 32bit from head_32.S, phys.
one for 64bit from head64.c. with _va.

Not sure if I could use early_printk from head_32.S, as Fenghua does not print out
from microcode updating early in the same parts.

Will check that.

Quoted 8 lines

drivers/acpi/osl.c void __init acpi_initrd_override_copy(void) · line 680

Quoted 6 lines
drivers/acpi/osl.c +1 -0
@@ -654,11 +677,14 @@ void __init acpi_initrd_override_copy(void)
      arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 
      for (no = 0; no < table_nr; no++) {
+             unsigned long phys_addr = (unsigned long)early_initrd_files[no].data;

Can we please use phys_addr_t for physical addresses?

ok.

Quoted 10 lines

drivers/acpi/osl.c void __init acpi_initrd_override_copy(void) · line 686

Quoted 7 lines
drivers/acpi/osl.c +4 -0
              unsigned long size = early_initrd_files[no].size;
 
+             q = early_ioremap(phys_addr, size);
+             pr_info("%4.4s ACPI table found in initrd [%#010lx-%#010lx]\n",
+                             ((struct acpi_table_header *)q)->signature,
+                             phys_addr, phys_addr + size - 1);

Maybe putting pr_info after ioremapping both p and q would be easier on the eyes?

ok.

Quoted 7 lines

drivers/acpi/osl.c void __init acpi_initrd_override_copy(void) · line 690

Quoted 7 lines
drivers/acpi/osl.c +0 -2
              p = early_ioremap(acpi_tables_addr + total_offset, size);
-             q = early_ioremap((unsigned long)early_initrd_files[no].data,
-                                      size);
              memcpy(p, q, size);
              early_iounmap(q, size);
              early_iounmap(p, size);

Thanks

Yinghai

#21 lore raw

Re: [PATCH 04/14] x86, ACPI: make acpi override finding work with 32bit flat mode

Hello, Yinghai.

Quoted 11 lines · Yinghai Lu
Quoted 6 lines · Tejun Heo
Quoted 3 lines · Yinghai Lu

We will find acpi tables in initrd during head_32.S in 32bit flat mode.

So need acpi_initrd_override_find could take phys directly.

The patch description doesn't explain even half of what's going on.

hope HPA could understand.

Access initrd before relocate_initrd and init_memory mapping.

I really hope the changelogs were better. Eh well...

Quoted 15 lines
Quoted 6 lines
Quoted 6 lines
drivers/acpi/osl.c +0 -6
-/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
-static const char * const table_sigs[] = {
-     ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
-     ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
-     ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
-     ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
Quoted 8 lines

drivers/acpi/osl.c u8 __init acpi_table_checksum(u8 *buffer, u32 length) · line 565

Quoted 5 lines
drivers/acpi/osl.c +0 -5
-     ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
-     ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
-     ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
-     ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
-     ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };

Why is this table made a stack variable? What's the benefit of doing that?

Quoted 1 line

so I do need to switch global variables to phys and access it.

I can't really understand what your response means. Can you please elaborate?

Quoted 10 lines
Quoted 9 lines

Is it really necessary to make the function take both virtual and physical addresses? Can't we just make the function take phys_addr_t and update everyone to call with physaddr? Also @is_phys isn't simple address switch. It also changes error reporting. If you're gonna keep @is_phys, let's at least write up a function comment explaining what's going on and why we need it. But, really, if at all possible, let's change the function to take single type of argument and predicate error message printing on something else (e.g. early printk initialized or whatever).

Quoted 2 lines

yes, one for 32bit from head_32.S, phys.
one for 64bit from head64.c. with _va.

head64.c can't call with phys? Why not?

Quoted 3 lines

Not sure if I could use early_printk from head_32.S, as Fenghua does not print out
from microcode updating early in the same parts.

ISTR it works but it doens't have to (although it would be much nicer if it did). You can test whether printk is online and skip if it isn't online yet.

Thanks.

Signature · 1 line
tejun
author
#22 lore raw

Re: [PATCH 04/14] x86, ACPI: make acpi override finding work with 32bit flat mode

Quoted 32 lines · Tejun Heo

Hello, Yinghai.

Quoted 11 lines · Yinghai Lu
Quoted 6 lines · Tejun Heo
Quoted 3 lines · Yinghai Lu

We will find acpi tables in initrd during head_32.S in 32bit flat mode.

So need acpi_initrd_override_find could take phys directly.

The patch description doesn't explain even half of what's going on.

hope HPA could understand.

Access initrd before relocate_initrd and init_memory mapping.

I really hope the changelogs were better. Eh well...

Quoted 15 lines
Quoted 14 lines

drivers/acpi/osl.c u8 __init acpi_table_checksum(u8 *buffer, u32 length) · line 565

Quoted 11 lines
drivers/acpi/osl.c +0 -11
-/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
-static const char * const table_sigs[] = {
-     ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
-     ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
-     ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
-     ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
-     ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
-     ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
-     ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
-     ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
-     ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };

Why is this table made a stack variable? What's the benefit of doing that?

Quoted 4 lines
Quoted 1 line

so I do need to switch global variables to phys and access it.

I can't really understand what your response means. Can you please elaborate?

sorry, I missed NOT.

so I do NOT need to switch global variables from kernel virtual addr to phys address and access it
in 32bit flat mode.

Quoted 11 lines
Quoted 11 lines
Quoted 10 lines

Is it really necessary to make the function take both virtual and physical addresses? Can't we just make the function take phys_addr_t and update everyone to call with physaddr? Also @is_phys isn't simple address switch. It also changes error reporting. If you're gonna keep @is_phys, let's at least write up a function comment explaining what's going on and why we need it. But, really, if at all possible, let's change the function to take single type of argument and predicate error message printing on something else (e.g. early printk initialized or whatever).

Quoted 4 lines
Quoted 2 lines

yes, one for 32bit from head_32.S, phys.
one for 64bit from head64.c. with _va.

head64.c can't call with phys? Why not?

HPA's #PF set up page table only handle kernel low mapping address.

and after reset_early_page_tables, only kernel high mapping address is there. and other low mapping will be supported via #PF handler.

Quoted 8 lines
Quoted 4 lines

Not sure if I could use early_printk from head_32.S, as Fenghua does not print out
from microcode updating early in the same parts.

ISTR it works but it doens't have to (although it would be much nicer if it did). You can test whether printk is online and skip if it isn't online yet.

ok, will give it try.

Thanks

Yinghai

#23 lore raw

Re: [PATCH 04/14] x86, ACPI: make acpi override finding work with 32bit flat mode

Quoted 5 lines · Yinghai Lu
Quoted 5 lines
Quoted 4 lines
Quoted 2 lines

Why is this table made a stack variable? What's the benefit of doing that?

so I do need to switch global variables to phys and access it.

Quoted 8 lines
Quoted 2 lines

I can't really understand what your response means. Can you please elaborate?

sorry, I missed NOT.

so I do NOT need to switch global variables from kernel virtual addr to phys address and access it
in 32bit flat mode.

Ah, okay, so the function is called with a completely different address mode and so you actually want to build the table on stack so that you don't have to flip the address mode for the global address.

Quoted 9 lines
Quoted 4 lines
Quoted 2 lines

yes, one for 32bit from head_32.S, phys.
one for 64bit from head64.c. with _va.

head64.c can't call with phys? Why not?

HPA's #PF set up page table only handle kernel low mapping address.

and after reset_early_page_tables, only kernel high mapping address is there. and other low mapping will be supported via #PF handler.

Okay, it now makes sense. Ah.... You'll definitely need a lot of documentation explanining what's going on.

Thanks.

Signature · 1 line
tejun
maintainer
#24 lore raw

Re: [PATCH 04/14] x86, ACPI: make acpi override finding work with 32bit flat mode

In reply to Yinghai Lu
Quoted 20 lines · On Thu, 7 Mar 2013 22:57:21 -0800 Yinghai Lu <[email protected]> wrote:
Quoted 5 lines
Quoted 5 lines
drivers/acpi/osl.c +0 -0
@@ -552,38 +552,47 @@ u8 __init acpi_table_checksum(u8 *buffer, u32 length)
      return sum;
 }
 
Quoted 14 lines

drivers/acpi/osl.c u8 __init acpi_table_checksum(u8 *buffer, u32 length) · line 565

Quoted 11 lines
drivers/acpi/osl.c +0 -11
-/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
-static const char * const table_sigs[] = {
-     ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
-     ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
-     ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
-     ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
-     ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
-     ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
-     ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
-     ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
-     ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };

Why is this table made a stack variable? What's the benefit of doing that?

Quoted 1 line

so I do need to switch global variables to phys and access it.

What Tejun means is that it should be marked "static" within acpi_initrd_override(), so we don't have to build a copy on the stack at runtime each time acpi_initrd_override() is called.

While we're there, it should be __initdata also.

#25 lore raw

Re: [PATCH 04/14] x86, ACPI: make acpi override finding work with 32bit flat mode

In reply to Yinghai Lu

Yinghai,

Quoted 9 lines · Yinghai Lu
Quoted 6 lines · Tejun Heo
Quoted 3 lines · Yinghai Lu

We will find acpi tables in initrd during head_32.S in 32bit flat mode.

So need acpi_initrd_override_find could take phys directly.

The patch description doesn't explain even half of what's going on.

hope HPA could understand.

What the heck? Is HPA your personal decryptor?

I'm really tired of this nonsense. There is a track record of people complaining about your completely useless and sloppy changelogs and your unwillingness to properly explain and discuss your patches.

Just to make it clear. We all are able and willing to cope with developers who are not native english speakers and have limited language skills. I'm rewriting changelogs on a regular base without complaining about that.

But that's not the problem at hand. I met you personally at KS and found out that your english skills are not those of the random Chinese person. You just prefer to hide your excellent language skills behind your Chinese name.

That's an utter waste of time and resources!

Please grow up and use your language and technical skills in a way which does not offend the people you need to interact with.

Seriously, if you can't convince yourself that a proper communication with maintainers and other developers is a primary task, please don't be surprised if you end up on the /dev/null filters and auto-NAK bots of quite a bunch of affected people.

That would be a sad outcome, really. But that's solely your decision.

Thanks,

tglx

author
#26 lore raw

PATCH 5/14 x86, ACPI: Find acpi tables in initrd early at head_32.S/head64.c

In reply to Yinghai Lu

head64.c could use #PF handler set page table to access initrd before mapping and relocating.

head_32.S could use 32bit flat mode to access initrd before mapping and relocating.

Cc Thomas Renninger <[email protected]>
Cc Pekka Enberg <[email protected]>
Cc Jacob Shin <[email protected]>
Cc Rafael J. Wysocki <[email protected]>
---
 arch/x86/include/asm/setup.h |    2 ++
 arch/x86/kernel/head64.c     |    2 ++
 arch/x86/kernel/head_32.S    |    4 ++++
 arch/x86/kernel/setup.c      |   28 ++++++++++++++++++++++++++--
 4 files changed, 34 insertions(+), 2 deletions(-)
arch/x86/include/asm/setup.h +2 -0
index b7bf350..b09db26 100644
@@ -42,6 +42,8 @@ extern void visws_early_detect(void);
 static inline void visws_early_detect(void) { }
 #endif
 
+void x86_acpi_override_find(void);
+
 extern unsigned long saved_video_mode;
 
 extern void reserve_standard_io_resources(void);
arch/x86/kernel/head64.c +2 -0
index c5e403f..a31bc63 100644
@@ -174,6 +174,8 @@ void __init x86_64_start_kernel(char * real_mode_data)
 	if (console_loglevel == 10)
 		early_printk("Kernel alive\n");
 
+	x86_acpi_override_find();
+
 	clear_page(init_level4_pgt);
 	/* set init_level4_pgt kernel high mapping*/
 	init_level4_pgt[511] = early_level4_pgt[511];
arch/x86/kernel/head_32.S +4 -0
index 73afd11..ca08f0e 100644
@@ -149,6 +149,10 @@ ENTRY(startup_32)
 	call load_ucode_bsp
 #endif
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+	call x86_acpi_override_find
+#endif
+
 /*
  * Initialize page tables.  This creates a PDE and a set of page
  * tables, which are located immediately beyond __brk_base.  The variable
arch/x86/kernel/setup.c +26 -2
index 668e658..d43545a 100644
@@ -424,6 +424,32 @@ static void __init reserve_initrd(void)
 }
 #endif /* CONFIG_BLK_DEV_INITRD */
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+void __init x86_acpi_override_find(void)
+{
+	unsigned long ramdisk_image, ramdisk_size;
+	unsigned char *p = NULL;
+
+#ifdef CONFIG_X86_32
+	struct boot_params *boot_params_p;
+
+	boot_params_p = (struct boot_params *)__pa_symbol(&boot_params);
+	ramdisk_image = boot_params_p->hdr.ramdisk_image;
+	ramdisk_size  = boot_params_p->hdr.ramdisk_size;
+	p = (unsigned char *)ramdisk_image;
+	acpi_initrd_override_find(p, ramdisk_size, true);
+#else
+	ramdisk_image = get_ramdisk_image();
+	ramdisk_size  = get_ramdisk_size();
+	if (ramdisk_image)
+		p = __va(ramdisk_image);
+	acpi_initrd_override_find(p, ramdisk_size, false);
+#endif
+}
+#else
+void __init x86_acpi_override_find(void) { }
+#endif
+
 static void __init parse_setup_data(void)
 {
 	struct setup_data *data;
@@ -1092,8 +1118,6 @@ void __init setup_arch(char **cmdline_p)
 
 	reserve_initrd();
 
-	acpi_initrd_override_find((void *)initrd_start,
-					initrd_end - initrd_start, false);
 	acpi_initrd_override_copy();
 
 	reserve_crashkernel();
Signature · 1 line
1.7.10.4
#27 lore raw

Re: [PATCH 05/14] x86, ACPI: Find acpi tables in initrd early at head_32.S/head64.c

arch/x86/kernel/head_32.S ENTRY(startup_32) · line 154

Quoted 11 lines · Yinghai Lu
arch/x86/kernel/head_32.S +3 -0
index 73afd11..ca08f0e 100644
@@ -149,6 +149,10 @@ ENTRY(startup_32)
 	call load_ucode_bsp
 #endif
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+	call x86_acpi_override_find
+#endif

The function is always defined. We can probalby lose ifdef here?

Also, does it really have to be called from head_32.S? No way this can be done after entering C code? It would be great if you can explain overall design choices in the head message (and important patches).

Quoted 22 lines
arch/x86/kernel/setup.c +14 -0
index 668e658..d43545a 100644
@@ -424,6 +424,32 @@ static void __init reserve_initrd(void)
 }
 #endif /* CONFIG_BLK_DEV_INITRD */
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+void __init x86_acpi_override_find(void)
+{
+	unsigned long ramdisk_image, ramdisk_size;
+	unsigned char *p = NULL;
+
+#ifdef CONFIG_X86_32
+	struct boot_params *boot_params_p;
+
+	boot_params_p = (struct boot_params *)__pa_symbol(&boot_params);
+	ramdisk_image = boot_params_p->hdr.ramdisk_image;
+	ramdisk_size  = boot_params_p->hdr.ramdisk_size;
+	p = (unsigned char *)ramdisk_image;
+	acpi_initrd_override_find(p, ramdisk_size, true);

arch/x86/kernel/setup.c static void __init reserve_initrd(void) · line 450

Quoted 10 lines
arch/x86/kernel/setup.c +10 -0
+#else
+	ramdisk_image = get_ramdisk_image();
+	ramdisk_size  = get_ramdisk_size();
+	if (ramdisk_image)
+		p = __va(ramdisk_image);
+	acpi_initrd_override_find(p, ramdisk_size, false);
+#endif
+}
+#else
+void __init x86_acpi_override_find(void) { }

And add a comment here why we're not doing static inline for the dummy function?

Thanks.

Signature · 1 line
tejun
author
#28 lore raw

Re: [PATCH 05/14] x86, ACPI: Find acpi tables in initrd early at head_32.S/head64.c

Quoted 9 lines · Tejun Heo
Quoted 8 lines · Yinghai Lu
arch/x86/kernel/head_32.S +0 -0
index 73afd11..ca08f0e 100644
@@ -149,6 +149,10 @@ ENTRY(startup_32)
      call load_ucode_bsp
 #endif
 
Quoted 5 lines

arch/x86/kernel/head_32.S ENTRY(startup_32) · line 154

Quoted 3 lines
arch/x86/kernel/head_32.S +3 -0
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+     call x86_acpi_override_find
+#endif

The function is always defined. We can probalby lose ifdef here?

just mimic microcode updating again.

Quoted 5 lines

Also, does it really have to be called from head_32.S? No way this can be done after entering C code? It would be great if you can explain overall design choices in the head message (and important patches).

have to be with head_32.S and it is with 32bit flat mode, so could access 4G blow without setting page table.

Will try add to more in the change log.

Quoted 36 lines
Quoted 23 lines
arch/x86/kernel/setup.c +14 -0
index 668e658..d43545a 100644
@@ -424,6 +424,32 @@ static void __init reserve_initrd(void)
 }
 #endif /* CONFIG_BLK_DEV_INITRD */
 
+#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
+void __init x86_acpi_override_find(void)
+{
+     unsigned long ramdisk_image, ramdisk_size;
+     unsigned char *p = NULL;
+
+#ifdef CONFIG_X86_32
+     struct boot_params *boot_params_p;
+
+     boot_params_p = (struct boot_params *)__pa_symbol(&boot_params);
+     ramdisk_image = boot_params_p->hdr.ramdisk_image;
+     ramdisk_size  = boot_params_p->hdr.ramdisk_size;
+     p = (unsigned char *)ramdisk_image;
+     acpi_initrd_override_find(p, ramdisk_size, true);

arch/x86/kernel/setup.c static void __init reserve_initrd(void) · line 450

Quoted 10 lines
arch/x86/kernel/setup.c +10 -0
+#else
+     ramdisk_image = get_ramdisk_image();
+     ramdisk_size  = get_ramdisk_size();
+     if (ramdisk_image)
+             p = __va(ramdisk_image);
+     acpi_initrd_override_find(p, ramdisk_size, false);
+#endif
+}
+#else
+void __init x86_acpi_override_find(void) { }

And add a comment here why we're not doing static inline for the dummy function?

...

#29 lore raw

Re: [PATCH 05/14] x86, ACPI: Find acpi tables in initrd early at head_32.S/head64.c

Quoted 9 lines · Yinghai Lu
Quoted 4 lines

Also, does it really have to be called from head_32.S? No way this can be done after entering C code? It would be great if you can explain overall design choices in the head message (and important patches).

have to be with head_32.S and it is with 32bit flat mode, so could access 4G blow without setting page table.

Will try add to more in the change log.

Yes, please. In the comment too.

Signature · 1 line
tejun
author
#30 lore raw

PATCH 6/14 x86, mm, numa: Move successful path handling code later

In reply to Yinghai Lu

We could move setup_node_data() and numa_init_array() calling out numa_init() to make numa_init() small.

Those functions only need to be called for success path, and only call them one time in x86_numa_init().

So later we could split parse numa info to two stages. early one will be before init_mem_mapping.

---
 arch/x86/mm/numa.c |   68 ++++++++++++++++++++++++++++------------------------
 1 file changed, 37 insertions(+), 31 deletions(-)
arch/x86/mm/numa.c +37 -31
index 72fe01e..24c20f0 100644
@@ -480,7 +480,7 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
 static int __init numa_register_memblks(struct numa_meminfo *mi)
 {
 	unsigned long uninitialized_var(pfn_align);
-	int i, nid;
+	int i;
 
 	/* Account for nodes with cpus and no memory */
 	node_possible_map = numa_nodes_parsed;
@@ -509,24 +509,6 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
 	if (!numa_meminfo_cover_memory(mi))
 		return -EINVAL;
 
-	/* Finally register nodes. */
-	for_each_node_mask(nid, node_possible_map) {
-		u64 start = PFN_PHYS(max_pfn);
-		u64 end = 0;
-
-		for (i = 0; i < mi->nr_blks; i++) {
-			if (nid != mi->blk[i].nid)
-				continue;
-			start = min(mi->blk[i].start, start);
-			end = max(mi->blk[i].end, end);
-		}
-
-		if (start < end)
-			setup_node_data(nid, start, end);
-	}
-
-	/* Dump memblock with node info and return. */
-	memblock_dump_all();
 	return 0;
 }
 
@@ -580,15 +562,6 @@ static int __init numa_init(int (*init_func)(void))
 	if (ret < 0)
 		return ret;
 
-	for (i = 0; i < nr_cpu_ids; i++) {
-		int nid = early_cpu_to_node(i);
-
-		if (nid == NUMA_NO_NODE)
-			continue;
-		if (!node_online(nid))
-			numa_clear_node(i);
-	}
-	numa_init_array();
 	return 0;
 }
 
@@ -623,22 +596,55 @@ static int __init dummy_numa_init(void)
  */
 void __init x86_numa_init(void)
 {
+	int i, nid;
+	struct numa_meminfo *mi = &numa_meminfo;
+
 	if (!numa_off) {
 #ifdef CONFIG_X86_NUMAQ
 		if (!numa_init(numaq_numa_init))
-			return;
+			goto out;
 #endif
 #ifdef CONFIG_ACPI_NUMA
 		if (!numa_init(x86_acpi_numa_init))
-			return;
+			goto out;
 #endif
 #ifdef CONFIG_AMD_NUMA
 		if (!numa_init(amd_numa_init))
-			return;
+			goto out;
 #endif
 	}
 
 	numa_init(dummy_numa_init);
+
+out:
+	/* Finally register nodes. */
+	for_each_node_mask(nid, node_possible_map) {
+		u64 start = PFN_PHYS(max_pfn);
+		u64 end = 0;
+
+		for (i = 0; i < mi->nr_blks; i++) {
+			if (nid != mi->blk[i].nid)
+				continue;
+			start = min(mi->blk[i].start, start);
+			end = max(mi->blk[i].end, end);
+		}
+
+		if (start < end)
+			setup_node_data(nid, start, end);
+	}
+
+	/* Dump memblock with node info */
+	memblock_dump_all();
+
+	for (i = 0; i < nr_cpu_ids; i++) {
+		int nid = early_cpu_to_node(i);
+
+		if (nid == NUMA_NO_NODE)
+			continue;
+		if (!node_online(nid))
+			numa_clear_node(i);
+	}
+	numa_init_array();
 }
 
 static __init int find_near_online_node(int node)
Signature · 1 line
1.7.10.4
#31 lore raw

Re: [PATCH 06/14] x86, mm, numa: Move successful path handling code later

Quoted 1 line

static int __init numa_register_memblks(struct numa_meminfo *mi)

After this patch, the above name is a bit misleading, I think.

Quoted 1 line

+out:

Maybe register: would fit better?

arch/x86/mm/numa.c static int __init dummy_numa_init(void) · line 622

Quoted 3 lines
arch/x86/mm/numa.c +3 -0
+	/* Finally register nodes. */
+	for_each_node_mask(nid, node_possible_map) {
+		u64 start = PFN_PHYS(max_pfn);

Thanks.

Signature · 1 line
tejun
author
#32 lore raw

Re: [PATCH 06/14] x86, mm, numa: Move successful path handling code later

Quoted 3 lines · Tejun Heo
Quoted 1 line

static int __init numa_register_memblks(struct numa_meminfo *mi)

After this patch, the above name is a bit misleading, I think.

later i changed it to numa_check_memblks()

Thanks

Yinghai

author
#33 lore raw

PATCH 7/14 x86, mm, numa: call numa_meminfo_cover_memory() early

In reply to Yinghai Lu

We do not need to use nid in memblock to find out absent pages.

So could move that numa_meminfo_cover_memory() early before set memblock nid.

Also could make __absent_pages_in_range() to static and use absent_pages_in_range() directly.

Later will only set memblock nid one time on successful path.

---
 arch/x86/mm/numa.c |    7 ++++---
 include/linux/mm.h |    2 --
 mm/page_alloc.c    |    2 +-
 3 files changed, 5 insertions(+), 6 deletions(-)
arch/x86/mm/numa.c +4 -3
index 24c20f0..6df5028 100644
@@ -460,7 +460,7 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
 		u64 s = mi->blk[i].start >> PAGE_SHIFT;
 		u64 e = mi->blk[i].end >> PAGE_SHIFT;
 		numaram += e - s;
-		numaram -= __absent_pages_in_range(mi->blk[i].nid, s, e);
+		numaram -= absent_pages_in_range(s, e);
 		if ((s64)numaram < 0)
 			numaram = 0;
 	}
@@ -488,6 +488,9 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
 	if (WARN_ON(nodes_empty(node_possible_map)))
 		return -EINVAL;
 
+	if (!numa_meminfo_cover_memory(mi))
+		return -EINVAL;
+
 	for (i = 0; i < mi->nr_blks; i++) {
 		struct numa_memblk *mb = &mi->blk[i];
 		memblock_set_node(mb->start, mb->end - mb->start, mb->nid);
@@ -506,8 +509,6 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
 		return -EINVAL;
 	}
 #endif
-	if (!numa_meminfo_cover_memory(mi))
-		return -EINVAL;
 
 	return 0;
 }
include/linux/mm.h +0 -2
index 7acc9dc..2ae2050 100644
@@ -1324,8 +1324,6 @@ extern void free_initmem(void);
  */
 extern void free_area_init_nodes(unsigned long *max_zone_pfn);
 unsigned long node_map_pfn_alignment(void);
-unsigned long __absent_pages_in_range(int nid, unsigned long start_pfn,
-						unsigned long end_pfn);
 extern unsigned long absent_pages_in_range(unsigned long start_pfn,
 						unsigned long end_pfn);
 extern void get_pfn_range_for_nid(unsigned int nid,
mm/page_alloc.c +1 -1
index 8fcced7..580d919 100644
@@ -4356,7 +4356,7 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid,
  * Return the number of holes in a range on a node. If nid is MAX_NUMNODES,
  * then all holes in the requested range will be accounted for.
  */
-unsigned long __meminit __absent_pages_in_range(int nid,
+static unsigned long __meminit __absent_pages_in_range(int nid,
 				unsigned long range_start_pfn,
 				unsigned long range_end_pfn)
 {
Signature · 1 line
1.7.10.4
author
#34 lore raw

PATCH 8/14 x86, mm, numa: use numa_meminfo to check node_map_pfn alignment

In reply to Yinghai Lu

We could use numa_meminfo directly instead of memblock nid.

So we could move down set memblock nid down and only do it one time for successful path

Move node_map_pfn_alignment() to arch/x86/mm as no other user for it.

---
 arch/x86/mm/numa.c |   76 +++++++++++++++++++++++++++++++++++++++++++++-------
 include/linux/mm.h |    1 -
 mm/page_alloc.c    |   50 ----------------------------------
 3 files changed, 67 insertions(+), 60 deletions(-)
arch/x86/mm/numa.c +67 -9
index 6df5028..b8cc248 100644
@@ -477,9 +477,69 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
 	return true;
 }
 
+/**
+ * node_map_pfn_alignment - determine the maximum internode alignment
+ *
+ * This function should be called after node map is populated and sorted.
+ * It calculates the maximum power of two alignment which can distinguish
+ * all the nodes.
+ *
+ * For example, if all nodes are 1GiB and aligned to 1GiB, the return value
+ * would indicate 1GiB alignment with (1 << (30 - PAGE_SHIFT)).  If the
+ * nodes are shifted by 256MiB, 256MiB.  Note that if only the last node is
+ * shifted, 1GiB is enough and this function will indicate so.
+ *
+ * This is used to test whether pfn -> nid mapping of the chosen memory
+ * model has fine enough granularity to avoid incorrect mapping for the
+ * populated node map.
+ *
+ * Returns the determined alignment in pfn's.  0 if there is no alignment
+ * requirement (single node).
+ */
+#ifdef NODE_NOT_IN_PAGE_FLAGS
+static unsigned long __init node_map_pfn_alignment(struct numa_meminfo *mi)
+{
+	unsigned long accl_mask = 0, last_end = 0;
+	unsigned long start, end, mask;
+	int last_nid = -1;
+	int i, nid;
+
+	for (i = 0; i < mi->nr_blks; i++) {
+		start = mi->blk[i].start >> PAGE_SHIFT;
+		end = mi->blk[i].end >> PAGE_SHIFT;
+		nid = mi->blk[i].nid;
+		if (!start || last_nid < 0 || last_nid == nid) {
+			last_nid = nid;
+			last_end = end;
+			continue;
+		}
+
+		/*
+		 * Start with a mask granular enough to pin-point to the
+		 * start pfn and tick off bits one-by-one until it becomes
+		 * too coarse to separate the current node from the last.
+		 */
+		mask = ~((1 << __ffs(start)) - 1);
+		while (mask && last_end <= (start & (mask << 1)))
+			mask <<= 1;
+
+		/* accumulate all internode masks */
+		accl_mask |= mask;
+	}
+
+	/* convert mask to number of pages */
+	return ~accl_mask + 1;
+}
+#else
+static unsigned long __init node_map_pfn_alignment(struct numa_meminfo *mi)
+{
+	return 0;
+}
+#endif
+
 static int __init numa_register_memblks(struct numa_meminfo *mi)
 {
-	unsigned long uninitialized_var(pfn_align);
+	unsigned long pfn_align;
 	int i;
 
 	/* Account for nodes with cpus and no memory */
@@ -491,24 +551,22 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
 	if (!numa_meminfo_cover_memory(mi))
 		return -EINVAL;
 
-	for (i = 0; i < mi->nr_blks; i++) {
-		struct numa_memblk *mb = &mi->blk[i];
-		memblock_set_node(mb->start, mb->end - mb->start, mb->nid);
-	}
-
 	/*
 	 * If sections array is gonna be used for pfn -> nid mapping, check
 	 * whether its granularity is fine enough.
 	 */
-#ifdef NODE_NOT_IN_PAGE_FLAGS
-	pfn_align = node_map_pfn_alignment();
+	pfn_align = node_map_pfn_alignment(mi);
 	if (pfn_align && pfn_align < PAGES_PER_SECTION) {
 		printk(KERN_WARNING "Node alignment %LuMB < min %LuMB, rejecting NUMA config\n",
 		       PFN_PHYS(pfn_align) >> 20,
 		       PFN_PHYS(PAGES_PER_SECTION) >> 20);
 		return -EINVAL;
 	}
-#endif
+
+	for (i = 0; i < mi->nr_blks; i++) {
+		struct numa_memblk *mb = &mi->blk[i];
+		memblock_set_node(mb->start, mb->end - mb->start, mb->nid);
+	}
 
 	return 0;
 }
include/linux/mm.h +0 -1
index 2ae2050..1c79b10 100644
@@ -1323,7 +1323,6 @@ extern void free_initmem(void);
  * CONFIG_HAVE_MEMBLOCK_NODE_MAP.
  */
 extern void free_area_init_nodes(unsigned long *max_zone_pfn);
-unsigned long node_map_pfn_alignment(void);
 extern unsigned long absent_pages_in_range(unsigned long start_pfn,
 						unsigned long end_pfn);
 extern void get_pfn_range_for_nid(unsigned int nid,
mm/page_alloc.c +0 -50

56 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#35 lore raw

Re: [PATCH 08/14] x86, mm, numa: use numa_meminfo to check node_map_pfn alignment

Quoted 6 lines · Yinghai Lu

We could use numa_meminfo directly instead of memblock nid.

So we could move down set memblock nid down and only do it one time for successful path

Move node_map_pfn_alignment() to arch/x86/mm as no other user for it.

Please don't move and update in the same patch. It makes it difficult to review what's really changing.

Thanks.

Signature · 1 line
tejun
author
#36 lore raw

Re: [PATCH 08/14] x86, mm, numa: use numa_meminfo to check node_map_pfn alignment

Quoted 10 lines · Tejun Heo
Quoted 6 lines · Yinghai Lu

We could use numa_meminfo directly instead of memblock nid.

So we could move down set memblock nid down and only do it one time for successful path

Move node_map_pfn_alignment() to arch/x86/mm as no other user for it.

Please don't move and update in the same patch. It makes it difficult to review what's really changing.

ok, will make it two patches, one for moving and one for changing to numa_meminfo.

Thanks

Yinghai

author
#37 lore raw

PATCH 9/14 x86, mm, numa: set memblock nid later

In reply to Yinghai Lu

Only set memblock nid one time.

Also rename numa_register_memblks to numa_check_memblks() after move set memblock nid out.

---
 arch/x86/mm/numa.c |   16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)
arch/x86/mm/numa.c +7 -9
index b8cc248..e875c2b 100644
@@ -537,10 +537,9 @@ static unsigned long __init node_map_pfn_alignment(struct numa_meminfo *mi)
 }
 #endif
 
-static int __init numa_register_memblks(struct numa_meminfo *mi)
+static int __init numa_check_memblks(struct numa_meminfo *mi)
 {
 	unsigned long pfn_align;
-	int i;
 
 	/* Account for nodes with cpus and no memory */
 	node_possible_map = numa_nodes_parsed;
@@ -563,11 +562,6 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
 		return -EINVAL;
 	}
 
-	for (i = 0; i < mi->nr_blks; i++) {
-		struct numa_memblk *mb = &mi->blk[i];
-		memblock_set_node(mb->start, mb->end - mb->start, mb->nid);
-	}
-
 	return 0;
 }
 
@@ -605,7 +599,6 @@ static int __init numa_init(int (*init_func)(void))
 	nodes_clear(node_possible_map);
 	nodes_clear(node_online_map);
 	memset(&numa_meminfo, 0, sizeof(numa_meminfo));
-	WARN_ON(memblock_set_node(0, ULLONG_MAX, MAX_NUMNODES));
 	numa_reset_distance();
 
 	ret = init_func();
@@ -617,7 +610,7 @@ static int __init numa_init(int (*init_func)(void))
 
 	numa_emulation(&numa_meminfo, numa_distance_cnt);
 
-	ret = numa_register_memblks(&numa_meminfo);
+	ret = numa_check_memblks(&numa_meminfo);
 	if (ret < 0)
 		return ret;
 
@@ -676,6 +669,11 @@ void __init x86_numa_init(void)
 	numa_init(dummy_numa_init);
 
 out:
+	for (i = 0; i < mi->nr_blks; i++) {
+		struct numa_memblk *mb = &mi->blk[i];
+		memblock_set_node(mb->start, mb->end - mb->start, mb->nid);
+	}
+
 	/* Finally register nodes. */
 	for_each_node_mask(nid, node_possible_map) {
 		u64 start = PFN_PHYS(max_pfn);
Signature · 1 line
1.7.10.4
#38 lore raw

Re: [PATCH 09/14] x86, mm, numa: set memblock nid later

Quoted 1 line · Yinghai Lu

Only set memblock nid one time.

Would be awesome if the description explains why we're doing this and why we're allowed to do this now.

Quoted 2 lines

Also rename numa_register_memblks to numa_check_memblks() after move set memblock nid out.

Ah... so, it's getting renamed here.

Signature · 1 line
tejun
author
#39 lore raw

Re: [PATCH 09/14] x86, mm, numa: set memblock nid later

Quoted 5 lines · Tejun Heo
Quoted 1 line · Yinghai Lu

Only set memblock nid one time.

Would be awesome if the description explains why we're doing this and why we're allowed to do this now.

will add more:

set memblock nid will cause membock layout change like array could be doubled. and we do not have current memblock limit set, so will put down under 1M and could
use too much under 1M.
And for fallback path, we can avoid restore memblock and remerge action.

After We use numa_meminfo nid for checking, we don't need to send it again.

Thanks

Yinghai

author
#40 lore raw

PATCH 10/14 x86, mm, numa: Move emulation handling down.

In reply to Yinghai Lu

It will need to allocate buffer for new numa_meminfo and distance matrix, so move it down.

Also we change the behavoir:
before this patch, if user input wrong data in command line, it will fall back to next numa or disabling numa.
after this patch, if user input wrong data in command line, it will stay with numa info from probing before, like acpi srat or amd_numa.

Cc Tejun Heo <[email protected]>
Cc David Rientjes <[email protected]>
---
 arch/x86/mm/numa.c           |   15 +++++++++------
 arch/x86/mm/numa_emulation.c |    2 +-
 arch/x86/mm/numa_internal.h  |    2 ++
 3 files changed, 12 insertions(+), 7 deletions(-)
arch/x86/mm/numa.c +9 -6
index e875c2b..ace0370 100644
@@ -537,14 +537,16 @@ static unsigned long __init node_map_pfn_alignment(struct numa_meminfo *mi)
 }
 #endif
 
-static int __init numa_check_memblks(struct numa_meminfo *mi)
+
+int __init numa_check_memblks(struct numa_meminfo *mi)
 {
+	nodemask_t tmp_node_map;
 	unsigned long pfn_align;
 
 	/* Account for nodes with cpus and no memory */
-	node_possible_map = numa_nodes_parsed;
-	numa_nodemask_from_meminfo(&node_possible_map, mi);
-	if (WARN_ON(nodes_empty(node_possible_map)))
+	tmp_node_map = numa_nodes_parsed;
+	numa_nodemask_from_meminfo(&tmp_node_map, mi);
+	if (WARN_ON(nodes_empty(tmp_node_map)))
 		return -EINVAL;
 
 	if (!numa_meminfo_cover_memory(mi))
@@ -562,6 +564,7 @@ static int __init numa_check_memblks(struct numa_meminfo *mi)
 		return -EINVAL;
 	}
 
+	node_possible_map = tmp_node_map;
 	return 0;
 }
 
@@ -608,8 +611,6 @@ static int __init numa_init(int (*init_func)(void))
 	if (ret < 0)
 		return ret;
 
-	numa_emulation(&numa_meminfo, numa_distance_cnt);
-
 	ret = numa_check_memblks(&numa_meminfo);
 	if (ret < 0)
 		return ret;
@@ -669,6 +670,8 @@ void __init x86_numa_init(void)
 	numa_init(dummy_numa_init);
 
 out:
+	numa_emulation(&numa_meminfo, numa_distance_cnt);
+
 	for (i = 0; i < mi->nr_blks; i++) {
 		struct numa_memblk *mb = &mi->blk[i];
 		memblock_set_node(mb->start, mb->end - mb->start, mb->nid);
arch/x86/mm/numa_emulation.c +1 -1
index dbbbb47..5a0433d 100644
@@ -348,7 +348,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
 	if (ret < 0)
 		goto no_emu;
 
-	if (numa_cleanup_meminfo(&ei) < 0) {
+	if (numa_cleanup_meminfo(&ei) < 0 || numa_check_memblks(&ei) < 0) {
 		pr_warning("NUMA: Warning: constructed meminfo invalid, disabling emulation\n");
 		goto no_emu;
 	}
arch/x86/mm/numa_internal.h +2 -0
index ad86ec9..bb2fbcc 100644
@@ -21,6 +21,8 @@ void __init numa_reset_distance(void);
 
 void __init x86_numa_init(void);
 
+int __init numa_check_memblks(struct numa_meminfo *mi);
+
 #ifdef CONFIG_NUMA_EMU
 void __init numa_emulation(struct numa_meminfo *numa_meminfo,
 			   int numa_dist_cnt);
Signature · 1 line
1.7.10.4
#41 lore raw

Re: [PATCH 10/14] x86, mm, numa: Move emulation handling down.

Quoted 18 lines · Yinghai Lu
arch/x86/mm/numa.c +6 -4
-static int __init numa_check_memblks(struct numa_meminfo *mi)
+
+int __init numa_check_memblks(struct numa_meminfo *mi)
 {
+	nodemask_t tmp_node_map;
 	unsigned long pfn_align;
 
 	/* Account for nodes with cpus and no memory */
-	node_possible_map = numa_nodes_parsed;
-	numa_nodemask_from_meminfo(&node_possible_map, mi);
-	if (WARN_ON(nodes_empty(node_possible_map)))
+	tmp_node_map = numa_nodes_parsed;
+	numa_nodemask_from_meminfo(&tmp_node_map, mi);
+	if (WARN_ON(nodes_empty(tmp_node_map)))
 		return -EINVAL;
 
 	if (!numa_meminfo_cover_memory(mi))

arch/x86/mm/numa.c static int __init numa_check_memblks(struct numa_meminfo *mi) · line 567

Quoted 4 lines
arch/x86/mm/numa.c +1 -0
@@ -562,6 +564,7 @@ static int __init numa_check_memblks(struct numa_meminfo *mi)
 		return -EINVAL;
 	}
 
+	node_possible_map = tmp_node_map;

Hmmm.... it's kinda nasty to have a side effect like the above for a function named numa_check_memblks(). Maybe we can move this to the caller or name the function to make it clear that some global state is being updated?

Quoted 23 lines
arch/x86/mm/numa.c +2 -2
@@ -608,8 +611,6 @@ static int __init numa_init(int (*init_func)(void))
 	if (ret < 0)
 		return ret;
 
-	numa_emulation(&numa_meminfo, numa_distance_cnt);
-
 	ret = numa_check_memblks(&numa_meminfo);
 	if (ret < 0)
 		return ret;
@@ -669,6 +670,8 @@ void __init x86_numa_init(void)
 	numa_init(dummy_numa_init);
 
 out:
+	numa_emulation(&numa_meminfo, numa_distance_cnt);
+
 	for (i = 0; i < mi->nr_blks; i++) {
 		struct numa_memblk *mb = &mi->blk[i];
 		memblock_set_node(mb->start, mb->end - mb->start, mb->nid);
arch/x86/mm/numa_emulation.c +0 -0
index dbbbb47..5a0433d 100644

arch/x86/mm/numa_emulation.c void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt) · line 354

Quoted 8 lines
arch/x86/mm/numa_emulation.c +1 -1
@@ -348,7 +348,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
 	if (ret < 0)
 		goto no_emu;
 
-	if (numa_cleanup_meminfo(&ei) < 0) {
+	if (numa_cleanup_meminfo(&ei) < 0 || numa_check_memblks(&ei) < 0) {
 		pr_warning("NUMA: Warning: constructed meminfo invalid, disabling emulation\n");
 		goto no_emu;
 	}

Given that acpi is the only mechanism which matters in any modern NUMA machines, I think the re-ordering should be fine.

Thanks.

Signature · 1 line
tejun
author
#42 lore raw

Re: [PATCH 10/14] x86, mm, numa: Move emulation handling down.

Quoted 22 lines · Tejun Heo
Quoted 21 lines · Yinghai Lu
arch/x86/mm/numa.c +6 -4
-static int __init numa_check_memblks(struct numa_meminfo *mi)
+
+int __init numa_check_memblks(struct numa_meminfo *mi)
 {
+     nodemask_t tmp_node_map;
      unsigned long pfn_align;
 
      /* Account for nodes with cpus and no memory */
-     node_possible_map = numa_nodes_parsed;
-     numa_nodemask_from_meminfo(&node_possible_map, mi);
-     if (WARN_ON(nodes_empty(node_possible_map)))
+     tmp_node_map = numa_nodes_parsed;
+     numa_nodemask_from_meminfo(&tmp_node_map, mi);
+     if (WARN_ON(nodes_empty(tmp_node_map)))
              return -EINVAL;
 
      if (!numa_meminfo_cover_memory(mi))
@@ -562,6 +564,7 @@ static int __init numa_check_memblks(struct numa_meminfo *mi)
              return -EINVAL;
      }
 
Quoted 6 lines

arch/x86/mm/numa.c static int __init numa_check_memblks(struct numa_meminfo *mi) · line 567

Quoted 1 line
arch/x86/mm/numa.c +1 -0
+     node_possible_map = tmp_node_map;

Hmmm.... it's kinda nasty to have a side effect like the above for a function named numa_check_memblks(). Maybe we can move this to the caller or name the function to make it clear that some global state is being updated?

ok, will split it out for node_possibe_map updating.

Quoted 27 lines
Quoted 27 lines
arch/x86/mm/numa.c +2 -2
@@ -608,8 +611,6 @@ static int __init numa_init(int (*init_func)(void))
      if (ret < 0)
              return ret;
 
-     numa_emulation(&numa_meminfo, numa_distance_cnt);
-
      ret = numa_check_memblks(&numa_meminfo);
      if (ret < 0)
              return ret;
@@ -669,6 +670,8 @@ void __init x86_numa_init(void)
      numa_init(dummy_numa_init);
 
 out:
+     numa_emulation(&numa_meminfo, numa_distance_cnt);
+
      for (i = 0; i < mi->nr_blks; i++) {
              struct numa_memblk *mb = &mi->blk[i];
              memblock_set_node(mb->start, mb->end - mb->start, mb->nid);
arch/x86/mm/numa_emulation.c +0 -0
index dbbbb47..5a0433d 100644
@@ -348,7 +348,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
      if (ret < 0)
              goto no_emu;
 
Quoted 8 lines

arch/x86/mm/numa_emulation.c void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt) · line 354

Quoted 5 lines
arch/x86/mm/numa_emulation.c +1 -1
-     if (numa_cleanup_meminfo(&ei) < 0) {
+     if (numa_cleanup_meminfo(&ei) < 0 || numa_check_memblks(&ei) < 0) {
              pr_warning("NUMA: Warning: constructed meminfo invalid, disabling emulation\n");
              goto no_emu;
      }

Given that acpi is the only mechanism which matters in any modern NUMA machines, I think the re-ordering should be fine.

Good.

author
#43 lore raw

PATCH 11/14 x86, acpi, numa: split SLIT handling out

In reply to Yinghai Lu

We need to handle slit later, as it need to allocate buffer.

Also we only need srat info before init_mem_mapping.

x86_acpi_numa_init become x86_acpi_numa_init_only_slit x86_acpi_numa_init_no_slit.

---
 arch/x86/include/asm/acpi.h |    3 ++-
 arch/x86/mm/numa.c          |   13 ++++++++++++-
 arch/x86/mm/srat.c          |    8 ++++++--
 drivers/acpi/numa.c         |   22 +++++++++++++++++++---
 include/linux/acpi.h        |    2 ++
 5 files changed, 41 insertions(+), 7 deletions(-)
arch/x86/include/asm/acpi.h +2 -1
index b31bf97..9f171a7 100644
@@ -178,7 +178,8 @@ static inline void disable_acpi(void) { }
 
 #ifdef CONFIG_ACPI_NUMA
 extern int acpi_numa;
-extern int x86_acpi_numa_init(void);
+int x86_acpi_numa_init_no_slit(void);
+void x86_acpi_numa_init_only_slit(void);
 #endif /* CONFIG_ACPI_NUMA */
 
 #define acpi_unlazy_tlb(x)	leave_mm(x)
arch/x86/mm/numa.c +12 -1
index ace0370..23ec6ba 100644
@@ -640,6 +640,10 @@ static int __init dummy_numa_init(void)
 	return 0;
 }
 
+#ifdef CONFIG_ACPI_NUMA
+static bool srat_used __initdata;
+#endif
+
 /**
  * x86_numa_init - Initialize NUMA
  *
@@ -658,8 +662,10 @@ void __init x86_numa_init(void)
 			goto out;
 #endif
 #ifdef CONFIG_ACPI_NUMA
-		if (!numa_init(x86_acpi_numa_init))
+		if (!numa_init(x86_acpi_numa_init_no_slit)) {
+			srat_used = true;
 			goto out;
+		}
 #endif
 #ifdef CONFIG_AMD_NUMA
 		if (!numa_init(amd_numa_init))
@@ -670,6 +676,11 @@ void __init x86_numa_init(void)
 	numa_init(dummy_numa_init);
 
 out:
+#ifdef CONFIG_ACPI_NUMA
+	if (srat_used)
+		x86_acpi_numa_init_only_slit();
+#endif
+
 	numa_emulation(&numa_meminfo, numa_distance_cnt);
 
 	for (i = 0; i < mi->nr_blks; i++) {
arch/x86/mm/srat.c +6 -2
index cdd0da9..47a62b2 100644
@@ -187,11 +187,15 @@ out_err:
 
 void __init acpi_numa_arch_fixup(void) {}
 
-int __init x86_acpi_numa_init(void)
+void __init x86_acpi_numa_init_only_slit(void)
+{
+	acpi_numa_init_only_slit();
+}
+int __init x86_acpi_numa_init_no_slit(void)
 {
 	int ret;
 
-	ret = acpi_numa_init();
+	ret = acpi_numa_init_no_slit();
 	if (ret < 0)
 		return ret;
 	return srat_disabled() ? -EINVAL : 0;
drivers/acpi/numa.c +19 -3
index 33e609f..2215718 100644
@@ -282,7 +282,13 @@ acpi_table_parse_srat(enum acpi_srat_type id,
 					    handler, max_entries);
 }
 
-int __init acpi_numa_init(void)
+void __init acpi_numa_init_only_slit(void)
+{
+	/* SLIT: System Locality Information Table */
+	acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
+}
+
+static int __init __acpi_numa_init(bool with_slit)
 {
 	int cnt = 0;
 
@@ -303,8 +309,8 @@ int __init acpi_numa_init(void)
 					    NR_NODE_MEMBLKS);
 	}
 
-	/* SLIT: System Locality Information Table */
-	acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
+	if (with_slit)
+		acpi_numa_init_only_slit();
 
 	acpi_numa_arch_fixup();
 
@@ -315,6 +321,16 @@ int __init acpi_numa_init(void)
 	return 0;
 }
 
+int __init acpi_numa_init(void)
+{
+	return __acpi_numa_init(true);
+}
+
+int __init acpi_numa_init_no_slit(void)
+{
+	return __acpi_numa_init(false);
+}
+
 int acpi_get_pxm(acpi_handle h)
 {
 	unsigned long long pxm;
include/linux/acpi.h +2 -0
index 46a8a89..bfd2852 100644
@@ -86,6 +86,8 @@ int acpi_boot_init (void);
 void acpi_boot_table_init (void);
 int acpi_mps_check (void);
 int acpi_numa_init (void);
+int acpi_numa_init_no_slit(void);
+void acpi_numa_init_only_slit(void);
 
 int acpi_table_init (void);
 int acpi_table_parse(char *id, acpi_tbl_table_handler handler);
Signature · 1 line
1.7.10.4
#44 lore raw

Re: [PATCH 11/14] x86, acpi, numa: split SLIT handling out

drivers/acpi/numa.c acpi_table_parse_srat(enum acpi_srat_type id, · line 293

Quoted 9 lines · Yinghai Lu
drivers/acpi/numa.c +7 -0
+void __init acpi_numa_init_only_slit(void)
+{
+	/* SLIT: System Locality Information Table */
+	acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
+}
+
+static int __init __acpi_numa_init(bool with_slit)
 {
 	int cnt = 0;

Hmmm.... how about just having the following two functions

	acpi_numa_init_srat();
	acpi_numa_init_slit();

and update both x86 and ia64 to use the two functions?

Signature · 1 line
tejun
author
#45 lore raw

Re: [PATCH 11/14] x86, acpi, numa: split SLIT handling out

Quoted 13 lines · Tejun Heo

drivers/acpi/numa.c acpi_table_parse_srat(enum acpi_srat_type id, · line 293

Quoted 9 lines · Yinghai Lu
drivers/acpi/numa.c +7 -0
+void __init acpi_numa_init_only_slit(void)
+{
+     /* SLIT: System Locality Information Table */
+     acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
+}
+
+static int __init __acpi_numa_init(bool with_slit)
 {
      int cnt = 0;

Hmmm.... how about just having the following two functions

Quoted 2 lines
        acpi_numa_init_srat();
        acpi_numa_init_slit();

ok.

Quoted 1 line

and update both x86 and ia64 to use the two functions?

ia64 like to call in this seqence
acpi_numa_init()
parse srat
parse slit
then
acpi_numa_arch_fixup()

in this arch_fixup, it will try to fill dummy distance_matrix.

so would to keep acpi_numa_init ...

#46 lore raw

Re: [PATCH 11/14] x86, acpi, numa: split SLIT handling out

Quoted 10 lines · Yinghai Lu

ia64 like to call in this seqence
acpi_numa_init()
parse srat
parse slit
then
acpi_numa_arch_fixup()

in this arch_fixup, it will try to fill dummy distance_matrix.

so would to keep acpi_numa_init ...

Can't it just call acpi_numa_init_srat() and then init_slit()? What am I missing?

Signature · 1 line
tejun
author
#47 lore raw

Re: [PATCH 11/14] x86, acpi, numa: split SLIT handling out

Quoted 8 lines · Tejun Heo
Quoted 7 lines · Yinghai Lu

ia64 like to call in this seqence
acpi_numa_init()
parse srat
parse slit
then
acpi_numa_arch_fixup()

Quoted 6 lines
Quoted 3 lines

in this arch_fixup, it will try to fill dummy distance_matrix.

so would to keep acpi_numa_init ...

Can't it just call acpi_numa_init_srat() and then init_slit()? What am I missing?

Yes, but need to break acpi_numa_init calling
in arch/ia64/kernel/setup.c

with
acpi_numa_init_srat()
acpi_numa_init_slit()
acpi_numa_arch_fixup()

current code is
acpi_numa_init calling arch_numa_arch_fixup()

Thanks

Yinghai

author
#48 lore raw

PATCH 12/14 x86, mm, numa: Add early_initmem_init() stub

In reply to Yinghai Lu

early_initmem_init() will call early_x86_numa_init().

later will call init_mem_mapping for nodes in it.

Cc Tejun Heo <[email protected]>
Cc Pekka Enberg <[email protected]>
Cc Jacob Shin <[email protected]>
---
 arch/x86/include/asm/page_types.h |    1 +
 arch/x86/kernel/setup.c           |    1 +
 arch/x86/mm/init_32.c             |    3 +++
 arch/x86/mm/init_64.c             |    3 +++
 arch/x86/mm/numa.c                |   23 +++++++++++++++--------
 5 files changed, 23 insertions(+), 8 deletions(-)
arch/x86/include/asm/page_types.h +1 -0
index b012b82..d04dd8c 100644
@@ -55,6 +55,7 @@ bool pfn_range_is_mapped(unsigned long start_pfn, unsigned long end_pfn);
 extern unsigned long init_memory_mapping(unsigned long start,
 					 unsigned long end);
 
+void early_initmem_init(void);
 extern void initmem_init(void);
 
 #endif	/* !__ASSEMBLY__ */
arch/x86/kernel/setup.c +1 -0
index d43545a..c4f1c63 100644
@@ -1133,6 +1133,7 @@ void __init setup_arch(char **cmdline_p)
 
 	early_acpi_boot_init();
 
+	early_initmem_init();
 	initmem_init();
 	memblock_find_dma_reserve();
 
arch/x86/mm/init_32.c +3 -0
index 2d19001..3801962 100644
@@ -660,6 +660,9 @@ void __init find_low_pfn_range(void)
 }
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
+void __init early_initmem_init(void)
+{
+}
 void __init initmem_init(void)
 {
 #ifdef CONFIG_HIGHMEM
arch/x86/mm/init_64.c +3 -0
index 474e28f..218a4e5 100644
@@ -640,6 +640,9 @@ kernel_physical_mapping_init(unsigned long start,
 }
 
 #ifndef CONFIG_NUMA
+void __init early_initmem_init(void)
+{
+}
 void __init initmem_init(void)
 {
 	memblock_set_node(0, (phys_addr_t)ULLONG_MAX, 0);
arch/x86/mm/numa.c +15 -8
index 23ec6ba..643b39a 100644
@@ -651,31 +651,38 @@ static bool srat_used __initdata;
  * last fallback is dummy single node config encomapssing whole memory and
  * never fails.
  */
-void __init x86_numa_init(void)
+static void __init early_x86_numa_init(void)
 {
-	int i, nid;
-	struct numa_meminfo *mi = &numa_meminfo;
-
 	if (!numa_off) {
 #ifdef CONFIG_X86_NUMAQ
 		if (!numa_init(numaq_numa_init))
-			goto out;
+			return;
 #endif
 #ifdef CONFIG_ACPI_NUMA
 		if (!numa_init(x86_acpi_numa_init_no_slit)) {
 			srat_used = true;
-			goto out;
+			return;
 		}
 #endif
 #ifdef CONFIG_AMD_NUMA
 		if (!numa_init(amd_numa_init))
-			goto out;
+			return;
 #endif
 	}
 
 	numa_init(dummy_numa_init);
+}
+
+void __init early_initmem_init(void)
+{
+	early_x86_numa_init();
+}
+
+void __init x86_numa_init(void)
+{
+	int i, nid;
+	struct numa_meminfo *mi = &numa_meminfo;
 
-out:
 #ifdef CONFIG_ACPI_NUMA
 	if (srat_used)
 		x86_acpi_numa_init_only_slit();
Signature · 1 line
1.7.10.4
author
#49 lore raw

PATCH 13/14 x86, mm: Parse numa info early

In reply to Yinghai Lu

Parse numa info at first and store info into numa_meminfo.

call early_initmem_init before init_memory_mapping(), will have numa info ready at first, and will still keep numaq, acpi_numa, amd_numa, dummy fall back sequence.

SLIT and numa emulation handling are still left in initmem_init().

Cc Pekka Enberg <[email protected]>
Cc Jacob Shin <[email protected]>
---
 arch/x86/kernel/setup.c |   24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)
arch/x86/kernel/setup.c +10 -14
index c4f1c63..29a6b94 100644
@@ -1096,13 +1096,21 @@ void __init setup_arch(char **cmdline_p)
 	trim_platform_memory_ranges();
 	trim_low_memory_range();
 
+	/*
+	 * Parse the ACPI tables for possible boot-time SMP configuration.
+	 */
+	acpi_initrd_override_copy();
+	acpi_boot_table_init();
+	early_acpi_boot_init();
+	early_initmem_init();
 	init_mem_mapping();
-
+	memblock.current_limit = get_max_mapped();
 	early_trap_pf_init();
 
+	reserve_initrd();
+
 	setup_real_mode();
 
-	memblock.current_limit = get_max_mapped();
 	dma_contiguous_reserve(0);
 
 	/*
@@ -1116,24 +1124,12 @@ void __init setup_arch(char **cmdline_p)
 	/* Allocate bigger log buffer */
 	setup_log_buf(1);
 
-	reserve_initrd();
-
-	acpi_initrd_override_copy();
-
 	reserve_crashkernel();
 
 	vsmp_init();
 
 	io_delay_init();
 
-	/*
-	 * Parse the ACPI tables for possible boot-time SMP configuration.
-	 */
-	acpi_boot_table_init();
-
-	early_acpi_boot_init();
-
-	early_initmem_init();
 	initmem_init();
 	memblock_find_dma_reserve();
 
Signature · 1 line
1.7.10.4
author
#50 lore raw

PATCH 14/14 x86, mm: Put pagetable on local node ram

In reply to Yinghai Lu

If node with ram is hotplugable, local node mem for page table and vmemmap should be on that node ram.

This patch is some kind of refreshment of

| commit 1411e0ec3123ae4c4ead6bfc9fe3ee5a3ae5c327
| Date:   Mon Dec 27 16:48:17 2010 -0800
|
|    x86-64, numa: Put pgtable to local node memory

That was reverted before.

We have reason to reintroduce it to make memory hotplug work.

Split calling of init_mem_mapping into early_initmem_info for nodes after we get numa info there.

First node will be low range.
Need to rework alloc_low_pages to alloc page table in following order:
BRK, local node, low range

Still only load_cr3 one time, otherwise we would break xen 64bit again.

Cc Tejun Heo <[email protected]>
Cc Pekka Enberg <[email protected]>
Cc Jacob Shin <[email protected]>
Cc Konrad Rzeszutek Wilk <[email protected]>
---
 arch/x86/include/asm/pgtable.h |    2 +-
 arch/x86/kernel/setup.c        |    1 -
 arch/x86/mm/init.c             |   83 ++++++++++++++++++++++------------------
 arch/x86/mm/init_32.c          |    8 ++++
 arch/x86/mm/init_64.c          |    9 +++++
 arch/x86/mm/numa.c             |   56 +++++++++++++++++++++++++++
 6 files changed, 119 insertions(+), 40 deletions(-)
arch/x86/include/asm/pgtable.h +1 -1
index 1e67223..868687c 100644
@@ -621,7 +621,7 @@ static inline int pgd_none(pgd_t pgd)
 #ifndef __ASSEMBLY__
 
 extern int direct_gbpages;
-void init_mem_mapping(void);
+void init_mem_mapping(unsigned long begin, unsigned long end);
 void early_alloc_pgt_buf(void);
 
 /* local pte updates need not use xchg for locking */
arch/x86/kernel/setup.c +0 -1
index 29a6b94..37d993f 100644
@@ -1103,7 +1103,6 @@ void __init setup_arch(char **cmdline_p)
 	acpi_boot_table_init();
 	early_acpi_boot_init();
 	early_initmem_init();
-	init_mem_mapping();
 	memblock.current_limit = get_max_mapped();
 	early_trap_pf_init();
 
arch/x86/mm/init.c +45 -38

129 lines not on this page · raw message

arch/x86/mm/init_32.c +8 -0
index 3801962..37e5768 100644
@@ -662,6 +662,14 @@ void __init find_low_pfn_range(void)
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 void __init early_initmem_init(void)
 {
+	init_mem_mapping(0, max_low_pfn<<PAGE_SHIFT);
+
+	early_ioremap_page_table_range_init();
+
+	load_cr3(swapper_pg_dir);
+	__flush_tlb_all();
+
+	early_memtest(0, max_pfn_mapped<<PAGE_SHIFT);
 }
 void __init initmem_init(void)
 {
arch/x86/mm/init_64.c +9 -0
index 218a4e5..a15db8a 100644
@@ -642,6 +642,15 @@ kernel_physical_mapping_init(unsigned long start,
 #ifndef CONFIG_NUMA
 void __init early_initmem_init(void)
 {
+	init_mem_mapping(0, max_pfn<<PAGE_SHIFT);
+
+	if (max_pfn > max_low_pfn)
+		max_low_pfn = max_pfn;
+
+	load_cr3(swapper_pg_dir);
+	__flush_tlb_all();
+
+	early_memtest(0, max_pfn_mapped<<PAGE_SHIFT);
 }
 void __init initmem_init(void)
 {
arch/x86/mm/numa.c +56 -0

73 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#51 lore raw

Re: [PATCH 14/14] x86, mm: Put pagetable on local node ram

Quoted 12 lines · Yinghai Lu

If node with ram is hotplugable, local node mem for page table and vmemmap should be on that node ram.

This patch is some kind of refreshment of

| commit 1411e0ec3123ae4c4ead6bfc9fe3ee5a3ae5c327
| Date:   Mon Dec 27 16:48:17 2010 -0800
|
|    x86-64, numa: Put pgtable to local node memory

That was reverted before.

We have reason to reintroduce it to make memory hotplug work.

Quoted 8 lines

Split calling of init_mem_mapping into early_initmem_info for nodes after we get numa info there.

First node will be low range.
Need to rework alloc_low_pages to alloc page table in following order:
BRK, local node, low range

Still only load_cr3 one time, otherwise we would break xen 64bit again.

Hmmm... can you please split this patch further? init_mem_mapping() change can be separated, no? Also, comments are disturbingly missing. How are other people reading the code supposed to know what it's trying to achieve why and how? Hmmm... we're also likely to end up with smaller mapping for misaligned NUMA configurations (I think my test machine is like that). Is it guaranteed that the top level ends up in the first node? It really needs documentation.

Thanks.

Signature · 1 line
tejun
author
#52 lore raw

Re: [PATCH 14/14] x86, mm: Put pagetable on local node ram

Quoted 16 lines · Tejun Heo
Quoted 15 lines · Yinghai Lu

If node with ram is hotplugable, local node mem for page table and vmemmap should be on that node ram.

This patch is some kind of refreshment of

| commit 1411e0ec3123ae4c4ead6bfc9fe3ee5a3ae5c327
| Date:   Mon Dec 27 16:48:17 2010 -0800
|
|    x86-64, numa: Put pgtable to local node memory

That was reverted before.

We have reason to reintroduce it to make memory hotplug work.

Split calling of init_mem_mapping into early_initmem_info for nodes after we get numa info there.

Quoted 8 lines
Quoted 5 lines

First node will be low range.
Need to rework alloc_low_pages to alloc page table in following order:
BRK, local node, low range

Still only load_cr3 one time, otherwise we would break xen 64bit again.

Hmmm... can you please split this patch further? init_mem_mapping() change can be separated, no?

will try to split it out.

Quoted 6 lines

Also, comments are disturbingly missing.
How are other people reading the code supposed to know what it's trying to achieve why and how? Hmmm... we're also likely to end up with smaller mapping for misaligned NUMA configurations (I think my test machine is like that). Is it guaranteed that the top level ends up in the first node? It really needs documentation.

Yes. To really memory hotplug working, will need to trim the node alignment to be
1G in memblock and numa_meminfo.

also need to put pgd page in low range (first node) if 512G block is crossing node.
for example: if node2 is [256g, 1024g), pgd for 256g-512g, must be stay on node0 and 512g-1024g could stay on node2.
or just put all PGD pages on low range (first node).

Thanks

Yinghai

#53 lore raw

Re: [PATCH 14/14] x86, mm: Put pagetable on local node ram

In reply to Yinghai Lu

Hi Yinghai,

On 03/08/2013 12:58 PM, Yinghai Lu wrote:
......

arch/x86/mm/init.c static unsigned long __init init_range_memory_mapping( · line 421

Quoted 3 lines

/* xen has big range in reserved near end of ram, skip it at first.*/

arch/x86/mm/init.c +1 -1
-	addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE, PMD_SIZE);
+	addr = memblock_find_in_range(begin, end, PMD_SIZE, PMD_SIZE);

Found that the latest code here is:

414 addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE,

 415                          PAGE_SIZE);
                             ^^^^^^^^^^^^

The "align" is PAGE_SIZE, not PMD_SIZE. Not sure if it is a problem. :)

Thanks. :)

author
#54 lore raw

Re: [PATCH 14/14] x86, mm: Put pagetable on local node ram

Quoted 12 lines · Tang Chen

Hi Yinghai,

On 03/08/2013 12:58 PM, Yinghai Lu wrote:
......

Quoted 5 lines
        /* xen has big range in reserved near end of ram, skip it at

first.*/
- addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE,
PMD_SIZE);
+ addr = memblock_find_in_range(begin, end, PMD_SIZE, PMD_SIZE);

Quoted 8 lines

Found that the latest code here is:

414 addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE,

 415                          PAGE_SIZE);
                             ^^^^^^^^^^^^

The "align" is PAGE_SIZE, not PMD_SIZE. Not sure if it is a problem. :)

Yes, it is PMD_SIZE.

https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=98e7a989979b185f49e86ddaed2ad6890299d9f0

Thanks

Yinghai