Skip to content
This repository has been archived by the owner on Oct 26, 2021. It is now read-only.

Commit

Permalink
Add Workldr trait, use it to load internal wasmldr
Browse files Browse the repository at this point in the history
In parallel with the Backend trait, this commit adds a Workldr trait for
handling `wasmldr` (and any future workldr implementations.)

We've also got a naive function for picking the "best" workldr (there's
only one, so that's easy) and using that for `exec` if nothing was
passed on the CLI.

Signed-off-by: Will Woods <[email protected]>
  • Loading branch information
wgwoods committed Sep 30, 2021
1 parent 50eb2f6 commit 1a3526f
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 6 deletions.
33 changes: 27 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@

mod backend;
mod protobuf;
mod workldr;

use backend::{Backend, Command};
use workldr::Workldr;

use std::convert::TryInto;
use std::path::PathBuf;
Expand All @@ -78,7 +80,7 @@ struct Info {}
#[derive(StructOpt)]
struct Exec {
/// The payload to run inside the keep
code: PathBuf,
code: Option<PathBuf>,
}

#[derive(StructOpt)]
Expand All @@ -95,9 +97,24 @@ fn main() -> Result<()> {
Box::new(backend::sgx::Backend),
];

let workldrs: &[Box<dyn Workldr>] = &[
#[cfg(feature = "wasmldr")]
Box::new(workldr::wasmldr::Wasmldr),
];

match Options::from_args() {
Options::Info(_) => info(backends),
Options::Exec(e) => exec(backends, e),
Options::Exec(e) => {
// FUTURE: accept tenant-provided shim, or fall back to builtin..
let backend = backend(backends);
let shim_bytes = backend.shim();
if let Some(path) = e.code {
let map = mmarinus::Kind::Private.load::<mmarinus::perms::Read, _>(&path)?;
exec(backend, shim_bytes, map)
} else {
exec(backend, shim_bytes, workldr(workldrs).exec())
}
}
}
}

Expand Down Expand Up @@ -149,12 +166,16 @@ fn backend(backends: &[Box<dyn Backend>]) -> &dyn Backend {
}
}

fn exec(backends: &[Box<dyn Backend>], opts: Exec) -> Result<()> {
let backend = backend(backends);
#[inline]
fn workldr(workldrs: &[Box<dyn Workldr>]) -> &dyn Workldr {
// NOTE: this is stupid, but we only have one workldr, so... ¯\_(ツ)_/¯
&*workldrs[0]
}

let map = mmarinus::Kind::Private.load::<mmarinus::perms::Read, _>(&opts.code)?;
fn exec(backend: &dyn Backend, shim: impl AsRef<[u8]>, exec: impl AsRef<[u8]>) -> Result<()> {
//let map = mmarinus::Kind::Private.load::<mmarinus::perms::Read, _>(&opts.code)?;

let keep = backend.keep(backend.shim(), &map)?;
let keep = backend.keep(shim.as_ref(), exec.as_ref())?;
let mut thread = keep.clone().spawn()?.unwrap();
loop {
match thread.enter()? {
Expand Down
39 changes: 39 additions & 0 deletions src/workldr/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: Apache-2.0

// FUTURE: right now we only have one Workldr, `wasmldr`.
// In the future there may be other workload types - in theory we can run
// any static PIE ELF binary. We could have a Lua interpreter, or a
// JavaScript interpreter, or whatever.
// So there's two parts to this trait - call them KeepSetup and Engine.
//
// KeepSetup is the part that actually sets up the Keep for the Workload,
// which might involve setting up network sockets, storage devices, etc.
// This part must be implemented by any Workldr, since we want the
// Enarx environment to be platform-agnostic.
//
// Engine is the (workload-specific) portion that actually interprets or
// executes the workload. It's responsible for taking the sockets / devices
// etc. that were set up by KeepSetup and making them usable in a way that
// the workload will understand.
//
// So: someday we might want to split this into two traits, and we might
// have multiple Workldrs for different languages/environments, and we
// might need to examine the workload and determine which Workldr is
// the right one to use. But first... we gotta make wasmldr work.

#[cfg(feature = "wasmldr")]
pub mod wasmldr;

/// A trait for the "Workloader" - shortened to Workldr, also known as "exec"
/// (as in Backend::keep(shim, exec) [q.v.]) and formerly known as the "code"
/// layer. This is the part that runs inside the keep, prepares the workload
/// environment, and then actually executes the tenant's workload.
///
/// Basically, this is a generic view of wasmldr.
pub trait Workldr {
/// The name of the Workldr
fn name(&self) -> &'static str;

/// The builtin Workldr binary (e.g. wasmldr)
fn exec(&self) -> &'static [u8];
}
15 changes: 15 additions & 0 deletions src/workldr/wasmldr/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: Apache-2.0

pub struct Wasmldr;

impl crate::workldr::Workldr for Wasmldr {
#[inline]
fn name(&self) -> &'static str {
"wasmldr"
}

#[inline]
fn exec(&self) -> &'static [u8] {
include_bytes!(concat!(env!("OUT_DIR"), "/bin/wasmldr"))
}
}

0 comments on commit 1a3526f

Please sign in to comment.