From patchwork Fri Apr 9 11:11:05 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Russell King - ARM Linux X-Patchwork-Id: 91686 X-Patchwork-Delegate: tony@atomide.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o39BCNBL009608 for ; Fri, 9 Apr 2010 11:12:24 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751981Ab0DILMQ (ORCPT ); Fri, 9 Apr 2010 07:12:16 -0400 Received: from caramon.arm.linux.org.uk ([78.32.30.218]:40177 "EHLO caramon.arm.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751577Ab0DILMO (ORCPT ); Fri, 9 Apr 2010 07:12:14 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arm.linux.org.uk; s=caramon; h=Date:From:To:Cc:Subject: Message-ID:References:MIME-Version:Content-Type:In-Reply-To: Sender; bh=/0Jd4D8L4JwJA5+UXT+M73qqc1DAtLbMT0sH/543HFw=; b=ou5IM MHVbK9pEzIN7GgSt+REWvVtPCCrSBcRvMyontp76d/qdBYn7XXIcjYNEFH6+N1e3 bXV5kf+4y18cTZWKvdnXg1vRjTtxsBzrf/UqL36FbeHl4bBNYGWiQ/SuxM6vQ4xi kneSZHfMc8tYT+zh2EpGy0ZeRS19TWWU6Bm+V0= Received: from n2100.arm.linux.org.uk ([2002:4e20:1eda:1:214:fdff:fe10:4f86]) by caramon.arm.linux.org.uk with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.69) (envelope-from ) id 1O0C79-0007dy-Fd; Fri, 09 Apr 2010 12:11:09 +0100 Received: from linux by n2100.arm.linux.org.uk with local (Exim 4.69) (envelope-from ) id 1O0C77-0000sT-VG; Fri, 09 Apr 2010 12:11:06 +0100 Date: Fri, 9 Apr 2010 12:11:05 +0100 From: Russell King - ARM Linux To: Rabin Vincent Cc: Tony Lindgren , linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: Re: [RFC] Initial attempt to make ARM use LMB Message-ID: <20100409111105.GA2804@n2100.arm.linux.org.uk> References: <20100325233248.GM24984@n2100.arm.linux.org.uk> <20100408153111.GA2598@debian> <20100408182715.GF31407@n2100.arm.linux.org.uk> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20100408182715.GF31407@n2100.arm.linux.org.uk> User-Agent: Mutt/1.5.19 (2009-01-05) Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Fri, 09 Apr 2010 11:12:26 +0000 (UTC) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c5408bf..48254a4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -10,6 +10,7 @@ config ARM default y select HAVE_AOUT select HAVE_IDE + select HAVE_LMB select RTC_LIB select SYS_SUPPORTS_APM_EMULATION select GENERIC_ATOMIC64 if (!CPU_32v6K) diff --git a/arch/arm/include/asm/lmb.h b/arch/arm/include/asm/lmb.h new file mode 100644 index 0000000..1f49657 --- /dev/null +++ b/arch/arm/include/asm/lmb.h @@ -0,0 +1,16 @@ +#ifndef _ASM_ARM_LMB_H +#define _ASM_ARM_LMB_H + +#ifdef CONFIG_MMU +extern phys_addr_t lowmem_end_addr; +#define LMB_REAL_LIMIT lowmem_end_addr +#else +#define LMB_REAL_LIMIT 0 +#endif + +struct meminfo; +struct machine_desc; + +extern void arm_lmb_init(struct meminfo *, struct machine_desc *); + +#endif diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index c59842d..f634dbe 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h @@ -37,6 +37,7 @@ struct machine_desc { void (*fixup)(struct machine_desc *, struct tag *, char **, struct meminfo *); + void (*reserve)(void);/* reserve lmb blocks */ void (*map_io)(void);/* IO mapping function */ void (*init_irq)(void); struct sys_timer *timer; /* system tick timer */ diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index c91c77b..4f132f7 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -714,6 +715,8 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); + arm_lmb_init(&meminfo, mdesc); + paging_init(mdesc); request_standard_resources(&meminfo, mdesc); diff --git a/arch/arm/mach-clps711x/edb7211-arch.c b/arch/arm/mach-clps711x/edb7211-arch.c index dc81cc6..aba952c 100644 --- a/arch/arm/mach-clps711x/edb7211-arch.c +++ b/arch/arm/mach-clps711x/edb7211-arch.c @@ -18,6 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include +#include #include #include @@ -29,6 +30,12 @@ extern void edb7211_map_io(void); +/* Reserve screen memory region at the start of main system memory. */ +static void __init edb7211_reserve(void) +{ + lmb_reserve(PHYS_OFFSET, 0x00020000); +} + static void __init fixup_edb7211(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi) @@ -57,6 +64,7 @@ MACHINE_START(EDB7211, "CL-EDB7211 (EP7211 eval board)") .boot_params = 0xc0020100, /* 0xc0000000 - 0xc001ffff can be video RAM */ .fixup = fixup_edb7211, .map_io = edb7211_map_io, + .reserve = edb7211_reserve, .init_irq = clps711x_init_irq, .timer = &clps711x_timer, MACHINE_END diff --git a/arch/arm/mach-clps711x/mm.c b/arch/arm/mach-clps711x/mm.c index a7b4591..9865921 100644 --- a/arch/arm/mach-clps711x/mm.c +++ b/arch/arm/mach-clps711x/mm.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-integrator/common.h b/arch/arm/mach-integrator/common.h index 609c49d..87cfeed 100644 --- a/arch/arm/mach-integrator/common.h +++ b/arch/arm/mach-integrator/common.h @@ -1,2 +1,3 @@ extern void integrator_time_init(unsigned long, unsigned int); extern unsigned long integrator_gettimeoffset(void); +void integrator_reserve(void); diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 8b390e3..417c772 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -334,3 +335,13 @@ void __init integrator_time_init(unsigned long reload, unsigned int ctrl) */ setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); } + +/* + * We need to stop things allocating the low memory; ideally we need a + * better implementation of GFP_DMA which does not assume that DMA-able + * memory starts at zero. + */ +void __init integrator_reserve(void) +{ + lmb_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET); +} diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 8138a7e..9fbde0d 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -350,6 +350,7 @@ MACHINE_START(INTEGRATOR, "ARM-Integrator") .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc, .boot_params = 0x00000100, .map_io = ap_map_io, + .reserve = integrator_reserve, .init_irq = ap_init_irq, .timer = &ap_timer, .init_machine = ap_init, diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 66ef86d..8de5f35 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -585,6 +585,7 @@ MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") .io_pg_offst = ((0xf1600000) >> 18) & 0xfffc, .boot_params = 0x00000100, .map_io = intcp_map_io, + .reserve = integrator_reserve, .init_irq = intcp_init_irq, .timer = &cp_timer, .init_machine = intcp_init, diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 71728d3..0bce097 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c index e36639f..8e313b4 100644 --- a/arch/arm/mach-omap1/board-htcherald.c +++ b/arch/arm/mach-omap1/board-htcherald.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index c664947..aa3e209 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c index d902a81..b33fbe3 100644 --- a/arch/arm/mach-pxa/palmt5.c +++ b/arch/arm/mach-pxa/palmt5.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -396,6 +397,11 @@ static void __init palmt5_udc_init(void) } } +static void __init palmt5_reserve(void) +{ + lmb_reserve(0xa0200000, 0x1000); +} + static void __init palmt5_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(palmt5_pin_config)); @@ -421,6 +427,7 @@ MACHINE_START(PALMT5, "Palm Tungsten|T5") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .boot_params = 0xa0000100, .map_io = pxa_map_io, + .reserve = palmt5_reserve, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = palmt5_init diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c index d8b4469..e712b86 100644 --- a/arch/arm/mach-pxa/palmtreo.c +++ b/arch/arm/mach-pxa/palmtreo.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -633,6 +634,12 @@ static void __init treo_lcd_power_init(void) treo_lcd_screen.pxafb_lcd_power = treo_lcd_power; } +static void __init treo_reserve(void) +{ + lmb_reserve(0xa0000000, 0x1000); + lmb_reserve(0xa2000000, 0x1000); +} + static void __init treo_init(void) { pxa_set_ffuart_info(NULL); @@ -668,6 +675,7 @@ MACHINE_START(TREO680, "Palm Treo 680") .io_pg_offst = io_p2v(0x40000000), .boot_params = 0xa0000100, .map_io = pxa_map_io, + .reserve = treo_reserve, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = treo680_init, @@ -691,6 +699,7 @@ MACHINE_START(CENTRO, "Palm Centro 685") .io_pg_offst = io_p2v(0x40000000), .boot_params = 0xa0000100, .map_io = pxa_map_io, + .reserve = treo_reserve, .init_irq = pxa27x_init_irq, .timer = &pxa_timer, .init_machine = centro_init, diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index fbedd07..bfbcdd0 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -301,6 +302,13 @@ static void __init h1940_map_io(void) s3c_pm_init(); } +/* H1940 and RX3715 need to reserve this for suspend */ +static void __init h1940_reserve(void) +{ + lmb_reserve(0x30003000, 0x1000); + lmb_reserve(0x30081000, 0x1000); +} + static void __init h1940_init_irq(void) { s3c24xx_init_irq(); @@ -342,6 +350,7 @@ MACHINE_START(H1940, "IPAQ-H1940") .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, .map_io = h1940_map_io, + .reserve = h1940_reserve, .init_irq = h1940_init_irq, .init_machine = h1940_init, .timer = &s3c24xx_timer, diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c index 1e836e5..76aa734 100644 --- a/arch/arm/mach-s3c2440/mach-rx3715.c +++ b/arch/arm/mach-s3c2440/mach-rx3715.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -191,6 +192,13 @@ static void __init rx3715_map_io(void) s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs)); } +/* H1940 and RX3715 need to reserve this for suspend */ +static void __init rx3715_reserve(void) +{ + lmb_reserve(0x30003000, 0x1000); + lmb_reserve(0x30081000, 0x1000); +} + static void __init rx3715_init_irq(void) { s3c24xx_init_irq(); @@ -214,6 +222,7 @@ MACHINE_START(RX3715, "IPAQ-RX3715") .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, .map_io = rx3715_map_io, + .reserve = rx3715_reserve, .init_irq = rx3715_init_irq, .init_machine = rx3715_init_machine, .timer = &s3c24xx_timer, diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c index d2a0b88..4fb8660 100644 --- a/arch/arm/mach-u300/u300.c +++ b/arch/arm/mach-u300/u300.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,21 @@ #include #include +static void __init u300_reserve(void) +{ + /* + * U300 - This platform family can share physical memory + * between two ARM cpus, one running Linux and the other + * running another OS. + */ +#ifdef CONFIG_MACH_U300_SINGLE_RAM +#if ((CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1) == 1) && \ + CONFIG_MACH_U300_2MB_ALIGNMENT_FIX + lmb_reserve(PHYS_OFFSET, 0x00100000); +#endif +#endif +} + static void __init u300_init_machine(void) { u300_init_devices(); @@ -49,6 +65,7 @@ MACHINE_START(U300, MACH_U300_STRING) .io_pg_offst = ((U300_AHB_PER_VIRT_BASE) >> 18) & 0xfffc, .boot_params = BOOT_PARAMS_OFFSET, .map_io = u300_map_io, + .reserve = u300_reserve, .init_irq = u300_init_irq, .timer = &u300_timer, .init_machine = u300_init_machine, diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 7829cb5..6eb00f8 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -15,8 +15,8 @@ #include #include #include -#include #include +#include #include #include @@ -150,119 +150,21 @@ static void __init find_node_limits(int node, struct meminfo *mi, } } -/* - * FIXME: We really want to avoid allocating the bootmap bitmap - * over the top of the initrd. Hopefully, this is located towards - * the start of a bank, so if we allocate the bootmap bitmap at - * the end, we won't clash. - */ -static unsigned int __init -find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages) -{ - unsigned int start_pfn, i, bootmap_pfn; - - start_pfn = PAGE_ALIGN(__pa(_end)) >> PAGE_SHIFT; - bootmap_pfn = 0; - - for_each_nodebank(i, mi, node) { - struct membank *bank = &mi->bank[i]; - unsigned int start, end; - - start = bank_pfn_start(bank); - end = bank_pfn_end(bank); - - if (end < start_pfn) - continue; - - if (start < start_pfn) - start = start_pfn; - - if (end <= start) - continue; - - if (end - start >= bootmap_pages) { - bootmap_pfn = start; - break; - } - } - - if (bootmap_pfn == 0) - BUG(); - - return bootmap_pfn; -} - -static int __init check_initrd(struct meminfo *mi) -{ - int initrd_node = -2; -#ifdef CONFIG_BLK_DEV_INITRD - unsigned long end = phys_initrd_start + phys_initrd_size; - - /* - * Make sure that the initrd is within a valid area of - * memory. - */ - if (phys_initrd_size) { - unsigned int i; - - initrd_node = -1; - - for (i = 0; i < mi->nr_banks; i++) { - struct membank *bank = &mi->bank[i]; - if (bank_phys_start(bank) <= phys_initrd_start && - end <= bank_phys_end(bank)) - initrd_node = bank->node; - } - } - - if (initrd_node == -1) { - printk(KERN_ERR "INITRD: 0x%08lx+0x%08lx extends beyond " - "physical memory - disabling initrd\n", - phys_initrd_start, phys_initrd_size); - phys_initrd_start = phys_initrd_size = 0; - } -#endif - - return initrd_node; -} - -static inline void map_memory_bank(struct membank *bank) -{ -#ifdef CONFIG_MMU - struct map_desc map; - - map.pfn = bank_pfn_start(bank); - map.virtual = __phys_to_virt(bank_phys_start(bank)); - map.length = bank_phys_size(bank); - map.type = MT_MEMORY; - - create_mapping(&map); -#endif -} - static void __init bootmem_init_node(int node, struct meminfo *mi, unsigned long start_pfn, unsigned long end_pfn) { - unsigned long boot_pfn; unsigned int boot_pages; + phys_addr_t bitmap; pg_data_t *pgdat; int i; /* - * Map the memory banks for this node. - */ - for_each_nodebank(i, mi, node) { - struct membank *bank = &mi->bank[i]; - - if (!bank->highmem) - map_memory_bank(bank); - } - - /* - * Allocate the bootmem bitmap page. + * Allocate the bootmem bitmap page. This must be in a region + * of memory which has already been mapped. */ boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); - boot_pfn = find_bootmap_pfn(node, mi, boot_pages); + bitmap = lmb_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES, + __pfn_to_phys(end_pfn)); /* * Initialise the bootmem allocator for this node, handing the @@ -270,7 +172,7 @@ static void __init bootmem_init_node(int node, struct meminfo *mi, */ node_set_online(node); pgdat = NODE_DATA(node); - init_bootmem_node(pgdat, boot_pfn, start_pfn, end_pfn); + init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn); for_each_nodebank(i, mi, node) { struct membank *bank = &mi->bank[i]; @@ -279,31 +181,16 @@ static void __init bootmem_init_node(int node, struct meminfo *mi, } /* - * Reserve the bootmem bitmap for this node. + * Reserve the LMB reserved regions in bootmem for this node. */ - reserve_bootmem_node(pgdat, boot_pfn << PAGE_SHIFT, - boot_pages << PAGE_SHIFT, BOOTMEM_DEFAULT); -} - -static void __init bootmem_reserve_initrd(int node) -{ -#ifdef CONFIG_BLK_DEV_INITRD - pg_data_t *pgdat = NODE_DATA(node); - int res; - - res = reserve_bootmem_node(pgdat, phys_initrd_start, - phys_initrd_size, BOOTMEM_EXCLUSIVE); - - if (res == 0) { - initrd_start = __phys_to_virt(phys_initrd_start); - initrd_end = initrd_start + phys_initrd_size; - } else { - printk(KERN_ERR - "INITRD: 0x%08lx+0x%08lx overlaps in-use " - "memory region - disabling initrd\n", - phys_initrd_start, phys_initrd_size); + for (i = 0; i < lmb.reserved.cnt; i++) { + phys_addr_t start = lmb_start_pfn(&lmb.reserved, i); + if (start >= start_pfn && + lmb_end_pfn(&lmb.reserved, i) <= end_pfn) + reserve_bootmem_node(pgdat, __pfn_to_phys(start), + lmb_size_bytes(&lmb.reserved, i), + BOOTMEM_DEFAULT); } -#endif } static void __init bootmem_free_node(int node, struct meminfo *mi) @@ -387,25 +274,41 @@ static void arm_memory_present(struct meminfo *mi, int node) } #endif -static int __init meminfo_cmp(const void *_a, const void *_b) +void __init arm_lmb_init(struct meminfo *mi, struct machine_desc *mdesc) { - const struct membank *a = _a, *b = _b; - long cmp = bank_pfn_start(a) - bank_pfn_start(b); - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; + int i; + + for (i = 0; i < mi->nr_banks; i++) + lmb_add(mi->bank[i].start, mi->bank[i].size); + + /* Register the kernel text, kernel data and initrd with lmb. */ +#ifdef CONFIG_XIP_KERNEL + lmb_reserve(__pa(_data), _end - _data); +#else + lmb_reserve(__pa(_stext), _end - _stext); +#endif +#ifdef CONFIG_BLK_DEV_INITRD + if (phys_initrd_size) { + lmb_reserve(phys_initrd_start, phys_initrd_size); + + /* Now convert initrd to virtual addresses */ + initrd_start = __phys_to_virt(phys_initrd_start); + initrd_end = initrd_start + phys_initrd_size; + } +#endif + + arm_mm_lmb_reserve(); + + /* reserve any lmb areas */ + if (mdesc->reserve) + mdesc->reserve(); } void __init bootmem_init(void) { struct meminfo *mi = &meminfo; unsigned long min, max_low, max_high; - int node, initrd_node; - - sort(&mi->bank, mi->nr_banks, sizeof(mi->bank[0]), meminfo_cmp, NULL); - - /* - * Locate which node contains the ramdisk image, if any. - */ - initrd_node = check_initrd(mi); + int node; max_low = max_high = 0; @@ -432,18 +335,6 @@ void __init bootmem_init(void) bootmem_init_node(node, mi, min, node_low); /* - * Reserve any special node zero regions. - */ - if (node == 0) - reserve_node_zero(NODE_DATA(node)); - - /* - * If the initrd is in this node, reserve its memory. - */ - if (node == initrd_node) - bootmem_reserve_initrd(node); - - /* * Sparsemem tries to allocate bootmem in memory_present(), * so must be done after the fixed reservations */ @@ -566,6 +457,13 @@ void __init mem_init(void) unsigned long reserved_pages, free_pages; int i, node; +#ifdef CONFIG_SA1111 + lmb_free(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET); +#endif + + lmb_analyze(); + lmb_dump_all(); + #ifndef CONFIG_DISCONTIGMEM max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map; #endif diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index a888363..966dc45 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -28,10 +28,6 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page #endif -struct map_desc; -struct meminfo; -struct pglist_data; - -void __init create_mapping(struct map_desc *md); void __init bootmem_init(void); -void reserve_node_zero(struct pglist_data *pgdat); +void arm_lmb_reserve(void); +void arm_mm_lmb_reserve(void); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9d4da6a..81eb08a 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -11,9 +11,10 @@ #include #include #include -#include #include #include +#include +#include #include #include @@ -483,6 +484,13 @@ static void __init build_mem_type_table(void) #define vectors_base() (vectors_high() ? 0xffff0000 : 0) +static void __init *early_alloc(unsigned long sz) +{ + void *ptr = __va(lmb_alloc(sz, sz)); + memset(ptr, 0, PAGE_SIZE); + return ptr; +} + static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, unsigned long end, unsigned long pfn, const struct mem_type *type) @@ -490,7 +498,7 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, pte_t *pte; if (pmd_none(*pmd)) { - pte = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * sizeof(pte_t)); + pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t)); __pmd_populate(pmd, __pa(pte) | type->prot_l1); } @@ -599,7 +607,7 @@ static void __init create_36bit_mapping(struct map_desc *md, * offsets, and we take full advantage of sections and * supersections. */ -void __init create_mapping(struct map_desc *md) +static void __init create_mapping(struct map_desc *md) { unsigned long phys, addr, length, end; const struct mem_type *type; @@ -693,6 +701,9 @@ early_param("vmalloc", early_vmalloc); #define VMALLOC_MIN (void *)(VMALLOC_END - vmalloc_reserve) +/* FIXME: we need to teach LMB about the highmem boundary */ +phys_addr_t lowmem_end_addr = PHYS_OFFSET + 32*1048576; + static void __init sanity_check_meminfo(void) { int i, j, highmem = 0; @@ -822,100 +833,23 @@ static inline void prepare_page_table(void) } /* - * Reserve the various regions of node 0 + * Reserve the special regions of memory */ -void __init reserve_node_zero(pg_data_t *pgdat) +void __init arm_mm_lmb_reserve(void) { - unsigned long res_size = 0; - - /* - * Register the kernel text and data with bootmem. - * Note that this can only be in node 0. - */ -#ifdef CONFIG_XIP_KERNEL - reserve_bootmem_node(pgdat, __pa(_data), _end - _data, - BOOTMEM_DEFAULT); -#else - reserve_bootmem_node(pgdat, __pa(_stext), _end - _stext, - BOOTMEM_DEFAULT); -#endif - /* * Reserve the page tables. These are already in use, * and can only be in node 0. */ - reserve_bootmem_node(pgdat, __pa(swapper_pg_dir), - PTRS_PER_PGD * sizeof(pgd_t), BOOTMEM_DEFAULT); - - /* - * Hmm... This should go elsewhere, but we really really need to - * stop things allocating the low memory; ideally we need a better - * implementation of GFP_DMA which does not assume that DMA-able - * memory starts at zero. - */ - if (machine_is_integrator() || machine_is_cintegrator()) - res_size = __pa(swapper_pg_dir) - PHYS_OFFSET; - - /* - * These should likewise go elsewhere. They pre-reserve the - * screen memory region at the start of main system memory. - */ - if (machine_is_edb7211()) - res_size = 0x00020000; - if (machine_is_p720t()) - res_size = 0x00014000; - - /* H1940 and RX3715 need to reserve this for suspend */ - - if (machine_is_h1940() || machine_is_rx3715()) { - reserve_bootmem_node(pgdat, 0x30003000, 0x1000, - BOOTMEM_DEFAULT); - reserve_bootmem_node(pgdat, 0x30081000, 0x1000, - BOOTMEM_DEFAULT); - } - - if (machine_is_palmld() || machine_is_palmtx()) { - reserve_bootmem_node(pgdat, 0xa0000000, 0x1000, - BOOTMEM_EXCLUSIVE); - reserve_bootmem_node(pgdat, 0xa0200000, 0x1000, - BOOTMEM_EXCLUSIVE); - } - - if (machine_is_treo680() || machine_is_centro()) { - reserve_bootmem_node(pgdat, 0xa0000000, 0x1000, - BOOTMEM_EXCLUSIVE); - reserve_bootmem_node(pgdat, 0xa2000000, 0x1000, - BOOTMEM_EXCLUSIVE); - } - - if (machine_is_palmt5()) - reserve_bootmem_node(pgdat, 0xa0200000, 0x1000, - BOOTMEM_EXCLUSIVE); - - /* - * U300 - This platform family can share physical memory - * between two ARM cpus, one running Linux and the other - * running another OS. - */ - if (machine_is_u300()) { -#ifdef CONFIG_MACH_U300_SINGLE_RAM -#if ((CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1) == 1) && \ - CONFIG_MACH_U300_2MB_ALIGNMENT_FIX - res_size = 0x00100000; -#endif -#endif - } + lmb_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t)); #ifdef CONFIG_SA1111 /* * Because of the SA1111 DMA bug, we want to preserve our * precious DMA-able memory... */ - res_size = __pa(swapper_pg_dir) - PHYS_OFFSET; + lmb_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET); #endif - if (res_size) - reserve_bootmem_node(pgdat, PHYS_OFFSET, res_size, - BOOTMEM_DEFAULT); } /* @@ -934,7 +868,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc) /* * Allocate the vector page early. */ - vectors = alloc_bootmem_low_pages(PAGE_SIZE); + vectors = early_alloc(PAGE_SIZE); for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE) pmd_clear(pmd_off_k(addr)); @@ -1006,13 +940,46 @@ static void __init kmap_init(void) { #ifdef CONFIG_HIGHMEM pmd_t *pmd = pmd_off_k(PKMAP_BASE); - pte_t *pte = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * sizeof(pte_t)); + pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t)); BUG_ON(!pmd_none(*pmd) || !pte); __pmd_populate(pmd, __pa(pte) | _PAGE_KERNEL_TABLE); pkmap_page_table = pte + PTRS_PER_PTE; #endif } +static inline void map_memory_bank(struct membank *bank) +{ + struct map_desc map; + + map.pfn = bank_pfn_start(bank); + map.virtual = __phys_to_virt(bank_phys_start(bank)); + map.length = bank_phys_size(bank); + map.type = MT_MEMORY; + + create_mapping(&map); +} + +static void __init map_lowmem(void) +{ + struct meminfo *mi = &meminfo; + int i; + + /* Map all the lowmem memory banks. */ + for (i = 0; i < mi->nr_banks; i++) { + struct membank *bank = &mi->bank[i]; + + if (!bank->highmem) + map_memory_bank(bank); + } +} + +static int __init meminfo_cmp(const void *_a, const void *_b) +{ + const struct membank *a = _a, *b = _b; + long cmp = bank_pfn_start(a) - bank_pfn_start(b); + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + /* * paging_init() sets up the page tables, initialises the zone memory * maps, and sets up the zero page, bad page and bad page tables. @@ -1021,20 +988,22 @@ void __init paging_init(struct machine_desc *mdesc) { void *zero_page; + sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL); + build_mem_type_table(); sanity_check_meminfo(); prepare_page_table(); - bootmem_init(); + map_lowmem(); devicemaps_init(mdesc); kmap_init(); top_pmd = pmd_off_k(0xffff0000); - /* - * allocate the zero page. Note that this always succeeds and - * returns a zeroed result. - */ - zero_page = alloc_bootmem_low_pages(PAGE_SIZE); + /* allocate the zero page. */ + zero_page = early_alloc(PAGE_SIZE); + + bootmem_init(); + empty_zero_page = virt_to_page(zero_page); __flush_dcache_page(NULL, empty_zero_page); } diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 9bfeb6b..ce00558 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -6,8 +6,8 @@ #include #include #include -#include #include +#include #include #include @@ -17,30 +17,14 @@ #include "mm.h" -/* - * Reserve the various regions of node 0 - */ -void __init reserve_node_zero(pg_data_t *pgdat) +void __init arm_mm_lmb_reserve(void) { /* - * Register the kernel text and data with bootmem. - * Note that this can only be in node 0. - */ -#ifdef CONFIG_XIP_KERNEL - reserve_bootmem_node(pgdat, __pa(_data), _end - _data, - BOOTMEM_DEFAULT); -#else - reserve_bootmem_node(pgdat, __pa(_stext), _end - _stext, - BOOTMEM_DEFAULT); -#endif - - /* * Register the exception vector page. * some architectures which the DRAM is the exception vector to trap, * alloc_page breaks with error, although it is not NULL, but "0." */ - reserve_bootmem_node(pgdat, CONFIG_VECTORS_BASE, PAGE_SIZE, - BOOTMEM_DEFAULT); + lmb_reserve(CONFIG_VECTORS_BASE, PAGE_SIZE); } /*