Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SMC calls forwarding framework #21

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions src/arch/aarch64/smc.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "smc.h"
#include "psci.h"
#include "fault.h"
#include "../../util/util.h"

// Values in this file are taken from:
Expand All @@ -32,6 +33,69 @@ typedef enum {
SMC_CALL_RESERVED = 64,
} smc_call_id_t;

#if defined(CONFIG_ALLOW_SMC_CALLS)
/* SMC Call Cap that the library makes SMC calls on; passed from an application */
seL4_CPtr smc_cap_current;

/* Set SMC Call Cap to use by the library API;
should be called before an application starts
handling exceptions from a VM thread
*/
bool smc_set_cap(seL4_CPtr smcccap)
{
if (!smcccap)
{
LOG_VMM_ERR("SMC forwarding: attempted to set zero SMC Call cap\n");
return false;
}
smc_cap_current = smcccap;
return true;
}
#endif /*CONFIG_ALLOW_SMC_CALLS*/

#if defined(CONFIG_ALLOW_SMC_CALLS)

/* Service handlers for services that require "physical" access to EL3 components
(vs emulation) are listed here.

'Active' handler is a pointer to a fucntion that actually will be invoked;
by default active handlers are set to NULL. Application should assign to an active handler
wheither a default handler that unconditionally forwards calls to Secure Monitor:

smc_set_handler_xxx_service(smc_default_handle_service);

or assign a custom handler impelemnting some forwarding policy:

smc_set_handler_xxx_service(wary_handle_service);

To remove active handler invoke:

smc_set_handler_xxx_service(NULL);

Note: application code should include smc.h
*/

/* 'smc_handle_sip()' is an active handler of SiP Service calls */
smc_handle_service_type smc_handle_sip = NULL;

/* 'smc_set_handler_sip_service()' assigns/removes active SiP Service handler;
NULL is a valid value to remove an earlier assigned handler;
function returns 'True' if handler was initialized with pointer to a function,
and 'False' if a handler was removed */
bool smc_set_handler_sip_service (smc_handle_service_type handler_func)
{
if (handler_func == NULL)
{
smc_handle_sip = NULL;
return false;
}
else
smc_handle_sip = handler_func;

return true;
}
#endif /*CONFIG_ALLOW_SMC_CALLS*/

static smc_call_id_t smc_get_call(size_t func_id)
{
uint64_t service = ((func_id >> SMC_SERVICE_CALL_SHIFT) & SMC_SERVICE_CALL_MASK);
Expand Down Expand Up @@ -109,10 +173,44 @@ bool handle_smc(size_t vcpu_id, uint32_t hsr)
}
LOG_VMM_ERR("Unhandled SMC: standard service call %lu\n", fn_number);
break;
#if defined(CONFIG_ALLOW_SMC_CALLS)
case SMC_CALL_SIP_SERVICE:
return smc_handle_sip(vcpu_id, &regs, fn_number);
#endif
default:
LOG_VMM_ERR("Unhandled SMC: unknown value service: 0x%lx, function number: 0x%lx\n", service, fn_number);
break;
}

return false;
}

#if defined(CONFIG_ALLOW_SMC_CALLS)
/* Default handler of calls to a Service (group of Functions) running at Secure Monitor level;
forwards all the calls without applying any policy
*/
bool smc_default_handle_service(size_t vcpu_id, seL4_UserContext *regs, uint64_t fn_number)
{

seL4_ARM_SMCContext request;
seL4_ARM_SMCContext response;

request.x0 = regs->x0; request.x1 = regs->x1;
request.x2 = regs->x2; request.x3 = regs->x3;
request.x4 = regs->x4; request.x5 = regs->x5;
request.x6 = regs->x6; request.x7 = regs->x7;

seL4_ARM_SMC_Call(smc_cap_current, &request, &response);

regs->x0 = response.x0; regs->x1 = response.x1;
regs->x2 = response.x2; regs->x3 = response.x3;
regs->x4 = response.x4; regs->x5 = response.x5;
regs->x6 = response.x6; regs->x7 = response.x7;


bool success = fault_advance_vcpu(vcpu_id, regs);
assert(success);

return success;
}
#endif /*CONFIG_ALLOW_SMC_CALLS*/
18 changes: 18 additions & 0 deletions src/arch/aarch64/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,21 @@ void smc_set_return_value(seL4_UserContext *u, uint64_t val);

/* Gets the value of x1-x6 */
uint64_t smc_get_arg(seL4_UserContext *u, uint64_t arg);

#if defined(CONFIG_ALLOW_SMC_CALLS)

/* Default handler of calls to a SMC Service */
bool smc_default_handle_service(size_t vcpu_id, seL4_UserContext *regs, uint64_t fn_number);

/* Service handler type */
typedef bool (* smc_handle_service_type)(size_t, seL4_UserContext *, uint64_t);

/* API for user: */

/* Set SMC Call Cap to use by the library API */
bool smc_set_cap(seL4_CPtr smcccap);

/* 'set_handler_sip_service()' assigns/removes active SiP Service handler */
bool smc_set_handler_sip_service(smc_handle_service_type handler_func);

#endif