Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

实现mremap系统调用 #518

Merged
merged 9 commits into from
Feb 19, 2024
39 changes: 39 additions & 0 deletions kernel/src/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,45 @@ pub mod ucontext;
/// 内核INIT进程的用户地址空间结构体(仅在process_init中初始化)
static mut __INITIAL_PROCESS_ADDRESS_SPACE: Option<Arc<AddressSpace>> = None;

bitflags! {
/// Virtual memory flags
pub struct VmFlags:u32{
const VM_NONE = 0x00000000;

const VM_READ = 0x00000001;
const VM_WRITE = 0x00000002;
const VM_EXEC = 0x00000004;
const VM_SHARED = 0x00000008;

const VM_MAYREAD = 0x00000010;
const VM_MAYWRITE = 0x00000020;
const VM_MAYEXEC = 0x00000040;
const VM_MAYSHARE = 0x00000080;

const VM_GROWSDOWN = 0x00000100;
const VM_UFFD_MISSING = 0x00000200;
const VM_PFNMAP = 0x00000400;
const VM_UFFD_WP = 0x00001000;

const VM_LOCKED = 0x00002000;
const VM_IO = 0x00004000;

const VM_SEQ_READ = 0x00008000;
const VM_RAND_READ = 0x00010000;

const VM_DONTCOPY = 0x00020000;
const VM_DONTEXPAND = 0x00040000;
const VM_LOCKONFAULT = 0x00080000;
const VM_ACCOUNT = 0x00100000;
const VM_NORESERVE = 0x00200000;
const VM_HUGETLB = 0x00400000;
const VM_SYNC = 0x00800000;
const VM_ARCH_1 = 0x01000000;
const VM_WIPEONFORK = 0x02000000;
const VM_DONTDUMP = 0x04000000;
}
}

/// 获取内核INIT进程的用户地址空间结构体
#[allow(non_snake_case)]
#[inline(always)]
Expand Down
176 changes: 175 additions & 1 deletion kernel/src/mm/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
use super::{
allocator::page_frame::{PageFrameCount, VirtPageFrame},
ucontext::{AddressSpace, DEFAULT_MMAP_MIN_ADDR},
verify_area, VirtAddr,
verify_area, VirtAddr, VmFlags,
};

bitflags! {
Expand Down Expand Up @@ -63,7 +63,93 @@ bitflags! {

/// For anonymous mmap, memory could be uninitialized
const MAP_UNINITIALIZED = 0x4000000;
}

/// Memory mremapping flags
pub struct MremapFlags: u8 {
const MREMAP_MAYMOVE = 1;
const MREMAP_FIXED = 2;
const MREMAP_DONTUNMAP = 4;
}
}

impl From<MapFlags> for VmFlags {
fn from(map_flags: MapFlags) -> Self {
let mut vm_flags = VmFlags::VM_NONE;

if map_flags.contains(MapFlags::MAP_GROWSDOWN) {
vm_flags |= VmFlags::VM_GROWSDOWN;
}

if map_flags.contains(MapFlags::MAP_LOCKED) {
vm_flags |= VmFlags::VM_LOCKED;
}

if map_flags.contains(MapFlags::MAP_SYNC) {
vm_flags |= VmFlags::VM_SYNC;
}

vm_flags
}
}

impl From<ProtFlags> for VmFlags {
fn from(prot_flags: ProtFlags) -> Self {
let mut vm_flags = VmFlags::VM_NONE;

if prot_flags.contains(ProtFlags::PROT_READ) {
vm_flags |= VmFlags::VM_READ;
}

if prot_flags.contains(ProtFlags::PROT_WRITE) {
vm_flags |= VmFlags::VM_WRITE;
}

if prot_flags.contains(ProtFlags::PROT_EXEC) {
vm_flags |= VmFlags::VM_EXEC;
}

vm_flags
}
}

