Skip to content

Commit

Permalink
feat(syscalls): more syscalls and unimplemented handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
florianhartung committed Aug 7, 2024
1 parent be79ab5 commit d535a1b
Show file tree
Hide file tree
Showing 3 changed files with 246 additions and 40 deletions.
34 changes: 27 additions & 7 deletions core/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -53,7 +56,14 @@ mod tests {
receiver::wrap_serialization::<syscalls::SendQueuingMessage, _>(
serialized_params,
|params| {
assert_eq!(&params, &[1, 2, 3]);
assert_eq!(
params,
(
0 as QueuingPortId,
[1u8, 2, 3].as_slice(),
0 as ApexSystemTime
)
);

Ok(())
},
Expand All @@ -70,7 +80,11 @@ mod tests {

// Make a syscall
let response: Result<(), a653rs::bindings::ErrorReturnCode> = sender
.execute::<syscalls::SendQueuingMessage>(&[1, 2, 3])
.execute::<syscalls::SendQueuingMessage>((
0 as QueuingPortId,
&[1, 2, 3],
0 as ApexSystemTime,
))
.expect("sending and receiving a response to succeed");

assert_eq!(response, Ok(()));
Expand All @@ -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<Vec<u8>> = VecDeque::new();
Expand All @@ -93,7 +108,7 @@ mod tests {
receiver::wrap_serialization::<syscalls::SendQueuingMessage, _>(
serialized_params,
|params| {
queuing_port_state.push_back(params.to_owned());
queuing_port_state.push_back(params.1.to_owned());

Ok(())
},
Expand All @@ -106,6 +121,7 @@ mod tests {
|_params| {
queuing_port_state
.pop_front()
.map(|msg| (false as QueueOverflow, msg))
.ok_or(a653rs::bindings::ErrorReturnCode::NotAvailable)
},
)
Expand All @@ -126,19 +142,23 @@ mod tests {

// Send one message into the queuing port
let response = sender
.execute::<syscalls::SendQueuingMessage>(&[4, 3, 2, 1])
.execute::<syscalls::SendQueuingMessage>((
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::<syscalls::ReceiveQueuingMessage>(())
.execute::<syscalls::ReceiveQueuingMessage>((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::<syscalls::ReceiveQueuingMessage>(())
.execute::<syscalls::ReceiveQueuingMessage>((0 as QueuingPortId, 0 as ApexSystemTime))
.expect("sending and receiving a response to succeed");
assert_eq!(
response,
Expand Down
69 changes: 56 additions & 13 deletions core/src/syscall/syscalls.rs
Original file line number Diff line number Diff line change
@@ -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<u8>;
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<u8>), // 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<u8>),
GetQueuingPortStatus: |QueuingPortId| -> QueuingPortStatus,
ClearQueuingPort: |QueuingPortId| -> (),
);

// ApexTimeP4
define_multiple_syscalls!(
PeriodicWait: |()| -> (),
GetTime: |()| -> ApexSystemTime,
);

// ApexErrorP4
define_multiple_syscalls!(
ReportApplicationMessage: |&'params [ApexByte]| -> (),
RaiseApplicationError: |(ErrorCode, &'params [ApexByte])| -> (),
);
183 changes: 163 additions & 20 deletions hypervisor/src/hypervisor/syscall.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -24,47 +26,188 @@ trait SyscallHandler<'params>: Syscall<'params> + Sized {
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode>;
}

fn handle_syscall(
pub fn handle_syscall(
ty: SyscallType,
params: &[u8],
serialized_params: &[u8],
hypervisor_state: &mut HypervisorState,
current_partition: PartitionId,
) -> Result<Vec<u8>> {
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<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall GetPartitionStatus")
}
}

impl<'params> SyscallHandler<'params> for syscalls::SetPartitionMode {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall SetPartitionMode")
}
}

impl<'params> SyscallHandler<'params> for syscalls::Start {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall Start")
}
}

impl<'params> SyscallHandler<'params> for syscalls::CreateSamplingPort {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall CreateSamplingPort")
}
}

impl<'params> SyscallHandler<'params> for syscalls::WriteSamplingMessage {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall WriteSamplingMessage")
}
}

impl<'params> SyscallHandler<'params> for syscalls::ReadSamplingMessage {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall ReadSamplingMessage")
}
}

impl<'params> SyscallHandler<'params> for syscalls::CreateQueuingPort {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall CreateQueuingPort")
}
}

impl<'params> SyscallHandler<'params> for syscalls::SendQueuingMessage {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall SendQueuingMessage")
}
}

impl<'params> SyscallHandler<'params> for syscalls::ReceiveQueuingMessage {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall ReceiveQueuingMessage")
}
}

impl<'params> SyscallHandler<'params> for syscalls::GetQueuingPortStatus {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall GetQueuingPortStatus")
}
}

impl<'params> SyscallHandler<'params> for syscalls::ClearQueuingPort {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall ClearQueuingPort")
}
}

impl<'params> SyscallHandler<'params> for syscalls::PeriodicWait {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall PeriodicWait")
}
}

impl<'params> SyscallHandler<'params> for syscalls::GetTime {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("handle syscall GetTime")
}
}

impl<'params> SyscallHandler<'params> for syscalls::ReportApplicationMessage {
fn handle(
_params: Self::Params,
_hv_state: &mut HypervisorState,
_current_partition: PartitionId,
) -> Result<Self::Returns, a653rs::bindings::ErrorReturnCode> {
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<Self::Returns, a653rs::bindings::ErrorReturnCode> {
todo!("Handle ReceiveQueuingMessage")
todo!("handle syscall RaiseApplicationError")
}
}

0 comments on commit d535a1b

Please sign in to comment.