Skip to content

Conversation

@csegarragonz
Copy link
Collaborator

@csegarragonz csegarragonz commented Mar 1, 2022

In this PR I implement the WASI calls to access argc and argv inside SGX: wasi_args_get and wasi_args_sizes_get. The immediate consequence is that now the test function: demo/argc_argv_test also runs on SGX.

The bulk of the implementation is almost copied from WAMR's (src/wamr/env.cpp), and requires no OCalls. The only major change to the OCall/ECall interface is that we now pass argc and argv to the ecallCallFunction call. Note that the OCall/ECall interface forces us to serialise argv into a byte array, which means some more work.

In addition, I re-factor the utility functions to run SGX tests to match the WAVM and WAMR counterparts: now we have execFunction, execWamrFunction, execSgxFunction, and execFuncWithPool, execFuncWithWamrPool, and execFuncWithSgxPool.

@csegarragonz csegarragonz marked this pull request as draft March 1, 2022 16:21
@csegarragonz csegarragonz self-assigned this Mar 1, 2022
@csegarragonz csegarragonz added the wasm/wamr-sgx SGX related stuff. label Mar 1, 2022
@csegarragonz csegarragonz marked this pull request as ready for review March 1, 2022 17:43
@csegarragonz csegarragonz force-pushed the barebones branch 2 times, most recently from 142bff0 to 7079b23 Compare March 1, 2022 19:03
Copy link
Collaborator

@Shillaker Shillaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, but I'm concerned that this approach will lead to having two versions of a lot WAMR-related logic. I think a mixin shared between EnclaveWasmModule and WAMRWasmModule makes sense (e.g. WAMRModuleMixin or WAMRModuleCommon or something)

//
// Link to WAMR docs:
// https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/export_native_api.md#buffer-address-conversion-and-boundary-check
// ----------------------------------------------
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks a lot like the comment in https://github.com/faasm/faasm/blob/main/include/wamr/native.h, and feels like it's just repeating what's in the WAMR docs. Is it necessary and can we somehow avoid having this information in two places?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added the new relevant bits to the file you link, and removed this duplicated comment and added a reference to where it is explained.

// In enclave release mode (i.e NDEBUG set) we disable debug logging
#ifdef NDEBUG
void ocallLogDebug(const char* msg) { ; };
#else
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come this has a different method signature to the declaration in debug mode? Shouldn't they be the same?

Copy link
Collaborator Author

@csegarragonz csegarragonz Mar 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both methods need to have different return values to prevent the RELEASE version from doing any kind of OCall. Whereas the second signature is that corresponding to an OCall.

uint32_t faaslet_id);
uint32_t faaslet_id,
uint32_t argc,
char** argv);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still some kebab_case in this file, would be good to refactor to PascalCase in future.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do in the immediately subsequent PR.

}
}

void EnclaveWasmModule::prepareArgcArgv(uint32_t argcIn, char** argvIn)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same point re. duplication with WARMWasmModule and mixin. We need to find a way to avoid duplicating these functions otherwise we'll end up with two copies of everything.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, this call in particular can not be abstracted out, as WAMR's (non-SGX) version is implemented in WasmModule and uses calls to faabric.

In addition, the method signature is different:

void EnclaveWasmModule::prepareArgcArgv(uint32_t argcIn, char** argvIn);

void WAMRWasmModule::prepareArgcArgv(const faabric::Message& msg);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok I see, it's slightly confusing to have the same name and have it factored out as a separate function then, especially as it's only called in one place. I'd probably just inline the logic in the callFunction method.

GET_EXECUTING_MODULE_AND_CHECK(exec_env);

*argcWasm = module->getArgc();
*argvBuffSizeWasm = module->getArgvBufferSize();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very similar to

