Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01066625 authored by Paul Mundt's avatar Paul Mundt Committed by Paul Mundt
Browse files

sh: bootmem tidying for discontig/sparsemem preparation.



This reworks some of the node 0 bootmem initialization in
preparation for discontigmem and sparsemem support.

ARCH_POPULATES_NODE_MAP is switched to as a result of this.

Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 759ab068
Loading
Loading
Loading
Loading
+95 −69
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@
 * This file handles the architecture-dependent parts of initialization
 *
 *  Copyright (C) 1999  Niibe Yutaka
 *  Copyright (C) 2002 - 2006 Paul Mundt
 *  Copyright (C) 2002 - 2007 Paul Mundt
 */
#include <linux/screen_info.h>
#include <linux/ioport.h>
@@ -15,15 +15,18 @@
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/utsname.h>
#include <linux/nodemask.h>
#include <linux/cpu.h>
#include <linux/pfn.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/sections.h>
#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/clock.h>
#include <asm/mmu_context.h>

extern void * __rd_start, * __rd_end;

@@ -202,65 +205,10 @@ static int __init sh_mv_setup(char **cmdline_p)
	return 0;
}

void __init setup_arch(char **cmdline_p)
{
	unsigned long bootmap_size;
	unsigned long start_pfn, max_pfn, max_low_pfn;

#ifdef CONFIG_CMDLINE_BOOL
        strcpy(COMMAND_LINE, CONFIG_CMDLINE);
#endif

	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);

#ifdef CONFIG_BLK_DEV_RAM
	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
#endif

	if (!MOUNT_ROOT_RDONLY)
		root_mountflags &= ~MS_RDONLY;
	init_mm.start_code = (unsigned long) _text;
	init_mm.end_code = (unsigned long) _etext;
	init_mm.end_data = (unsigned long) _edata;
	init_mm.brk = (unsigned long) _end;

	code_resource.start = (unsigned long)virt_to_phys(_text);
	code_resource.end = (unsigned long)virt_to_phys(_etext)-1;
	data_resource.start = (unsigned long)virt_to_phys(_etext);
	data_resource.end = (unsigned long)virt_to_phys(_edata)-1;

	sh_mv_setup(cmdline_p);


	/*
	 * Find the highest page frame number we have available
	 */
	max_pfn = PFN_DOWN(__pa(memory_end));

	/*
	 * Determine low and high memory ranges:
	 */
	max_low_pfn = max_pfn;

	/*
	 * Partially used pages are not usable - thus
	 * we are rounding upwards:
	 */
	start_pfn = PFN_UP(__pa(_end));

	/*
	 * Find a proper area for the bootmem bitmap. After this
	 * bootstrap step all allocations (until the page allocator
	 * is intact) must be done via bootmem_alloc().
	 */
	bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
					 __MEMORY_START>>PAGE_SHIFT,
					 max_low_pfn);
/*
 * Register fully available low RAM pages with the bootmem allocator.
 */
static void __init register_bootmem_low_pages(void)
{
	unsigned long curr_pfn, last_pfn, pages;

@@ -268,6 +216,7 @@ void __init setup_arch(char **cmdline_p)
	 * We are rounding up the start address of usable memory:
	 */
	curr_pfn = PFN_UP(__MEMORY_START);

	/*
	 * ... and at the end of the usable range downwards:
	 */
@@ -277,10 +226,24 @@ void __init setup_arch(char **cmdline_p)
		last_pfn = max_low_pfn;

	pages = last_pfn - curr_pfn;
		free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn),
				  PFN_PHYS(pages));
	free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages));
}

