discontig patch (work in progress)
Subsystems (2)
PATCH 1/1 discontig patch (work in progress)
I spent some time trying to make things a little clearer, eliminate some redundancy, conform to coding style, and generally cleanup the patch. The contig/discontig split patch I posted still hasn't made its way to lia64.bkbits.net, so this patch is against a tree with my patch applied. I still plan on splitting things out quite a bit more and cleaning more stuff up, but I thought I'd post this so people can look at it.
arch/ia64/Kconfig | 30 -- arch/ia64/Makefile | 2 arch/ia64/kernel/acpi.c | 30 -- arch/ia64/kernel/setup.c | 34 --- arch/ia64/mm/contig.c | 33 +++ arch/ia64/mm/discontig.c | 471 +++++++++++++++++++++++--------------------- arch/ia64/mm/init.c | 167 +++++++-------- include/asm-ia64/meminit.h | 8 include/asm-ia64/mmzone.h | 144 ++----------- include/asm-ia64/nodedata.h | 29 -- include/asm-ia64/numa.h | 19 + include/asm-ia64/page.h | 8 include/asm-ia64/percpu.h | 1 include/asm-ia64/pgtable.h | 4 include/linux/mm.h | 5 kernel/ksyms.c | 2 mm/memory.c | 2
One thing that immediately springs to mind is the per-cpu stuff. That should probably be split into contig and discontig versions and put in the appropriate files, and obviously the non-ia64 stuff (!CONFIG_DISCONTIGMEM -> CONFIG_VIRTUAL_MEM_MAP || !CONFIG_DISCONTIGMEM) will be split out and sent seperately. I could probably also seperate the patch that changes the arguments to the callback functions to be more consistent. And of course there's other cleanup that needs to be done, like removing the shouting from GRANULEROUND* and naming nodeid() something better (maybe numa_node_id()?).
Thanks,
Jesse
arch/ia64/Kconfig +5 -25
@@ -220,24 +220,8 @@ Access). This option is for configuring high-end multiprocessor server systems. If in doubt, say N. -choice - prompt "Maximum Memory per NUMA Node" if NUMA && IA64_DIG - depends on NUMA && IA64_DIG - default IA64_NODESIZE_16GB - -config IA64_NODESIZE_16GB - bool "16GB" - -config IA64_NODESIZE_64GB - bool "64GB" - -config IA64_NODESIZE_256GB - bool "256GB" - -endchoice - config DISCONTIGMEM - bool "Discontiguous memory support" if (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA + bool "Discontiguous memory support" if (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA && VIRTUAL_MEM_MAP default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA help Say Y to support efficient handling of discontiguous physical memory,
@@ -250,14 +234,10 @@ default y if !IA64_HP_SIM help Say Y to compile the kernel with support for a virtual mem map. - This is an alternate method of supporting large holes in the - physical address space on non NUMA machines. Since the DISCONTIGMEM - option is not supported on machines with the ZX1 chipset, this is - the only way of supporting more than 1 Gb of memory on those - machines. This code also only takes effect if a memory hole of - greater than 1 Gb is found during boot, so it is safe to enable - unless you require the DISCONTIGMEM option for your machine. If you - are unsure, say Y. + This code also only takes effect if a memory hole of greater than + 1 Gb is found during boot. You must turn this option on if you + require the DISCONTIGMEM option for your machine. If you are + unsure, say Y. config IA64_MCA bool "Enable IA-64 Machine Check Abort"
arch/ia64/Makefile +1 -1
@@ -64,7 +64,7 @@ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ -drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ +drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/ drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/ boot := arch/ia64/hp/sim/boot
arch/ia64/kernel/acpi.c +1 -29
@@ -379,7 +379,7 @@void __init acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma) { -unsigned long paddr, size, hole_size, min_hole_size; +unsigned long paddr, size;u8 pxm;struct node_memblk_s *p, *q, *pend;
@@ -401,34 +401,6 @@if (!ma->flags.enabled)return ; -/* -* When the chunk is not the first one in the node, check distance -* from the other chunks. When the hole is too huge ignore the chunk. -* This restriction should be removed when multiple chunks per node -* is supported. -*/ - pend = &node_memblk[num_memblks]; - min_hole_size =0 ; -for (p = &node_memblk[0 ]; p < pend; p++) { -if (p->nid != pxm) -continue ; -if (p->start_paddr < paddr) - hole_size = paddr - (p->start_paddr + p->size); -else - hole_size = p->start_paddr - (paddr + size); - -if (!min_hole_size || hole_size < min_hole_size) - min_hole_size = hole_size; - } - -if (min_hole_size) { -if (min_hole_size > size) { -printk (KERN_ERR "Too huge memory hole. Ignoring %ld MBytes at %lx\n" , - size/(1024 *1024 ), paddr); -return ; - } - } -/* record this node in proximity bitmap */ pxm_bit_set (pxm);
arch/ia64/kernel/setup.c +7 -27
@@ -101,7 +101,7 @@ filter_rsvd_memory (unsigned long start, unsigned long end, void *arg) {unsigned long range_start, range_end, prev_start; -void (*func)(unsigned long ,unsigned long ); +void (*func)(unsigned long ,unsigned long ,int );int i;#if IGNORE_PFN0
@@ -123,9 +123,9 @@ if (range_start < range_end)#ifdef CONFIG_DISCONTIGMEM -call_pernode_memory (__pa (range_start),__pa (range_end), func); +call_pernode_memory (range_start, range_end, arg);#else - (*func)(__pa (range_start), range_end - range_start); + (*func)(range_start, range_end,0 );#endif /* nothing more available in this segment */
@@ -237,7 +237,6 @@strlcpy (saved_command_line, *cmdline_p,sizeof (saved_command_line));efi_init (); -find_memory ();#ifdef CONFIG_ACPI_BOOT /* Initialize the ACPI boot-time table parser */
@@ -251,6 +250,8 @@# endif #endif /* CONFIG_APCI_BOOT */ +find_memory (); +/* process SAL system table: */ ia64_sal_init (efi.sal_systab);
@@ -542,28 +543,7 @@struct cpuinfo_ia64 *cpu_info;void *cpu_data; -#ifdef CONFIG_SMP -int cpu; - -/* -* get_free_pages() cannot be used before cpu_init() done. BSP allocates -* "NR_CPUS" pages for all CPUs to avoid that AP calls get_zeroed_page(). -*/ -if (smp_processor_id () =0 ) { - cpu_data =__alloc_bootmem (PERCPU_PAGE_SIZE *NR_CPUS ,PERCPU_PAGE_SIZE , -__pa (MAX_DMA_ADDRESS )); -for (cpu =0 ; cpu <NR_CPUS ; cpu++) { -memcpy (cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); - __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; - cpu_data +=PERCPU_PAGE_SIZE ; - -per_cpu (local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; - } - } - cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id ()]; -#else /* !CONFIG_SMP */ - cpu_data = __phys_per_cpu_start; -#endif /* !CONFIG_SMP */ + cpu_data =per_cpu_init ();get_max_cacheline_size ();
@@ -575,7 +555,7 @@*/ cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var (cpu_info) - __per_cpu_start);#ifdef CONFIG_NUMA - cpu_info->node_data =get_node_data_ptr (); + cpu_info->node_data =early_get_node_data ();#endif identify_cpu (cpu_info);
arch/ia64/mm/contig.c +33 -0
@@ -155,3 +155,36 @@find_initrd (); } + +/** +* per_cpu_init - setup per-cpu variables +* +* Allocate and setup per-cpu data areas. +*/ +void *per_cpu_init (void ) +{ +void *cpu_data; + +#ifdef CONFIG_SMP +int cpu; + +/* +* get_free_pages() cannot be used before cpu_init() done. BSP allocates +* "NR_CPUS" pages for all CPUs to avoid that AP calls get_zeroed_page(). +*/ + +if (smp_processor_id () =0 ) { + cpu_data =__alloc_bootmem (PERCPU_PAGE_SIZE *NR_CPUS ,PERCPU_PAGE_SIZE , +__pa (MAX_DMA_ADDRESS )); +for (cpu =0 ; cpu <NR_CPUS ; cpu++) { +memcpy (cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); + __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; + cpu_data +=PERCPU_PAGE_SIZE ; +per_cpu (local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; + } + } +return __per_cpu_start + __per_cpu_offset[smp_processor_id ()]; +#else /* !CONFIG_SMP */ +return __phys_per_cpu_start; +#endif /* !CONFIG_SMP */ +}
arch/ia64/mm/discontig.c +250 -220
593 lines not on this page · raw message
arch/ia64/mm/init.c +81 -86
241 lines not on this page · raw message
include/asm-ia64/meminit.h +8 -0
@@ -31,6 +31,14 @@extern void find_initrd (void );extern int filter_rsvd_memory (unsigned long start,unsigned long end,void *arg); +extern void paging_init (void ); + +/* +* For rounding an address to the next IA64_GRANULE_SIZE or order +*/ +#define GRANULEROUNDDOWN (n) ((n) & ~(IA64_GRANULE_SIZE-1)) +#define GRANULEROUNDUP (n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1)) +#define ORDERROUNDDOWN (n) ((n) & ~((PAGE_SIZE<<MAX_ORDER)-1))#ifdef CONFIG_DISCONTIGMEM extern void call_pernode_memory (unsigned long start,unsigned long end,void *arg);
include/asm-ia64/mmzone.h +22 -122
179 lines not on this page · raw message
include/asm-ia64/nodedata.h +3 -26
@@ -13,7 +13,7 @@#ifndef _ASM_IA64_NODEDATA_H#define _ASM_IA64_NODEDATA_H - +#include <asm/percpu.h> #include <asm/mmzone.h> /*
@@ -24,10 +24,7 @@struct ia64_node_data {short active_cpu_count;short node; -struct pglist_data *pg_data_ptrs[NR_NODES ]; -struct page *bank_mem_map_base[NR_BANKS ]; -struct ia64_node_data *node_data_ptrs[NR_NODES ]; -short node_id_map[NR_BANKS ]; +struct pglist_data *pg_data_ptrs[NR_NODES ]; };
@@ -36,41 +33,21 @@*/ #define local_node_data (local_cpu_data->node_data) - -/* -* Return a pointer to the node_data structure for the specified node. -*/ -#define node_data (node) (local_node_data->node_data_ptrs[node]) -/* * Get a pointer to the node_id/node_data for the current cpu. * (boot time only) */ -extern int boot_get_local_nodeid (void ); -extern struct ia64_node_data *get_node_data_ptr (void ); +extern struct ia64_node_data *early_get_node_data (void );/* * Given a node id, return a pointer to the pg_data_t for the node. -* The following 2 macros are similar. * * NODE_DATA - should be used in all code not related to system * initialization. It uses pernode data structures to minimize * offnode memory references. However, these structure are not * present during boot. This macro can be used once cpu_init * completes. -* -* BOOT_NODE_DATA -* - should be used during system initialization -* prior to freeing __initdata. It does not depend on the percpu -* area being present. -* -* NOTE: The names of these macros are misleading but are difficult to change -* since they are used in generic linux & on other architecures. */ #define NODE_DATA (nid) (local_node_data->pg_data_ptrs[nid]) -#define BOOT_NODE_DATA (nid) boot_get_pg_data_ptr((long)(nid)) - -struct pglist_data ; -extern struct pglist_data *__init boot_get_pg_data_ptr (long );#endif /* _ASM_IA64_NODEDATA_H */
include/asm-ia64/numa.h +16 -3
@@ -13,18 +13,25 @@#include <linux/config.h> #include <linux/cpumask.h> +#include <linux/cache.h> +#include <linux/threads.h> +#include <linux/smp.h> #ifdef CONFIG_NUMA #ifdef CONFIG_DISCONTIGMEM # include <asm/mmzone.h> -# define NR_MEMBLKS (NR_BANKS)#else # define NR_NODES (8)# define NR_MEMBLKS (NR_NODES * 8)#endif -#include <linux/cache.h> +#define NODEMASK_WORDCOUNT ((NR_NODES+(BITS_PER_LONG-1))/BITS_PER_LONG) + +#define NODE_MASK_NONE { [0 ... ((NR_NODES+BITS_PER_LONG-1)/BITS_PER_LONG)-1] = 0 } + +typedef unsigned long nodemask_t [NODEMASK_WORDCOUNT ]; + extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned; extern volatile cpumask_t node_to_cpu_mask[NR_NODES] __cacheline_aligned;
@@ -65,7 +72,13 @@extern int paddr_to_nid (unsigned long paddr); -#define local_nodeid (cpu_to_node_map[smp_processor_id()]) +#define nodeid () ((int)cpu_to_node_map[smp_processor_id()]) + +#else /* !CONFIG_NUMA */ + +#define node_distance (from,to) 10 +#define paddr_to_nid (x) 0 +#define nodeid () 0#endif /* CONFIG_NUMA */
include/asm-ia64/page.h +3 -5
@@ -94,18 +94,16 @@#define virt_addr_valid (kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) -#ifndef CONFIG_DISCONTIGMEM -# ifdef CONFIG_VIRTUAL_MEM_MAP +#ifdef CONFIG_VIRTUAL_MEM_MAP extern int ia64_pfn_valid (unsigned long pfn);# define pfn_valid (pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn)) -# else +#else # define pfn_valid (pfn) ((pfn) < max_mapnr) -# endif +#endif #define virt_to_page (kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)#define page_to_pfn (page) ((unsigned long) (page - mem_map))#define pfn_to_page (pfn) (mem_map + (pfn))#define page_to_phys (page) (page_to_pfn(page) << PAGE_SHIFT) -#endif typedef union ia64_va { struct {
include/asm-ia64/percpu.h +1 -0
@@ -46,6 +46,7 @@extern void percpu_modcopy (void *pcpudst,const void *src,unsigned long size);extern void setup_per_cpu_areas (void ); +extern void *per_cpu_init (void );#else /* ! SMP */
include/asm-ia64/pgtable.h +0 -1
@@ -174,7 +174,6 @@return (addr & (local_cpu_data->unimpl_pa_mask)) =0 ; } -#ifndef CONFIG_DISCONTIGMEM /* * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel * memory. For the return value to be meaningful, ADDR must be >@@ -190,7 +189,6 @@
*/
#define kern_addr_valid(addr) (1)
-#endif
/*
* Now come the defines and routines to manage and access the three-level
@@ -241,10 +239,8 @@
#define pte_none(pte) (!pte_val(pte))
#define pte_present(pte) (pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
#define pte_clear(pte) (pte_val(*(pte)) = 0UL)
-#ifndef CONFIG_DISCONTIGMEM
/* pte_page() returns the "struct page *" corresponding to the PTE: */
#define pte_page(pte) virt_to_page(((pte_val(pte) & _PFN_MASK) + PAGE_OFFSET))
-#endif
#define pmd_none(pmd) (!pmd_val(pmd))
#define pmd_bad(pmd) (!ia64_phys_addr_valid(pmd_val(pmd)))
include/linux/mm.h +3 -2
@@ -13,7 +13,8 @@#include <linux/rbtree.h> #include <linux/fs.h> -#ifndef CONFIG_DISCONTIGMEM /* Don't use mapnrs, do it properly */ +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM ) +/* Don't use mapnrs, do it properly */ extern unsigned long max_mapnr;#endif
@@ -340,7 +341,7 @@ page->flags |= zone_num <<ZONE_SHIFT ; } -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )/* The array of struct pages - for discontigmem use pgdat->lmem_map */ extern struct page *mem_map;#endif
kernel/ksyms.c +1 -1
@@ -114,7 +114,7 @@EXPORT_SYMBOL (vunmap);EXPORT_SYMBOL (vmalloc_to_page);EXPORT_SYMBOL (remap_page_range); -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )EXPORT_SYMBOL (contig_page_data);EXPORT_SYMBOL (mem_map);EXPORT_SYMBOL (max_mapnr);
mm/memory.c +1 -1
@@ -55,7 +55,7 @@#include <linux/swapops.h> -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )/* use the per-pgdat data instead for discontigmem - mbligh */ unsigned long max_mapnr;struct page *mem_map;
Quoted 2 lines · Jesse Barnes
done, like removing the shouting from GRANULEROUND* and naming
nodeid()something better (maybenuma_node_id()?).
How about I just nuke it since numa_node_id() is already defined in include/linux/mmzone.h? Here's an updated version. And even though CONFIG_DISCONTIGMEM depends on CONFIG_VIRTUAL_MEM_MAP with this patch, I've left the #if defined(VIRTUAL_MEM_MAP) || !defined(DISCONTIGMEM) in the ia64 files as opposed to removing them altogether since (1) it's more consistent with the rest of the tree that way and (2) I'd like to remove that dependency so we can measure the perf. impact of virtual memmap on discontig machines like David said he wanted to do for zx1.
Thanks,
Jesse
arch/ia64/Kconfig +5 -25
@@ -220,24 +220,8 @@ Access). This option is for configuring high-end multiprocessor server systems. If in doubt, say N. -choice - prompt "Maximum Memory per NUMA Node" if NUMA && IA64_DIG - depends on NUMA && IA64_DIG - default IA64_NODESIZE_16GB - -config IA64_NODESIZE_16GB - bool "16GB" - -config IA64_NODESIZE_64GB - bool "64GB" - -config IA64_NODESIZE_256GB - bool "256GB" - -endchoice - config DISCONTIGMEM - bool "Discontiguous memory support" if (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA + bool "Discontiguous memory support" if (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA && VIRTUAL_MEM_MAP default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA help Say Y to support efficient handling of discontiguous physical memory,
@@ -250,14 +234,10 @@ default y if !IA64_HP_SIM help Say Y to compile the kernel with support for a virtual mem map. - This is an alternate method of supporting large holes in the - physical address space on non NUMA machines. Since the DISCONTIGMEM - option is not supported on machines with the ZX1 chipset, this is - the only way of supporting more than 1 Gb of memory on those - machines. This code also only takes effect if a memory hole of - greater than 1 Gb is found during boot, so it is safe to enable - unless you require the DISCONTIGMEM option for your machine. If you - are unsure, say Y. + This code also only takes effect if a memory hole of greater than + 1 Gb is found during boot. You must turn this option on if you + require the DISCONTIGMEM option for your machine. If you are + unsure, say Y. config IA64_MCA bool "Enable IA-64 Machine Check Abort"
arch/ia64/Makefile +1 -1
@@ -64,7 +64,7 @@ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ -drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ +drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/ drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/ boot := arch/ia64/hp/sim/boot
arch/ia64/kernel/acpi.c +1 -29
@@ -379,7 +379,7 @@void __init acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma) { -unsigned long paddr, size, hole_size, min_hole_size; +unsigned long paddr, size;u8 pxm;struct node_memblk_s *p, *q, *pend;
@@ -401,34 +401,6 @@if (!ma->flags.enabled)return ; -/* -* When the chunk is not the first one in the node, check distance -* from the other chunks. When the hole is too huge ignore the chunk. -* This restriction should be removed when multiple chunks per node -* is supported. -*/ - pend = &node_memblk[num_memblks]; - min_hole_size =0 ; -for (p = &node_memblk[0 ]; p < pend; p++) { -if (p->nid != pxm) -continue ; -if (p->start_paddr < paddr) - hole_size = paddr - (p->start_paddr + p->size); -else - hole_size = p->start_paddr - (paddr + size); - -if (!min_hole_size || hole_size < min_hole_size) - min_hole_size = hole_size; - } - -if (min_hole_size) { -if (min_hole_size > size) { -printk (KERN_ERR "Too huge memory hole. Ignoring %ld MBytes at %lx\n" , - size/(1024 *1024 ), paddr); -return ; - } - } -/* record this node in proximity bitmap */ pxm_bit_set (pxm);
arch/ia64/kernel/setup.c +7 -27
@@ -101,7 +101,7 @@ filter_rsvd_memory (unsigned long start, unsigned long end, void *arg) {unsigned long range_start, range_end, prev_start; -void (*func)(unsigned long ,unsigned long ); +void (*func)(unsigned long ,unsigned long ,int );int i;#if IGNORE_PFN0
@@ -123,9 +123,9 @@ if (range_start < range_end)#ifdef CONFIG_DISCONTIGMEM -call_pernode_memory (__pa (range_start),__pa (range_end), func); +call_pernode_memory (range_start, range_end, arg);#else - (*func)(__pa (range_start), range_end - range_start); + (*func)(range_start, range_end,0 );#endif /* nothing more available in this segment */
@@ -237,7 +237,6 @@strlcpy (saved_command_line, *cmdline_p,sizeof (saved_command_line));efi_init (); -find_memory ();#ifdef CONFIG_ACPI_BOOT /* Initialize the ACPI boot-time table parser */
@@ -251,6 +250,8 @@# endif #endif /* CONFIG_APCI_BOOT */ +find_memory (); +/* process SAL system table: */ ia64_sal_init (efi.sal_systab);
@@ -542,28 +543,7 @@struct cpuinfo_ia64 *cpu_info;void *cpu_data; -#ifdef CONFIG_SMP -int cpu; - -/* -* get_free_pages() cannot be used before cpu_init() done. BSP allocates -* "NR_CPUS" pages for all CPUs to avoid that AP calls get_zeroed_page(). -*/ -if (smp_processor_id () =0 ) { - cpu_data =__alloc_bootmem (PERCPU_PAGE_SIZE *NR_CPUS ,PERCPU_PAGE_SIZE , -__pa (MAX_DMA_ADDRESS )); -for (cpu =0 ; cpu <NR_CPUS ; cpu++) { -memcpy (cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); - __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; - cpu_data +=PERCPU_PAGE_SIZE ; - -per_cpu (local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; - } - } - cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id ()]; -#else /* !CONFIG_SMP */ - cpu_data = __phys_per_cpu_start; -#endif /* !CONFIG_SMP */ + cpu_data =per_cpu_init ();get_max_cacheline_size ();
@@ -575,7 +555,7 @@*/ cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var (cpu_info) - __per_cpu_start);#ifdef CONFIG_NUMA - cpu_info->node_data =get_node_data_ptr (); + cpu_info->node_data =early_get_node_data ();#endif identify_cpu (cpu_info);
arch/ia64/mm/contig.c +33 -0
@@ -155,3 +155,36 @@find_initrd (); } + +/** +* per_cpu_init - setup per-cpu variables +* +* Allocate and setup per-cpu data areas. +*/ +void *per_cpu_init (void ) +{ +void *cpu_data; + +#ifdef CONFIG_SMP +int cpu; + +/* +* get_free_pages() cannot be used before cpu_init() done. BSP allocates +* "NR_CPUS" pages for all CPUs to avoid that AP calls get_zeroed_page(). +*/ + +if (smp_processor_id () =0 ) { + cpu_data =__alloc_bootmem (PERCPU_PAGE_SIZE *NR_CPUS ,PERCPU_PAGE_SIZE , +__pa (MAX_DMA_ADDRESS )); +for (cpu =0 ; cpu <NR_CPUS ; cpu++) { +memcpy (cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); + __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; + cpu_data +=PERCPU_PAGE_SIZE ; +per_cpu (local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; + } + } +return __per_cpu_start + __per_cpu_offset[smp_processor_id ()]; +#else /* !CONFIG_SMP */ +return __phys_per_cpu_start; +#endif /* !CONFIG_SMP */ +}
arch/ia64/mm/discontig.c +250 -220
593 lines not on this page · raw message
arch/ia64/mm/init.c +83 -86
243 lines not on this page · raw message
include/asm-ia64/meminit.h +8 -0
@@ -31,6 +31,14 @@extern void find_initrd (void );extern int filter_rsvd_memory (unsigned long start,unsigned long end,void *arg); +extern void paging_init (void ); + +/* +* For rounding an address to the next IA64_GRANULE_SIZE or order +*/ +#define GRANULEROUNDDOWN (n) ((n) & ~(IA64_GRANULE_SIZE-1)) +#define GRANULEROUNDUP (n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1)) +#define ORDERROUNDDOWN (n) ((n) & ~((PAGE_SIZE<<MAX_ORDER)-1))#ifdef CONFIG_DISCONTIGMEM extern void call_pernode_memory (unsigned long start,unsigned long end,void *arg);
include/asm-ia64/mmzone.h +26 -129
185 lines not on this page · raw message
include/asm-ia64/nodedata.h +3 -26
@@ -13,7 +13,7 @@#ifndef _ASM_IA64_NODEDATA_H#define _ASM_IA64_NODEDATA_H - +#include <asm/percpu.h> #include <asm/mmzone.h> /*
@@ -24,10 +24,7 @@struct ia64_node_data {short active_cpu_count;short node; -struct pglist_data *pg_data_ptrs[NR_NODES ]; -struct page *bank_mem_map_base[NR_BANKS ]; -struct ia64_node_data *node_data_ptrs[NR_NODES ]; -short node_id_map[NR_BANKS ]; +struct pglist_data *pg_data_ptrs[NR_NODES ]; };
@@ -36,41 +33,21 @@*/ #define local_node_data (local_cpu_data->node_data) - -/* -* Return a pointer to the node_data structure for the specified node. -*/ -#define node_data (node) (local_node_data->node_data_ptrs[node]) -/* * Get a pointer to the node_id/node_data for the current cpu. * (boot time only) */ -extern int boot_get_local_nodeid (void ); -extern struct ia64_node_data *get_node_data_ptr (void ); +extern struct ia64_node_data *early_get_node_data (void );/* * Given a node id, return a pointer to the pg_data_t for the node. -* The following 2 macros are similar. * * NODE_DATA - should be used in all code not related to system * initialization. It uses pernode data structures to minimize * offnode memory references. However, these structure are not * present during boot. This macro can be used once cpu_init * completes. -* -* BOOT_NODE_DATA -* - should be used during system initialization -* prior to freeing __initdata. It does not depend on the percpu -* area being present. -* -* NOTE: The names of these macros are misleading but are difficult to change -* since they are used in generic linux & on other architecures. */ #define NODE_DATA (nid) (local_node_data->pg_data_ptrs[nid]) -#define BOOT_NODE_DATA (nid) boot_get_pg_data_ptr((long)(nid)) - -struct pglist_data ; -extern struct pglist_data *__init boot_get_pg_data_ptr (long );#endif /* _ASM_IA64_NODEDATA_H */
include/asm-ia64/numa.h +8 -10
@@ -13,18 +13,13 @@#include <linux/config.h> #include <linux/cpumask.h> +#include <linux/cache.h> +#include <linux/threads.h> +#include <linux/smp.h> +#include <asm/mmzone.h> #ifdef CONFIG_NUMA -#ifdef CONFIG_DISCONTIGMEM -# include <asm/mmzone.h> -# define NR_MEMBLKS (NR_BANKS) -#else -# define NR_NODES (8) -# define NR_MEMBLKS (NR_NODES * 8) -#endif - -#include <linux/cache.h> extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned; extern volatile cpumask_t node_to_cpu_mask[NR_NODES] __cacheline_aligned;
@@ -65,7 +60,10 @@extern int paddr_to_nid (unsigned long paddr); -#define local_nodeid (cpu_to_node_map[smp_processor_id()]) +#else /* !CONFIG_NUMA */ + +#define node_distance (from,to) 10 +#define paddr_to_nid (x) 0#endif /* CONFIG_NUMA */
include/asm-ia64/page.h +3 -5
@@ -94,18 +94,16 @@#define virt_addr_valid (kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) -#ifndef CONFIG_DISCONTIGMEM -# ifdef CONFIG_VIRTUAL_MEM_MAP +#ifdef CONFIG_VIRTUAL_MEM_MAP extern int ia64_pfn_valid (unsigned long pfn);# define pfn_valid (pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn)) -# else +#else # define pfn_valid (pfn) ((pfn) < max_mapnr) -# endif +#endif #define virt_to_page (kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)#define page_to_pfn (page) ((unsigned long) (page - mem_map))#define pfn_to_page (pfn) (mem_map + (pfn))#define page_to_phys (page) (page_to_pfn(page) << PAGE_SHIFT) -#endif typedef union ia64_va { struct {
include/asm-ia64/percpu.h +1 -0
@@ -46,6 +46,7 @@extern void percpu_modcopy (void *pcpudst,const void *src,unsigned long size);extern void setup_per_cpu_areas (void ); +extern void *per_cpu_init (void );#else /* ! SMP */
include/asm-ia64/pgtable.h +1 -1
@@ -174,7 +174,7 @@return (addr & (local_cpu_data->unimpl_pa_mask)) =0 ; } -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )/* * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel * memory. For the return value to be meaningful, ADDR must be >@@ -190,7 +190,7 @@
*/
#define kern_addr_valid(addr) (1)
-#endif
+#endif /* CONFIG_VIRTUAL_MEM_MAP || !CONFIG_DISCONTIGMEM */
/*
* Now come the defines and routines to manage and access the three-level
@@ -241,10 +241,10 @@
#define pte_none(pte) (!pte_val(pte))
#define pte_present(pte) (pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
#define pte_clear(pte) (pte_val(*(pte)) = 0UL)
-#ifndef CONFIG_DISCONTIGMEM
+#if defined(CONFIG_VIRTUAL_MEM_MAP) || !defined(CONFIG_DISCONTIGMEM)
/* pte_page() returns the "struct page *" corresponding to the PTE: */
#define pte_page(pte) virt_to_page(((pte_val(pte) & _PFN_MASK) + PAGE_OFFSET))
-#endif
+#endif /* CONFIG_VIRTUAL_MEM_MAP || !CONFIG_DISCONTIGMEM */
#define pmd_none(pmd) (!pmd_val(pmd))
#define pmd_bad(pmd) (!ia64_phys_addr_valid(pmd_val(pmd)))
include/linux/mm.h +3 -2
@@ -13,7 +13,8 @@#include <linux/rbtree.h> #include <linux/fs.h> -#ifndef CONFIG_DISCONTIGMEM /* Don't use mapnrs, do it properly */ +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM ) +/* Don't use mapnrs, do it properly */ extern unsigned long max_mapnr;#endif
@@ -340,7 +341,7 @@ page->flags |= zone_num <<ZONE_SHIFT ; } -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )/* The array of struct pages - for discontigmem use pgdat->lmem_map */ extern struct page *mem_map;#endif
kernel/ksyms.c +1 -1
@@ -114,7 +114,7 @@EXPORT_SYMBOL (vunmap);EXPORT_SYMBOL (vmalloc_to_page);EXPORT_SYMBOL (remap_page_range); -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )EXPORT_SYMBOL (contig_page_data);EXPORT_SYMBOL (mem_map);EXPORT_SYMBOL (max_mapnr);
mm/memory.c +1 -1
@@ -55,7 +55,7 @@#include <linux/swapops.h> -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )/* use the per-pgdat data instead for discontigmem - mbligh */ unsigned long max_mapnr;struct page *mem_map;
Quoted 4 lines · Jesse Barnes
Quoted 2 lines · Jesse Barnes
done, like removing the shouting from GRANULEROUND* and naming
nodeid()something better (maybenuma_node_id()?).
Quoted 8 lines
How about I just nuke it since
numa_node_id()is already defined ininclude/linux/mmzone.h? Here's an updated version. And even thoughCONFIG_DISCONTIGMEMdepends onCONFIG_VIRTUAL_MEM_MAPwith this patch, I've left the #ifdefined(VIRTUAL_MEM_MAP)|| !defined(DISCONTIGMEM) in the ia64 files as opposed to removing them altogether since (1) it's more consistent with the rest of the tree that way and (2) I'd like to remove that dependency so we can measure the perf. impact of virtual memmap on discontig machines like David said he wanted to do for zx1.
The #if defined(VIRTUAL_MEM_MAP) || !defined(DISCONTIGMEM) in generic code have to go away. All this mem_map/contig_page_data/etc crap has should probably go away some day, but for now let's not make it even messier.
Also in the discontig + vmem_map case you don't want them - always use the per-node mem_maps even if it's just to avoid the pagetable lookups and to be more similar to the other arches numa code.
More comments:
#ifdef CONFIG_DISCONTIGMEM
- call_pernode_memory(__pa(range_start), __pa(range_end), func);
+ call_pernode_memory(range_start, range_end, arg);
#else
- (*func)(__pa(range_start), range_end - range_start);
+ (*func)(range_start, range_end, 0);
#endif
What's the point of passing arg directly here if we just casted it to func? Also the ifdef is horrible. Please add a call_pernode_memory wrapper for !CONFIG_DISCONTIGMEM ala
#define call_pernode_memory(start, end, func) (*func)(start, end, 0)
What about moving call_pernode_memory to discontig.c?
--------
count_cpus() seems to reimplemement nr_cpus_node() from topology.h badly, or is it just me?
--------
per_cpu_init looks strange, in the !SMP case both implementations are identical and have an unused variable..
What about just having
#ifdef CONFIG_SMP
extern void *per_cpu_init(void);
#else
# define per_cpu_init() (__phys_per_cpu_start) #endif
into percpu.h?
This whole per-cpu thing looks like a candidate for the next small patch.
--------
+ if (numnodes = 1 && max_gap < LARGE_GAP) {
+ /* Just one node with no big holes... */
+ vmem_map = (struct page *)0;
+ zones_size[ZONE_DMA] += cdata.min_pfn;
+ zholes_size[ZONE_DMA] += cdata.min_pfn;
+ free_area_init_node(0, NODE_DATA(node), NODE_DATA(node)->node_mem_map,
+ zones_size, 0, zholes_size);
+ }
+ else {
+ /* allocate virtual mem_map */
+ if (node = 0) {
+ unsigned long map_size;
+ map_size = PAGE_ALIGN(max_low_pfn*sizeof(struct page));
+ vmalloc_end -= map_size;
+ vmem_map = (struct page *) vmalloc_end;
+ efi_memmap_walk(create_mem_map_page_table, 0);
+ printk("Virtual mem_map starts at 0x%p\n", vmem_map);
+ mem_map = vmem_map;
+ }
+ free_area_init_node(node, NODE_DATA(node), vmem_map + cdata.min_pfn,
+ zones_size, cdata.min_pfn, zholes_size);
+ }
}
Should look something like
/* Just one node with no big holes... */
if (numnodes = 1 && max_gap < LARGE_GAP) {
zones_size[ZONE_DMA] += cdata.min_pfn;
zholes_size[ZONE_DMA] += cdata.min_pfn;
/* XXX: probably already done somewhere else? */
mem_map = NODE_DATA(node)->node_mem_map;
pfn_offset = 0;
/* allocate virtual mem_map */
} else if (node = 0) {
vmalloc_end - PAGE_ALIGN(max_low_pfn * sizeof(struct page));
mem_map = vmem_map = (struct page *)vmalloc_end;
efi_memmap_walk(create_mem_map_page_table, 0);
pfn_offset = cdata.min_pfn;
}
free_area_init_node(node, NODE_DATA(node), mem_map + pfn_offset,
zones_size, pfn_offset, zholes_size);--------
- pgd_populate(&init_mm, pgd, alloc_bootmem_pages(PAGE_SIZE));
+ pgd_populate(&init_mm, pgd, alloc_bootmem_pages_node(NODE_DATA(node), PAGE_SIZE));
This could use some linewraps :) Also alloc_bootmem_pages_node probably wants a nid argument instead of of a pgdat, but that's not really in scope for this series..
--------
asm/mmzone.h looks a bit fishy. The SN2 and generic cases are the same, why not merge them. Also the £error is ugly - it if works for the generic kernel it'll surely work for a newly added arch, too, no?
What about something like:
/* DIG systems only support rather small configurations for now */ #ifdef CONFIG_IA64_DIG
#define MAX_PHYSNODE_ID 8
#define NR_NODES 8
#define NR_MEMBLKS (NR_NODES * 32) /* interleaved, contiguous memory */
#else
/* Currently SN2 marks the maximum. Should work for everyone else, too */
#define MAX_PHYSNODE_ID 2048
#define NR_NODES 256
#define NR_MEMBLKS (NR_NODES)
#endif
And as asm/mmzone.h is only included for CONFIG_DISCONTIGMEM and ia64 couples DISCONTIG and NUMA tighly you should just scrap the non-numa case in this file
--------
-#ifndef CONFIG_DISCONTIGMEM
-# ifdef CONFIG_VIRTUAL_MEM_MAP
+#ifdef CONFIG_VIRTUAL_MEM_MAP
extern int ia64_pfn_valid (unsigned long pfn);
# define pfn_valid(pfn) (((pfn) < max_mapnr) &&
# ia64_pfn_valid(pfn))
-# else
+#else
# define pfn_valid(pfn) ((pfn) < max_mapnr)
-# endif
+#endif
Didn't I tell you some time ago that the proper way to write this would be:
#ifdef CONFIG_VIRTUAL_MEM_MAP
extern int ia64_pfn_valid(unsigned long pfn);
#else
# define ia64_pfn_valid(pfn) 1 #endif
and then an unconditional
#define pfn_valid(pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn))
?
Quoted 4 lines · Christoph Hellwig
The #if
defined(VIRTUAL_MEM_MAP)|| !defined(DISCONTIGMEM) in generic code have to go away. All this mem_map/contig_page_data/etc crap has should probably go away some day, but for now let's not make it even messier.
Sure, I'm all for them going away, any suggestions on how to get there?
Quoted 3 lines
Also in the discontig +
vmem_mapcase you don't want them - always use the per-nodemem_mapseven if it's just to avoid the pagetable lookups and to be more similar to the other arches numa code.
The vmem_map is only used statically in arch/ia64/mm/init.c, but we use the global mem_map for the macros in include/asm-ia64/pgtable.h for convenience. There are a bunch of cases to deal with:
o CONFIG_VIRTUAL_MEM_MAP and !CONFIG_VIRTUAL_MEM_MAP
o CONFIG_DISCONTIGMEM and !CONFIG_DISCONTIGMEM
o any combination of the two above
We need CONFIG_VIRTUAL_MEM_MAP and CONFIG_DISCONTIGMEM work together at the very least so that ia64 generic kernels will work.
Quoted 11 lines
More comments:
#ifdef
CONFIG_DISCONTIGMEMarch/ia64/kernel/setup.c +1
-1-call_pernode_memory (__pa (range_start),__pa (range_end), func); +call_pernode_memory (range_start, range_end, arg);#else
arch/ia64/kernel/setup.c +1
-1- (*func)(__pa (range_start), range_end - range_start); + (*func)(range_start, range_end,0 );#endif
Quoted 3 lines
What's the point of passing arg directly here if we just casted it to func? Also the ifdef is horrible. Please add a
call_pernode_memorywrapper for !CONFIG_DISCONTIGMEM ala
Ok, I was thinking of doing that anyway.
Quoted 3 lines
#define
call_pernode_memory(start, end, func)(*func)(start, end, 0)What about moving
call_pernode_memorytodiscontig.c?
Yeah, this patch moves it there already.
Quoted 4 lines
--------
count_cpus()seems to reimplemementnr_cpus_node()fromtopology.hbadly, or is it just me?
No, you're probably right. I'll double check and remove it (had to do the same for local_nodeid->nodeid()->numa_node_id()->NULL because it was in topology.h. I don't know where this stuff came from *sigh*).
Quoted 5 lines
per_cpu_initlooks strange, in the !SMP case both implementations are identical and have an unused variable..What about just having
Quoted 7 lines
#ifdef
CONFIG_SMP
extern void*per_cpu_init(void);
#else# define per_cpu_init() (__phys_per_cpu_start) #endifinto
percpu.h?
Yeah, that's a good idea.
Quoted 1 line
This whole per-cpu thing looks like a candidate for the next small patch.
Sounds good.
Quoted 52 lines
--------
arch/ia64/mm/init.c +22
-0+if (numnodes =1 && max_gap <LARGE_GAP ) { +/* Just one node with no big holes... */ + vmem_map = (struct page *)0 ; + zones_size[ZONE_DMA ] += cdata.min_pfn; + zholes_size[ZONE_DMA ] += cdata.min_pfn; +free_area_init_node (0 ,NODE_DATA (node),NODE_DATA (node)->node_mem_map, + zones_size,0 , zholes_size); + } +else { +/* allocate virtual mem_map */ +if (node =0 ) { +unsigned long map_size; + map_size =PAGE_ALIGN (max_low_pfn*sizeof (struct page )); + vmalloc_end -= map_size; + vmem_map = (struct page *) vmalloc_end; +efi_memmap_walk (create_mem_map_page_table,0 ); +printk ("Virtual mem_map starts at 0x%p\n" , vmem_map); + mem_map = vmem_map; + } +free_area_init_node (node,NODE_DATA (node), vmem_map + cdata.min_pfn, + zones_size, cdata.min_pfn, zholes_size); + } }Should look something like
/* Just one node with no big holes... */ if (numnodes = 1 && max_gap < LARGE_GAP) { zones_size[ZONE_DMA] += cdata.min_pfn; zholes_size[ZONE_DMA] += cdata.min_pfn; /* XXX: probably already done somewhere else? */ mem_map = NODE_DATA(node)->node_mem_map; pfn_offset = 0; /* allocate virtual mem_map */ } else if (node = 0) { vmalloc_end -> PAGE_ALIGN(max_low_pfn * sizeof(struct page)); mem_map = vmem_map = (struct page *)vmalloc_end; efi_memmap_walk(create_mem_map_page_table, 0); pfn_offset = cdata.min_pfn; } free_area_init_node(node, NODE_DATA(node), mem_map + pfn_offset, zones_size, pfn_offset, zholes_size);
Quoted 1 line
--------
Yep, much better.
Quoted 6 lines
arch/ia64/mm/init.c +1
-1-pgd_populate (&init_mm, pgd,alloc_bootmem_pages (PAGE_SIZE )); +pgd_populate (&init_mm, pgd,alloc_bootmem_pages_node (NODE_DATA (node),PAGE_SIZE ));This could use some linewraps :) Also
alloc_bootmem_pages_nodeprobably wants a nid argument instead of of a pgdat, but that's not really in scope for this series..
Sure, that's another small patch, s/alloc_bootmem_pages/alloc_bootmem_pages_node(NODE_DATA(node)/g.
Quoted 5 lines
--------
asm/mmzone.hlooks a bit fishy. The SN2 and generic cases are the same, why not merge them. Also the ?error is ugly - it if works for the generic kernel it'll surely work for a newly added arch, too, no?
Probably, and making the worst case config and the generic config the same is a good idea.
Quoted 14 lines
What about something like:
/* DIG systems only support rather small configurations for now */ #ifdef
CONFIG_IA64_DIG
#defineMAX_PHYSNODE_ID8
#defineNR_NODES8
#defineNR_MEMBLKS(NR_NODES* 32) /* interleaved, contiguous memory */
#else
/* Currently SN2 marks the maximum. Should work for everyone else, too */
#defineMAX_PHYSNODE_ID2048
#defineNR_NODES256
#defineNR_MEMBLKS(NR_NODES)
#endif
Quoted 3 lines
And as
asm/mmzone.his only included forCONFIG_DISCONTIGMEMand ia64 couples DISCONTIG and NUMA tighly you should just scrap the non-numa case in this file
Ok.
Quoted 20 lines
--------
include/asm-ia64/page.h +3
-4-#ifndef CONFIG_DISCONTIGMEM -# ifdef CONFIG_VIRTUAL_MEM_MAP +#ifdef CONFIG_VIRTUAL_MEM_MAP extern int ia64_pfn_valid (unsigned long pfn);# define pfn_valid (pfn) (((pfn) < max_mapnr) &&# ia64_pfn_valid (pfn)) -# else +#else # define pfn_valid (pfn) ((pfn) < max_mapnr) -# endif +#endif Didn't I tell you some time ago that the proper way to write this would be:
#ifdef
CONFIG_VIRTUAL_MEM_MAP
extern intia64_pfn_valid(unsigned long pfn);
#else
Quoted 8 lines
# define ia64_pfn_valid(pfn) 1 #endifand then an unconditional
#define
pfn_valid(pfn)(((pfn) <max_mapnr) &&ia64_pfn_valid(pfn))?
Oops, I cleaned it up to remove a bunch of other stuff and lost that piece. I'll fix it.
Thanks,
Jesse
Quoted 6 lines · Jesse Barnes
Quoted 4 lines
The #if
defined(VIRTUAL_MEM_MAP)|| !defined(DISCONTIGMEM) in generic code have to go away. All this mem_map/contig_page_data/etc crap has should probably go away some day, but for now let's not make it even messier.Sure, I'm all for them going away, any suggestions on how to get there?
Always use the node-local mem_map, in the !DISCONTIG case we just have only one of them. But as said above this is in scope for this work (or 2.6 at all).
Quoted 11 lines
Quoted 3 lines
Also in the discontig +
vmem_mapcase you don't want them - always use the per-nodemem_mapseven if it's just to avoid the pagetable lookups and to be more similar to the other arches numa code.The
vmem_mapis only used statically inarch/ia64/mm/init.c, but we use the globalmem_mapfor the macros ininclude/asm-ia64/pgtable.hfor convenience. There are a bunch of cases to deal with:
oCONFIG_VIRTUAL_MEM_MAPand !CONFIG_VIRTUAL_MEM_MAP
oCONFIG_DISCONTIGMEMand !CONFIG_DISCONTIGMEM
o any combination of the two above
Quoted 2 lines
We need
CONFIG_VIRTUAL_MEM_MAPandCONFIG_DISCONTIGMEMwork together at the very least so that ia64 generic kernels will work.
Slightly less ugly hack than the ifdefs in generic code is a
#define mem_map vmem_map somewhere in a ia64 header. The right fix is to just always use the per-node mem_map. For SN2 you probably want a per-node virtual mem_map then.
Quoted 11 lines · Christoph Hellwig
Quoted 6 lines · Jesse Barnes
Quoted 4 lines
The #if
defined(VIRTUAL_MEM_MAP)|| !defined(DISCONTIGMEM) in generic code have to go away. All this mem_map/contig_page_data/etc crap has should probably go away some day, but for now let's not make it even messier.Sure, I'm all for them going away, any suggestions on how to get there?
Always use the node-local
mem_map, in the !DISCONTIG case we just have only one of them. But as said above this is in scope for this work (or 2.6 at all).
Yeah, I agree, but ia64 discontig doesn't have pfn_to_nid for example, so all of that needs to be written. I'll try to tackle that next.
Quoted 5 lines
Slightly less ugly hack than the ifdefs in generic code is a
#define
mem_mapvmem_mapsomewhere in a ia64 header. The right fix is to just always use the per-nodemem_map. For SN2 you probably want a per-node virtualmem_mapthen.
I'd rather avoid that if possible and do it correctly. Here's a new patch that incorporates almost all of your comments, as well as fixing (well, sort of) one of David's complaints about the callback data structure. I've re-seperated the discontig version of paging_init and put it in discontig.c, but I had to export a few things from init.c to do it. Please let me know what you think.
Thanks,
Jesse
arch/ia64/Kconfig +5 -25
@@ -220,24 +220,8 @@ Access). This option is for configuring high-end multiprocessor server systems. If in doubt, say N. -choice - prompt "Maximum Memory per NUMA Node" if NUMA && IA64_DIG - depends on NUMA && IA64_DIG - default IA64_NODESIZE_16GB - -config IA64_NODESIZE_16GB - bool "16GB" - -config IA64_NODESIZE_64GB - bool "64GB" - -config IA64_NODESIZE_256GB - bool "256GB" - -endchoice - config DISCONTIGMEM - bool "Discontiguous memory support" if (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA + bool "Discontiguous memory support" if (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA && VIRTUAL_MEM_MAP default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA help Say Y to support efficient handling of discontiguous physical memory,
@@ -250,14 +234,10 @@ default y if !IA64_HP_SIM help Say Y to compile the kernel with support for a virtual mem map. - This is an alternate method of supporting large holes in the - physical address space on non NUMA machines. Since the DISCONTIGMEM - option is not supported on machines with the ZX1 chipset, this is - the only way of supporting more than 1 Gb of memory on those - machines. This code also only takes effect if a memory hole of - greater than 1 Gb is found during boot, so it is safe to enable - unless you require the DISCONTIGMEM option for your machine. If you - are unsure, say Y. + This code also only takes effect if a memory hole of greater than + 1 Gb is found during boot. You must turn this option on if you + require the DISCONTIGMEM option for your machine. If you are + unsure, say Y. config IA64_MCA bool "Enable IA-64 Machine Check Abort"
arch/ia64/Makefile +1 -1
@@ -64,7 +64,7 @@ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ -drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ +drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/ drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/ boot := arch/ia64/hp/sim/boot
arch/ia64/kernel/setup.c +6 -30
@@ -101,7 +101,7 @@ filter_rsvd_memory (unsigned long start, unsigned long end, void *arg) {unsigned long range_start, range_end, prev_start; -void (*func)(unsigned long ,unsigned long ); +void (*func)(unsigned long ,unsigned long ,int );int i;#if IGNORE_PFN0
@@ -122,11 +122,7 @@ range_end =min (end, rsvd_region[i].start);if (range_start < range_end) -#ifdef CONFIG_DISCONTIGMEM -call_pernode_memory (__pa (range_start),__pa (range_end), func); -#else - (*func)(__pa (range_start), range_end - range_start); -#endif +call_pernode_memory (range_start, range_end, arg);/* nothing more available in this segment */ if (range_end = end)return 0 ;
@@ -239,7 +235,6 @@strlcpy (saved_command_line, *cmdline_p,sizeof (saved_command_line));efi_init (); -find_memory ();#ifdef CONFIG_ACPI_BOOT /* Initialize the ACPI boot-time table parser */
@@ -253,6 +248,8 @@# endif #endif /* CONFIG_APCI_BOOT */ +find_memory (); +/* process SAL system table: */ ia64_sal_init (efi.sal_systab);
@@ -544,28 +541,7 @@struct cpuinfo_ia64 *cpu_info;void *cpu_data; -#ifdef CONFIG_SMP -int cpu; - -/* -* get_free_pages() cannot be used before cpu_init() done. BSP allocates -* "NR_CPUS" pages for all CPUs to avoid that AP calls get_zeroed_page(). -*/ -if (smp_processor_id () =0 ) { - cpu_data =__alloc_bootmem (PERCPU_PAGE_SIZE *NR_CPUS ,PERCPU_PAGE_SIZE , -__pa (MAX_DMA_ADDRESS )); -for (cpu =0 ; cpu <NR_CPUS ; cpu++) { -memcpy (cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); - __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; - cpu_data +=PERCPU_PAGE_SIZE ; - -per_cpu (local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; - } - } - cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id ()]; -#else /* !CONFIG_SMP */ - cpu_data = __phys_per_cpu_start; -#endif /* !CONFIG_SMP */ + cpu_data =per_cpu_init ();get_max_cacheline_size ();
@@ -577,7 +553,7 @@*/ cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var (cpu_info) - __per_cpu_start);#ifdef CONFIG_NUMA - cpu_info->node_data =get_node_data_ptr (); + cpu_info->node_data =early_get_node_data ();#endif identify_cpu (cpu_info);
arch/ia64/mm/contig.c +31 -0
@@ -161,3 +161,34 @@find_initrd (); } + +/** +* per_cpu_init - setup per-cpu variables +* +* Allocate and setup per-cpu data areas. +*/ +void *per_cpu_init (void ) +{ +void *cpu_data; +int cpu; + +/* +* get_free_pages() cannot be used before cpu_init() done. BSP +* allocates "NR_CPUS" pages for all CPUs to avoid that AP calls +* get_zeroed_page(). +*/ +if (smp_processor_id () =0 ) { + cpu_data =__alloc_bootmem (PERCPU_PAGE_SIZE *NR_CPUS , +PERCPU_PAGE_SIZE , +__pa (MAX_DMA_ADDRESS )); +for (cpu =0 ; cpu <NR_CPUS ; cpu++) { +memcpy (cpu_data, __phys_per_cpu_start, + __per_cpu_end - __per_cpu_start); + __per_cpu_offset[cpu] = (char *) cpu_data - + __per_cpu_start; + cpu_data +=PERCPU_PAGE_SIZE ; +per_cpu (local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; + } + } +return __per_cpu_start + __per_cpu_offset[smp_processor_id ()]; +}
arch/ia64/mm/discontig.c +387 -221
730 lines not on this page · raw message
arch/ia64/mm/init.c +8 -18
@@ -24,7 +24,7 @@#include <asm/ia32.h> #include <asm/io.h> #include <asm/machvec.h> -#include <asm/numa.h> +#include <asm/meminit.h> #include <asm/patch.h> #include <asm/pgalloc.h> #include <asm/sal.h>
@@ -43,8 +43,8 @@#ifdef CONFIG_VIRTUAL_MEM_MAP # define LARGE_GAP 0x40000000/* Use virtual mem map if hole is > than this */ unsigned long vmalloc_end =VMALLOC_END_INIT ; -static struct page *vmem_map; -static unsigned long num_dma_physpages; +struct page *vmem_map; +unsigned long num_dma_physpages;#endif static int pgt_cache_water[2 ] = {25 ,50 };
@@ -338,7 +338,7 @@#ifdef CONFIG_VIRTUAL_MEM_MAP -static int +int create_mem_map_page_table (u64 start,u64 end,void *arg) {unsigned long address, start_page, end_page;
@@ -446,7 +446,7 @@return 0 ; } -static int +int find_largest_hole (u64 start,u64 end,void *arg) {u64 *max_gap = arg;
@@ -462,6 +462,7 @@ }#endif /* CONFIG_VIRTUAL_MEM_MAP */ +#ifndef CONFIG_DISCONTIGMEM static int count_pages (u64 start,u64 end,void *arg) {
@@ -475,17 +476,6 @@* Set up the page tables. */ -#ifdef CONFIG_DISCONTIGMEM -void -paging_init (void ) -{ -extern void discontig_paging_init (void ); - -discontig_paging_init (); -efi_memmap_walk (count_pages, &num_physpages); - zero_page_memmap_ptr =virt_to_page (ia64_imva (empty_zero_page)); -} -#else /* !CONFIG_DISCONTIGMEM */ void paging_init (void ) {
@@ -609,11 +599,11 @@platform_dma_init ();#endif -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )if (!mem_map)BUG (); max_mapnr = max_low_pfn; -#endif +#endif /* CONFIG_VIRTUAL_MEM_MAP || !CONFIG_DISCONTIGMEM */ high_memory =__va (max_low_pfn *PAGE_SIZE );
include/asm-ia64/meminit.h +20 -0
@@ -31,11 +31,31 @@extern void reserve_memory (void );extern void find_initrd (void );extern int filter_rsvd_memory (unsigned long start,unsigned long end,void *arg); +extern void paging_init (void ); + +/* +* For rounding an address to the next IA64_GRANULE_SIZE or order +*/ +#define GRANULEROUNDDOWN (n) ((n) & ~(IA64_GRANULE_SIZE-1)) +#define GRANULEROUNDUP (n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1)) +#define ORDERROUNDDOWN (n) ((n) & ~((PAGE_SIZE<<MAX_ORDER)-1))#ifdef CONFIG_DISCONTIGMEM extern void call_pernode_memory (unsigned long start,unsigned long end,void *arg); +#else +#define call_pernode_memory (start, end, func) (*func)(start, end, 0)#endif +#ifdef CONFIG_VIRTUAL_MEM_MAP +#define LARGE_GAP 0x40000000/* Use virtual mem map if hole is > than this */ +extern unsigned long vmalloc_end; +extern struct page *vmem_map; +extern unsigned long num_dma_physpages; +extern int find_largest_hole (u64 start,u64 end,void *arg); +extern int create_mem_map_page_table (u64 start,u64 end,void *arg); +#endif + +#define IGNORE_PFN0 1/* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */ #endif /* meminit_h */
include/asm-ia64/mmzone.h +10 -145
169 lines not on this page · raw message
include/asm-ia64/nodedata.h +3 -26
@@ -13,7 +13,7 @@#ifndef _ASM_IA64_NODEDATA_H#define _ASM_IA64_NODEDATA_H - +#include <asm/percpu.h> #include <asm/mmzone.h> /*
@@ -24,10 +24,7 @@struct ia64_node_data {short active_cpu_count;short node; -struct pglist_data *pg_data_ptrs[NR_NODES ]; -struct page *bank_mem_map_base[NR_BANKS ]; -struct ia64_node_data *node_data_ptrs[NR_NODES ]; -short node_id_map[NR_BANKS ]; +struct pglist_data *pg_data_ptrs[NR_NODES ]; };
@@ -36,41 +33,21 @@*/ #define local_node_data (local_cpu_data->node_data) - -/* -* Return a pointer to the node_data structure for the specified node. -*/ -#define node_data (node) (local_node_data->node_data_ptrs[node]) -/* * Get a pointer to the node_id/node_data for the current cpu. * (boot time only) */ -extern int boot_get_local_nodeid (void ); -extern struct ia64_node_data *get_node_data_ptr (void ); +extern struct ia64_node_data *early_get_node_data (void );/* * Given a node id, return a pointer to the pg_data_t for the node. -* The following 2 macros are similar. * * NODE_DATA - should be used in all code not related to system * initialization. It uses pernode data structures to minimize * offnode memory references. However, these structure are not * present during boot. This macro can be used once cpu_init * completes. -* -* BOOT_NODE_DATA -* - should be used during system initialization -* prior to freeing __initdata. It does not depend on the percpu -* area being present. -* -* NOTE: The names of these macros are misleading but are difficult to change -* since they are used in generic linux & on other architecures. */ #define NODE_DATA (nid) (local_node_data->pg_data_ptrs[nid]) -#define BOOT_NODE_DATA (nid) boot_get_pg_data_ptr((long)(nid)) - -struct pglist_data ; -extern struct pglist_data *__init boot_get_pg_data_ptr (long );#endif /* _ASM_IA64_NODEDATA_H */
include/asm-ia64/numa.h +6 -14
@@ -13,18 +13,13 @@#include <linux/config.h> #include <linux/cpumask.h> +#include <linux/cache.h> +#include <linux/threads.h> +#include <linux/smp.h> +#include <asm/mmzone.h> #ifdef CONFIG_NUMA -#ifdef CONFIG_DISCONTIGMEM -# include <asm/mmzone.h> -# define NR_MEMBLKS (NR_BANKS) -#else -# define NR_NODES (8) -# define NR_MEMBLKS (NR_NODES * 8) -#endif - -#include <linux/cache.h> extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned; extern volatile cpumask_t node_to_cpu_mask[NR_NODES] __cacheline_aligned;
@@ -65,13 +60,10 @@extern int paddr_to_nid (unsigned long paddr); -#define local_nodeid (cpu_to_node_map[smp_processor_id()]) -#else /* !CONFIG_NUMA */ -#define node_distance (from,to) 10 -#define paddr_to_nid (addr) 0 -#define local_nodeid 0 +#define node_distance (from,to) 10 +#define paddr_to_nid (x) 0#endif /* CONFIG_NUMA */
include/asm-ia64/page.h +6 -7
@@ -94,18 +94,17 @@#define virt_addr_valid (kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) -#ifndef CONFIG_DISCONTIGMEM -# ifdef CONFIG_VIRTUAL_MEM_MAP +#ifdef CONFIG_VIRTUAL_MEM_MAP extern int ia64_pfn_valid (unsigned long pfn); -# define pfn_valid (pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn)) -# else -# define pfn_valid (pfn) ((pfn) < max_mapnr) -# endif +#else +# define ia64_pfn_valid (pfn) 1 +#endif + +#define pfn_valid (pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn))#define virt_to_page (kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)#define page_to_pfn (page) ((unsigned long) (page - mem_map))#define pfn_to_page (pfn) (mem_map + (pfn))#define page_to_phys (page) (page_to_pfn(page) << PAGE_SHIFT) -#endif typedef union ia64_va { struct {
include/asm-ia64/percpu.h +2 -0
@@ -46,11 +46,13 @@extern void percpu_modcopy (void *pcpudst,const void *src,unsigned long size);extern void setup_per_cpu_areas (void ); +extern void *per_cpu_init (void );#else /* ! SMP */ #define per_cpu (var, cpu) ((void)cpu, per_cpu__##var)#define __get_cpu_var (var) per_cpu__##var +#define per_cpu_init () (__phys_per_cpu_start)#endif /* SMP */
include/asm-ia64/pgtable.h +0 -1
@@ -174,7 +174,6 @@return (addr & (local_cpu_data->unimpl_pa_mask)) =0 ; } -#ifndef CONFIG_DISCONTIGMEM /* * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel * memory. For the return value to be meaningful, ADDR must be >@@ -190,7 +189,6 @@
*/
#define kern_addr_valid(addr) (1)
-#endif
/*
* Now come the defines and routines to manage and access the three-level
@@ -241,10 +239,8 @@
#define pte_none(pte) (!pte_val(pte))
#define pte_present(pte) (pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
#define pte_clear(pte) (pte_val(*(pte)) = 0UL)
-#ifndef CONFIG_DISCONTIGMEM
/* pte_page() returns the "struct page *" corresponding to the PTE: */
#define pte_page(pte) virt_to_page(((pte_val(pte) & _PFN_MASK) + PAGE_OFFSET))
-#endif
#define pmd_none(pmd) (!pmd_val(pmd))
#define pmd_bad(pmd) (!ia64_phys_addr_valid(pmd_val(pmd)))
include/linux/mm.h +3 -2
@@ -13,7 +13,8 @@#include <linux/rbtree.h> #include <linux/fs.h> -#ifndef CONFIG_DISCONTIGMEM /* Don't use mapnrs, do it properly */ +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM ) +/* Don't use mapnrs, do it properly */ extern unsigned long max_mapnr;#endif
@@ -340,7 +341,7 @@ page->flags |= zone_num <<ZONE_SHIFT ; } -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )/* The array of struct pages - for discontigmem use pgdat->lmem_map */ extern struct page *mem_map;#endif
kernel/ksyms.c +1 -1
@@ -114,7 +114,7 @@EXPORT_SYMBOL (vunmap);EXPORT_SYMBOL (vmalloc_to_page);EXPORT_SYMBOL (remap_page_range); -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )EXPORT_SYMBOL (contig_page_data);EXPORT_SYMBOL (mem_map);EXPORT_SYMBOL (max_mapnr);
mm/memory.c +1 -1
@@ -55,7 +55,7 @@#include <linux/swapops.h> -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )/* use the per-pgdat data instead for discontigmem - mbligh */ unsigned long max_mapnr;struct page *mem_map;
Quoted 22 lines · Jesse Barnes
Quoted 11 lines · Christoph Hellwig
Quoted 6 lines · Jesse Barnes
Quoted 4 lines
The #if
defined(VIRTUAL_MEM_MAP)|| !defined(DISCONTIGMEM) in generic code have to go away. All this mem_map/contig_page_data/etc crap has should probably go away some day, but for now let's not make it even messier.Sure, I'm all for them going away, any suggestions on how to get there?
Always use the node-local
mem_map, in the !DISCONTIG case we just have only one of them. But as said above this is in scope for this work (or 2.6 at all).Yeah, I agree, but ia64 discontig doesn't have
pfn_to_nidfor example, so all of that needs to be written. I'll try to tackle that next.Quoted 5 lines
Slightly less ugly hack than the ifdefs in generic code is a
#define
mem_mapvmem_mapsomewhere in a ia64 header. The right fix is to just always use the per-nodemem_map. For SN2 you probably want a per-node virtualmem_mapthen.
Quoted 6 lines
I'd rather avoid that if possible and do it correctly. Here's a new patch that incorporates almost all of your comments, as well as fixing (well, sort of) one of David's complaints about the callback data structure. I've re-seperated the discontig version of
paging_initand put it indiscontig.c, but I had to export a few things frominit.cto do it. Please let me know what you think.
This patch fixes the last one by not changing around the callback args. All are physical addr, length pairs now.
Thanks,
Jesse
arch/ia64/Kconfig +5 -25
@@ -220,24 +220,8 @@ Access). This option is for configuring high-end multiprocessor server systems. If in doubt, say N. -choice - prompt "Maximum Memory per NUMA Node" if NUMA && IA64_DIG - depends on NUMA && IA64_DIG - default IA64_NODESIZE_16GB - -config IA64_NODESIZE_16GB - bool "16GB" - -config IA64_NODESIZE_64GB - bool "64GB" - -config IA64_NODESIZE_256GB - bool "256GB" - -endchoice - config DISCONTIGMEM - bool "Discontiguous memory support" if (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA + bool "Discontiguous memory support" if (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC) && NUMA && VIRTUAL_MEM_MAP default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA help Say Y to support efficient handling of discontiguous physical memory,
@@ -250,14 +234,10 @@ default y if !IA64_HP_SIM help Say Y to compile the kernel with support for a virtual mem map. - This is an alternate method of supporting large holes in the - physical address space on non NUMA machines. Since the DISCONTIGMEM - option is not supported on machines with the ZX1 chipset, this is - the only way of supporting more than 1 Gb of memory on those - machines. This code also only takes effect if a memory hole of - greater than 1 Gb is found during boot, so it is safe to enable - unless you require the DISCONTIGMEM option for your machine. If you - are unsure, say Y. + This code also only takes effect if a memory hole of greater than + 1 Gb is found during boot. You must turn this option on if you + require the DISCONTIGMEM option for your machine. If you are + unsure, say Y. config IA64_MCA bool "Enable IA-64 Machine Check Abort"
arch/ia64/Makefile +1 -1
@@ -64,7 +64,7 @@ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ -drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ +drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/ drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/ boot := arch/ia64/hp/sim/boot
arch/ia64/kernel/setup.c +7 -30
@@ -101,7 +101,7 @@ filter_rsvd_memory (unsigned long start, unsigned long end, void *arg) {unsigned long range_start, range_end, prev_start; -void (*func)(unsigned long ,unsigned long ); +void (*func)(unsigned long ,unsigned long ,int );int i;#if IGNORE_PFN0
@@ -122,11 +122,8 @@ range_end =min (end, rsvd_region[i].start);if (range_start < range_end) -#ifdef CONFIG_DISCONTIGMEM -call_pernode_memory (__pa (range_start),__pa (range_end), func); -#else - (*func)(__pa (range_start), range_end - range_start); -#endif +call_pernode_memory (__pa (range_start), + range_end - range_start, func);/* nothing more available in this segment */ if (range_end = end)return 0 ;
@@ -239,7 +236,6 @@strlcpy (saved_command_line, *cmdline_p,sizeof (saved_command_line));efi_init (); -find_memory ();#ifdef CONFIG_ACPI_BOOT /* Initialize the ACPI boot-time table parser */
@@ -253,6 +249,8 @@# endif #endif /* CONFIG_APCI_BOOT */ +find_memory (); +/* process SAL system table: */ ia64_sal_init (efi.sal_systab);
@@ -544,28 +542,7 @@struct cpuinfo_ia64 *cpu_info;void *cpu_data; -#ifdef CONFIG_SMP -int cpu; - -/* -* get_free_pages() cannot be used before cpu_init() done. BSP allocates -* "NR_CPUS" pages for all CPUs to avoid that AP calls get_zeroed_page(). -*/ -if (smp_processor_id () =0 ) { - cpu_data =__alloc_bootmem (PERCPU_PAGE_SIZE *NR_CPUS ,PERCPU_PAGE_SIZE , -__pa (MAX_DMA_ADDRESS )); -for (cpu =0 ; cpu <NR_CPUS ; cpu++) { -memcpy (cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start); - __per_cpu_offset[cpu] = (char *) cpu_data - __per_cpu_start; - cpu_data +=PERCPU_PAGE_SIZE ; - -per_cpu (local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; - } - } - cpu_data = __per_cpu_start + __per_cpu_offset[smp_processor_id ()]; -#else /* !CONFIG_SMP */ - cpu_data = __phys_per_cpu_start; -#endif /* !CONFIG_SMP */ + cpu_data =per_cpu_init ();get_max_cacheline_size ();
@@ -577,7 +554,7 @@*/ cpu_info = cpu_data + ((char *) &__ia64_per_cpu_var (cpu_info) - __per_cpu_start);#ifdef CONFIG_NUMA - cpu_info->node_data =get_node_data_ptr (); + cpu_info->node_data =early_get_node_data ();#endif identify_cpu (cpu_info);
arch/ia64/mm/contig.c +31 -0
@@ -161,3 +161,34 @@find_initrd (); } + +/** +* per_cpu_init - setup per-cpu variables +* +* Allocate and setup per-cpu data areas. +*/ +void *per_cpu_init (void ) +{ +void *cpu_data; +int cpu; + +/* +* get_free_pages() cannot be used before cpu_init() done. BSP +* allocates "NR_CPUS" pages for all CPUs to avoid that AP calls +* get_zeroed_page(). +*/ +if (smp_processor_id () =0 ) { + cpu_data =__alloc_bootmem (PERCPU_PAGE_SIZE *NR_CPUS , +PERCPU_PAGE_SIZE , +__pa (MAX_DMA_ADDRESS )); +for (cpu =0 ; cpu <NR_CPUS ; cpu++) { +memcpy (cpu_data, __phys_per_cpu_start, + __per_cpu_end - __per_cpu_start); + __per_cpu_offset[cpu] = (char *) cpu_data - + __per_cpu_start; + cpu_data +=PERCPU_PAGE_SIZE ; +per_cpu (local_per_cpu_offset, cpu) = __per_cpu_offset[cpu]; + } + } +return __per_cpu_start + __per_cpu_offset[smp_processor_id ()]; +}
arch/ia64/mm/discontig.c +387 -227
733 lines not on this page · raw message
arch/ia64/mm/init.c +8 -17
@@ -24,6 +24,7 @@#include <asm/ia32.h> #include <asm/io.h> #include <asm/machvec.h> +#include <asm/meminit.h> #include <asm/patch.h> #include <asm/pgalloc.h> #include <asm/sal.h>
@@ -42,8 +43,8 @@#ifdef CONFIG_VIRTUAL_MEM_MAP # define LARGE_GAP 0x40000000/* Use virtual mem map if hole is > than this */ unsigned long vmalloc_end =VMALLOC_END_INIT ; -static struct page *vmem_map; -static unsigned long num_dma_physpages; +struct page *vmem_map; +unsigned long num_dma_physpages;#endif static int pgt_cache_water[2 ] = {25 ,50 };
@@ -337,11 +338,12 @@#ifdef CONFIG_VIRTUAL_MEM_MAP -static int +int create_mem_map_page_table (u64 start,u64 end,void *arg) {unsigned long address, start_page, end_page;
@@ -443,7 +446,7 @@return 0 ; } -static int +int find_largest_hole (u64 start,u64 end,void *arg) {u64 *max_gap = arg;
@@ -459,6 +462,7 @@ }#endif /* CONFIG_VIRTUAL_MEM_MAP */ +#ifndef CONFIG_DISCONTIGMEM static int count_pages (u64 start,u64 end,void *arg) {
@@ -472,17 +476,6 @@* Set up the page tables. */ -#ifdef CONFIG_DISCONTIGMEM -void -paging_init (void ) -{ -extern void discontig_paging_init (void ); - -discontig_paging_init (); -efi_memmap_walk (count_pages, &num_physpages); - zero_page_memmap_ptr =virt_to_page (ia64_imva (empty_zero_page)); -} -#else /* !CONFIG_DISCONTIGMEM */ void paging_init (void ) {
@@ -606,11 +599,11 @@platform_dma_init ();#endif -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )if (!mem_map)BUG (); max_mapnr = max_low_pfn; -#endif +#endif /* CONFIG_VIRTUAL_MEM_MAP || !CONFIG_DISCONTIGMEM */ high_memory =__va (max_low_pfn *PAGE_SIZE );
include/asm-ia64/meminit.h +22 -1
@@ -31,10 +31,31 @@extern void reserve_memory (void );extern void find_initrd (void );extern int filter_rsvd_memory (unsigned long start,unsigned long end,void *arg); +extern void paging_init (void ); + +/* +* For rounding an address to the next IA64_GRANULE_SIZE or order +*/ +#define GRANULEROUNDDOWN (n) ((n) & ~(IA64_GRANULE_SIZE-1)) +#define GRANULEROUNDUP (n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1)) +#define ORDERROUNDDOWN (n) ((n) & ~((PAGE_SIZE<<MAX_ORDER)-1))#ifdef CONFIG_DISCONTIGMEM -extern void call_pernode_memory (unsigned long start,unsigned long end,void *arg); +extern void call_pernode_memory (unsigned long start,unsigned long len, +void *func); +#else +#define call_pernode_memory (start, len, func) (*func)(start, len, 0)#endif + +#ifdef CONFIG_VIRTUAL_MEM_MAP +#define LARGE_GAP 0x40000000/* Use virtual mem map if hole is > than this */ +extern unsigned long vmalloc_end; +extern struct page *vmem_map; +extern unsigned long num_dma_physpages; +extern int find_largest_hole (u64 start,u64 end,void *arg); +extern int create_mem_map_page_table (u64 start,u64 end,void *arg); +#endif +#define IGNORE_PFN0 1/* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
include/asm-ia64/mmzone.h +10 -145
169 lines not on this page · raw message
include/asm-ia64/nodedata.h +7 -25
@@ -13,9 +13,12 @@#ifndef _ASM_IA64_NODEDATA_H#define _ASM_IA64_NODEDATA_H - +#include <linux/config.h> +#include <asm/percpu.h> #include <asm/mmzone.h> +#ifdef CONFIG_DISCONTIGMEM +/* * Node Data. One of these structures is located on each node of a NUMA system. */
@@ -24,10 +27,7 @@struct ia64_node_data {short active_cpu_count;short node; -struct pglist_data *pg_data_ptrs[NR_NODES ]; -struct page *bank_mem_map_base[NR_BANKS ]; -struct ia64_node_data *node_data_ptrs[NR_NODES ]; -short node_id_map[NR_BANKS ]; +struct pglist_data *pg_data_ptrs[NR_NODES ]; };
@@ -36,41 +36,23 @@*/ #define local_node_data (local_cpu_data->node_data) - -/* -* Return a pointer to the node_data structure for the specified node. -*/ -#define node_data (node) (local_node_data->node_data_ptrs[node]) -/* * Get a pointer to the node_id/node_data for the current cpu. * (boot time only) */ -extern int boot_get_local_nodeid (void ); -extern struct ia64_node_data *get_node_data_ptr (void ); +extern struct ia64_node_data *early_get_node_data (void );/* * Given a node id, return a pointer to the pg_data_t for the node. -* The following 2 macros are similar. * * NODE_DATA - should be used in all code not related to system * initialization. It uses pernode data structures to minimize * offnode memory references. However, these structure are not * present during boot. This macro can be used once cpu_init * completes. -* -* BOOT_NODE_DATA -* - should be used during system initialization -* prior to freeing __initdata. It does not depend on the percpu -* area being present. -* -* NOTE: The names of these macros are misleading but are difficult to change -* since they are used in generic linux & on other architecures. */ #define NODE_DATA (nid) (local_node_data->pg_data_ptrs[nid]) -#define BOOT_NODE_DATA (nid) boot_get_pg_data_ptr((long)(nid)) -struct pglist_data ; -extern struct pglist_data *__init boot_get_pg_data_ptr (long ); +#endif /* CONFIG_DISCONTIGMEM */ #endif /* _ASM_IA64_NODEDATA_H */
include/asm-ia64/numa.h +8 -10
@@ -13,18 +13,13 @@#include <linux/config.h> #include <linux/cpumask.h> +#include <linux/cache.h> +#include <linux/threads.h> +#include <linux/smp.h> +#include <asm/mmzone.h> #ifdef CONFIG_NUMA -#ifdef CONFIG_DISCONTIGMEM -# include <asm/mmzone.h> -# define NR_MEMBLKS (NR_BANKS) -#else -# define NR_NODES (8) -# define NR_MEMBLKS (NR_NODES * 8) -#endif - -#include <linux/cache.h> extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned; extern volatile cpumask_t node_to_cpu_mask[NR_NODES] __cacheline_aligned;
@@ -65,7 +60,10 @@extern int paddr_to_nid (unsigned long paddr); -#define local_nodeid (cpu_to_node_map[smp_processor_id()]) +#else /* !CONFIG_NUMA */ + +#define node_distance (from,to) 10 +#define paddr_to_nid (x) 0#endif /* CONFIG_NUMA */
include/asm-ia64/page.h +6 -7
@@ -94,18 +94,17 @@#define virt_addr_valid (kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) -#ifndef CONFIG_DISCONTIGMEM -# ifdef CONFIG_VIRTUAL_MEM_MAP +#ifdef CONFIG_VIRTUAL_MEM_MAP extern int ia64_pfn_valid (unsigned long pfn); -# define pfn_valid (pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn)) -# else -# define pfn_valid (pfn) ((pfn) < max_mapnr) -# endif +#else +# define ia64_pfn_valid (pfn) 1 +#endif + +#define pfn_valid (pfn) (((pfn) < max_mapnr) && ia64_pfn_valid(pfn))#define virt_to_page (kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)#define page_to_pfn (page) ((unsigned long) (page - mem_map))#define pfn_to_page (pfn) (mem_map + (pfn))#define page_to_phys (page) (page_to_pfn(page) << PAGE_SHIFT) -#endif typedef union ia64_va { struct {
include/asm-ia64/percpu.h +2 -0
@@ -46,11 +46,13 @@extern void percpu_modcopy (void *pcpudst,const void *src,unsigned long size);extern void setup_per_cpu_areas (void ); +extern void *per_cpu_init (void );#else /* ! SMP */ #define per_cpu (var, cpu) ((void)cpu, per_cpu__##var)#define __get_cpu_var (var) per_cpu__##var +#define per_cpu_init () (__phys_per_cpu_start)#endif /* SMP */
include/asm-ia64/pgtable.h +0 -1
@@ -174,7 +174,6 @@return (addr & (local_cpu_data->unimpl_pa_mask)) =0 ; } -#ifndef CONFIG_DISCONTIGMEM /* * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel * memory. For the return value to be meaningful, ADDR must be >@@ -190,7 +189,6 @@
*/
#define kern_addr_valid(addr) (1)
-#endif
/*
* Now come the defines and routines to manage and access the three-level
@@ -241,10 +239,8 @@
#define pte_none(pte) (!pte_val(pte))
#define pte_present(pte) (pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
#define pte_clear(pte) (pte_val(*(pte)) = 0UL)
-#ifndef CONFIG_DISCONTIGMEM
/* pte_page() returns the "struct page *" corresponding to the PTE: */
#define pte_page(pte) virt_to_page(((pte_val(pte) & _PFN_MASK) + PAGE_OFFSET))
-#endif
#define pmd_none(pmd) (!pmd_val(pmd))
#define pmd_bad(pmd) (!ia64_phys_addr_valid(pmd_val(pmd)))
include/linux/mm.h +3 -2
@@ -13,7 +13,8 @@#include <linux/rbtree.h> #include <linux/fs.h> -#ifndef CONFIG_DISCONTIGMEM /* Don't use mapnrs, do it properly */ +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM ) +/* Don't use mapnrs, do it properly */ extern unsigned long max_mapnr;#endif
@@ -340,7 +341,7 @@ page->flags |= zone_num <<ZONE_SHIFT ; } -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )/* The array of struct pages - for discontigmem use pgdat->lmem_map */ extern struct page *mem_map;#endif
kernel/ksyms.c +1 -1
@@ -114,7 +114,7 @@EXPORT_SYMBOL (vunmap);EXPORT_SYMBOL (vmalloc_to_page);EXPORT_SYMBOL (remap_page_range); -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )EXPORT_SYMBOL (contig_page_data);EXPORT_SYMBOL (mem_map);EXPORT_SYMBOL (max_mapnr);
mm/memory.c +1 -1
@@ -55,7 +55,7 @@#include <linux/swapops.h> -#ifndef CONFIG_DISCONTIGMEM +#if defined(CONFIG_VIRTUAL_MEM_MAP ) || !defined(CONFIG_DISCONTIGMEM )/* use the per-pgdat data instead for discontigmem - mbligh */ unsigned long max_mapnr;struct page *mem_map;
Quoted 2 lines · Jesse Barnes
This patch fixes the last one by not changing around the callback args. All are physical addr, length pairs now.
Oh, and it doesn't break zx1 either. Boot tested zx1 and sn2 configs.
Jesse