Hello Michał,
I was looking into that from the Wine point of view and did a bit
of testing, so will try to answer the question cited below.
Without Windows large pages I guess the only way to make this work
correctly is to disable THP with madvise(MADV_NOHUGEPAGE) on the memory
ranges allocated with MEM_WRITE_WATCH, as the memory changes should not
only be reported but also tracked with 4k page granularity as Windows
applications expect.
Currently we don't implement MEM_LARGE_PAGES flag support in Wine
(while of course might want to do that in the future). On Windows using
this flag requires special permissions and implies more than just using
huge pages under the hood but also, in particular, locking pages in
memory. I'd expect that support to be extended in Windows though in the
future in some way. WRT write watches, the range is watched with large
page granularity. GetWriteWatch lpdwGranularity output parameter returns
the value of "large page minimum" (returned by GetLargePageMinimum) and
the returned addresses correspond to those large pages. I suppose to
implement that on top of Linux huge pages we'd need a way to control
huge pages allocation at the first place, i. e., a way to enforce the
specified size for the huge pages for the memory ranged being mapped.
Without that I am afraid the only way to correctly implement that is to
still disable THP on the range and only adjust our API output so that
matches expected.
Not related to the question, but without any relation to Wine and
Windows API current way of dealing with THP in the API design looks a
bit not straightforward to me. In a sense that transparent huge pages
will appear not so transparent when it comes to dirty pages tracking. If
I understand correctly, the application which allocated a reasonably big
memory area and didn't use madvise(MADV_NOHUGEPAGE) might end up with a
whole range being a single page and getting dirtified as a whole, which
may likely void app's optimization based on changed memory tracking. Not
that I know an ideal way out of this, maybe it is a matter of having THP
disabled by default on watched ranges or clearly warning about this
caveat in documentation?
Regards,
Paul.
On 7/26/23 15:10, Michał Mirosław wrote:
3. BTW, One of the uses is the GetWriteWatch and I wonder how it
behaves on HugeTLB (MEM_LARGE_PAGES allocation)? Shouldn't it return a
list of huge pages and write *lpdwGranularity = HPAGE_SIZE?
Wine/Proton doesn't used hugetlb by default. Hugetlb isn't enabled by
default on Debian as well. For GetWriteWatch() we don't care about the
hugetlb at all. We have added hugetlb's implementation to complete the
feature and leave out something.
How is GetWriteWatch() working when passed a VirtualAlloc(...,
MEM_LARGE_PAGES|MEM_WRITE_WATCH...)-allocated range? Does it still
report 4K pages?
This is only a problem when using max_pages: a hugetlb range might
need counting and reporting huge pages and not 4K parts.
Best Regards
Michał Mirosław