void __init setup_bootmem_allocator(unsigned long start_pfn)
{
	unsigned long bootmap_size;

	/*
	 * Find a proper area for the bootmem bitmap. After this
	 * bootstrap step all allocations (until the page allocator
	 * is intact) must be done via bootmem_alloc().
	 */
	bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
					 min_low_pfn, max_low_pfn);

	register_bootmem_low_pages();

	node_set_online(0);

	/*
	 * Reserve the kernel text and
@@ -289,14 +252,14 @@ void __init setup_arch(char **cmdline_p)
	 * case of us accidentally initializing the bootmem allocator with
	 * an invalid RAM area.
	 */
	reserve_bootmem_node(NODE_DATA(0), __MEMORY_START+PAGE_SIZE,
	reserve_bootmem(__MEMORY_START+PAGE_SIZE,
		(PFN_PHYS(start_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START);

	/*
	 * reserve physical page 0 - it's a special BIOS page on many boxes,
	 * enabling clean reboots, SMP operation, laptop functions.
	 */
	reserve_bootmem_node(NODE_DATA(0), __MEMORY_START, PAGE_SIZE);
	reserve_bootmem(__MEMORY_START, PAGE_SIZE);

#ifdef CONFIG_BLK_DEV_INITRD
	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
@@ -310,8 +273,8 @@ void __init setup_arch(char **cmdline_p)

	if (LOADER_TYPE && INITRD_START) {
		if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
			reserve_bootmem_node(NODE_DATA(0), INITRD_START +
						__MEMORY_START, INITRD_SIZE);
			reserve_bootmem(INITRD_START + __MEMORY_START,
					INITRD_SIZE);
			initrd_start = INITRD_START + PAGE_OFFSET +
					__MEMORY_START;
			initrd_end = initrd_start + INITRD_SIZE;
@@ -324,6 +287,71 @@ void __init setup_arch(char **cmdline_p)
		}
	}
#endif
}

#ifndef CONFIG_NEED_MULTIPLE_NODES
static void __init setup_memory(void)
{
	unsigned long start_pfn;

	/*
	 * Partially used pages are not usable - thus
	 * we are rounding upwards:
	 */
	start_pfn = PFN_UP(__pa(_end));
	setup_bootmem_allocator(start_pfn);
}
#else
extern void __init setup_memory(void);
#endif

void __init setup_arch(char **cmdline_p)
{
	enable_mmu();

#ifdef CONFIG_CMDLINE_BOOL
	strcpy(COMMAND_LINE, CONFIG_CMDLINE);
#endif

	ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);

#ifdef CONFIG_BLK_DEV_RAM
	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
#endif

	if (!MOUNT_ROOT_RDONLY)
		root_mountflags &= ~MS_RDONLY;
	init_mm.start_code = (unsigned long) _text;
	init_mm.end_code = (unsigned long) _etext;
	init_mm.end_data = (unsigned long) _edata;
	init_mm.brk = (unsigned long) _end;

	code_resource.start = virt_to_phys(_text);
	code_resource.end = virt_to_phys(_etext)-1;
	data_resource.start = virt_to_phys(_etext);
	data_resource.end = virt_to_phys(_edata)-1;

	parse_early_param();

	sh_mv_setup(cmdline_p);

	/*
	 * Find the highest page frame number we have available
	 */
	max_pfn = PFN_DOWN(__pa(memory_end));

	/*
	 * Determine low and high memory ranges:
	 */
	max_low_pfn = max_pfn;
	min_low_pfn = __MEMORY_START >> PAGE_SHIFT;

	nodes_clear(node_online_map);
	setup_memory();
	paging_init();
	sparse_init();

#ifdef CONFIG_DUMMY_CONSOLE
	conswitchp = &dummy_con;
@@ -332,8 +360,6 @@ void __init setup_arch(char **cmdline_p)
	/* Perform the machine specific initialisation */
	if (likely(sh_mv.mv_setup))
		sh_mv.mv_setup(cmdline_p);

	paging_init();
}

struct sh_machine_vector* __init get_mv_byname(const char* name)
+11 −0
Original line number Diff line number Diff line
@@ -291,6 +291,17 @@ config VSYSCALL
	  For systems with an MMU that can afford to give up a page,
	  (the default value) say Y.

config NODES_SHIFT
	int
	default "1"
	depends on NEED_MULTIPLE_NODES

config ARCH_FLATMEM_ENABLE
	def_bool y

config ARCH_POPULATES_NODE_MAP
	def_bool y

choice
	prompt "Kernel page size"
	default PAGE_SIZE_4KB
+92 −105
Original line number Diff line number Diff line
/* $Id: init.c,v 1.19 2004/02/21 04:42:16 kkojima Exp $
 *
/*
 * linux/arch/sh/mm/init.c
 *
 *  Copyright (C) 1999  Niibe Yutaka
 *  Copyright (C) 2002, 2004  Paul Mundt
 *  Copyright (C) 2002 - 2007  Paul Mundt
 *
 *  Based on linux/arch/i386/mm/init.c:
 *   Copyright (C) 1995  Linus Torvalds
 */

#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/highmem.h>
#include <linux/bootmem.h>
#include <linux/pagemap.h>
#include <linux/proc_fs.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <linux/percpu.h>
#include <linux/io.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
#include <asm/tlb.h>
#include <asm/cacheflush.h>
#include <asm/cache.h>
@@ -39,35 +22,49 @@
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
pgd_t swapper_pg_dir[PTRS_PER_PGD];

