Change pagemap output format to allow for future reporting of huge pages

Change pagemap output format to allow for future reporting of huge pages.

(Format comment and minor cleanups: mpm@selenic.com)

Signed-off-by: Hans Rosenfeld <hans.rosenfeld@amd.com>
Signed-off-by: Matt Mackall <mpm@selenic.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Hans Rosenfeld and committed by Linus Torvalds f16278c6 51ec92e2

+34 -16
+34 -16
fs/proc/task_mmu.c
··· 527 char __user *out, *end; 528 }; 529 530 - #define PM_ENTRY_BYTES sizeof(u64) 531 - #define PM_RESERVED_BITS 3 532 - #define PM_RESERVED_OFFSET (64 - PM_RESERVED_BITS) 533 - #define PM_RESERVED_MASK (((1LL<<PM_RESERVED_BITS)-1) << PM_RESERVED_OFFSET) 534 - #define PM_SPECIAL(nr) (((nr) << PM_RESERVED_OFFSET) & PM_RESERVED_MASK) 535 - #define PM_NOT_PRESENT PM_SPECIAL(1LL) 536 - #define PM_SWAP PM_SPECIAL(2LL) 537 #define PM_END_OF_BUFFER 1 538 539 static int add_to_pagemap(unsigned long addr, u64 pfn, ··· 582 u64 swap_pte_to_pagemap_entry(pte_t pte) 583 { 584 swp_entry_t e = pte_to_swp_entry(pte); 585 - return PM_SWAP | swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT); 586 } 587 588 static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, ··· 596 u64 pfn = PM_NOT_PRESENT; 597 pte = pte_offset_map(pmd, addr); 598 if (is_swap_pte(*pte)) 599 - pfn = swap_pte_to_pagemap_entry(*pte); 600 else if (pte_present(*pte)) 601 - pfn = pte_pfn(*pte); 602 /* unmap so we're not in atomic when we copy to userspace */ 603 pte_unmap(pte); 604 err = add_to_pagemap(addr, pfn, pm); ··· 621 /* 622 * /proc/pid/pagemap - an array mapping virtual pages to pfns 623 * 624 - * For each page in the address space, this file contains one 64-bit 625 - * entry representing the corresponding physical page frame number 626 - * (PFN) if the page is present. If there is a swap entry for the 627 - * physical page, then an encoding of the swap file number and the 628 - * page's offset into the swap file are returned. If no page is 629 - * present at all, PM_NOT_PRESENT is returned. This allows determining 630 * precisely which pages are mapped (or in swap) and comparing mapped 631 * pages between processes. 632 *
··· 527 char __user *out, *end; 528 }; 529 530 + #define PM_ENTRY_BYTES sizeof(u64) 531 + #define PM_STATUS_BITS 3 532 + #define PM_STATUS_OFFSET (64 - PM_STATUS_BITS) 533 + #define PM_STATUS_MASK (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET) 534 + #define PM_STATUS(nr) (((nr) << PM_STATUS_OFFSET) & PM_STATUS_MASK) 535 + #define PM_PSHIFT_BITS 6 536 + #define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS) 537 + #define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET) 538 + #define PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK) 539 + #define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1) 540 + #define PM_PFRAME(x) ((x) & PM_PFRAME_MASK) 541 + 542 + #define PM_PRESENT PM_STATUS(4LL) 543 + #define PM_SWAP PM_STATUS(2LL) 544 + #define PM_NOT_PRESENT PM_PSHIFT(PAGE_SHIFT) 545 #define PM_END_OF_BUFFER 1 546 547 static int add_to_pagemap(unsigned long addr, u64 pfn, ··· 574 u64 swap_pte_to_pagemap_entry(pte_t pte) 575 { 576 swp_entry_t e = pte_to_swp_entry(pte); 577 + return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT); 578 } 579 580 static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, ··· 588 u64 pfn = PM_NOT_PRESENT; 589 pte = pte_offset_map(pmd, addr); 590 if (is_swap_pte(*pte)) 591 + pfn = PM_PFRAME(swap_pte_to_pagemap_entry(*pte)) 592 + | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP; 593 else if (pte_present(*pte)) 594 + pfn = PM_PFRAME(pte_pfn(*pte)) 595 + | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT; 596 /* unmap so we're not in atomic when we copy to userspace */ 597 pte_unmap(pte); 598 err = add_to_pagemap(addr, pfn, pm); ··· 611 /* 612 * /proc/pid/pagemap - an array mapping virtual pages to pfns 613 * 614 + * For each page in the address space, this file contains one 64-bit entry 615 + * consisting of the following: 616 + * 617 + * Bits 0-55 page frame number (PFN) if present 618 + * Bits 0-4 swap type if swapped 619 + * Bits 5-55 swap offset if swapped 620 + * Bits 55-60 page shift (page size = 1<<page shift) 621 + * Bit 61 reserved for future use 622 + * Bit 62 page swapped 623 + * Bit 63 page present 624 + * 625 + * If the page is not present but in swap, then the PFN contains an 626 + * encoding of the swap file number and the page's offset into the 627 + * swap. Unmapped pages return a null PFN. This allows determining 628 * precisely which pages are mapped (or in swap) and comparing mapped 629 * pages between processes. 630 *