aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/task_mmu.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index ef6f6c62dfee..39d641292579 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -807,6 +807,7 @@ typedef struct {
807struct pagemapread { 807struct pagemapread {
808 int pos, len; 808 int pos, len;
809 pagemap_entry_t *buffer; 809 pagemap_entry_t *buffer;
810 bool v2;
810}; 811};
811 812
812#define PAGEMAP_WALK_SIZE (PMD_SIZE) 813#define PAGEMAP_WALK_SIZE (PMD_SIZE)
@@ -820,14 +821,16 @@ struct pagemapread {
820#define PM_PSHIFT_BITS 6 821#define PM_PSHIFT_BITS 6
821#define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS) 822#define PM_PSHIFT_OFFSET (PM_STATUS_OFFSET - PM_PSHIFT_BITS)
822#define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET) 823#define PM_PSHIFT_MASK (((1LL << PM_PSHIFT_BITS) - 1) << PM_PSHIFT_OFFSET)
823#define PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK) 824#define __PM_PSHIFT(x) (((u64) (x) << PM_PSHIFT_OFFSET) & PM_PSHIFT_MASK)
824#define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1) 825#define PM_PFRAME_MASK ((1LL << PM_PSHIFT_OFFSET) - 1)
825#define PM_PFRAME(x) ((x) & PM_PFRAME_MASK) 826#define PM_PFRAME(x) ((x) & PM_PFRAME_MASK)
827/* in "new" pagemap pshift bits are occupied with more status bits */
828#define PM_STATUS2(v2, x) (__PM_PSHIFT(v2 ? x : PAGE_SHIFT))
826 829
827#define PM_PRESENT PM_STATUS(4LL) 830#define PM_PRESENT PM_STATUS(4LL)
828#define PM_SWAP PM_STATUS(2LL) 831#define PM_SWAP PM_STATUS(2LL)
829#define PM_FILE PM_STATUS(1LL) 832#define PM_FILE PM_STATUS(1LL)
830#define PM_NOT_PRESENT PM_PSHIFT(PAGE_SHIFT) 833#define PM_NOT_PRESENT(v2) PM_STATUS2(v2, 0)
831#define PM_END_OF_BUFFER 1 834#define PM_END_OF_BUFFER 1
832 835
833static inline pagemap_entry_t make_pme(u64 val) 836static inline pagemap_entry_t make_pme(u64 val)
@@ -850,7 +853,7 @@ static int pagemap_pte_hole(unsigned long start, unsigned long end,
850 struct pagemapread *pm = walk->private; 853 struct pagemapread *pm = walk->private;
851 unsigned long addr; 854 unsigned long addr;
852 int err = 0; 855 int err = 0;
853 pagemap_entry_t pme = make_pme(PM_NOT_PRESENT); 856 pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
854 857
855 for (addr = start; addr < end; addr += PAGE_SIZE) { 858 for (addr = start; addr < end; addr += PAGE_SIZE) {
856 err = add_to_pagemap(addr, &pme, pm); 859 err = add_to_pagemap(addr, &pme, pm);
@@ -860,7 +863,7 @@ static int pagemap_pte_hole(unsigned long start, unsigned long end,
860 return err; 863 return err;
861} 864}
862 865
863static void pte_to_pagemap_entry(pagemap_entry_t *pme, 866static void pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
864 struct vm_area_struct *vma, unsigned long addr, pte_t pte) 867 struct vm_area_struct *vma, unsigned long addr, pte_t pte)
865{ 868{
866 u64 frame, flags; 869 u64 frame, flags;
@@ -879,18 +882,18 @@ static void pte_to_pagemap_entry(pagemap_entry_t *pme,
879 if (is_migration_entry(entry)) 882 if (is_migration_entry(entry))
880 page = migration_entry_to_page(entry); 883 page = migration_entry_to_page(entry);
881 } else { 884 } else {
882 *pme = make_pme(PM_NOT_PRESENT); 885 *pme = make_pme(PM_NOT_PRESENT(pm->v2));
883 return; 886 return;
884 } 887 }
885 888
886 if (page && !PageAnon(page)) 889 if (page && !PageAnon(page))
887 flags |= PM_FILE; 890 flags |= PM_FILE;
888 891
889 *pme = make_pme(PM_PFRAME(frame) | PM_PSHIFT(PAGE_SHIFT) | flags); 892 *pme = make_pme(PM_PFRAME(frame) | PM_STATUS2(pm->v2, 0) | flags);
890} 893}
891 894
892#ifdef CONFIG_TRANSPARENT_HUGEPAGE 895#ifdef CONFIG_TRANSPARENT_HUGEPAGE
893static void thp_pmd_to_pagemap_entry(pagemap_entry_t *pme, 896static void thp_pmd_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
894 pmd_t pmd, int offset) 897 pmd_t pmd, int offset)
895{ 898{
896 /* 899 /*
@@ -900,12 +903,12 @@ static void thp_pmd_to_pagemap_entry(pagemap_entry_t *pme,
900 */ 903 */
901 if (pmd_present(pmd)) 904 if (pmd_present(pmd))
902 *pme = make_pme(PM_PFRAME(pmd_pfn(pmd) + offset) 905 *pme = make_pme(PM_PFRAME(pmd_pfn(pmd) + offset)
903 | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT); 906 | PM_STATUS2(pm->v2, 0) | PM_PRESENT);
904 else 907 else
905 *pme = make_pme(PM_NOT_PRESENT); 908 *pme = make_pme(PM_NOT_PRESENT(pm->v2));
906} 909}
907#else 910#else
908static inline void thp_pmd_to_pagemap_entry(pagemap_entry_t *pme, 911static inline void thp_pmd_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
909 pmd_t pmd, int offset) 912 pmd_t pmd, int offset)
910{ 913{
911} 914}
@@ -918,7 +921,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
918 struct pagemapread *pm = walk->private; 921 struct pagemapread *pm = walk->private;
919 pte_t *pte; 922 pte_t *pte;
920 int err = 0; 923 int err = 0;
921 pagemap_entry_t pme = make_pme(PM_NOT_PRESENT); 924 pagemap_entry_t pme = make_pme(PM_NOT_PRESENT(pm->v2));
922 925
923 /* find the first VMA at or above 'addr' */ 926 /* find the first VMA at or above 'addr' */
924 vma = find_vma(walk->mm, addr); 927 vma = find_vma(walk->mm, addr);
@@ -928,7 +931,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
928 931
929 offset = (addr & ~PAGEMAP_WALK_MASK) >> 932 offset = (addr & ~PAGEMAP_WALK_MASK) >>
930 PAGE_SHIFT; 933 PAGE_SHIFT;
931 thp_pmd_to_pagemap_entry(&pme, *pmd, offset); 934 thp_pmd_to_pagemap_entry(&pme, pm, *pmd, offset);
932 err = add_to_pagemap(addr, &pme, pm); 935 err = add_to_pagemap(addr, &pme, pm);
933 if (err) 936 if (err)
934 break; 937 break;
@@ -945,7 +948,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
945 * and need a new, higher one */ 948 * and need a new, higher one */
946 if (vma && (addr >= vma->vm_end)) { 949 if (vma && (addr >= vma->vm_end)) {
947 vma = find_vma(walk->mm, addr); 950 vma = find_vma(walk->mm, addr);
948 pme = make_pme(PM_NOT_PRESENT); 951 pme = make_pme(PM_NOT_PRESENT(pm->v2));
949 } 952 }
950 953
951 /* check that 'vma' actually covers this address, 954 /* check that 'vma' actually covers this address,
@@ -953,7 +956,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
953 if (vma && (vma->vm_start <= addr) && 956 if (vma && (vma->vm_start <= addr) &&
954 !is_vm_hugetlb_page(vma)) { 957 !is_vm_hugetlb_page(vma)) {
955 pte = pte_offset_map(pmd, addr); 958 pte = pte_offset_map(pmd, addr);
956 pte_to_pagemap_entry(&pme, vma, addr, *pte); 959 pte_to_pagemap_entry(&pme, pm, vma, addr, *pte);
957 /* unmap before userspace copy */ 960 /* unmap before userspace copy */
958 pte_unmap(pte); 961 pte_unmap(pte);
959 } 962 }
@@ -968,14 +971,14 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
968} 971}
969 972
970#ifdef CONFIG_HUGETLB_PAGE 973#ifdef CONFIG_HUGETLB_PAGE
971static void huge_pte_to_pagemap_entry(pagemap_entry_t *pme, 974static void huge_pte_to_pagemap_entry(pagemap_entry_t *pme, struct pagemapread *pm,
972 pte_t pte, int offset) 975 pte_t pte, int offset)
973{ 976{
974 if (pte_present(pte)) 977 if (pte_present(pte))
975 *pme = make_pme(PM_PFRAME(pte_pfn(pte) + offset) 978 *pme = make_pme(PM_PFRAME(pte_pfn(pte) + offset)
976 | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT); 979 | PM_STATUS2(pm->v2, 0) | PM_PRESENT);
977 else 980 else
978 *pme = make_pme(PM_NOT_PRESENT); 981 *pme = make_pme(PM_NOT_PRESENT(pm->v2));
979} 982}
980 983
981/* This function walks within one hugetlb entry in the single call */ 984/* This function walks within one hugetlb entry in the single call */
@@ -989,7 +992,7 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask,
989 992
990 for (; addr != end; addr += PAGE_SIZE) { 993 for (; addr != end; addr += PAGE_SIZE) {
991 int offset = (addr & ~hmask) >> PAGE_SHIFT; 994 int offset = (addr & ~hmask) >> PAGE_SHIFT;
992 huge_pte_to_pagemap_entry(&pme, *pte, offset); 995 huge_pte_to_pagemap_entry(&pme, pm, *pte, offset);
993 err = add_to_pagemap(addr, &pme, pm); 996 err = add_to_pagemap(addr, &pme, pm);
994 if (err) 997 if (err)
995 return err; 998 return err;
@@ -1051,6 +1054,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
1051 if (!count) 1054 if (!count)
1052 goto out_task; 1055 goto out_task;
1053 1056
1057 pm.v2 = false;
1054 pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); 1058 pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
1055 pm.buffer = kmalloc(pm.len, GFP_TEMPORARY); 1059 pm.buffer = kmalloc(pm.len, GFP_TEMPORARY);
1056 ret = -ENOMEM; 1060 ret = -ENOMEM;