smaps: Report correct page sizes with THP
Subsystems (4)
PATCH v2 1/1 smaps: Report correct page sizes with THP
The earlier version of this patch kit wasn't that well received, with the main objection being non support for mTHP. This variant tracks any mTHP sizes in a VMA and reports them with MMUPageSizeN in smaps, with increasing N. The base page size is still reported w/o a number postfix to stay compatible.
The nice thing is that the patch is actually simpler and more straight forward than the THP only variant. Also improved the documentation.
Recently I wasted quite some time debugging why THP didn't work, when it was just smaps always reporting the base page size. It has separate counts for (non m) THP, but using them is not always obvious. I left KernelPageSize alone.
--- Documentation/filesystems/proc.rst | 8 ++++++-- fs/proc/task_mmu.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-)
Documentation/filesystems/proc.rst +6 -2
@@ -452,6 +452,7 @@ Memory Area, or VMA) there is a series of lines such as the following:: Size: 1084 kB KernelPageSize: 4 kB MMUPageSize: 4 kB + MMUPageSize2: 2048 kB Rss: 892 kB Pss: 374 kB Pss_Dirty: 0 kB
@@ -476,14 +477,17 @@ Memory Area, or VMA) there is a series of lines such as the following:: VmFlags: rd ex mr mw me dw The first of these lines shows the same information as is displayed for -the mapping in /proc/PID/maps. Following lines show the size of the +the mapping in /proc/PID/maps (except that there might be more page sizes +if the mapping has them) +Following lines show the size of the mapping (size); the size of each page allocated when backing a VMA (KernelPageSize), which is usually the same as the size in the page table entries; the page size used by the MMU when backing a VMA (in most cases, the same as KernelPageSize); the amount of the mapping that is currently resident in RAM (RSS); the process's proportional share of this mapping (PSS); and the number of clean and dirty shared and private pages in the -mapping. +mapping. If the mapping has multiple page size there might be a be multiple +numbered MMUPageSize entries. The "proportional set size" (PSS) of a process is the count of pages it has in memory, where each page is divided by the number of processes sharing it.
fs/proc/task_mmu.c +13 -1
@@ -874,6 +874,7 @@ struct mem_size_stats {unsigned long shared_hugetlb;unsigned long private_hugetlb;unsigned long ksm; +unsigned long compound_orders;u64 pss;u64 pss_anon;u64 pss_file;
@@ -942,6 +943,9 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,if (young ||folio_test_young (folio) ||folio_test_referenced (folio)) mss->referenced += size; + mss->compound_orders |= +BIT_ULL (compound ?folio_large_order (folio) :0 ); +/* * Then accumulate quantities that may depend on sharing, or that may * differ page-by-page.
@@ -1371,6 +1375,7 @@ static int show_smap(struct seq_file *m, void *v) {struct vm_area_struct *vma = v;struct mem_size_stats mss = {}; +int i, cnt =0 ;smap_gather_stats (vma, &mss,0 );
@@ -1378,7 +1383,14 @@ static int show_smap(struct seq_file *m, void *v)SEQ_PUT_DEC ("Size: " , vma->vm_end - vma->vm_start);SEQ_PUT_DEC (" kB\nKernelPageSize: " ,vma_kernel_pagesize (vma)); -SEQ_PUT_DEC (" kB\nMMUPageSize: " ,vma_mmu_pagesize (vma)); + +for_each_set_bit (i, &mss.compound_orders,BITS_PER_LONG ) { +if (cnt++ ==0 ) +SEQ_PUT_DEC (" kB\nMMUPageSize: " ,PAGE_SIZE << i); +else +seq_printf (m," kB\nMMUPageSize%d: %8u" , + cnt,1 << (PAGE_SHIFT -10 +i)); + }seq_puts (m," kB\n" );__show_smap (m, &mss, false);
Signature · 1 line
2.53.0
Quoted 84 lines · On Wed, 25 Feb 2026 15:27:08 -0800 Andi Kleen <[email protected]> wrote:
The earlier version of this patch kit wasn't that well received, with the main objection being non support for mTHP. This variant tracks any mTHP sizes in a VMA and reports them with MMUPageSizeN in smaps, with increasing N. The base page size is still reported w/o a number postfix to stay compatible.
The nice thing is that the patch is actually simpler and more straight forward than the THP only variant. Also improved the documentation.
Recently I wasted quite some time debugging why THP didn't work, when it was just smaps always reporting the base page size. It has separate counts for (non m) THP, but using them is not always obvious. I left KernelPageSize alone.
Signed-off-by Andi Kleen <[email protected]>--- Documentation/filesystems/proc.rst | 8 ++++++-- fs/proc/task_mmu.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-)Documentation/filesystems/proc.rst +6
-2@@ -452,6 +452,7 @@ Memory Area, or VMA) there is a series of lines such as the following:: Size: 1084 kB KernelPageSize: 4 kB MMUPageSize: 4 kB + MMUPageSize2: 2048 kB Rss: 892 kB Pss: 374 kB Pss_Dirty: 0 kB@@ -476,14 +477,17 @@ Memory Area, or VMA) there is a series of lines such as the following:: VmFlags: rd ex mr mw me dw The first of these lines shows the same information as is displayed for -the mapping in /proc/PID/maps. Following lines show the size of the +the mapping in /proc/PID/maps (except that there might be more page sizes +if the mapping has them) +Following lines show the size of the mapping (size); the size of each page allocated when backing a VMA (KernelPageSize), which is usually the same as the size in the page table entries; the page size used by the MMU when backing a VMA (in most cases, the same as KernelPageSize); the amount of the mapping that is currently resident in RAM (RSS); the process's proportional share of this mapping (PSS); and the number of clean and dirty shared and private pages in the -mapping. +mapping. If the mapping has multiple page size there might be a be multiple +numbered MMUPageSize entries. The "proportional set size" (PSS) of a process is the count of pages it has in memory, where each page is divided by the number of processes sharing it.fs/proc/task_mmu.c +5
-0@@ -874,6 +874,7 @@ struct mem_size_stats {unsigned long shared_hugetlb;unsigned long private_hugetlb;unsigned long ksm; +unsigned long compound_orders;u64 pss;u64 pss_anon;u64 pss_file;@@ -942,6 +943,9 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,if (young ||folio_test_young (folio) ||folio_test_referenced (folio)) mss->referenced += size; + mss->compound_orders |= +BIT_ULL (compound ?folio_large_order (folio) :0 ); +/* * Then accumulate quantities that may depend on sharing, or that may * differ page-by-page. @@ -1371,6 +1375,7 @@ static int show_smap(struct seq_file *m, void *v) {struct vm_area_struct *vma = v;struct mem_size_stats mss = {}; +int i, cnt =0 ;smap_gather_stats (vma, &mss,0 );
fs/proc/task_mmu.c static int show_smap(struct seq_file *m, void *v) · line 1387
Quoted 6 lines
fs/proc/task_mmu.c +2
-1@@ -1378,7 +1383,14 @@ static int show_smap(struct seq_file *m, void *v)SEQ_PUT_DEC ("Size: " , vma->vm_end - vma->vm_start);SEQ_PUT_DEC (" kB\nKernelPageSize: " ,vma_kernel_pagesize (vma)); -SEQ_PUT_DEC (" kB\nMMUPageSize: " ,vma_mmu_pagesize (vma)); + +for_each_set_bit (i, &mss.compound_orders,BITS_PER_LONG ) {
Hello Andi!
When a VMA has no resident pages (e.g., freshly mmap'd but not yet faulted), compound_orders will be zero and the for_each_set_bit loop will not execute at all. This means no MMUPageSize line is emitted for that VMA.
Previously, vma_mmu_pagesize() was called unconditionally and always produced the MMUPageSize field. Userspace tools that parse smaps and expect MMUPageSize to always be present would break on VMAs with no resident pages. Should we always add it?
Thanks
Quoted 14 lines
fs/proc/task_mmu.c +6
-0+if (cnt++ ==0 ) +SEQ_PUT_DEC (" kB\nMMUPageSize: " ,PAGE_SIZE << i); +else +seq_printf (m," kB\nMMUPageSize%d: %8u" , + cnt,1 << (PAGE_SHIFT -10 +i)); + }seq_puts (m," kB\n" );__show_smap (m, &mss, false);Signature · 1 line
2.53.0
Quoted 9 lines
When a VMA has no resident pages (e.g., freshly mmap'd but not yet faulted),
compound_orderswill be zero and thefor_each_set_bitloop will not execute at all. This means no MMUPageSize line is emitted for that VMA.Previously,
vma_mmu_pagesize()was called unconditionally and always produced the MMUPageSize field. Userspace tools that parse smaps and expect MMUPageSize to always be present would break on VMAs with no resident pages. Should we always add it?
Yes that's a good point. Should fall back to the base page size then. Will just make the simple logic a bit more complex again.
-Andi
Quoted 10 lines · Andi Kleen
The earlier version of this patch kit wasn't that well received, with the main objection being non support for mTHP. This variant tracks any mTHP sizes in a VMA and reports them with MMUPageSizeN in smaps, with increasing N. The base page size is still reported w/o a number postfix to stay compatible.
The nice thing is that the patch is actually simpler and more straight forward than the THP only variant. Also improved the documentation.
Quoted 7 lines
Recently I wasted quite some time debugging why THP didn't work, when it was just smaps always reporting the base page size. It has separate counts for (non m) THP, but using them is not always obvious. I left KernelPageSize alone.
Signed-off-by Andi Kleen <[email protected]>---
You should CC people that were commented on earlier versions.
I still don't like this.
a) Just because a folio has a certain order does not imply that hw actually coalesces anything. MMUPageSize is otherwise misleading.
b) Simply because you find a folio of a certain order does not imply that it is even fully mapped in there.
c) PTE coalescing on AMD can even span folios
But more importantly
d) MMUPageSize is independent of the actual page mappings, and I don't think we should change these semantics.
Let's see why MMUPageSize was added in the first place:
commit 3340289ddf29ca75c3acfb3a6b72f234b2f74d5c
Author: Mel Gorman <[email protected]> Date: Tue Jan 6 14:38:54 2009 -0800
mm: report the MMU pagesize in /proc/pid/smaps
The KernelPageSize entry in /proc/pid/smaps is the pagesize used by the kernel to back a VMA. This matches the size used by the MMU in the majority of cases. However, one counter-example occurs on PPC64 kernels whereby a kernel using 64K as a base pagesize may still use 4K pages for the MMU on older processor. To distinguish, this patch reports MMUPageSize as the pagesize used by the MMU in /proc/pid/smaps.
So instead of 64K (PAGE_SIZE), they reported 4K. Always. Even if nothing is mapped.
So you could indicate all MMUPageSize that hardware possibly supports in here. I don't think it's that helpful.
We once discussed exporting more stats here (similar to AnonHugePages/ShmemPmdMapped, ...) but we were concerned about creating a mess with mTHP stats.
For this reason, Ryan developed a tool (tools/mm/thpmaps) to introspect the actual mappings.
See
commit 2444172cfde45a3d6e655f50c620727c76bab4a2
Author: Ryan Roberts <[email protected]> Date: Tue Jan 16 14:12:35 2024 +0000
tools/mm: add thpmaps script to dump THP usage info
With the proliferation of large folios for file-backed memory, and more recently the introduction of multi-size THP for anonymous memory, it is becoming useful to be able to see exactly how large folios are mapped into processes. For some architectures (e.g. arm64), if most memory is mapped using contpte-sized and -aligned blocks, TLB usage can be optimized so it's useful to see where these requirements are and are not being met.
Signature · 3 lines
Cheers, David
Quoted 3 lines
a) Just because a folio has a certain order does not imply that hw actually coalesces anything. MMUPageSize is otherwise misleading.
That's true. However reporting 4K for a 2MB THP mapping today is even more misleading. That's where I started, it misled me totally!
So you're asking for an architecture specific / cpu specific hook to filter it? I suppose it could be added, however it might take a very long time to get merged, and even that cannot handle all corner cases.
Quoted 2 lines
b) Simply because you find a folio of a certain order does not imply that it is even fully mapped in there.
Ok. I suppose the walker could handle that.
Quoted 2 lines
c) PTE coalescing on AMD can even span folios
and d) it might randomly not happen due to various runtime reasons.
It seems the only thing that would satisfy all your correctness criteria would be to not report a MMUPageSize at all, but we cannot do that for compatibility reasons as you yourself pointed out.
Given that your requirements are impossible, we have to settle on something better. I still think that what I proposed is a good compromise, although yes it's far from perfect.
Quoted 5 lines
But more importantly
d) MMUPageSize is independent of the actual page mappings, and I don't think we should change these semantics.
That makes no sense. What is it good for then? Just a random number that looks good?
Quoted 18 lines
Let's see why MMUPageSize was added in the first place:
commit
3340289ddf29ca75c3acfb3a6b72f234b2f74d5cAuthor: Mel Gorman <[email protected]> Date: Tue Jan 6 14:38:54 2009 -0800mm: report the MMU pagesize in
/proc/pid/smapsThe KernelPageSize entry in
/proc/pid/smapsis the pagesize used by the kernel to back a VMA. This matches the size used by the MMU in the majority of cases. However, one counter-example occurs on PPC64 kernels whereby a kernel using 64K as a base pagesize may still use 4K pages for the MMU on older processor. To distinguish, this patch reports MMUPageSize as the pagesize used by the MMU in/proc/pid/smaps.
Quoted 1 line
So instead of 64K (
PAGE_SIZE), they reported 4K. Always. Even if nothing is mapped.
It doesn't seem like a good design. I don't know what that is good for.
What is reasonable to report something at least approximating what is really mapped.
Quoted 3 lines
So you could indicate all MMUPageSize that hardware possibly supports in here. I don't think it's that helpful.
Right.
Quoted 6 lines
We once discussed exporting more stats here (similar to AnonHugePages/ShmemPmdMapped, ...) but we were concerned about creating a mess with mTHP stats.
For this reason, Ryan developed a tool (
tools/mm/thpmaps) to introspect the actual mappings.
Some magic other tool doesn't help with the current output confusing people.
Yes I can always dump the page tables through debugfs (or at least I could if not most distributions don't bother to enable that config option for unknown reasons)
-Andi
Quoted 8 lines
Quoted 5 lines
But more importantly
d) MMUPageSize is independent of the actual page mappings, and I don't think we should change these semantics.
That makes no sense. What is it good for then? Just a random number that looks good?
Especially after reading 3340289ddf29ca75c3acfb3a6b72f234b2f74d5c I ended up with he following conclusion:
"KernelPageSize" tells you in which granularity we can mmap()/munmap() etc. Simple.
"MMUPageSize" tells us how this granularity is implemented (or emulated) under the hood.
The case we care about is when MMUPageSize < KernelPageSize. A process might have to know that detail even when nothing is currently/yet faulted in.
Assume a process would perform an atomic that would cross MMUPageSize, but not KernelPageSize. Depending on the architecture, atomics would not work as expected in that case.
I'd expect other cases where an architecture might have to care about the actual, smallest possible MMUPageSize it might be executed on while running the program.
It's a shame we had to add MMUPageSize, but maybe it might resurface if we ever support emulating 64K/16K user pagesizes on 4K MMUs.
Quoted 19 lines
Quoted 19 lines
Let's see why MMUPageSize was added in the first place:
commit
3340289ddf29ca75c3acfb3a6b72f234b2f74d5cAuthor: Mel Gorman <[email protected]> Date: Tue Jan 6 14:38:54 2009 -0800mm: report the MMU pagesize in
/proc/pid/smapsThe KernelPageSize entry in
/proc/pid/smapsis the pagesize used by the kernel to back a VMA. This matches the size used by the MMU in the majority of cases. However, one counter-example occurs on PPC64 kernels whereby a kernel using 64K as a base pagesize may still use 4K pages for the MMU on older processor. To distinguish, this patch reports MMUPageSize as the pagesize used by the MMU in/proc/pid/smaps.
Quoted 6 lines
Quoted 1 line
So instead of 64K (
PAGE_SIZE), they reported 4K. Always. Even if nothing is mapped.It doesn't seem like a good design. I don't know what that is good for.
What is reasonable to report something at least approximating what is really mapped.
I disagree. It is not of a lot of use to know "In this 1 TiB region, there is something mapped with 2 MiB", and then exposing it under the MMUPageSize umbrella with different (mapped) semantics.
AnonHugePages/ShmemPmdMapped/FilePmdMapped are better in that regard, although historically suboptimal.
Ideally we'd have better statistics out of the box (similar to what thpmaps does), but as we recently discussed in the context of "AnonZero" we should much rather look into a better interface to expose something like that (e.g., a new syscall where on can enable selected statistics), including new tooling that can obtain exactly the statistics we want.
Quoted 11 lines
Quoted 7 lines
We once discussed exporting more stats here (similar to AnonHugePages/ShmemPmdMapped, ...) but we were concerned about creating a mess with mTHP stats.
For this reason, Ryan developed a tool (
tools/mm/thpmaps) to introspect the actual mappings.Some magic other tool doesn't help with the current output confusing people.
Adding more confusion with this MMUPageSize extension is not an option. We should likely clarify what MMUPageSize really means.
So my NAK stands.
CCing Lorenzo:
https://lore.kernel.org/all/[email protected]/
Signature · 3 lines
Cheers, David
Quoted 9 lines
Especially after reading
3340289ddf29ca75c3acfb3a6b72f234b2f74d5cI ended up with he following conclusion:"KernelPageSize" tells you in which granularity we can mmap()/munmap() etc. Simple.
"MMUPageSize" tells us how this granularity is implemented (or emulated) under the hood.
Quoted 7 lines
The case we care about is when MMUPageSize < KernelPageSize. A process might have to know that detail even when nothing is currently/yet faulted in.
Assume a process would perform an atomic that would cross MMUPageSize, but not KernelPageSize. Depending on the architecture, atomics would not work as expected in that case.
I thought most architectures don't support atomics crossing pages anyways. x86 supports it, but it's discouraged.
Quoted 4 lines
I'd expect other cases where an architecture might have to care about the actual, smallest possible MMUPageSize it might be executed on while running the program.
That's fine, they can use the min, or just the first match (which is always the smallest)
Quoted 3 lines
It's a shame we had to add MMUPageSize, but maybe it might resurface if we ever support emulating 64K/16K user pagesizes on 4K MMUs.
Okay, so if I follow that correctly you're suggesting to change KernelPageSize, not MMUPageSize. I can do that change.
Quoted 2 lines
Adding more confusion with this MMUPageSize extension is not an option. We should likely clarify what MMUPageSize really means.
That would be an orthogonal documentation patch.
Thanks,
-Andi
Quoted 13 lines · Andi Kleen
Quoted 13 lines
Especially after reading
3340289ddf29ca75c3acfb3a6b72f234b2f74d5cI ended up with he following conclusion:"KernelPageSize" tells you in which granularity we can mmap()/munmap() etc. Simple.
"MMUPageSize" tells us how this granularity is implemented (or emulated) under the hood.
The case we care about is when MMUPageSize < KernelPageSize. A process might have to know that detail even when nothing is currently/yet faulted in.
Quoted 6 lines
Quoted 3 lines
Assume a process would perform an atomic that would cross MMUPageSize, but not KernelPageSize. Depending on the architecture, atomics would not work as expected in that case.
I thought most architectures don't support atomics crossing pages anyways. x86 supports it, but it's discouraged.
Right. And if your user space thinks it has "64k" pages, when it's actually emulated through "4k" pages under the hood, that could be a
problem: user space could perform an atomic "within" a 64k page that actually crosses two 4k pages. So it must be aware that mmap etc operate in 64k, but the underlying emulation might be smaller.
I suspect (but don't know for sure) that ppc exposed it for such a reason (maybe not atomic, but something else where user space might be able to detect the difference).
It's not that common nowadays, but I suspect it might get more common in the future again.
Quoted 10 lines
Quoted 5 lines
I'd expect other cases where an architecture might have to care about the actual, smallest possible MMUPageSize it might be executed on while running the program.
That's fine, they can use the min, or just the first match (which is always the smallest)
Quoted 1 line
Quoted 5 lines
Quoted 2 lines
It's a shame we had to add MMUPageSize, but maybe it might resurface if we ever support emulating 64K/16K user pagesizes on 4K MMUs.
Okay, so if I follow that correctly you're suggesting to change KernelPageSize, not MMUPageSize. I can do that change.
Not at all. I'm saying that we leave KernelPageSize and MMUPageSize alone, just as they are today.
Instead, if we want better statistics (and I think we want) regarding how things are mapped, we should look into a better interface.
Ideally, that will tell you "how much" of a certain contiguous size is mapped, if that contiguous size benefits somehow from TLB optimizations, etc.
Similar to tlbmaps but easier to consume (and obtain, IIRC thpmaps requires root permissions and has to jump through some racy hoops to detect folio sizes) and easier to configure and extend.
Signature · 3 lines
Cheers, David
Quoted 18 lines · David Hildenbrand (Arm)
Quoted 17 lines · Andi Kleen
Quoted 16 lines
Especially after reading
3340289ddf29ca75c3acfb3a6b72f234b2f74d5cI ended up with he following conclusion:"KernelPageSize" tells you in which granularity we can mmap()/munmap() etc. Simple.
"MMUPageSize" tells us how this granularity is implemented (or emulated) under the hood.
The case we care about is when MMUPageSize < KernelPageSize. A process might have to know that detail even when nothing is currently/yet faulted in.
Assume a process would perform an atomic that would cross MMUPageSize, but not KernelPageSize. Depending on the architecture, atomics would not work as expected in that case.
Quoted 6 lines
Quoted 2 lines
I thought most architectures don't support atomics crossing pages anyways. x86 supports it, but it's discouraged.
Right. And if your user space thinks it has "64k" pages, when it's actually emulated through "4k" pages under the hood, that could be a
problem: user space could perform an atomic "within" a 64k page that
PPC user space doesn't do it.
Quoted 2 lines
actually crosses two 4k pages. So it must be aware that mmap etc operate in 64k, but the underlying emulation might be smaller.
Sounds like a very contrived use case, which I'm not sure actually happens. From my past experiences most software usually doesn't use complicated enumerations anyways but just hard codes something reasonable (like in your example just always assume 4K worst case). From their POV it makes sense, how would you test
a complicated enumeration for cases that don't happen on your current system.
Quoted 8 lines
Quoted 8 lines
Quoted 3 lines
I'd expect other cases where an architecture might have to care about the actual, smallest possible MMUPageSize it might be executed on while running the program.
That's fine, they can use the min, or just the first match (which is always the smallest)
Quoted 1 line
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
It's a shame we had to add MMUPageSize, but maybe it might resurface if we ever support emulating 64K/16K user pagesizes on 4K MMUs.
Okay, so if I follow that correctly you're suggesting to change KernelPageSize, not MMUPageSize. I can do that change.
Not at all. I'm saying that we leave KernelPageSize and MMUPageSize alone, just as they are today.
That doesn't solve the problem that motivated my patch smaps is confusing today and would stay so.
Quoted 3 lines
Instead, if we want better statistics (and I think we want) regarding how things are mapped, we should look into a better interface.
I don't see how a new interface helps really. Some of the problems you mentioned earlier could be either solved today with smaps (e.g. handling the case when a folio is mapped partially and just report the smaller page size), or are unsolveable in the general case (what the TLB actually handles)
A new interface doesn't really change anything given that smaps is extensible.
I'll look at the partial folio case, but will only handle it if it's simple.
Quoted 3 lines
Ideally, that will tell you "how much" of a certain contiguous size is mapped, if that contiguous size benefits somehow from TLB optimizations, etc.
The key word is "somehow". It's better to work with real use cases instead of such hypothetics.
-Andi
Quoted 6 lines
Quoted 3 lines
Ideally, that will tell you "how much" of a certain contiguous size is mapped, if that contiguous size benefits somehow from TLB optimizations, etc.
The key word is "somehow". It's better to work with real use cases instead of such hypothetics.
I don't have time to discuss this further, unfortunately, so NAK from my side.
Signature · 3 lines
Cheers, David
Quoted 31 lines · Andi Kleen
Quoted 18 lines · David Hildenbrand (Arm)
Quoted 17 lines · Andi Kleen
Quoted 16 lines
Especially after reading
3340289ddf29ca75c3acfb3a6b72f234b2f74d5cI ended up with he following conclusion:"KernelPageSize" tells you in which granularity we can mmap()/munmap() etc. Simple.
"MMUPageSize" tells us how this granularity is implemented (or emulated) under the hood.
The case we care about is when MMUPageSize < KernelPageSize. A process might have to know that detail even when nothing is currently/yet faulted in.
Assume a process would perform an atomic that would cross MMUPageSize, but not KernelPageSize. Depending on the architecture, atomics would not work as expected in that case.
Quoted 6 lines
Quoted 2 lines
I thought most architectures don't support atomics crossing pages anyways. x86 supports it, but it's discouraged.
Right. And if your user space thinks it has "64k" pages, when it's actually emulated through "4k" pages under the hood, that could be a
problem: user space could perform an atomic "within" a 64k page thatPPC user space doesn't do it.
Quoted 2 lines
actually crosses two 4k pages. So it must be aware that mmap etc operate in 64k, but the underlying emulation might be smaller.
Quoted 7 lines
Sounds like a very contrived use case, which I'm not sure actually happens. From my past experiences most software usually doesn't use complicated enumerations anyways but just hard codes something reasonable (like in your example just always assume 4K worst case). From their POV it makes sense, how would you test
a complicated enumeration for cases that don't happen on your current system.
I'm sorry but it's a legacy user-facing stat, we don't get to change it or add a nearly-identically named entry that means something totally different (?!!)
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 4 lines
I'd expect other cases where an architecture might have to care about the actual, smallest possible MMUPageSize it might be executed on while running the program.
That's fine, they can use the min, or just the first match (which is always the smallest)
Quoted 3 lines
It's a shame we had to add MMUPageSize, but maybe it might resurface if we ever support emulating 64K/16K user pagesizes on 4K MMUs.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
Okay, so if I follow that correctly you're suggesting to change KernelPageSize, not MMUPageSize. I can do that change.
Not at all. I'm saying that we leave KernelPageSize and MMUPageSize alone, just as they are today.
That doesn't solve the problem that motivated my patch smaps is confusing today and would stay so.
Except as you've been told you can find this information out in different ways.
Quoted 6 lines
Quoted 4 lines
Instead, if we want better statistics (and I think we want) regarding how things are mapped, we should look into a better interface.
I don't see how a new interface helps really. Some of the problems
I mean, you want information X, we're suggesting the providing of an interface to provide information X and... you don't see how that helps?
Quoted 4 lines
you mentioned earlier could be either solved today with smaps (e.g. handling the case when a folio is mapped partially and just report the smaller page size), or are unsolveable in the general case (what the TLB actually handles)
We're not having multiple entries in smaps for every mapping size, it's broken and ungreppable, and very liable to add additional confusion to users.
A new interface gives us flexibility to do what we want, we aren't running out of syscalls or places to put statistics.
Smaps is necessarily a user-facing contract at this point so we have to tread carefully there.
Quoted 3 lines
A new interface doesn't really change anything given that smaps is extensible.
See above.
Quoted 3 lines
I'll look at the partial folio case, but will only handle it if it's simple.
Feel free to look at whatever you like, maintainers decide what gets merged.
Quoted 7 lines
Quoted 4 lines
Ideally, that will tell you "how much" of a certain contiguous size is mapped, if that contiguous size benefits somehow from TLB optimizations, etc.
The key word is "somehow". It's better to work with real use cases instead of such hypothetics.
Except your suggestion already demonstrates fundamental confusion about how folios are mapped in userspace?
We have to live with the legacy of MMUPageSize it means what it means. We're not adding variable-key entries to smaps full stop, because they're ungreppable and confusing.
so in _real world_ terms we are looking at a new interface, not overloading smaps.
Quoted 3 lines
-Andi
Thanks, Lorenzo
Quoted 11 lines · Lorenzo Stoakes
Quoted 10 lines
Quoted 2 lines
actually crosses two 4k pages. So it must be aware that mmap etc operate in 64k, but the underlying emulation might be smaller.
Sounds like a very contrived use case, which I'm not sure actually happens. From my past experiences most software usually doesn't use complicated enumerations anyways but just hard codes something reasonable (like in your example just always assume 4K worst case). From their POV it makes sense, how would you test
a complicated enumeration for cases that don't happen on your current system.
Quoted 1 line
I'm sorry but it's a legacy user-facing stat, we don't get to change it or add a
I would rather call it a legacy user-facing lie at this point.
Labelling something with 4K that is only 2MB is just wrong and incorrect.
Quoted 14 lines
Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
Quoted 3 lines
I'd expect other cases where an architecture might have to care about the actual, smallest possible MMUPageSize it might be executed on while running the program.
That's fine, they can use the min, or just the first match (which is always the smallest)
Quoted 3 lines
It's a shame we had to add MMUPageSize, but maybe it might resurface if we ever support emulating 64K/16K user pagesizes on 4K MMUs.
Okay, so if I follow that correctly you're suggesting to change KernelPageSize, not MMUPageSize. I can do that change.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
Not at all. I'm saying that we leave KernelPageSize and MMUPageSize alone, just as they are today.
That doesn't solve the problem that motivated my patch smaps is confusing today and would stay so.
Except as you've been told you can find this information out in different ways.
Yes I figured this out by myself, but only wasting a lot of time caused by the confusing and incorrect legacy interface. That's the problem I'm trying to address here.
Thank you for rubbing salt into the wounds.
The crazy thing about this is that hugetlbfs even does it correctly, it's only THP that is blatantly wrong.
Quoted 10 lines
Quoted 7 lines
Quoted 5 lines
Instead, if we want better statistics (and I think we want) regarding how things are mapped, we should look into a better interface.
I don't see how a new interface helps really. Some of the problems
I mean, you want information X, we're suggesting the providing of an interface to provide information X and... you don't see how that helps?
My goal was to fix the old interface to not blatantly report wrong information. A new magical interface doesn't really help with that.
Quoted 8 lines
Quoted 5 lines
you mentioned earlier could be either solved today with smaps (e.g. handling the case when a folio is mapped partially and just report the smaller page size), or are unsolveable in the general case (what the TLB actually handles)
We're not having multiple entries in smaps for every mapping size, it's broken and ungreppable, and very liable to add additional confusion to users.
Okay, I guess one way to address your objections with "ungreppable" would be to report the majority page size in MMUPageSize and call the minority page sizes something else that doesn't trigger on grep.
(MMUSecondaryPS or something like that)
If you don't like numbers I guess we can spell it out.
Quoted 2 lines
A new interface gives us flexibility to do what we want, we aren't running out of syscalls or places to put statistics.
I don't see why a new interface is needed TBH. Can just add fields and fix the existing fields not to lie. Yes need to take care of compatibility, I don't disagree on that. But just adding new interfaces for everything instead of maintaining the old stuff properly isn't the right answer.
-Andi
Andrew - to be clear - NAK this patch and anything like it from Andi. Thanks.
Quoted 1 line · Andi Kleen
I would rather call it a legacy user-facing lie at this point.
...
Quoted 1 line
Thank you for rubbing salt into the wounds.
...
Quoted 2 lines
My goal was to fix the old interface to not blatantly report wrong information. A new magical interface doesn't really help with that.
...
Quoted 1 line
If you don't like numbers I guess we can spell it out.
...
This is just rude and unnecessary, if you want to engage in technical debate, make technical points.
Anyway, I don't have the time or energy to engage with people who behave uncivilly. Your idea is broken, NAK (David and I have already explained why).
Thanks, Lorenzo
BTW your comment earlier about partially mapped compound pages made me reconsider the code and unless I'm missing something the accounting is all wrong for this case anyways in the current code.
The code currently calls smaps_account for every PTE, which will happily account the complete compound page, but this will be repeated for each PTE entry. So for the mTHP case when multiple contiguous PTEs point to the same page it will over count by the order.
This doesn't affect page size reporting, which is idempotent, but all the other mss counts in proc task_mmu.c.
-Andi
Quoted 7 lines · Andi Kleen
BTW your comment earlier about partially mapped compound pages made me reconsider the code and unless I'm missing something the accounting is all wrong for this case anyways in the current code.
The code currently calls
smaps_accountfor every PTE, which will happily account the complete compound page
I suggest you re-read the code and realize how the misleading "compound" parameter is used.
Signature · 3 lines
Cheers, David
Quoted 1 line · Andi Kleen
The earlier version of this patch kit wasn't that well received,
Nor this one... NAK!
Quoted 25 lines
with the main objection being non support for mTHP. This variant tracks any mTHP sizes in a VMA and reports them with MMUPageSizeN in smaps, with increasing N. The base page size is still reported w/o a number postfix to stay compatible.
The nice thing is that the patch is actually simpler and more straight forward than the THP only variant. Also improved the documentation.
Recently I wasted quite some time debugging why THP didn't work, when it was just smaps always reporting the base page size. It has separate counts for (non m) THP, but using them is not always obvious. I left KernelPageSize alone.
Signed-off-by Andi Kleen <[email protected]>--- Documentation/filesystems/proc.rst | 8 ++++++-- fs/proc/task_mmu.c | 14 +++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-)Documentation/filesystems/proc.rst +0
-0
Documentation/filesystems/proc.rst Memory Area, or VMA) there is a series of lines such as the following:: · line 455
Quoted 4 lines
Documentation/filesystems/proc.rst +1
-0@@ -452,6 +452,7 @@ Memory Area, or VMA) there is a series of lines such as the following:: Size: 1084 kB KernelPageSize: 4 kB MMUPageSize: 4 kB + MMUPageSize2: 2048 kB
I hate this interface. You're:
a. breaking grepping and probably userland, anything that greps MMUPageSize b. making the keys a variable as well as the values (yuck)
c. Introducing a horrible Foo2 Foo3 etc. naming convention.
It's a NAK on that alone.
Quoted 10 lines
Documentation/filesystems/proc.rst +2
-1Rss: 892 kB Pss: 374 kB Pss_Dirty: 0 kB@@ -476,14 +477,17 @@ Memory Area, or VMA) there is a series of lines such as the following:: VmFlags: rd ex mr mw me dw The first of these lines shows the same information as is displayed for -the mapping in /proc/PID/maps. Following lines show the size of the +the mapping in /proc/PID/maps (except that there might be more page sizes +if the mapping has them)
Documentation/filesystems/proc.rst Memory Area, or VMA) there is a series of lines such as the following:: · line 490
Quoted 10 lines
Documentation/filesystems/proc.rst +3
-1+Following lines show the size of the mapping (size); the size of each page allocated when backing a VMA (KernelPageSize), which is usually the same as the size in the page table entries; the page size used by the MMU when backing a VMA (in most cases, the same as KernelPageSize); the amount of the mapping that is currently resident in RAM (RSS); the process's proportional share of this mapping (PSS); and the number of clean and dirty shared and private pages in the -mapping. +mapping. If the mapping has multiple page size there might be a be multiple +numbered MMUPageSize entries.
You're hugely confusing the existing MMUPageSize case as David pointed out, and again, we're simply not going to add some variable key value.
Also naming something Foo2, Foo3, etc. is additionally horrible, confusing, and ungreppable.
You can use /proc/$pid/pagemap to figure this stuff out if you really want at folio level.
And as David pointed out, folios can be split at the folio _and_ the page mapping level, so a folio order isn't indicative necessarily of what you think it is.
AnonHugePages is a better measure of that as it looks at actual PMD mappings.
I mean this patch is just a no.
We could do with a better interface, that'd be the better way to expose something more detailed.
Quoted 50 lines
Documentation/filesystems/proc.rst +0
-0The "proportional set size" (PSS) of a process is the count of pages it has in memory, where each page is divided by the number of processes sharing it.fs/proc/task_mmu.c +13
-2@@ -874,6 +874,7 @@ struct mem_size_stats {unsigned long shared_hugetlb;unsigned long private_hugetlb;unsigned long ksm; +unsigned long compound_orders;u64 pss;u64 pss_anon;u64 pss_file;@@ -942,6 +943,9 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,if (young ||folio_test_young (folio) ||folio_test_referenced (folio)) mss->referenced += size; + mss->compound_orders |= +BIT_ULL (compound ?folio_large_order (folio) :0 ); +/* * Then accumulate quantities that may depend on sharing, or that may * differ page-by-page. @@ -1371,6 +1375,7 @@ static int show_smap(struct seq_file *m, void *v) {struct vm_area_struct *vma = v;struct mem_size_stats mss = {}; +int i, cnt =0 ;smap_gather_stats (vma, &mss,0 );@@ -1378,7 +1383,14 @@ static int show_smap(struct seq_file *m, void *v)SEQ_PUT_DEC ("Size: " , vma->vm_end - vma->vm_start);SEQ_PUT_DEC (" kB\nKernelPageSize: " ,vma_kernel_pagesize (vma)); -SEQ_PUT_DEC (" kB\nMMUPageSize: " ,vma_mmu_pagesize (vma)); + +for_each_set_bit (i, &mss.compound_orders,BITS_PER_LONG ) { +if (cnt++ ==0 ) +SEQ_PUT_DEC (" kB\nMMUPageSize: " ,PAGE_SIZE << i); +else +seq_printf (m," kB\nMMUPageSize%d: %8u" , + cnt,1 << (PAGE_SHIFT -10 +i)); + }seq_puts (m," kB\n" );__show_smap (m, &mss, false); --
Quoted 3 lines
2.53.0
Thanks, Lorenzo