Skip to content

Commit

Permalink
kernel+oro: add address space layout interface
Browse files Browse the repository at this point in the history
  • Loading branch information
Qix- committed Feb 14, 2025
1 parent 94e360d commit 324391a
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 36 deletions.
41 changes: 41 additions & 0 deletions oro-kernel/src/iface/kernel/addr_layout_v0.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//! Implements the address space layout query interface (version 0).
use core::marker::PhantomData;

use oro::{key, syscall::Error as SysError};
use oro_mem::mapper::{AddressSpace as _, AddressSegment};

use super::KernelInterface;
use crate::{AddressSpace, arch::Arch, syscall::InterfaceResponse, tab::Tab, thread::Thread};

/// Version 0 of the thread control kernel interface.
#[repr(transparent)]
pub struct AddrLayoutV0<A: Arch>(pub(crate) PhantomData<A>);

impl<A: Arch> KernelInterface<A> for AddrLayoutV0<A> {
fn get(&self, _thread: &Tab<Thread<A>>, index: u64, key: u64) -> InterfaceResponse {
let segment = match index {
key!("module") => AddressSpace::<A>::user_data(),
key!("thrdstck") => AddressSpace::<A>::user_thread_stack(),
_ => return InterfaceResponse::immediate(SysError::BadIndex, 0),
};

::oro_macro::assert::fits_within::<usize, u64>();

match key {
key!("start") => InterfaceResponse::ok(segment.range().0 as u64),
key!("end") => InterfaceResponse::ok(segment.range().1 as u64),
_ => InterfaceResponse::immediate(SysError::BadKey, 0),
}
}

fn set(
&self,
_thread: &Tab<Thread<A>>,
_index: u64,
_key: u64,
_value: u64,
) -> InterfaceResponse {
InterfaceResponse::immediate(SysError::ReadOnly, 0)
}
}
1 change: 1 addition & 0 deletions oro-kernel/src/iface/kernel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,6 @@ pub(crate) fn register_kernel_interfaces<A: Arch>(table: &mut Table<Box<dyn Kern
KERNEL_IFACE_QUERY_TYPE_META_V0 => "./iface_query_type_meta_v0.rs" IfaceQueryTypeMetaV0,
KERNEL_MEM_TOKEN_V0 => "./mem_token_v0.rs" MemTokenV0,
KERNEL_PAGE_ALLOC_V0 => "./page_alloc_v0.rs" PageAllocV0,
KERNEL_ADDR_LAYOUT_V0 => "./addr_layout_v0.rs" AddrLayoutV0,
}
}
45 changes: 39 additions & 6 deletions oro/src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use core::ptr::NonNull;

use crate::{buddy_system::Heap, lock::Mutex};
use crate::{buddy_system::Heap, lock::Mutex, syscall_get};

#[doc(hidden)]
const ORDER: usize = 32;
Expand Down Expand Up @@ -59,11 +59,7 @@ unsafe impl core::alloc::GlobalAlloc for HeapAllocator {

if inner.base == 0 {
// First allocation; set the base.
inner.base = crate::arch::heap_top();
debug_assert!(
inner.base % 4096 == 0,
"crate::arch::heap_top() returned non-page-aligned address"
);
inner.base = heap_top();
}

// We've allocated the token; now map it.
Expand Down Expand Up @@ -145,3 +141,40 @@ unsafe impl core::alloc::GlobalAlloc for HeapAllocator {
}
}
}

/// The top address (exclusive; one byte higher past the end)
/// of the heap. The heap's pages grow downwards from this address.
///
/// # Performance
/// This is a "cold" function, and should be used sparingly.
/// It incurs a syscall and a number of runtime assertions.
///
/// # Panics
/// Panics if the heap top syscall fails, or if the kernel reports
/// `u64::MAX` as the heap top (it should never do this).
#[must_use]
pub fn heap_top() -> u64 {
// SAFETY: This is a query; it's always safe.
let high_byte = unsafe {
syscall_get!(
crate::id::iface::KERNEL_ADDR_LAYOUT_V0,
crate::id::iface::KERNEL_ADDR_LAYOUT_V0,
crate::key!("module"),
crate::key!("end"),
)
.expect("failed to get heap top")
};

let high_byte = high_byte.wrapping_add(1);
assert_ne!(
high_byte, 0,
"heap top is at highest address; allocator will not work"
);

assert!(
high_byte % 4096 == 0,
"heap top is non-page-aligned address"
);

high_byte
}
10 changes: 0 additions & 10 deletions oro/src/arch/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,6 @@

use crate::syscall;

/// The top address (exclusive; one byte higher past the end)
/// of the heap. The heap's pages grow downwards from this address.
pub const fn heap_top() -> u64 {
// TODO(qix-): This is a temporary solution, and will definitely change.
// TODO(qix-): See <https://github.com/oro-os/kernel/issues/49> (while that
// TODO(qix-): issue is mostly about x86_64 LA57, the question of how address
// TODO(qix-): space is laid out, especially w.r.t. ASLR, is still TBD).
230 << (12 + 9 * 3)
}

/// Lowest level system call for aarch64.
#[inline(always)]
pub unsafe fn syscall(
Expand Down
20 changes: 0 additions & 20 deletions oro/src/arch/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,6 @@ use core::{arch::asm, mem::transmute};

use crate::syscall;

/// The top address (exclusive; one byte higher past the end)
/// of the heap. The heap's pages grow downwards from this address.
pub fn heap_top() -> u64 {
// Check the LA57 bit to determine if we are using 57-bit
// linear addressing.
// TODO(qix-): This is a temporary solution; I erroneously had
// TODO(qix-): a direct `cr4` check in here which, obviously, isn't
// TODO(qix-): allowed in user mode. Will need to add a kernel interface
// TODO(qix-): for this.
let la57 = false;

// TODO(qix-): This is a temporary solution, and will definitely change.
// TODO(qix-): See <https://github.com/oro-os/kernel/issues/49>.
if la57 {
230 << (12 + 9 * 4)
} else {
230 << (12 + 9 * 3)
}
}

/// Lowest level system call for x86_64.
///
/// # Safety
Expand Down
2 changes: 2 additions & 0 deletions oro/src/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ pub mod iface {
pub const KERNEL_MEM_TOKEN_V0: u64 = KERNEL_ID_TYPE_IFACE | 0x00_0004;
/// The ID of the kernel page allocation interface (version 0).
pub const KERNEL_PAGE_ALLOC_V0: u64 = KERNEL_ID_TYPE_IFACE | 0x00_0005;
/// The ID of the kernel address layout query interface (version 0).
pub const KERNEL_ADDR_LAYOUT_V0: u64 = KERNEL_ID_TYPE_IFACE | 0x00_0006;

/// (x86_64 only) The ID of the x86_64 TLS base pointer (FS/GS) interface (version 0).
pub const KERNEL_X86_64_TLS_BASE_V0: u64 = KERNEL_ID_TYPE_ARCH_IFACE | 0x00_0001;
Expand Down

0 comments on commit 324391a

Please sign in to comment.