]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
memblock, bootmem: Round pfn properly for memory and reserved regions
authorYinghai Lu <yinghai@kernel.org>
Tue, 12 Oct 2010 21:07:09 +0000 (14:07 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Tue, 12 Oct 2010 22:37:51 +0000 (15:37 -0700)
We need to round memory regions correctly -- specifically, we need to
round reserved region in the more expansive direction (lower limit
down, upper limit up) whereas usable memory regions need to be rounded
in the more restrictive direction (lower limit up, upper limit down).

This introduces two set of inlines:

memblock_region_memory_base_pfn()
memblock_region_memory_end_pfn()
memblock_region_reserved_base_pfn()
memblock_region_reserved_end_pfn()

Although they are antisymmetric (and therefore are technically
duplicates) the use of the different inlines explicitly documents the
programmer's intention.

The lack of proper rounding caused a bug on ARM, which was then found
to also affect other architectures.

Reported-by: Russell King <rmk@arm.linux.org.uk>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
LKML-Reference: <4CB4CDFD.4020105@kernel.org>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
arch/arm/mm/init.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/sh/mm/init.c
arch/sparc/mm/init_64.c
include/linux/memblock.h

index d6022d1f51d107e8a38439fdcb16a172ffe2592a..63f441797c96e6d795e4c710ecef887cb7f89e6d 100644 (file)
@@ -182,8 +182,8 @@ static void __init arm_bootmem_init(struct meminfo *mi,
         * Reserve the memblock reserved regions in bootmem.
         */
        for_each_memblock(reserved, reg) {
-               phys_addr_t start = memblock_region_base_pfn(reg);
-               phys_addr_t end = memblock_region_end_pfn(reg);
+               phys_addr_t start = memblock_region_reserved_base_pfn(reg);
+               phys_addr_t end = memblock_region_reserved_end_pfn(reg);
                if (start >= start_pfn && end <= end_pfn)
                        reserve_bootmem_node(pgdat, __pfn_to_phys(start),
                                             (end - start) << PAGE_SHIFT,
@@ -251,8 +251,8 @@ static void arm_memory_present(void)
        struct memblock_region *reg;
 
        for_each_memblock(memory, reg)
-               memory_present(0, memblock_region_base_pfn(reg),
-                              memblock_region_end_pfn(reg));
+               memory_present(0, memblock_region_memory_base_pfn(reg),
+                              memblock_region_memory_end_pfn(reg));
 }
 #endif
 
index f661f6c527da4f940e5e8301bda429be995c379c..a66499650909bb1bce5d97a48ca7894b22d5241e 100644 (file)
@@ -148,8 +148,8 @@ walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
        int ret = -1;
 
        for_each_memblock(memory, reg) {
-               tstart = max(start_pfn, memblock_region_base_pfn(reg));
-               tend = min(end_pfn, memblock_region_end_pfn(reg));
+               tstart = max(start_pfn, memblock_region_memory_base_pfn(reg));
+               tend = min(end_pfn, memblock_region_memory_end_pfn(reg));
                if (tstart >= tend)
                        continue;
                ret = (*func)(tstart, tend - tstart, arg);
@@ -195,8 +195,8 @@ void __init do_init_bootmem(void)
        /* Add active regions with valid PFNs */
        for_each_memblock(memory, reg) {
                unsigned long start_pfn, end_pfn;
-               start_pfn = memblock_region_base_pfn(reg);
-               end_pfn = memblock_region_end_pfn(reg);
+               start_pfn = memblock_region_memory_base_pfn(reg);
+               end_pfn = memblock_region_memory_end_pfn(reg);
                add_active_range(0, start_pfn, end_pfn);
        }
 
@@ -236,9 +236,9 @@ static int __init mark_nonram_nosave(void)
 
        for_each_memblock(memory, reg) {
                if (prev &&
-                   memblock_region_end_pfn(prev) < memblock_region_base_pfn(reg))
-                       register_nosave_region(memblock_region_end_pfn(prev),
-                                              memblock_region_base_pfn(reg));
+                   memblock_region_memory_end_pfn(prev) < memblock_region_memory_base_pfn(reg))
+                       register_nosave_region(memblock_region_memory_end_pfn(prev),
+                                              memblock_region_memory_base_pfn(reg));
                prev = reg;
        }
        return 0;
index 066fb443ba5ac58e8fceb984a20032c691fd3724..74505b245374e305d64625056271147ab4125b1d 100644 (file)
@@ -811,8 +811,8 @@ static void __init setup_nonnuma(void)
               (top_of_ram - total_ram) >> 20);
 
        for_each_memblock(memory, reg) {
-               start_pfn = memblock_region_base_pfn(reg);
-               end_pfn = memblock_region_end_pfn(reg);
+               start_pfn = memblock_region_memory_base_pfn(reg);
+               end_pfn = memblock_region_memory_end_pfn(reg);
 
                fake_numa_create_new_node(end_pfn, &nid);
                add_active_range(nid, start_pfn, end_pfn);
index b977475f744616979ad4f80776ec0e5241743b71..552bea5113f550c415f2d9d70b86082e905b0814 100644 (file)
@@ -244,8 +244,8 @@ static void __init do_init_bootmem(void)
        /* Add active regions with valid PFNs. */
        for_each_memblock(memory, reg) {
                unsigned long start_pfn, end_pfn;
-               start_pfn = memblock_region_base_pfn(reg);
-               end_pfn = memblock_region_end_pfn(reg);
+               start_pfn = memblock_region_memory_base_pfn(reg);
+               end_pfn = memblock_region_memory_end_pfn(reg);
                __add_active_range(0, start_pfn, end_pfn);
        }
 
index dc584d26d597ea5e8d53fedeba061f61dd21d744..4c2572773b55a330868933b633882f9520a155ba 100644 (file)
@@ -1294,8 +1294,8 @@ static void __init bootmem_init_nonnuma(void)
                if (!reg->size)
                        continue;
 
-               start_pfn = memblock_region_base_pfn(reg);
-               end_pfn = memblock_region_end_pfn(reg);
+               start_pfn = memblock_region_memory_base_pfn(reg);
+               end_pfn = memblock_region_memory_end_pfn(reg);
                add_active_range(0, start_pfn, end_pfn);
        }
 
index 5096458c7535a6bb3396da49a25b94f2685d34be..62a10c2a11f2dc6a68f5bf4b1e30bbb23149ce6a 100644 (file)
@@ -111,40 +111,39 @@ extern void memblock_set_current_limit(phys_addr_t limit);
  */
 
 /**
- * memblock_region_base_pfn - Return the lowest pfn intersecting with the region
+ * memblock_region_memory_base_pfn - Return the lowest pfn intersecting with the memory region
  * @reg: memblock_region structure
  */
-static inline unsigned long memblock_region_base_pfn(const struct memblock_region *reg)
+static inline unsigned long memblock_region_memory_base_pfn(const struct memblock_region *reg)
 {
-       return reg->base >> PAGE_SHIFT;
+       return PFN_UP(reg->base);
 }
 
 /**
- * memblock_region_last_pfn - Return the highest pfn intersecting with the region
+ * memblock_region_memory_end_pfn - Return the end_pfn this region
  * @reg: memblock_region structure
  */
-static inline unsigned long memblock_region_last_pfn(const struct memblock_region *reg)
+static inline unsigned long memblock_region_memory_end_pfn(const struct memblock_region *reg)
 {
-       return (reg->base + reg->size - 1) >> PAGE_SHIFT;
+       return PFN_DOWN(reg->base + reg->size);
 }
 
 /**
- * memblock_region_end_pfn - Return the pfn of the first page following the region
- *                      but not intersecting it
+ * memblock_region_reserved_base_pfn - Return the lowest pfn intersecting with the reserved region
  * @reg: memblock_region structure
  */
-static inline unsigned long memblock_region_end_pfn(const struct memblock_region *reg)
+static inline unsigned long memblock_region_reserved_base_pfn(const struct memblock_region *reg)
 {
-       return memblock_region_last_pfn(reg) + 1;
+       return PFN_DOWN(reg->base);
 }
 
 /**
- * memblock_region_pages - Return the number of pages covering a region
+ * memblock_region_reserved_end_pfn - Return the end_pfn this region
  * @reg: memblock_region structure
  */
-static inline unsigned long memblock_region_pages(const struct memblock_region *reg)
+static inline unsigned long memblock_region_reserved_end_pfn(const struct memblock_region *reg)
 {
-       return memblock_region_end_pfn(reg) - memblock_region_end_pfn(reg);
+       return PFN_UP(reg->base + reg->size);
 }
 
 #define for_each_memblock(memblock_type, region)                                       \