On Mon, Jun 28, 2021 at 5:24 AM Kirill A. Shutemov <kirill@xxxxxxxxxxxxx> wrote: > > On Sat, Jun 19, 2021 at 02:20:02AM -0700, Peter Collingbourne wrote: > > #include <stdio.h> > > #include <stdlib.h> > > #include <string.h> > > #include <sys/mman.h> > > #include <unistd.h> > > > > constexpr unsigned char pattern_byte = 0xaa; > > > > #define PAGE_SIZE 4096 > > > > _Alignas(PAGE_SIZE) static unsigned char pattern[PAGE_SIZE]; > > > > int main(int argc, char **argv) { > > if (argc < 3) > > return 1; > > bool use_refpage = argc > 3; > > size_t mmap_size = atoi(argv[1]); > > size_t touch_size = atoi(argv[2]); > > > > int refpage_fd; > > if (use_refpage) { > > memset(pattern, pattern_byte, PAGE_SIZE); > > refpage_fd = syscall(448, pattern, 0); > > } > > for (unsigned i = 0; i != 1000; ++i) { > > char *p; > > if (use_refpage) { > > p = (char *)mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, > > refpage_fd, 0); > > } else { > > p = (char *)mmap(0, mmap_size, PROT_READ | PROT_WRITE, > > MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > > memset(p, pattern_byte, mmap_size); > > } > > for (unsigned j = 0; j < touch_size; j += PAGE_SIZE) > > p[j] = 0; > > munmap(p, mmap_size); > > } > > } > > I don't like the inteface. It is tied to PAGE_SIZE and this doesn't seem > to be very future looking. How would it work with THPs? The idea with this interface is that the FD would be passed to mmap, and anything that uses mmap already needs to be tied to the page size to some extent. For THPs I would expect that the kernel would duplicate the contents of the page as needed. Another reason that I thought to use a page size based interface was to allow future optimizations that may reuse the actual page passed to the syscall. So for example if libc.so contained a page filled with the required pattern and the allocator passed a pointer to that page then it could be shared between all of the processes on the system that link against that libc. But I suppose that such optimizations would not require passing in a whole page like that. For pattern based optimizations we could use a reference counted hash table or something, and for larger patterns we could activate the optimization only if the size argument were equal to the page size. > Maybe we should cosider passing down a filling pattern to kernel and let > kernel allocate appropriate page size on read page fault? The pattern has > to be power of 2 and limited in lenght. Okay, so this sounds like my idea for handling THPs except applied to any size. This seems reasonable enough to me, however in order to optimize use cases where the page is only ever read, let's have the kernel prepare the reference page instead of recreating it every time. In v5 I've adopted Matthew's proposed prototype: int refpage_create(const void *__user content, unsigned int size, unsigned long pattern, unsigned long flags); Peter