Skip to content

Commit

Permalink
kernel+x86_64+aarch64: add SystemCallFrame trait and arch impls
Browse files Browse the repository at this point in the history
  • Loading branch information
Qix- committed Dec 30, 2024
1 parent c20c2f7 commit 85d686a
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 5 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions oro-arch-aarch64/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ oro-dbgutil.workspace = true
oro-dtb.workspace = true
oro-type.workspace = true
oro-sync.workspace = true
oro-sysabi.workspace = true

# Work around non-composability of `test` profile and global allocator conflicts in unit test runner.
[dev-dependencies]
Expand Down
2 changes: 2 additions & 0 deletions oro-arch-aarch64/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub mod mair;
pub mod mem;
pub mod psci;
pub mod reg;
pub mod syscall;

pub(crate) mod init;

Expand All @@ -59,6 +60,7 @@ pub(crate) struct Arch;
impl oro_kernel::Arch for Arch {
type AddrSpace = crate::mem::address_space::AddressSpaceLayout;
type CoreState = ();
type SystemCallFrame = crate::syscall::SystemCallFrame;
type ThreadState = ();

fn make_instance_unique(
Expand Down
46 changes: 46 additions & 0 deletions oro-arch-aarch64/src/syscall.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! System call handling for the AArch64 architecture.
/// Holds the data related to a system call frame.
pub struct SystemCallFrame;

impl oro_kernel::SystemCallFrame for SystemCallFrame {
#[inline]
fn opcode(&self) -> oro_sysabi::syscall::Opcode {
todo!();
}

#[inline]
fn table_id(&self) -> u64 {
todo!();
}

#[inline]
fn key(&self) -> u64 {
todo!();
}

#[inline]
fn value(&self) -> u64 {
todo!();
}

#[inline]
fn entity_id(&self) -> u64 {
todo!();
}

#[inline]
fn set_error(&mut self, _error: oro_sysabi::syscall::Error) {
todo!();
}

#[inline]
fn set_return_value(&mut self, _value: u64) {
todo!();
}

#[inline]
unsafe fn return_to_caller(self) -> ! {
todo!();
}
}
1 change: 1 addition & 0 deletions oro-arch-x86_64/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ oro-dbgutil.workspace = true
oro-acpi.workspace = true
oro-id.workspace = true
oro-sync.workspace = true
oro-sysabi.workspace = true

# Work around non-composability of `test` profile and global allocator conflicts in unit test runner.
[dev-dependencies]
Expand Down
1 change: 1 addition & 0 deletions oro-arch-x86_64/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ pub(crate) struct Arch;
impl oro_kernel::Arch for Arch {
type AddrSpace = crate::mem::address_space::AddressSpaceLayout;
type CoreState = CoreState;
type SystemCallFrame = crate::syscall::AbiCallFrame;
type ThreadState = ThreadState;

fn make_instance_unique(
Expand Down
56 changes: 51 additions & 5 deletions oro-arch-x86_64/src/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ unsafe extern "C" fn syscall_enter_non_compat_stage3() -> ! {
out("r8") abi_frame_ptr,
};

let abi_frame = (abi_frame_ptr as *const AbiCallFrame).read_volatile();
let mut abi_frame = (abi_frame_ptr as *const AbiCallFrame).read_volatile();

// Sanity check that the syscall instruction cleared the IF flag.
debug_assert!(
Expand All @@ -281,7 +281,9 @@ unsafe extern "C" fn syscall_enter_non_compat_stage3() -> ! {

// Now we can call the syscall handler.
// XXX(qix-): placeholder stub
return_to_user_from_syscall(abi_frame, 1337, 867_5309)
abi_frame.rax = oro_sysabi::syscall::Error::NotImplemented as u64;
abi_frame.rdx = 0;
return_to_user_from_syscall(abi_frame)
}

/// Returns to userspace from a syscall (previously constructed from the
Expand All @@ -296,7 +298,7 @@ unsafe extern "C" fn syscall_enter_non_compat_stage3() -> ! {
/// originally made the syscall that created the given [`AbiCallFrame`].
///
/// **Interrupts must be disabled when calling this function.**
pub unsafe fn return_to_user_from_syscall(frame: AbiCallFrame, error: u32, value: u64) -> ! {
unsafe fn return_to_user_from_syscall(frame: AbiCallFrame) -> ! {
// TODO(qix-): There is almost definitely some missing functionality here, namely
// TODO(qix-): around the resume flag (RF) and the trap flag (TF) in the RFLAGS register.

Expand All @@ -321,8 +323,8 @@ pub unsafe fn return_to_user_from_syscall(frame: AbiCallFrame, error: u32, value
"xor rsi, rsi",
// Return to userspace.
"sysretq",
in("rax") u64::from(error),
in("rdx") value,
in("rax") frame.rax,
in("rdx") frame.rdx,
in("r9") frame.rsp,
in("r12") frame.r12,
in("r13") frame.r13,
Expand All @@ -340,3 +342,47 @@ pub unsafe fn return_to_user_from_syscall(frame: AbiCallFrame, error: u32, value
const fn must_be_u16(x: u16) -> u16 {
x
}

impl oro_kernel::SystemCallFrame for AbiCallFrame {
#[inline]
fn opcode(&self) -> oro_sysabi::syscall::Opcode {
// SAFETY: This is safe because the opcode is non_exhaustive and the
// SAFETY: kernel validates the value before using it.
unsafe { core::mem::transmute(self.rax) }
}

#[inline]
fn table_id(&self) -> u64 {
self.rsi
}

#[inline]
fn key(&self) -> u64 {
self.rdi
}

#[inline]
fn value(&self) -> u64 {
self.rdx
}

#[inline]
fn entity_id(&self) -> u64 {
self.r9
}

#[inline]
fn set_error(&mut self, error: oro_sysabi::syscall::Error) {
self.rax = error as u64;
}

#[inline]
fn set_return_value(&mut self, value: u64) {
self.rdx = value;
}

#[inline]
unsafe fn return_to_caller(self) -> ! {
return_to_user_from_syscall(self)
}
}
1 change: 1 addition & 0 deletions oro-kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ oro-macro.workspace = true
oro-id.workspace = true
oro-debug.workspace = true
oro-sync.workspace = true
oro-sysabi.workspace = true

[lints]
workspace = true
39 changes: 39 additions & 0 deletions oro-kernel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ pub trait Arch: 'static {
type ThreadState: Sized + Send = ();
/// The core-local state type.
type CoreState: Sized + Send + Sync + 'static = ();
/// The system call frame type.
type SystemCallFrame: SystemCallFrame + 'static;

/// Makes the given instance mapper unique, either by duplicating
/// all RW pages or by implementing COW (copy-on-write) semantics.
Expand All @@ -283,6 +285,43 @@ pub trait Arch: 'static {
);
}

/// Implements a type that reports information about a system call to the kernel.
///
/// Frames are handed to the kernel to either process or store (if the task must
/// be made dormant) in order to hand _back_ to the architecture for restoration
/// at a later time.
pub trait SystemCallFrame: Sized + Send + Sync {
/// Returns the opcode for the operation.
///
/// Does not need to be validated; the kernel will do that.
fn opcode(&self) -> oro_sysabi::syscall::Opcode;
/// Returns the table ID for the operation.
///
/// Does not need to be validated; the kernel will do that.
fn table_id(&self) -> u64;
/// Returns the entity ID for the operation.
///
/// Does not need to be validated; the kernel will do that.
fn entity_id(&self) -> u64;
/// Returns the key for the operation.
fn key(&self) -> u64;
/// Returns the value for the operation.
///
/// Does not need to be validated; the kernel will do that.
fn value(&self) -> u64;
/// Sets the return value for the system call.
fn set_return_value(&mut self, value: u64);
/// Sets the error code for the system call.
fn set_error(&mut self, error: oro_sysabi::syscall::Error);

/// Returns to the task that made the system call.
///
/// # Safety
/// The caller must ensure that the task's context has been
/// appropriately restored before calling this function.
unsafe fn return_to_caller(self) -> !;
}

/// Helper trait association type for `Arch::AddrSpace`.
pub(crate) type AddrSpace<A> = <A as Arch>::AddrSpace;
/// Helper trait association type for `Arch::AddrSpace::SupervisorHandle`.
Expand Down

0 comments on commit 85d686a

Please sign in to comment.