mirror of
https://github.com/hexagonal-sun/moss-kernel.git
synced 2026-01-30 17:11:47 -05:00
implement mincore
This commit is contained in:
@@ -98,7 +98,7 @@
|
||||
| 0x5f (95) | waitid | (int which, pid_t upid, struct siginfo *infop, int options, struct rusage *ru) | __arm64_sys_waitid | false |
|
||||
| 0x60 (96) | set_tid_address | (int *tidptr) | __arm64_sys_set_tid_address | dummy |
|
||||
| 0x61 (97) | unshare | (unsigned long unshare_flags) | __arm64_sys_unshare | false |
|
||||
| 0x62 (98) | futex | (u32 *uaddr, int op, u32 val, const struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) | __arm64_sys_futex | false |
|
||||
| 0x62 (98) | futex | (u32 *uaddr, int op, u32 val, const struct __kernel_timespec *utime, u32 *uaddr2, u32 val3) | __arm64_sys_futex | true |
|
||||
| 0x63 (99) | set_robust_list | (struct robust_list_head *head, size_t len) | __arm64_sys_set_robust_list | true |
|
||||
| 0x64 (100) | get_robust_list | (int pid, struct robust_list_head **head_ptr, size_t *len_ptr) | __arm64_sys_get_robust_list | false |
|
||||
| 0x65 (101) | nanosleep | (struct __kernel_timespec *rqtp, struct __kernel_timespec *rmtp) | __arm64_sys_nanosleep | true |
|
||||
@@ -232,7 +232,7 @@
|
||||
| 0xe5 (229) | munlock | (unsigned long start, size_t len) | __arm64_sys_munlock | false |
|
||||
| 0xe6 (230) | mlockall | (int flags) | __arm64_sys_mlockall | false |
|
||||
| 0xe7 (231) | munlockall | () | __arm64_sys_munlockall | false |
|
||||
| 0xe8 (232) | mincore | (unsigned long start, size_t len, unsigned char *vec) | __arm64_sys_mincore | false |
|
||||
| 0xe8 (232) | mincore | (unsigned long start, size_t len, unsigned char *vec) | __arm64_sys_mincore | true |
|
||||
| 0xe9 (233) | madvise | (unsigned long start, size_t len_in, int behavior) | __arm64_sys_madvise | noop |
|
||||
| 0xea (234) | remap_file_pages | (unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags) | __arm64_sys_remap_file_pages | false |
|
||||
| 0xeb (235) | mbind | (unsigned long start, unsigned long len, unsigned long mode, const unsigned long *nmask, unsigned long maxnode, unsigned int flags) | __arm64_sys_mbind | false |
|
||||
|
||||
@@ -45,6 +45,7 @@ use crate::{
|
||||
kernel::{power::sys_reboot, rand::sys_getrandom, sysinfo::sys_sysinfo, uname::sys_uname},
|
||||
memory::{
|
||||
brk::sys_brk,
|
||||
mincore::sys_mincore,
|
||||
mmap::{sys_mmap, sys_mprotect, sys_munmap},
|
||||
process_vm::sys_process_vm_readv,
|
||||
},
|
||||
@@ -511,6 +512,7 @@ pub async fn handle_syscall() {
|
||||
0xde => sys_mmap(arg1, arg2, arg3, arg4, arg5.into(), arg6).await,
|
||||
0xdf => Ok(0), // fadvise64_64 is a no-op
|
||||
0xe2 => sys_mprotect(VA::from_value(arg1 as _), arg2 as _, arg3 as _),
|
||||
0xe8 => sys_mincore(arg1, arg2 as _, TUA::from_value(arg3 as _)).await,
|
||||
0xe9 => Ok(0), // sys_madvise is a no-op
|
||||
0x104 => {
|
||||
sys_wait4(
|
||||
|
||||
66
src/memory/mincore.rs
Normal file
66
src/memory/mincore.rs
Normal file
@@ -0,0 +1,66 @@
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::memory::uaccess::copy_to_user_slice;
|
||||
use crate::sched::current::current_task;
|
||||
use libkernel::memory::region::VirtMemoryRegion;
|
||||
use libkernel::{
|
||||
UserAddressSpace,
|
||||
error::{KernelError, Result},
|
||||
memory::PAGE_SHIFT,
|
||||
memory::address::{UA, VA},
|
||||
};
|
||||
|
||||
pub async fn sys_mincore(start: u64, len: usize, vec: UA) -> Result<usize> {
|
||||
// addr must be a multiple of the system page size
|
||||
// len must be > 0
|
||||
let start_va = VA::from_value(start as usize);
|
||||
if !start_va.is_page_aligned() {
|
||||
return Err(KernelError::InvalidValue);
|
||||
}
|
||||
|
||||
if len == 0 {
|
||||
return Err(KernelError::InvalidValue);
|
||||
}
|
||||
|
||||
let region = VirtMemoryRegion::new(start_va, len)
|
||||
.to_mappable_region()
|
||||
.region();
|
||||
if region.size() == 0 {
|
||||
return Err(KernelError::InvalidValue);
|
||||
}
|
||||
|
||||
// Vector length must be number of pages covering the region
|
||||
let pages = region.size() >> PAGE_SHIFT;
|
||||
let mut buf: Vec<u8> = vec![0; pages];
|
||||
|
||||
{
|
||||
let task = current_task();
|
||||
let mut vm_guard = task.vm.lock_save_irq();
|
||||
let mm = vm_guard.mm_mut();
|
||||
|
||||
// Validate the entire region is covered by VMAs
|
||||
for va in region.iter_pages() {
|
||||
if mm.find_vma(va).is_none() {
|
||||
return Err(KernelError::NoMemory);
|
||||
}
|
||||
}
|
||||
|
||||
let as_ref = mm.address_space_mut();
|
||||
|
||||
for (i, va) in region.iter_pages().enumerate() {
|
||||
let resident = as_ref.translate(va).is_some();
|
||||
if resident {
|
||||
buf[i] |= 1;
|
||||
} else {
|
||||
buf[i] &= !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
copy_to_user_slice(&buf, vec)
|
||||
.await
|
||||
.map_err(|_| KernelError::Fault)?;
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use libkernel::memory::{
|
||||
|
||||
pub mod brk;
|
||||
pub mod fault;
|
||||
pub mod mincore;
|
||||
pub mod mmap;
|
||||
pub mod page;
|
||||
pub mod process_vm;
|
||||
|
||||
@@ -151,6 +151,50 @@ fn test_thread_with_name() {
|
||||
|
||||
register_test!(test_thread_with_name, "Testing thread with name");
|
||||
|
||||
fn test_mincore() {
|
||||
use std::ptr;
|
||||
|
||||
unsafe {
|
||||
let page_size = libc::sysconf(libc::_SC_PAGESIZE) as usize;
|
||||
assert!(page_size > 0);
|
||||
|
||||
// Map exactly one page, read-write, anonymous private
|
||||
let addr = libc::mmap(
|
||||
ptr::null_mut(),
|
||||
page_size,
|
||||
libc::PROT_READ | libc::PROT_WRITE,
|
||||
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
|
||||
-1,
|
||||
0,
|
||||
);
|
||||
if addr == libc::MAP_FAILED {
|
||||
panic!("mmap failed: {}", std::io::Error::last_os_error());
|
||||
}
|
||||
|
||||
// Touch the page to fault it in
|
||||
ptr::write(addr as *mut u8, 42);
|
||||
|
||||
let mut vec_byte: u8 = 0;
|
||||
let ret = libc::mincore(addr as *mut _, page_size, &mut vec_byte as *mut u8);
|
||||
if ret != 0 {
|
||||
let err = std::io::Error::last_os_error();
|
||||
panic!("mincore failed: {}", err);
|
||||
}
|
||||
// LSB set indicates resident
|
||||
assert!(
|
||||
vec_byte & 0x1 == 0x1,
|
||||
"Expected page to be resident, vec={:02x}",
|
||||
vec_byte
|
||||
);
|
||||
|
||||
// Cleanup
|
||||
let rc = libc::munmap(addr, page_size);
|
||||
assert_eq!(rc, 0, "munmap failed: {}", std::io::Error::last_os_error());
|
||||
}
|
||||
}
|
||||
|
||||
register_test!(test_mincore, "Testing mincore syscall");
|
||||
|
||||
fn run_test(test_fn: fn()) {
|
||||
// Fork a new process to run the test
|
||||
unsafe {
|
||||
@@ -167,7 +211,7 @@ fn run_test(test_fn: fn()) {
|
||||
libc::waitpid(pid, &mut status, 0);
|
||||
if !libc::WIFEXITED(status) || libc::WEXITSTATUS(status) != 0 {
|
||||
panic!(
|
||||
"Test failed in child process: {}",
|
||||
"Test failed in child process: {} (this might be incorrect)",
|
||||
std::io::Error::last_os_error()
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user