diff options
| -rw-r--r-- | include/linux/mm.h | 53 | ||||
| -rw-r--r-- | include/linux/mmzone.h | 19 | ||||
| -rw-r--r-- | mm/page_alloc.c | 2 |
3 files changed, 52 insertions, 22 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index 1813b162b0a8..57b2ead51dba 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -395,19 +395,41 @@ static inline void put_page(struct page *page) | |||
| 395 | /* | 395 | /* |
| 396 | * The zone field is never updated after free_area_init_core() | 396 | * The zone field is never updated after free_area_init_core() |
| 397 | * sets it, so none of the operations on it need to be atomic. | 397 | * sets it, so none of the operations on it need to be atomic. |
| 398 | * We'll have up to (MAX_NUMNODES * MAX_NR_ZONES) zones total, | ||
| 399 | * so we use (MAX_NODES_SHIFT + MAX_ZONES_SHIFT) here to get enough bits. | ||
| 400 | */ | 398 | */ |
| 401 | #define NODEZONE_SHIFT (sizeof(page_flags_t)*8 - MAX_NODES_SHIFT - MAX_ZONES_SHIFT) | 399 | |
| 400 | /* Page flags: | NODE | ZONE | ... | FLAGS | */ | ||
| 401 | #define NODES_PGOFF ((sizeof(page_flags_t)*8) - NODES_SHIFT) | ||
| 402 | #define ZONES_PGOFF (NODES_PGOFF - ZONES_SHIFT) | ||
| 403 | |||
| 404 | /* | ||
| 405 | * Define the bit shifts to access each section. For non-existant | ||
| 406 | * sections we define the shift as 0; that plus a 0 mask ensures | ||
| 407 | * the compiler will optimise away reference to them. | ||
| 408 | */ | ||
| 409 | #define NODES_PGSHIFT (NODES_PGOFF * (NODES_SHIFT != 0)) | ||
| 410 | #define ZONES_PGSHIFT (ZONES_PGOFF * (ZONES_SHIFT != 0)) | ||
| 411 | |||
| 412 | /* NODE:ZONE is used to lookup the zone from a page. */ | ||
| 413 | #define ZONETABLE_SHIFT (NODES_SHIFT + ZONES_SHIFT) | ||
| 414 | #define ZONETABLE_PGSHIFT ZONES_PGSHIFT | ||
| 415 | |||
| 416 | #if NODES_SHIFT+ZONES_SHIFT > FLAGS_RESERVED | ||
| 417 | #error NODES_SHIFT+ZONES_SHIFT > FLAGS_RESERVED | ||
| 418 | #endif | ||
| 419 | |||
| 402 | #define NODEZONE(node, zone) ((node << ZONES_SHIFT) | zone) | 420 | #define NODEZONE(node, zone) ((node << ZONES_SHIFT) | zone) |
| 403 | 421 | ||
| 422 | #define ZONES_MASK ((1UL << ZONES_SHIFT) - 1) | ||
| 423 | #define NODES_MASK ((1UL << NODES_SHIFT) - 1) | ||
| 424 | #define ZONETABLE_MASK ((1UL << ZONETABLE_SHIFT) - 1) | ||
| 425 | |||
| 404 | static inline unsigned long page_zonenum(struct page *page) | 426 | static inline unsigned long page_zonenum(struct page *page) |
| 405 | { | 427 | { |
| 406 | return (page->flags >> NODEZONE_SHIFT) & (~(~0UL << ZONES_SHIFT)); | 428 | return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK; |
| 407 | } | 429 | } |
| 408 | static inline unsigned long page_to_nid(struct page *page) | 430 | static inline unsigned long page_to_nid(struct page *page) |
| 409 | { | 431 | { |
| 410 | return (page->flags >> (NODEZONE_SHIFT + ZONES_SHIFT)); | 432 | return (page->flags >> NODES_PGSHIFT) & NODES_MASK; |
| 411 | } | 433 | } |
| 412 | 434 | ||
| 413 | struct zone; | 435 | struct zone; |
| @@ -415,13 +437,26 @@ extern struct zone *zone_table[]; | |||
| 415 | 437 | ||
| 416 | static inline struct zone *page_zone(struct page *page) | 438 | static inline struct zone *page_zone(struct page *page) |
| 417 | { | 439 | { |
| 418 | return zone_table[page->flags >> NODEZONE_SHIFT]; | 440 | return zone_table[(page->flags >> ZONETABLE_PGSHIFT) & |
| 441 | ZONETABLE_MASK]; | ||
| 442 | } | ||
| 443 | |||
| 444 | static inline void set_page_zone(struct page *page, unsigned long zone) | ||
| 445 | { | ||
| 446 | page->flags &= ~(ZONES_MASK << ZONES_PGSHIFT); | ||
| 447 | page->flags |= (zone & ZONES_MASK) << ZONES_PGSHIFT; | ||
| 448 | } | ||
| 449 | static inline void set_page_node(struct page *page, unsigned long node) | ||
| 450 | { | ||
| 451 | page->flags &= ~(NODES_MASK << NODES_PGSHIFT); | ||
| 452 | page->flags |= (node & NODES_MASK) << NODES_PGSHIFT; | ||
| 419 | } | 453 | } |
| 420 | 454 | ||
| 421 | static inline void set_page_zone(struct page *page, unsigned long nodezone_num) | 455 | static inline void set_page_links(struct page *page, unsigned long zone, |
| 456 | unsigned long node) | ||
| 422 | { | 457 | { |
| 423 | page->flags &= ~(~0UL << NODEZONE_SHIFT); | 458 | set_page_zone(page, zone); |
| 424 | page->flags |= nodezone_num << NODEZONE_SHIFT; | 459 | set_page_node(page, node); |
| 425 | } | 460 | } |
| 426 | 461 | ||
| 427 | #ifndef CONFIG_DISCONTIGMEM | 462 | #ifndef CONFIG_DISCONTIGMEM |
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index b79633d3a97b..39e912708e2a 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
| @@ -414,30 +414,25 @@ extern struct pglist_data contig_page_data; | |||
| 414 | 414 | ||
| 415 | #include <asm/mmzone.h> | 415 | #include <asm/mmzone.h> |
| 416 | 416 | ||
| 417 | #endif /* !CONFIG_DISCONTIGMEM */ | ||
| 418 | |||
| 417 | #if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED) | 419 | #if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED) |
| 418 | /* | 420 | /* |
| 419 | * with 32 bit page->flags field, we reserve 8 bits for node/zone info. | 421 | * with 32 bit page->flags field, we reserve 8 bits for node/zone info. |
| 420 | * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes. | 422 | * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes. |
| 421 | */ | 423 | */ |
| 422 | #define MAX_NODES_SHIFT 6 | 424 | #define FLAGS_RESERVED 8 |
| 425 | |||
| 423 | #elif BITS_PER_LONG == 64 | 426 | #elif BITS_PER_LONG == 64 |
| 424 | /* | 427 | /* |
| 425 | * with 64 bit flags field, there's plenty of room. | 428 | * with 64 bit flags field, there's plenty of room. |
| 426 | */ | 429 | */ |
| 427 | #define MAX_NODES_SHIFT 10 | 430 | #define FLAGS_RESERVED 32 |
| 428 | #endif | ||
| 429 | 431 | ||
| 430 | #endif /* !CONFIG_DISCONTIGMEM */ | 432 | #else |
| 431 | |||
| 432 | #if NODES_SHIFT > MAX_NODES_SHIFT | ||
| 433 | #error NODES_SHIFT > MAX_NODES_SHIFT | ||
| 434 | #endif | ||
| 435 | 433 | ||
| 436 | /* There are currently 3 zones: DMA, Normal & Highmem, thus we need 2 bits */ | 434 | #error BITS_PER_LONG not defined |
| 437 | #define MAX_ZONES_SHIFT 2 | ||
| 438 | 435 | ||
| 439 | #if ZONES_SHIFT > MAX_ZONES_SHIFT | ||
| 440 | #error ZONES_SHIFT > MAX_ZONES_SHIFT | ||
| 441 | #endif | 436 | #endif |
| 442 | 437 | ||
| 443 | #endif /* !__ASSEMBLY__ */ | 438 | #endif /* !__ASSEMBLY__ */ |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bf1dd8819097..1958358e29b0 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -1653,7 +1653,7 @@ void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone, | |||
| 1653 | struct page *page; | 1653 | struct page *page; |
| 1654 | 1654 | ||
| 1655 | for (page = start; page < (start + size); page++) { | 1655 | for (page = start; page < (start + size); page++) { |
| 1656 | set_page_zone(page, NODEZONE(nid, zone)); | 1656 | set_page_links(page, zone, nid); |
| 1657 | set_page_count(page, 0); | 1657 | set_page_count(page, 0); |
| 1658 | reset_page_mapcount(page); | 1658 | reset_page_mapcount(page); |
| 1659 | SetPageReserved(page); | 1659 | SetPageReserved(page); |