#ifdef CONFIG_MMU
/* It'd be good if these lines were in the standard header file. */
#define START_PFN	(NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
#define MAX_LOW_PFN	(NODE_DATA(0)->bdata->node_low_pfn)
#endif

void (*copy_page)(void *from, void *to);
void (*clear_page)(void *to);

void show_mem(void)
{
	int i, total = 0, reserved = 0;
	int shared = 0, cached = 0;
	int total = 0, reserved = 0, free = 0;
	int shared = 0, cached = 0, slab = 0;
	pg_data_t *pgdat;

	printk("Mem-info:\n");
	show_free_areas();
	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
	i = max_mapnr;
	while (i-- > 0) {

	for_each_online_pgdat(pgdat) {
		struct page *page, *end;
		unsigned long flags;

		pgdat_resize_lock(pgdat, &flags);
		page = pgdat->node_mem_map;
		end = page + pgdat->node_spanned_pages;

		do {
			total++;
		if (PageReserved(mem_map+i))
			if (PageReserved(page))
				reserved++;
		else if (PageSwapCache(mem_map+i))
			else if (PageSwapCache(page))
				cached++;
		else if (page_count(mem_map+i))
			shared += page_count(mem_map+i) - 1;
			else if (PageSlab(page))
				slab++;
			else if (!page_count(page))
				free++;
			else
				shared += page_count(page) - 1;
			page++;
		} while (page < end);

		pgdat_resize_unlock(pgdat, &flags);
	}

	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
	printk("%d pages of RAM\n", total);
	printk("%d free pages\n", free);
	printk("%d reserved pages\n", reserved);
	printk("%d slab pages\n", slab);
	printk("%d pages shared\n", shared);
	printk("%d pages swap cached\n", cached);
}
@@ -147,52 +144,38 @@ extern char __init_begin, __init_end;
 */
void __init paging_init(void)
{
	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
	int nid;

	/*
	 * Setup some defaults for the zone sizes.. these should be safe
	 * regardless of distcontiguous memory or MMU settings.
	 */
	zones_size[ZONE_NORMAL] = __MEMORY_SIZE >> PAGE_SHIFT;
#ifdef CONFIG_HIGHMEM
	zones_size[ZONE_HIGHMEM] = 0 >> PAGE_SHIFT;
#endif

#ifdef CONFIG_MMU
	/*
	 * If we have an MMU, and want to be using it .. we need to adjust
	 * the zone sizes accordingly, in addition to turning it on.
	 */
	{
	/* We don't need to map the kernel through the TLB, as
	 * it is permanatly mapped using P1. So clear the
	 * entire pgd. */
	memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));

		/* Turn on the MMU */
		enable_mmu();
		zones_size[ZONE_NORMAL] = MAX_LOW_PFN - START_PFN;
	}

	/* Set an initial value for the MMU.TTB so we don't have to
	 * check for a null value. */
	set_TTB(swapper_pg_dir);

#elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
	/*
	 * If we don't have CONFIG_MMU set and the processor in question
	 * still has an MMU, care needs to be taken to make sure it doesn't
	 * stay on.. Since the boot loader could have potentially already
	 * turned it on, and we clearly don't want it, we simply turn it off.
	 *
	 * We don't need to do anything special for the zone sizes, since the
	 * default values that were already configured up above should be
	 * satisfactory.
	 */
	disable_mmu();
#endif
	NODE_DATA(0)->node_mem_map = NULL;
	free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
	for_each_online_node(nid) {
		pg_data_t *pgdat = NODE_DATA(nid);
		unsigned long max_zone_pfns[MAX_NR_ZONES];
		unsigned long low, start_pfn;

		memset(max_zone_pfns, 0, sizeof(max_zone_pfns));

		start_pfn = pgdat->bdata->node_boot_start >> PAGE_SHIFT;
		low = pgdat->bdata->node_low_pfn;

		max_zone_pfns[ZONE_NORMAL] = low;
		add_active_range(nid, start_pfn, low);

		printk("Node %u: start_pfn = 0x%lx, low = 0x%lx\n",
		       nid, start_pfn, low);

		free_area_init_nodes(max_zone_pfns);

		printk("Node %u: mem_map starts at %p\n",
		       pgdat->node_id, pgdat->node_mem_map);
	}
}

