-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add mpagemap, a system call to fetch PTE data from a range of address space. It's more or less mincore-like, but doesn't take into account the page cache, it just dumps PTEs. This is useful for userspace testing, etc. Signed-off-by: Pedro Falcato <[email protected]>
- Loading branch information
Showing
7 changed files
with
180 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright (c) 2024 Pedro Falcato | ||
* This file is part of Onyx, and is released under the terms of the MIT License | ||
* check LICENSE at the root directory for more information | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
#ifndef _UAPI_MINCORE_H | ||
#define _UAPI_MINCORE_H | ||
|
||
#define PAGE_PRESENT (1 << 0) | ||
#define PAGE_GLOBAL (1 << 1) | ||
#define PAGE_WRITABLE (1 << 2) | ||
#define PAGE_EXECUTABLE (1 << 3) | ||
#define PAGE_DIRTY (1 << 4) | ||
#define PAGE_ACCESSED (1 << 5) | ||
#define PAGE_USER (1 << 6) | ||
#define PAGE_HUGE (1 << 7) | ||
|
||
/* Reserve the 12 bottom bits for flags, this lines up nicely with 4K pages */ | ||
|
||
#define MAPPING_INFO_PADDR(x) ((x) & -4096UL) | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* Copyright (c) 2024 Pedro Falcato | ||
* This file is part of Onyx, and is released under the terms of the MIT License | ||
* check LICENSE at the root directory for more information | ||
* | ||
* SPDX-License-Identifier: MIT | ||
*/ | ||
|
||
#include <onyx/process.h> | ||
#include <onyx/vm.h> | ||
|
||
// TODO: Export this stuff in some header, and avoid sticking everything into vm.cpp | ||
vm_area_struct *vm_search(struct mm_address_space *mm, void *addr, size_t length) | ||
REQUIRES_SHARED(mm->vm_lock); | ||
|
||
static long do_pagemap(struct mm_address_space *as, unsigned long start, unsigned long end, | ||
u64 *pagemap) | ||
{ | ||
|
||
scoped_mutex g{as->vm_lock}; | ||
long pfns_processed = 0; | ||
struct vm_area_struct *vma = vm_search(as, (void *) start, 1); | ||
if (!vma) | ||
return -ENOMEM; | ||
|
||
while (vma) | ||
{ | ||
if (vma->vm_start > end) | ||
break; | ||
|
||
spin_lock(&as->page_table_lock); | ||
|
||
/* Note: This is bad and slow(er). Nonetheless, it does the job for now */ | ||
for (; start < end; start += PAGE_SIZE) | ||
pagemap[pfns_processed++] = __get_mapping_info((void *) start, as); | ||
|
||
spin_unlock(&as->page_table_lock); | ||
|
||
if (start == end) | ||
break; | ||
|
||
vma = containerof_null_safe(bst_next(&as->region_tree, &vma->vm_tree_node), | ||
struct vm_area_struct, vm_tree_node); | ||
} | ||
|
||
return pfns_processed; | ||
} | ||
|
||
int sys_mpagemap(void *addr, size_t length, u64 *pagemap) | ||
{ | ||
unsigned long start = (unsigned long) addr & -PAGE_SIZE; | ||
length += (unsigned long) addr & (PAGE_SIZE - 1); | ||
unsigned long end = ALIGN_TO(start + length, PAGE_SIZE); | ||
struct mm_address_space *as = get_current_address_space(); | ||
struct page *buffer; | ||
int ret = 0; | ||
|
||
if (start < as->start || end > as->end) | ||
return -EINVAL; | ||
|
||
buffer = alloc_page(GFP_KERNEL); | ||
if (!buffer) | ||
return -ENOMEM; | ||
|
||
while (start < end) | ||
{ | ||
/* Limit runs to PAGE_SIZE / sizeof(u64) */ | ||
u64 *kbuffer = (u64 *) PAGE_TO_VIRT(buffer); | ||
unsigned long this_run_end = cul::min(end, start + (PAGE_SIZE / sizeof(u64))); | ||
long processed = do_pagemap(as, start, this_run_end, kbuffer); | ||
|
||
if (processed == 0) | ||
break; | ||
|
||
if (processed < 0) | ||
{ | ||
ret = processed; | ||
break; | ||
} | ||
|
||
if (copy_to_user(pagemap, kbuffer, processed * sizeof(u64)) < 0) | ||
{ | ||
ret = -EFAULT; | ||
break; | ||
} | ||
|
||
pagemap += processed; | ||
start += processed << PAGE_SHIFT; | ||
} | ||
|
||
free_page(buffer); | ||
|
||
return ret; | ||
} |
Submodule musl
updated
3 files
+1 −0 | arch/aarch64/bits/syscall.h.in | |
+2 −1 | arch/riscv64/bits/syscall.h.in | |
+1 −0 | arch/x86_64/bits/syscall.h.in |