]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
acpi, memory-hotplug: parse SRAT before memblock is ready
authorTang Chen <tangchen@cn.fujitsu.com>
Wed, 20 Feb 2013 02:14:27 +0000 (13:14 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Wed, 20 Feb 2013 05:52:38 +0000 (16:52 +1100)
On linux, the pages used by kernel could not be migrated.  As a result, if
a memory range is used by kernel, it cannot be hot-removed.  So if we want
to hot-remove memory, we should prevent kernel from using it.

The way now used to prevent this is specify a memory range by
movablemem_map boot option and set it as ZONE_MOVABLE.

But when the system is booting, memblock will allocate memory, and reserve
the memory for kernel.  And before we parse SRAT, and know the node memory
ranges, memblock is working.  And it may allocate memory in ranges to be
set as ZONE_MOVABLE.  This memory can be used by kernel, and never be
freed.

So, let's parse SRAT before memblock is called first. And it is early enough.

The first call of memblock_find_in_range_node() is in:
setup_arch()
 |-->setup_real_mode()

so, this patch add a function early_parse_srat() to parse SRAT, and call
it before setup_real_mode() is called.

NOTE:

1) Do not clear numa_nodes_parsed in numa_init() because SRAT was
   parsed earlier.

2) I don't know why using count of memory affinities parsed from SRAT
   as a return value in original acpi_numa_init().  So I add a static
   variable srat_mem_cnt to remember this count and use it as the return
   value of the new acpi_numa_init()

Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
Reviewed-by: Wen Congyang <wency@cn.fujitsu.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Jiang Liu <jiang.liu@huawei.com>
Cc: Jianguo Wu <wujianguo@huawei.com>
Cc: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
Cc: Wu Jianguo <wujianguo@huawei.com>
Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Len Brown <lenb@kernel.org>
Cc: "Brown, Len" <len.brown@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
arch/x86/kernel/setup.c
arch/x86/mm/numa.c
drivers/acpi/numa.c
include/linux/acpi.h

index 915f5efefcf5203e66f00955083be008de064554..9c857f05cef0fccea2dab9769a865ff2f63c920b 100644 (file)
@@ -1056,6 +1056,15 @@ void __init setup_arch(char **cmdline_p)
        setup_bios_corruption_check();
 #endif
 
+       /*
+        * In the memory hotplug case, the kernel needs info from SRAT to
+        * determine which memory is hotpluggable before allocating memory
+        * using memblock.
+        */
+       acpi_boot_table_init();
+       early_acpi_boot_init();
+       early_parse_srat();
+
 #ifdef CONFIG_X86_32
        printk(KERN_DEBUG "initial memory mapped: [mem 0x00000000-%#010lx]\n",
                        (max_pfn_mapped<<PAGE_SHIFT) - 1);
@@ -1101,10 +1110,6 @@ void __init setup_arch(char **cmdline_p)
        /*
         * Parse the ACPI tables for possible boot-time SMP configuration.
         */
-       acpi_boot_table_init();
-
-       early_acpi_boot_init();
-
        initmem_init();
        memblock_find_dma_reserve();
 
index 7dbf5af423bbae70f7ae91643d4c477cd2be9795..3545585207c771b294497d18d5c8f1da5481f151 100644 (file)
@@ -559,7 +559,7 @@ static int __init numa_init(int (*init_func)(void))
        for (i = 0; i < MAX_LOCAL_APIC; i++)
                set_apicid_to_node(i, NUMA_NO_NODE);
 
-       nodes_clear(numa_nodes_parsed);
+       /* Do not clear numa_nodes_parsed because SRAT was parsed earlier. */
        nodes_clear(node_possible_map);
        nodes_clear(node_online_map);
        memset(&numa_meminfo, 0, sizeof(numa_meminfo));
index 33e609f6358580647412dd0d029f065fdfb73741..59844ee149bed01dbe522393637c39f74f7c8ae7 100644 (file)
@@ -282,10 +282,10 @@ acpi_table_parse_srat(enum acpi_srat_type id,
                                            handler, max_entries);
 }
 
-int __init acpi_numa_init(void)
-{
-       int cnt = 0;
+static int srat_mem_cnt;
 
+void __init early_parse_srat(void)
+{
        /*
         * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
         * SRAT cpu entries could have different order with that in MADT.
@@ -295,21 +295,24 @@ int __init acpi_numa_init(void)
        /* SRAT: Static Resource Affinity Table */
        if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
                acpi_table_parse_srat(ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY,
-                                    acpi_parse_x2apic_affinity, 0);
+                                     acpi_parse_x2apic_affinity, 0);
                acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
-                                    acpi_parse_processor_affinity, 0);
-               cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
-                                           acpi_parse_memory_affinity,
-                                           NR_NODE_MEMBLKS);
+                                     acpi_parse_processor_affinity, 0);
+               srat_mem_cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
+                                                    acpi_parse_memory_affinity,
+                                                    NR_NODE_MEMBLKS);
        }
+}
 
+int __init acpi_numa_init(void)
+{
        /* SLIT: System Locality Information Table */
        acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
 
        acpi_numa_arch_fixup();
 
-       if (cnt < 0)
-               return cnt;
+       if (srat_mem_cnt < 0)
+               return srat_mem_cnt;
        else if (!parsed_numa_memblks)
                return -ENOENT;
        return 0;
index bcbdd7484e581404d54be807c034fced32ba45c2..b7cc2309671fbd14c9e7bc8c883b13960c655a0b 100644 (file)
@@ -94,6 +94,7 @@ int acpi_boot_init (void);
 void acpi_boot_table_init (void);
 int acpi_mps_check (void);
 int acpi_numa_init (void);
+void __init early_parse_srat(void);
 
 int acpi_table_init (void);
 int acpi_table_parse(char *id, acpi_tbl_table_handler handler);