impl Into<MapFlags> for VmFlags {
fn into(self) -> MapFlags {
let mut map_flags = MapFlags::MAP_NONE;

if self.contains(VmFlags::VM_GROWSDOWN) {
map_flags |= MapFlags::MAP_GROWSDOWN;
}

if self.contains(VmFlags::VM_LOCKED) {
map_flags |= MapFlags::MAP_LOCKED;
}

if self.contains(VmFlags::VM_SYNC) {
map_flags |= MapFlags::MAP_SYNC;
}

map_flags
}
}

impl Into<ProtFlags> for VmFlags {
fn into(self) -> ProtFlags {
let mut prot_flags = ProtFlags::PROT_NONE;

if self.contains(VmFlags::VM_READ) {
prot_flags |= ProtFlags::PROT_READ;
}

if self.contains(VmFlags::VM_WRITE) {
prot_flags |= ProtFlags::PROT_WRITE;
}

if self.contains(VmFlags::VM_EXEC) {
prot_flags |= ProtFlags::PROT_EXEC;
}

prot_flags
}
}

Expand Down Expand Up @@ -156,6 +242,93 @@ impl Syscall {
return Ok(start_page.virt_address().data());
}

/// ## mremap系统调用
///
///
/// ## 参数
///
/// - `old_vaddr`:原映射的起始地址
/// - `old_len`:原映射的长度
/// - `new_len`:重新映射的长度
/// - `mremap_flags`:重映射标志
/// - `new_vaddr`:重新映射的起始地址
///
/// ## 返回值
///
/// 成功时返回重映射的起始地址,失败时返回错误码
pub fn mremap(
old_vaddr: VirtAddr,
old_len: usize,
new_len: usize,
mremap_flags: MremapFlags,
new_vaddr: VirtAddr,
) -> Result<usize, SystemError> {
// 需要重映射到新内存区域的情况下,必须包含MREMAP_MAYMOVE并且指定新地址
if mremap_flags.contains(MremapFlags::MREMAP_FIXED)
&& (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE)
|| new_vaddr == VirtAddr::new(0))
{
return Err(SystemError::EINVAL);
}

// 不取消旧映射的情况下,必须包含MREMAP_MAYMOVE并且新内存大小等于旧内存大小
if mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP)
&& (!mremap_flags.contains(MremapFlags::MREMAP_MAYMOVE) || old_len != new_len)
{
return Err(SystemError::EINVAL);
}

// 旧内存地址必须对齐
if !old_vaddr.check_aligned(MMArch::PAGE_SIZE) {
return Err(SystemError::EINVAL);
}

// 将old_len、new_len 对齐页面大小
let old_len = page_align_up(old_len);
let new_len = page_align_up(new_len);

// 不允许重映射内存区域大小为0
if new_len == 0 {
return Err(SystemError::EINVAL);
}

let current_address_space = AddressSpace::current()?;
let vma = current_address_space.read().mappings.contains(old_vaddr);
if vma.is_none() {
return Err(SystemError::EINVAL);
}
let vma = vma.unwrap();
let vm_flags = vma.lock().vm_flags().clone();

// 暂时不支持巨页映射
if vm_flags.contains(VmFlags::VM_HUGETLB) {
kerror!("mmap: not support huge page mapping");
return Err(SystemError::ENOSYS);
}

// 缩小旧内存映射区域
if old_len > new_len {
Self::munmap(old_vaddr + new_len, old_len - new_len)?;
return Ok(old_vaddr.data());
}

// 重映射到新内存区域
let r = current_address_space.write().mremap(
old_vaddr,
old_len,
new_len,
mremap_flags,
new_vaddr,
vm_flags,
)?;

if !mremap_flags.contains(MremapFlags::MREMAP_DONTUNMAP) {
Self::munmap(old_vaddr, old_len)?;
}

return Ok(r.data());
}

/// ## munmap系统调用
///
/// ## 参数
Expand Down Expand Up @@ -185,6 +358,7 @@ impl Syscall {
.write()
.munmap(start_frame, page_count)
.map_err(|_| SystemError::EINVAL)?;

return Ok(0);
}

Expand Down