linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: linux@arm.linux.org.uk (Russell King - ARM Linux)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] ARM: allow, but warn, when issuing ioremap() on RAM
Date: Mon, 11 Oct 2010 16:25:16 +0100	[thread overview]
Message-ID: <20101011152516.GF27153@n2100.arm.linux.org.uk> (raw)
In-Reply-To: <AANLkTimQJLmDZPHtVJLCv9ZQgx_Yjh9=MOwOxMSAz4QX@mail.gmail.com>

On Sun, Oct 10, 2010 at 04:52:36AM +0300, Felipe Contreras wrote:
> At the time 'fixup' is called, 'meminfo' is empty; the tags haven't
> been parsed. So my solution is to move the memblock_add() after
> 'reserve', and pass 'meminfo' as an argument:

Here's a different approach which will work.  This pushes ARM further
towards using memblock for everything relating to memory init (although
we still have the old membank stuff around.)

The advantage with this is that memblock is now used as the basis for
determining where memory is, setting up the maps, freeing memory into
the pools, etc.

What this also means is that this code in the ->reserve callback:

	size = min(size, SZ_2M);
	base = memblock_alloc(size, min(align, SZ_2M));
	memblock_free(base, size);
	memblock_remove(base, size);

will result in [base+size] being removed from the available memory,
using highmem if available, if not from lowmem and removing it from
the lowmem memory map - which is exactly the behaviour we want.

 arch/arm/mm/init.c |  160 +++++++++++++++++++++++++++++++++++-----------------
 arch/arm/mm/mmu.c  |   43 ++++++++------
 mm/memblock.c      |    4 +
 3 files changed, 138 insertions(+), 69 deletions(-)

diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 36c4553..66db6b2 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -121,34 +121,32 @@ void show_mem(void)
 	printk("%d pages swap cached\n", cached);
 }
 
-static void __init find_limits(struct meminfo *mi,
-	unsigned long *min, unsigned long *max_low, unsigned long *max_high)
+static void __init find_limits(unsigned long *min, unsigned long *max_low,
+	unsigned long *max_high)
 {
+	struct meminfo *mi = &meminfo;
 	int i;
 
-	*min = -1UL;
-	*max_low = *max_high = 0;
+	*min = memblock_start_pfn(&memblock.memory, 0);
+	*max_high = PFN_DOWN(memblock_end_of_DRAM());
 
+	/* Use the old method to find the top of lowmem */
+	*max_low = 0;
 	for_each_bank (i, mi) {
 		struct membank *bank = &mi->bank[i];
-		unsigned long start, end;
-
-		start = bank_pfn_start(bank);
-		end = bank_pfn_end(bank);
+		unsigned long end;
 
-		if (*min > start)
-			*min = start;
-		if (*max_high < end)
-			*max_high = end;
 		if (bank->highmem)
 			continue;
+
+		end = bank_pfn_end(bank);
 		if (*max_low < end)
 			*max_low = end;
 	}
 }
 
