Skip to content

Commit

Permalink
ARM: Fix pfn_valid() for sparse memory
Browse files Browse the repository at this point in the history
On OMAP platforms, some people want to declare to segment up the memory
between the kernel and a separate application such that there is a hole
in the middle of the memory as far as Linux is concerned.  However,
they want to be able to mmap() the hole.

This currently causes problems, because update_mmu_cache() thinks that
there are valid struct pages for the "hole".  Fix this by making
pfn_valid() slightly more expensive, by checking whether the PFN is
contained within the meminfo array.

Signed-off-by: Russell King <[email protected]>
Tested-by: Khasim Syed Mohammed <[email protected]>
  • Loading branch information
Russell King authored and Russell King committed Sep 12, 2009
1 parent 5eb38f4 commit b7cfda9
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 17 deletions.
17 changes: 0 additions & 17 deletions arch/arm/include/asm/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
*
* page_to_pfn(page) convert a struct page * to a PFN number
* pfn_to_page(pfn) convert a _valid_ PFN number to struct page *
* pfn_valid(pfn) indicates whether a PFN number is valid
*
* virt_to_page(k) convert a _valid_ virtual address to struct page *
* virt_addr_valid(k) indicates whether a virtual address is valid
Expand All @@ -221,10 +220,6 @@ static inline __deprecated void *bus_to_virt(unsigned long x)

#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET

#ifndef CONFIG_SPARSEMEM
#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
#endif

#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)

Expand All @@ -241,18 +236,6 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
#define arch_pfn_to_nid(pfn) PFN_TO_NID(pfn)
#define arch_local_page_offset(pfn, nid) LOCAL_MAP_NR((pfn) << PAGE_SHIFT)

#define pfn_valid(pfn) \
({ \
unsigned int nid = PFN_TO_NID(pfn); \
int valid = nid < MAX_NUMNODES; \
if (valid) { \
pg_data_t *node = NODE_DATA(nid); \
valid = (pfn - node->node_start_pfn) < \
node->node_spanned_pages; \
} \
valid; \
})

#define virt_to_page(kaddr) \
(ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))

Expand Down
4 changes: 4 additions & 0 deletions arch/arm/include/asm/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ typedef unsigned long pgprot_t;

typedef struct page *pgtable_t;

#ifndef CONFIG_SPARSEMEM
extern int pfn_valid(unsigned long);
#endif

#include <asm/memory.h>

#endif /* !__ASSEMBLY__ */
Expand Down
32 changes: 32 additions & 0 deletions arch/arm/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/mman.h>
#include <linux/nodemask.h>
#include <linux/initrd.h>
#include <linux/sort.h>
#include <linux/highmem.h>

#include <asm/mach-types.h>
Expand Down Expand Up @@ -349,12 +350,43 @@ static void __init bootmem_free_node(int node, struct meminfo *mi)
free_area_init_node(node, zone_size, min, zhole_size);
}

#ifndef CONFIG_SPARSEMEM
int pfn_valid(unsigned long pfn)
{
struct meminfo *mi = &meminfo;
unsigned int left = 0, right = mi->nr_banks;

do {
unsigned int mid = (right + left) / 2;
struct membank *bank = &mi->bank[mid];

if (pfn < bank_pfn_start(bank))
right = mid;
else if (pfn >= bank_pfn_end(bank))
left = mid + 1;
else
return 1;
} while (left < right);
return 0;
}
EXPORT_SYMBOL(pfn_valid);
#endif

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;
}

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.
*/
Expand Down

0 comments on commit b7cfda9

Please sign in to comment.