From 02f04752e8fb83a7592dd16026f47336af36ecfb Mon Sep 17 00:00:00 2001
From: 4lDO2 <4lDO2@protonmail.com>
Date: Mon, 10 Jul 2023 11:39:29 +0200
Subject: [PATCH] Use proper locks for PageInfo.
---
src/context/memory.rs | 33 +++++++++++++++++++++------------
src/memory/mod.rs | 10 ++++------
2 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/src/context/memory.rs b/src/context/memory.rs
index 53e99e2cf1..09e0f4027b 100644
--- a/src/context/memory.rs
+++ b/src/context/memory.rs
@@ -780,7 +780,8 @@ impl Grant {
};
if let Some(page_info) = get_page_info(frame) {
- page_info.add_ref(false);
+ let guard = page_info.lock();
+ guard.add_ref(false);
}
unsafe {
@@ -909,7 +910,8 @@ impl Grant {
};
let src_page_info = get_page_info(src_frame).expect("allocated page was not present in the global page array");
- src_page_info.add_ref(is_cow);
+ let guard = src_page_info.lock();
+ guard.add_ref(is_cow);
let Some(map_result) = (unsafe { dst_mapper.map_phys(dst_page, src_frame.start_address(), flags.write(flags.has_write() && !is_cow)) }) else {
break;
@@ -990,7 +992,8 @@ impl Grant {
};
if let Some(info) = get_page_info(frame) {
- if info.remove_ref(is_cow) == 0 {
+ let guard = info.lock();
+ if guard.remove_ref(is_cow) == 0 {
deallocate_frames(frame, 1);
};
} else {
@@ -1330,8 +1333,9 @@ fn cow(dst_mapper: &mut PageMapper, page: Page, old_frame: Frame, info: &PageInf
fn init_frame(init_rc: usize, init_borrowed_rc: usize) -> Result {
let new_frame = crate::memory::allocate_frames(1).ok_or(PfError::Oom)?;
let page_info = get_page_info(new_frame).expect("all allocated frames need an associated page info");
- page_info.refcount.store(init_rc, Ordering::Relaxed);
- page_info.borrowed_refcount.store(init_borrowed_rc, Ordering::Relaxed);
+ let guard = page_info.lock();
+ guard.refcount.store(init_rc, Ordering::Relaxed);
+ guard.borrowed_refcount.store(init_borrowed_rc, Ordering::Relaxed);
Ok(new_frame)
}
@@ -1421,10 +1425,13 @@ fn correct_inner<'l>(addr_space_lock: &'l RwLock, mut addr_space_guar
Provider::Allocated { .. } | Provider::AllocatedShared if access == AccessMode::Write => {
match faulting_pageinfo_opt {
Some((_, None)) => unreachable!("allocated page needs frame to be valid"),
- Some((frame, Some(info))) => if info.owned_refcount() == 1 {
- frame
- } else {
- cow(&mut addr_space.table.utable, faulting_page, frame, info, grant_flags)?
+ Some((frame, Some(info_lock))) => {
+ let guard = info_lock.lock();
+ if guard.owned_refcount() == 1 {
+ frame
+ } else {
+ cow(&mut addr_space.table.utable, faulting_page, frame, &*guard, grant_flags)?
+ }
},
_ => map_zeroed(&mut addr_space.table.utable, faulting_page, grant_flags, true)?,
}
@@ -1433,11 +1440,12 @@ fn correct_inner<'l>(addr_space_lock: &'l RwLock, mut addr_space_guar
Provider::Allocated { .. } | Provider::AllocatedShared => {
match faulting_pageinfo_opt {
Some((_, None)) => unreachable!("allocated page needs frame to be valid"),
- Some((frame, Some(page_info))) => {
+ Some((frame, Some(page_info_lock))) => {
+ let guard = page_info_lock.lock();
// Keep in mind that alloc_writable must always be true if this code is reached
// for AllocatedShared, since shared pages cannot be mapped lazily (without
// using AddrSpace backrefs).
- allow_writable = page_info.owned_refcount() == 1;
+ allow_writable = guard.owned_refcount() == 1;
frame
}
@@ -1481,7 +1489,8 @@ fn correct_inner<'l>(addr_space_lock: &'l RwLock, mut addr_space_guar
frame
};
- let info = get_page_info(src_frame).expect("all allocated frames need a PageInfo");
+ let info_lock = get_page_info(src_frame).expect("all allocated frames need a PageInfo");
+ let info = info_lock.lock();
info.add_ref(false);
src_frame
diff --git a/src/memory/mod.rs b/src/memory/mod.rs
index cae5b662fc..9e0b887464 100644
--- a/src/memory/mod.rs
+++ b/src/memory/mod.rs
@@ -20,7 +20,7 @@ use rmm::{
FrameAllocator,
FrameCount,
};
-use spin::RwLock;
+use spin::{RwLock, Mutex};
use crate::syscall::flag::{PartialAllocStrategy, PhysallocFlags};
use crate::syscall::error::{ENOMEM, Error};
@@ -196,7 +196,6 @@ pub struct PageInfo {
pub borrowed_refcount: AtomicUsize,
// TODO: AtomicFlags?
pub flags: FrameFlags,
- pub _padding: usize,
}
bitflags::bitflags! {
@@ -213,7 +212,7 @@ pub static SECTIONS: RwLock> = RwLock::new(Vec::new());
pub struct Section {
base: Frame,
- frames: Box<[PageInfo]>,
+ frames: Box<[Mutex]>,
}
pub const MAX_SECTION_SIZE_BITS: u32 = 27;
@@ -235,7 +234,7 @@ pub fn init_mm() {
sections.push(Box::leak(Box::new(Section {
base,
// TODO: zeroed rather than PageInfo::new()?
- frames: try_box_slice_new(PageInfo::new, section_page_count).expect("failed to allocate pages array"),
+ frames: try_box_slice_new(|| Mutex::new(PageInfo::new()), section_page_count).expect("failed to allocate pages array"),
})) as &'static Section);
pages_left -= section_page_count;
@@ -254,7 +253,6 @@ impl PageInfo {
refcount: AtomicUsize::new(0),
borrowed_refcount: AtomicUsize::new(0),
flags: FrameFlags::NONE,
- _padding: 0,
}
}
pub fn add_ref(&self, cow: bool) {
@@ -278,7 +276,7 @@ impl PageInfo {
self.refcount.load(Ordering::SeqCst) - self.borrowed_refcount.load(Ordering::SeqCst)
}
}
-pub fn get_page_info(frame: Frame) -> Option<&'static PageInfo> {
+pub fn get_page_info(frame: Frame) -> Option<&'static Mutex> {
let sections = SECTIONS.read();
let idx = sections