uint32_t wasi_args_sizes_get(wasm_exec_env_t exec_env,
, potentially same point around moving some of this logic into a mixin.

Copy link
Collaborator Author

@csegarragonz csegarragonz Mar 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think native symbols aren't such good candidates to be included in a mixin. The native symbol registration doesn't work well with templated functions, and there are some methods (like logging and getting the executing module) that have different names and signatures.

That being said, after the new mixin structure the methods body is either trivial or implemented in the WAMRModuleMixin.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mean we should merge the whole native symbol thing in, just the logic of the body of the function. This is how we share host interface logic between WAVM and WAMR normally, e.g. having a method like module->setUpArgcArgv(argcWasm, argvBuffSizeWasm) rather individual calls to getArgc and getArgvBufferSize. Admittedly here it will only save a couple of lines, but it's more the principle of absolutely minimising duplication.

@csegarragonz csegarragonz requested a review from Shillaker March 3, 2022 08:46

// ---- argc/arv ----

uint32_t getArgc();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getters I need to implement in the actual modules, as the mixin does not have access to private members.

@@ -0,0 +1,66 @@
#pragma once
Copy link
Collaborator Author

@csegarragonz csegarragonz Mar 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Shillaker this is the header file where are define the mixin (I plan on adding more calls currently in WAMRWasmModule as I need to implement them as well in EnclaveWasmModule).

Copy link
Collaborator

@Shillaker Shillaker Mar 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok nice, great that we can share this stuff more now.

I just wanted to check, do you think we could actually do this via an intermediate superclass? I.e. have the following hierarchy:

             WasmModule
                  |
          WAMRModuleCommon
         |                |
WAMRWasmModule           EnclaveWasmModule

We could then move the common properties between WAMRWasmModule and EnclaveWasmModule, like argc and argvBufferSize into WAMRModuleCommon and avoid the need for the stuff with underlying. We could also then potentially share methods like loadWasm.

I have a feeling we discussed this before, but can't remember why we couldn't do a superclass.

(Happy to continue discussion on Slack if easier)

}
}

void EnclaveWasmModule::prepareArgcArgv(uint32_t argcIn, char** argvIn)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok I see, it's slightly confusing to have the same name and have it factored out as a separate function then, especially as it's only called in one place. I'd probably just inline the logic in the callFunction method.

GET_EXECUTING_MODULE_AND_CHECK(exec_env);

*argcWasm = module->getArgc();
*argvBuffSizeWasm = module->getArgvBufferSize();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mean we should merge the whole native symbol thing in, just the logic of the body of the function. This is how we share host interface logic between WAVM and WAMR normally, e.g. having a method like module->setUpArgcArgv(argcWasm, argvBuffSizeWasm) rather individual calls to getArgc and getArgvBufferSize. Admittedly here it will only save a couple of lines, but it's more the principle of absolutely minimising duplication.

@@ -0,0 +1,66 @@
#pragma once
Copy link
Collaborator

@Shillaker Shillaker Mar 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok nice, great that we can share this stuff more now.

I just wanted to check, do you think we could actually do this via an intermediate superclass? I.e. have the following hierarchy:

             WasmModule
                  |
          WAMRModuleCommon
         |                |
WAMRWasmModule           EnclaveWasmModule

We could then move the common properties between WAMRWasmModule and EnclaveWasmModule, like argc and argvBufferSize into WAMRModuleCommon and avoid the need for the stuff with underlying. We could also then potentially share methods like loadWasm.

I have a feeling we discussed this before, but can't remember why we couldn't do a superclass.

(Happy to continue discussion on Slack if easier)

#include <vector>

template<typename T>
struct WAMRModuleMixin
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a class? It gives us more flexibility around scoping the members.

@csegarragonz csegarragonz requested a review from Shillaker March 3, 2022 12:11
@csegarragonz
Copy link
Collaborator Author

After our offline discussion I have added a comment in the mixin header file, explaining our design choices.

@csegarragonz csegarragonz merged commit 46699e6 into main Mar 4, 2022
@csegarragonz csegarragonz deleted the barebones branch March 4, 2022 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

wasm/wamr-sgx SGX related stuff.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants