Skip to content

Commit 03170e2

Browse files
committed
Refactor frame management to arch indep. code.
1 parent e1416f7 commit 03170e2

5 files changed

Lines changed: 122 additions & 87 deletions

File tree

kernel/src/arch/unix/process.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ use crate::memory::vspace::{AddressSpace, TlbFlushHandle};
2626
use crate::memory::{Frame, VAddr, LARGE_PAGE_SIZE};
2727
use crate::nrproc::NrProcess;
2828
use crate::process::{
29-
Eid, Executor, Pid, Process, ResumeHandle, MAX_FRAMES_PER_PROCESS, MAX_PROCESSES,
29+
Eid, Executor, FrameManagement, Pid, Process, ResumeHandle, MAX_FRAMES_PER_PROCESS,
30+
MAX_PROCESSES,
3031
};
3132

3233
use super::debug;
@@ -259,20 +260,26 @@ impl Process for UnixProcess {
259260
fn pinfo(&self) -> &kpi::process::ProcessInfo {
260261
&self.pinfo
261262
}
263+
}
262264

263-
fn add_frame(&mut self, _frame: Frame) -> Result<FrameId, KError> {
265+
impl FrameManagement for UnixProcess {
266+
fn add_frame(&mut self, frame: Frame) -> Result<FrameId, KError> {
264267
Err(KError::InvalidFrameId)
265268
}
266269

267-
fn get_frame(&mut self, _frame_id: FrameId) -> Result<(Frame, Option<VAddr>), KError> {
270+
fn get_frame(&mut self, frame_id: FrameId) -> Result<(Frame, usize), KError> {
268271
Err(KError::InvalidFrameId)
269272
}
270273

271274
fn add_frame_mapping(&mut self, frame_id: FrameId, vaddr: VAddr) -> Result<(), KError> {
272275
Err(KError::InvalidFrameId)
273276
}
274277

275-
fn deallocate_frame(&mut self, _fid: FrameId) -> Result<(Frame, Option<VAddr>), KError> {
278+
fn remove_frame_mapping(&mut self, frame_id: FrameId, _vaddr: VAddr) -> Result<(), KError> {
279+
Err(KError::InvalidFrameId)
280+
}
281+
282+
fn deallocate_frame(&mut self, fid: FrameId) -> Result<Frame, KError> {
276283
Err(KError::InvalidFrameId)
277284
}
278285
}

kernel/src/arch/x86_64/process.rs

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::memory::vspace::{AddressSpace, MapAction};
3131
use crate::memory::{paddr_to_kernel_vaddr, Frame, KernelAllocator, MemType, PAddr, VAddr};
3232
use crate::nrproc::NrProcess;
3333
use crate::process::{
34-
Eid, Executor, Pid, Process, ResumeHandle, MAX_FRAMES_PER_PROCESS, MAX_PROCESSES,
34+
Eid, Executor, FrameManagement, Pid, Process, ProcessFrames, ResumeHandle, MAX_PROCESSES,
3535
MAX_WRITEABLE_SECTIONS_PER_PROCESS,
3636
};
3737
use crate::round_up;
@@ -859,7 +859,7 @@ pub(crate) struct Ring3Process {
859859
/// File descriptors for the opened file.
860860
pub fds: ArrayVec<Option<FileDescriptorEntry>, MAX_FILES_PER_PROCESS>,
861861
/// Physical frame objects registered to the process.
862-
pub frames: ArrayVec<(Option<Frame>, Option<VAddr>), MAX_FRAMES_PER_PROCESS>,
862+
pub pfm: ProcessFrames,
863863
/// Frames of the writeable ELF data section (shared across all replicated Process structs)
864864
pub writeable_sections: ArrayVec<Frame, MAX_WRITEABLE_SECTIONS_PER_PROCESS>,
865865
/// Section in ELF where last read-only header is
@@ -879,8 +879,7 @@ impl Ring3Process {
879879
let fds: ArrayVec<Option<FileDescriptorEntry>, MAX_FILES_PER_PROCESS> =
880880
ArrayVec::from([NONE_FD; MAX_FILES_PER_PROCESS]);
881881

882-
let frames: ArrayVec<(Option<Frame>, Option<VAddr>), MAX_FRAMES_PER_PROCESS> =
883-
ArrayVec::from([(None, None); MAX_FRAMES_PER_PROCESS]);
882+
let pfm = ProcessFrames::default();
884883

885884
Ok(Ring3Process {
886885
pid: pid,
@@ -892,7 +891,7 @@ impl Ring3Process {
892891
executor_offset: VAddr::from(EXECUTOR_OFFSET),
893892
fds,
894893
pinfo: Default::default(),
895-
frames,
894+
pfm,
896895
writeable_sections: ArrayVec::new(),
897896
read_only_offset: VAddr::zero(),
898897
})
@@ -1333,51 +1332,27 @@ impl Process for Ring3Process {
13331332
fn pinfo(&self) -> &kpi::process::ProcessInfo {
13341333
&self.pinfo
13351334
}
1335+
}
13361336

1337+
impl FrameManagement for Ring3Process {
13371338
fn add_frame(&mut self, frame: Frame) -> Result<FrameId, KError> {
1338-
if let Some(fid) = self.frames.iter().position(|entry| entry.0.is_none()) {
1339-
self.frames[fid] = (Some(frame), None);
1340-
Ok(fid)
1341-
} else {
1342-
Err(KError::TooManyRegisteredFrames)
1343-
}
1339+
self.pfm.add_frame(frame)
13441340
}
13451341

1346-
fn get_frame(&mut self, frame_id: FrameId) -> Result<(Frame, Option<VAddr>), KError> {
1347-
let (frame, mapped_at) = self
1348-
.frames
1349-
.get(frame_id)
1350-
.cloned()
1351-
.ok_or(KError::InvalidFrameId)?;
1352-
1353-
if let Some(frame) = frame {
1354-
Ok((frame, mapped_at))
1355-
} else {
1356-
Err(KError::InvalidFrameId)
1357-
}
1342+
fn get_frame(&mut self, frame_id: FrameId) -> Result<(Frame, usize), KError> {
1343+
self.pfm.get_frame(frame_id)
13581344
}
13591345

1360-
fn add_frame_mapping(&mut self, frame_id: FrameId, base: VAddr) -> Result<(), KError> {
1361-
self.frames
1362-
.get_mut(frame_id)
1363-
.and_then(|(_, mapping)| {
1364-
*mapping = Some(base);
1365-
Some(())
1366-
})
1367-
.ok_or(KError::InvalidFrameId)
1346+
fn add_frame_mapping(&mut self, frame_id: FrameId, vaddr: VAddr) -> Result<(), KError> {
1347+
self.pfm.add_frame_mapping(frame_id, vaddr)
13681348
}
13691349

1370-
fn deallocate_frame(&mut self, fid: FrameId) -> Result<(Frame, Option<VAddr>), KError> {
1371-
match self.frames.get_mut(fid) {
1372-
Some(cur) => {
1373-
let mut temp = (None, None);
1374-
core::mem::swap(&mut temp, cur);
1350+
fn remove_frame_mapping(&mut self, frame_id: FrameId, _vaddr: VAddr) -> Result<(), KError> {
1351+
self.pfm.remove_frame_mapping(frame_id, _vaddr)
1352+
}
13751353

1376-
let va = temp.1;
1377-
Ok((temp.0.ok_or(KError::InvalidFrame)?, va))
1378-
}
1379-
_ => Err(KError::InvalidFrameId),
1380-
}
1354+
fn deallocate_frame(&mut self, fid: FrameId) -> Result<Frame, KError> {
1355+
self.pfm.deallocate_frame(fid)
13811356
}
13821357
}
13831358

kernel/src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ pub enum KError {
9999
BinaryNotFound { binary: &'static str },
100100
/// Supplied frame was invalid
101101
InvalidFrame,
102+
/// The frame could not be detached from the process -- still mapped in its VSpace.
103+
FrameStillMapped,
102104
/// Address space operation covers existing mapping {base:?}
103105
AlreadyMapped { base: VAddr },
104106
/// Provided virtual base {base:?} is invalid (led to overflow on mappings).

kernel/src/nrproc.rs

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ impl<P: Process> NrProcess<P> {
238238
debug_assert!(pid < MAX_PROCESSES, "Invalid PID");
239239

240240
let node = *crate::environment::NODE_ID;
241+
//action.multiple_mappings(true);
241242

242243
let response = PROCESS_TABLE[node][pid].execute_mut(
243244
ProcessOpMut::MemMapFrameId(base, frame_id, action),
@@ -548,19 +549,11 @@ where
548549
}
549550

550551
ProcessOpMut::MemMapFrameId(base, frame_id, action) => {
551-
let (frame, mapped_at) = self.process.get_frame(frame_id)?;
552-
if let Some(va) = mapped_at {
553-
if va != base {
554-
return Err(KError::AlreadyMapped { base: va });
555-
} else {
556-
return Ok(ProcessResult::MappedFrameId(frame.base, frame.size));
557-
}
558-
} else {
559-
crate::memory::KernelAllocator::try_refill_tcache(7, 0, MemType::Mem)?;
560-
self.process.vspace_mut().map_frame(base, frame, action)?;
561-
self.process.add_frame_mapping(frame_id, base)?;
562-
Ok(ProcessResult::MappedFrameId(frame.base, frame.size))
563-
}
552+
let (frame, _refcnt) = self.process.get_frame(frame_id)?;
553+
self.process.add_frame_mapping(frame_id, base)?;
554+
crate::memory::KernelAllocator::try_refill_tcache(7, 0, MemType::Mem)?;
555+
self.process.vspace_mut().map_frame(base, frame, action)?;
556+
Ok(ProcessResult::MappedFrameId(frame.base, frame.size))
564557
}
565558

566559
ProcessOpMut::MemUnmap(vaddr) => {
@@ -587,32 +580,8 @@ where
587580
}
588581

589582
ProcessOpMut::ReleaseFrameFromProcess(fid) => {
590-
let (frame, mapped_at) = self.process.get_frame(fid)?;
591-
if let Some(va) = mapped_at {
592-
//
593-
match self.process.vspace_mut().unmap(va) {
594-
Ok(mut shootdown_handle) => {
595-
for (gtid, _eid) in self.active_cores.iter() {
596-
shootdown_handle.add_core(*gtid);
597-
}
598-
self.process.deallocate_frame(fid).expect("Should not fail");
599-
return Ok(ProcessResult::Unmapped(shootdown_handle));
600-
}
601-
Err(KError::NotMapped) => {
602-
// Note: the `unmap` call might fail if the frame was
603-
// already unmapped this is fine as long as we do
604-
// `deallocate_frame` first (and removed the mapping in
605-
// `frames`)
606-
self.process.deallocate_frame(fid).expect("Should not fail");
607-
return Ok(ProcessResult::Ok);
608-
}
609-
Err(e) => return Err(e),
610-
}
611-
} else {
612-
// Wasn't mapped, no need to clear TLB
613-
self.process.deallocate_frame(fid).expect("Should not fail");
614-
Ok(ProcessResult::Frame(frame))
615-
}
583+
let frame = self.process.deallocate_frame(fid)?;
584+
Ok(ProcessResult::Frame(frame))
616585
}
617586
}
618587
}

kernel/src/process.rs

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub(crate) const MAX_FRAMES_PER_PROCESS: usize = MAX_CORES;
4747
pub(crate) const MAX_WRITEABLE_SECTIONS_PER_PROCESS: usize = 4;
4848

4949
/// Abstract definition of a process.
50-
pub(crate) trait Process {
50+
pub(crate) trait Process: FrameManagement {
5151
type E: Executor + Copy + Sync + Send + Debug + PartialEq;
5252
type A: AddressSpace;
5353

@@ -82,11 +82,93 @@ pub(crate) trait Process {
8282
fn get_fd(&self, index: usize) -> &FileDescriptorEntry;
8383

8484
fn pinfo(&self) -> &kpi::process::ProcessInfo;
85+
}
8586

87+
pub(crate) trait FrameManagement {
8688
fn add_frame(&mut self, frame: Frame) -> Result<FrameId, KError>;
87-
fn get_frame(&mut self, frame_id: FrameId) -> Result<(Frame, Option<VAddr>), KError>;
89+
fn get_frame(&mut self, frame_id: FrameId) -> Result<(Frame, usize), KError>;
8890
fn add_frame_mapping(&mut self, frame_id: FrameId, vaddr: VAddr) -> Result<(), KError>;
89-
fn deallocate_frame(&mut self, fid: FrameId) -> Result<(Frame, Option<VAddr>), KError>;
91+
fn remove_frame_mapping(&mut self, frame_id: FrameId, _vaddr: VAddr) -> Result<(), KError>;
92+
fn deallocate_frame(&mut self, fid: FrameId) -> Result<Frame, KError>;
93+
}
94+
95+
/// Implementation for managing a process' frames.
96+
pub(crate) struct ProcessFrames {
97+
/// Physical frame objects registered to the process.
98+
frames: ArrayVec<(Option<Frame>, usize), MAX_FRAMES_PER_PROCESS>,
99+
}
100+
101+
impl Default for ProcessFrames {
102+
fn default() -> Self {
103+
let frames: ArrayVec<(Option<Frame>, usize), MAX_FRAMES_PER_PROCESS> =
104+
ArrayVec::from([(None, 0); MAX_FRAMES_PER_PROCESS]);
105+
Self { frames }
106+
}
107+
}
108+
109+
impl FrameManagement for ProcessFrames {
110+
fn add_frame(&mut self, frame: Frame) -> Result<FrameId, KError> {
111+
if let Some(fid) = self.frames.iter().position(|entry| entry.0.is_none()) {
112+
self.frames[fid] = (Some(frame), 0);
113+
Ok(fid)
114+
} else {
115+
Err(KError::TooManyRegisteredFrames)
116+
}
117+
}
118+
119+
fn get_frame(&mut self, frame_id: FrameId) -> Result<(Frame, usize), KError> {
120+
let (frame, metadata) = self
121+
.frames
122+
.get(frame_id)
123+
.cloned()
124+
.ok_or(KError::InvalidFrameId)?;
125+
126+
if let Some(frame) = frame {
127+
Ok((frame, metadata))
128+
} else {
129+
Err(KError::InvalidFrameId)
130+
}
131+
}
132+
133+
fn add_frame_mapping(&mut self, frame_id: FrameId, _vaddr: VAddr) -> Result<(), KError> {
134+
self.frames
135+
.get_mut(frame_id)
136+
.and_then(|(frame, ref mut refcnt)| {
137+
if frame.is_some() {
138+
*refcnt += 1;
139+
Some(())
140+
} else {
141+
None
142+
}
143+
})
144+
.ok_or(KError::InvalidFrameId)
145+
}
146+
147+
fn remove_frame_mapping(&mut self, frame_id: FrameId, _vaddr: VAddr) -> Result<(), KError> {
148+
let (frame, ref mut refcnt) = self
149+
.frames
150+
.get_mut(frame_id)
151+
.ok_or(KError::InvalidFrameId)?;
152+
if frame.is_some() {
153+
if *refcnt > 0 {
154+
*refcnt -= 1;
155+
Ok(())
156+
} else {
157+
panic!("Can't call remove_frame_mapping on 0 refcnt frame");
158+
}
159+
} else {
160+
Err(KError::InvalidFrameId)
161+
}
162+
}
163+
164+
fn deallocate_frame(&mut self, fid: FrameId) -> Result<Frame, KError> {
165+
let (frame, refcnt) = self.frames.get_mut(fid).ok_or(KError::InvalidFrameId)?;
166+
if *refcnt == 0 {
167+
frame.take().ok_or(KError::InvalidFrameId)
168+
} else {
169+
Err(KError::FrameStillMapped)
170+
}
171+
}
90172
}
91173

92174
/// ResumeHandle is the HW specific logic that switches the CPU

0 commit comments

Comments
 (0)