Patch for sparsemem support
The patch below allows sparsemem to work for Mips64. This is my first foray into the boot memory handling code, so hopefully I haven't made any serious blunders. Unfortunately the Octeon processor I made the changes for isn't currently in the linux-mips.org tree. This means there isn't an example of sparsemem usage yet. I plan to work at fixing this soon.
Other than various ifdef changes, the most important change was moving memory_present() in arch/mips/kernel/setup.c. When you're using sparsemem extreme, this function does an allocate for bootmem. This would always fail since init_bootmem hasn't been called yet. I moved memory_present after free_bootmem. This only marks actual memory ranges as present instead of the entire address space.
This patch was made against 2.6.16.16
Chad
arch/mips/kernel/setup.c | 3 +-- arch/mips/mm/init.c | 2 +- include/asm-mips/page.h | 2 ++ include/asm-mips/sparsemem.h | 14 ++++++++++++++ include/linux/mm.h | 2 +- include/linux/mmzone.h | 1 + 6 files changed, 20 insertions(+), 4 deletions(-)
arch/mips/kernel/setup.c +1 -2
@@ -358,8 +358,6 @@ static inline void bootmem_init(void) }#endif -memory_present (0 , first_usable_pfn, max_low_pfn); -/* Initialize the boot-time allocator with low memory only. */ bootmap_size =init_bootmem (first_usable_pfn, max_low_pfn);
@@ -413,6 +411,7 @@ static inline void bootmem_init(void)/* Register lowmem ranges */ free_bootmem (PFN_PHYS (curr_pfn),PFN_PHYS (size)); +memory_present (0 , curr_pfn, curr_pfn + size -1 ); }/* Reserve the bootmap memory. */
arch/mips/mm/init.c +1 -1
@@ -228,7 +228,7 @@ void __init mem_init(void)for (tmp =0 ; tmp < max_low_pfn; tmp++)if (page_is_ram (tmp)) { ram++; -if (PageReserved (mem_map+tmp)) +if (PageReserved (pfn_to_page (tmp))) reservedpages++; }
include/asm-mips/page.h +2 -0
@@ -145,11 +145,13 @@ typedef struct { unsigned long pgprot; }#define pfn_to_kaddr (pfn) __va((pfn) << PAGE_SHIFT) +#ifndef CONFIG_SPARSEMEM #ifndef CONFIG_NEED_MULTIPLE_NODES #define pfn_to_page (pfn) (mem_map + (pfn))#define page_to_pfn (page) ((unsigned long)((page) - mem_map))#define pfn_valid (pfn) ((pfn) < max_mapnr)#endif +#endif #define virt_to_page (kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)#define virt_addr_valid (kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
include/asm-mips/sparsemem.h new file +14 -0
@@ -0,0 +1,14 @@ +#ifndef _MIPS_SPARSEMEM_H +#define _MIPS_SPARSEMEM_H +#ifdef CONFIG_SPARSEMEM + +/* +* SECTION_SIZE_BITS 2^N: how big each section will be +* MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space +*/ +#define SECTION_SIZE_BITS 28 +#define MAX_PHYSMEM_BITS 35 + +#endif /* CONFIG_SPARSEMEM */ +#endif /* _MIPS_SPARSEMEM_H */ +
include/linux/mm.h +1 -1
@@ -506,7 +506,7 @@ static inline void set_page_links(structset_page_section (page,pfn_to_section_nr (pfn)); } -#ifndef CONFIG_DISCONTIGMEM +#if !defined(CONFIG_DISCONTIGMEM ) && !defined(CONFIG_SPARSEMEM )/* The array of struct pages - for discontigmem use pgdat->lmem_map */ extern struct page *mem_map;#endif
include/linux/mmzone.h +1 -0
@@ -14,6 +14,7 @@#include <linux/init.h> #include <linux/seqlock.h> #include <asm/atomic.h> +#include <asm/page.h> /* Free memory management - zoned buddy allocator. */ #ifndef CONFIG_FORCE_MAX_ZONEORDER
On Sun, May 21, 2006 at 01:18:06PM -0700, Chad Reese wrote:
Looks ok - but the patch is corrupt, can you resend?
Ralf
Resend of previous patch
I've attached the patch compressed with gzip and as clear text. Hopefully one of them will survive whatever corruption occurred last time.
Chad
---
The patch below allows sparsemem to work for Mips64. This is my first foray into the boot memory handling code, so hopefully I haven't made any serious blunders. Unfortunately the Octeon processor I made the changes for isn't currently in the linux-mips.org tree. This means there isn't an example of sparsemem usage yet. I plan to work at fixing this soon.
Other than various ifdef changes, the most important change was moving memory_present() in arch/mips/kernel/setup.c. When you're using sparsemem extreme, this function does an allocate for bootmem. This would always fail since init_bootmem hasn't been called yet. I moved memory_present after free_bootmem. This only marks actual memory ranges as present instead of the entire address space.
This patch was made against 2.6.16.16
arch/mips/kernel/setup.c | 3 +-- arch/mips/mm/init.c | 2 +- include/asm-mips/page.h | 2 ++ include/asm-mips/sparsemem.h | 14 ++++++++++++++ include/linux/mm.h | 2 +- include/linux/mmzone.h | 1 + 6 files changed, 20 insertions(+), 4 deletions(-)
Quoted 6 lines · Ralf Baechle
On Sun, May 21, 2006 at 01:18:06PM -0700, Chad Reese wrote:
Looks ok - but the patch is corrupt, can you resend?
Ralf
arch/mips/kernel/setup.c +1 -2
@@ -358,8 +358,6 @@ static inline void bootmem_init(void) }#endif -memory_present (0 , first_usable_pfn, max_low_pfn); -/* Initialize the boot-time allocator with low memory only. */ bootmap_size =init_bootmem (first_usable_pfn, max_low_pfn);
@@ -413,6 +411,7 @@ static inline void bootmem_init(void)/* Register lowmem ranges */ free_bootmem (PFN_PHYS (curr_pfn),PFN_PHYS (size)); +memory_present (0 , curr_pfn, curr_pfn + size -1 ); }/* Reserve the bootmap memory. */
arch/mips/mm/init.c +1 -1
@@ -228,7 +228,7 @@ void __init mem_init(void)for (tmp =0 ; tmp < max_low_pfn; tmp++)if (page_is_ram (tmp)) { ram++; -if (PageReserved (mem_map+tmp)) +if (PageReserved (pfn_to_page (tmp))) reservedpages++; }
include/asm-mips/page.h +2 -0
@@ -145,11 +145,13 @@ typedef struct { unsigned long pgprot; }#define pfn_to_kaddr (pfn) __va((pfn) << PAGE_SHIFT) +#ifndef CONFIG_SPARSEMEM #ifndef CONFIG_NEED_MULTIPLE_NODES #define pfn_to_page (pfn) (mem_map + (pfn))#define page_to_pfn (page) ((unsigned long)((page) - mem_map))#define pfn_valid (pfn) ((pfn) < max_mapnr)#endif +#endif #define virt_to_page (kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)#define virt_addr_valid (kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
include/asm-mips/sparsemem.h new file +14 -0
@@ -0,0 +1,14 @@ +#ifndef _MIPS_SPARSEMEM_H +#define _MIPS_SPARSEMEM_H +#ifdef CONFIG_SPARSEMEM + +/* +* SECTION_SIZE_BITS 2^N: how big each section will be +* MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space +*/ +#define SECTION_SIZE_BITS 28 +#define MAX_PHYSMEM_BITS 35 + +#endif /* CONFIG_SPARSEMEM */ +#endif /* _MIPS_SPARSEMEM_H */ +
include/linux/mm.h +1 -1
@@ -506,7 +506,7 @@ static inline void set_page_links(structset_page_section (page,pfn_to_section_nr (pfn)); } -#ifndef CONFIG_DISCONTIGMEM +#if !defined(CONFIG_DISCONTIGMEM ) && !defined(CONFIG_SPARSEMEM )/* The array of struct pages - for discontigmem use pgdat->lmem_map */ extern struct page *mem_map;#endif
include/linux/mmzone.h +1 -0
@@ -14,6 +14,7 @@#include <linux/init.h> #include <linux/seqlock.h> #include <asm/atomic.h> +#include <asm/page.h> /* Free memory management - zoned buddy allocator. */ #ifndef CONFIG_FORCE_MAX_ZONEORDER