x86: early check if one system is numaq v2
Subsystems (5)
PATCH 1/1 x86: early check if one system is numaq v2
so could fallback one node numa
v2: using found_numaq with MP_processor_info and MP_bus_info
arch/x86/kernel/mpparse.c +11 -3
@@ -70,7 +70,10 @@ static void __cpuinit MP_processor_info(return ; }#ifdef CONFIG_X86_NUMAQ - apicid =mpc_apic_id (m, translation_table[mpc_record]); +if (found_numaq) + apicid =mpc_apic_id (m, translation_table[mpc_record]); +else + apicid = m->mpc_apicid;#else apicid = m->mpc_apicid;#endif
@@ -91,7 +94,8 @@ static void __init MP_bus_info(struct mp str[6 ] =0 ;#ifdef CONFIG_X86_NUMAQ -mpc_oem_bus_info (m, str, translation_table[mpc_record]); +if (found_numaq) +mpc_oem_bus_info (m, str, translation_table[mpc_record]);#else printk (KERN_INFO "Bus #%d is %s\n" , m->mpc_busid, str);#endif
@@ -112,7 +116,8 @@ static void __init MP_bus_info(struct mp#endif }else if (strncmp (str,BUSTYPE_PCI ,sizeof (BUSTYPE_PCI ) -1 ) ==0 ) {#ifdef CONFIG_X86_NUMAQ -mpc_oem_pci_bus (m, translation_table[mpc_record]); +if (found_numaq) +mpc_oem_pci_bus (m, translation_table[mpc_record]);#endif clear_bit (m->mpc_busid, mp_bus_not_pci);#if defined(CONFIG_EISA ) || defined (CONFIG_MCA )
@@ -321,6 +326,9 @@ static inline void mps_oem_check(struct {if (strncmp (oem,"IBM NUMA" ,8 ))printk ("Warning! May not be a NUMA-Q system!\n" ); +else + found_numaq =1 ; +if (mpc->mpc_oemptr)smp_read_mpc_oem ((struct mp_config_oemtable *)mpc->mpc_oemptr, mpc->mpc_oemsize);
arch/x86/kernel/numaq_32.c +19 -5
@@ -31,9 +31,12 @@#include <asm/numaq.h> #include <asm/topology.h> #include <asm/processor.h> +#include <asm/mpspec.h> #define MB_TO_PAGES (addr) ((addr) << (20 - PAGE_SHIFT)) +int found_numaq; +/* * Function: smp_dump_qct() *
@@ -67,13 +70,24 @@ static void __init smp_dump_qct(void) } } -/* -* Unlike Summit, we don't really care to let the NUMA-Q -* fall back to flat mode. Don't compile for NUMA-Q -* unless you really need it! -*/ +static __init void early_check_numaq (void ) +{ +/* +* Find possible boot-time SMP configuration: +*/ +early_find_smp_config (); +/* +* get boot-time SMP configuration: +*/ +if (smp_found_config) +early_get_smp_config (); +} +int __init get_memcfg_numaq (void ) { +early_check_numaq (); +if (!found_numaq) +return 0 ;smp_dump_qct ();return 1 ; }
include/asm-x86/numaq.h +1 -0
@@ -28,6 +28,7 @@#ifdef CONFIG_X86_NUMAQ +extern int found_numaq;extern int get_memcfg_numaq (void );/*
include/asm-x86/mpspec.h +2 -2
@@ -21,11 +21,11 @@ extern int pic_mode;/* Each PCI slot may be a combo card with its own bus. 4 IRQ pins per slot. */ #define MAX_IRQ_SOURCES (MAX_MP_BUSSES * 4) +#endif +extern void early_find_smp_config (void );extern void early_get_smp_config (void ); -#endif -#if defined(CONFIG_MCA ) || defined(CONFIG_EISA )extern int mp_bus_id_to_type[MAX_MP_BUSSES ];#endif
PATCH 1/1 x86: numa32 make sure get kva space
when 1/3 user/kernel is used, and less memory is installed, or have big hole below 4g, max_low_pfn is still using 3g-128m
try to go down from max_low_pfn until get it. otherwise will panic.
need to make 32bit code to use register_e820_active_regions...later
arch/x86/mm/discontig_32.c +12 -5
@@ -306,6 +306,7 @@ unsigned long __init setup_memory(void) {int nid;unsigned long system_start_pfn, system_max_low_pfn; +long kva_target_pfn;/* * When mapping a NUMA machine we allocate the node_mem_map arrays
@@ -322,11 +323,17 @@ unsigned long __init setup_memory(void) system_start_pfn = min_low_pfn =PFN_UP (init_pg_tables_end); system_max_low_pfn = max_low_pfn =find_max_low_pfn (); - kva_start_pfn =round_down (max_low_pfn - kva_pages,PTRS_PER_PTE ); - kva_start_pfn =find_e820_area (kva_start_pfn<<PAGE_SHIFT , - max_low_pfn<<PAGE_SHIFT , - kva_pages<<PAGE_SHIFT , -PTRS_PER_PTE <<PAGE_SHIFT ) >>PAGE_SHIFT ; + kva_target_pfn =round_down (max_low_pfn - kva_pages,PTRS_PER_PTE ); +do { + kva_start_pfn =find_e820_area (kva_target_pfn<<PAGE_SHIFT , + max_low_pfn<<PAGE_SHIFT , + kva_pages<<PAGE_SHIFT , +PTRS_PER_PTE <<PAGE_SHIFT ) >>PAGE_SHIFT ; + kva_target_pfn -=PTRS_PER_PTE ; + }while (kva_start_pfn ==-1UL && kva_target_pfn > min_low_pfn); + +if (kva_start_pfn ==-1UL ) +panic ("Can not get kva space\n" );printk ("kva_start_pfn ~ %ld find_max_low_pfn() ~ %ld\n" , kva_start_pfn, max_low_pfn);
Ingo Molnar
AppliedRe: [PATCH] x86: numa32 make sure get kva space
Quoted 8 lines · Yinghai Lu
when 1/3 user/kernel is used, and less memory is installed, or have big hole below 4g,
max_low_pfnis still using 3g-128mtry to go down from
max_low_pfnuntil get it. otherwise will panic.need to make 32bit code to use register_e820_active_regions...later
Signed-off-by Yinghai Lu <[email protected]>
applied, thanks.
Ingo
PATCH 1/1 x86: move e820_register_active to e820.c
In reply to Yinghai Luto prepare 32 bit to use it
arch/x86/kernel/e820.c +109 -0
@@ -764,3 +764,112 @@ u64 __init early_reserve_e820(u64 starttreturn addr; } +#ifdef CONFIG_X86_32 +# ifdef CONFIG_X86_PAE +# define MAX_ARCH_PFN (1ULL<<(36-PAGE_SHIFT)) +# else +# define MAX_ARCH_PFN (1ULL<<(32-PAGE_SHIFT)) +# endif +#else /* CONFIG_X86_32 */ +# define MAX_ARCH_PFN MAXMEM<<PAGE_SHIFT +#endif + +/* +* Last pfn which the user wants to use. +*/ +unsigned long __initdata end_user_pfn =MAX_ARCH_PFN ; + +/* +* Find the highest page frame number we have available +*/ +unsigned long __init e820_end_of_ram (void ) +{ +unsigned long last_pfn; +unsigned long max_arch_pfn =MAX_ARCH_PFN ; + + last_pfn =find_max_pfn_with_active_regions (); + +if (last_pfn > max_arch_pfn) + last_pfn = max_arch_pfn; +if (last_pfn > end_user_pfn) + last_pfn = end_user_pfn; + +printk (KERN_INFO "last_pfn = %lu max_arch_pfn = %lu\n" , + last_pfn, max_arch_pfn); +return last_pfn; +} + +/* +* Finds an active region in the address range from start_pfn to last_pfn and +* returns its range in ei_startpfn and ei_endpfn for the e820 entry. +*/ +int __init e820_find_active_region (const struct e820entry *ei, +unsigned long start_pfn, +unsigned long last_pfn, +unsigned long *ei_startpfn, +unsigned long *ei_endpfn) +{ +u64 align =PAGE_SIZE ; + + *ei_startpfn =round_up (ei->addr, align) >>PAGE_SHIFT ; + *ei_endpfn =round_down (ei->addr + ei->size, align) >>PAGE_SHIFT ; + +/* Skip map entries smaller than a page */ +if (*ei_startpfn >= *ei_endpfn) +return 0 ; + +/* Skip if map is outside the node */ +if (ei->type !=E820_RAM || *ei_endpfn <= start_pfn || + *ei_startpfn >= last_pfn) +return 0 ; + +/* Check for overlaps */ +if (*ei_startpfn < start_pfn) + *ei_startpfn = start_pfn; +if (*ei_endpfn > last_pfn) + *ei_endpfn = last_pfn; + +/* Obey end_user_pfn to save on memmap */ +if (*ei_startpfn >= end_user_pfn) +return 0 ; +if (*ei_endpfn > end_user_pfn) + *ei_endpfn = end_user_pfn; + +return 1 ; +} + +/* Walk the e820 map and register active regions within a node */ +void __init e820_register_active_regions (int nid,unsigned long start_pfn, +unsigned long last_pfn) +{ +unsigned long ei_startpfn; +unsigned long ei_endpfn; +int i; + +for (i =0 ; i < e820.nr_map; i++) +if (e820_find_active_region (&e820.map[i], + start_pfn, last_pfn, + &ei_startpfn, &ei_endpfn)) +add_active_range (nid, ei_startpfn, ei_endpfn); +} + +/* +* Find the hole size (in bytes) in the memory range. +* @start: starting address of the memory range to scan +* @end: ending address of the memory range to scan +*/ +u64 __init e820_hole_size (u64 start,u64 end) +{ +unsigned long start_pfn = start >>PAGE_SHIFT ; +unsigned long last_pfn = end >>PAGE_SHIFT ; +unsigned long ei_startpfn, ei_endpfn, ram =0 ; +int i; + +for (i =0 ; i < e820.nr_map; i++) { +if (e820_find_active_region (&e820.map[i], + start_pfn, last_pfn, + &ei_startpfn, &ei_endpfn)) + ram += ei_endpfn - ei_startpfn; + } +return end - start - ((u64 )ram <<PAGE_SHIFT ); +}
arch/x86/kernel/e820_64.c +0 -97
109 lines not on this page · raw message
include/asm-x86/e820.h +11 -0
@@ -79,6 +79,8 @@ static inline void e820_mark_nosave_regi }#endif +extern unsigned long end_user_pfn; +extern u64 find_e820_area (u64 start,u64 end,u64 size,u64 align);extern u64 find_e820_area_size (u64 start,u64 *sizep,u64 align);extern void reserve_early (u64 start,u64 end,char *name);
@@ -86,6 +88,15 @@ extern void free_early(u64 start, u64 enextern void early_res_to_bootmem (u64 start,u64 end);extern u64 early_reserve_e820 (u64 startt,u64 sizet,u64 align); +extern unsigned long e820_end_of_ram (void ); +extern int e820_find_active_region (const struct e820entry *ei, +unsigned long start_pfn, +unsigned long last_pfn, +unsigned long *ei_startpfn, +unsigned long *ei_endpfn); +extern void e820_register_active_regions (int nid,unsigned long start_pfn, +unsigned long end_pfn); +extern u64 e820_hole_size (u64 start,u64 end);#endif /* __ASSEMBLY__ */ #define ISA_START_ADDRESS 0xa0000
include/asm-x86/e820_64.h +0 -5
@@ -16,16 +16,11 @@#ifndef __ASSEMBLY__extern void setup_memory_region (void );extern void contig_e820_setup (void ); -extern unsigned long e820_end_of_ram (void );extern void e820_reserve_resources (void );extern int e820_any_non_reserved (unsigned long start,unsigned long end);extern int is_memory_any_valid (unsigned long start,unsigned long end);extern int e820_all_non_reserved (unsigned long start,unsigned long end);extern int is_memory_all_valid (unsigned long start,unsigned long end); -extern unsigned long e820_hole_size (unsigned long start,unsigned long end); - -extern void e820_register_active_regions (int nid,unsigned long start_pfn, -unsigned long end_pfn);extern void finish_e820_parsing (void );
PATCH 1/1 x86: 32 bit use e820_register_active_regions
so 32bit is more like 64bit, and more smart with combining e820 and numa.
arch/x86/kernel/setup_32.c +18 -6
@@ -406,11 +406,12 @@ static void __init zone_sizes_init(void) max_zone_pfns[ZONE_DMA ] =virt_to_phys ((char *)MAX_DMA_ADDRESS ) >>PAGE_SHIFT ; max_zone_pfns[ZONE_NORMAL ] = max_low_pfn; +remove_all_active_ranges ();#ifdef CONFIG_HIGHMEM max_zone_pfns[ZONE_HIGHMEM ] = highend_pfn; -add_active_range (0 ,0 , highend_pfn); +e820_register_active_regions (0 ,0 , highend_pfn);#else -add_active_range (0 ,0 , max_low_pfn); +e820_register_active_regions (0 ,0 , max_low_pfn);#endif free_area_init_nodes (max_zone_pfns);
@@ -583,6 +584,7 @@ static void __init relocate_initrd(void)void __init setup_bootmem_allocator (void ) { +int i;unsigned long bootmap_size, bootmap;/* * Initialize the boot-time allocator (with low memory only):
@@ -604,7 +606,8 @@ void __init setup_bootmem_allocator(void min_low_pfn<<PAGE_SHIFT, max_low_pfn<<PAGE_SHIFT);printk (KERN_INFO " bootmap %08lx - %08lx\n" , bootmap, bootmap + bootmap_size); -register_bootmem_low_pages (max_low_pfn); +for_each_online_node (i) +free_bootmem_with_active_regions (i, max_low_pfn);early_res_to_bootmem (0 , max_low_pfn<<PAGE_SHIFT );#ifdef CONFIG_ACPI_SLEEP
@@ -745,11 +748,20 @@ void __init setup_arch(char **cmdline_p)if (efi_enabled)efi_init (); +e820_register_active_regions (0 ,0 ,-1UL ); +/* +* partially used pages are not usable - thus +* we are rounding upwards: +*/ + max_pfn =e820_end_of_ram (); +/* update e820 for memory not covered by WB MTRRs */ -find_max_pfn ();mtrr_bp_init (); -if (mtrr_trim_uncached_memory (max_pfn)) -find_max_pfn (); +if (mtrr_trim_uncached_memory (max_pfn)) { +remove_all_active_ranges (); +e820_register_active_regions (0 ,0 ,-1UL ); + max_pfn =e820_end_of_ram (); + } max_low_pfn =setup_memory ();
arch/x86/mm/discontig_32.c +6 -13
@@ -120,10 +120,9 @@ int __init get_memcfg_numa_flat(void) {printk ("NUMA - single node, flat memory mode\n" ); -/* Run the memory configuration and find the top of memory. */ -find_max_pfn (); node_start_pfn[0 ] =0 ; node_end_pfn[0 ] = max_pfn; +e820_register_active_regions (0 ,0 , max_pfn);memory_present (0 ,0 , max_pfn); node_remap_size[0 ] =node_memmap_size_bytes (0 ,0 , max_pfn);
@@ -315,6 +314,11 @@ unsigned long __init setup_memory(void)* this space and use it to adjust the boundary between ZONE_NORMAL * and ZONE_HIGHMEM. */ + +/* call find_max_low_pfn at first, it could update max_pfn */ + system_max_low_pfn = max_low_pfn =find_max_low_pfn (); + +remove_all_active_ranges ();get_memcfg_numa (); kva_pages =round_up (calculate_numa_remap_pages (),PTRS_PER_PTE );
@@ -322,7 +326,6 @@ unsigned long __init setup_memory(void)/* partially used pages are not usable - thus round upwards */ system_start_pfn = min_low_pfn =PFN_UP (init_pg_tables_end); - system_max_low_pfn = max_low_pfn =find_max_low_pfn (); kva_target_pfn =round_down (max_low_pfn - kva_pages,PTRS_PER_PTE ); do { kva_start_pfn = find_e820_area(kva_target_pfn<<PAGE_SHIFT,
@@ -380,7 +383,6 @@ unsigned long __init setup_memory(void)void __init zone_sizes_init (void ) { -int nid;unsigned long max_zone_pfns[MAX_NR_ZONES ];memset (max_zone_pfns,0 ,sizeof (max_zone_pfns)); max_zone_pfns[ZONE_DMA] =
@@ -390,15 +392,6 @@ void __init zone_sizes_init(void) max_zone_pfns[ZONE_HIGHMEM ] = highend_pfn;#endif -/* If SRAT has not registered memory, register it now */ -if (find_max_pfn_with_active_regions () ==0 ) { -for_each_online_node (nid) { -if (node_has_online_mem (nid)) -add_active_range (nid, node_start_pfn[nid], - node_end_pfn[nid]); - } - } -free_area_init_nodes (max_zone_pfns);return ; }
arch/x86/kernel/numaq_32.c +3 -0
@@ -32,6 +32,7 @@#include <asm/topology.h> #include <asm/processor.h> #include <asm/mpspec.h> +#include <asm/e820.h> #define MB_TO_PAGES (addr) ((addr) << (20 - PAGE_SHIFT))
@@ -61,6 +62,8 @@ static void __init smp_dump_qct(void) node_end_pfn[node] =MB_TO_PAGES ( eq->hi_shrd_mem_start + eq->hi_shrd_mem_size); +e820_register_active_regions (node, node_start_pfn[node], + node_end_pfn[node]);memory_present (node, node_start_pfn[node], node_end_pfn[node]); node_remap_size[node] = node_memmap_size_bytes(node,
arch/x86/kernel/e820_32.c +3 -65
80 lines not on this page · raw message
arch/x86/kernel/srat_32.c +3 -1
@@ -31,6 +31,7 @@#include <asm/srat.h> #include <asm/topology.h> #include <asm/smp.h> +#include <asm/e820.h> /* * proximity macros and definitions
@@ -244,7 +245,8 @@ static int __init acpi20_parse_srat(struprintk ("chunk %d nid %d start_pfn %08lx end_pfn %08lx\n" , j, chunk->nid, chunk->start_pfn, chunk->end_pfn);node_read_chunk (chunk->nid, chunk); -add_active_range (chunk->nid, chunk->start_pfn, chunk->end_pfn); +e820_register_active_regions (chunk->nid, chunk->start_pfn, +min (chunk->end_pfn, max_pfn)); }for_each_online_node (nid) {
include/asm-x86/e820_32.h +0 -2
@@ -21,8 +21,6 @@extern void setup_memory_map (void );extern void finish_e820_parsing (void ); -extern void find_max_pfn (void ); -extern void register_bootmem_low_pages (unsigned long max_low_pfn);extern void limit_regions (unsigned long long size); extern void init_iomem_resources(struct resource *code_resource, struct resource *data_resource,
PATCH 1/1 x86: e820 merge parse mem/memmap
after we get 32 bit support e820_register_active_regions
we could merge parse mem/memmap
arch/x86/kernel/e820.c +86 -0
@@ -873,3 +873,89 @@ u64 __init e820_hole_size(u64 start, u64 }return end - start - ((u64 )ram <<PAGE_SHIFT ); } + +static void early_panic (char *msg) +{ +early_printk (msg); +panic (msg); +} + +/* "mem=nopentium" disables the 4MB page tables. */ +static int __init parse_memopt (char *p) +{ +u64 mem_size; + +if (!p) +return -EINVAL ; + +#ifdef CONFIG_X86_32 +if (!strcmp (p,"nopentium" )) { +setup_clear_cpu_cap (X86_FEATURE_PSE ); +return 0 ; + } +#endif + + mem_size =memparse (p, &p); + end_user_pfn = mem_size>>PAGE_SHIFT ; +return 0 ; +} +early_param ("mem" , parse_memopt); + +static int userdef__initdata ; + +static int __init parse_memmap_opt (char *p) +{ +char *oldp; +u64 start_at, mem_size; + +if (!strcmp (p,"exactmap" )) { +#ifdef CONFIG_CRASH_DUMP +/* +* If we are doing a crash dump, we still need to know +* the real mem size before original memory map is +* reset. +*/ +e820_register_active_regions (0 ,0 ,-1UL ); + saved_max_pfn =e820_end_of_ram (); +remove_all_active_ranges (); +#endif + e820.nr_map =0 ; + userdef =1 ; +return 0 ; + } + + oldp = p; + mem_size =memparse (p, &p); +if (p == oldp) +return -EINVAL ; + + userdef =1 ; +if (*p =='@' ) { + start_at =memparse (p+1 , &p); +add_memory_region (start_at, mem_size,E820_RAM ); + }else if (*p =='#' ) { + start_at =memparse (p+1 , &p); +add_memory_region (start_at, mem_size,E820_ACPI ); + }else if (*p =='$' ) { + start_at =memparse (p+1 , &p); +add_memory_region (start_at, mem_size,E820_RESERVED ); + }else { + end_user_pfn = (mem_size >>PAGE_SHIFT ); + } +return *p =='\0' ?0 : -EINVAL ; +} +early_param ("memmap" , parse_memmap_opt); + +void __init finish_e820_parsing (void ) +{ +if (userdef) { +int nr = e820.nr_map; + +if (sanitize_e820_map (e820.map,ARRAY_SIZE (e820.map), &nr) <0 ) +early_panic ("Invalid user supplied memory map" ); + e820.nr_map = nr; + +printk (KERN_INFO "user-defined physical RAM map:\n" ); +e820_print_map ("user" ); + } +}
arch/x86/kernel/e820_32.c +0 -120
129 lines not on this page · raw message
arch/x86/kernel/e820_64.c +0 -69
75 lines not on this page · raw message
include/asm-x86/e820.h +2 -0
@@ -97,6 +97,8 @@ extern int e820_find_active_region(constextern void e820_register_active_regions (int nid,unsigned long start_pfn,unsigned long end_pfn);extern u64 e820_hole_size (u64 start,u64 end); +extern void finish_e820_parsing (void ); +#endif /* __ASSEMBLY__ */ #define ISA_START_ADDRESS 0xa0000
include/asm-x86/e820_32.h +0 -2
@@ -19,9 +19,7 @@#ifndef __ASSEMBLY__extern void setup_memory_map (void ); -extern void finish_e820_parsing (void ); -extern void limit_regions (unsigned long long size);extern void init_iomem_resources (struct resource *code_resource,struct resource *data_resource,struct resource *bss_resource);
include/asm-x86/e820_64.h +0 -2
@@ -22,8 +22,6 @@ extern int is_memory_any_valid(unsignedextern int e820_all_non_reserved (unsigned long start,unsigned long end);extern int is_memory_all_valid (unsigned long start,unsigned long end); -extern void finish_e820_parsing (void ); -#endif /*!__ASSEMBLY__*/ #endif /*__E820_HEADER*/
Ingo Molnar
AppliedRe: [PATCH] x86: 32 bit use e820_register_active_regions
In reply to Yinghai LuQuoted 3 lines · Yinghai Lu
so 32bit is more like 64bit, and more smart with combining e820 and numa.
Signed-off-by Yinghai Lu <[email protected]>
applied, thanks.
Ingo
PATCH 1/1 x86: e820 max_arch_pfn typo fix for 64 bit
In reply to Yinghai Lushould use right shift
arch/x86/kernel/e820.c +1 -1
@@ -771,7 +771,7 @@ u64 __init early_reserve_e820(u64 startt# define MAX_ARCH_PFN (1ULL<<(32-PAGE_SHIFT))# endif #else /* CONFIG_X86_32 */ -# define MAX_ARCH_PFN MAXMEM<<PAGE_SHIFT +# define MAX_ARCH_PFN MAXMEM>>PAGE_SHIFT#endif /*
H. Peter Anvin
reviewerRe: [PATCH] x86: e820 max_arch_pfn typo fix for 64 bit
Quoted 9 lines · Yinghai Lu
should use right shift
Signed-off-by Yinghai Lu <[email protected]>Index:
linux-2.6/arch/x86/kernel/e820.c
===================================================================
arch/x86/kernel/e820.c u64 __init early_reserve_e820(u64 startt · line 776
Quoted 7 lines
arch/x86/kernel/e820.c +1
-1@@ -771,7 +771,7 @@ u64 __init early_reserve_e820(u64 startt# define MAX_ARCH_PFN (1ULL<<(32-PAGE_SHIFT))# endif #else /* CONFIG_X86_32 */ -# define MAX_ARCH_PFN MAXMEM<<PAGE_SHIFT +# define MAX_ARCH_PFN MAXMEM>>PAGE_SHIFT#endif
Should also use parens (operator inside a macro).
-hpa
PATCH 1/1 x86: shrink pages should check all
In reply to Yinghai Luwe are uing register_e820_active_regions instead of add_active_range directly. so end_pfn could be different between the value in early_node_map to node_end_pfn.
need to make shrink_active_range more smart.
shrink_active_range is only used x86 32 bit, or need to move back in some file in arch/x86?
arch/x86/mm/discontig_32.c +1 -1
@@ -279,7 +279,7 @@ static unsigned long calculate_numa_rema node_end_pfn[nid] -= size; node_remap_start_pfn[nid] = node_end_pfn[nid]; -shrink_active_range (nid, old_end_pfn, node_end_pfn[nid]); +shrink_active_range (nid, node_end_pfn[nid]); }printk ("Reserving total of %ld pages for numa KVA remap\n" , reserve_pages);
include/linux/mm.h +1 -2
@@ -997,8 +997,7 @@ extern void free_area_init_node(int nid,extern void free_area_init_nodes (unsigned long *max_zone_pfn);extern void add_active_range (unsigned int nid,unsigned long start_pfn,unsigned long end_pfn); -extern void shrink_active_range (unsigned int nid,unsigned long old_end_pfn, -unsigned long new_end_pfn); +extern void shrink_active_range (unsigned int nid,unsigned long new_end_pfn);extern void push_node_boundaries (unsigned int nid,unsigned long start_pfn,unsigned long end_pfn);extern void remove_all_active_ranges (void );
mm/page_alloc.c +36 -10
61 lines not on this page · raw message
PATCH 1/1 x86: numa32 use find_e820_area to find KVA ram on node
don't assume we can use ram near end of every node. esp some system has less memory. and they could have kva address and kva ram all below max_low_pfn
arch/x86/mm/discontig_32.c +31 -24
@@ -225,17 +225,21 @@ static unsigned long calculate_numa_rema {int nid;unsigned long size, reserve_pages =0 ; -unsigned long pfn;for_each_online_node (nid) { -unsigned old_end_pfn = node_end_pfn[nid]; +u64 node_end_target; +u64 node_end_final;/* * The acpi/srat node info can show hot-add memroy zones * where memory could be added but not currently present. */ +printk ("node %d pfn: [%lx - %lx]\n" , + nid, node_start_pfn[nid], node_end_pfn[nid]);if (node_start_pfn[nid] > max_pfn)continue ; +if (!node_end_pfn[nid]) +continue ;if (node_end_pfn[nid] > max_pfn) node_end_pfn[nid] = max_pfn;
@@ -247,37 +251,40 @@ static unsigned long calculate_numa_rema/* now the roundup is correct, convert to PAGE_SIZE pages */ size = size *PTRS_PER_PTE ; -/* -* Validate the region we are allocating only contains valid -* pages. -*/ -for (pfn = node_end_pfn[nid] - size; - pfn < node_end_pfn[nid]; pfn++) -if (!page_is_ram (pfn)) -break ; + node_end_target =round_down (node_end_pfn[nid] - size, +PTRS_PER_PTE ); + node_end_target <<=PAGE_SHIFT ; +do { + node_end_final =find_e820_area (node_end_target, + ((u64 )node_end_pfn[nid])<<PAGE_SHIFT , + ((u64 )size)<<PAGE_SHIFT , +LARGE_PAGE_BYTES ); + node_end_target -=LARGE_PAGE_BYTES ; + }while (node_end_final ==-1ULL && + (node_end_target>>PAGE_SHIFT ) > (node_start_pfn[nid])); -if (pfn != node_end_pfn[nid]) - size =0 ; +if (node_end_final ==-1ULL ) +panic ("Can not get kva ram\n" );printk ("Reserving %ld pages of KVA for lmem_map of node %d\n" , size, nid); node_remap_size[nid] = size; node_remap_offset[nid] = reserve_pages; reserve_pages += size; -printk ("Shrinking node %d from %ld pages to %ld pages\n" , - nid, node_end_pfn[nid], node_end_pfn[nid] - size); +printk ("Shrinking node %d from %ld pages to %lld pages\n" , + nid, node_end_pfn[nid], node_end_final>>PAGE_SHIFT ); -if (node_end_pfn[nid] & (PTRS_PER_PTE -1 )) { -/* -* Align node_end_pfn[] and node_remap_start_pfn[] to -* pmd boundary. remap_numa_kva will barf otherwise. -*/ -printk ("Shrinking node %d further by %ld pages for proper alignment\n" , - nid, node_end_pfn[nid] & (PTRS_PER_PTE -1 )); - size += node_end_pfn[nid] & (PTRS_PER_PTE -1 ); - } +/* +* prevent kva address below max_low_pfn want it on system +* with less memory later. +* layout will be: KVA address , KVA RAM +*/ +if ((node_end_final>>PAGE_SHIFT ) < max_low_pfn) +reserve_early (node_end_final, + node_end_final+(((u64 )size)<<PAGE_SHIFT ), +"KVA RAM" ); - node_end_pfn[nid] -= size; + node_end_pfn[nid] = node_end_final>>PAGE_SHIFT ; node_remap_start_pfn[nid] = node_end_pfn[nid];shrink_active_range (nid, node_end_pfn[nid]); }
Ingo Molnar
AppliedRe: [PATCH] x86: numa32 use find_e820_area to find KVA ram on node
Quoted 3 lines · Yinghai Lu
don't assume we can use ram near end of every node. esp some system has less memory. and they could have kva address and kva ram all below
max_low_pfn
applied to tip/x86/mpparse, thanks Yinghai.
Ingo
PATCH 1/1 x86: fix fail with 64g above system with numa32
In reply to Yinghai Luarch/x86/kernel/srat_32.c +1 -1
@@ -251,7 +251,7 @@ static int __init acpi20_parse_srat(strufor_each_online_node (nid) {unsigned long start = node_start_pfn[nid]; -unsigned long end = node_end_pfn[nid]; +unsigned long end =min (node_end_pfn[nid],max_pfn);memory_present (nid, start, end); node_remap_size[nid] =node_memmap_size_bytes (nid, start, end);
Ingo Molnar
AppliedRe: [PATCH] x86: fix fail with 64g above system with numa32
arch/x86/kernel/srat_32.c static int __init acpi20_parse_srat(stru · line 256
Quoted 9 lines · Yinghai Lu
+++
b/arch/x86/kernel/srat_32.c2008-06-06 17:38:38.000000000 -0700arch/x86/kernel/srat_32.c +1
-1@@ -251,7 +251,7 @@ static int __init acpi20_parse_srat(strufor_each_online_node (nid) {unsigned long start = node_start_pfn[nid]; -unsigned long end = node_end_pfn[nid]; +unsigned long end =min (node_end_pfn[nid],max_pfn);memory_present (nid, start, end);
applied to tip/x86/mpparse, thanks.
Ingo
PATCH 1/1 x86: shrink pages should check all v2
In reply to Yinghai Luwe are uing register_e820_active_regions instead of add_active_range directly. so end_pfn could be different between the value in early_node_map to node_end_pfn.
need to make shrink_active_range more smart.
shrink_active_range is only used x86 32 bit, or need to move back in some file in arch/x86?
v2: use memcpy instead
include/linux/mm.h +1 -2
@@ -997,8 +997,7 @@ extern void free_area_init_node(int nid,extern void free_area_init_nodes (unsigned long *max_zone_pfn);extern void add_active_range (unsigned int nid,unsigned long start_pfn,unsigned long end_pfn); -extern void shrink_active_range (unsigned int nid,unsigned long old_end_pfn, -unsigned long new_end_pfn); +extern void shrink_active_range (unsigned int nid,unsigned long new_end_pfn);extern void push_node_boundaries (unsigned int nid,unsigned long start_pfn,unsigned long end_pfn);extern void remove_all_active_ranges (void );
mm/page_alloc.c +34 -10
59 lines not on this page · raw message
arch/x86/mm/discontig_32.c +1 -1
@@ -279,7 +279,7 @@ static unsigned long calculate_numa_rema node_end_pfn[nid] -= size; node_remap_start_pfn[nid] = node_end_pfn[nid]; -shrink_active_range (nid, old_end_pfn, node_end_pfn[nid]); +shrink_active_range (nid, node_end_pfn[nid]); }printk ("Reserving total of %ld pages for numa KVA remap\n" , reserve_pages);
Ingo Molnar
AppliedRe: [PATCH] x86: shrink pages should check all v2
Quoted 10 lines · Yinghai Lu
we are uing
register_e820_active_regionsinstead ofadd_active_rangedirectly. soend_pfncould be different between the value inearly_node_maptonode_end_pfn.need to make
shrink_active_rangemore smart.
shrink_active_rangeis only used x86 32 bit, or need to move back in some file inarch/x86?v2: use memcpy instead
applied, thanks.
Ingo
PATCH 1/1 x86: e820 merge parse mem/memmap
In reply to Yinghai Luresend. it seems Ingo missed it.
after we get 32 bit support e820_register_active_regions
we could merge parse mem/memmap
arch/x86/kernel/e820.c +86 -0
@@ -873,3 +873,89 @@ u64 __init e820_hole_size(u64 start, u64 }return end - start - ((u64 )ram <<PAGE_SHIFT ); } + +static void early_panic (char *msg) +{ +early_printk (msg); +panic (msg); +} + +/* "mem=nopentium" disables the 4MB page tables. */ +static int __init parse_memopt (char *p) +{ +u64 mem_size; + +if (!p) +return -EINVAL ; + +#ifdef CONFIG_X86_32 +if (!strcmp (p,"nopentium" )) { +setup_clear_cpu_cap (X86_FEATURE_PSE ); +return 0 ; + } +#endif + + mem_size =memparse (p, &p); + end_user_pfn = mem_size>>PAGE_SHIFT ; +return 0 ; +} +early_param ("mem" , parse_memopt); + +static int userdef__initdata ; + +static int __init parse_memmap_opt (char *p) +{ +char *oldp; +u64 start_at, mem_size; + +if (!strcmp (p,"exactmap" )) { +#ifdef CONFIG_CRASH_DUMP +/* +* If we are doing a crash dump, we still need to know +* the real mem size before original memory map is +* reset. +*/ +e820_register_active_regions (0 ,0 ,-1UL ); + saved_max_pfn =e820_end_of_ram (); +remove_all_active_ranges (); +#endif + e820.nr_map =0 ; + userdef =1 ; +return 0 ; + } + + oldp = p; + mem_size =memparse (p, &p); +if (p == oldp) +return -EINVAL ; + + userdef =1 ; +if (*p =='@' ) { + start_at =memparse (p+1 , &p); +add_memory_region (start_at, mem_size,E820_RAM ); + }else if (*p =='#' ) { + start_at =memparse (p+1 , &p); +add_memory_region (start_at, mem_size,E820_ACPI ); + }else if (*p =='$' ) { + start_at =memparse (p+1 , &p); +add_memory_region (start_at, mem_size,E820_RESERVED ); + }else { + end_user_pfn = (mem_size >>PAGE_SHIFT ); + } +return *p =='\0' ?0 : -EINVAL ; +} +early_param ("memmap" , parse_memmap_opt); + +void __init finish_e820_parsing (void ) +{ +if (userdef) { +int nr = e820.nr_map; + +if (sanitize_e820_map (e820.map,ARRAY_SIZE (e820.map), &nr) <0 ) +early_panic ("Invalid user supplied memory map" ); + e820.nr_map = nr; + +printk (KERN_INFO "user-defined physical RAM map:\n" ); +e820_print_map ("user" ); + } +}
arch/x86/kernel/e820_32.c +0 -120
129 lines not on this page · raw message
arch/x86/kernel/e820_64.c +0 -69
75 lines not on this page · raw message
include/asm-x86/e820.h +2 -0
@@ -97,6 +97,8 @@ extern int e820_find_active_region(constextern void e820_register_active_regions (int nid,unsigned long start_pfn,unsigned long end_pfn);extern u64 e820_hole_size (u64 start,u64 end); +extern void finish_e820_parsing (void ); +#endif /* __ASSEMBLY__ */ #define ISA_START_ADDRESS 0xa0000
include/asm-x86/e820_32.h +0 -2
@@ -19,9 +19,7 @@#ifndef __ASSEMBLY__extern void setup_memory_map (void ); -extern void finish_e820_parsing (void ); -extern void limit_regions (unsigned long long size);extern void init_iomem_resources (struct resource *code_resource,struct resource *data_resource,struct resource *bss_resource);
include/asm-x86/e820_64.h +0 -2
@@ -22,8 +22,6 @@ extern int is_memory_any_valid(unsignedextern int e820_all_non_reserved (unsigned long start,unsigned long end);extern int is_memory_all_valid (unsigned long start,unsigned long end); -extern void finish_e820_parsing (void ); -#endif /*!__ASSEMBLY__*/ #endif /*__E820_HEADER*/
Ingo Molnar
AppliedRe: [PATCH] x86: move e820_register_active to e820.c
In reply to Yinghai LuQuoted 3 lines · Yinghai Lu
to prepare 32 bit to use it
Signed-off-by Yinghai Lu <[email protected]>
applied, thanks.
Ingo
Ingo Molnar
AppliedQuoted 4 lines · Yinghai Lu
so could fallback one node numa
v2: usingfound_numaqwithMP_processor_infoandMP_bus_infoSigned-off-by Yinghai Lu <[email protected]>
applied, thanks.
Ingo