From d535a1b83f8c918b65e562ad8940822db2d64004 Mon Sep 17 00:00:00 2001 From: Florian Hartung Date: Wed, 7 Aug 2024 13:50:56 +0200 Subject: [PATCH] feat(syscalls): more syscalls and unimplemented handlers --- core/src/syscall/mod.rs | 34 ++++- core/src/syscall/syscalls.rs | 69 ++++++++-- hypervisor/src/hypervisor/syscall.rs | 183 ++++++++++++++++++++++++--- 3 files changed, 246 insertions(+), 40 deletions(-) diff --git a/core/src/syscall/mod.rs b/core/src/syscall/mod.rs index 0e417e9..066016f 100644 --- a/core/src/syscall/mod.rs +++ b/core/src/syscall/mod.rs @@ -29,6 +29,9 @@ mod tests { use std::thread; use std::time::Duration; + use a653rs::bindings::ApexSystemTime; + use a653rs::prelude::{QueueOverflow, QueuingPortId}; + use super::SyscallType; use crate::syscall::receiver::{self, SyscallReceiver}; use crate::syscall::sender::SyscallSender; @@ -53,7 +56,14 @@ mod tests { receiver::wrap_serialization::( serialized_params, |params| { - assert_eq!(¶ms, &[1, 2, 3]); + assert_eq!( + params, + ( + 0 as QueuingPortId, + [1u8, 2, 3].as_slice(), + 0 as ApexSystemTime + ) + ); Ok(()) }, @@ -70,7 +80,11 @@ mod tests { // Make a syscall let response: Result<(), a653rs::bindings::ErrorReturnCode> = sender - .execute::(&[1, 2, 3]) + .execute::(( + 0 as QueuingPortId, + &[1, 2, 3], + 0 as ApexSystemTime, + )) .expect("sending and receiving a response to succeed"); assert_eq!(response, Ok(())); @@ -83,6 +97,7 @@ mod tests { pub fn two_syscalls() { let (sender, receiver) = new_sender_receiver_pair(); + // The receiver thread represents the hypervisor. let receiver_thread = thread::spawn(move || { // A simulated queuing port. This represents the hypervisor state. let mut queuing_port_state: VecDeque> = VecDeque::new(); @@ -93,7 +108,7 @@ mod tests { receiver::wrap_serialization::( serialized_params, |params| { - queuing_port_state.push_back(params.to_owned()); + queuing_port_state.push_back(params.1.to_owned()); Ok(()) }, @@ -106,6 +121,7 @@ mod tests { |_params| { queuing_port_state .pop_front() + .map(|msg| (false as QueueOverflow, msg)) .ok_or(a653rs::bindings::ErrorReturnCode::NotAvailable) }, ) @@ -126,19 +142,23 @@ mod tests { // Send one message into the queuing port let response = sender - .execute::(&[4, 3, 2, 1]) + .execute::(( + 0 as QueuingPortId, + &[4, 3, 2, 1], + 0 as ApexSystemTime, + )) .unwrap(); assert_eq!(response, Ok(())); // Receive the previous message from the queuing port let response = sender - .execute::(()) + .execute::((0 as QueuingPortId, 0 as ApexSystemTime)) .expect("sending and receiving a response to succeed"); - assert_eq!(response, Ok(vec![4, 3, 2, 1])); + assert_eq!(response, Ok((false as QueueOverflow, vec![4, 3, 2, 1]))); // Now the queuing port should be empty let response = sender - .execute::(()) + .execute::((0 as QueuingPortId, 0 as ApexSystemTime)) .expect("sending and receiving a response to succeed"); assert_eq!( response, diff --git a/core/src/syscall/syscalls.rs b/core/src/syscall/syscalls.rs index aa5622e..435ead5 100644 --- a/core/src/syscall/syscalls.rs +++ b/core/src/syscall/syscalls.rs @@ -1,24 +1,67 @@ +use a653rs::bindings::*; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; -use super::SyscallType; - pub trait Syscall<'params> { - const TY: SyscallType; + const TY: super::SyscallType; type Params: Serialize + Deserialize<'params>; type Returns: Serialize + DeserializeOwned; } -pub struct SendQueuingMessage; -impl<'msg> Syscall<'msg> for SendQueuingMessage { - const TY: SyscallType = SyscallType::SendQueuingMessage; - type Params = &'msg [u8]; - type Returns = (); +/// `'params` is available as a lifetime for parameter types +macro_rules! define_syscall { + ($name:ident: |$params:ty| -> $returns:ty) => { + pub struct $name; + impl<'params> Syscall<'params> for $name { + const TY: super::SyscallType = super::SyscallType::$name; + type Params = $params; + type Returns = $returns; + } + }; } -pub struct ReceiveQueuingMessage; -impl<'de> Syscall<'de> for ReceiveQueuingMessage { - const TY: SyscallType = SyscallType::ReceiveQueuingMessage; - type Params = (); - type Returns = Vec; +macro_rules! define_multiple_syscalls { + ($($name:ident: |$params:ty| -> $returns:ty),* $(,)?) => { + $(define_syscall!($name: |$params| -> $returns);)* + } } + +// ApexPartitionP4 +define_multiple_syscalls!( + GetPartitionStatus: |()| -> ApexPartitionStatus, + SetPartitionMode: |OperatingMode| -> (), +); + +// ApexProcessP4 +define_multiple_syscalls!( + // CreateProcess: |&'params ApexProcessAttribute| -> ProcessId, + Start: |ProcessId| -> (), +); + +// ApexSamplingPortP4 +define_multiple_syscalls!( + CreateSamplingPort: |(SamplingPortName, MessageSize, PortDirection, ApexSystemTime)| -> SamplingPortId, + WriteSamplingMessage: |(SamplingPortId, &'params [ApexByte])| -> (), + ReadSamplingMessage: |SamplingPortId| -> (Validity, Vec), // TODO is Validitiy necessary +); + +// ApexQueuingPortP4 +define_multiple_syscalls!( + CreateQueuingPort: |(QueuingPortName, MessageSize, MessageRange, PortDirection, QueuingDiscipline)| -> QueuingPortId, + SendQueuingMessage: |(QueuingPortId, &'params [ApexByte], ApexSystemTime)| -> (), + ReceiveQueuingMessage: |(QueuingPortId, ApexSystemTime)| -> (QueueOverflow, Vec), + GetQueuingPortStatus: |QueuingPortId| -> QueuingPortStatus, + ClearQueuingPort: |QueuingPortId| -> (), +); + +// ApexTimeP4 +define_multiple_syscalls!( + PeriodicWait: |()| -> (), + GetTime: |()| -> ApexSystemTime, +); + +// ApexErrorP4 +define_multiple_syscalls!( + ReportApplicationMessage: |&'params [ApexByte]| -> (), + RaiseApplicationError: |(ErrorCode, &'params [ApexByte])| -> (), +); diff --git a/hypervisor/src/hypervisor/syscall.rs b/hypervisor/src/hypervisor/syscall.rs index ee4bedb..8dde65a 100644 --- a/hypervisor/src/hypervisor/syscall.rs +++ b/hypervisor/src/hypervisor/syscall.rs @@ -1,8 +1,10 @@ use a653rs::prelude::PartitionId; -use a653rs_linux_core::syscall::syscalls::{ReceiveQueuingMessage, SendQueuingMessage, Syscall}; -use a653rs_linux_core::syscall::SyscallType; +use a653rs_linux_core::syscall::syscalls::{self, Syscall}; +use a653rs_linux_core::syscall::{self, SyscallType}; use anyhow::Result; +// Temporary replacement until the new hypervisor architecture allows for a +// modular and mutable hypervisor state during partition execution type HypervisorState = (); trait SyscallHandler<'params>: Syscall<'params> + Sized { @@ -24,47 +26,188 @@ trait SyscallHandler<'params>: Syscall<'params> + Sized { ) -> Result; } -fn handle_syscall( +pub fn handle_syscall( ty: SyscallType, - params: &[u8], + serialized_params: &[u8], hypervisor_state: &mut HypervisorState, current_partition: PartitionId, ) -> Result> { - match ty { - SyscallType::SendQueuingMessage => SendQueuingMessage::handle_with_serialization( - params, - hypervisor_state, - current_partition, - ), - SyscallType::ReceiveQueuingMessage => ReceiveQueuingMessage::handle_with_serialization( - params, - hypervisor_state, - current_partition, - ), + use syscalls::*; + + let handler_fn = match ty { + SyscallType::GetPartitionStatus => GetPartitionStatus::handle_with_serialization, + SyscallType::SetPartitionMode => SetPartitionMode::handle_with_serialization, + SyscallType::Start => Start::handle_with_serialization, + SyscallType::CreateSamplingPort => CreateSamplingPort::handle_with_serialization, + SyscallType::WriteSamplingMessage => WriteSamplingMessage::handle_with_serialization, + SyscallType::ReadSamplingMessage => ReadSamplingMessage::handle_with_serialization, + SyscallType::CreateQueuingPort => CreateQueuingPort::handle_with_serialization, + SyscallType::SendQueuingMessage => SendQueuingMessage::handle_with_serialization, + SyscallType::ReceiveQueuingMessage => ReceiveQueuingMessage::handle_with_serialization, + SyscallType::GetQueuingPortStatus => GetQueuingPortStatus::handle_with_serialization, + SyscallType::ClearQueuingPort => ClearQueuingPort::handle_with_serialization, + SyscallType::PeriodicWait => PeriodicWait::handle_with_serialization, + SyscallType::GetTime => GetTime::handle_with_serialization, + SyscallType::ReportApplicationMessage => { + ReportApplicationMessage::handle_with_serialization + } + SyscallType::RaiseApplicationError => RaiseApplicationError::handle_with_serialization, other_ty => { todo!("Implement syscall {other_ty:?}") } - } + }; + + handler_fn(serialized_params, hypervisor_state, current_partition) } // --------------- HANDLER IMPLEMENTATIONS --------------- -impl<'params> SyscallHandler<'params> for SendQueuingMessage { +impl SyscallHandler<'_> for syscalls::GetPartitionStatus { + fn handle( + _params: (), + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall GetPartitionStatus") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::SetPartitionMode { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall SetPartitionMode") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::Start { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall Start") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::CreateSamplingPort { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall CreateSamplingPort") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::WriteSamplingMessage { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall WriteSamplingMessage") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::ReadSamplingMessage { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall ReadSamplingMessage") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::CreateQueuingPort { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall CreateQueuingPort") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::SendQueuingMessage { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall SendQueuingMessage") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::ReceiveQueuingMessage { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall ReceiveQueuingMessage") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::GetQueuingPortStatus { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall GetQueuingPortStatus") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::ClearQueuingPort { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall ClearQueuingPort") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::PeriodicWait { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall PeriodicWait") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::GetTime { + fn handle( + _params: Self::Params, + _hv_state: &mut HypervisorState, + _current_partition: PartitionId, + ) -> Result { + todo!("handle syscall GetTime") + } +} + +impl<'params> SyscallHandler<'params> for syscalls::ReportApplicationMessage { fn handle( _params: Self::Params, _hv_state: &mut HypervisorState, _current_partition: PartitionId, ) -> Result { - todo!("Handle SendQueuingMessage") + todo!("handle syscall ReportApplicationMessage") } } -impl<'params> SyscallHandler<'params> for ReceiveQueuingMessage { +impl<'params> SyscallHandler<'params> for syscalls::RaiseApplicationError { fn handle( _params: Self::Params, _hv_state: &mut HypervisorState, _current_partition: PartitionId, ) -> Result { - todo!("Handle ReceiveQueuingMessage") + todo!("handle syscall RaiseApplicationError") } }