-static void __init arm_bootmem_init(struct meminfo *mi,
-	unsigned long start_pfn, unsigned long end_pfn)
+static void __init arm_bootmem_init(unsigned long start_pfn,
+	unsigned long end_pfn)
 {
 	unsigned int boot_pages;
 	phys_addr_t bitmap;
@@ -171,27 +169,35 @@ static void __init arm_bootmem_init(struct meminfo *mi,
 	pgdat = NODE_DATA(0);
 	init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn);
 
-	for_each_bank(i, mi) {
-		struct membank *bank = &mi->bank[i];
-		if (!bank->highmem)
-			free_bootmem(bank_phys_start(bank), bank_phys_size(bank));
+	/* Free the lowmem regions from memblock into bootmem. */
+	for (i = 0; i < memblock.memory.cnt; i++) {
+		unsigned long start = memblock_start_pfn(&memblock.memory, i);
+		unsigned long end = memblock_end_pfn(&memblock.memory, i);
+
+		if (end >= end_pfn)
+			end = end_pfn;
+		if (start >= end)
+			break;
+
+		free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT);
 	}
 
-	/*
-	 * Reserve the memblock reserved regions in bootmem.
-	 */
+	/* Reserve the lowmem memblock reserved regions in bootmem. */
 	for (i = 0; i < memblock.reserved.cnt; i++) {
-		phys_addr_t start = memblock_start_pfn(&memblock.reserved, i);
-		if (start >= start_pfn &&
-		    memblock_end_pfn(&memblock.reserved, i) <= end_pfn)
-			reserve_bootmem_node(pgdat, __pfn_to_phys(start),
-				memblock_size_bytes(&memblock.reserved, i),
-				BOOTMEM_DEFAULT);
+		unsigned long start = memblock_start_pfn(&memblock.reserved, i);
+		unsigned long size = memblock_size_bytes(&memblock.reserved, i);
+
+		if (start >= end_pfn)
+			break;
+		if (start + PFN_UP(size) > end_pfn)
+			size = (end_pfn - start) << PAGE_SHIFT;
+
+		reserve_bootmem(__pfn_to_phys(start), size, BOOTMEM_DEFAULT);
 	}
 }
 
