diff options
Diffstat (limited to 'include/linux/mmzone.h')
-rw-r--r-- | include/linux/mmzone.h | 171 |
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 | ||
288 | extern struct pglist_data *pgdat_list; | 296 | extern 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 | ||
405 | extern struct pglist_data contig_page_data; | 413 | extern 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 */ | 477 | struct page; |
435 | #define MAX_ZONES_SHIFT 2 | 478 | struct 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 | |||
490 | extern struct mem_section mem_section[NR_MEM_SECTIONS]; | ||
436 | 491 | ||
437 | #if ZONES_SHIFT > MAX_ZONES_SHIFT | 492 | static 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 | |||
507 | static 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 | |||
514 | static inline int valid_section(struct mem_section *section) | ||
515 | { | ||
516 | return (section->section_mem_map & SECTION_MARKED_PRESENT); | ||
517 | } | ||
518 | |||
519 | static inline int section_has_mem_map(struct mem_section *section) | ||
520 | { | ||
521 | return (section->section_mem_map & SECTION_HAS_MEM_MAP); | ||
522 | } | ||
523 | |||
524 | static 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 | |||
534 | static 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 | |||
550 | static 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) | ||
572 | void 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 | ||
587 | void memory_present(int nid, unsigned long start, unsigned long end); | ||
588 | unsigned 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 */ |