Skip to content

Commit d48cb99

Browse files
committed
mem+kernel+x86_64+examples: initial plumbing for token mapping
1 parent 05c1c7a commit d48cb99

File tree

5 files changed

+91
-17
lines changed

5 files changed

+91
-17
lines changed

examples/no-std/page-alloc/src/main.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,22 @@ fn main() {
4141

4242
println!("token type: {:?}", Key(&ty));
4343

44-
const TARGET_ADDR: usize = 0x400_0000_0000;
44+
const TARGET_ADDR: u64 = 0x400_0000_0000;
4545

4646
// Map it in.
47-
// TODO: This is not yet implemented.
47+
match syscall::set!(
48+
KERNEL_MEM_TOKEN_V0,
49+
KERNEL_MEM_TOKEN_V0,
50+
token,
51+
syscall::key!("base"),
52+
TARGET_ADDR
53+
) {
54+
Ok(_) => (),
55+
Err((e, ex)) => {
56+
println!("error mapping in token: {e:?}[{ex}]");
57+
return;
58+
}
59+
}
4860

4961
// Try to read and write from it.
5062
unsafe {

oro-arch-x86_64/src/mem/segment.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,7 @@ unsafe impl Segment<AddressSpaceHandle> for &'static AddressSegment {
519519
let entry = &mut top_level[idx];
520520

521521
if entry.present() {
522-
return Err(MapError::Exists);
522+
continue;
523523
}
524524

525525
let frame_phys_addr = alloc.allocate().ok_or(MapError::OutOfMemory)?;

oro-kernel/src/iface/kernel/mem_token_v0.rs

+59-13
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,25 @@
11
//! Allows for querying information about memory tokens.
22
3+
use oro_mem::mapper::MapError;
34
use oro_sysabi::{key, syscall::Error as SysError};
45

56
use super::KernelInterface;
67
use crate::{arch::Arch, syscall::InterfaceResponse, tab::Tab, thread::Thread, token::Token};
78

9+
/// Interface specific errors.
10+
#[derive(Debug, Clone, Copy)]
11+
#[repr(u64)]
12+
pub enum Error {
13+
/// An address conflict (existing mapping) was encountered when mapping a token.
14+
Conflict = key!("conflict"),
15+
/// The requested address is not aligned to the page size.
16+
NotAligned = key!("align"),
17+
/// The requested address is out of the address space range.
18+
OutOfRange = key!("range"),
19+
/// The system ran out of memory trying to service the request.
20+
OutOfMemory = key!("oom"),
21+
}
22+
823
/// Version 0 of the memory token query interface.
924
#[repr(transparent)]
1025
pub struct MemTokenV0;
@@ -13,10 +28,8 @@ impl KernelInterface for MemTokenV0 {
1328
const TYPE_ID: u64 = oro_sysabi::id::iface::KERNEL_MEM_TOKEN_V0;
1429

1530
fn get<A: Arch>(thread: &Tab<Thread<A>>, index: u64, key: u64) -> InterfaceResponse {
16-
let Some(token) = thread
17-
.with(|t| t.instance().clone())
18-
.with(|i| i.token(index))
19-
else {
31+
let instance = thread.with(|t| t.instance().clone());
32+
let Some(token) = instance.with(|i| i.token(index)) else {
2033
return InterfaceResponse::immediate(SysError::BadIndex, 0);
2134
};
2235

@@ -34,6 +47,7 @@ impl KernelInterface for MemTokenV0 {
3447
key!("pages") => InterfaceResponse::ok(token.page_count() as u64),
3548
key!("size") => InterfaceResponse::ok(token.size() as u64),
3649
key!("commit") => InterfaceResponse::ok(token.commit() as u64),
50+
key!("base") => InterfaceResponse::immediate(SysError::WriteOnly, 0),
3751
_ => InterfaceResponse::immediate(SysError::BadKey, 0),
3852
}
3953
}
@@ -45,16 +59,48 @@ impl KernelInterface for MemTokenV0 {
4559
thread: &Tab<Thread<A>>,
4660
index: u64,
4761
key: u64,
48-
_value: u64,
62+
value: u64,
4963
) -> InterfaceResponse {
50-
if key == key!("forget") {
51-
let instance = thread.with(|t| t.instance().clone());
52-
return instance.with_mut(|i| i.forget_token(index)).map_or_else(
53-
|| InterfaceResponse::immediate(SysError::BadIndex, 0),
54-
|_| InterfaceResponse::ok(0),
55-
);
56-
}
64+
match key {
65+
key!("forget") => {
66+
let instance = thread.with(|t| t.instance().clone());
67+
instance.with_mut(|i| i.forget_token(index)).map_or_else(
68+
|| InterfaceResponse::immediate(SysError::BadIndex, 0),
69+
|_| InterfaceResponse::ok(0),
70+
)
71+
}
72+
key!("base") => {
73+
let instance = thread.with(|t| t.instance().clone());
74+
instance.with_mut(|i| {
75+
let Some(token) = i.token(index) else {
76+
return InterfaceResponse::immediate(SysError::BadIndex, 0);
77+
};
5778

58-
InterfaceResponse::immediate(SysError::ReadOnly, 0)
79+
let Ok(virt) = usize::try_from(value) else {
80+
return InterfaceResponse::immediate(
81+
SysError::InterfaceError,
82+
Error::OutOfRange as u64,
83+
);
84+
};
85+
86+
i.map_token(&token, virt).map_or_else(
87+
|err| {
88+
InterfaceResponse::immediate(
89+
SysError::InterfaceError,
90+
match err {
91+
MapError::Exists => Error::Conflict as u64,
92+
MapError::OutOfMemory => Error::OutOfMemory as u64,
93+
MapError::VirtNotAligned => Error::NotAligned as u64,
94+
MapError::VirtOutOfRange
95+
| MapError::VirtOutOfAddressSpaceRange => Error::OutOfRange as u64,
96+
},
97+
)
98+
},
99+
|()| InterfaceResponse::ok(0),
100+
)
101+
})
102+
}
103+
_ => InterfaceResponse::immediate(SysError::ReadOnly, 0),
104+
}
59105
}
60106
}

oro-kernel/src/instance.rs

+16
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ impl<A: Arch> Instance<A> {
8686
.apply_user_space_shallow(handle.mapper(), module.mapper())
8787
})?;
8888

89+
// Make the entire memory space shared.
90+
// TODO(qix-): This is a gross waste of memory, and will be addressed
91+
// TODO(qix-): in the future to be more fine-grained. I don't have a good
92+
// TODO(qix-): data structure written for random page fault fetches, so
93+
// TODO(qix-): instead we share all memory between all threads
94+
// TODO(qix-): in the instance, which requires around (255 * 4096) = 1MiB
95+
// TODO(qix-): of memory per instance. This isn't ideal, but it works for now.
96+
AddressSpace::<A>::user_data().provision_as_shared(handle.mapper())?;
97+
8998
let tab = crate::tab::get()
9099
.add(Self {
91100
module: module.clone(),
@@ -142,6 +151,13 @@ impl<A: Arch> Instance<A> {
142151
self.tokens.insert_tab(token)
143152
}
144153

154+
/// Maps a [`Token`] into the instance's address space.
155+
///
156+
/// Returns the address segment of the mapping.
157+
pub fn map_token(&self, token: &Tab<Token>, virt: usize) -> Result<(), MapError> {
158+
todo!("map token: {:016X} -> {virt:016X}", token.id());
159+
}
160+
145161
/// Returns the instance's address space handle.
146162
#[inline]
147163
#[must_use]

oro-mem/src/mapper.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ pub unsafe trait AddressSegment<Handle: Sized>: Send + 'static {
321321

322322
/// Makes the segment shared across all address spaces. Uses the given allocator.
323323
///
324-
/// Returns an error if the segment is not empty.
324+
/// **Skips any checks for emptiness;** must not return [`MapError::Exists`].
325325
fn provision_as_shared_in<A>(&self, space: &Handle, alloc: &A) -> Result<(), MapError>
326326
where
327327
A: Alloc;

0 commit comments

Comments
 (0)