All of lore.kernel.org
 help / color / mirror / Atom feed
From: Xu Yu <xuyu@linux.alibaba.com>
To: linux-mm@kvack.org
Cc: akpm@linux-foundation.org, zokeefe@google.com, song@kernel.org,
	shy828301@gmail.com
Subject: [PATCH 0/1] mm/khugepaged: map anonymous pte-mapped THPs by pmds
Date: Mon, 13 Nov 2023 17:05:57 +0800	[thread overview]
Message-ID: <cover.1699865107.git.xuyu@linux.alibaba.com> (raw)

I write a testcase[1] to demonstrate this scenario.

vanilla kernel (v6.6):
# ./test
[mmap rw    ] vaddr: 0x0x7f2000000000, pfn: 0x110000, is_thp: 1, is_thp_mapped: 1
[mprotect ro] vaddr: 0x0x7f2000000000, pfn: 0x110000, is_thp: 1, is_thp_mapped: 0
          ^^ __split_huge_pmd() is called in  change_protection()
[mprotect rw] vaddr: 0x0x7f2000000000, pfn: 0x110000, is_thp: 1, is_thp_mapped: 0
          ^^ vma_merge()
[khugepaged ] vaddr: 0x0x7f2000000000, pfn: 0x110000, is_thp: 1, is_thp_mapped: 0
[khugepaged ] vaddr: 0x0x7f2000000000, pfn: 0x110000, is_thp: 1, is_thp_mapped: 0
[khugepaged ] vaddr: 0x0x7f2000000000, pfn: 0x117a00, is_thp: 1, is_thp_mapped: 1
         ^^ hpage_collapse_scan_pmd         ^^^^^^^^ new hugepage is allocated
[khugepaged ] vaddr: 0x0x7f2000000000, pfn: 0x117a00, is_thp: 1, is_thp_mapped: 1

patched kernel:
# ./test
[mmap rw    ] vaddr: 0x0x7f2000000000, pfn: 0x128400, is_thp: 1, is_thp_mapped: 1
[mprotect ro] vaddr: 0x0x7f2000000000, pfn: 0x128400, is_thp: 1, is_thp_mapped: 0
[mprotect rw] vaddr: 0x0x7f2000000000, pfn: 0x128400, is_thp: 1, is_thp_mapped: 0
[khugepaged ] vaddr: 0x0x7f2000000000, pfn: 0x128400, is_thp: 1, is_thp_mapped: 0
[khugepaged ] vaddr: 0x0x7f2000000000, pfn: 0x128400, is_thp: 1, is_thp_mapped: 0
[khugepaged ] vaddr: 0x0x7f2000000000, pfn: 0x128400, is_thp: 1, is_thp_mapped: 1
         ^^ hpage_collapse_scan_pmd         ^^^^^^^^ old hugepage
[khugepaged ] vaddr: 0x0x7f2000000000, pfn: 0x128400, is_thp: 1, is_thp_mapped: 1

[1] testcase source code
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <ctype.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include<signal.h>

#define PAGE_SHIFT	12
#define SIZE_2M		(2<<20)
#define ADDRESS		0x7f2000000000

#define PAGEMAP_PRESENT		63
#define PAGEMAP_PFN_MASK	0x007FFFFFFFFFFFFFUL    /* bits 54:0 */

#define KPF_SIZE	8
#define KPF_THP		22

static bool is_thp(unsigned long pfn)
{
	int kpageflags_fd;
	unsigned long flag;
	int ret;

	kpageflags_fd = open("/proc/kpageflags", O_RDONLY);
	ret = pread(kpageflags_fd, &flag, KPF_SIZE, KPF_SIZE * pfn);
	close(kpageflags_fd);

	if (ret != KPF_SIZE)
		return false;

	return flag & (1 << KPF_THP);
}

static bool is_thp_mapped(void *addr)
{
	char path[64], line[128], pattern[64];
	int pid;
	FILE *fp;
	int anon_huge_pages = 0;

	snprintf(pattern, 64, "%lx", (unsigned long)addr);
	pid = getpid();
	snprintf(path, 64, "/proc/%u/smaps", pid);
	fp = fopen(path, "r");

	while (fgets(line, 64, fp) != NULL) {
		if (strstr(line, pattern))
			break;
	}

	while (fgets(line, 64, fp) != NULL) {
		if (1 == sscanf(line, "AnonHugePages:      %d kB", &anon_huge_pages))
			break;
	}
	fclose(fp);

	return anon_huge_pages != 0;
}

static unsigned long get_pfn(unsigned long vaddr)
{
	char path[64];
	int pid, pagemap_fd;
	off64_t offset;
	unsigned long pfn = 0;
	int ret;

	offset = (vaddr >> PAGE_SHIFT) * sizeof(unsigned long);
	pid = getpid();
	snprintf(path, 64, "/proc/%u/pagemap", pid);

	pagemap_fd = open(path, O_RDONLY);
	lseek64(pagemap_fd, offset, SEEK_SET);
	ret = read(pagemap_fd, &pfn, sizeof(pfn));
	close(pagemap_fd);

	if (ret < 0)
		return -1;

	if (!(pfn & (1UL << PAGEMAP_PRESENT)))
		return 0;

	return (pfn & PAGEMAP_PFN_MASK);
}

static void show_addr_info(void *addr, char *msg)
{
	unsigned long pfn;

	pfn = get_pfn((unsigned long)addr);
	printf("[%s] vaddr: 0x%p, pfn: 0x%lx, is_thp: %d, is_thp_mapped: %d\n",
	       msg, addr, pfn, is_thp(pfn), is_thp_mapped(addr));
}

int main(int argc, char *argv[])
{
	void *addr;

	addr = mmap((void *)ADDRESS, SIZE_2M, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, -1, 0);
	if (addr == MAP_FAILED) {
		perror("mmap");
		return 1;
	}
	show_addr_info(addr, "mmap rw    ");

	mprotect(addr, SIZE_2M / 2, PROT_READ);
	show_addr_info(addr, "mprotect ro");

	mprotect(addr, SIZE_2M / 2, PROT_READ | PROT_WRITE);
	show_addr_info(addr, "mprotect rw");

	while (1) {
		show_addr_info(addr, "khugepaged ");
		sleep(5);
	}

	return 0;
}

Xu Yu (1):
  mm/khugepaged: map anonymous pte-mapped THPs by pmds

 mm/khugepaged.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 180 insertions(+), 7 deletions(-)

-- 
2.37.1



             reply	other threads:[~2023-11-13  9:06 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-11-13  9:05 Xu Yu [this message]
2023-11-13  9:05 ` [PATCH 1/1] mm/khugepaged: map anonymous pte-mapped THPs by pmds Xu Yu
2023-11-13  9:26   ` David Hildenbrand
2023-11-13  9:33     ` Xu Yu
2023-11-13 10:10       ` David Hildenbrand
2023-12-07  3:09 ` [PATCH v2 0/2] attempt to " Xu Yu
2023-12-07  3:09   ` [PATCH v2 1/2] mm/khugepaged: " Xu Yu
2023-12-07  7:47     ` Xu Yu
2023-12-07 10:37     ` David Hildenbrand
2023-12-18  2:45       ` Xu Yu
2023-12-07  3:09   ` [PATCH v2 2/2] mm/khugepaged: add case for mapping " Xu Yu
2023-12-18  7:06 ` [PATCH v3 0/2] attempt to map " Xu Yu
2023-12-18  7:06   ` [PATCH v3 1/2] mm/khugepaged: map RO non-exclusive pte-mapped anon " Xu Yu
2023-12-18  7:06   ` [PATCH v3 2/2] mm/khugepaged: map exclusive anonymous pte-mapped " Xu Yu
2023-12-21 20:40   ` [PATCH v3 0/2] attempt to map " Zach O'Keefe
2023-12-21 20:54     ` David Hildenbrand

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=cover.1699865107.git.xuyu@linux.alibaba.com \
    --to=xuyu@linux.alibaba.com \
    --cc=akpm@linux-foundation.org \
    --cc=linux-mm@kvack.org \
    --cc=shy828301@gmail.com \
    --cc=song@kernel.org \
    --cc=zokeefe@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.