-static void __init arm_bootmem_free(struct meminfo *mi, unsigned long min,
-	unsigned long max_low, unsigned long max_high)
+static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
+	unsigned long max_high)
 {
 	unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
 	int i;
@@ -216,13 +222,23 @@ static void __init arm_bootmem_free(struct meminfo *mi, unsigned long min,
 	 *  holes = node_size - sum(bank_sizes)
 	 */
 	memcpy(zhole_size, zone_size, sizeof(zhole_size));
-	for_each_bank(i, mi) {
-		int idx = 0;
+	for (i = 0; i < memblock.memory.cnt; i++) {
+		unsigned long start = memblock_start_pfn(&memblock.memory, i);
+		unsigned long end = memblock_end_pfn(&memblock.memory, i);
+
+		if (start < max_low) {
+			unsigned long low_end = min(end, max_low);
+
+			zhole_size[0] -= low_end - start;
+		}
+
 #ifdef CONFIG_HIGHMEM
-		if (mi->bank[i].highmem)
-			idx = ZONE_HIGHMEM;
+		if (end > max_low) {
+			unsigned long high_start = max(start, max_low);
+
+			zhole_size[ZONE_HIGHMEM] -= end - high_start;
+		}
 #endif
-		zhole_size[idx] -= bank_pfn_size(&mi->bank[i]);
 	}
 
 	/*
@@ -303,14 +319,13 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
 
 void __init bootmem_init(void)
 {
-	struct meminfo *mi = &meminfo;
 	unsigned long min, max_low, max_high;
 
 	max_low = max_high = 0;
 
-	find_limits(mi, &min, &max_low, &max_high);
+	find_limits(&min, &max_low, &max_high);
 
-	arm_bootmem_init(mi, min, max_low);
+	arm_bootmem_init(min, max_low);
 
 	/*
 	 * Sparsemem tries to allocate bootmem in memory_present(),
@@ -328,7 +343,7 @@ void __init bootmem_init(void)
 	 * the sparse mem_map arrays initialized by sparse_init()
 	 * for memmap_init_zone(), otherwise all PFNs are invalid.
 	 */
-	arm_bootmem_free(mi, min, max_low, max_high);
+	arm_bootmem_free(min, max_low, max_high);
 
 	high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
 
@@ -422,6 +437,57 @@ static void __init free_unused_memmap(struct meminfo *mi)
 	}
 }
 
+static void __init free_highpages(void)
+{
+#ifdef CONFIG_HIGHMEM
+	unsigned long max_low = max_low_pfn + PHYS_PFN_OFFSET;
+	int i, j;
+
+	/* set highmem page free */
+	for (i = j = 0; i < memblock.memory.cnt; i++) {
+		unsigned long start = memblock_start_pfn(&memblock.memory, i);
+		unsigned long end = memblock_end_pfn(&memblock.memory, i);
+
+		/* Ignore complete lowmem entries */
+		if (end <= max_low)
+			continue;
+
+		/* Truncate partial highmem entries */
+		if (start < max_low)
+			start = max_low;
+
+		/* Find and exclude any reserved regions */
+		for (; j < memblock.reserved.cnt; j++) {
+			unsigned long res_start;
+			unsigned long res_end;
+
+			res_start = memblock_start_pfn(&memblock.reserved, j);
+			res_end = res_start + PFN_UP(memblock_size_bytes(&memblock.reserved, j));
+
+			if (res_end < start)
+				continue;
+			if (res_start < start)
+				res_start = start;
+			if (res_start > end)
+				res_start = end;
+			if (res_end > end)
+				res_end = end;
+			if (res_start != start)
+				totalhigh_pages += free_area(start, res_start,
+							     NULL);
+			start = res_end;
+			if (start == end)
+				break;
+		}
+
+		/* And now free anything which remains */
+		if (start < end)
+			totalhigh_pages += free_area(start, end, NULL);
+	}
+	totalram_pages += totalhigh_pages;
+#endif
+}
+
 /*
  * mem_init() marks the free areas in the mem_map and tells us how much
  * memory is free.  This is done after various parts of the system have
@@ -450,16 +516,7 @@ void __init mem_init(void)
 				    __phys_to_pfn(__pa(swapper_pg_dir)), NULL);
 #endif
 
-#ifdef CONFIG_HIGHMEM
-	/* set highmem page free */
-	for_each_bank (i, &meminfo) {
-		unsigned long start = bank_pfn_start(&meminfo.bank[i]);
-		unsigned long end = bank_pfn_end(&meminfo.bank[i]);
-		if (start >= max_low_pfn + PHYS_PFN_OFFSET)
-			totalhigh_pages += free_area(start, end, NULL);
-	}
-	totalram_pages += totalhigh_pages;
-#endif
+	free_highpages();
 
 	reserved_pages = free_pages = 0;
 
@@ -489,9 +546,10 @@ void __init mem_init(void)
 	 */
 	printk(KERN_INFO "Memory:");
 	num_physpages = 0;
-	for (i = 0; i < meminfo.nr_banks; i++) {
-		num_physpages += bank_pfn_size(&meminfo.bank[i]);
-		printk(" %ldMB", bank_phys_size(&meminfo.bank[i]) >> 20);
+	for (i = 0; i < memblock.memory.cnt; i++) {
+		unsigned long pages = memblock_size_pages(&memblock.memory, i);
+		num_physpages += pages;
+		printk(" %luMB", pages >> (20 - PAGE_SHIFT));
 	}
 	printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
 
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index e233581..6176e11 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -852,6 +852,7 @@ static void __init sanity_check_meminfo(void)
 static inline void prepare_page_table(void)
 {
 	unsigned long addr;
+	phys_addr_t end;
 
 	/*
 	 * Clear out all the mappings below the kernel image.
@@ -867,10 +868,18 @@ static inline void prepare_page_table(void)
 		pmd_clear(pmd_off_k(addr));
 
 	/*
+	 * Find the end of the first block of lowmem.  This is complicated
+	 * when we use memblock.
+	 */
+	end = memblock.memory.region[0].base + memblock.memory.region[0].size;
+	if (end >= lowmem_end_addr)
+		end = lowmem_end_addr;
+
+	/*
 	 * Clear out all the kernel space mappings, except for the first
 	 * memory bank, up to the end of the vmalloc region.
 	 */
-	for (addr = __phys_to_virt(bank_phys_end(&meminfo.bank[0]));
+	for (addr = __phys_to_virt(end);
 	     addr < VMALLOC_END; addr += PGDIR_SIZE)
 		pmd_clear(pmd_off_k(addr));
 }
@@ -987,29 +996,27 @@ static void __init kmap_init(void)
 #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];
+	for (i = 0; i < memblock.memory.cnt; i++) {
+		phys_addr_t start = memblock.memory.region[i].base;
+		phys_addr_t end = start + memblock.memory.region[i].size;
+		struct map_desc map;
+
+		if (end >= lowmem_end_addr)
+			end = lowmem_end_addr;
+		if (start >= end)
+			break;
+
+		map.pfn = __phys_to_pfn(start);
+		map.virtual = __phys_to_virt(start);
+		map.length = end - start;
+		map.type = MT_MEMORY;
 
-		if (!bank->highmem)
-			map_memory_bank(bank);
+		create_mapping(&map);
 	}
 }
 
diff --git a/mm/memblock.c b/mm/memblock.c
index 43840b3..aa69191 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -196,6 +196,10 @@ static long memblock_add_region(struct memblock_region *rgn, u64 base, u64 size)
 long memblock_add(u64 base, u64 size)
 {
 	struct memblock_region *_rgn = &memblock.memory;
+	u64 end = base + size;
+
+	base = PAGE_ALIGN(base);
+	size = (end & PAGE_MASK) - base;
 
 	/* On pSeries LPAR systems, the first MEMBLOCK is our RMO region. */
 	if (base == 0)

  parent reply	other threads:[~2010-10-11 15:25 UTC|newest]

Thread overview: 101+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-07  9:44 [PATCH] ARM: allow, but warn, when issuing ioremap() on RAM Felipe Contreras
2010-10-07 11:51 ` Baruch Siach
2010-10-07 12:29   ` [PATCH v2] " Felipe Contreras
2010-10-07 18:00     ` Uwe Kleine-König
2010-10-07 19:22 ` [PATCH] " Russell King - ARM Linux
2010-10-08  9:32   ` Felipe Contreras
2010-10-08 17:53     ` Russell King - ARM Linux
2010-10-08 19:37       ` Felipe Contreras
2010-10-08 23:04         ` Russell King - ARM Linux
2010-10-08 23:25           ` Greg KH
2010-10-08 23:44             ` Russell King - ARM Linux
2010-10-09  0:00               ` Greg KH
2010-10-09  0:25                 ` Russell King - ARM Linux
2010-10-09  0:54                   ` Greg KH
2010-10-09  2:41                   ` Nicolas Pitre
2010-10-09  3:04                     ` Greg KH
2010-10-09  9:32                       ` Felipe Contreras
2010-10-11 10:05                     ` Catalin Marinas
2010-10-11 10:39                       ` Felipe Contreras
2010-10-11 10:52                         ` Russell King - ARM Linux
2010-10-11 11:23                         ` Catalin Marinas
2010-10-11 12:03                           ` Felipe Contreras
2010-10-11 12:30                             ` Catalin Marinas
2010-10-11 22:53                               ` Nicolas Pitre
2010-10-14 15:02                               ` Felipe Contreras
2010-10-14 17:18                                 ` Catalin Marinas
2010-10-14 17:44                                   ` Felipe Contreras
2010-10-11 11:01                       ` Pawel Moll
2010-10-11 11:03                         ` Catalin Marinas
2010-10-16  2:39                 ` Benjamin Herrenschmidt
2010-10-16  9:43                   ` Felipe Contreras
2010-10-09  0:10               ` Russell King - ARM Linux
2010-10-09  0:56               ` Felipe Contreras
2010-10-09  9:21                 ` Russell King - ARM Linux
2010-10-09 10:28                   ` Felipe Contreras
2010-10-09 11:11                     ` Arnd Bergmann
2010-10-09 11:43                       ` Dave Airlie
2010-10-09 11:55                         ` Christoph Hellwig
2010-10-09 12:17                           ` Felipe Contreras
2010-10-09 12:10                         ` Felipe Contreras
2010-10-09 14:37                           ` Russell King - ARM Linux
2010-10-09 16:18                             ` Felipe Contreras
2010-10-09 11:44                       ` Uwe Kleine-König
2010-10-09 12:05                         ` Russell King - ARM Linux
2010-10-09 11:59                       ` Felipe Contreras
2010-10-09 14:43                         ` Arnd Bergmann
2010-10-09 18:59                           ` Guennadi Liakhovetski
2010-10-10  1:52                   ` Felipe Contreras
2010-10-11  8:35                     ` Uwe Kleine-König
2010-10-11  9:02                       ` Russell King - ARM Linux
2010-10-11  9:24                         ` Uwe Kleine-König
2010-10-11 10:08                           ` Felipe Contreras
2010-10-11 10:15                             ` Russell King - ARM Linux
2010-10-11 15:25                     ` Russell King - ARM Linux [this message]
2010-10-14 14:47                       ` Felipe Contreras
2010-10-19  8:13                       ` Colin Cross
2010-10-19 18:12                         ` Russell King - ARM Linux
2010-10-19 19:21                         ` Russell King - ARM Linux
2010-11-23  9:43                       ` [PATCH] ARM: mx3/pcm037: properly allocate memory for mx3-camera Uwe Kleine-König
2010-11-23 10:12                         ` Russell King - ARM Linux
2010-11-23 10:26                           ` Uwe Kleine-König
2010-11-23 14:08                             ` Alberto Panizzo
2010-11-23 14:17                               ` Uwe Kleine-König
2010-11-24  8:02                                 ` Uwe Kleine-König
2010-12-06  8:33                                   ` Uwe Kleine-König
2010-12-06 10:14                                     ` Alberto Panizzo
2010-12-06 10:26                                       ` Russell King - ARM Linux
2010-12-06 11:37                                         ` Alberto Panizzo
2010-12-06 11:46                                           ` Russell King - ARM Linux
2010-12-06 14:09                                             ` Alberto Panizzo
2010-12-06 14:34                                               ` Russell King - ARM Linux
2010-12-06 14:54                                                 ` Alberto Panizzo
2010-12-06 16:54                                                   ` Alberto Panizzo
2010-11-23 10:39                           ` About multi-line printk and the need (not) to repeat loglevel markers [Was: Re: [PATCH] ARM: mx3/pcm037: properly allocate memory for mx3-camera] Uwe Kleine-König
2010-11-23 10:58                             ` Uwe Kleine-König
2010-11-23 22:16                               ` Linus Torvalds
2010-11-23 22:33                                 ` Russell King - ARM Linux
2010-11-23 23:23                                   ` Joe Perches
2010-11-24  8:17                                 ` Uwe Kleine-König
2010-11-24  9:09                                   ` Michał Mirosław
2010-11-23 22:54                         ` [PATCH] ARM: mx3/pcm037: properly allocate memory for mx3-camera Guennadi Liakhovetski
2010-10-09  0:45             ` [PATCH] ARM: allow, but warn, when issuing ioremap() on RAM Felipe Contreras
2010-10-09  8:56               ` Russell King - ARM Linux
2010-10-08 23:19       ` Greg KH
2010-10-09  3:36         ` Nicolas Pitre
2010-10-09 10:00           ` Felipe Contreras
2010-10-09 17:38             ` Nicolas Pitre
2010-10-09 20:16               ` Felipe Contreras
2010-10-13 16:17             ` Woodruff, Richard
2010-10-14 13:48               ` Felipe Contreras
2010-10-14 15:29                 ` Woodruff, Richard
2010-10-16  2:36       ` Benjamin Herrenschmidt
2010-10-17 13:05         ` Woodruff, Richard
2010-10-17 23:17           ` Benjamin Herrenschmidt
2010-10-08 19:58   ` Andrew Morton
2010-10-09 13:52 ` Russell King - ARM Linux
2010-10-09 16:07   ` Felipe Contreras
2010-10-09 16:45     ` Russell King - ARM Linux
2010-10-09 19:25       ` Felipe Contreras
2010-10-10 14:23       ` Pedanekar, Hemant
2010-10-11  9:26       ` Catalin Marinas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20101011152516.GF27153@n2100.arm.linux.org.uk \
    --to=linux@arm.linux.org.uk \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).