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.h171
1 files changed, 160 insertions, 11 deletions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 4733d35d8223..6c90461ed99f 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -269,7 +269,9 @@ typedef struct pglist_data {
269 struct zone node_zones[MAX_NR_ZONES]; 269 struct zone node_zones[MAX_NR_ZONES];
270 struct zonelist node_zonelists[GFP_ZONETYPES]; 270 struct zonelist node_zonelists[GFP_ZONETYPES];
271 int nr_zones; 271 int nr_zones;
272#ifdef CONFIG_FLAT_NODE_MEM_MAP
272 struct page *node_mem_map; 273 struct page *node_mem_map;
274#endif
273 struct bootmem_data *bdata; 275 struct bootmem_data *bdata;
274 unsigned long node_start_pfn; 276 unsigned long node_start_pfn;
275 unsigned long node_present_pages; /* total number of physical pages */ 277 unsigned long node_present_pages; /* total number of physical pages */
@@ -284,6 +286,12 @@ typedef struct pglist_data {
284 286
285#define node_present_pages(nid) (NODE_DATA(nid)->node_present_pages) 287#define node_present_pages(nid) (NODE_DATA(nid)->node_present_pages)
286#define node_spanned_pages(nid) (NODE_DATA(nid)->node_spanned_pages) 288#define node_spanned_pages(nid) (NODE_DATA(nid)->node_spanned_pages)
289#ifdef CONFIG_FLAT_NODE_MEM_MAP
290#define pgdat_page_nr(pgdat, pagenr) ((pgdat)->node_mem_map + (pagenr))
291#else
292#define pgdat_page_nr(pgdat, pagenr) pfn_to_page((pgdat)->node_start_pfn + (pagenr))
293#endif
294#define nid_page_nr(nid, pagenr) pgdat_page_nr(NODE_DATA(nid),(pagenr))
287 295
288extern struct pglist_data *pgdat_list; 296extern struct pglist_data *pgdat_list;
289 297
@@ -400,7 +408,7 @@ int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, struct file *,
400/* Returns the number of the current Node. */ 408/* Returns the number of the current Node. */
401#define numa_node_id() (cpu_to_node(raw_smp_processor_id())) 409#define numa_node_id() (cpu_to_node(raw_smp_processor_id()))
402 410
403#ifndef CONFIG_DISCONTIGMEM 411#ifndef CONFIG_NEED_MULTIPLE_NODES
404 412
405extern struct pglist_data contig_page_data; 413extern struct pglist_data contig_page_data;
406#define NODE_DATA(nid) (&contig_page_data) 414#define NODE_DATA(nid) (&contig_page_data)
@@ -408,36 +416,177 @@ extern struct pglist_data contig_page_data;
408#define MAX_NODES_SHIFT 1 416#define MAX_NODES_SHIFT 1
409#define pfn_to_nid(pfn) (0) 417#define pfn_to_nid(pfn) (0)
410 418
411#else /* CONFIG_DISCONTIGMEM */ 419#else /* CONFIG_NEED_MULTIPLE_NODES */
412 420
413#include <asm/mmzone.h> 421#include <asm/mmzone.h>
414 422
423#endif /* !CONFIG_NEED_MULTIPLE_NODES */
424
425#ifdef CONFIG_SPARSEMEM
426#include <asm/sparsemem.h>
427#endif
428
415#if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED) 429#if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED)
416/* 430/*
417 * with 32 bit page->flags field, we reserve 8 bits for node/zone info. 431 * with 32 bit page->flags field, we reserve 8 bits for node/zone info.
418 * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes. 432 * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes.
419 */ 433 */
420#define MAX_NODES_SHIFT 6 434#define FLAGS_RESERVED 8
435
421#elif BITS_PER_LONG == 64 436#elif BITS_PER_LONG == 64
422/* 437/*
423 * with 64 bit flags field, there's plenty of room. 438 * with 64 bit flags field, there's plenty of room.
424 */ 439 */
425#define MAX_NODES_SHIFT 10 440#define FLAGS_RESERVED 32
441
442#else
443
444#error BITS_PER_LONG not defined
445
446#endif
447
448#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
449#define early_pfn_to_nid(nid) (0UL)
426#endif 450#endif
427 451
428#endif /* !CONFIG_DISCONTIGMEM */ 452#define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT)
453#define section_nr_to_pfn(sec) ((sec) << PFN_SECTION_SHIFT)
454
455#ifdef CONFIG_SPARSEMEM
456
457/*
458 * SECTION_SHIFT #bits space required to store a section #
459 *
460 * PA_SECTION_SHIFT physical address to/from section number
461 * PFN_SECTION_SHIFT pfn to/from section number
462 */
463#define SECTIONS_SHIFT (MAX_PHYSMEM_BITS - SECTION_SIZE_BITS)
464
465#define PA_SECTION_SHIFT (SECTION_SIZE_BITS)
466#define PFN_SECTION_SHIFT (SECTION_SIZE_BITS - PAGE_SHIFT)
467
468#define NR_MEM_SECTIONS (1UL << SECTIONS_SHIFT)
429 469
430#if NODES_SHIFT > MAX_NODES_SHIFT 470#define PAGES_PER_SECTION (1UL << PFN_SECTION_SHIFT)
431#error NODES_SHIFT > MAX_NODES_SHIFT 471#define PAGE_SECTION_MASK (~(PAGES_PER_SECTION-1))
472
473#if (MAX_ORDER - 1 + PAGE_SHIFT) > SECTION_SIZE_BITS
474#error Allocator MAX_ORDER exceeds SECTION_SIZE
432#endif 475#endif
433 476
434/* There are currently 3 zones: DMA, Normal & Highmem, thus we need 2 bits */ 477struct page;
435#define MAX_ZONES_SHIFT 2 478struct mem_section {
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;
488};
489
490extern struct mem_section mem_section[NR_MEM_SECTIONS];
436 491
437#if ZONES_SHIFT > MAX_ZONES_SHIFT 492static inline struct mem_section *__nr_to_section(unsigned long nr)
438#error ZONES_SHIFT > MAX_ZONES_SHIFT 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
529/*
530 * Given a kernel address, find the home node of the underlying memory.
531 */
532#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT)
533
534static inline struct mem_section *__pfn_to_section(unsigned long pfn)
535{
536 return __nr_to_section(pfn_to_section_nr(pfn));
537}
538
539#define pfn_to_page(pfn) \
540({ \
541 unsigned long __pfn = (pfn); \
542 __section_mem_map_addr(__pfn_to_section(__pfn)) + __pfn; \
543})
544#define page_to_pfn(page) \
545({ \
546 page - __section_mem_map_addr(__nr_to_section( \
547 page_to_section(page))); \
548})
549
550static inline int pfn_valid(unsigned long pfn)
551{
552 if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
553 return 0;
554 return valid_section(__nr_to_section(pfn_to_section_nr(pfn)));
555}
556
557/*
558 * These are _only_ used during initialisation, therefore they
559 * can use __initdata ... They could have names to indicate
560 * this restriction.
561 */
562#ifdef CONFIG_NUMA
563#define pfn_to_nid early_pfn_to_nid
564#endif
565
566#define pfn_to_pgdat(pfn) \
567({ \
568 NODE_DATA(pfn_to_nid(pfn)); \
569})
570
571#define early_pfn_valid(pfn) pfn_valid(pfn)
572void sparse_init(void);
573#else
574#define sparse_init() do {} while (0)
575#endif /* CONFIG_SPARSEMEM */
576
577#ifdef CONFIG_NODES_SPAN_OTHER_NODES
578#define early_pfn_in_nid(pfn, nid) (early_pfn_to_nid(pfn) == (nid))
579#else
580#define early_pfn_in_nid(pfn, nid) (1)
581#endif
582
583#ifndef early_pfn_valid
584#define early_pfn_valid(pfn) (1)
439#endif 585#endif
440 586
587void memory_present(int nid, unsigned long start, unsigned long end);
588unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
589
441#endif /* !__ASSEMBLY__ */ 590#endif /* !__ASSEMBLY__ */
442#endif /* __KERNEL__ */ 591#endif /* __KERNEL__ */
443#endif /* _LINUX_MMZONE_H */ 592#endif /* _LINUX_MMZONE_H */