aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/mmzone.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/mmzone.h')
-rw-r--r--include/linux/mmzone.h56
1 files changed, 51 insertions, 5 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 746b57e3d370..6c90461ed99f 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -476,11 +476,56 @@ extern struct pglist_data contig_page_data;
476 476
477struct page; 477struct page;
478struct mem_section { 478struct mem_section {
479 struct page *section_mem_map; 479 /*
480 * This is, logically, a pointer to an array of struct
481 * pages. However, it is stored with some other magic.
482 * (see sparse.c::sparse_init_one_section())
483 *
484 * Making it a UL at least makes someone do a cast
485 * before using it wrong.
486 */
487 unsigned long section_mem_map;
480}; 488};
481 489
482extern struct mem_section mem_section[NR_MEM_SECTIONS]; 490extern struct mem_section mem_section[NR_MEM_SECTIONS];
483 491
492static inline struct mem_section *__nr_to_section(unsigned long nr)
493{
494 return &mem_section[nr];
495}
496
497/*
498 * We use the lower bits of the mem_map pointer to store
499 * a little bit of information. There should be at least
500 * 3 bits here due to 32-bit alignment.
501 */
502#define SECTION_MARKED_PRESENT (1UL<<0)
503#define SECTION_HAS_MEM_MAP (1UL<<1)
504#define SECTION_MAP_LAST_BIT (1UL<<2)
505#define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1))
506
507static inline struct page *__section_mem_map_addr(struct mem_section *section)
508{
509 unsigned long map = section->section_mem_map;
510 map &= SECTION_MAP_MASK;
511 return (struct page *)map;
512}
513
514static inline int valid_section(struct mem_section *section)
515{
516 return (section->section_mem_map & SECTION_MARKED_PRESENT);
517}
518
519static inline int section_has_mem_map(struct mem_section *section)
520{
521 return (section->section_mem_map & SECTION_HAS_MEM_MAP);
522}
523
524static inline int valid_section_nr(unsigned long nr)
525{
526 return valid_section(__nr_to_section(nr));
527}
528
484/* 529/*
485 * Given a kernel address, find the home node of the underlying memory. 530 * Given a kernel address, find the home node of the underlying memory.
486 */ 531 */
@@ -488,24 +533,25 @@ extern struct mem_section mem_section[NR_MEM_SECTIONS];
488 533
489static inline struct mem_section *__pfn_to_section(unsigned long pfn) 534static inline struct mem_section *__pfn_to_section(unsigned long pfn)
490{ 535{
491 return &mem_section[pfn_to_section_nr(pfn)]; 536 return __nr_to_section(pfn_to_section_nr(pfn));
492} 537}
493 538
494#define pfn_to_page(pfn) \ 539#define pfn_to_page(pfn) \
495({ \ 540({ \
496 unsigned long __pfn = (pfn); \ 541 unsigned long __pfn = (pfn); \
497 __pfn_to_section(__pfn)->section_mem_map + __pfn; \ 542 __section_mem_map_addr(__pfn_to_section(__pfn)) + __pfn; \
498}) 543})
499#define page_to_pfn(page) \ 544#define page_to_pfn(page) \
500({ \ 545({ \
501 page - mem_section[page_to_section(page)].section_mem_map; \ 546 page - __section_mem_map_addr(__nr_to_section( \
547 page_to_section(page))); \
502}) 548})
503 549
504static inline int pfn_valid(unsigned long pfn) 550static inline int pfn_valid(unsigned long pfn)
505{ 551{
506 if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS) 552 if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
507 return 0; 553 return 0;
508 return mem_section[pfn_to_section_nr(pfn)].section_mem_map != 0; 554 return valid_section(__nr_to_section(pfn_to_section_nr(pfn)));
509} 555}
510 556
511/* 557/*