static struct kcore_list kcore_mem, kcore_vmalloc;
@@ -200,18 +183,33 @@ static struct kcore_list kcore_mem, kcore_vmalloc;
void __init mem_init(void)
{
	int codesize, reservedpages, datasize, initsize;
	int tmp;
	extern unsigned long memory_start;
	int nid;

#ifdef CONFIG_MMU
	high_memory = (void *)__va(MAX_LOW_PFN * PAGE_SIZE);
#else
	extern unsigned long memory_end;
	reservedpages = 0;

	high_memory = (void *)(memory_end & PAGE_MASK);
#endif
	for_each_online_node(nid) {
		pg_data_t *pgdat = NODE_DATA(nid);
		unsigned long node_pages = 0;
		void *node_high_memory;
		int i;

	max_mapnr = num_physpages = MAP_NR(high_memory) - MAP_NR(memory_start);
		num_physpages += pgdat->node_present_pages;

		if (pgdat->node_spanned_pages)
			node_pages = free_all_bootmem_node(pgdat);

		totalram_pages += node_pages;

		for (i = 0; i < node_pages; i++)
			if (PageReserved(pgdat->node_mem_map + i))
				reservedpages++;

		node_high_memory = (void *)((pgdat->node_start_pfn +
					     pgdat->node_spanned_pages) <<
						PAGE_SHIFT);
		if (node_high_memory > high_memory)
			high_memory = node_high_memory;
	}

	/* clear the zero-page */
	memset(empty_zero_page, 0, PAGE_SIZE);
@@ -229,16 +227,6 @@ void __init mem_init(void)
	clear_page = clear_page_nommu;
#endif

	/* this will put all low memory onto the freelists */
	totalram_pages += free_all_bootmem_node(NODE_DATA(0));
	reservedpages = 0;
	for (tmp = 0; tmp < num_physpages; tmp++)
		/*
		 * Only count reserved RAM pages
		 */
		if (PageReserved(mem_map+tmp))
			reservedpages++;

	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
@@ -250,7 +238,7 @@ void __init mem_init(void)
	printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
	       "%dk reserved, %dk data, %dk init)\n",
		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
		max_mapnr << (PAGE_SHIFT-10),
		totalram_pages << (PAGE_SHIFT-10),
		codesize >> 10,
		reservedpages << (PAGE_SHIFT-10),
		datasize >> 10,
@@ -289,4 +277,3 @@ void free_initrd_mem(unsigned long start, unsigned long end)
	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
}
#endif
+4 −2
Original line number Diff line number Diff line
@@ -169,6 +169,8 @@ enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
#define destroy_context(mm)		do { } while (0)
#define set_asid(asid)			do { } while (0)
#define get_asid()			(0)
#define set_TTB(pgd)			do { } while (0)
#define get_TTB()			(0)
#define activate_context(mm,cpu)	do { } while (0)
#define switch_mm(prev,next,tsk)	do { } while (0)
#define deactivate_mm(tsk,mm)		do { } while (0)
@@ -211,8 +213,8 @@ static inline void disable_mmu(void)
 * MMU control handlers for processors lacking memory
 * management hardware.
 */
#define enable_mmu()	do { BUG(); } while (0)
#define disable_mmu()	do { BUG(); } while (0)
#define enable_mmu()	do { } while (0)
#define disable_mmu()	do { } while (0)
#endif

#endif /* __KERNEL__ */
+5 −5
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ extern void (*clear_page)(void *to);
extern void (*copy_page)(void *to, void *from);

extern unsigned long shm_align_mask;
extern unsigned long max_low_pfn, min_low_pfn;

#ifdef CONFIG_MMU
extern void clear_page_slow(void *to);
@@ -124,17 +125,16 @@ typedef struct { unsigned long pgd; } pgd_t;
#define PAGE_OFFSET		CONFIG_PAGE_OFFSET
#define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
#define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)

#define MAP_NR(addr)		(((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)

#define phys_to_page(phys)	(mem_map + (((phys)-__MEMORY_START) >> PAGE_SHIFT))
#define page_to_phys(page)	(((page - mem_map) << PAGE_SHIFT) + __MEMORY_START)
#define phys_to_page(phys)	(pfn_to_page(phys >> PAGE_SHIFT))
#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)

/* PFN start number, because of __MEMORY_START */
#define PFN_START		(__MEMORY_START >> PAGE_SHIFT)
#define ARCH_PFN_OFFSET		(PFN_START)
#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_valid(pfn)		(((pfn) - PFN_START) < max_mapnr)
#define pfn_valid(pfn)		((pfn) >= min_low_pfn && (pfn) < max_low_pfn)
#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)

#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \