Skip to content

Instantly share code, notes, and snippets.

@avagin
Created August 4, 2023 21:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save avagin/c5a22f3c78f8cb34281602dfe9c43d10 to your computer and use it in GitHub Desktop.
Save avagin/c5a22f3c78f8cb34281602dfe9c43d10 to your computer and use it in GitHub Desktop.
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
/* Pagemap ioctl */
#define PAGEMAP_SCAN _IOWR('f', 16, struct pm_scan_arg)
/* Bits are set in flags of the page_region and masks in pm_scan_args */
#define PAGE_IS_WRITTEN (1 << 0)
#define PAGE_IS_FILE (1 << 1)
#define PAGE_IS_PRESENT (1 << 2)
#define PAGE_IS_SWAPPED (1 << 3)
#define PAGE_IS_PFNZERO (1 << 4)
/*
* struct page_region - Page region with flags
* @start: Start of the region
* @len: Length of the region in pages
* @bitmap: Bits sets for the region
*/
struct page_region {
__u64 start;
__u64 len;
__u64 flags;
};
/*
* struct pm_scan_arg - Pagemap ioctl argument
* @size: Size of the structure
* @flags: Flags for the IOCTL
* @start: Starting address of the region
* (Ending address of the walk is also returned in it)
* @end: Ending address of the region
* @vec: Address of page_region struct array for output
* @vec_len: Length of the page_region struct array
* @max_pages: Optional max return pages
* @required_mask: Required mask - All of these bits have to be set in the PTE
* @anyof_mask: Any mask - Any of these bits are set in the PTE
* @excluded_mask: Exclude mask - None of these bits are set in the PTE
* @return_mask: Bits that are to be reported in page_region
*/
struct pm_scan_arg {
__u64 size;
__u64 flags;
__u64 start;
__u64 end;
__u64 vec;
__u64 vec_len;
__u64 max_pages;
__u64 required_mask;
__u64 anyof_mask;
__u64 excluded_mask;
__u64 return_mask;
};
/* Supported flags */
#define PM_SCAN_OP_GET (1 << 0)
#define PM_SCAN_OP_WP (1 << 1)
int main()
{
int fd = open("/proc/self/pagemap", O_RDONLY);
if (fd < 0)
return 1;
struct page_region regs[1024];
memset(regs, 0, sizeof(regs));
struct pm_scan_arg args = {};
args.size = sizeof(args);
args.start = 0;
args.end = 1UL<<50;
args.vec = (long)regs;
args.vec_len = 1024;
args.required_mask = PAGE_IS_PRESENT;
args.return_mask = PAGE_IS_PRESENT;
args.flags = PM_SCAN_OP_GET;
ioctl(fd, PAGEMAP_SCAN, &args);
return 0;
}
- 100.00% 0.00% a.out [kernel.vmlinux] [k] entry_SYSCALL_64_after_hwframe (inlined) ▒
entry_SYSCALL_64_after_hwframe (inlined) ▒
do_syscall_64 ▒
- do_syscall_x64 (inlined) ▒
- 100.00% __x64_sys_ioctl ▒
__se_sys_ioctl (inlined) ▒
__do_sys_ioctl (inlined) ◆
vfs_ioctl (inlined) ▒
- do_pagemap_cmd ▒
- 86.07% do_pagemap_scan ▒
- 58.50% walk_page_range ▒
+ 48.10% find_vma ▒
2.36% pagemap_scan_pte_hole ▒
1.12% mt_find ▒
+ 17.29% mmap_read_lock_killable (inlined) ▒
2.18% find_vma ▒
1.79% pagemap_scan_pte_hole ▒
+ 0.57% mmap_read_unlock (inlined) ▒
+ 10.99% up_read ▒
1.75% down_read_killable ▒
1.19% walk_page_range
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment